浏览代码

Migrate reader slider and next/prev buttons to Compose

arkon 1 年之前
父节点
当前提交
9a10656bf0

+ 121 - 0
app/src/main/java/eu/kanade/presentation/reader/ChapterNavigator.kt

@@ -0,0 +1,121 @@
+package eu.kanade.presentation.reader
+
+import androidx.compose.foundation.background
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.shape.RoundedCornerShape
+import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.outlined.SkipNext
+import androidx.compose.material.icons.outlined.SkipPrevious
+import androidx.compose.material3.FilledIconButton
+import androidx.compose.material3.Icon
+import androidx.compose.material3.IconButtonDefaults
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.Slider
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.CompositionLocalProvider
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.clip
+import androidx.compose.ui.hapticfeedback.HapticFeedbackType
+import androidx.compose.ui.platform.LocalHapticFeedback
+import androidx.compose.ui.platform.LocalLayoutDirection
+import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.unit.LayoutDirection
+import androidx.compose.ui.unit.dp
+import eu.kanade.presentation.util.isTabletUi
+import eu.kanade.tachiyomi.R
+
+@Composable
+fun ChapterNavigator(
+    isRtl: Boolean,
+    onNextChapter: () -> Unit,
+    enabledNext: Boolean,
+    onPreviousChapter: () -> Unit,
+    enabledPrevious: Boolean,
+    currentPage: Int,
+    totalPages: Int,
+    onSliderValueChange: (Int) -> Unit,
+) {
+    val isTabletUi = isTabletUi()
+    val horizontalPadding = if (isTabletUi) 24.dp else 16.dp
+    val layoutDirection = if (isRtl) LayoutDirection.Rtl else LayoutDirection.Ltr
+
+    val backgroundColor = MaterialTheme.colorScheme.surface.copy(alpha = 0.9f)
+    val haptic = LocalHapticFeedback.current
+
+    // We explicitly handle direction based on the reader viewer rather than the system direction
+    CompositionLocalProvider(LocalLayoutDirection provides LayoutDirection.Ltr) {
+        Row(
+            modifier = Modifier
+                .fillMaxWidth()
+                .padding(horizontal = horizontalPadding),
+            verticalAlignment = Alignment.CenterVertically,
+        ) {
+            val isLeftEnabled = if (isRtl) enabledNext else enabledPrevious
+            if (isLeftEnabled) {
+                FilledIconButton(
+                    onClick = if (isRtl) onNextChapter else onPreviousChapter,
+                    colors = IconButtonDefaults.filledIconButtonColors(
+                        containerColor = backgroundColor,
+                    ),
+                ) {
+                    Icon(
+                        imageVector = Icons.Outlined.SkipPrevious,
+                        contentDescription = stringResource(if (isRtl) R.string.action_next_chapter else R.string.action_previous_chapter),
+                    )
+                }
+            }
+
+            if (totalPages > 1) {
+                CompositionLocalProvider(LocalLayoutDirection provides layoutDirection) {
+                    Row(
+                        modifier = Modifier
+                            .weight(1f)
+                            .clip(RoundedCornerShape(24.dp))
+                            .background(backgroundColor)
+                            .padding(horizontal = 16.dp),
+                        verticalAlignment = Alignment.CenterVertically,
+                    ) {
+                        Text(text = currentPage.toString())
+
+                        Slider(
+                            modifier = Modifier
+                                .weight(1f)
+                                .padding(horizontal = 8.dp),
+                            value = currentPage.toFloat(),
+                            valueRange = 1f..totalPages.toFloat(),
+                            steps = totalPages,
+                            onValueChange = {
+                                onSliderValueChange(it.toInt() - 1)
+                                haptic.performHapticFeedback(HapticFeedbackType.TextHandleMove)
+                            },
+                        )
+
+                        Text(text = totalPages.toString())
+                    }
+                }
+            } else {
+                Spacer(Modifier.weight(1f))
+            }
+
+            val isRightEnabled = if (isRtl) enabledPrevious else enabledNext
+            if (isRightEnabled) {
+                FilledIconButton(
+                    onClick = if (isRtl) onPreviousChapter else onNextChapter,
+                    colors = IconButtonDefaults.filledIconButtonColors(
+                        containerColor = backgroundColor,
+                    ),
+                ) {
+                    Icon(
+                        imageVector = Icons.Outlined.SkipNext,
+                        contentDescription = stringResource(if (isRtl) R.string.action_previous_chapter else R.string.action_next_chapter),
+                    )
+                }
+            }
+        }
+    }
+}

+ 28 - 114
app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderActivity.kt

@@ -6,18 +6,15 @@ import android.app.ProgressDialog
 import android.app.assist.AssistContent
 import android.content.Context
 import android.content.Intent
-import android.content.res.ColorStateList
 import android.graphics.Bitmap
 import android.graphics.Color
 import android.graphics.ColorMatrix
 import android.graphics.ColorMatrixColorFilter
 import android.graphics.Paint
-import android.graphics.drawable.RippleDrawable
 import android.net.Uri
 import android.os.Build
 import android.os.Bundle
 import android.view.Gravity
-import android.view.HapticFeedbackConstants
 import android.view.KeyEvent
 import android.view.Menu
 import android.view.MenuItem
@@ -37,17 +34,16 @@ import androidx.core.transition.doOnEnd
 import androidx.core.view.WindowCompat
 import androidx.core.view.WindowInsetsCompat
 import androidx.core.view.WindowInsetsControllerCompat
-import androidx.core.view.isInvisible
 import androidx.core.view.isVisible
 import androidx.core.view.updateLayoutParams
 import androidx.lifecycle.lifecycleScope
 import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView
 import com.google.android.material.shape.MaterialShapeDrawable
-import com.google.android.material.slider.Slider
 import com.google.android.material.transition.platform.MaterialContainerTransform
 import dev.chrisbanes.insetter.applyInsetter
 import eu.kanade.domain.base.BasePreferences
 import eu.kanade.domain.manga.model.orientationType
+import eu.kanade.presentation.reader.ChapterNavigator
 import eu.kanade.presentation.reader.PageIndicatorText
 import eu.kanade.tachiyomi.R
 import eu.kanade.tachiyomi.data.notification.NotificationReceiver
@@ -66,14 +62,12 @@ import eu.kanade.tachiyomi.ui.reader.setting.OrientationType
 import eu.kanade.tachiyomi.ui.reader.setting.ReaderPreferences
 import eu.kanade.tachiyomi.ui.reader.setting.ReaderSettingsSheet
 import eu.kanade.tachiyomi.ui.reader.setting.ReadingModeType
-import eu.kanade.tachiyomi.ui.reader.viewer.BaseViewer
 import eu.kanade.tachiyomi.ui.reader.viewer.ReaderProgressIndicator
 import eu.kanade.tachiyomi.ui.reader.viewer.pager.R2LPagerViewer
 import eu.kanade.tachiyomi.ui.webview.WebViewActivity
 import eu.kanade.tachiyomi.util.preference.toggle
 import eu.kanade.tachiyomi.util.system.applySystemAnimatorScale
 import eu.kanade.tachiyomi.util.system.createReaderThemeContext
-import eu.kanade.tachiyomi.util.system.getThemeColor
 import eu.kanade.tachiyomi.util.system.hasDisplayCutout
 import eu.kanade.tachiyomi.util.system.isNightMode
 import eu.kanade.tachiyomi.util.system.toShareIntent
@@ -101,7 +95,6 @@ import tachiyomi.core.util.system.logcat
 import tachiyomi.domain.manga.model.Manga
 import uy.kohesive.injekt.injectLazy
 import kotlin.math.abs
-import kotlin.math.max
 
 class ReaderActivity : BaseActivity() {
 
@@ -113,9 +106,6 @@ class ReaderActivity : BaseActivity() {
                 addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
             }
         }
-
-        private const val ENABLED_BUTTON_IMAGE_ALPHA = 255
-        private const val DISABLED_BUTTON_IMAGE_ALPHA = 64
     }
 
     private val readerPreferences: ReaderPreferences by injectLazy()
