add per Extension Incognito Mode

This commit is contained in:
sdaqo 2024-01-20 13:04:52 +01:00
parent 38d6ab80ce
commit 748ed867c5
No known key found for this signature in database
GPG Key ID: 8667036D76A57EB8
9 changed files with 91 additions and 11 deletions

View File

@ -8,23 +8,30 @@ class ToggleSource(
private val preferences: SourcePreferences, private val preferences: SourcePreferences,
) { ) {
fun await(source: Source, enable: Boolean = isEnabled(source.id)) { fun awaitDisable(source: Source, enable: Boolean = isEnabled(source.id)) {
await(source.id, enable) awaitDisable(source.id, enable)
} }
fun await(sourceId: Long, enable: Boolean = isEnabled(sourceId)) { fun awaitDisable(sourceId: Long, enable: Boolean = isEnabled(sourceId)) {
preferences.disabledSources().getAndSet { disabled -> preferences.disabledSources().getAndSet { disabled ->
if (enable) disabled.minus("$sourceId") else disabled.plus("$sourceId") if (enable) disabled.minus("$sourceId") else disabled.plus("$sourceId")
} }
} }
fun await(sourceIds: List<Long>, enable: Boolean) { fun awaitDisable(sourceIds: List<Long>, enable: Boolean) {
val transformedSourceIds = sourceIds.map { it.toString() } val transformedSourceIds = sourceIds.map { it.toString() }
preferences.disabledSources().getAndSet { disabled -> preferences.disabledSources().getAndSet { disabled ->
if (enable) disabled.minus(transformedSourceIds) else disabled.plus(transformedSourceIds) if (enable) disabled.minus(transformedSourceIds) else disabled.plus(transformedSourceIds)
} }
} }
fun awaitIncognito(sourceIds: List<Long>, 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 { private fun isEnabled(sourceId: Long): Boolean {
return sourceId.toString() in preferences.disabledSources().get() return sourceId.toString() in preferences.disabledSources().get()
} }

View File

@ -22,6 +22,8 @@ class SourcePreferences(
fun disabledSources() = preferenceStore.getStringSet("hidden_catalogues", emptySet()) fun disabledSources() = preferenceStore.getStringSet("hidden_catalogues", emptySet())
fun incognitoSources() = preferenceStore.getStringSet("incognito_catalogues", 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

@ -36,8 +36,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
@ -49,6 +51,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
@ -66,12 +69,14 @@ import tachiyomi.presentation.core.screens.EmptyScreen
fun ExtensionDetailsScreen( fun ExtensionDetailsScreen(
navigateUp: () -> Unit, navigateUp: () -> Unit,
state: ExtensionDetailsScreenModel.State, state: ExtensionDetailsScreenModel.State,
extIncognitoMode: Boolean,
onClickSourcePreferences: (sourceId: Long) -> Unit, onClickSourcePreferences: (sourceId: Long) -> Unit,
onClickEnableAll: () -> Unit, onClickEnableAll: () -> Unit,
onClickDisableAll: () -> Unit, onClickDisableAll: () -> Unit,
onClickClearCookies: () -> Unit, onClickClearCookies: () -> Unit,
onClickUninstall: () -> Unit, onClickUninstall: () -> Unit,
onClickSource: (sourceId: Long) -> Unit, onClickSource: (sourceId: Long) -> Unit,
onExtIncognitoChange: (Boolean) -> Unit
) { ) {
val uriHandler = LocalUriHandler.current val uriHandler = LocalUriHandler.current
val url = remember(state.extension) { val url = remember(state.extension) {
@ -140,9 +145,11 @@ fun ExtensionDetailsScreen(
contentPadding = paddingValues, contentPadding = paddingValues,
extension = state.extension, extension = state.extension,
sources = state.sources, sources = state.sources,
extIncognitoMode = extIncognitoMode,
onClickSourcePreferences = onClickSourcePreferences, onClickSourcePreferences = onClickSourcePreferences,
onClickUninstall = onClickUninstall, onClickUninstall = onClickUninstall,
onClickSource = onClickSource, onClickSource = onClickSource,
onExtIncognitoChange = onExtIncognitoChange,
) )
} }
} }
@ -152,9 +159,11 @@ private fun ExtensionDetails(
contentPadding: PaddingValues, contentPadding: PaddingValues,
extension: Extension.Installed, extension: Extension.Installed,
sources: ImmutableList<ExtensionSourceItem>, sources: ImmutableList<ExtensionSourceItem>,
extIncognitoMode: Boolean,
onClickSourcePreferences: (sourceId: Long) -> Unit, onClickSourcePreferences: (sourceId: Long) -> Unit,
onClickUninstall: () -> Unit, onClickUninstall: () -> Unit,
onClickSource: (sourceId: Long) -> Unit, onClickSource: (sourceId: Long) -> Unit,
onExtIncognitoChange: (Boolean) -> Unit
) { ) {
val context = LocalContext.current val context = LocalContext.current
var showNsfwWarning by remember { mutableStateOf(false) } var showNsfwWarning by remember { mutableStateOf(false) }
@ -171,6 +180,7 @@ private fun ExtensionDetails(
item { item {
DetailsHeader( DetailsHeader(
extension = extension, extension = extension,
extIncognitoMode = extIncognitoMode,
onClickUninstall = onClickUninstall, onClickUninstall = onClickUninstall,
onClickAppInfo = { onClickAppInfo = {
Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS).apply { Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS).apply {
@ -182,6 +192,7 @@ private fun ExtensionDetails(
onClickAgeRating = { onClickAgeRating = {
showNsfwWarning = true showNsfwWarning = true
}, },
onExtIncognitoChange = onExtIncognitoChange,
) )
} }
@ -209,9 +220,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
@ -293,7 +306,7 @@ private fun DetailsHeader(
start = MaterialTheme.padding.medium, start = MaterialTheme.padding.medium,
end = MaterialTheme.padding.medium, end = MaterialTheme.padding.medium,
top = MaterialTheme.padding.small, top = MaterialTheme.padding.small,
bottom = MaterialTheme.padding.medium, bottom = MaterialTheme.padding.small,
), ),
horizontalArrangement = Arrangement.spacedBy(MaterialTheme.padding.medium), 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() HorizontalDivider()
} }
} }

View File

@ -4,6 +4,9 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue 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 androidx.compose.ui.platform.LocalContext
import cafe.adriel.voyager.core.model.rememberScreenModel import cafe.adriel.voyager.core.model.rememberScreenModel
import cafe.adriel.voyager.navigator.LocalNavigator import cafe.adriel.voyager.navigator.LocalNavigator
@ -22,6 +25,8 @@ data class ExtensionDetailsScreen(
val context = LocalContext.current val context = LocalContext.current
val screenModel = rememberScreenModel { ExtensionDetailsScreenModel(pkgName = pkgName, context = context) } val screenModel = rememberScreenModel { ExtensionDetailsScreenModel(pkgName = pkgName, context = context) }
val state by screenModel.state.collectAsState() val state by screenModel.state.collectAsState()
var isIncognitoMode by remember { mutableStateOf(screenModel.isIncognito()) }
if (state.isLoading) { if (state.isLoading) {
LoadingScreen() LoadingScreen()
@ -33,12 +38,17 @@ data class ExtensionDetailsScreen(
ExtensionDetailsScreen( ExtensionDetailsScreen(
navigateUp = navigator::pop, navigateUp = navigator::pop,
state = state, state = state,
extIncognitoMode = isIncognitoMode,
onClickSourcePreferences = { navigator.push(SourcePreferencesScreen(it)) }, onClickSourcePreferences = { navigator.push(SourcePreferencesScreen(it)) },
onClickEnableAll = { screenModel.toggleSources(true) }, onClickEnableAll = { screenModel.toggleSources(true) },
onClickDisableAll = { screenModel.toggleSources(false) }, onClickDisableAll = { screenModel.toggleSources(false) },
onClickClearCookies = screenModel::clearCookies, onClickClearCookies = screenModel::clearCookies,
onClickUninstall = screenModel::uninstallExtension, onClickUninstall = screenModel::uninstallExtension,
onClickSource = screenModel::toggleSource, onClickSource = screenModel::toggleSource,
onExtIncognitoChange = { newState ->
screenModel.toggleIncognito(newState)
isIncognitoMode = screenModel.isIncognito()
}
) )
LaunchedEffect(Unit) { LaunchedEffect(Unit) {

View File

@ -7,6 +7,7 @@ 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.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
@ -36,6 +37,7 @@ 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 preferences: SourcePreferences = Injekt.get(),
) : StateScreenModel<ExtensionDetailsScreenModel.State>(State()) { ) : StateScreenModel<ExtensionDetailsScreenModel.State>(State()) {
private val _events: Channel<ExtensionDetailsEvent> = Channel() private val _events: Channel<ExtensionDetailsEvent> = Channel()
@ -109,13 +111,25 @@ class ExtensionDetailsScreenModel(
} }
fun toggleSource(sourceId: Long) { fun toggleSource(sourceId: Long) {
toggleSource.await(sourceId) toggleSource.awaitDisable(sourceId)
} }
fun toggleSources(enable: Boolean) { fun toggleSources(enable: Boolean) {
state.value.extension?.sources state.value.extension?.sources
?.map { it.id } ?.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 @Immutable

View File

@ -51,7 +51,7 @@ class SourcesFilterScreenModel(
} }
fun toggleSource(source: Source) { fun toggleSource(source: Source) {
toggleSource.await(source) toggleSource.awaitDisable(source)
} }
fun toggleLanguage(language: String) { fun toggleLanguage(language: String) {

View File

@ -83,7 +83,7 @@ class SourcesScreenModel(
} }
fun toggleSource(source: Source) { fun toggleSource(source: Source) {
toggleSource.await(source) toggleSource.awaitDisable(source)
} }
fun togglePin(source: Source) { fun togglePin(source: Source) {

View File

@ -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) sourcePreferences.lastUsedSource().set(source.id)
} }
} }

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.service.SourcePreferences
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
@ -92,6 +93,7 @@ class ReaderViewModel @JvmOverloads constructor(
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(),
private val sourcePreferences: SourcePreferences = Injekt.get(),
private val trackPreferences: TrackPreferences = Injekt.get(), private val trackPreferences: TrackPreferences = Injekt.get(),
private val trackChapter: TrackChapter = Injekt.get(), private val trackChapter: TrackChapter = Injekt.get(),
private val getManga: GetManga = Injekt.get(), private val getManga: GetManga = Injekt.get(),
@ -211,7 +213,10 @@ class ReaderViewModel @JvmOverloads constructor(
.map(::ReaderChapter) .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() private val downloadAheadAmount = downloadPreferences.autoDownloadWhileReading().get()
init { init {