From a330258f6a26a57ceca9a318270b5db3b4653e24 Mon Sep 17 00:00:00 2001 From: AntsyLich <59261191+AntsyLich@users.noreply.github.com> Date: Thu, 4 Jun 2026 01:54:52 +0600 Subject: [PATCH] Add vertical chapter navigator for long strip mode (#3377) --- CHANGELOG.md | 1 + .../settings/screen/SettingsReaderScreen.kt | 15 +- .../reader/appbars/ReaderAppBars.kt | 77 +++++--- .../reader/components/ChapterNavigator.kt | 183 ++++++++++++++++-- .../reader/settings/GeneralSettingsPage.kt | 13 ++ .../tachiyomi/ui/reader/ReaderActivity.kt | 19 +- .../ui/reader/setting/ReaderPreferences.kt | 10 + .../moko-resources/base/strings.xml | 2 + 8 files changed, 273 insertions(+), 47 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 513b4fb42..18223500b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ The format is a modified version of [Keep a Changelog](https://keepachangelog.co ## [Unreleased] ### Added - Add support for `tachiyomix` extension index format ([@AntsyLich](https://github.com/AntsyLich)) ([#3349](https://github.com/mihonapp/mihon/pull/3349)) +- Add vertical chapter navigator for long strip mode ([@AntsyLich](https://github.com/AntsyLich)) ([#3377](https://github.com/mihonapp/mihon/pull/3377)) ### Changed - Change all reference of extension repo to extension store ([@AntsyLich](https://github.com/AntsyLich)) ([#3349](https://github.com/mihonapp/mihon/pull/3349)) diff --git a/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsReaderScreen.kt b/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsReaderScreen.kt index eea437206..eb34f1175 100644 --- a/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsReaderScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsReaderScreen.kt @@ -74,8 +74,8 @@ object SettingsReaderScreen : SearchableSettings { @Composable private fun getDisplayGroup(readerPreferences: ReaderPreferences): Preference.PreferenceGroup { - val fullscreenPref = readerPreferences.fullscreen - val fullscreen by fullscreenPref.collectAsState() + val fullscreen by readerPreferences.fullscreen.collectAsState() + val verticalNavigatorForLongStrip by readerPreferences.verticalNavigatorForLongStrip.collectAsState() return Preference.PreferenceGroup( title = stringResource(MR.strings.pref_category_display), preferenceItems = persistentListOf( @@ -97,7 +97,7 @@ object SettingsReaderScreen : SearchableSettings { title = stringResource(MR.strings.pref_reader_theme), ), Preference.PreferenceItem.SwitchPreference( - preference = fullscreenPref, + preference = readerPreferences.fullscreen, title = stringResource(MR.strings.pref_fullscreen), ), Preference.PreferenceItem.SwitchPreference( @@ -113,6 +113,15 @@ object SettingsReaderScreen : SearchableSettings { preference = readerPreferences.showPageNumber, title = stringResource(MR.strings.pref_show_page_number), ), + Preference.PreferenceItem.SwitchPreference( + preference = readerPreferences.verticalNavigatorForLongStrip, + title = stringResource(MR.strings.pref_webtoon_vertical_navigator), + ), + Preference.PreferenceItem.SwitchPreference( + preference = readerPreferences.verticalNavigatorOnLeft, + title = stringResource(MR.strings.pref_webtoon_vertical_navigator_on_left), + enabled = verticalNavigatorForLongStrip, + ), ), ) } diff --git a/app/src/main/java/eu/kanade/presentation/reader/appbars/ReaderAppBars.kt b/app/src/main/java/eu/kanade/presentation/reader/appbars/ReaderAppBars.kt index fe2b2de0c..dae9bfd9a 100644 --- a/app/src/main/java/eu/kanade/presentation/reader/appbars/ReaderAppBars.kt +++ b/app/src/main/java/eu/kanade/presentation/reader/appbars/ReaderAppBars.kt @@ -4,13 +4,16 @@ import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.core.tween import androidx.compose.animation.fadeIn import androidx.compose.animation.fadeOut +import androidx.compose.animation.slideInHorizontally import androidx.compose.animation.slideInVertically +import androidx.compose.animation.slideOutHorizontally import androidx.compose.animation.slideOutVertically import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.WindowInsets import androidx.compose.foundation.layout.fillMaxHeight @@ -21,14 +24,16 @@ import androidx.compose.foundation.layout.windowInsetsPadding import androidx.compose.material3.MaterialTheme import androidx.compose.material3.surfaceColorAtElevation import androidx.compose.runtime.Composable +import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalLayoutDirection import androidx.compose.ui.unit.IntOffset +import androidx.compose.ui.unit.LayoutDirection import androidx.compose.ui.unit.dp import eu.kanade.presentation.reader.components.ChapterNavigator +import eu.kanade.presentation.reader.components.ChapterNavigatorType import eu.kanade.tachiyomi.ui.reader.setting.ReaderOrientation import eu.kanade.tachiyomi.ui.reader.setting.ReadingMode -import eu.kanade.tachiyomi.ui.reader.viewer.Viewer -import eu.kanade.tachiyomi.ui.reader.viewer.pager.R2LPagerViewer import tachiyomi.presentation.core.components.material.padding private val readerBarsSlideAnimationSpec = tween(200) @@ -48,7 +53,7 @@ fun ReaderAppBars( onOpenInBrowser: (() -> Unit)?, onShare: (() -> Unit)?, - viewer: Viewer?, + chapterNavigatorType: ChapterNavigatorType, onNextChapter: () -> Unit, enabledNext: Boolean, onPreviousChapter: () -> Unit, @@ -65,7 +70,6 @@ fun ReaderAppBars( onClickCropBorder: () -> Unit, onClickSettings: () -> Unit, ) { - val isRtl = viewer is R2LPagerViewer val backgroundColor = MaterialTheme.colorScheme .surfaceColorAtElevation(3.dp) .copy(alpha = if (isSystemInDarkTheme()) 0.9f else 0.95f) @@ -73,10 +77,8 @@ fun ReaderAppBars( Column(modifier = Modifier.fillMaxHeight()) { AnimatedVisibility( visible = visible, - enter = slideInVertically(initialOffsetY = { -it }, animationSpec = readerBarsSlideAnimationSpec) + - fadeIn(animationSpec = readerBarsFadeAnimationSpec), - exit = slideOutVertically(targetOffsetY = { -it }, animationSpec = readerBarsSlideAnimationSpec) + - fadeOut(animationSpec = readerBarsFadeAnimationSpec), + enter = slideInVertically(readerBarsSlideAnimationSpec) { -it } + fadeIn(readerBarsFadeAnimationSpec), + exit = slideOutVertically(readerBarsSlideAnimationSpec) { -it } + fadeOut(readerBarsFadeAnimationSpec), ) { ReaderTopBar( modifier = Modifier @@ -93,26 +95,55 @@ fun ReaderAppBars( ) } - Spacer(modifier = Modifier.weight(1f)) + if (!chapterNavigatorType.isHorizontal()) { + val sliderOnLeft = chapterNavigatorType == ChapterNavigatorType.VERTICAL_LEFT + CompositionLocalProvider( + LocalLayoutDirection provides if (sliderOnLeft) LayoutDirection.Ltr else LayoutDirection.Rtl, + ) { + Row(modifier = Modifier.weight(1f)) { + AnimatedVisibility( + visible = visible, + enter = slideInHorizontally(readerBarsSlideAnimationSpec) { if (sliderOnLeft) -it else it } + + fadeIn(readerBarsFadeAnimationSpec), + exit = slideOutHorizontally(readerBarsSlideAnimationSpec) { if (sliderOnLeft) -it else it } + + fadeOut(readerBarsFadeAnimationSpec), + ) { + ChapterNavigator( + type = chapterNavigatorType, + onNextChapter = onNextChapter, + enabledNext = enabledNext, + onPreviousChapter = onPreviousChapter, + enabledPrevious = enabledPrevious, + currentPage = currentPage, + totalPages = totalPages, + onPageIndexChange = onPageIndexChange, + ) + } + Spacer(modifier = Modifier.weight(1f)) + } + } + } else { + Spacer(Modifier.weight(1f)) + } AnimatedVisibility( visible = visible, - enter = slideInVertically(initialOffsetY = { it }, animationSpec = readerBarsSlideAnimationSpec) + - fadeIn(animationSpec = readerBarsFadeAnimationSpec), - exit = slideOutVertically(targetOffsetY = { it }, animationSpec = readerBarsSlideAnimationSpec) + - fadeOut(animationSpec = readerBarsFadeAnimationSpec), + enter = slideInVertically(readerBarsSlideAnimationSpec) { it } + fadeIn(readerBarsFadeAnimationSpec), + exit = slideOutVertically(readerBarsSlideAnimationSpec) { it } + fadeOut(readerBarsFadeAnimationSpec), ) { Column(verticalArrangement = Arrangement.spacedBy(MaterialTheme.padding.small)) { - ChapterNavigator( - isRtl = isRtl, - onNextChapter = onNextChapter, - enabledNext = enabledNext, - onPreviousChapter = onPreviousChapter, - enabledPrevious = enabledPrevious, - currentPage = currentPage, - totalPages = totalPages, - onPageIndexChange = onPageIndexChange, - ) + if (chapterNavigatorType.isHorizontal()) { + ChapterNavigator( + type = chapterNavigatorType, + onNextChapter = onNextChapter, + enabledNext = enabledNext, + onPreviousChapter = onPreviousChapter, + enabledPrevious = enabledPrevious, + currentPage = currentPage, + totalPages = totalPages, + onPageIndexChange = onPageIndexChange, + ) + } ReaderBottomBar( modifier = Modifier .fillMaxWidth() diff --git a/app/src/main/java/eu/kanade/presentation/reader/components/ChapterNavigator.kt b/app/src/main/java/eu/kanade/presentation/reader/components/ChapterNavigator.kt index d39391b74..e21a73905 100644 --- a/app/src/main/java/eu/kanade/presentation/reader/components/ChapterNavigator.kt +++ b/app/src/main/java/eu/kanade/presentation/reader/components/ChapterNavigator.kt @@ -5,8 +5,10 @@ import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.interaction.collectIsDraggedAsState import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.foundation.layout.Box +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 @@ -15,9 +17,14 @@ 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.IconButtonColors import androidx.compose.material3.IconButtonDefaults import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Slider +import androidx.compose.material3.SliderState import androidx.compose.material3.Text +import androidx.compose.material3.VerticalSlider +import androidx.compose.material3.rememberSliderState import androidx.compose.material3.surfaceColorAtElevation import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider @@ -29,22 +36,34 @@ import androidx.compose.runtime.setValue 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.Color import androidx.compose.ui.hapticfeedback.HapticFeedbackType import androidx.compose.ui.platform.LocalHapticFeedback import androidx.compose.ui.platform.LocalLayoutDirection import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.LayoutDirection import androidx.compose.ui.unit.dp import eu.kanade.presentation.theme.TachiyomiPreviewTheme import eu.kanade.presentation.util.isTabletUi import tachiyomi.i18n.MR -import tachiyomi.presentation.core.components.material.Slider import tachiyomi.presentation.core.i18n.stringResource +import kotlin.math.roundToInt + +enum class ChapterNavigatorType { + HORIZONTAL_LTR, + HORIZONTAL_RTL, + VERTICAL_LEFT, + VERTICAL_RIGHT, + ; + + fun isHorizontal() = this in setOf(HORIZONTAL_LTR, HORIZONTAL_RTL) +} @Composable fun ChapterNavigator( - isRtl: Boolean, + type: ChapterNavigatorType, onNextChapter: () -> Unit, enabledNext: Boolean, onPreviousChapter: () -> Unit, @@ -53,11 +72,27 @@ fun ChapterNavigator( totalPages: Int, onPageIndexChange: (Int) -> Unit, ) { - val isTabletUi = isTabletUi() - val horizontalPadding = if (isTabletUi) 24.dp else 8.dp - val layoutDirection = if (isRtl) LayoutDirection.Rtl else LayoutDirection.Ltr val haptic = LocalHapticFeedback.current + val state = rememberSliderState( + value = currentPage.toFloat(), + steps = totalPages - 2, + valueRange = 1f..totalPages.toFloat(), + ) + state.value = currentPage.toFloat() + state.onValueChange = { onPageIndexChange(it.roundToInt() - 1) } + + val interactionSource = remember { MutableInteractionSource() } + val sliderDragged by interactionSource.collectIsDraggedAsState() + LaunchedEffect(currentPage) { + if (sliderDragged) { + haptic.performHapticFeedback(HapticFeedbackType.TextHandleMove) + } + } + + val isTabletUi = isTabletUi() + val mainAxisPadding = if (isTabletUi) 24.dp else 8.dp + // Match with toolbar background color set in ReaderActivity val backgroundColor = MaterialTheme.colorScheme .surfaceColorAtElevation(3.dp) @@ -67,12 +102,61 @@ fun ChapterNavigator( disabledContainerColor = backgroundColor, ) + if (type.isHorizontal()) { + ChapterNavigator( + isRtl = type == ChapterNavigatorType.HORIZONTAL_RTL, + state = state, + onNextChapter = onNextChapter, + enabledNext = enabledNext, + onPreviousChapter = onPreviousChapter, + enabledPrevious = enabledPrevious, + currentPage = currentPage, + totalPages = totalPages, + interactionSource = interactionSource, + mainAxisPadding = mainAxisPadding, + backgroundColor = backgroundColor, + buttonColor = buttonColor, + ) + } else { + VerticalChapterNavigator( + state = state, + onNextChapter = onNextChapter, + enabledNext = enabledNext, + onPreviousChapter = onPreviousChapter, + enabledPrevious = enabledPrevious, + currentPage = currentPage, + totalPages = totalPages, + interactionSource = interactionSource, + mainAxisPadding = mainAxisPadding, + backgroundColor = backgroundColor, + buttonColor = buttonColor, + ) + } +} + +@Composable +fun ChapterNavigator( + isRtl: Boolean, + state: SliderState, + onNextChapter: () -> Unit, + enabledNext: Boolean, + onPreviousChapter: () -> Unit, + enabledPrevious: Boolean, + currentPage: Int, + totalPages: Int, + interactionSource: MutableInteractionSource, + mainAxisPadding: Dp, + backgroundColor: Color, + buttonColor: IconButtonColors, +) { + val layoutDirection = if (isRtl) LayoutDirection.Rtl else LayoutDirection.Ltr + // 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), + .padding(horizontal = mainAxisPadding), verticalAlignment = Alignment.CenterVertically, ) { FilledIconButton( @@ -104,23 +188,11 @@ fun ChapterNavigator( Text(text = totalPages.toString(), color = Color.Transparent) } - val interactionSource = remember { MutableInteractionSource() } - val sliderDragged by interactionSource.collectIsDraggedAsState() - LaunchedEffect(currentPage) { - if (sliderDragged) { - haptic.performHapticFeedback(HapticFeedbackType.TextHandleMove) - } - } Slider( + state = state, modifier = Modifier .weight(1f) .padding(horizontal = 8.dp), - value = currentPage, - valueRange = 1..totalPages, - onValueChange = f@{ - if (it == currentPage) return@f - onPageIndexChange(it - 1) - }, interactionSource = interactionSource, ) @@ -147,13 +219,84 @@ fun ChapterNavigator( } } +@Composable +fun VerticalChapterNavigator( + state: SliderState, + onNextChapter: () -> Unit, + enabledNext: Boolean, + onPreviousChapter: () -> Unit, + enabledPrevious: Boolean, + currentPage: Int, + totalPages: Int, + interactionSource: MutableInteractionSource, + mainAxisPadding: Dp, + backgroundColor: Color, + buttonColor: IconButtonColors, +) { + Column( + modifier = Modifier + .fillMaxHeight() + .padding(vertical = mainAxisPadding), + horizontalAlignment = Alignment.CenterHorizontally, + ) { + FilledIconButton( + enabled = enabledPrevious, + onClick = onPreviousChapter, + colors = buttonColor, + ) { + Icon( + imageVector = Icons.Outlined.SkipPrevious, + contentDescription = stringResource(MR.strings.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, + ) { + Text(text = currentPage.toString()) + + VerticalSlider( + state = state, + modifier = Modifier + .weight(1f) + .padding(vertical = 8.dp), + interactionSource = interactionSource, + ) + + Text(text = totalPages.toString()) + } + } else { + Spacer(Modifier.weight(1f)) + } + + FilledIconButton( + enabled = enabledNext, + onClick = onNextChapter, + colors = buttonColor, + ) { + Icon( + imageVector = Icons.Outlined.SkipNext, + contentDescription = stringResource(MR.strings.action_next_chapter), + modifier = Modifier.rotate(90f), + ) + } + } +} + @Preview @Composable private fun ChapterNavigatorPreview() { var currentPage by remember { mutableIntStateOf(1) } TachiyomiPreviewTheme { ChapterNavigator( - isRtl = false, + type = ChapterNavigatorType.VERTICAL_RIGHT, onNextChapter = {}, enabledNext = true, onPreviousChapter = {}, diff --git a/app/src/main/java/eu/kanade/presentation/reader/settings/GeneralSettingsPage.kt b/app/src/main/java/eu/kanade/presentation/reader/settings/GeneralSettingsPage.kt index 196a77d5c..1e1ad2b25 100644 --- a/app/src/main/java/eu/kanade/presentation/reader/settings/GeneralSettingsPage.kt +++ b/app/src/main/java/eu/kanade/presentation/reader/settings/GeneralSettingsPage.kt @@ -61,6 +61,19 @@ internal fun ColumnScope.GeneralPage(screenModel: ReaderSettingsScreenModel) { pref = screenModel.preferences.showPageNumber, ) + val verticalNavigatorForLongStrip by screenModel.preferences.verticalNavigatorForLongStrip.collectAsState() + CheckboxItem( + label = stringResource(MR.strings.pref_webtoon_vertical_navigator), + pref = screenModel.preferences.verticalNavigatorForLongStrip, + ) + + if (verticalNavigatorForLongStrip) { + CheckboxItem( + label = stringResource(MR.strings.pref_webtoon_vertical_navigator_on_left), + pref = screenModel.preferences.verticalNavigatorOnLeft, + ) + } + CheckboxItem( label = stringResource(MR.strings.pref_fullscreen), pref = screenModel.preferences.fullscreen, diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderActivity.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderActivity.kt index 830c6ccc2..f916208e1 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderActivity.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderActivity.kt @@ -56,6 +56,7 @@ import eu.kanade.presentation.reader.ReaderPageActionsDialog import eu.kanade.presentation.reader.ReaderPageIndicator import eu.kanade.presentation.reader.ReadingModeSelectDialog import eu.kanade.presentation.reader.appbars.ReaderAppBars +import eu.kanade.presentation.reader.components.ChapterNavigatorType import eu.kanade.presentation.reader.settings.ReaderSettingsDialog import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.coil.TachiyomiImageDecoder @@ -76,6 +77,7 @@ import eu.kanade.tachiyomi.ui.reader.setting.ReaderPreferences import eu.kanade.tachiyomi.ui.reader.setting.ReaderSettingsScreenModel import eu.kanade.tachiyomi.ui.reader.setting.ReadingMode 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.system.isNightMode import eu.kanade.tachiyomi.util.system.openInBrowser @@ -458,6 +460,9 @@ class ReaderActivity : BaseActivity() { val isPagerType = ReadingMode.isPagerType(viewModel.getMangaReadingMode()) val cropEnabled = if (isPagerType) cropBorderPaged else cropBorderWebtoon + val verticalNavigatorForLongStrip by readerPreferences.verticalNavigatorForLongStrip.collectAsState() + val verticalNavigatorOnLeft by readerPreferences.verticalNavigatorOnLeft.collectAsState() + ReaderAppBars( visible = state.menuVisible, @@ -471,7 +476,19 @@ class ReaderActivity : BaseActivity() { onOpenInBrowser = ::openChapterInBrowser.takeIf { isHttpSource }, onShare = ::shareChapter.takeIf { isHttpSource }, - viewer = state.viewer, + chapterNavigatorType = if (isPagerType || !verticalNavigatorForLongStrip) { + if (state.viewer is R2LPagerViewer) { + ChapterNavigatorType.HORIZONTAL_RTL + } else { + ChapterNavigatorType.HORIZONTAL_LTR + } + } else { + if (verticalNavigatorOnLeft) { + ChapterNavigatorType.VERTICAL_LEFT + } else { + ChapterNavigatorType.VERTICAL_RIGHT + } + }, onNextChapter = ::loadNextChapter, enabledNext = state.viewerChapters?.nextChapter != null, onPreviousChapter = ::loadPreviousChapter, diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/setting/ReaderPreferences.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/setting/ReaderPreferences.kt index f4854a219..6254d62d3 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/setting/ReaderPreferences.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/setting/ReaderPreferences.kt @@ -28,6 +28,16 @@ class ReaderPreferences( val showPageNumber: Preference = preferenceStore.getBoolean("pref_show_page_number_key", true) + val verticalNavigatorForLongStrip: Preference = preferenceStore.getBoolean( + "pref_webtoon_vertical_navigator", + true, + ) + + val verticalNavigatorOnLeft: Preference = preferenceStore.getBoolean( + "pref_webtoon_vertical_navigator_on_left", + false, + ) + val showReadingMode: Preference = preferenceStore.getBoolean("pref_show_reading_mode", true) val fullscreen: Preference = preferenceStore.getBoolean("fullscreen", true) diff --git a/i18n/src/commonMain/moko-resources/base/strings.xml b/i18n/src/commonMain/moko-resources/base/strings.xml index f624eac2e..cf2d5ad1e 100644 --- a/i18n/src/commonMain/moko-resources/base/strings.xml +++ b/i18n/src/commonMain/moko-resources/base/strings.xml @@ -400,6 +400,8 @@ White and Black Double tap animation speed Show page number + Use vertical navigator for long strip reading + Place vertical navigator on the left side Show reading mode Briefly show current mode when reader is opened Custom hardware bitmap threshold