@@ -128,12 +118,6 @@ class ReaderActivity : BaseActivity() {
 
     val hasCutout by lazy { hasDisplayCutout() }
 
-    /**
-     * Viewer used to display the pages (pager, webtoon, ...).
-     */
-    var viewer: BaseViewer? = null
-        private set
-
     /**
      * Whether the menu is currently visible.
      */
@@ -255,8 +239,7 @@ class ReaderActivity : BaseActivity() {
      */
     override fun onDestroy() {
         super.onDestroy()
-        viewer?.destroy()
-        viewer = null
+        viewModel.state.value.viewer?.destroy()
         config = null
         menuToggleToast?.cancel()
         readingModeToast?.cancel()
@@ -365,7 +348,7 @@ class ReaderActivity : BaseActivity() {
      * Dispatches a key event. If the viewer doesn't handle it, call the default implementation.
      */
     override fun dispatchKeyEvent(event: KeyEvent): Boolean {
-        val handled = viewer?.handleKeyEvent(event) ?: false
+        val handled = viewModel.state.value.viewer?.handleKeyEvent(event) ?: false
         return handled || super.dispatchKeyEvent(event)
     }
 
@@ -374,7 +357,7 @@ class ReaderActivity : BaseActivity() {
      * implementation.
      */
     override fun dispatchGenericMotionEvent(event: MotionEvent): Boolean {
-        val handled = viewer?.handleGenericMotionEvent(event) ?: false
+        val handled = viewModel.state.value.viewer?.handleGenericMotionEvent(event) ?: false
         return handled || super.dispatchGenericMotionEvent(event)
     }
 
@@ -416,46 +399,30 @@ class ReaderActivity : BaseActivity() {
 
             PageIndicatorText(
                 currentPage = state.currentPage,
-                totalPages = state.viewerChapters?.currChapter?.pages?.size ?: -1,
+                totalPages = state.totalPages,
             )
         }
 
         // Init listeners on bottom menu
-        binding.pageSlider.addOnSliderTouchListener(
-            object : Slider.OnSliderTouchListener {
-                override fun onStartTrackingTouch(slider: Slider) {
-                    isScrollingThroughPages = true
-                }
+        binding.readerNav.setComposeContent {
+            val state by viewModel.state.collectAsState()
 
-                override fun onStopTrackingTouch(slider: Slider) {
-                    isScrollingThroughPages = false
-                }
-            },
-        )
-        binding.pageSlider.addOnChangeListener { slider, value, fromUser ->
-            if (viewer != null && fromUser) {
-                isScrollingThroughPages = true
-                moveToPageIndex(value.toInt())
-                slider.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY)
-            }
-        }
-        binding.leftChapter.setOnClickListener {
-            if (viewer != null) {
-                if (viewer is R2LPagerViewer) {
-                    loadNextChapter()
-                } else {
-                    loadPreviousChapter()
-                }
-            }
-        }
-        binding.rightChapter.setOnClickListener {
-            if (viewer != null) {
-                if (viewer is R2LPagerViewer) {
-                    loadPreviousChapter()
-                } else {
-                    loadNextChapter()
-                }
-            }
+            if (state.viewer == null) return@setComposeContent
+            val isRtl = state.viewer is R2LPagerViewer
+
+            ChapterNavigator(
+                isRtl = isRtl,
+                onNextChapter = ::loadNextChapter,
+                enabledNext = state.viewerChapters?.nextChapter != null,
+                onPreviousChapter = ::loadPreviousChapter,
+                enabledPrevious = state.viewerChapters?.prevChapter != null,
+                currentPage = state.currentPage,
+                totalPages = state.totalPages,
+                onSliderValueChange = {
+                    isScrollingThroughPages = true
+                    moveToPageIndex(it)
+                },
+            )
         }
 
         initBottomShortcuts()
@@ -466,18 +433,6 @@ class ReaderActivity : BaseActivity() {
         }
         binding.toolbarBottom.background = toolbarBackground.copy(this@ReaderActivity)
 
-        binding.readerSeekbar.background = toolbarBackground.copy(this@ReaderActivity)?.apply {
-            setCornerSize(999F)
-        }
-        listOf(binding.leftChapter, binding.rightChapter).forEach {
-            it.background = binding.readerSeekbar.background.copy(this)
-            it.foreground = RippleDrawable(
-                ColorStateList.valueOf(getThemeColor(android.R.attr.colorControlHighlight)),
-                null,
-                it.background,
-            )
-        }
-
         val toolbarColor = ColorUtils.setAlphaComponent(
             toolbarBackground.resolvedTintColor,
             toolbarBackground.alpha,
@@ -671,7 +626,7 @@ class ReaderActivity : BaseActivity() {
      * and the toolbar title.
      */
     private fun setManga(manga: Manga) {
-        val prevViewer = viewer
+        val prevViewer = viewModel.state.value.viewer
 
         val viewerMode = ReadingModeType.fromPreference(viewModel.getMangaReadingMode(resolveDefault = false))
         binding.actionReadingMode.setImageResource(viewerMode.iconRes)
@@ -693,7 +648,7 @@ class ReaderActivity : BaseActivity() {
             prevViewer.destroy()
             binding.viewerContainer.removeAllViews()
         }
-        viewer = newViewer
+        viewModel.onViewerLoaded(newViewer)
         updateViewerInset(readerPreferences.fullscreen().get())
         binding.viewerContainer.addView(newViewer.getView())
 
@@ -703,15 +658,6 @@ class ReaderActivity : BaseActivity() {
 
         supportActionBar?.title = manga.title
 
-        binding.pageSlider.isRTL = newViewer is R2LPagerViewer
-        if (newViewer is R2LPagerViewer) {
-            binding.leftChapter.setTooltip(R.string.action_next_chapter)
-            binding.rightChapter.setTooltip(R.string.action_previous_chapter)
-        } else {
-            binding.leftChapter.setTooltip(R.string.action_previous_chapter)
-            binding.rightChapter.setTooltip(R.string.action_next_chapter)
-        }
-
         val loadingIndicatorContext = createReaderThemeContext()
         loadingIndicator = ReaderProgressIndicator(loadingIndicatorContext).apply {
             updateLayoutParams<FrameLayout.LayoutParams> {
@@ -751,26 +697,9 @@ class ReaderActivity : BaseActivity() {
      */
     private fun setChapters(viewerChapters: ViewerChapters) {
         binding.readerContainer.removeView(loadingIndicator)
-        viewer?.setChapters(viewerChapters)
+        viewModel.state.value.viewer?.setChapters(viewerChapters)
         binding.toolbar.subtitle = viewerChapters.currChapter.chapter.name
 
-        val currentChapterPageCount = viewerChapters.currChapter.pages?.size ?: 1
-        binding.readerSeekbar.isInvisible = currentChapterPageCount == 1
-
-        val leftChapterObject = if (viewer is R2LPagerViewer) viewerChapters.nextChapter else viewerChapters.prevChapter
-        val rightChapterObject = if (viewer is R2LPagerViewer) viewerChapters.prevChapter else viewerChapters.nextChapter
-
-        if (leftChapterObject == null && rightChapterObject == null) {
-            binding.leftChapter.isVisible = false
-            binding.rightChapter.isVisible = false
-        } else {
-            binding.leftChapter.isEnabled = leftChapterObject != null
-            binding.leftChapter.imageAlpha = if (leftChapterObject != null) ENABLED_BUTTON_IMAGE_ALPHA else DISABLED_BUTTON_IMAGE_ALPHA
-
-            binding.rightChapter.isEnabled = rightChapterObject != null
-            binding.rightChapter.imageAlpha = if (rightChapterObject != null) ENABLED_BUTTON_IMAGE_ALPHA else DISABLED_BUTTON_IMAGE_ALPHA
-        }
-
         // Invalidate menu to show proper chapter bookmark state
         invalidateOptionsMenu()
 
@@ -812,7 +741,7 @@ class ReaderActivity : BaseActivity() {
      * page is not found.
      */
     private fun moveToPageIndex(index: Int) {
-        val viewer = viewer ?: return
+        val viewer = viewModel.state.value.viewer ?: return
         val currentChapter = viewModel.getCurrentChapter() ?: return
         val page = currentChapter.pages?.getOrNull(index) ?: return
         viewer.moveToPage(page)
@@ -847,21 +776,6 @@ class ReaderActivity : BaseActivity() {
     @SuppressLint("SetTextI18n")
     fun onPageSelected(page: ReaderPage) {
         viewModel.onPageSelected(page)
-        val pages = page.chapter.pages ?: return
-
-        // Set page numbers
-        if (viewer !is R2LPagerViewer) {
-            binding.leftPageText.text = "${page.number}"
-            binding.rightPageText.text = "${pages.size}"
-        } else {
-            binding.rightPageText.text = "${page.number}"
-            binding.leftPageText.text = "${pages.size}"
-        }
-
-        // Set slider progress
-        binding.pageSlider.isEnabled = pages.size > 1
-        binding.pageSlider.valueTo = max(pages.lastIndex.toFloat(), 1f)
-        binding.pageSlider.value = page.index.toFloat()
     }
 
     /**
@@ -989,7 +903,7 @@ class ReaderActivity : BaseActivity() {
      * Updates viewer inset depending on fullscreen reader preferences.
      */
     fun updateViewerInset(fullscreen: Boolean) {
-        viewer?.getView()?.applyInsetter {
+        viewModel.state.value.viewer?.getView()?.applyInsetter {
             if (!fullscreen) {
                 type(navigationBars = true, statusBars = true) {
                     padding()

+ 0 - 30
app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderSlider.kt

@@ -1,30 +0,0 @@
-package eu.kanade.tachiyomi.ui.reader
-
-import android.content.Context
-import android.util.AttributeSet
-import com.google.android.material.slider.Slider
-
-/**
- * Slider to show current chapter progress.
- */
-class ReaderSlider @JvmOverloads constructor(
-    context: Context,
-    attrs: AttributeSet? = null,
-) : Slider(context, attrs) {
-
-    init {
-        stepSize = 1f
-        setLabelFormatter { value ->
-            (value.toInt() + 1).toString()
-        }
-    }
-
-    /**
-     * Whether the slider should draw from right to left.
-     */
-    var isRTL: Boolean
-        set(value) {
-            layoutDirection = if (value) LAYOUT_DIRECTION_RTL else LAYOUT_DIRECTION_LTR
-        }
-        get() = layoutDirection == LAYOUT_DIRECTION_RTL
-}

+ 18 - 1
app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderViewModel.kt

@@ -33,6 +33,7 @@ import eu.kanade.tachiyomi.ui.reader.model.ViewerChapters
 import eu.kanade.tachiyomi.ui.reader.setting.OrientationType
 import eu.kanade.tachiyomi.ui.reader.setting.ReaderPreferences
 import eu.kanade.tachiyomi.ui.reader.setting.ReadingModeType
+import eu.kanade.tachiyomi.ui.reader.viewer.Viewer
 import eu.kanade.tachiyomi.util.chapter.removeDuplicates
 import eu.kanade.tachiyomi.util.editCover
 import eu.kanade.tachiyomi.util.lang.byteSize
@@ -396,6 +397,14 @@ class ReaderViewModel(
         eventChannel.trySend(Event.ReloadViewerChapters)
     }
 
+    fun onViewerLoaded(viewer: Viewer?) {
+        mutableState.update {
+            it.copy(
+                viewer = viewer,
+            )
+        }
+    }
+
     /**
      * Called every time a page changes on the reader. Used to mark the flag of chapters being
      * read, update tracking services, enqueue downloaded chapter deletion, and updating the active chapter if this
@@ -881,7 +890,15 @@ class ReaderViewModel(
         val viewerChapters: ViewerChapters? = null,
         val isLoadingAdjacentChapter: Boolean = false,
         val currentPage: Int = -1,
-    )
+
+        /**
+         * Viewer used to display the pages (pager, webtoon, ...).
+         */
+        val viewer: Viewer? = null,
+    ) {
+        val totalPages: Int
+            get() = viewerChapters?.currChapter?.pages?.size ?: -1
+    }
 
     sealed class Event {
         object ReloadViewerChapters : Event()

+ 1 - 1
app/src/main/java/eu/kanade/tachiyomi/ui/reader/setting/ReaderReadingModeSettings.kt

@@ -34,7 +34,7 @@ class ReaderReadingModeSettings @JvmOverloads constructor(context: Context, attr
 
         initGeneralPreferences()
 
-        when ((context as ReaderActivity).viewer) {
+        when ((context as ReaderActivity).viewModel.state.value.viewer) {
             is PagerViewer -> initPagerPreferences()
             is WebtoonViewer -> initWebtoonPreferences()
         }

+ 2 - 2
app/src/main/java/eu/kanade/tachiyomi/ui/reader/setting/ReadingModeType.kt

@@ -4,7 +4,7 @@ import androidx.annotation.DrawableRes
 import androidx.annotation.StringRes
 import eu.kanade.tachiyomi.R
 import eu.kanade.tachiyomi.ui.reader.ReaderActivity
-import eu.kanade.tachiyomi.ui.reader.viewer.BaseViewer
+import eu.kanade.tachiyomi.ui.reader.viewer.Viewer
 import eu.kanade.tachiyomi.ui.reader.viewer.pager.L2RPagerViewer
 import eu.kanade.tachiyomi.ui.reader.viewer.pager.R2LPagerViewer
 import eu.kanade.tachiyomi.ui.reader.viewer.pager.VerticalPagerViewer
@@ -31,7 +31,7 @@ enum class ReadingModeType(val prefValue: Int, @StringRes val stringRes: Int, @D
 
         fun fromSpinner(position: Int?) = values().find { value -> value.prefValue == position } ?: DEFAULT
 
-        fun toViewer(preference: Int?, activity: ReaderActivity): BaseViewer {
+        fun toViewer(preference: Int?, activity: ReaderActivity): Viewer {
             return when (fromPreference(preference)) {
                 LEFT_TO_RIGHT -> L2RPagerViewer(activity)
                 RIGHT_TO_LEFT -> R2LPagerViewer(activity)

+ 1 - 1
app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/BaseViewer.kt → app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/Viewer.kt

@@ -9,7 +9,7 @@ import eu.kanade.tachiyomi.ui.reader.model.ViewerChapters
 /**
  * Interface for implementing a viewer.
  */
-interface BaseViewer {
+interface Viewer {
 
     /**
      * Returns the view this viewer uses.

+ 3 - 3
app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/pager/PagerViewer.kt

@@ -17,7 +17,7 @@ import eu.kanade.tachiyomi.ui.reader.model.ChapterTransition
 import eu.kanade.tachiyomi.ui.reader.model.InsertPage
 import eu.kanade.tachiyomi.ui.reader.model.ReaderPage
 import eu.kanade.tachiyomi.ui.reader.model.ViewerChapters
-import eu.kanade.tachiyomi.ui.reader.viewer.BaseViewer
+import eu.kanade.tachiyomi.ui.reader.viewer.Viewer
 import eu.kanade.tachiyomi.ui.reader.viewer.ViewerNavigation.NavigationRegion
 import kotlinx.coroutines.MainScope
 import kotlinx.coroutines.cancel
@@ -26,10 +26,10 @@ import uy.kohesive.injekt.injectLazy
 import kotlin.math.min
 
 /**
- * Implementation of a [BaseViewer] to display pages with a [ViewPager].
+ * Implementation of a [Viewer] to display pages with a [ViewPager].
  */
 @Suppress("LeakingThis")
-abstract class PagerViewer(val activity: ReaderActivity) : BaseViewer {
+abstract class PagerViewer(val activity: ReaderActivity) : Viewer {
 
     val downloadManager: DownloadManager by injectLazy()
 

+ 3 - 3
app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/webtoon/WebtoonViewer.kt

@@ -18,7 +18,7 @@ import eu.kanade.tachiyomi.ui.reader.model.ReaderPage
 import eu.kanade.tachiyomi.ui.reader.model.StencilPage
 import eu.kanade.tachiyomi.ui.reader.model.ViewerChapters
 import eu.kanade.tachiyomi.ui.reader.setting.ReaderPreferences
-import eu.kanade.tachiyomi.ui.reader.viewer.BaseViewer
+import eu.kanade.tachiyomi.ui.reader.viewer.Viewer
 import eu.kanade.tachiyomi.ui.reader.viewer.ViewerNavigation.NavigationRegion
 import kotlinx.coroutines.MainScope
 import kotlinx.coroutines.cancel
@@ -30,9 +30,9 @@ import kotlin.math.max
 import kotlin.math.min
 
 /**
- * Implementation of a [BaseViewer] to display pages with a [RecyclerView].
+ * Implementation of a [Viewer] to display pages with a [RecyclerView].
  */
-class WebtoonViewer(val activity: ReaderActivity, val isContinuous: Boolean = true) : BaseViewer {
+class WebtoonViewer(val activity: ReaderActivity, val isContinuous: Boolean = true) : Viewer {
 
     val downloadManager: DownloadManager by injectLazy()
 

+ 0 - 14
app/src/main/java/eu/kanade/tachiyomi/util/system/ContextExtensions.kt

@@ -12,7 +12,6 @@ import android.graphics.drawable.Drawable
 import android.net.Uri
 import android.os.Build
 import android.os.PowerManager
-import android.util.TypedValue
 import androidx.annotation.AttrRes
 import androidx.annotation.ColorInt
 import androidx.appcompat.view.ContextThemeWrapper
@@ -89,19 +88,6 @@ fun Context.hasPermission(permission: String) = PermissionChecker.checkSelfPermi
     return color
 }
 
-@ColorInt fun Context.getThemeColor(attr: Int): Int {
-    val tv = TypedValue()
-    return if (this.theme.resolveAttribute(attr, tv, true)) {
-        if (tv.resourceId != 0) {
-            getColor(tv.resourceId)
-        } else {
-            tv.data
-        }
-    } else {
-        0
-    }
-}
-
 val Context.powerManager: PowerManager
     get() = getSystemService()!!
 

+ 0 - 9
app/src/main/res/drawable/ic_skip_next_24dp.xml

@@ -1,9 +0,0 @@
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:width="24dp"
-    android:height="24dp"
-    android:viewportWidth="24"
-    android:viewportHeight="24">
-    <path
-        android:fillColor="@android:color/black"
-        android:pathData="M6,18l8.5,-6L6,6v12zM16,6v12h2V6h-2z" />
-</vector>

+ 0 - 9
app/src/main/res/drawable/ic_skip_previous_24dp.xml

@@ -1,9 +0,0 @@
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:width="24dp"
-    android:height="24dp"
-    android:viewportWidth="24"
-    android:viewportHeight="24">
-    <path
-        android:fillColor="@android:color/black"
-        android:pathData="M6,6h2v12L6,18zM9.5,12l8.5,6L18,6z" />
-</vector>

+ 2 - 72
app/src/main/res/layout/reader_activity.xml

@@ -59,82 +59,12 @@
             android:layout_gravity="bottom"
             android:orientation="vertical">
 
-            <LinearLayout
+            <androidx.compose.ui.platform.ComposeView
                 android:id="@+id/reader_nav"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
-                android:layout_marginStart="8dp"
-                android:layout_marginEnd="8dp"
                 android:layout_marginBottom="16dp"
-                android:layoutDirection="ltr"
-                android:orientation="horizontal">
-
-                <ImageButton
-                    android:id="@+id/left_chapter"
-                    android:layout_width="48dp"
-                    android:layout_height="48dp"
-                    android:layout_marginEnd="8dp"
-                    android:contentDescription="@string/action_previous_chapter"
-                    android:padding="@dimen/screen_edge_margin"
-                    app:srcCompat="@drawable/ic_skip_previous_24dp"
-                    app:tint="?attr/colorOnSurface" />
-
-                <LinearLayout
-                    android:id="@+id/reader_seekbar"
-                    android:layout_width="0dp"
-                    android:layout_height="match_parent"
-                    android:layout_weight="1"
-                    android:clickable="true"
-                    android:paddingStart="8dp"
-                    android:paddingEnd="8dp"
-                    tools:ignore="KeyboardInaccessibleWidget">
-
-                    <TextView
-                        android:id="@+id/left_page_text"
-                        android:layout_width="wrap_content"
-                        android:layout_height="match_parent"
-                        android:gravity="center"
-                        android:minWidth="32dp"
-                        android:textColor="?attr/colorOnSurface"
-                        android:textSize="15sp"
-                        tools:text="1" />
-
-                    <!--
-                        Wonky way of setting height due to issues with horizontally centering the thumb in Android 5.
-                        See https://stackoverflow.com/questions/15701767/android-thumb-is-not-centered-in-seekbar
-                    -->
-                    <eu.kanade.tachiyomi.ui.reader.ReaderSlider
-                        android:id="@+id/page_slider"
-                        android:layout_width="0dp"
-                        android:layout_height="wrap_content"
-                        android:layout_weight="1"
-                        android:maxHeight="?attr/actionBarSize"
-                        android:minHeight="?attr/actionBarSize"
-                        app:tickVisible="true"/>
-
-                    <TextView
-                        android:id="@+id/right_page_text"
-                        android:layout_width="wrap_content"
-                        android:layout_height="match_parent"
-                        android:gravity="center"
-                        android:minWidth="32dp"
-                        android:textColor="?attr/colorOnSurface"
-                        android:textSize="15sp"
-                        tools:text="15" />
-
-                </LinearLayout>
-
-                <ImageButton
-                    android:id="@+id/right_chapter"
-                    android:layout_width="48dp"
-                    android:layout_height="48dp"
-                    android:layout_marginStart="8dp"
-                    android:contentDescription="@string/action_next_chapter"
-                    android:padding="@dimen/screen_edge_margin"
-                    app:srcCompat="@drawable/ic_skip_next_24dp"
-                    app:tint="?attr/colorOnSurface" />
-
-            </LinearLayout>
+                android:layoutDirection="ltr" />
 
             <androidx.constraintlayout.widget.ConstraintLayout
                 android:id="@+id/toolbar_bottom"