Add option to enable incognito mode per extension (#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>
This commit is contained in:
sdaqo 2025-01-12 04:38:05 +01:00 committed by GitHub
parent 4bc593861c
commit c283abefb0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
14 changed files with 146 additions and 21 deletions

View File

@ -13,6 +13,7 @@ The format is a modified version of [Keep a Changelog](https://keepachangelog.co
## [Unreleased] ## [Unreleased]
### Added ### Added
- Add option to always decode long strip images with SSIV - 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))
### Fixed ### Fixed
- Fix MAL `main_picture` nullability breaking search if a result doesn't have a cover set ([@MajorTanya](https://github.com/MajorTanya)) ([#1618](https://github.com/mihonapp/mihon/pull/1618)) - Fix MAL `main_picture` nullability breaking search if a result doesn't have a cover set ([@MajorTanya](https://github.com/MajorTanya)) ([#1618](https://github.com/mihonapp/mihon/pull/1618))

View File

@ -13,9 +13,11 @@ import eu.kanade.domain.manga.interactor.SetExcludedScanlators
import eu.kanade.domain.manga.interactor.SetMangaViewerFlags import eu.kanade.domain.manga.interactor.SetMangaViewerFlags
import eu.kanade.domain.manga.interactor.UpdateManga import eu.kanade.domain.manga.interactor.UpdateManga
import eu.kanade.domain.source.interactor.GetEnabledSources 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.GetLanguagesWithSources
import eu.kanade.domain.source.interactor.GetSourcesWithFavoriteCount import eu.kanade.domain.source.interactor.GetSourcesWithFavoriteCount
import eu.kanade.domain.source.interactor.SetMigrateSorting 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.ToggleLanguage
import eu.kanade.domain.source.interactor.ToggleSource import eu.kanade.domain.source.interactor.ToggleSource
import eu.kanade.domain.source.interactor.ToggleSourcePin import eu.kanade.domain.source.interactor.ToggleSourcePin
@ -191,5 +193,7 @@ class DomainModule : InjektModule {
addFactory { DeleteExtensionRepo(get()) } addFactory { DeleteExtensionRepo(get()) }
addFactory { ReplaceExtensionRepo(get()) } addFactory { ReplaceExtensionRepo(get()) }
addFactory { UpdateExtensionRepo(get(), get()) } addFactory { UpdateExtensionRepo(get(), get()) }
addFactory { ToggleIncognito(get()) }
addFactory { GetIncognitoState(get(), get(), get()) }
} }
} }

View File

@ -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<Boolean> {
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()
}
}

View File

@ -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)
}
}
}

View File

