Ask for one-time incognito for nsfw manga
This commit is contained in:
@@ -123,7 +123,7 @@ class AllBookmarksFragment :
|
||||
if (selectionController?.onItemClick(item.pageId) != true) {
|
||||
val intent = ReaderIntent.Builder(view.context)
|
||||
.bookmark(item)
|
||||
.incognito(true)
|
||||
.incognito()
|
||||
.build()
|
||||
router.openReader(intent)
|
||||
Toast.makeText(view.context, R.string.incognito_mode, Toast.LENGTH_SHORT).show()
|
||||
|
||||
@@ -27,8 +27,8 @@ value class ReaderIntent private constructor(
|
||||
intent.putExtra(AppRouter.KEY_ID, mangaId)
|
||||
}
|
||||
|
||||
fun incognito(incognito: Boolean) = apply {
|
||||
intent.putExtra(EXTRA_INCOGNITO, incognito)
|
||||
fun incognito() = apply {
|
||||
intent.putExtra(EXTRA_INCOGNITO, true)
|
||||
}
|
||||
|
||||
fun branch(branch: String?) = apply {
|
||||
|
||||
@@ -214,8 +214,9 @@ class AppSettings @Inject constructor(@ApplicationContext context: Context) {
|
||||
val progressIndicatorMode: ProgressIndicatorMode
|
||||
get() = prefs.getEnumValue(KEY_PROGRESS_INDICATORS, ProgressIndicatorMode.PERCENT_READ)
|
||||
|
||||
val isHistoryExcludeNsfw: Boolean
|
||||
get() = prefs.getBoolean(KEY_HISTORY_EXCLUDE_NSFW, false)
|
||||
var incognitoModeForNsfw: TriStateOption
|
||||
get() = prefs.getEnumValue(KEY_INCOGNITO_NSFW, TriStateOption.ASK)
|
||||
set(value) = prefs.edit { putEnumValue(KEY_INCOGNITO_NSFW, value) }
|
||||
|
||||
var isIncognitoModeEnabled: Boolean
|
||||
get() = prefs.getBoolean(KEY_INCOGNITO_MODE, false)
|
||||
@@ -545,6 +546,10 @@ class AppSettings @Inject constructor(@ApplicationContext context: Context) {
|
||||
prefs.edit { putStringSet(KEY_TIPS_CLOSED, closedTips + tip) }
|
||||
}
|
||||
|
||||
fun isIncognitoModeEnabled(isNsfw: Boolean): Boolean {
|
||||
return isIncognitoModeEnabled || (isNsfw && incognitoModeForNsfw == TriStateOption.ENABLED)
|
||||
}
|
||||
|
||||
fun getPagesSaveDir(context: Context): DocumentFile? =
|
||||
prefs.getString(KEY_PAGES_SAVE_DIR, null)?.toUriOrNull()?.let {
|
||||
DocumentFile.fromTreeUri(context, it)?.takeIf { it.canWrite() }
|
||||
@@ -656,7 +661,7 @@ class AppSettings @Inject constructor(@ApplicationContext context: Context) {
|
||||
const val KEY_PROGRESS_INDICATORS = "progress_indicators"
|
||||
const val KEY_REVERSE_CHAPTERS = "reverse_chapters"
|
||||
const val KEY_GRID_VIEW_CHAPTERS = "grid_view_chapters"
|
||||
const val KEY_HISTORY_EXCLUDE_NSFW = "history_exclude_nsfw"
|
||||
const val KEY_INCOGNITO_NSFW = "incognito_nsfw"
|
||||
const val KEY_PAGES_NUMBERS = "pages_numbers"
|
||||
const val KEY_SCREENSHOTS_POLICY = "screenshots_policy"
|
||||
const val KEY_PAGES_PRELOAD = "pages_preload"
|
||||
|
||||
@@ -3,10 +3,13 @@ package org.koitharu.kotatsu.details.domain
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.distinctUntilChangedBy
|
||||
import kotlinx.coroutines.flow.filterNotNull
|
||||
import kotlinx.coroutines.flow.flatMapLatest
|
||||
import kotlinx.coroutines.flow.flowOf
|
||||
import org.koitharu.kotatsu.core.model.FavouriteCategory
|
||||
import org.koitharu.kotatsu.core.model.isNsfw
|
||||
import org.koitharu.kotatsu.core.prefs.AppSettings
|
||||
import org.koitharu.kotatsu.core.prefs.TriStateOption
|
||||
import org.koitharu.kotatsu.core.prefs.observeAsFlow
|
||||
import org.koitharu.kotatsu.details.data.MangaDetails
|
||||
import org.koitharu.kotatsu.favourites.domain.FavouritesRepository
|
||||
@@ -53,14 +56,15 @@ class DetailsInteractor @Inject constructor(
|
||||
}
|
||||
}
|
||||
|
||||
fun observeIncognitoMode(mangaFlow: Flow<Manga?>): Flow<Boolean> {
|
||||
fun observeIncognitoMode(mangaFlow: Flow<Manga?>): Flow<TriStateOption> {
|
||||
return mangaFlow
|
||||
.distinctUntilChangedBy { it?.isNsfw }
|
||||
.flatMapLatest { manga ->
|
||||
if (manga != null) {
|
||||
historyRepository.observeShouldSkip(manga)
|
||||
} else {
|
||||
settings.observeAsFlow(AppSettings.KEY_INCOGNITO_MODE) { isIncognitoModeEnabled }
|
||||
.filterNotNull()
|
||||
.distinctUntilChangedBy { it.isNsfw() }
|
||||
.combine(observeIncognitoMode()) { manga, globalIncognito ->
|
||||
when {
|
||||
globalIncognito -> TriStateOption.ENABLED
|
||||
manga.isNsfw() -> settings.incognitoModeForNsfw
|
||||
else -> TriStateOption.DISABLED
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -87,4 +91,8 @@ class DetailsInteractor @Inject constructor(
|
||||
}
|
||||
|
||||
suspend fun findRemote(seed: Manga) = localMangaRepository.getRemoteManga(seed)
|
||||
|
||||
private fun observeIncognitoMode() = settings.observeAsFlow(AppSettings.KEY_INCOGNITO_MODE) {
|
||||
isIncognitoModeEnabled
|
||||
}
|
||||
}
|
||||
|
||||
@@ -263,7 +263,7 @@ class DetailsActivity :
|
||||
}
|
||||
|
||||
override fun onItemClick(item: Bookmark, view: View) {
|
||||
router.openReader(ReaderIntent.Builder(view.context).bookmark(item).incognito(true).build())
|
||||
router.openReader(ReaderIntent.Builder(view.context).bookmark(item).incognito().build())
|
||||
Toast.makeText(view.context, R.string.incognito_mode, Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ import org.koitharu.kotatsu.core.model.getPreferredBranch
|
||||
import org.koitharu.kotatsu.core.nav.MangaIntent
|
||||
import org.koitharu.kotatsu.core.prefs.AppSettings
|
||||
import org.koitharu.kotatsu.core.prefs.ListMode
|
||||
import org.koitharu.kotatsu.core.prefs.TriStateOption
|
||||
import org.koitharu.kotatsu.core.ui.util.ReversibleAction
|
||||
import org.koitharu.kotatsu.core.util.ext.call
|
||||
import org.koitharu.kotatsu.core.util.ext.computeSize
|
||||
@@ -63,7 +64,7 @@ class DetailsViewModel @Inject constructor(
|
||||
private val scrobblers: Set<@JvmSuppressWildcards Scrobbler>,
|
||||
@LocalStorageChanges localStorageChanges: SharedFlow<LocalManga?>,
|
||||
downloadScheduler: DownloadWorker.Scheduler,
|
||||
private val interactor: DetailsInteractor,
|
||||
interactor: DetailsInteractor,
|
||||
savedStateHandle: SavedStateHandle,
|
||||
deleteLocalMangaUseCase: DeleteLocalMangaUseCase,
|
||||
private val relatedMangaUseCase: RelatedMangaUseCase,
|
||||
@@ -113,7 +114,7 @@ class DetailsViewModel @Inject constructor(
|
||||
interactor.observeIncognitoMode(manga),
|
||||
) { m, b, h, im ->
|
||||
val estimatedTime = readingTimeUseCase.invoke(m, b, h)
|
||||
HistoryInfo(m, b, h, im, estimatedTime)
|
||||
HistoryInfo(m, b, h, im == TriStateOption.ENABLED, estimatedTime)
|
||||
}.withErrorHandling()
|
||||
.stateIn(
|
||||
scope = viewModelScope + Dispatchers.Default,
|
||||
|
||||
@@ -111,13 +111,13 @@ class ReadButtonDelegate(
|
||||
Snackbar.make(buttonRead, R.string.chapter_is_missing, Snackbar.LENGTH_SHORT)
|
||||
.show() // TODO
|
||||
} else {
|
||||
router.openReader(
|
||||
ReaderIntent.Builder(context)
|
||||
.manga(manga)
|
||||
.branch(viewModel.selectedBranchValue)
|
||||
.incognito(isIncognitoMode)
|
||||
.build(),
|
||||
)
|
||||
val intentBuilder = ReaderIntent.Builder(context)
|
||||
.manga(manga)
|
||||
.branch(viewModel.selectedBranchValue)
|
||||
if (isIncognitoMode) {
|
||||
intentBuilder.incognito()
|
||||
}
|
||||
router.openReader(intentBuilder.build())
|
||||
if (isIncognitoMode) {
|
||||
Toast.makeText(context, R.string.incognito_mode, Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@ import org.koitharu.kotatsu.reader.ui.ReaderViewModel
|
||||
|
||||
abstract class ChaptersPagesViewModel(
|
||||
@JvmField protected val settings: AppSettings,
|
||||
private val interactor: DetailsInteractor,
|
||||
@JvmField protected val interactor: DetailsInteractor,
|
||||
private val bookmarksRepository: BookmarksRepository,
|
||||
private val historyRepository: HistoryRepository,
|
||||
private val downloadScheduler: DownloadWorker.Scheduler,
|
||||
|
||||
@@ -140,7 +140,7 @@ class BookmarksFragment : BaseFragment<FragmentMangaBookmarksBinding>(),
|
||||
val intent = ReaderIntent.Builder(view.context)
|
||||
.manga(activityViewModel.getMangaOrNull() ?: return)
|
||||
.bookmark(item)
|
||||
.incognito(true)
|
||||
.incognito()
|
||||
.build()
|
||||
router.openReader(intent)
|
||||
}
|
||||
|
||||
@@ -288,7 +288,7 @@ class MangaSourcesRepository @Inject constructor(
|
||||
}
|
||||
|
||||
suspend fun trackUsage(source: MangaSource) {
|
||||
if (!settings.isIncognitoModeEnabled && !(settings.isHistoryExcludeNsfw && source.isNsfw())) {
|
||||
if (!settings.isIncognitoModeEnabled(source.isNsfw())) {
|
||||
dao.setLastUsed(source.name, System.currentTimeMillis())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -201,13 +201,11 @@ class HistoryRepository @Inject constructor(
|
||||
return db.getHistoryDao().findPopularSources(limit).toMangaSources()
|
||||
}
|
||||
|
||||
fun shouldSkip(manga: Manga): Boolean {
|
||||
return ((manga.source.isNsfw() || manga.isNsfw) && settings.isHistoryExcludeNsfw) || settings.isIncognitoModeEnabled
|
||||
}
|
||||
fun shouldSkip(manga: Manga): Boolean = settings.isIncognitoModeEnabled(manga.isNsfw())
|
||||
|
||||
fun observeShouldSkip(manga: Manga): Flow<Boolean> {
|
||||
return settings.observe()
|
||||
.filter { key -> key == AppSettings.KEY_INCOGNITO_MODE || key == AppSettings.KEY_HISTORY_EXCLUDE_NSFW }
|
||||
.filter { key -> key == AppSettings.KEY_INCOGNITO_MODE || key == AppSettings.KEY_INCOGNITO_NSFW }
|
||||
.onStart { emit("") }
|
||||
.map { shouldSkip(manga) }
|
||||
.distinctUntilChanged()
|
||||
|
||||
@@ -25,7 +25,7 @@ class HistoryListQuickFilter @Inject constructor(
|
||||
add(ListFilterOption.Macro.COMPLETED)
|
||||
add(ListFilterOption.Macro.FAVORITE)
|
||||
add(ListFilterOption.NOT_FAVORITE)
|
||||
if (!settings.isNsfwContentDisabled && !settings.isHistoryExcludeNsfw) {
|
||||
if (!settings.isNsfwContentDisabled) {
|
||||
add(ListFilterOption.Macro.NSFW)
|
||||
}
|
||||
repository.getPopularTags(3).mapTo(this) {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package org.koitharu.kotatsu.reader.ui
|
||||
|
||||
import android.content.DialogInterface
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.view.Gravity
|
||||
@@ -35,6 +36,8 @@ import org.koitharu.kotatsu.core.nav.router
|
||||
import org.koitharu.kotatsu.core.prefs.AppSettings
|
||||
import org.koitharu.kotatsu.core.prefs.ReaderMode
|
||||
import org.koitharu.kotatsu.core.ui.BaseFullscreenActivity
|
||||
import org.koitharu.kotatsu.core.ui.dialog.buildAlertDialog
|
||||
import org.koitharu.kotatsu.core.ui.dialog.setCheckbox
|
||||
import org.koitharu.kotatsu.core.ui.util.MenuInvalidator
|
||||
import org.koitharu.kotatsu.core.ui.widgets.ZoomControl
|
||||
import org.koitharu.kotatsu.core.util.IdlingDetector
|
||||
@@ -145,6 +148,7 @@ class ReaderActivity :
|
||||
viewModel.isInfoBarTransparent.observe(this) { viewBinding.infoBar.drawBackground = !it }
|
||||
viewModel.isInfoBarEnabled.observe(this, ::onReaderBarChanged)
|
||||
viewModel.isBookmarkAdded.observe(this, MenuInvalidator(this))
|
||||
viewModel.onAskNsfwIncognito.observeEvent(this) { askForIncognitoMode() }
|
||||
viewModel.onShowToast.observeEvent(this) { msgId ->
|
||||
Snackbar.make(viewBinding.container, msgId, Snackbar.LENGTH_SHORT)
|
||||
.setAnchorView(viewBinding.toolbarDocked)
|
||||
@@ -432,6 +436,30 @@ class ReaderActivity :
|
||||
viewBinding.actionsView.isPrevEnabled = uiState.hasPreviousChapter()
|
||||
}
|
||||
|
||||
private fun askForIncognitoMode() {
|
||||
buildAlertDialog(this, isCentered = true) {
|
||||
var dontAskAgain = false
|
||||
val listener = DialogInterface.OnClickListener { _, which ->
|
||||
if (which == DialogInterface.BUTTON_NEUTRAL) {
|
||||
finishAfterTransition()
|
||||
} else {
|
||||
viewModel.setIncognitoMode(which == DialogInterface.BUTTON_POSITIVE, dontAskAgain)
|
||||
}
|
||||
}
|
||||
setCheckbox(R.string.dont_ask_again, dontAskAgain) { _, isChecked ->
|
||||
dontAskAgain = isChecked
|
||||
}
|
||||
setIcon(R.drawable.ic_incognito)
|
||||
setTitle(R.string.incognito_mode)
|
||||
setMessage(R.string.incognito_mode_hint_nsfw)
|
||||
setPositiveButton(R.string.incognito, listener)
|
||||
setNegativeButton(R.string.disable, listener)
|
||||
setNeutralButton(android.R.string.cancel, listener)
|
||||
setOnCancelListener { finishAfterTransition() }
|
||||
setCancelable(true)
|
||||
}.show()
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
private const val TOAST_DURATION = 2000L
|
||||
|
||||
@@ -35,10 +35,12 @@ import org.koitharu.kotatsu.core.os.AppShortcutManager
|
||||
import org.koitharu.kotatsu.core.parser.MangaDataRepository
|
||||
import org.koitharu.kotatsu.core.prefs.AppSettings
|
||||
import org.koitharu.kotatsu.core.prefs.ReaderMode
|
||||
import org.koitharu.kotatsu.core.prefs.TriStateOption
|
||||
import org.koitharu.kotatsu.core.prefs.observeAsFlow
|
||||
import org.koitharu.kotatsu.core.prefs.observeAsStateFlow
|
||||
import org.koitharu.kotatsu.core.util.ext.MutableEventFlow
|
||||
import org.koitharu.kotatsu.core.util.ext.call
|
||||
import org.koitharu.kotatsu.core.util.ext.firstNotNull
|
||||
import org.koitharu.kotatsu.core.util.ext.requireValue
|
||||
import org.koitharu.kotatsu.details.data.MangaDetails
|
||||
import org.koitharu.kotatsu.details.domain.DetailsInteractor
|
||||
@@ -112,14 +114,10 @@ class ReaderViewModel @Inject constructor(
|
||||
val readerMode = MutableStateFlow<ReaderMode?>(null)
|
||||
val onPageSaved = MutableEventFlow<Collection<Uri>>()
|
||||
val onShowToast = MutableEventFlow<Int>()
|
||||
val onAskNsfwIncognito = MutableEventFlow<Unit>()
|
||||
val uiState = MutableStateFlow<ReaderUiState?>(null)
|
||||
|
||||
val incognitoMode = if (savedStateHandle.get<Boolean>(ReaderIntent.EXTRA_INCOGNITO) == true) {
|
||||
MutableStateFlow(true)
|
||||
} else {
|
||||
interactor.observeIncognitoMode(manga)
|
||||
.stateIn(viewModelScope + Dispatchers.Default, SharingStarted.Eagerly, false)
|
||||
}
|
||||
val isIncognitoMode = MutableStateFlow(savedStateHandle.get<Boolean>(ReaderIntent.EXTRA_INCOGNITO))
|
||||
|
||||
val content = MutableStateFlow(ReaderContent(emptyList(), null))
|
||||
|
||||
@@ -191,10 +189,13 @@ class ReaderViewModel @Inject constructor(
|
||||
}.stateIn(viewModelScope + Dispatchers.Default, SharingStarted.Eagerly, false)
|
||||
|
||||
init {
|
||||
initIncognitoMode()
|
||||
loadImpl()
|
||||
launchJob(Dispatchers.Default) {
|
||||
val mangaId = manga.filterNotNull().first().id
|
||||
appShortcutManager.notifyMangaOpened(mangaId)
|
||||
if (!isIncognitoMode.firstNotNull()) {
|
||||
appShortcutManager.notifyMangaOpened(mangaId)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -228,7 +229,7 @@ class ReaderViewModel @Inject constructor(
|
||||
readingState.value = state
|
||||
savedStateHandle[ReaderIntent.EXTRA_STATE] = state
|
||||
}
|
||||
if (incognitoMode.value) {
|
||||
if (isIncognitoMode.value != false) {
|
||||
return
|
||||
}
|
||||
val readerState = state ?: readingState.value ?: return
|
||||
@@ -381,6 +382,13 @@ class ReaderViewModel @Inject constructor(
|
||||
}
|
||||
}
|
||||
|
||||
fun setIncognitoMode(value: Boolean, dontAskAgain: Boolean) {
|
||||
isIncognitoMode.value = value
|
||||
if (dontAskAgain) {
|
||||
settings.incognitoModeForNsfw = if (value) TriStateOption.ENABLED else TriStateOption.DISABLED
|
||||
}
|
||||
}
|
||||
|
||||
private fun loadImpl() {
|
||||
loadingJob = launchLoadingJob(Dispatchers.Default) {
|
||||
val details = detailsLoadUseCase.invoke(intent, force = false).first { x -> x.isLoaded }
|
||||
@@ -399,7 +407,7 @@ class ReaderViewModel @Inject constructor(
|
||||
|
||||
chaptersLoader.loadSingleChapter(requireNotNull(readingState.value).chapterId)
|
||||
// save state
|
||||
if (!incognitoMode.value) {
|
||||
if (!isIncognitoMode.firstNotNull()) {
|
||||
readingState.value?.let {
|
||||
val percent = computePercent(it.chapterId, it.page)
|
||||
historyUpdateUseCase.invoke(manga, it, percent)
|
||||
@@ -444,10 +452,10 @@ class ReaderViewModel @Inject constructor(
|
||||
totalPages = chaptersLoader.getPagesCount(chapter.id),
|
||||
currentPage = state.page,
|
||||
percent = computePercent(state.chapterId, state.page),
|
||||
incognito = incognitoMode.value,
|
||||
incognito = isIncognitoMode.value == true,
|
||||
)
|
||||
uiState.value = newState
|
||||
if (!incognitoMode.value) {
|
||||
if (isIncognitoMode.value == false) {
|
||||
statsCollector.onStateChanged(m.id, state)
|
||||
}
|
||||
}
|
||||
@@ -481,6 +489,26 @@ class ReaderViewModel @Inject constructor(
|
||||
valueProducer = { isReaderZoomButtonsEnabled },
|
||||
)
|
||||
|
||||
private fun initIncognitoMode() {
|
||||
if (isIncognitoMode.value != null) {
|
||||
return
|
||||
}
|
||||
launchJob(Dispatchers.Default) {
|
||||
interactor.observeIncognitoMode(manga)
|
||||
.collect {
|
||||
when (it) {
|
||||
TriStateOption.ENABLED -> isIncognitoMode.value = true
|
||||
TriStateOption.ASK -> {
|
||||
onAskNsfwIncognito.call(Unit)
|
||||
return@collect
|
||||
}
|
||||
|
||||
TriStateOption.DISABLED -> isIncognitoMode.value = false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun getStateFromIntent(manga: Manga): ReaderState {
|
||||
val history = historyRepository.getOne(manga)
|
||||
val preselectedBranch = selectedBranch.value
|
||||
|
||||
@@ -21,6 +21,7 @@ import org.koitharu.kotatsu.core.os.AppShortcutManager
|
||||
import org.koitharu.kotatsu.core.prefs.AppSettings
|
||||
import org.koitharu.kotatsu.core.prefs.ScreenshotsPolicy
|
||||
import org.koitharu.kotatsu.core.prefs.SearchSuggestionType
|
||||
import org.koitharu.kotatsu.core.prefs.TriStateOption
|
||||
import org.koitharu.kotatsu.core.ui.BasePreferenceFragment
|
||||
import org.koitharu.kotatsu.core.util.FileSize
|
||||
import org.koitharu.kotatsu.core.util.ext.observe
|
||||
@@ -58,6 +59,10 @@ class UserDataSettingsFragment : BasePreferenceFragment(R.string.data_and_privac
|
||||
entryValues = ScreenshotsPolicy.entries.names()
|
||||
setDefaultValueCompat(ScreenshotsPolicy.ALLOW.name)
|
||||
}
|
||||
findPreference<ListPreference>(AppSettings.KEY_INCOGNITO_NSFW)?.run {
|
||||
entryValues = TriStateOption.entries.names()
|
||||
setDefaultValueCompat(TriStateOption.ASK.name)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
|
||||
@@ -137,4 +137,9 @@
|
||||
<item>@string/favourites</item>
|
||||
<item>@string/saved_manga</item>
|
||||
</string-array>
|
||||
<string-array name="incognito_nsfw_options" translatable="false">
|
||||
<item>@string/enable</item>
|
||||
<item>@string/ask_every_time</item>
|
||||
<item>@string/disable</item>
|
||||
</string-array>
|
||||
</resources>
|
||||
|
||||
@@ -832,4 +832,7 @@
|
||||
<string name="pick_custom_file">Pick custom file</string>
|
||||
<string name="change_cover">Change cover</string>
|
||||
<string name="page_switch_timer">The page will switch every ~%d seconds</string>
|
||||
<string name="dont_ask_again">Don\'t ask again</string>
|
||||
<string name="incognito_mode_hint_nsfw">This manga may contain adult content. Do you want to use incognito mode?</string>
|
||||
<string name="incognito_for_nsfw">Incognito mode for NSFW manga</string>
|
||||
</resources>
|
||||
|
||||
@@ -17,10 +17,11 @@
|
||||
android:title="@string/screenshots_policy"
|
||||
app:useSimpleSummaryProvider="true" />
|
||||
|
||||
<SwitchPreferenceCompat
|
||||
android:key="history_exclude_nsfw"
|
||||
android:summary="@string/exclude_nsfw_from_history_summary"
|
||||
android:title="@string/exclude_nsfw_from_history" />
|
||||
<ListPreference
|
||||
android:entries="@array/incognito_nsfw_options"
|
||||
android:key="incognito_nsfw"
|
||||
android:title="@string/incognito_for_nsfw"
|
||||
app:useSimpleSummaryProvider="true" />
|
||||
|
||||
<SwitchPreferenceCompat
|
||||
android:defaultValue="true"
|
||||
|
||||
Reference in New Issue
Block a user