From 19a62fc046c33aa2d3cf2e35199bbe02ca5d0c0a Mon Sep 17 00:00:00 2001 From: sdaqo Date: Sun, 12 Jan 2025 04:38:05 +0100 Subject: [PATCH] Add option to enable incognito mode per extension (mihonapp/mihon#157) * add per Extension Incognito Mode * migrate incognito sources when extension is updated * remove incognito sources when extension is uninstalled * remove not used variable * address change requests address change requests * Rebase and cleanup code --------- Co-authored-by: AntsyLich <59261191+AntsyLich@users.noreply.github.com> (cherry picked from commit c283abefb03f79ce6652492db71cde410f828f78) --- CHANGELOG.md | 1 + .../java/eu/kanade/domain/DomainModule.kt | 4 ++ .../source/interactor/GetIncognitoState.kt | 35 ++++++++++++++++ .../source/interactor/ToggleIncognito.kt | 14 +++++++ .../source/service/SourcePreferences.kt | 2 + .../browse/ExtensionDetailsScreen.kt | 42 +++++++++++++++---- .../tachiyomi/extension/ExtensionManager.kt | 22 +++++++--- .../details/ExtensionDetailsScreen.kt | 1 + .../details/ExtensionDetailsScreenModel.kt | 21 ++++++++++ .../source/browse/BrowseSourceScreen.kt | 2 +- .../source/browse/BrowseSourceScreenModel.kt | 6 +-- .../kanade/tachiyomi/ui/main/MainActivity.kt | 10 ++++- .../tachiyomi/ui/reader/ReaderViewModel.kt | 5 ++- .../moko-resources/base/strings.xml | 1 + 14 files changed, 146 insertions(+), 20 deletions(-) create mode 100644 app/src/main/java/eu/kanade/domain/source/interactor/GetIncognitoState.kt create mode 100644 app/src/main/java/eu/kanade/domain/source/interactor/ToggleIncognito.kt diff --git a/CHANGELOG.md b/CHANGELOG.md index c5775ab80a..5abed88c69 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 option to always decode long strip images with SSIV +- Added option to enable incognito per extension ([@sdaqo](https://github.com/sdaqo), [@AntsyLich](https://github.com/AntsyLich)) ([#157](https://github.com/mihonapp/mihon/pull/157)) ## [v0.17.1] - 2024-12-06 ### Changed diff --git a/app/src/main/java/eu/kanade/domain/DomainModule.kt b/app/src/main/java/eu/kanade/domain/DomainModule.kt index d4165fcdfd..4d75e18fd4 100644 --- a/app/src/main/java/eu/kanade/domain/DomainModule.kt +++ b/app/src/main/java/eu/kanade/domain/DomainModule.kt @@ -13,9 +13,11 @@ import eu.kanade.domain.manga.interactor.SetExcludedScanlators import eu.kanade.domain.manga.interactor.SetMangaViewerFlags import eu.kanade.domain.manga.interactor.UpdateManga import eu.kanade.domain.source.interactor.GetEnabledSources +import eu.kanade.domain.source.interactor.GetIncognitoState import eu.kanade.domain.source.interactor.GetLanguagesWithSources import eu.kanade.domain.source.interactor.GetSourcesWithFavoriteCount import eu.kanade.domain.source.interactor.SetMigrateSorting +import eu.kanade.domain.source.interactor.ToggleIncognito import eu.kanade.domain.source.interactor.ToggleLanguage import eu.kanade.domain.source.interactor.ToggleSource import eu.kanade.domain.source.interactor.ToggleSourcePin @@ -195,5 +197,7 @@ class DomainModule : InjektModule { addFactory { DeleteExtensionRepo(get()) } addFactory { ReplaceExtensionRepo(get()) } addFactory { UpdateExtensionRepo(get(), get()) } + addFactory { ToggleIncognito(get()) } + addFactory { GetIncognitoState(get(), get(), get()) } } } diff --git a/app/src/main/java/eu/kanade/domain/source/interactor/GetIncognitoState.kt b/app/src/main/java/eu/kanade/domain/source/interactor/GetIncognitoState.kt new file mode 100644 index 0000000000..41ab65f30c --- /dev/null +++ b/app/src/main/java/eu/kanade/domain/source/interactor/GetIncognitoState.kt @@ -0,0 +1,35 @@ +package eu.kanade.domain.source.interactor + +import eu.kanade.domain.base.BasePreferences +import eu.kanade.domain.source.service.SourcePreferences +import eu.kanade.tachiyomi.extension.ExtensionManager +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.distinctUntilChanged + +class GetIncognitoState( + private val basePreferences: BasePreferences, + private val sourcePreferences: SourcePreferences, + private val extensionManager: ExtensionManager, +) { + fun await(sourceId: Long?): Boolean { + if (basePreferences.incognitoMode().get()) return true + if (sourceId == null) return false + val extensionPackage = extensionManager.getExtensionPackage(sourceId) ?: return false + + return extensionPackage in sourcePreferences.incognitoExtensions().get() + } + + fun subscribe(sourceId: Long?): Flow { + if (sourceId == null) return basePreferences.incognitoMode().changes() + + return combine( + basePreferences.incognitoMode().changes(), + sourcePreferences.incognitoExtensions().changes(), + extensionManager.getExtensionPackageAsFlow(sourceId), + ) { incognito, incognitoExtensions, extensionPackage -> + incognito || (extensionPackage in incognitoExtensions) + } + .distinctUntilChanged() + } +} diff --git a/app/src/main/java/eu/kanade/domain/source/interactor/ToggleIncognito.kt b/app/src/main/java/eu/kanade/domain/source/interactor/ToggleIncognito.kt new file mode 100644 index 0000000000..ccd13bf6ad --- /dev/null +++ b/app/src/main/java/eu/kanade/domain/source/interactor/ToggleIncognito.kt @@ -0,0 +1,14 @@ +package eu.kanade.domain.source.interactor + +import eu.kanade.domain.source.service.SourcePreferences +import tachiyomi.core.common.preference.getAndSet + +class ToggleIncognito( + private val preferences: SourcePreferences, +) { + fun await(extensions: String, enable: Boolean) { + preferences.incognitoExtensions().getAndSet { + if (enable) it.plus(extensions) else it.minus(extensions) + } + } +} diff --git a/app/src/main/java/eu/kanade/domain/source/service/SourcePreferences.kt b/app/src/main/java/eu/kanade/domain/source/service/SourcePreferences.kt index fdc5e085a0..6754a77a74 100644 --- a/app/src/main/java/eu/kanade/domain/source/service/SourcePreferences.kt +++ b/app/src/main/java/eu/kanade/domain/source/service/SourcePreferences.kt @@ -23,6 +23,8 @@ class SourcePreferences( fun disabledSources() = preferenceStore.getStringSet("hidden_catalogues", emptySet()) + fun incognitoExtensions() = preferenceStore.getStringSet("incognito_extensions", emptySet()) + fun pinnedSources() = preferenceStore.getStringSet("pinned_catalogues", emptySet()) fun lastUsedSource() = preferenceStore.getLong( diff --git a/app/src/main/java/eu/kanade/presentation/browse/ExtensionDetailsScreen.kt b/app/src/main/java/eu/kanade/presentation/browse/ExtensionDetailsScreen.kt index 4a40a75c8d..e257834e8a 100644 --- a/app/src/main/java/eu/kanade/presentation/browse/ExtensionDetailsScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/browse/ExtensionDetailsScreen.kt @@ -36,8 +36,10 @@ import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalUriHandler +import androidx.compose.ui.res.vectorResource import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextAlign @@ -49,6 +51,7 @@ import eu.kanade.presentation.components.AppBarActions import eu.kanade.presentation.components.WarningBanner import eu.kanade.presentation.more.settings.widget.TextPreferenceWidget import eu.kanade.presentation.more.settings.widget.TrailingWidgetBuffer +import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.extension.model.Extension import eu.kanade.tachiyomi.source.ConfigurableSource import eu.kanade.tachiyomi.ui.browse.extension.details.ExtensionDetailsScreenModel @@ -77,6 +80,7 @@ fun ExtensionDetailsScreen( onClickClearCookies: () -> Unit, onClickUninstall: () -> Unit, onClickSource: (sourceId: Long) -> Unit, + onClickIncognito: (Boolean) -> Unit, ) { val uriHandler = LocalUriHandler.current val url = remember(state.extension) { @@ -154,9 +158,11 @@ fun ExtensionDetailsScreen( contentPadding = paddingValues, extension = state.extension, sources = state.sources, + incognitoMode = state.isIncognito, onClickSourcePreferences = onClickSourcePreferences, onClickUninstall = onClickUninstall, onClickSource = onClickSource, + onClickIncognito = onClickIncognito, ) } } @@ -166,9 +172,11 @@ private fun ExtensionDetails( contentPadding: PaddingValues, extension: Extension.Installed, sources: ImmutableList, + incognitoMode: Boolean, onClickSourcePreferences: (sourceId: Long) -> Unit, onClickUninstall: () -> Unit, onClickSource: (sourceId: Long) -> Unit, + onClickIncognito: (Boolean) -> Unit, ) { val context = LocalContext.current var showNsfwWarning by remember { mutableStateOf(false) } @@ -192,6 +200,7 @@ private fun ExtensionDetails( item { DetailsHeader( extension = extension, + extIncognitoMode = incognitoMode, onClickUninstall = onClickUninstall, onClickAppInfo = { Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS).apply { @@ -203,6 +212,7 @@ private fun ExtensionDetails( onClickAgeRating = { showNsfwWarning = true }, + onExtIncognitoChange = onClickIncognito, ) } @@ -230,9 +240,11 @@ private fun ExtensionDetails( @Composable private fun DetailsHeader( extension: Extension, + extIncognitoMode: Boolean, onClickAgeRating: () -> Unit, onClickUninstall: () -> Unit, onClickAppInfo: (() -> Unit)?, + onExtIncognitoChange: (Boolean) -> Unit, ) { val context = LocalContext.current @@ -240,9 +252,8 @@ private fun DetailsHeader( Column( modifier = Modifier .fillMaxWidth() + .padding(horizontal = MaterialTheme.padding.medium) .padding( - start = MaterialTheme.padding.medium, - end = MaterialTheme.padding.medium, top = MaterialTheme.padding.medium, bottom = MaterialTheme.padding.small, ) @@ -334,12 +345,9 @@ private fun DetailsHeader( } Row( - modifier = Modifier.padding( - start = MaterialTheme.padding.medium, - end = MaterialTheme.padding.medium, - top = MaterialTheme.padding.small, - bottom = MaterialTheme.padding.medium, - ), + modifier = Modifier + .padding(horizontal = MaterialTheme.padding.medium) + .padding(top = MaterialTheme.padding.small), horizontalArrangement = Arrangement.spacedBy(MaterialTheme.padding.medium), ) { OutlinedButton( @@ -362,6 +370,24 @@ private fun DetailsHeader( } } + TextPreferenceWidget( + modifier = Modifier.padding(horizontal = MaterialTheme.padding.small), + title = stringResource(MR.strings.pref_incognito_mode), + subtitle = stringResource(MR.strings.pref_incognito_mode_extension_summary), + icon = ImageVector.vectorResource(R.drawable.ic_glasses_24dp), + widget = { + Row( + verticalAlignment = Alignment.CenterVertically, + ) { + Switch( + checked = extIncognitoMode, + onCheckedChange = onExtIncognitoChange, + modifier = Modifier.padding(start = TrailingWidgetBuffer), + ) + } + }, + ) + HorizontalDivider() } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/extension/ExtensionManager.kt b/app/src/main/java/eu/kanade/tachiyomi/extension/ExtensionManager.kt index f2e9cf4e91..3970490a62 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/extension/ExtensionManager.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/extension/ExtensionManager.kt @@ -89,12 +89,24 @@ class ExtensionManager( private var subLanguagesEnabledOnFirstRun = preferences.enabledLanguages().isSet() - fun getAppIconForSource(sourceId: Long): Drawable? { - val pkgName = installedExtensionMapFlow.value.values - .find { ext -> - ext.sources.any { it.id == sourceId } - } + fun getExtensionPackage(sourceId: Long): String? { + return installedExtensionsFlow.value.find { extension -> + extension.sources.any { it.id == sourceId } + } ?.pkgName + } + + fun getExtensionPackageAsFlow(sourceId: Long): Flow { + return installedExtensionsFlow.map { extensions -> + extensions.find { extension -> + extension.sources.any { it.id == sourceId } + } + ?.pkgName + } + } + + fun getAppIconForSource(sourceId: Long): Drawable? { + val pkgName = getExtensionPackage(sourceId) if (pkgName != null) { return iconMap[pkgName] ?: iconMap.getOrPut(pkgName) { ExtensionLoader.getExtensionPackageInfoFromPkgName(context, pkgName)!!.applicationInfo!! diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/extension/details/ExtensionDetailsScreen.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/extension/details/ExtensionDetailsScreen.kt index 0ae6335bf6..5eb5370323 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/extension/details/ExtensionDetailsScreen.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/extension/details/ExtensionDetailsScreen.kt @@ -59,6 +59,7 @@ data class ExtensionDetailsScreen( onClickClearCookies = screenModel::clearCookies, onClickUninstall = screenModel::uninstallExtension, onClickSource = screenModel::toggleSource, + onClickIncognito = screenModel::toggleIncognito, ) LaunchedEffect(Unit) { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/extension/details/ExtensionDetailsScreenModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/extension/details/ExtensionDetailsScreenModel.kt index 4266c4730f..7997f72626 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/extension/details/ExtensionDetailsScreenModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/extension/details/ExtensionDetailsScreenModel.kt @@ -6,7 +6,9 @@ import cafe.adriel.voyager.core.model.StateScreenModel import cafe.adriel.voyager.core.model.screenModelScope import eu.kanade.domain.extension.interactor.ExtensionSourceItem import eu.kanade.domain.extension.interactor.GetExtensionSources +import eu.kanade.domain.source.interactor.ToggleIncognito import eu.kanade.domain.source.interactor.ToggleSource +import eu.kanade.domain.source.service.SourcePreferences import eu.kanade.tachiyomi.extension.ExtensionManager import eu.kanade.tachiyomi.extension.model.Extension import eu.kanade.tachiyomi.network.NetworkHelper @@ -19,6 +21,7 @@ import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.catch import kotlinx.coroutines.flow.collectLatest +import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.receiveAsFlow import kotlinx.coroutines.flow.update @@ -36,6 +39,8 @@ class ExtensionDetailsScreenModel( private val extensionManager: ExtensionManager = Injekt.get(), private val getExtensionSources: GetExtensionSources = Injekt.get(), private val toggleSource: ToggleSource = Injekt.get(), + private val toggleIncognito: ToggleIncognito = Injekt.get(), + private val preferences: SourcePreferences = Injekt.get(), ) : StateScreenModel(State()) { private val _events: Channel = Channel() @@ -80,6 +85,15 @@ class ExtensionDetailsScreenModel( } } } + launch { + preferences.incognitoExtensions() + .changes() + .map { pkgName in it } + .distinctUntilChanged() + .collectLatest { isIncognito -> + mutableState.update { it.copy(isIncognito = isIncognito) } + } + } } } @@ -118,9 +132,16 @@ class ExtensionDetailsScreenModel( ?.let { toggleSource.await(it, enable) } } + fun toggleIncognito(enable: Boolean) { + state.value.extension?.pkgName?.let { packageName -> + toggleIncognito.await(packageName, enable) + } + } + @Immutable data class State( val extension: Extension.Installed? = null, + val isIncognito: Boolean = false, private val _sources: ImmutableList? = null, ) { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourceScreen.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourceScreen.kt index dd83dfa632..29f583760c 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourceScreen.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourceScreen.kt @@ -83,7 +83,7 @@ import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get data class BrowseSourceScreen( - private val sourceId: Long, + val sourceId: Long, private val listingQuery: String?, // SY --> private val filtersJson: String? = null, diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourceScreenModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourceScreenModel.kt index 94bc5c6ab6..54e7a16db0 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourceScreenModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourceScreenModel.kt @@ -15,10 +15,10 @@ import cafe.adriel.voyager.core.model.StateScreenModel import cafe.adriel.voyager.core.model.screenModelScope import dev.icerock.moko.resources.StringResource import eu.kanade.core.preference.asState -import eu.kanade.domain.base.BasePreferences import eu.kanade.domain.manga.interactor.UpdateManga import eu.kanade.domain.manga.model.toDomainManga import eu.kanade.domain.source.interactor.GetExhSavedSearch +import eu.kanade.domain.source.interactor.GetIncognitoState import eu.kanade.domain.source.service.SourcePreferences import eu.kanade.domain.track.interactor.AddTracks import eu.kanade.domain.ui.UiPreferences @@ -93,7 +93,6 @@ open class BrowseSourceScreenModel( // SY <-- private val sourceManager: SourceManager = Injekt.get(), sourcePreferences: SourcePreferences = Injekt.get(), - basePreferences: BasePreferences = Injekt.get(), private val libraryPreferences: LibraryPreferences = Injekt.get(), private val coverCache: CoverCache = Injekt.get(), private val getRemoteManga: GetRemoteManga = Injekt.get(), @@ -105,6 +104,7 @@ open class BrowseSourceScreenModel( val networkToLocalManga: NetworkToLocalManga = Injekt.get(), private val updateManga: UpdateManga = Injekt.get(), private val addTracks: AddTracks = Injekt.get(), + private val getIncognitoState: GetIncognitoState = Injekt.get(), // SY --> unsortedPreferences: UnsortedPreferences = Injekt.get(), @@ -161,7 +161,7 @@ open class BrowseSourceScreenModel( } }.join() - if (!basePreferences.incognitoMode().get()) { + if (!getIncognitoState.await(source.id)) { sourcePreferences.lastUsedSource().set(source.id) } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/main/MainActivity.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/main/MainActivity.kt index 348784806d..59b00f9f38 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/main/MainActivity.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/main/MainActivity.kt @@ -52,6 +52,7 @@ import cafe.adriel.voyager.navigator.Navigator import cafe.adriel.voyager.navigator.NavigatorDisposeBehavior import cafe.adriel.voyager.navigator.currentOrThrow import eu.kanade.domain.base.BasePreferences +import eu.kanade.domain.source.interactor.GetIncognitoState import eu.kanade.domain.sync.SyncPreferences import eu.kanade.presentation.components.AppStateBanners import eu.kanade.presentation.components.DownloadedOnlyBannerBackgroundColor @@ -142,6 +143,8 @@ class MainActivity : BaseActivity() { private val downloadCache: DownloadCache by injectLazy() private val chapterCache: ChapterCache by injectLazy() + private val getIncognitoState: GetIncognitoState by injectLazy() + // To be checked by splash screen. If true then splash screen will be removed. var ready = false @@ -200,7 +203,7 @@ class MainActivity : BaseActivity() { setComposeContent { val context = LocalContext.current - val incognito by preferences.incognitoMode().collectAsState() + var incognito by remember { mutableStateOf(getIncognitoState.await(null)) } val downloadOnly by preferences.downloadedOnly().collectAsState() val indexing by downloadCache.isInitializing.collectAsState() // KMK --> @@ -269,6 +272,11 @@ class MainActivity : BaseActivity() { // SY <-- } } + LaunchedEffect(navigator.lastItem) { + (navigator.lastItem as? BrowseSourceScreen)?.sourceId + .let(getIncognitoState::subscribe) + .collectLatest { incognito = it } + } val scaffoldInsets = WindowInsets.navigationBars.only(WindowInsetsSides.Horizontal) Scaffold( diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderViewModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderViewModel.kt index f7818d6120..c155315b54 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderViewModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderViewModel.kt @@ -14,6 +14,7 @@ import eu.kanade.domain.chapter.model.toDbChapter import eu.kanade.domain.manga.interactor.SetMangaViewerFlags import eu.kanade.domain.manga.model.readerOrientation import eu.kanade.domain.manga.model.readingMode +import eu.kanade.domain.source.interactor.GetIncognitoState import eu.kanade.domain.sync.SyncPreferences import eu.kanade.domain.track.interactor.TrackChapter import eu.kanade.domain.track.service.TrackPreferences @@ -115,7 +116,6 @@ class ReaderViewModel @JvmOverloads constructor( private val downloadProvider: DownloadProvider = Injekt.get(), private val tempFileManager: UniFileTempFileManager = Injekt.get(), private val imageSaver: ImageSaver = Injekt.get(), - preferences: BasePreferences = Injekt.get(), val readerPreferences: ReaderPreferences = Injekt.get(), private val basePreferences: BasePreferences = Injekt.get(), private val downloadPreferences: DownloadPreferences = Injekt.get(), @@ -127,6 +127,7 @@ class ReaderViewModel @JvmOverloads constructor( private val upsertHistory: UpsertHistory = Injekt.get(), private val updateChapter: UpdateChapter = Injekt.get(), private val setMangaViewerFlags: SetMangaViewerFlags = Injekt.get(), + private val getIncognitoState: GetIncognitoState = Injekt.get(), private val syncPreferences: SyncPreferences = Injekt.get(), // SY --> private val uiPreferences: UiPreferences = Injekt.get(), @@ -264,7 +265,7 @@ class ReaderViewModel @JvmOverloads constructor( .map(::ReaderChapter) } - private val incognitoMode = preferences.incognitoMode().get() + private val incognitoMode: Boolean by lazy { getIncognitoState.await(manga?.source) } private val downloadAheadAmount = downloadPreferences.autoDownloadWhileReading().get() init { diff --git a/i18n/src/commonMain/moko-resources/base/strings.xml b/i18n/src/commonMain/moko-resources/base/strings.xml index e76d75873e..5da224da95 100644 --- a/i18n/src/commonMain/moko-resources/base/strings.xml +++ b/i18n/src/commonMain/moko-resources/base/strings.xml @@ -639,6 +639,7 @@ Downloaded only Incognito mode Pauses reading history + Pause reading history for extension Disable incognito mode Filters all entries in your library