@ -22,6 +22,8 @@ class SourcePreferences(
fun disabledSources() = preferenceStore.getStringSet("hidden_catalogues", emptySet()) fun disabledSources() = preferenceStore.getStringSet("hidden_catalogues", emptySet())
fun incognitoExtensions() = preferenceStore.getStringSet("incognito_extensions", emptySet())
fun pinnedSources() = preferenceStore.getStringSet("pinned_catalogues", emptySet()) fun pinnedSources() = preferenceStore.getStringSet("pinned_catalogues", emptySet())
fun lastUsedSource() = preferenceStore.getLong( fun lastUsedSource() = preferenceStore.getLong(

View File

@ -35,8 +35,10 @@ import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalUriHandler import androidx.compose.ui.platform.LocalUriHandler
import androidx.compose.ui.res.vectorResource
import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextAlign
@ -48,6 +50,7 @@ import eu.kanade.presentation.components.AppBarActions
import eu.kanade.presentation.components.WarningBanner import eu.kanade.presentation.components.WarningBanner
import eu.kanade.presentation.more.settings.widget.TextPreferenceWidget import eu.kanade.presentation.more.settings.widget.TextPreferenceWidget
import eu.kanade.presentation.more.settings.widget.TrailingWidgetBuffer import eu.kanade.presentation.more.settings.widget.TrailingWidgetBuffer
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.extension.model.Extension import eu.kanade.tachiyomi.extension.model.Extension
import eu.kanade.tachiyomi.source.ConfigurableSource import eu.kanade.tachiyomi.source.ConfigurableSource
import eu.kanade.tachiyomi.ui.browse.extension.details.ExtensionDetailsScreenModel import eu.kanade.tachiyomi.ui.browse.extension.details.ExtensionDetailsScreenModel
@ -72,6 +75,7 @@ fun ExtensionDetailsScreen(
onClickClearCookies: () -> Unit, onClickClearCookies: () -> Unit,
onClickUninstall: () -> Unit, onClickUninstall: () -> Unit,
onClickSource: (sourceId: Long) -> Unit, onClickSource: (sourceId: Long) -> Unit,
onClickIncognito: (Boolean) -> Unit,
) { ) {
val uriHandler = LocalUriHandler.current val uriHandler = LocalUriHandler.current
val url = remember(state.extension) { val url = remember(state.extension) {
@ -140,9 +144,11 @@ fun ExtensionDetailsScreen(
contentPadding = paddingValues, contentPadding = paddingValues,
extension = state.extension, extension = state.extension,
sources = state.sources, sources = state.sources,
incognitoMode = state.isIncognito,
onClickSourcePreferences = onClickSourcePreferences, onClickSourcePreferences = onClickSourcePreferences,
onClickUninstall = onClickUninstall, onClickUninstall = onClickUninstall,
onClickSource = onClickSource, onClickSource = onClickSource,
onClickIncognito = onClickIncognito,
) )
} }
} }
@ -152,9 +158,11 @@ private fun ExtensionDetails(
contentPadding: PaddingValues, contentPadding: PaddingValues,
extension: Extension.Installed, extension: Extension.Installed,
sources: ImmutableList<ExtensionSourceItem>, sources: ImmutableList<ExtensionSourceItem>,
incognitoMode: Boolean,
onClickSourcePreferences: (sourceId: Long) -> Unit, onClickSourcePreferences: (sourceId: Long) -> Unit,
onClickUninstall: () -> Unit, onClickUninstall: () -> Unit,
onClickSource: (sourceId: Long) -> Unit, onClickSource: (sourceId: Long) -> Unit,
onClickIncognito: (Boolean) -> Unit,
) { ) {
val context = LocalContext.current val context = LocalContext.current
var showNsfwWarning by remember { mutableStateOf(false) } var showNsfwWarning by remember { mutableStateOf(false) }
@ -171,6 +179,7 @@ private fun ExtensionDetails(
item { item {
DetailsHeader( DetailsHeader(
extension = extension, extension = extension,
extIncognitoMode = incognitoMode,
onClickUninstall = onClickUninstall, onClickUninstall = onClickUninstall,
onClickAppInfo = { onClickAppInfo = {
Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS).apply { Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS).apply {
@ -182,6 +191,7 @@ private fun ExtensionDetails(
onClickAgeRating = { onClickAgeRating = {
showNsfwWarning = true showNsfwWarning = true
}, },
onExtIncognitoChange = onClickIncognito,
) )
} }
@ -209,9 +219,11 @@ private fun ExtensionDetails(
@Composable @Composable
private fun DetailsHeader( private fun DetailsHeader(
extension: Extension, extension: Extension,
extIncognitoMode: Boolean,
onClickAgeRating: () -> Unit, onClickAgeRating: () -> Unit,
onClickUninstall: () -> Unit, onClickUninstall: () -> Unit,
onClickAppInfo: (() -> Unit)?, onClickAppInfo: (() -> Unit)?,
onExtIncognitoChange: (Boolean) -> Unit,
) { ) {
val context = LocalContext.current val context = LocalContext.current
@ -219,9 +231,8 @@ private fun DetailsHeader(
Column( Column(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.padding(horizontal = MaterialTheme.padding.medium)
.padding( .padding(
start = MaterialTheme.padding.medium,
end = MaterialTheme.padding.medium,
top = MaterialTheme.padding.medium, top = MaterialTheme.padding.medium,
bottom = MaterialTheme.padding.small, bottom = MaterialTheme.padding.small,
) )
@ -313,12 +324,9 @@ private fun DetailsHeader(
} }
Row( Row(
modifier = Modifier.padding( modifier = Modifier
start = MaterialTheme.padding.medium, .padding(horizontal = MaterialTheme.padding.medium)
end = MaterialTheme.padding.medium, .padding(top = MaterialTheme.padding.small),
top = MaterialTheme.padding.small,
bottom = MaterialTheme.padding.medium,
),
horizontalArrangement = Arrangement.spacedBy(MaterialTheme.padding.medium), horizontalArrangement = Arrangement.spacedBy(MaterialTheme.padding.medium),
) { ) {
OutlinedButton( OutlinedButton(
@ -341,6 +349,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() HorizontalDivider()
} }
} }

View File

@ -78,13 +78,24 @@ class ExtensionManager(
private var subLanguagesEnabledOnFirstRun = preferences.enabledLanguages().isSet() private var subLanguagesEnabledOnFirstRun = preferences.enabledLanguages().isSet()
fun getAppIconForSource(sourceId: Long): Drawable? { fun getExtensionPackage(sourceId: Long): String? {
val pkgName = installedExtensionMapFlow.value.values return installedExtensionsFlow.value.find { extension ->
.find { ext -> extension.sources.any { it.id == sourceId }
ext.sources.any { it.id == sourceId }
} }
?.pkgName ?.pkgName
?: return null }
fun getExtensionPackageAsFlow(sourceId: Long): Flow<String?> {
return installedExtensionsFlow.map { extensions ->
extensions.find { extension ->
extension.sources.any { it.id == sourceId }
}
?.pkgName
}
}
fun getAppIconForSource(sourceId: Long): Drawable? {
val pkgName = getExtensionPackage(sourceId) ?: return null
return iconMap[pkgName] ?: iconMap.getOrPut(pkgName) { return iconMap[pkgName] ?: iconMap.getOrPut(pkgName) {
ExtensionLoader.getExtensionPackageInfoFromPkgName(context, pkgName)!!.applicationInfo!! ExtensionLoader.getExtensionPackageInfoFromPkgName(context, pkgName)!!.applicationInfo!!

View File

@ -39,6 +39,7 @@ data class ExtensionDetailsScreen(
onClickClearCookies = screenModel::clearCookies, onClickClearCookies = screenModel::clearCookies,
onClickUninstall = screenModel::uninstallExtension, onClickUninstall = screenModel::uninstallExtension,
onClickSource = screenModel::toggleSource, onClickSource = screenModel::toggleSource,
onClickIncognito = screenModel::toggleIncognito,
) )
LaunchedEffect(Unit) { LaunchedEffect(Unit) {

View File

@ -6,7 +6,9 @@ import cafe.adriel.voyager.core.model.StateScreenModel
import cafe.adriel.voyager.core.model.screenModelScope import cafe.adriel.voyager.core.model.screenModelScope
import eu.kanade.domain.extension.interactor.ExtensionSourceItem import eu.kanade.domain.extension.interactor.ExtensionSourceItem
import eu.kanade.domain.extension.interactor.GetExtensionSources 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.interactor.ToggleSource
import eu.kanade.domain.source.service.SourcePreferences
import eu.kanade.tachiyomi.extension.ExtensionManager import eu.kanade.tachiyomi.extension.ExtensionManager
import eu.kanade.tachiyomi.extension.model.Extension import eu.kanade.tachiyomi.extension.model.Extension
import eu.kanade.tachiyomi.network.NetworkHelper import eu.kanade.tachiyomi.network.NetworkHelper
@ -19,6 +21,7 @@ import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.catch import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.receiveAsFlow import kotlinx.coroutines.flow.receiveAsFlow
import kotlinx.coroutines.flow.update import kotlinx.coroutines.flow.update
@ -36,6 +39,8 @@ class ExtensionDetailsScreenModel(
private val extensionManager: ExtensionManager = Injekt.get(), private val extensionManager: ExtensionManager = Injekt.get(),
private val getExtensionSources: GetExtensionSources = Injekt.get(), private val getExtensionSources: GetExtensionSources = Injekt.get(),
private val toggleSource: ToggleSource = Injekt.get(), private val toggleSource: ToggleSource = Injekt.get(),
private val toggleIncognito: ToggleIncognito = Injekt.get(),
private val preferences: SourcePreferences = Injekt.get(),
) : StateScreenModel<ExtensionDetailsScreenModel.State>(State()) { ) : StateScreenModel<ExtensionDetailsScreenModel.State>(State()) {
private val _events: Channel<ExtensionDetailsEvent> = Channel() private val _events: Channel<ExtensionDetailsEvent> = 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) } ?.let { toggleSource.await(it, enable) }
} }
fun toggleIncognito(enable: Boolean) {
state.value.extension?.pkgName?.let { packageName ->
toggleIncognito.await(packageName, enable)
}
}
@Immutable @Immutable
data class State( data class State(
val extension: Extension.Installed? = null, val extension: Extension.Installed? = null,
val isIncognito: Boolean = false,
private val _sources: ImmutableList<ExtensionSourceItem>? = null, private val _sources: ImmutableList<ExtensionSourceItem>? = null,
) { ) {

View File

@ -67,7 +67,7 @@ import tachiyomi.presentation.core.screens.LoadingScreen
import tachiyomi.source.local.LocalSource import tachiyomi.source.local.LocalSource
data class BrowseSourceScreen( data class BrowseSourceScreen(
private val sourceId: Long, val sourceId: Long,
private val listingQuery: String?, private val listingQuery: String?,
) : Screen(), AssistContentScreen { ) : Screen(), AssistContentScreen {

View File

@ -14,9 +14,9 @@ import androidx.paging.map
import cafe.adriel.voyager.core.model.StateScreenModel import cafe.adriel.voyager.core.model.StateScreenModel
import cafe.adriel.voyager.core.model.screenModelScope import cafe.adriel.voyager.core.model.screenModelScope
import eu.kanade.core.preference.asState import eu.kanade.core.preference.asState
import eu.kanade.domain.base.BasePreferences
import eu.kanade.domain.manga.interactor.UpdateManga import eu.kanade.domain.manga.interactor.UpdateManga
import eu.kanade.domain.manga.model.toDomainManga import eu.kanade.domain.manga.model.toDomainManga
import eu.kanade.domain.source.interactor.GetIncognitoState
import eu.kanade.domain.source.service.SourcePreferences import eu.kanade.domain.source.service.SourcePreferences
import eu.kanade.domain.track.interactor.AddTracks import eu.kanade.domain.track.interactor.AddTracks
import eu.kanade.presentation.util.ioCoroutineScope import eu.kanade.presentation.util.ioCoroutineScope
@ -60,7 +60,6 @@ class BrowseSourceScreenModel(
listingQuery: String?, listingQuery: String?,
sourceManager: SourceManager = Injekt.get(), sourceManager: SourceManager = Injekt.get(),
sourcePreferences: SourcePreferences = Injekt.get(), sourcePreferences: SourcePreferences = Injekt.get(),
basePreferences: BasePreferences = Injekt.get(),
private val libraryPreferences: LibraryPreferences = Injekt.get(), private val libraryPreferences: LibraryPreferences = Injekt.get(),
private val coverCache: CoverCache = Injekt.get(), private val coverCache: CoverCache = Injekt.get(),
private val getRemoteManga: GetRemoteManga = Injekt.get(), private val getRemoteManga: GetRemoteManga = Injekt.get(),
@ -72,6 +71,7 @@ class BrowseSourceScreenModel(
private val networkToLocalManga: NetworkToLocalManga = Injekt.get(), private val networkToLocalManga: NetworkToLocalManga = Injekt.get(),
private val updateManga: UpdateManga = Injekt.get(), private val updateManga: UpdateManga = Injekt.get(),
private val addTracks: AddTracks = Injekt.get(), private val addTracks: AddTracks = Injekt.get(),
private val getIncognitoState: GetIncognitoState = Injekt.get(),
) : StateScreenModel<BrowseSourceScreenModel.State>(State(Listing.valueOf(listingQuery))) { ) : StateScreenModel<BrowseSourceScreenModel.State>(State(Listing.valueOf(listingQuery))) {
var displayMode by sourcePreferences.sourceDisplayMode().asState(screenModelScope) var displayMode by sourcePreferences.sourceDisplayMode().asState(screenModelScope)
@ -97,7 +97,7 @@ class BrowseSourceScreenModel(
} }
} }
if (!basePreferences.incognitoMode().get()) { if (!getIncognitoState.await(source.id)) {
sourcePreferences.lastUsedSource().set(source.id) sourcePreferences.lastUsedSource().set(source.id)
} }
} }

View File

@ -54,6 +54,7 @@ import cafe.adriel.voyager.navigator.Navigator
import cafe.adriel.voyager.navigator.NavigatorDisposeBehavior import cafe.adriel.voyager.navigator.NavigatorDisposeBehavior
import cafe.adriel.voyager.navigator.currentOrThrow import cafe.adriel.voyager.navigator.currentOrThrow
import eu.kanade.domain.base.BasePreferences import eu.kanade.domain.base.BasePreferences
import eu.kanade.domain.source.interactor.GetIncognitoState
import eu.kanade.presentation.components.AppStateBanners import eu.kanade.presentation.components.AppStateBanners
import eu.kanade.presentation.components.DownloadedOnlyBannerBackgroundColor import eu.kanade.presentation.components.DownloadedOnlyBannerBackgroundColor
import eu.kanade.presentation.components.IncognitoModeBannerBackgroundColor import eu.kanade.presentation.components.IncognitoModeBannerBackgroundColor
@ -110,6 +111,8 @@ class MainActivity : BaseActivity() {
private val downloadCache: DownloadCache by injectLazy() private val downloadCache: DownloadCache by injectLazy()
private val chapterCache: ChapterCache 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. // To be checked by splash screen. If true then splash screen will be removed.
var ready = false var ready = false
@ -138,7 +141,7 @@ class MainActivity : BaseActivity() {
setComposeContent { setComposeContent {
val context = LocalContext.current 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 downloadOnly by preferences.downloadedOnly().collectAsState()
val indexing by downloadCache.isInitializing.collectAsState() val indexing by downloadCache.isInitializing.collectAsState()
@ -174,6 +177,11 @@ class MainActivity : BaseActivity() {
preferences.incognitoMode().set(false) preferences.incognitoMode().set(false)
} }
} }
LaunchedEffect(navigator.lastItem) {
(navigator.lastItem as? BrowseSourceScreen)?.sourceId
.let(getIncognitoState::subscribe)
.collectLatest { incognito = it }
}
val scaffoldInsets = WindowInsets.navigationBars.only(WindowInsetsSides.Horizontal) val scaffoldInsets = WindowInsets.navigationBars.only(WindowInsetsSides.Horizontal)
Scaffold( Scaffold(

View File

@ -12,6 +12,7 @@ import eu.kanade.domain.chapter.model.toDbChapter
import eu.kanade.domain.manga.interactor.SetMangaViewerFlags import eu.kanade.domain.manga.interactor.SetMangaViewerFlags
import eu.kanade.domain.manga.model.readerOrientation import eu.kanade.domain.manga.model.readerOrientation
import eu.kanade.domain.manga.model.readingMode import eu.kanade.domain.manga.model.readingMode
import eu.kanade.domain.source.interactor.GetIncognitoState
import eu.kanade.domain.track.interactor.TrackChapter import eu.kanade.domain.track.interactor.TrackChapter
import eu.kanade.domain.track.service.TrackPreferences import eu.kanade.domain.track.service.TrackPreferences
import eu.kanade.tachiyomi.data.database.models.toDomainChapter import eu.kanade.tachiyomi.data.database.models.toDomainChapter
@ -87,7 +88,6 @@ class ReaderViewModel @JvmOverloads constructor(
private val downloadManager: DownloadManager = Injekt.get(), private val downloadManager: DownloadManager = Injekt.get(),
private val downloadProvider: DownloadProvider = Injekt.get(), private val downloadProvider: DownloadProvider = Injekt.get(),
private val imageSaver: ImageSaver = Injekt.get(), private val imageSaver: ImageSaver = Injekt.get(),
preferences: BasePreferences = Injekt.get(),
val readerPreferences: ReaderPreferences = Injekt.get(), val readerPreferences: ReaderPreferences = Injekt.get(),
private val basePreferences: BasePreferences = Injekt.get(), private val basePreferences: BasePreferences = Injekt.get(),
private val downloadPreferences: DownloadPreferences = Injekt.get(), private val downloadPreferences: DownloadPreferences = Injekt.get(),
@ -99,6 +99,7 @@ class ReaderViewModel @JvmOverloads constructor(
private val upsertHistory: UpsertHistory = Injekt.get(), private val upsertHistory: UpsertHistory = Injekt.get(),
private val updateChapter: UpdateChapter = Injekt.get(), private val updateChapter: UpdateChapter = Injekt.get(),
private val setMangaViewerFlags: SetMangaViewerFlags = Injekt.get(), private val setMangaViewerFlags: SetMangaViewerFlags = Injekt.get(),
private val getIncognitoState: GetIncognitoState = Injekt.get(),
) : ViewModel() { ) : ViewModel() {
private val mutableState = MutableStateFlow(State()) private val mutableState = MutableStateFlow(State())
@ -216,7 +217,7 @@ class ReaderViewModel @JvmOverloads constructor(
.map(::ReaderChapter) .map(::ReaderChapter)
} }
private val incognitoMode = preferences.incognitoMode().get() private val incognitoMode: Boolean by lazy { getIncognitoState.await(manga?.source) }
private val downloadAheadAmount = downloadPreferences.autoDownloadWhileReading().get() private val downloadAheadAmount = downloadPreferences.autoDownloadWhileReading().get()
init { init {

View File

@ -637,6 +637,7 @@
<string name="label_downloaded_only">Downloaded only</string> <string name="label_downloaded_only">Downloaded only</string>
<string name="pref_incognito_mode">Incognito mode</string> <string name="pref_incognito_mode">Incognito mode</string>
<string name="pref_incognito_mode_summary">Pauses reading history</string> <string name="pref_incognito_mode_summary">Pauses reading history</string>
<string name="pref_incognito_mode_extension_summary">Pause reading history for extension</string>
<string name="notification_incognito_text">Disable incognito mode</string> <string name="notification_incognito_text">Disable incognito mode</string>
<string name="downloaded_only_summary">Filters all entries in your library</string> <string name="downloaded_only_summary">Filters all entries in your library</string>