Migrate reader slider and next/prev buttons to Compose
(cherry picked from commit 9a10656bf07a7dd35400fa6e42dd0e4889ddb177) # Conflicts: # app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderActivity.kt # app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderViewModel.kt # app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/webtoon/WebtoonViewer.kt # app/src/main/res/layout/reader_activity.xml
This commit is contained in:
parent
c320daf832
commit
2d013c551d
@ -0,0 +1,255 @@
|
|||||||
|
package eu.kanade.presentation.reader
|
||||||
|
|
||||||
|
import androidx.compose.foundation.background
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.Row
|
||||||
|
import androidx.compose.foundation.layout.Spacer
|
||||||
|
import androidx.compose.foundation.layout.fillMaxHeight
|
||||||
|
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.draw.rotate
|
||||||
|
import androidx.compose.ui.graphics.TransformOrigin
|
||||||
|
import androidx.compose.ui.graphics.graphicsLayer
|
||||||
|
import androidx.compose.ui.hapticfeedback.HapticFeedbackType
|
||||||
|
import androidx.compose.ui.layout.layout
|
||||||
|
import androidx.compose.ui.platform.LocalHapticFeedback
|
||||||
|
import androidx.compose.ui.platform.LocalLayoutDirection
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.compose.ui.unit.Constraints
|
||||||
|
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,
|
||||||
|
isVerticalSlider: Boolean,
|
||||||
|
onNextChapter: () -> Unit,
|
||||||
|
enabledNext: Boolean,
|
||||||
|
onPreviousChapter: () -> Unit,
|
||||||
|
enabledPrevious: Boolean,
|
||||||
|
currentPage: Int,
|
||||||
|
// SY -->
|
||||||
|
currentPageText: String,
|
||||||
|
// SY <--
|
||||||
|
totalPages: Int,
|
||||||
|
onSliderValueChange: (Int) -> Unit,
|
||||||
|
) {
|
||||||
|
// SY -->
|
||||||
|
if (isVerticalSlider) {
|
||||||
|
ChapterNavigatorVert(
|
||||||
|
onNextChapter = onNextChapter,
|
||||||
|
enabledNext = enabledNext,
|
||||||
|
onPreviousChapter = onPreviousChapter,
|
||||||
|
enabledPrevious = enabledPrevious,
|
||||||
|
currentPage = currentPage,
|
||||||
|
currentPageText = currentPageText,
|
||||||
|
totalPages = totalPages,
|
||||||
|
onSliderValueChange = onSliderValueChange,
|
||||||
|
)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// SY <--
|
||||||
|
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,
|
||||||
|
) {
|
||||||
|
// SY -->
|
||||||
|
Text(text = currentPageText)
|
||||||
|
// SY <--
|
||||||
|
|
||||||
|
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),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun ChapterNavigatorVert(
|
||||||
|
onNextChapter: () -> Unit,
|
||||||
|
enabledNext: Boolean,
|
||||||
|
onPreviousChapter: () -> Unit,
|
||||||
|
enabledPrevious: Boolean,
|
||||||
|
currentPage: Int,
|
||||||
|
// SY -->
|
||||||
|
currentPageText: String,
|
||||||
|
// SY <--
|
||||||
|
totalPages: Int,
|
||||||
|
onSliderValueChange: (Int) -> Unit,
|
||||||
|
) {
|
||||||
|
val isTabletUi = isTabletUi()
|
||||||
|
val verticalPadding = if (isTabletUi) 24.dp else 16.dp
|
||||||
|
|
||||||
|
val backgroundColor = MaterialTheme.colorScheme.surface.copy(alpha = 0.9f)
|
||||||
|
val haptic = LocalHapticFeedback.current
|
||||||
|
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxHeight()
|
||||||
|
.padding(vertical = verticalPadding, horizontal = 8.dp),
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
|
) {
|
||||||
|
if (enabledPrevious) {
|
||||||
|
FilledIconButton(
|
||||||
|
onClick = onPreviousChapter,
|
||||||
|
colors = IconButtonDefaults.filledIconButtonColors(
|
||||||
|
containerColor = backgroundColor,
|
||||||
|
),
|
||||||
|
) {
|
||||||
|
Icon(
|
||||||
|
imageVector = Icons.Outlined.SkipPrevious,
|
||||||
|
contentDescription = stringResource(R.string.action_previous_chapter),
|
||||||
|
modifier = Modifier.rotate(90f),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (totalPages > 1) {
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.weight(1f)
|
||||||
|
.clip(RoundedCornerShape(24.dp))
|
||||||
|
.background(backgroundColor)
|
||||||
|
.padding(vertical = 16.dp),
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
|
) {
|
||||||
|
// SY -->
|
||||||
|
Text(text = currentPageText)
|
||||||
|
// SY <--
|
||||||
|
|
||||||
|
Slider(
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(vertical = 8.dp)
|
||||||
|
.graphicsLayer {
|
||||||
|
rotationZ = 90f
|
||||||
|
transformOrigin = TransformOrigin(0f, 0f)
|
||||||
|
}
|
||||||
|
.layout { measurable, constraints ->
|
||||||
|
val placeable = measurable.measure(
|
||||||
|
Constraints(
|
||||||
|
minWidth = constraints.minHeight,
|
||||||
|
maxWidth = constraints.maxHeight,
|
||||||
|
minHeight = constraints.minWidth,
|
||||||
|
maxHeight = constraints.maxWidth,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
layout(placeable.height, placeable.width) {
|
||||||
|
placeable.place(0, -placeable.height)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.weight(1f),
|
||||||
|
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))
|
||||||
|
}
|
||||||
|
|
||||||
|
if (enabledNext) {
|
||||||
|
FilledIconButton(
|
||||||
|
onClick = onNextChapter,
|
||||||
|
colors = IconButtonDefaults.filledIconButtonColors(
|
||||||
|
containerColor = backgroundColor,
|
||||||
|
),
|
||||||
|
) {
|
||||||
|
Icon(
|
||||||
|
imageVector = Icons.Outlined.SkipNext,
|
||||||
|
contentDescription = stringResource(R.string.action_next_chapter),
|
||||||
|
modifier = Modifier.rotate(90f),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -13,14 +13,12 @@ import android.graphics.Color
|
|||||||
import android.graphics.ColorMatrix
|
import android.graphics.ColorMatrix
|
||||||
import android.graphics.ColorMatrixColorFilter
|
import android.graphics.ColorMatrixColorFilter
|
||||||
import android.graphics.Paint
|
import android.graphics.Paint
|
||||||
import android.graphics.drawable.RippleDrawable
|
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.text.Editable
|
import android.text.Editable
|
||||||
import android.text.TextWatcher
|
import android.text.TextWatcher
|
||||||
import android.view.Gravity
|
import android.view.Gravity
|
||||||
import android.view.HapticFeedbackConstants
|
|
||||||
import android.view.KeyEvent
|
import android.view.KeyEvent
|
||||||
import android.view.Menu
|
import android.view.Menu
|
||||||
import android.view.MotionEvent
|
import android.view.MotionEvent
|
||||||
@ -35,6 +33,7 @@ import android.widget.TextView
|
|||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.activity.viewModels
|
import androidx.activity.viewModels
|
||||||
import androidx.annotation.ColorInt
|
import androidx.annotation.ColorInt
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.collectAsState
|
import androidx.compose.runtime.collectAsState
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.core.graphics.ColorUtils
|
import androidx.core.graphics.ColorUtils
|
||||||
@ -43,7 +42,6 @@ import androidx.core.transition.doOnEnd
|
|||||||
import androidx.core.view.WindowCompat
|
import androidx.core.view.WindowCompat
|
||||||
import androidx.core.view.WindowInsetsCompat
|
import androidx.core.view.WindowInsetsCompat
|
||||||
import androidx.core.view.WindowInsetsControllerCompat
|
import androidx.core.view.WindowInsetsControllerCompat
|
||||||
import androidx.core.view.isInvisible
|
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import androidx.core.view.updateLayoutParams
|
import androidx.core.view.updateLayoutParams
|
||||||
import androidx.lifecycle.Lifecycle
|
import androidx.lifecycle.Lifecycle
|
||||||
@ -52,12 +50,12 @@ import androidx.lifecycle.repeatOnLifecycle
|
|||||||
import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView
|
import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView
|
||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
import com.google.android.material.shape.MaterialShapeDrawable
|
import com.google.android.material.shape.MaterialShapeDrawable
|
||||||
import com.google.android.material.slider.Slider
|
|
||||||
import com.google.android.material.transition.platform.MaterialContainerTransform
|
import com.google.android.material.transition.platform.MaterialContainerTransform
|
||||||
import dev.chrisbanes.insetter.applyInsetter
|
import dev.chrisbanes.insetter.applyInsetter
|
||||||
import eu.kanade.domain.base.BasePreferences
|
import eu.kanade.domain.base.BasePreferences
|
||||||
import eu.kanade.domain.manga.model.orientationType
|
import eu.kanade.domain.manga.model.orientationType
|
||||||
import eu.kanade.domain.manga.model.readingModeType
|
import eu.kanade.domain.manga.model.readingModeType
|
||||||
|
import eu.kanade.presentation.reader.ChapterNavigator
|
||||||
import eu.kanade.presentation.reader.PageIndicatorText
|
import eu.kanade.presentation.reader.PageIndicatorText
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
import eu.kanade.tachiyomi.data.notification.NotificationReceiver
|
import eu.kanade.tachiyomi.data.notification.NotificationReceiver
|
||||||
@ -80,7 +78,6 @@ import eu.kanade.tachiyomi.ui.reader.setting.ReaderBottomButton
|
|||||||
import eu.kanade.tachiyomi.ui.reader.setting.ReaderPreferences
|
import eu.kanade.tachiyomi.ui.reader.setting.ReaderPreferences
|
||||||
import eu.kanade.tachiyomi.ui.reader.setting.ReaderSettingsSheet
|
import eu.kanade.tachiyomi.ui.reader.setting.ReaderSettingsSheet
|
||||||
import eu.kanade.tachiyomi.ui.reader.setting.ReadingModeType
|
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.ReaderProgressIndicator
|
||||||
import eu.kanade.tachiyomi.ui.reader.viewer.pager.PagerConfig
|
import eu.kanade.tachiyomi.ui.reader.viewer.pager.PagerConfig
|
||||||
import eu.kanade.tachiyomi.ui.reader.viewer.pager.PagerViewer
|
import eu.kanade.tachiyomi.ui.reader.viewer.pager.PagerViewer
|
||||||
@ -91,7 +88,6 @@ import eu.kanade.tachiyomi.ui.webview.WebViewActivity
|
|||||||
import eu.kanade.tachiyomi.util.preference.toggle
|
import eu.kanade.tachiyomi.util.preference.toggle
|
||||||
import eu.kanade.tachiyomi.util.system.applySystemAnimatorScale
|
import eu.kanade.tachiyomi.util.system.applySystemAnimatorScale
|
||||||
import eu.kanade.tachiyomi.util.system.createReaderThemeContext
|
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.hasDisplayCutout
|
||||||
import eu.kanade.tachiyomi.util.system.isLTR
|
import eu.kanade.tachiyomi.util.system.isLTR
|
||||||
import eu.kanade.tachiyomi.util.system.isNightMode
|
import eu.kanade.tachiyomi.util.system.isNightMode
|
||||||
@ -105,7 +101,6 @@ import eu.kanade.tachiyomi.widget.listener.SimpleAnimationListener
|
|||||||
import exh.log.xLogE
|
import exh.log.xLogE
|
||||||
import exh.source.isEhBasedSource
|
import exh.source.isEhBasedSource
|
||||||
import exh.util.defaultReaderType
|
import exh.util.defaultReaderType
|
||||||
import exh.util.floor
|
|
||||||
import exh.util.mangaType
|
import exh.util.mangaType
|
||||||
import kotlinx.coroutines.channels.awaitClose
|
import kotlinx.coroutines.channels.awaitClose
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
@ -134,7 +129,6 @@ import tachiyomi.domain.manga.model.Manga
|
|||||||
import tachiyomi.domain.source.service.SourceManager
|
import tachiyomi.domain.source.service.SourceManager
|
||||||
import uy.kohesive.injekt.injectLazy
|
import uy.kohesive.injekt.injectLazy
|
||||||
import kotlin.math.abs
|
import kotlin.math.abs
|
||||||
import kotlin.math.max
|
|
||||||
import kotlin.time.Duration.Companion.seconds
|
import kotlin.time.Duration.Companion.seconds
|
||||||
|
|
||||||
class ReaderActivity : BaseActivity() {
|
class ReaderActivity : BaseActivity() {
|
||||||
@ -155,9 +149,6 @@ class ReaderActivity : BaseActivity() {
|
|||||||
const val SHIFT_DOUBLE_PAGES = "shiftingDoublePages"
|
const val SHIFT_DOUBLE_PAGES = "shiftingDoublePages"
|
||||||
const val SHIFTED_PAGE_INDEX = "shiftedPageIndex"
|
const val SHIFTED_PAGE_INDEX = "shiftedPageIndex"
|
||||||
const val SHIFTED_CHAP_INDEX = "shiftedChapterIndex"
|
const val SHIFTED_CHAP_INDEX = "shiftedChapterIndex"
|
||||||
|
|
||||||
private const val ENABLED_BUTTON_IMAGE_ALPHA = 255
|
|
||||||
private const val DISABLED_BUTTON_IMAGE_ALPHA = 64
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private val readerPreferences: ReaderPreferences by injectLazy()
|
private val readerPreferences: ReaderPreferences by injectLazy()
|
||||||
@ -170,12 +161,6 @@ class ReaderActivity : BaseActivity() {
|
|||||||
|
|
||||||
val hasCutout by lazy { hasDisplayCutout() }
|
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.
|
* Whether the menu is currently visible.
|
||||||
*/
|
*/
|
||||||
@ -330,8 +315,7 @@ class ReaderActivity : BaseActivity() {
|
|||||||
*/
|
*/
|
||||||
override fun onDestroy() {
|
override fun onDestroy() {
|
||||||
super.onDestroy()
|
super.onDestroy()
|
||||||
viewer?.destroy()
|
viewModel.state.value.viewer?.destroy()
|
||||||
viewer = null
|
|
||||||
config = null
|
config = null
|
||||||
menuToggleToast?.cancel()
|
menuToggleToast?.cancel()
|
||||||
readingModeToast?.cancel()
|
readingModeToast?.cancel()
|
||||||
@ -349,7 +333,7 @@ class ReaderActivity : BaseActivity() {
|
|||||||
outState.putBoolean(::ehUtilsVisible.name, ehUtilsVisible)
|
outState.putBoolean(::ehUtilsVisible.name, ehUtilsVisible)
|
||||||
// EXH <--
|
// EXH <--
|
||||||
// SY -->
|
// SY -->
|
||||||
(viewer as? PagerViewer)?.let { pViewer ->
|
(viewModel.state.value.viewer as? PagerViewer)?.let { pViewer ->
|
||||||
val config = pViewer.config
|
val config = pViewer.config
|
||||||
outState.putBoolean(SHIFT_DOUBLE_PAGES, config.shiftDoublePage)
|
outState.putBoolean(SHIFT_DOUBLE_PAGES, config.shiftDoublePage)
|
||||||
if (config.shiftDoublePage && config.doublePages) {
|
if (config.shiftDoublePage && config.doublePages) {
|
||||||
@ -455,7 +439,7 @@ class ReaderActivity : BaseActivity() {
|
|||||||
* Dispatches a key event. If the viewer doesn't handle it, call the default implementation.
|
* Dispatches a key event. If the viewer doesn't handle it, call the default implementation.
|
||||||
*/
|
*/
|
||||||
override fun dispatchKeyEvent(event: KeyEvent): Boolean {
|
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)
|
return handled || super.dispatchKeyEvent(event)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -464,7 +448,7 @@ class ReaderActivity : BaseActivity() {
|
|||||||
* implementation.
|
* implementation.
|
||||||
*/
|
*/
|
||||||
override fun dispatchGenericMotionEvent(event: MotionEvent): Boolean {
|
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)
|
return handled || super.dispatchGenericMotionEvent(event)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -535,60 +519,47 @@ class ReaderActivity : BaseActivity() {
|
|||||||
val state by viewModel.state.collectAsState()
|
val state by viewModel.state.collectAsState()
|
||||||
|
|
||||||
PageIndicatorText(
|
PageIndicatorText(
|
||||||
currentPage = state.currentPage,
|
// SY -->
|
||||||
totalPages = state.viewerChapters?.currChapter?.pages?.size ?: -1,
|
currentPage = state.currentPageText,
|
||||||
|
// SY <--
|
||||||
|
totalPages = state.totalPages,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SY -->
|
// SY -->
|
||||||
|
val sliderContent: @Composable (Boolean) -> Unit = a@{ isVertical ->
|
||||||
|
val state by viewModel.state.collectAsState()
|
||||||
|
|
||||||
|
if (state.viewer == null) return@a
|
||||||
|
val isRtl = state.viewer is R2LPagerViewer
|
||||||
|
|
||||||
|
ChapterNavigator(
|
||||||
|
isRtl = isRtl,
|
||||||
|
// SY -->
|
||||||
|
isVerticalSlider = isVertical,
|
||||||
|
// SY <--
|
||||||
|
onNextChapter = ::loadNextChapter,
|
||||||
|
enabledNext = state.viewerChapters?.nextChapter != null,
|
||||||
|
onPreviousChapter = ::loadPreviousChapter,
|
||||||
|
enabledPrevious = state.viewerChapters?.prevChapter != null,
|
||||||
|
currentPage = state.currentPage,
|
||||||
|
// SY -->
|
||||||
|
currentPageText = state.currentPageText,
|
||||||
|
// SY <--
|
||||||
|
totalPages = state.totalPages,
|
||||||
|
onSliderValueChange = {
|
||||||
|
isScrollingThroughPages = true
|
||||||
|
moveToPageIndex(it)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
// Init listeners on bottom menu
|
// Init listeners on bottom menu
|
||||||
val listener = object : Slider.OnSliderTouchListener {
|
binding.readerNavHorz.setComposeContent {
|
||||||
override fun onStartTrackingTouch(slider: Slider) {
|
sliderContent(false)
|
||||||
isScrollingThroughPages = true
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onStopTrackingTouch(slider: Slider) {
|
|
||||||
isScrollingThroughPages = false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
val onChangeListener = Slider.OnChangeListener { slider, value, fromUser ->
|
binding.readerNavVert.setComposeContent {
|
||||||
if (viewer != null && fromUser) {
|
sliderContent(true)
|
||||||
isScrollingThroughPages = true
|
|
||||||
moveToPageIndex(value.toInt())
|
|
||||||
slider.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
listOf(binding.pageSlider, binding.pageSliderVert)
|
|
||||||
.forEach {
|
|
||||||
it.addOnSliderTouchListener(listener)
|
|
||||||
it.addOnChangeListener(onChangeListener)
|
|
||||||
}
|
|
||||||
// SY <--
|
|
||||||
|
|
||||||
// Extra menu buttons
|
|
||||||
|
|
||||||
// SY -->
|
|
||||||
listOf(binding.leftChapter, binding.aboveChapter).forEach {
|
|
||||||
it.setOnClickListener {
|
|
||||||
if (viewer != null) {
|
|
||||||
if (viewer is R2LPagerViewer) {
|
|
||||||
loadNextChapter()
|
|
||||||
} else {
|
|
||||||
loadPreviousChapter()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
listOf(binding.rightChapter, binding.belowChapter).forEach {
|
|
||||||
it.setOnClickListener {
|
|
||||||
if (viewer != null) {
|
|
||||||
if (viewer is R2LPagerViewer) {
|
|
||||||
loadPreviousChapter()
|
|
||||||
} else {
|
|
||||||
loadNextChapter()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
initBottomShortcuts()
|
initBottomShortcuts()
|
||||||
@ -604,23 +575,6 @@ class ReaderActivity : BaseActivity() {
|
|||||||
}
|
}
|
||||||
binding.toolbarBottom.background = toolbarBackground.copy(this@ReaderActivity)
|
binding.toolbarBottom.background = toolbarBackground.copy(this@ReaderActivity)
|
||||||
|
|
||||||
binding.readerSeekbar.background = toolbarBackground.copy(this@ReaderActivity)?.apply {
|
|
||||||
setCornerSize(999F)
|
|
||||||
}
|
|
||||||
// SY -->
|
|
||||||
binding.readerSeekbarVert.background = toolbarBackground.copy(this@ReaderActivity)?.apply {
|
|
||||||
setCornerSize(999F)
|
|
||||||
}
|
|
||||||
// SY <--
|
|
||||||
listOf(binding.leftChapter, binding.rightChapter /* SY --> */, binding.belowChapter, binding.aboveChapter /* SY <-- */).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(
|
val toolbarColor = ColorUtils.setAlphaComponent(
|
||||||
toolbarBackground.resolvedTintColor,
|
toolbarBackground.resolvedTintColor,
|
||||||
toolbarBackground.alpha,
|
toolbarBackground.alpha,
|
||||||
@ -766,7 +720,7 @@ class ReaderActivity : BaseActivity() {
|
|||||||
|
|
||||||
setOnClickListener {
|
setOnClickListener {
|
||||||
if (readerPreferences.pageLayout().get() == PagerConfig.PageLayout.AUTOMATIC) {
|
if (readerPreferences.pageLayout().get() == PagerConfig.PageLayout.AUTOMATIC) {
|
||||||
(viewer as? PagerViewer)?.config?.let { config ->
|
(viewModel.state.value.viewer as? PagerViewer)?.config?.let { config ->
|
||||||
config.doublePages = !config.doublePages
|
config.doublePages = !config.doublePages
|
||||||
reloadChapters(config.doublePages, true)
|
reloadChapters(config.doublePages, true)
|
||||||
}
|
}
|
||||||
@ -821,7 +775,7 @@ class ReaderActivity : BaseActivity() {
|
|||||||
val interval = parsed.seconds
|
val interval = parsed.seconds
|
||||||
while (true) {
|
while (true) {
|
||||||
if (!binding.readerMenu.isVisible) {
|
if (!binding.readerMenu.isVisible) {
|
||||||
viewer.let { v ->
|
viewModel.state.value.viewer.let { v ->
|
||||||
when (v) {
|
when (v) {
|
||||||
is PagerViewer -> v.moveToNext()
|
is PagerViewer -> v.moveToNext()
|
||||||
is WebtoonViewer -> {
|
is WebtoonViewer -> {
|
||||||
@ -903,7 +857,7 @@ class ReaderActivity : BaseActivity() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
binding.ehBoostPage.setOnClickListener {
|
binding.ehBoostPage.setOnClickListener {
|
||||||
viewer ?: return@setOnClickListener
|
viewModel.state.value.viewer ?: return@setOnClickListener
|
||||||
val curPage = exhCurrentpage() ?: run {
|
val curPage = exhCurrentpage() ?: run {
|
||||||
toast(R.string.eh_boost_page_invalid)
|
toast(R.string.eh_boost_page_invalid)
|
||||||
return@setOnClickListener
|
return@setOnClickListener
|
||||||
@ -936,11 +890,13 @@ class ReaderActivity : BaseActivity() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun exhCurrentpage(): ReaderPage? {
|
private fun exhCurrentpage(): ReaderPage? {
|
||||||
|
val viewer = viewModel.state.value.viewer
|
||||||
val currentPage = (((viewer as? PagerViewer)?.currentPage ?: (viewer as? WebtoonViewer)?.currentPage) as? ReaderPage)?.index
|
val currentPage = (((viewer as? PagerViewer)?.currentPage ?: (viewer as? WebtoonViewer)?.currentPage) as? ReaderPage)?.index
|
||||||
return currentPage?.let { viewModel.state.value.viewerChapters?.currChapter?.pages?.getOrNull(it) }
|
return currentPage?.let { viewModel.state.value.viewerChapters?.currChapter?.pages?.getOrNull(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun updateBottomButtons() {
|
fun updateBottomButtons() {
|
||||||
|
val viewer = viewModel.state.value.viewer
|
||||||
val enabledButtons = readerPreferences.readerBottomButtons().get()
|
val enabledButtons = readerPreferences.readerBottomButtons().get()
|
||||||
with(binding) {
|
with(binding) {
|
||||||
actionReadingMode.isVisible = ReaderBottomButton.ReadingMode.isIn(enabledButtons)
|
actionReadingMode.isVisible = ReaderBottomButton.ReadingMode.isIn(enabledButtons)
|
||||||
@ -968,23 +924,23 @@ class ReaderActivity : BaseActivity() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun reloadChapters(doublePages: Boolean, force: Boolean = false) {
|
fun reloadChapters(doublePages: Boolean, force: Boolean = false) {
|
||||||
val pViewer = viewer as? PagerViewer ?: return
|
val viewer = viewModel.state.value.viewer as? PagerViewer ?: return
|
||||||
pViewer.updateShifting()
|
viewer.updateShifting()
|
||||||
if (!force && pViewer.config.autoDoublePages) {
|
if (!force && viewer.config.autoDoublePages) {
|
||||||
setDoublePageMode(pViewer)
|
setDoublePageMode(viewer)
|
||||||
} else {
|
} else {
|
||||||
pViewer.config.doublePages = doublePages
|
viewer.config.doublePages = doublePages
|
||||||
}
|
}
|
||||||
val currentChapter = viewModel.getCurrentChapter()
|
val currentChapter = viewModel.getCurrentChapter()
|
||||||
if (doublePages) {
|
if (doublePages) {
|
||||||
// If we're moving from singe to double, we want the current page to be the first page
|
// If we're moving from singe to double, we want the current page to be the first page
|
||||||
pViewer.config.shiftDoublePage = (
|
val currentPage = viewModel.state.value.currentPage
|
||||||
binding.pageSlider.value.floor() +
|
viewer.config.shiftDoublePage = (
|
||||||
(currentChapter?.pages?.take(binding.pageSlider.value.floor())?.count { it.fullPage || it.isolatedPage } ?: 0)
|
currentPage + (currentChapter?.pages?.take(currentPage)?.count { it.fullPage || it.isolatedPage } ?: 0)
|
||||||
) % 2 != 0
|
) % 2 != 0
|
||||||
}
|
}
|
||||||
viewModel.state.value.viewerChapters?.let {
|
viewModel.state.value.viewerChapters?.let {
|
||||||
pViewer.setChaptersDoubleShift(it)
|
viewer.setChaptersDoubleShift(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -994,11 +950,12 @@ class ReaderActivity : BaseActivity() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun shiftDoublePages() {
|
private fun shiftDoublePages() {
|
||||||
(viewer as? PagerViewer)?.config?.let { config ->
|
val viewer = viewModel.state.value.viewer as? PagerViewer ?: return
|
||||||
|
viewer.config.let { config ->
|
||||||
config.shiftDoublePage = !config.shiftDoublePage
|
config.shiftDoublePage = !config.shiftDoublePage
|
||||||
viewModel.state.value.viewerChapters?.let {
|
viewModel.state.value.viewerChapters?.let {
|
||||||
(viewer as? PagerViewer)?.updateShifting()
|
viewer.updateShifting()
|
||||||
(viewer as? PagerViewer)?.setChaptersDoubleShift(it)
|
viewer.setChaptersDoubleShift(it)
|
||||||
invalidateOptionsMenu()
|
invalidateOptionsMenu()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1119,7 +1076,7 @@ class ReaderActivity : BaseActivity() {
|
|||||||
* and the toolbar title.
|
* and the toolbar title.
|
||||||
*/
|
*/
|
||||||
private fun setManga(manga: Manga) {
|
private fun setManga(manga: Manga) {
|
||||||
val prevViewer = viewer
|
val prevViewer = viewModel.state.value.viewer
|
||||||
|
|
||||||
val viewerMode = ReadingModeType.fromPreference(viewModel.getMangaReadingMode(resolveDefault = false))
|
val viewerMode = ReadingModeType.fromPreference(viewModel.getMangaReadingMode(resolveDefault = false))
|
||||||
binding.actionReadingMode.setImageResource(viewerMode.iconRes)
|
binding.actionReadingMode.setImageResource(viewerMode.iconRes)
|
||||||
@ -1141,7 +1098,7 @@ class ReaderActivity : BaseActivity() {
|
|||||||
prevViewer.destroy()
|
prevViewer.destroy()
|
||||||
binding.viewerContainer.removeAllViews()
|
binding.viewerContainer.removeAllViews()
|
||||||
}
|
}
|
||||||
viewer = newViewer
|
viewModel.onViewerLoaded(newViewer)
|
||||||
updateViewerInset(readerPreferences.fullscreen().get())
|
updateViewerInset(readerPreferences.fullscreen().get())
|
||||||
binding.viewerContainer.addView(newViewer.getView())
|
binding.viewerContainer.addView(newViewer.getView())
|
||||||
|
|
||||||
@ -1174,7 +1131,7 @@ class ReaderActivity : BaseActivity() {
|
|||||||
) ||
|
) ||
|
||||||
resources.configuration.orientation == Configuration.ORIENTATION_PORTRAIT
|
resources.configuration.orientation == Configuration.ORIENTATION_PORTRAIT
|
||||||
) &&
|
) &&
|
||||||
(viewer is WebtoonViewer || viewer is VerticalPagerViewer)
|
(viewModel.state.value.viewer is WebtoonViewer || viewModel.state.value.viewer is VerticalPagerViewer)
|
||||||
) {
|
) {
|
||||||
binding.readerNavVert.isVisible = true
|
binding.readerNavVert.isVisible = true
|
||||||
binding.readerNavHorz.isVisible = false
|
binding.readerNavHorz.isVisible = false
|
||||||
@ -1199,17 +1156,6 @@ class ReaderActivity : BaseActivity() {
|
|||||||
// SY <--
|
// SY <--
|
||||||
supportActionBar?.title = manga.title
|
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)
|
|
||||||
}
|
|
||||||
binding.aboveChapter.setTooltip(R.string.action_previous_chapter)
|
|
||||||
binding.belowChapter.setTooltip(R.string.action_next_chapter)
|
|
||||||
|
|
||||||
val loadingIndicatorContext = createReaderThemeContext()
|
val loadingIndicatorContext = createReaderThemeContext()
|
||||||
loadingIndicator = ReaderProgressIndicator(loadingIndicatorContext).apply {
|
loadingIndicator = ReaderProgressIndicator(loadingIndicatorContext).apply {
|
||||||
updateLayoutParams<FrameLayout.LayoutParams> {
|
updateLayoutParams<FrameLayout.LayoutParams> {
|
||||||
@ -1252,13 +1198,13 @@ class ReaderActivity : BaseActivity() {
|
|||||||
// SY -->
|
// SY -->
|
||||||
if (indexChapterToShift != null && indexPageToShift != null) {
|
if (indexChapterToShift != null && indexPageToShift != null) {
|
||||||
viewerChapters.currChapter.pages?.find { it.index == indexPageToShift && it.chapter.chapter.id == indexChapterToShift }?.let {
|
viewerChapters.currChapter.pages?.find { it.index == indexPageToShift && it.chapter.chapter.id == indexChapterToShift }?.let {
|
||||||
(viewer as? PagerViewer)?.updateShifting(it)
|
(viewModel.state.value.viewer as? PagerViewer)?.updateShifting(it)
|
||||||
}
|
}
|
||||||
indexChapterToShift = null
|
indexChapterToShift = null
|
||||||
indexPageToShift = null
|
indexPageToShift = null
|
||||||
} else if (lastShiftDoubleState != null) {
|
} else if (lastShiftDoubleState != null) {
|
||||||
val currentChapter = viewerChapters.currChapter
|
val currentChapter = viewerChapters.currChapter
|
||||||
(viewer as? PagerViewer)?.config?.shiftDoublePage = (
|
(viewModel.state.value.viewer as? PagerViewer)?.config?.shiftDoublePage = (
|
||||||
currentChapter.requestedPage +
|
currentChapter.requestedPage +
|
||||||
(
|
(
|
||||||
currentChapter.pages?.take(currentChapter.requestedPage)
|
currentChapter.pages?.take(currentChapter.requestedPage)
|
||||||
@ -1268,35 +1214,9 @@ class ReaderActivity : BaseActivity() {
|
|||||||
}
|
}
|
||||||
// SY <--
|
// SY <--
|
||||||
|
|
||||||
viewer?.setChapters(viewerChapters)
|
viewModel.state.value.viewer?.setChapters(viewerChapters)
|
||||||
binding.toolbar.subtitle = viewerChapters.currChapter.chapter.name
|
binding.toolbar.subtitle = viewerChapters.currChapter.chapter.name
|
||||||
|
|
||||||
val currentChapterPageCount = viewerChapters.currChapter.pages?.size ?: 1
|
|
||||||
binding.readerSeekbar.isInvisible = currentChapterPageCount == 1
|
|
||||||
binding.readerSeekbarVert.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
|
|
||||||
binding.aboveChapter.isVisible = false
|
|
||||||
binding.belowChapter.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
|
|
||||||
|
|
||||||
binding.aboveChapter.isEnabled = leftChapterObject != null
|
|
||||||
binding.aboveChapter.imageAlpha = if (leftChapterObject != null) ENABLED_BUTTON_IMAGE_ALPHA else DISABLED_BUTTON_IMAGE_ALPHA
|
|
||||||
|
|
||||||
binding.belowChapter.isEnabled = rightChapterObject != null
|
|
||||||
binding.belowChapter.imageAlpha = if (rightChapterObject != null) ENABLED_BUTTON_IMAGE_ALPHA else DISABLED_BUTTON_IMAGE_ALPHA
|
|
||||||
}
|
|
||||||
|
|
||||||
// Invalidate menu to show proper chapter bookmark state
|
// Invalidate menu to show proper chapter bookmark state
|
||||||
invalidateOptionsMenu()
|
invalidateOptionsMenu()
|
||||||
|
|
||||||
@ -1338,7 +1258,7 @@ class ReaderActivity : BaseActivity() {
|
|||||||
* page is not found.
|
* page is not found.
|
||||||
*/
|
*/
|
||||||
private fun moveToPageIndex(index: Int) {
|
private fun moveToPageIndex(index: Int) {
|
||||||
val viewer = viewer ?: return
|
val viewer = viewModel.state.value.viewer ?: return
|
||||||
val currentChapter = viewModel.getCurrentChapter() ?: return
|
val currentChapter = viewModel.getCurrentChapter() ?: return
|
||||||
val page = currentChapter.pages?.getOrNull(index) ?: return
|
val page = currentChapter.pages?.getOrNull(index) ?: return
|
||||||
viewer.moveToPage(page)
|
viewer.moveToPage(page)
|
||||||
@ -1374,38 +1294,13 @@ class ReaderActivity : BaseActivity() {
|
|||||||
fun onPageSelected(page: ReaderPage, hasExtraPage: Boolean = false) {
|
fun onPageSelected(page: ReaderPage, hasExtraPage: Boolean = false) {
|
||||||
// SY -->
|
// SY -->
|
||||||
val currentPage = if (hasExtraPage) {
|
val currentPage = if (hasExtraPage) {
|
||||||
val invertDoublePage = (viewer as? PagerViewer)?.config?.invertDoublePages ?: false
|
val invertDoublePage = (viewModel.state.value.viewer as? PagerViewer)?.config?.invertDoublePages ?: false
|
||||||
if (resources.isLTR xor invertDoublePage) "${page.number}-${page.number + 1}" else "${page.number + 1}-${page.number}"
|
if (resources.isLTR xor invertDoublePage) "${page.number}-${page.number + 1}" else "${page.number + 1}-${page.number}"
|
||||||
} else {
|
} else {
|
||||||
"${page.number}"
|
"${page.number}"
|
||||||
}
|
}
|
||||||
viewModel.onPageSelected(page, hasExtraPage, currentPage)
|
viewModel.onPageSelected(page, hasExtraPage, currentPage)
|
||||||
// SY <--
|
// SY <--
|
||||||
val pages = page.chapter.pages ?: return
|
|
||||||
|
|
||||||
// Set page numbers
|
|
||||||
if (viewer !is R2LPagerViewer) {
|
|
||||||
binding.leftPageText.text = currentPage
|
|
||||||
binding.rightPageText.text = "${pages.size}"
|
|
||||||
} else {
|
|
||||||
binding.rightPageText.text = currentPage
|
|
||||||
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()
|
|
||||||
|
|
||||||
// SY -->
|
|
||||||
binding.pageSliderVert.valueTo = max(pages.lastIndex.toFloat(), 1f)
|
|
||||||
binding.pageSliderVert.value = page.index.toFloat()
|
|
||||||
// SY <--
|
|
||||||
|
|
||||||
// SY -->
|
|
||||||
binding.abovePageText.text = currentPage
|
|
||||||
binding.belowPageText.text = "${pages.size}"
|
|
||||||
// SY <--
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1415,7 +1310,7 @@ class ReaderActivity : BaseActivity() {
|
|||||||
fun onPageLongTap(page: ReaderPage, extraPage: ReaderPage? = null) {
|
fun onPageLongTap(page: ReaderPage, extraPage: ReaderPage? = null) {
|
||||||
// SY -->
|
// SY -->
|
||||||
try {
|
try {
|
||||||
val viewer = viewer as? PagerViewer
|
val viewer = viewModel.state.value.viewer as? PagerViewer
|
||||||
ReaderPageSheet(
|
ReaderPageSheet(
|
||||||
this,
|
this,
|
||||||
page,
|
page,
|
||||||
@ -1566,7 +1461,7 @@ class ReaderActivity : BaseActivity() {
|
|||||||
* Updates viewer inset depending on fullscreen reader preferences.
|
* Updates viewer inset depending on fullscreen reader preferences.
|
||||||
*/
|
*/
|
||||||
fun updateViewerInset(fullscreen: Boolean) {
|
fun updateViewerInset(fullscreen: Boolean) {
|
||||||
viewer?.getView()?.applyInsetter {
|
viewModel.state.value.viewer?.getView()?.applyInsetter {
|
||||||
if (!fullscreen) {
|
if (!fullscreen) {
|
||||||
type(navigationBars = true, statusBars = true) {
|
type(navigationBars = true, statusBars = true) {
|
||||||
padding()
|
padding()
|
||||||
@ -1671,7 +1566,7 @@ class ReaderActivity : BaseActivity() {
|
|||||||
readerPreferences.dualPageSplitPaged().changes()
|
readerPreferences.dualPageSplitPaged().changes()
|
||||||
.drop(1)
|
.drop(1)
|
||||||
.onEach {
|
.onEach {
|
||||||
if (viewer !is PagerViewer) return@onEach
|
if (viewModel.state.value.viewer !is PagerViewer) return@onEach
|
||||||
updateBottomButtons()
|
updateBottomButtons()
|
||||||
reloadChapters(
|
reloadChapters(
|
||||||
!it && when (readerPreferences.pageLayout().get()) {
|
!it && when (readerPreferences.pageLayout().get()) {
|
||||||
|
@ -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
|
|
||||||
}
|
|
@ -39,6 +39,7 @@ import eu.kanade.tachiyomi.ui.reader.model.ViewerChapters
|
|||||||
import eu.kanade.tachiyomi.ui.reader.setting.OrientationType
|
import eu.kanade.tachiyomi.ui.reader.setting.OrientationType
|
||||||
import eu.kanade.tachiyomi.ui.reader.setting.ReaderPreferences
|
import eu.kanade.tachiyomi.ui.reader.setting.ReaderPreferences
|
||||||
import eu.kanade.tachiyomi.ui.reader.setting.ReadingModeType
|
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.chapter.removeDuplicates
|
||||||
import eu.kanade.tachiyomi.util.editCover
|
import eu.kanade.tachiyomi.util.editCover
|
||||||
import eu.kanade.tachiyomi.util.lang.byteSize
|
import eu.kanade.tachiyomi.util.lang.byteSize
|
||||||
@ -480,6 +481,14 @@ class ReaderViewModel(
|
|||||||
eventChannel.trySend(Event.ReloadViewerChapters)
|
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
|
* 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
|
* read, update tracking services, enqueue downloaded chapter deletion, and updating the active chapter if this
|
||||||
@ -498,8 +507,9 @@ class ReaderViewModel(
|
|||||||
// Save last page read and mark as read if needed
|
// Save last page read and mark as read if needed
|
||||||
mutableState.update {
|
mutableState.update {
|
||||||
it.copy(
|
it.copy(
|
||||||
|
currentPage = page.number,
|
||||||
// SY -->
|
// SY -->
|
||||||
currentPage = currentPage,
|
currentPageText = currentPage,
|
||||||
// SY <--
|
// SY <--
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -1108,12 +1118,21 @@ class ReaderViewModel(
|
|||||||
val manga: Manga? = null,
|
val manga: Manga? = null,
|
||||||
val viewerChapters: ViewerChapters? = null,
|
val viewerChapters: ViewerChapters? = null,
|
||||||
val isLoadingAdjacentChapter: Boolean = false,
|
val isLoadingAdjacentChapter: Boolean = false,
|
||||||
|
val currentPage: Int = -1,
|
||||||
|
/**
|
||||||
|
* Viewer used to display the pages (pager, webtoon, ...).
|
||||||
|
*/
|
||||||
|
val viewer: Viewer? = null,
|
||||||
|
|
||||||
// SY -->
|
// SY -->
|
||||||
val currentPage: String = "",
|
val currentPageText: String = "",
|
||||||
val meta: RaisedSearchMetadata? = null,
|
val meta: RaisedSearchMetadata? = null,
|
||||||
val mergedManga: Map<Long, Manga>? = null,
|
val mergedManga: Map<Long, Manga>? = null,
|
||||||
// SY <--
|
// SY <--
|
||||||
)
|
) {
|
||||||
|
val totalPages: Int
|
||||||
|
get() = viewerChapters?.currChapter?.pages?.size ?: -1
|
||||||
|
}
|
||||||
|
|
||||||
sealed class Event {
|
sealed class Event {
|
||||||
object ReloadViewerChapters : Event()
|
object ReloadViewerChapters : Event()
|
||||||
|
@ -34,7 +34,7 @@ class ReaderReadingModeSettings @JvmOverloads constructor(context: Context, attr
|
|||||||
|
|
||||||
initGeneralPreferences()
|
initGeneralPreferences()
|
||||||
|
|
||||||
when ((context as ReaderActivity).viewer) {
|
when ((context as ReaderActivity).viewModel.state.value.viewer) {
|
||||||
is PagerViewer -> initPagerPreferences()
|
is PagerViewer -> initPagerPreferences()
|
||||||
is WebtoonViewer -> initWebtoonPreferences()
|
is WebtoonViewer -> initWebtoonPreferences()
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@ import androidx.annotation.DrawableRes
|
|||||||
import androidx.annotation.StringRes
|
import androidx.annotation.StringRes
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
import eu.kanade.tachiyomi.ui.reader.ReaderActivity
|
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.L2RPagerViewer
|
||||||
import eu.kanade.tachiyomi.ui.reader.viewer.pager.R2LPagerViewer
|
import eu.kanade.tachiyomi.ui.reader.viewer.pager.R2LPagerViewer
|
||||||
import eu.kanade.tachiyomi.ui.reader.viewer.pager.VerticalPagerViewer
|
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 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)) {
|
return when (fromPreference(preference)) {
|
||||||
LEFT_TO_RIGHT -> L2RPagerViewer(activity)
|
LEFT_TO_RIGHT -> L2RPagerViewer(activity)
|
||||||
RIGHT_TO_LEFT -> R2LPagerViewer(activity)
|
RIGHT_TO_LEFT -> R2LPagerViewer(activity)
|
||||||
|
@ -9,7 +9,7 @@ import eu.kanade.tachiyomi.ui.reader.model.ViewerChapters
|
|||||||
/**
|
/**
|
||||||
* Interface for implementing a viewer.
|
* Interface for implementing a viewer.
|
||||||
*/
|
*/
|
||||||
interface BaseViewer {
|
interface Viewer {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the view this viewer uses.
|
* Returns the view this viewer uses.
|
@ -18,7 +18,7 @@ import eu.kanade.tachiyomi.ui.reader.model.InsertPage
|
|||||||
import eu.kanade.tachiyomi.ui.reader.model.ReaderItem
|
import eu.kanade.tachiyomi.ui.reader.model.ReaderItem
|
||||||
import eu.kanade.tachiyomi.ui.reader.model.ReaderPage
|
import eu.kanade.tachiyomi.ui.reader.model.ReaderPage
|
||||||
import eu.kanade.tachiyomi.ui.reader.model.ViewerChapters
|
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 eu.kanade.tachiyomi.ui.reader.viewer.ViewerNavigation.NavigationRegion
|
||||||
import kotlinx.coroutines.MainScope
|
import kotlinx.coroutines.MainScope
|
||||||
import kotlinx.coroutines.cancel
|
import kotlinx.coroutines.cancel
|
||||||
@ -27,10 +27,10 @@ import uy.kohesive.injekt.injectLazy
|
|||||||
import kotlin.math.min
|
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")
|
@Suppress("LeakingThis")
|
||||||
abstract class PagerViewer(val activity: ReaderActivity) : BaseViewer {
|
abstract class PagerViewer(val activity: ReaderActivity) : Viewer {
|
||||||
|
|
||||||
val downloadManager: DownloadManager by injectLazy()
|
val downloadManager: DownloadManager by injectLazy()
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@ import eu.kanade.tachiyomi.ui.reader.model.ReaderPage
|
|||||||
import eu.kanade.tachiyomi.ui.reader.model.StencilPage
|
import eu.kanade.tachiyomi.ui.reader.model.StencilPage
|
||||||
import eu.kanade.tachiyomi.ui.reader.model.ViewerChapters
|
import eu.kanade.tachiyomi.ui.reader.model.ViewerChapters
|
||||||
import eu.kanade.tachiyomi.ui.reader.setting.ReaderPreferences
|
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 eu.kanade.tachiyomi.ui.reader.viewer.ViewerNavigation.NavigationRegion
|
||||||
import kotlinx.coroutines.MainScope
|
import kotlinx.coroutines.MainScope
|
||||||
import kotlinx.coroutines.cancel
|
import kotlinx.coroutines.cancel
|
||||||
@ -32,9 +32,9 @@ import kotlin.math.min
|
|||||||
import kotlin.time.Duration
|
import kotlin.time.Duration
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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, private val tapByPage: Boolean = false) : BaseViewer {
|
class WebtoonViewer(val activity: ReaderActivity, val isContinuous: Boolean = true, private val tapByPage: Boolean = false) : Viewer {
|
||||||
|
|
||||||
val downloadManager: DownloadManager by injectLazy()
|
val downloadManager: DownloadManager by injectLazy()
|
||||||
|
|
||||||
|
@ -12,7 +12,6 @@ import android.graphics.drawable.Drawable
|
|||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.PowerManager
|
import android.os.PowerManager
|
||||||
import android.util.TypedValue
|
|
||||||
import androidx.annotation.AttrRes
|
import androidx.annotation.AttrRes
|
||||||
import androidx.annotation.ColorInt
|
import androidx.annotation.ColorInt
|
||||||
import androidx.appcompat.view.ContextThemeWrapper
|
import androidx.appcompat.view.ContextThemeWrapper
|
||||||
@ -89,19 +88,6 @@ fun Context.hasPermission(permission: String) = PermissionChecker.checkSelfPermi
|
|||||||
return color
|
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
|
val Context.powerManager: PowerManager
|
||||||
get() = getSystemService()!!
|
get() = getSystemService()!!
|
||||||
|
|
||||||
|
@ -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>
|
|
@ -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>
|
|
@ -195,104 +195,13 @@
|
|||||||
app:layout_constraintTop_toBottomOf="@id/above_guideline"
|
app:layout_constraintTop_toBottomOf="@id/above_guideline"
|
||||||
tools:ignore="NotSibling">
|
tools:ignore="NotSibling">
|
||||||
|
|
||||||
<LinearLayout
|
<androidx.compose.ui.platform.ComposeView
|
||||||
android:id="@+id/reader_nav_vert"
|
android:id="@+id/reader_nav_vert"
|
||||||
android:layout_width="48dp"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:layout_alignParentEnd="true"
|
android:layout_alignParentEnd="true"
|
||||||
android:layout_centerVertical="true"
|
android:layout_centerVertical="true"
|
||||||
android:layout_marginStart="8dp"
|
android:gravity="center"/>
|
||||||
android:layout_marginEnd="8dp"
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:gravity="center">
|
|
||||||
|
|
||||||
<ImageButton
|
|
||||||
android:id="@+id/above_chapter"
|
|
||||||
android:layout_width="48dp"
|
|
||||||
android:layout_height="48dp"
|
|
||||||
android:layout_gravity="center"
|
|
||||||
android:layout_marginTop="80dp"
|
|
||||||
android:layout_marginBottom="8dp"
|
|
||||||
android:contentDescription="@string/action_previous_chapter"
|
|
||||||
android:padding="@dimen/screen_edge_margin"
|
|
||||||
android:rotation="90"
|
|
||||||
app:srcCompat="@drawable/ic_skip_previous_24dp"
|
|
||||||
app:tint="?attr/colorOnSurface" />
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:id="@+id/reader_seekbar_vert"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:orientation="vertical">
|
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/above_page_text"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="12dp"
|
|
||||||
android:gravity="center"
|
|
||||||
android:textColor="?attr/colorOnSurface"
|
|
||||||
android:textSize="15sp"
|
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
tools:text="1" />
|
|
||||||
|
|
||||||
<FrameLayout
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:layout_marginTop="27dp"
|
|
||||||
android:layout_marginBottom="27dp"
|
|
||||||
app:layout_constraintDimensionRatio="1:1"
|
|
||||||
app:layout_constraintBottom_toTopOf="@id/below_page_text"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toBottomOf="@id/above_page_text" >
|
|
||||||
|
|
||||||
<eu.kanade.tachiyomi.ui.reader.ReaderSlider
|
|
||||||
android:id="@+id/page_slider_vert"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:rotation="90"
|
|
||||||
android:layout_gravity="center"
|
|
||||||
app:layout_constraintDimensionRatio="1:1" />
|
|
||||||
|
|
||||||
</FrameLayout>
|
|
||||||
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/below_page_text"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginBottom="12dp"
|
|
||||||
android:gravity="center"
|
|
||||||
android:textColor="?attr/colorOnSurface"
|
|
||||||
android:textSize="15sp"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
tools:text="15" />
|
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<ImageButton
|
|
||||||
android:id="@+id/below_chapter"
|
|
||||||
android:layout_width="48dp"
|
|
||||||
android:layout_height="48dp"
|
|
||||||
android:layout_gravity="center"
|
|
||||||
android:layout_marginTop="8dp"
|
|
||||||
android:layout_marginBottom="80dp"
|
|
||||||
android:contentDescription="@string/action_next_chapter"
|
|
||||||
android:padding="@dimen/screen_edge_margin"
|
|
||||||
android:rotation="90"
|
|
||||||
app:srcCompat="@drawable/ic_skip_next_24dp"
|
|
||||||
app:tint="?attr/colorOnSurface" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
|
||||||
@ -314,82 +223,12 @@
|
|||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent">
|
app:layout_constraintStart_toStartOf="parent">
|
||||||
|
|
||||||
<LinearLayout
|
<androidx.compose.ui.platform.ComposeView
|
||||||
android:id="@+id/reader_nav_horz"
|
android:id="@+id/reader_nav_horz"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="8dp"
|
|
||||||
android:layout_marginEnd="8dp"
|
|
||||||
android:layout_marginBottom="16dp"
|
android:layout_marginBottom="16dp"
|
||||||
android:layoutDirection="ltr"
|
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>
|
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
android:id="@+id/toolbar_bottom"
|
android:id="@+id/toolbar_bottom"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user