mirror of
https://github.com/mihonapp/mihon.git
synced 2025-02-21 06:29:00 +01:00
add per Extension Incognito Mode
This commit is contained in:
parent
38d6ab80ce
commit
748ed867c5
@ -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()
|
||||||
}
|
}
|
||||||
|
@ -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(
|
||||||
|
@ -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()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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) {
|
||||||
|
@ -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
|
||||||
|
@ -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) {
|
||||||
|
@ -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) {
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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 {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user