feat(incognito): add toggle for incognito mode in BrowseSource & SourceFeed (#902)
* feat(incognito): add `toggle for incognito` mode in BrowseSource & SourceFeed * fix null check
This commit is contained in:
parent
a862bda9d5
commit
8a2b063cd9
6 changed files with 94 additions and 24 deletions
|
|
@ -104,6 +104,7 @@ fun SourceFeedScreen(
|
||||||
// KMK -->
|
// KMK -->
|
||||||
navigateUp: () -> Unit,
|
navigateUp: () -> Unit,
|
||||||
onWebViewClick: (() -> Unit)?,
|
onWebViewClick: (() -> Unit)?,
|
||||||
|
onToggleIncognito: () -> Unit,
|
||||||
onSourceSettingClick: (() -> Unit?)?,
|
onSourceSettingClick: (() -> Unit?)?,
|
||||||
onSortFeedClick: (() -> Unit)?,
|
onSortFeedClick: (() -> Unit)?,
|
||||||
onLongClickManga: (Manga) -> Unit,
|
onLongClickManga: (Manga) -> Unit,
|
||||||
|
|
@ -145,6 +146,7 @@ fun SourceFeedScreen(
|
||||||
// KMK -->
|
// KMK -->
|
||||||
navigateUp = navigateUp,
|
navigateUp = navigateUp,
|
||||||
onWebViewClick = onWebViewClick,
|
onWebViewClick = onWebViewClick,
|
||||||
|
onToggleIncognito = onToggleIncognito,
|
||||||
onSourceSettingClick = onSourceSettingClick,
|
onSourceSettingClick = onSourceSettingClick,
|
||||||
onSortFeedClick = onSortFeedClick,
|
onSortFeedClick = onSortFeedClick,
|
||||||
toggleSelectionMode = bulkFavoriteScreenModel::toggleSelectionMode,
|
toggleSelectionMode = bulkFavoriteScreenModel::toggleSelectionMode,
|
||||||
|
|
@ -298,6 +300,7 @@ fun SourceFeedToolbar(
|
||||||
// KMK -->
|
// KMK -->
|
||||||
navigateUp: () -> Unit,
|
navigateUp: () -> Unit,
|
||||||
onWebViewClick: (() -> Unit)?,
|
onWebViewClick: (() -> Unit)?,
|
||||||
|
onToggleIncognito: () -> Unit,
|
||||||
onSourceSettingClick: (() -> Unit?)?,
|
onSourceSettingClick: (() -> Unit?)?,
|
||||||
onSortFeedClick: (() -> Unit)?,
|
onSortFeedClick: (() -> Unit)?,
|
||||||
toggleSelectionMode: () -> Unit,
|
toggleSelectionMode: () -> Unit,
|
||||||
|
|
@ -332,6 +335,15 @@ fun SourceFeedToolbar(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// KMK -->
|
||||||
|
add(
|
||||||
|
AppBar.OverflowAction(
|
||||||
|
title = stringResource(MR.strings.pref_incognito_mode),
|
||||||
|
onClick = onToggleIncognito,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
// KMK <--
|
||||||
|
|
||||||
onSortFeedClick?.let {
|
onSortFeedClick?.let {
|
||||||
add(
|
add(
|
||||||
AppBar.OverflowAction(
|
AppBar.OverflowAction(
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@ import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.automirrored.filled.ViewList
|
import androidx.compose.material.icons.automirrored.filled.ViewList
|
||||||
import androidx.compose.material.icons.automirrored.outlined.Help
|
import androidx.compose.material.icons.automirrored.outlined.Help
|
||||||
import androidx.compose.material.icons.filled.ViewModule
|
import androidx.compose.material.icons.filled.ViewModule
|
||||||
import androidx.compose.material.icons.outlined.Public
|
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.material3.TopAppBarScrollBehavior
|
import androidx.compose.material3.TopAppBarScrollBehavior
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
|
@ -39,6 +38,7 @@ fun BrowseSourceToolbar(
|
||||||
onWebViewClick: () -> Unit,
|
onWebViewClick: () -> Unit,
|
||||||
onHelpClick: () -> Unit,
|
onHelpClick: () -> Unit,
|
||||||
// KMK -->
|
// KMK -->
|
||||||
|
onToggleIncognito: () -> Unit,
|
||||||
onSettingsClick: (() -> Unit)?,
|
onSettingsClick: (() -> Unit)?,
|
||||||
// KMK <--
|
// KMK <--
|
||||||
onSearch: (String) -> Unit,
|
onSearch: (String) -> Unit,
|
||||||
|
|
@ -100,22 +100,20 @@ fun BrowseSourceToolbar(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (isConfigurableSource && displayMode != null) {
|
// KMK -->
|
||||||
|
add(
|
||||||
|
AppBar.OverflowAction(
|
||||||
|
title = stringResource(MR.strings.pref_incognito_mode),
|
||||||
|
onClick = onToggleIncognito,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
// KMK <--
|
||||||
add(
|
add(
|
||||||
AppBar.OverflowAction(
|
AppBar.OverflowAction(
|
||||||
title = stringResource(MR.strings.action_web_view),
|
title = stringResource(MR.strings.action_web_view),
|
||||||
onClick = onWebViewClick,
|
onClick = onWebViewClick,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
} else {
|
|
||||||
add(
|
|
||||||
AppBar.Action(
|
|
||||||
title = stringResource(MR.strings.action_web_view),
|
|
||||||
icon = Icons.Outlined.Public,
|
|
||||||
onClick = onWebViewClick,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// SY <--
|
// SY <--
|
||||||
// KMK -->
|
// KMK -->
|
||||||
|
|
|
||||||
|
|
@ -227,6 +227,7 @@ data class BrowseSourceScreen(
|
||||||
onWebViewClick = onWebViewClick,
|
onWebViewClick = onWebViewClick,
|
||||||
onHelpClick = onHelpClick,
|
onHelpClick = onHelpClick,
|
||||||
// KMK -->
|
// KMK -->
|
||||||
|
onToggleIncognito = screenModel::toggleIncognitoMode,
|
||||||
onSettingsClick = {
|
onSettingsClick = {
|
||||||
when {
|
when {
|
||||||
screenModel.source.isEhBasedSource() && isHentaiEnabled ->
|
screenModel.source.isEhBasedSource() && isHentaiEnabled ->
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import android.content.res.Configuration
|
||||||
import androidx.compose.foundation.lazy.grid.GridCells
|
import androidx.compose.foundation.lazy.grid.GridCells
|
||||||
import androidx.compose.runtime.Immutable
|
import androidx.compose.runtime.Immutable
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.paging.Pager
|
import androidx.paging.Pager
|
||||||
|
|
@ -18,18 +19,22 @@ import eu.kanade.core.preference.asState
|
||||||
import eu.kanade.domain.manga.interactor.UpdateManga
|
import eu.kanade.domain.manga.interactor.UpdateManga
|
||||||
import eu.kanade.domain.source.interactor.GetExhSavedSearch
|
import eu.kanade.domain.source.interactor.GetExhSavedSearch
|
||||||
import eu.kanade.domain.source.interactor.GetIncognitoState
|
import eu.kanade.domain.source.interactor.GetIncognitoState
|
||||||
|
import eu.kanade.domain.source.interactor.ToggleIncognito
|
||||||
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.domain.ui.UiPreferences
|
import eu.kanade.domain.ui.UiPreferences
|
||||||
import eu.kanade.presentation.util.ioCoroutineScope
|
import eu.kanade.presentation.util.ioCoroutineScope
|
||||||
import eu.kanade.tachiyomi.data.cache.CoverCache
|
import eu.kanade.tachiyomi.data.cache.CoverCache
|
||||||
|
import eu.kanade.tachiyomi.extension.ExtensionManager
|
||||||
import eu.kanade.tachiyomi.source.CatalogueSource
|
import eu.kanade.tachiyomi.source.CatalogueSource
|
||||||
import eu.kanade.tachiyomi.source.model.FilterList
|
import eu.kanade.tachiyomi.source.model.FilterList
|
||||||
import eu.kanade.tachiyomi.source.online.MetadataSource
|
import eu.kanade.tachiyomi.source.online.MetadataSource
|
||||||
import eu.kanade.tachiyomi.source.online.all.MangaDex
|
import eu.kanade.tachiyomi.source.online.all.MangaDex
|
||||||
import eu.kanade.tachiyomi.util.removeCovers
|
import eu.kanade.tachiyomi.util.removeCovers
|
||||||
import exh.metadata.metadata.RaisedSearchMetadata
|
import exh.metadata.metadata.RaisedSearchMetadata
|
||||||
|
import exh.source.EH_PACKAGE
|
||||||
import exh.source.getMainSource
|
import exh.source.getMainSource
|
||||||
|
import exh.source.isEhBasedSource
|
||||||
import kotlinx.collections.immutable.ImmutableList
|
import kotlinx.collections.immutable.ImmutableList
|
||||||
import kotlinx.collections.immutable.persistentListOf
|
import kotlinx.collections.immutable.persistentListOf
|
||||||
import kotlinx.collections.immutable.toImmutableList
|
import kotlinx.collections.immutable.toImmutableList
|
||||||
|
|
@ -72,6 +77,7 @@ import tachiyomi.domain.source.interactor.GetRemoteManga
|
||||||
import tachiyomi.domain.source.interactor.InsertSavedSearch
|
import tachiyomi.domain.source.interactor.InsertSavedSearch
|
||||||
import tachiyomi.domain.source.model.EXHSavedSearch
|
import tachiyomi.domain.source.model.EXHSavedSearch
|
||||||
import tachiyomi.domain.source.model.SavedSearch
|
import tachiyomi.domain.source.model.SavedSearch
|
||||||
|
import tachiyomi.domain.source.model.StubSource
|
||||||
import tachiyomi.domain.source.repository.SourcePagingSource
|
import tachiyomi.domain.source.repository.SourcePagingSource
|
||||||
import tachiyomi.domain.source.service.SourceManager
|
import tachiyomi.domain.source.service.SourceManager
|
||||||
import tachiyomi.i18n.sy.SYMR
|
import tachiyomi.i18n.sy.SYMR
|
||||||
|
|
@ -101,6 +107,10 @@ open class BrowseSourceScreenModel(
|
||||||
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(),
|
private val getIncognitoState: GetIncognitoState = Injekt.get(),
|
||||||
|
// KMK -->
|
||||||
|
private val toggleIncognito: ToggleIncognito = Injekt.get(),
|
||||||
|
private val extensionManager: ExtensionManager = Injekt.get(),
|
||||||
|
// KMK <--
|
||||||
|
|
||||||
// SY -->
|
// SY -->
|
||||||
unsortedPreferences: UnsortedPreferences = Injekt.get(),
|
unsortedPreferences: UnsortedPreferences = Injekt.get(),
|
||||||
|
|
@ -124,6 +134,10 @@ open class BrowseSourceScreenModel(
|
||||||
private val filterSerializer = FilterSerializer()
|
private val filterSerializer = FilterSerializer()
|
||||||
// SY <--
|
// SY <--
|
||||||
|
|
||||||
|
// KMK -->
|
||||||
|
var incognitoMode = mutableStateOf(getIncognitoState.await(source.id))
|
||||||
|
// KMK <--
|
||||||
|
|
||||||
init {
|
init {
|
||||||
// KMK -->
|
// KMK -->
|
||||||
screenModelScope.launch {
|
screenModelScope.launch {
|
||||||
|
|
@ -155,10 +169,6 @@ open class BrowseSourceScreenModel(
|
||||||
}
|
}
|
||||||
}.join()
|
}.join()
|
||||||
|
|
||||||
if (!getIncognitoState.await(source.id)) {
|
|
||||||
sourcePreferences.lastUsedSource().set(source.id)
|
|
||||||
}
|
|
||||||
|
|
||||||
// SY -->
|
// SY -->
|
||||||
val savedSearchId = savedSearch
|
val savedSearchId = savedSearch
|
||||||
val jsonFilters = filtersJson
|
val jsonFilters = filtersJson
|
||||||
|
|
@ -189,9 +199,31 @@ open class BrowseSourceScreenModel(
|
||||||
}
|
}
|
||||||
.launchIn(screenModelScope)
|
.launchIn(screenModelScope)
|
||||||
// SY <--
|
// SY <--
|
||||||
|
|
||||||
|
// KMK-->
|
||||||
|
getIncognitoState.subscribe(sourceId)
|
||||||
|
.onEach {
|
||||||
|
if (!it) sourcePreferences.lastUsedSource().set(source.id)
|
||||||
|
incognitoMode.value = it
|
||||||
|
}
|
||||||
|
.launchIn(screenModelScope)
|
||||||
|
// KMK <--
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// KMK -->
|
||||||
|
fun toggleIncognitoMode() {
|
||||||
|
val packageName = when {
|
||||||
|
source is StubSource -> null
|
||||||
|
source.isEhBasedSource() -> EH_PACKAGE
|
||||||
|
else -> extensionManager.getExtensionPackage(sourceId)
|
||||||
|
}
|
||||||
|
packageName?.let {
|
||||||
|
toggleIncognito.await(it, !incognitoMode.value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// KMK <--
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Flow of Pager flow tied to [State.listing]
|
* Flow of Pager flow tied to [State.listing]
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -148,6 +148,7 @@ class SourceFeedScreen(val sourceId: Long) : Screen() {
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
}.takeIf { screenModel.source is HttpSource },
|
}.takeIf { screenModel.source is HttpSource },
|
||||||
|
onToggleIncognito = screenModel::toggleIncognitoMode,
|
||||||
onSourceSettingClick = {
|
onSourceSettingClick = {
|
||||||
when {
|
when {
|
||||||
screenModel.source.isEhBasedSource() && isHentaiEnabled ->
|
screenModel.source.isEhBasedSource() && isHentaiEnabled ->
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.Immutable
|
import androidx.compose.runtime.Immutable
|
||||||
import androidx.compose.runtime.State
|
import androidx.compose.runtime.State
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.produceState
|
import androidx.compose.runtime.produceState
|
||||||
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
|
||||||
|
|
@ -11,14 +12,18 @@ import dev.icerock.moko.resources.StringResource
|
||||||
import eu.kanade.core.preference.asState
|
import eu.kanade.core.preference.asState
|
||||||
import eu.kanade.domain.source.interactor.GetExhSavedSearch
|
import eu.kanade.domain.source.interactor.GetExhSavedSearch
|
||||||
import eu.kanade.domain.source.interactor.GetIncognitoState
|
import eu.kanade.domain.source.interactor.GetIncognitoState
|
||||||
|
import eu.kanade.domain.source.interactor.ToggleIncognito
|
||||||
import eu.kanade.domain.source.service.SourcePreferences
|
import eu.kanade.domain.source.service.SourcePreferences
|
||||||
import eu.kanade.domain.ui.UiPreferences
|
import eu.kanade.domain.ui.UiPreferences
|
||||||
import eu.kanade.presentation.browse.SourceFeedUI
|
import eu.kanade.presentation.browse.SourceFeedUI
|
||||||
|
import eu.kanade.tachiyomi.extension.ExtensionManager
|
||||||
import eu.kanade.tachiyomi.source.CatalogueSource
|
import eu.kanade.tachiyomi.source.CatalogueSource
|
||||||
import eu.kanade.tachiyomi.source.model.FilterList
|
import eu.kanade.tachiyomi.source.model.FilterList
|
||||||
import eu.kanade.tachiyomi.source.online.all.MangaDex
|
import eu.kanade.tachiyomi.source.online.all.MangaDex
|
||||||
import eu.kanade.tachiyomi.ui.browse.feed.MaxFeedItems
|
import eu.kanade.tachiyomi.ui.browse.feed.MaxFeedItems
|
||||||
|
import exh.source.EH_PACKAGE
|
||||||
import exh.source.getMainSource
|
import exh.source.getMainSource
|
||||||
|
import exh.source.isEhBasedSource
|
||||||
import exh.source.mangaDexSourceIds
|
import exh.source.mangaDexSourceIds
|
||||||
import exh.util.nullIfBlank
|
import exh.util.nullIfBlank
|
||||||
import kotlinx.collections.immutable.ImmutableList
|
import kotlinx.collections.immutable.ImmutableList
|
||||||
|
|
@ -51,6 +56,7 @@ import tachiyomi.domain.source.interactor.ReorderFeed
|
||||||
import tachiyomi.domain.source.model.EXHSavedSearch
|
import tachiyomi.domain.source.model.EXHSavedSearch
|
||||||
import tachiyomi.domain.source.model.FeedSavedSearch
|
import tachiyomi.domain.source.model.FeedSavedSearch
|
||||||
import tachiyomi.domain.source.model.SavedSearch
|
import tachiyomi.domain.source.model.SavedSearch
|
||||||
|
import tachiyomi.domain.source.model.StubSource
|
||||||
import tachiyomi.domain.source.service.SourceManager
|
import tachiyomi.domain.source.service.SourceManager
|
||||||
import tachiyomi.i18n.kmk.KMR
|
import tachiyomi.i18n.kmk.KMR
|
||||||
import tachiyomi.i18n.sy.SYMR
|
import tachiyomi.i18n.sy.SYMR
|
||||||
|
|
@ -75,6 +81,8 @@ open class SourceFeedScreenModel(
|
||||||
// KMK -->
|
// KMK -->
|
||||||
private val reorderFeed: ReorderFeed = Injekt.get(),
|
private val reorderFeed: ReorderFeed = Injekt.get(),
|
||||||
private val getIncognitoState: GetIncognitoState = Injekt.get(),
|
private val getIncognitoState: GetIncognitoState = Injekt.get(),
|
||||||
|
private val toggleIncognito: ToggleIncognito = Injekt.get(),
|
||||||
|
private val extensionManager: ExtensionManager = Injekt.get(),
|
||||||
sourcePreferences: SourcePreferences = Injekt.get(),
|
sourcePreferences: SourcePreferences = Injekt.get(),
|
||||||
// KMK <--
|
// KMK <--
|
||||||
) : StateScreenModel<SourceFeedState>(SourceFeedState()) {
|
) : StateScreenModel<SourceFeedState>(SourceFeedState()) {
|
||||||
|
|
@ -87,6 +95,10 @@ open class SourceFeedScreenModel(
|
||||||
|
|
||||||
val startExpanded by uiPreferences.expandFilters().asState(screenModelScope)
|
val startExpanded by uiPreferences.expandFilters().asState(screenModelScope)
|
||||||
|
|
||||||
|
// KMK -->
|
||||||
|
var incognitoMode = mutableStateOf(getIncognitoState.await(source.id))
|
||||||
|
// KMK <--
|
||||||
|
|
||||||
init {
|
init {
|
||||||
// KMK -->
|
// KMK -->
|
||||||
screenModelScope.launch {
|
screenModelScope.launch {
|
||||||
|
|
@ -104,9 +116,12 @@ open class SourceFeedScreenModel(
|
||||||
// KMK -->
|
// KMK -->
|
||||||
reloadSavedSearches()
|
reloadSavedSearches()
|
||||||
|
|
||||||
if (!getIncognitoState.await(source.id)) {
|
getIncognitoState.subscribe(sourceId)
|
||||||
sourcePreferences.lastUsedSource().set(source.id)
|
.onEach {
|
||||||
|
if (!it) sourcePreferences.lastUsedSource().set(source.id)
|
||||||
|
incognitoMode.value = it
|
||||||
}
|
}
|
||||||
|
.launchIn(screenModelScope)
|
||||||
// KMK <--
|
// KMK <--
|
||||||
getFeedSavedSearchBySourceId.subscribe(source.id)
|
getFeedSavedSearchBySourceId.subscribe(source.id)
|
||||||
.onEach {
|
.onEach {
|
||||||
|
|
@ -123,6 +138,17 @@ open class SourceFeedScreenModel(
|
||||||
}
|
}
|
||||||
|
|
||||||
// KMK-->
|
// KMK-->
|
||||||
|
fun toggleIncognitoMode() {
|
||||||
|
val packageName = when {
|
||||||
|
source is StubSource -> null
|
||||||
|
source.isEhBasedSource() -> EH_PACKAGE
|
||||||
|
else -> extensionManager.getExtensionPackage(sourceId)
|
||||||
|
}
|
||||||
|
packageName?.let {
|
||||||
|
toggleIncognito.await(it, !incognitoMode.value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun resetFilters() {
|
fun resetFilters() {
|
||||||
val source = source
|
val source = source
|
||||||
if (source !is CatalogueSource) return
|
if (source !is CatalogueSource) return
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue