From 748ed867c50311721750f1cc72f484b8a3e47960 Mon Sep 17 00:00:00 2001 From: sdaqo Date: Sat, 20 Jan 2024 13:04:52 +0100 Subject: [PATCH] add per Extension Incognito Mode --- .../domain/source/interactor/ToggleSource.kt | 15 +++++-- .../source/service/SourcePreferences.kt | 2 + .../browse/ExtensionDetailsScreen.kt | 44 ++++++++++++++++++- .../details/ExtensionDetailsScreen.kt | 10 +++++ .../details/ExtensionDetailsScreenModel.kt | 18 +++++++- .../browse/source/SourcesFilterScreenModel.kt | 2 +- .../ui/browse/source/SourcesScreenModel.kt | 2 +- .../source/browse/BrowseSourceScreenModel.kt | 2 +- .../tachiyomi/ui/reader/ReaderViewModel.kt | 7 ++- 9 files changed, 91 insertions(+), 11 deletions(-) diff --git a/app/src/main/java/eu/kanade/domain/source/interactor/ToggleSource.kt b/app/src/main/java/eu/kanade/domain/source/interactor/ToggleSource.kt index fbcb3147c..10a18ed5b 100644 --- a/app/src/main/java/eu/kanade/domain/source/interactor/ToggleSource.kt +++ b/app/src/main/java/eu/kanade/domain/source/interactor/ToggleSource.kt @@ -8,23 +8,30 @@ class ToggleSource( private val preferences: SourcePreferences, ) { - fun await(source: Source, enable: Boolean = isEnabled(source.id)) { - await(source.id, enable) + fun awaitDisable(source: Source, enable: Boolean = isEnabled(source.id)) { + awaitDisable(source.id, enable) } - fun await(sourceId: Long, enable: Boolean = isEnabled(sourceId)) { + fun awaitDisable(sourceId: Long, enable: Boolean = isEnabled(sourceId)) { preferences.disabledSources().getAndSet { disabled -> if (enable) disabled.minus("$sourceId") else disabled.plus("$sourceId") } } - fun await(sourceIds: List, enable: Boolean) { + fun awaitDisable(sourceIds: List, enable: Boolean) { val transformedSourceIds = sourceIds.map { it.toString() } preferences.disabledSources().getAndSet { disabled -> if (enable) disabled.minus(transformedSourceIds) else disabled.plus(transformedSourceIds) } } + fun awaitIncognito(sourceIds: List, enableIncognito: Boolean) { + val transformedSourceIds = sourceIds.map { it.toString() } + preferences.incognitoSources().getAndSet { incognitoed -> + if (enableIncognito) incognitoed.plus(transformedSourceIds) else incognitoed.minus(transformedSourceIds) + } + } + private fun isEnabled(sourceId: Long): Boolean { return sourceId.toString() in preferences.disabledSources().get() } 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 5779020a2..5f0397f29 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 @@ -22,6 +22,8 @@ class SourcePreferences( fun disabledSources() = preferenceStore.getStringSet("hidden_catalogues", emptySet()) + fun incognitoSources() = preferenceStore.getStringSet("incognito_catalogues", 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 e55576db8..8a918e1b0 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 @@ -66,12 +69,14 @@ import tachiyomi.presentation.core.screens.EmptyScreen fun ExtensionDetailsScreen( navigateUp: () -> Unit, state: ExtensionDetailsScreenModel.State, + extIncognitoMode: Boolean, onClickSourcePreferences: (sourceId: Long) -> Unit, onClickEnableAll: () -> Unit, onClickDisableAll: () -> Unit, onClickClearCookies: () -> Unit, onClickUninstall: () -> Unit, onClickSource: (sourceId: Long) -> Unit, + onExtIncognitoChange: (Boolean) -> Unit ) { val uriHandler = LocalUriHandler.current val url = remember(state.extension) { @@ -140,9 +145,11 @@ fun ExtensionDetailsScreen( contentPadding = paddingValues, extension = state.extension, sources = state.sources, + extIncognitoMode = extIncognitoMode, onClickSourcePreferences = onClickSourcePreferences, onClickUninstall = onClickUninstall, onClickSource = onClickSource, + onExtIncognitoChange = onExtIncognitoChange, ) } } @@ -152,9 +159,11 @@ private fun ExtensionDetails( contentPadding: PaddingValues, extension: Extension.Installed, sources: ImmutableList, + extIncognitoMode: Boolean, onClickSourcePreferences: (sourceId: Long) -> Unit, onClickUninstall: () -> Unit, onClickSource: (sourceId: Long) -> Unit, + onExtIncognitoChange: (Boolean) -> Unit ) { val context = LocalContext.current var showNsfwWarning by remember { mutableStateOf(false) } @@ -171,6 +180,7 @@ private fun ExtensionDetails( item { DetailsHeader( extension = extension, + extIncognitoMode = extIncognitoMode, onClickUninstall = onClickUninstall, onClickAppInfo = { Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS).apply { @@ -182,6 +192,7 @@ private fun ExtensionDetails( onClickAgeRating = { showNsfwWarning = true }, + onExtIncognitoChange = onExtIncognitoChange, ) } @@ -209,9 +220,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 @@ -293,7 +306,7 @@ private fun DetailsHeader( start = MaterialTheme.padding.medium, end = MaterialTheme.padding.medium, top = MaterialTheme.padding.small, - bottom = MaterialTheme.padding.medium, + bottom = MaterialTheme.padding.small, ), horizontalArrangement = Arrangement.spacedBy(MaterialTheme.padding.medium), ) { @@ -317,6 +330,35 @@ private fun DetailsHeader( } } + Row( + modifier = Modifier.padding( + start = MaterialTheme.padding.small, + end = MaterialTheme.padding.small, + top = MaterialTheme.padding.extraSmall, + bottom = MaterialTheme.padding.medium, + ), + horizontalArrangement = Arrangement.spacedBy(MaterialTheme.padding.medium), + ) { + TextPreferenceWidget( + modifier = Modifier, + title = stringResource(MR.strings.pref_incognito_mode), + subtitle = stringResource(MR.strings.pref_incognito_mode_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/ui/browse/extension/details/ExtensionDetailsScreen.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/extension/details/ExtensionDetailsScreen.kt index 4a4a78cde..8a7628b38 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 @@ -4,6 +4,9 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue import androidx.compose.ui.platform.LocalContext import cafe.adriel.voyager.core.model.rememberScreenModel import cafe.adriel.voyager.navigator.LocalNavigator @@ -22,6 +25,8 @@ data class ExtensionDetailsScreen( val context = LocalContext.current val screenModel = rememberScreenModel { ExtensionDetailsScreenModel(pkgName = pkgName, context = context) } val state by screenModel.state.collectAsState() + var isIncognitoMode by remember { mutableStateOf(screenModel.isIncognito()) } + if (state.isLoading) { LoadingScreen() @@ -33,12 +38,17 @@ data class ExtensionDetailsScreen( ExtensionDetailsScreen( navigateUp = navigator::pop, state = state, + extIncognitoMode = isIncognitoMode, onClickSourcePreferences = { navigator.push(SourcePreferencesScreen(it)) }, onClickEnableAll = { screenModel.toggleSources(true) }, onClickDisableAll = { screenModel.toggleSources(false) }, onClickClearCookies = screenModel::clearCookies, onClickUninstall = screenModel::uninstallExtension, onClickSource = screenModel::toggleSource, + onExtIncognitoChange = { newState -> + screenModel.toggleIncognito(newState) + isIncognitoMode = screenModel.isIncognito() + } ) 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 8d8a9f607..32b2f7c85 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 @@ -7,6 +7,7 @@ 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.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 @@ -36,6 +37,7 @@ class ExtensionDetailsScreenModel( private val extensionManager: ExtensionManager = Injekt.get(), private val getExtensionSources: GetExtensionSources = Injekt.get(), private val toggleSource: ToggleSource = Injekt.get(), + private val preferences: SourcePreferences = Injekt.get(), ) : StateScreenModel(State()) { private val _events: Channel = Channel() @@ -109,13 +111,25 @@ class ExtensionDetailsScreenModel( } fun toggleSource(sourceId: Long) { - toggleSource.await(sourceId) + toggleSource.awaitDisable(sourceId) } fun toggleSources(enable: Boolean) { state.value.extension?.sources ?.map { it.id } - ?.let { toggleSource.await(it, enable) } + ?.let { toggleSource.awaitDisable(it, enable) } + } + + fun toggleIncognito(enableIncognito: Boolean) { + state.value.extension?.sources + ?.map { it.id } + ?.let { toggleSource.awaitIncognito(it, enableIncognito) } + } + + fun isIncognito(): Boolean { + return state.value.extension?.sources + ?.first() + ?.id.toString() in preferences.incognitoSources().get() } @Immutable diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/SourcesFilterScreenModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/SourcesFilterScreenModel.kt index 4f4ff301c..8c33dafac 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/SourcesFilterScreenModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/SourcesFilterScreenModel.kt @@ -51,7 +51,7 @@ class SourcesFilterScreenModel( } fun toggleSource(source: Source) { - toggleSource.await(source) + toggleSource.awaitDisable(source) } fun toggleLanguage(language: String) { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/SourcesScreenModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/SourcesScreenModel.kt index ce98bf629..2ae438eed 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/SourcesScreenModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/SourcesScreenModel.kt @@ -83,7 +83,7 @@ class SourcesScreenModel( } fun toggleSource(source: Source) { - toggleSource.await(source) + toggleSource.awaitDisable(source) } fun togglePin(source: Source) { 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 4b0835850..c992ec220 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 @@ -97,7 +97,7 @@ class BrowseSourceScreenModel( } } - if (!basePreferences.incognitoMode().get()) { + if (!(basePreferences.incognitoMode().get() || source.id.toString() in sourcePreferences.incognitoSources().get())) { sourcePreferences.lastUsedSource().set(source.id) } } 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 b7f4c9c14..66a8b22c4 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 @@ -12,6 +12,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.service.SourcePreferences import eu.kanade.domain.track.interactor.TrackChapter import eu.kanade.domain.track.service.TrackPreferences import eu.kanade.tachiyomi.data.database.models.toDomainChapter @@ -92,6 +93,7 @@ class ReaderViewModel @JvmOverloads constructor( val readerPreferences: ReaderPreferences = Injekt.get(), private val basePreferences: BasePreferences = Injekt.get(), private val downloadPreferences: DownloadPreferences = Injekt.get(), + private val sourcePreferences: SourcePreferences = Injekt.get(), private val trackPreferences: TrackPreferences = Injekt.get(), private val trackChapter: TrackChapter = Injekt.get(), private val getManga: GetManga = Injekt.get(), @@ -211,7 +213,10 @@ class ReaderViewModel @JvmOverloads constructor( .map(::ReaderChapter) } - private val incognitoMode = preferences.incognitoMode().get() + // Use lazy here as manga can be null + private val incognitoMode: Boolean by lazy { + preferences.incognitoMode().get() || manga?.source.toString() in sourcePreferences.incognitoSources().get() + } private val downloadAheadAmount = downloadPreferences.autoDownloadWhileReading().get() init {