Incognito mode indicator in reader

master
Koitharu 2 years ago
parent d56fc674ab
commit db1ddf539c
Signed by: Koitharu
GPG Key ID: 676DEE768C17A9D7

@ -8,9 +8,11 @@ import androidx.annotation.AttrRes
import androidx.annotation.ColorInt import androidx.annotation.ColorInt
import androidx.annotation.FloatRange import androidx.annotation.FloatRange
import androidx.annotation.Px import androidx.annotation.Px
import androidx.annotation.StyleRes
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.core.content.res.use import androidx.core.content.res.use
import androidx.core.graphics.ColorUtils import androidx.core.graphics.ColorUtils
import com.google.android.material.R as materialR
fun Context.getThemeDrawable( fun Context.getThemeDrawable(
@AttrRes resId: Int, @AttrRes resId: Int,
@ -75,3 +77,7 @@ fun TypedArray.getDrawableCompat(context: Context, index: Int): Drawable? {
val resId = getResourceId(index, 0) val resId = getResourceId(index, 0)
return if (resId != 0) ContextCompat.getDrawable(context, resId) else null return if (resId != 0) ContextCompat.getDrawable(context, resId) else null
} }
@get:StyleRes
val DIALOG_THEME_CENTERED: Int
inline get() = materialR.style.ThemeOverlay_Material3_MaterialAlertDialog_Centered

@ -7,6 +7,7 @@ import android.view.MenuItem
import androidx.core.view.MenuProvider import androidx.core.view.MenuProvider
import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.dialog.MaterialAlertDialogBuilder
import org.koitharu.kotatsu.R import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.util.ext.DIALOG_THEME_CENTERED
import org.koitharu.kotatsu.settings.SettingsActivity import org.koitharu.kotatsu.settings.SettingsActivity
class DownloadsMenuProvider( class DownloadsMenuProvider(
@ -41,10 +42,8 @@ class DownloadsMenuProvider(
} }
private fun confirmCancelAll() { private fun confirmCancelAll() {
MaterialAlertDialogBuilder( MaterialAlertDialogBuilder(context, DIALOG_THEME_CENTERED)
context, .setTitle(R.string.cancel_all)
com.google.android.material.R.style.ThemeOverlay_Material3_MaterialAlertDialog_Centered,
).setTitle(R.string.cancel_all)
.setMessage(R.string.cancel_all_downloads_confirm) .setMessage(R.string.cancel_all_downloads_confirm)
.setIcon(R.drawable.ic_cancel_multiple) .setIcon(R.drawable.ic_cancel_multiple)
.setNegativeButton(android.R.string.cancel, null) .setNegativeButton(android.R.string.cancel, null)
@ -54,10 +53,8 @@ class DownloadsMenuProvider(
} }
private fun confirmRemoveCompleted() { private fun confirmRemoveCompleted() {
MaterialAlertDialogBuilder( MaterialAlertDialogBuilder(context, DIALOG_THEME_CENTERED)
context, .setTitle(R.string.remove_completed)
com.google.android.material.R.style.ThemeOverlay_Material3_MaterialAlertDialog_Centered,
).setTitle(R.string.remove_completed)
.setMessage(R.string.remove_completed_downloads_confirm) .setMessage(R.string.remove_completed_downloads_confirm)
.setIcon(R.drawable.ic_clear_all) .setIcon(R.drawable.ic_clear_all)
.setNegativeButton(android.R.string.cancel, null) .setNegativeButton(android.R.string.cancel, null)

@ -7,7 +7,7 @@ import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.dialog.MaterialAlertDialogBuilder
import org.koitharu.kotatsu.R import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.ui.list.ListSelectionController import org.koitharu.kotatsu.core.ui.list.ListSelectionController
import com.google.android.material.R as materialR import org.koitharu.kotatsu.core.util.ext.DIALOG_THEME_CENTERED
class CategoriesSelectionCallback( class CategoriesSelectionCallback(
private val recyclerView: RecyclerView, private val recyclerView: RecyclerView,
@ -75,7 +75,7 @@ class CategoriesSelectionCallback(
private fun confirmDeleteCategories(ids: Set<Long>, mode: ActionMode) { private fun confirmDeleteCategories(ids: Set<Long>, mode: ActionMode) {
val context = recyclerView.context val context = recyclerView.context
MaterialAlertDialogBuilder(context, materialR.style.ThemeOverlay_Material3_MaterialAlertDialog_Centered) MaterialAlertDialogBuilder(context, DIALOG_THEME_CENTERED)
.setMessage(R.string.categories_delete_confirm) .setMessage(R.string.categories_delete_confirm)
.setTitle(R.string.remove_category) .setTitle(R.string.remove_category)
.setIcon(R.drawable.ic_delete) .setIcon(R.drawable.ic_delete)

@ -7,6 +7,7 @@ import android.view.MenuItem
import androidx.core.view.MenuProvider import androidx.core.view.MenuProvider
import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.dialog.MaterialAlertDialogBuilder
import org.koitharu.kotatsu.R import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.util.ext.DIALOG_THEME_CENTERED
import org.koitharu.kotatsu.favourites.ui.categories.edit.FavouritesCategoryEditActivity import org.koitharu.kotatsu.favourites.ui.categories.edit.FavouritesCategoryEditActivity
import org.koitharu.kotatsu.favourites.ui.list.FavouritesListFragment.Companion.NO_ID import org.koitharu.kotatsu.favourites.ui.list.FavouritesListFragment.Companion.NO_ID
@ -40,10 +41,8 @@ class FavouriteTabPopupMenuProvider(
} }
private fun confirmDelete() { private fun confirmDelete() {
MaterialAlertDialogBuilder( MaterialAlertDialogBuilder(context, DIALOG_THEME_CENTERED)
context, .setMessage(R.string.categories_delete_confirm)
com.google.android.material.R.style.ThemeOverlay_Material3_MaterialAlertDialog_Centered,
).setMessage(R.string.categories_delete_confirm)
.setTitle(R.string.remove_category) .setTitle(R.string.remove_category)
.setIcon(R.drawable.ic_delete) .setIcon(R.drawable.ic_delete)
.setNegativeButton(android.R.string.cancel, null) .setNegativeButton(android.R.string.cancel, null)

@ -15,6 +15,7 @@ import org.koitharu.kotatsu.core.db.entity.toMangaTags
import org.koitharu.kotatsu.core.model.MangaHistory import org.koitharu.kotatsu.core.model.MangaHistory
import org.koitharu.kotatsu.core.model.findById import org.koitharu.kotatsu.core.model.findById
import org.koitharu.kotatsu.core.model.isLocal import org.koitharu.kotatsu.core.model.isLocal
import org.koitharu.kotatsu.core.model.isNsfw
import org.koitharu.kotatsu.core.parser.MangaDataRepository import org.koitharu.kotatsu.core.parser.MangaDataRepository
import org.koitharu.kotatsu.core.prefs.AppSettings import org.koitharu.kotatsu.core.prefs.AppSettings
import org.koitharu.kotatsu.core.ui.util.ReversibleHandle import org.koitharu.kotatsu.core.ui.util.ReversibleHandle
@ -161,7 +162,7 @@ class HistoryRepository @Inject constructor(
} }
fun shouldSkip(manga: Manga): Boolean { fun shouldSkip(manga: Manga): Boolean {
return manga.isNsfw && settings.isHistoryExcludeNsfw || settings.isIncognitoModeEnabled return ((manga.source.isNsfw() || manga.isNsfw) && settings.isHistoryExcludeNsfw) || settings.isIncognitoModeEnabled
} }
fun observeShouldSkip(manga: Manga): Flow<Boolean> { fun observeShouldSkip(manga: Manga): Flow<Boolean> {

@ -8,6 +8,7 @@ import androidx.core.view.MenuProvider
import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.dialog.MaterialAlertDialogBuilder
import org.koitharu.kotatsu.R import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.ui.dialog.RememberSelectionDialogListener import org.koitharu.kotatsu.core.ui.dialog.RememberSelectionDialogListener
import org.koitharu.kotatsu.core.util.ext.DIALOG_THEME_CENTERED
import java.time.Instant import java.time.Instant
import java.time.LocalDate import java.time.LocalDate
import java.time.ZoneId import java.time.ZoneId
@ -36,7 +37,7 @@ class HistoryListMenuProvider(
private fun showClearHistoryDialog() { private fun showClearHistoryDialog() {
val selectionListener = RememberSelectionDialogListener(2) val selectionListener = RememberSelectionDialogListener(2)
MaterialAlertDialogBuilder(context, materialR.style.ThemeOverlay_Material3_MaterialAlertDialog_Centered) MaterialAlertDialogBuilder(context, DIALOG_THEME_CENTERED)
.setTitle(R.string.clear_history) .setTitle(R.string.clear_history)
.setSingleChoiceItems( .setSingleChoiceItems(
arrayOf( arrayOf(

@ -10,7 +10,6 @@ import android.transition.TransitionManager
import android.transition.TransitionSet import android.transition.TransitionSet
import android.view.Gravity import android.view.Gravity
import android.view.KeyEvent import android.view.KeyEvent
import android.view.Menu
import android.view.MenuItem import android.view.MenuItem
import android.view.MotionEvent import android.view.MotionEvent
import android.view.View import android.view.View
@ -40,6 +39,7 @@ import org.koitharu.kotatsu.core.parser.MangaIntent
import org.koitharu.kotatsu.core.prefs.AppSettings import org.koitharu.kotatsu.core.prefs.AppSettings
import org.koitharu.kotatsu.core.prefs.ReaderMode import org.koitharu.kotatsu.core.prefs.ReaderMode
import org.koitharu.kotatsu.core.ui.BaseFullscreenActivity import org.koitharu.kotatsu.core.ui.BaseFullscreenActivity
import org.koitharu.kotatsu.core.ui.util.MenuInvalidator
import org.koitharu.kotatsu.core.ui.widgets.ZoomControl import org.koitharu.kotatsu.core.ui.widgets.ZoomControl
import org.koitharu.kotatsu.core.util.GridTouchHelper import org.koitharu.kotatsu.core.util.GridTouchHelper
import org.koitharu.kotatsu.core.util.IdlingDetector import org.koitharu.kotatsu.core.util.IdlingDetector
@ -140,6 +140,7 @@ class ReaderActivity :
viewModel.content.observe(this) { viewModel.content.observe(this) {
onLoadingStateChanged(viewModel.isLoading.value) onLoadingStateChanged(viewModel.isLoading.value)
} }
viewModel.incognitoMode.observe(this, MenuInvalidator(this))
viewModel.isScreenshotsBlockEnabled.observe(this, this::setWindowSecure) viewModel.isScreenshotsBlockEnabled.observe(this, this::setWindowSecure)
viewModel.isKeepScreenOnEnabled.observe(this, this::setKeepScreenOn) viewModel.isKeepScreenOnEnabled.observe(this, this::setKeepScreenOn)
viewModel.isInfoBarEnabled.observe(this, ::onReaderBarChanged) viewModel.isInfoBarEnabled.observe(this, ::onReaderBarChanged)
@ -152,6 +153,7 @@ class ReaderActivity :
viewModel.isZoomControlsEnabled.observe(this) { viewModel.isZoomControlsEnabled.observe(this) {
viewBinding.zoomControl.isVisible = it viewBinding.zoomControl.isVisible = it
} }
addMenuProvider(ReaderTopMenuProvider(this, viewModel))
} }
override fun getParentActivityIntent(): Intent? { override fun getParentActivityIntent(): Intent? {
@ -190,21 +192,12 @@ class ReaderActivity :
viewBinding.slider.isRtl = mode == ReaderMode.REVERSED viewBinding.slider.isRtl = mode == ReaderMode.REVERSED
} }
override fun onCreateOptionsMenu(menu: Menu): Boolean {
menuInflater.inflate(R.menu.opt_reader_top, menu)
return super.onCreateOptionsMenu(menu)
}
override fun onOptionsItemSelected(item: MenuItem): Boolean { override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) { when (item.itemId) {
R.id.action_settings -> { R.id.action_settings -> {
startActivity(SettingsActivity.newReaderSettingsIntent(this)) startActivity(SettingsActivity.newReaderSettingsIntent(this))
} }
R.id.action_chapters -> {
ChaptersSheet.show(supportFragmentManager)
}
R.id.action_pages_thumbs -> { R.id.action_pages_thumbs -> {
val state = viewModel.getCurrentState() ?: return false val state = viewModel.getCurrentState() ?: return false
PagesThumbnailsSheet.show( PagesThumbnailsSheet.show(

@ -0,0 +1,48 @@
package org.koitharu.kotatsu.reader.ui
import android.view.Menu
import android.view.MenuInflater
import android.view.MenuItem
import androidx.core.view.MenuProvider
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.util.ext.DIALOG_THEME_CENTERED
class ReaderTopMenuProvider(
private val activity: ReaderActivity,
private val viewModel: ReaderViewModel,
) : MenuProvider {
override fun onCreateMenu(menu: Menu, menuInflater: MenuInflater) {
menuInflater.inflate(R.menu.opt_reader_top, menu)
}
override fun onPrepareMenu(menu: Menu) {
menu.findItem(R.id.action_incognito)?.isVisible = viewModel.incognitoMode.value
}
override fun onMenuItemSelected(menuItem: MenuItem): Boolean {
return when (menuItem.itemId) {
R.id.action_chapters -> {
ChaptersSheet.show(activity.supportFragmentManager)
true
}
R.id.action_incognito -> {
showIncognitoModeDialog()
true
}
else -> false
}
}
private fun showIncognitoModeDialog() {
MaterialAlertDialogBuilder(activity, DIALOG_THEME_CENTERED)
.setIcon(R.drawable.ic_incognito)
.setTitle(R.string.incognito_mode)
.setMessage(R.string.incognito_mode_hint)
.setPositiveButton(R.string.got_it, null)
.show()
}
}

@ -96,6 +96,12 @@ class ReaderViewModel @Inject constructor(
val onShowToast = MutableEventFlow<Int>() val onShowToast = MutableEventFlow<Int>()
val uiState = MutableStateFlow<ReaderUiState?>(null) val uiState = MutableStateFlow<ReaderUiState?>(null)
val incognitoMode = if (isIncognito) {
MutableStateFlow(true)
} else mangaFlow.map {
it != null && historyRepository.shouldSkip(it)
}.stateIn(viewModelScope + Dispatchers.Default, SharingStarted.Eagerly, false)
val content = MutableStateFlow(ReaderContent(emptyList(), null)) val content = MutableStateFlow(ReaderContent(emptyList(), null))
val manga: MangaDetails? val manga: MangaDetails?
get() = mangaData.value get() = mangaData.value

@ -8,6 +8,7 @@ import androidx.activity.result.ActivityResultLauncher
import androidx.core.view.MenuProvider import androidx.core.view.MenuProvider
import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.dialog.MaterialAlertDialogBuilder
import org.koitharu.kotatsu.R import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.util.ext.DIALOG_THEME_CENTERED
import org.koitharu.kotatsu.core.util.ext.resolve import org.koitharu.kotatsu.core.util.ext.resolve
import org.koitharu.kotatsu.core.util.ext.tryLaunch import org.koitharu.kotatsu.core.util.ext.tryLaunch
import com.google.android.material.R as materialR import com.google.android.material.R as materialR
@ -43,7 +44,7 @@ class SearchSuggestionMenuProvider(
} }
private fun clearSearchHistory() { private fun clearSearchHistory() {
MaterialAlertDialogBuilder(context, materialR.style.ThemeOverlay_Material3_MaterialAlertDialog_Centered) MaterialAlertDialogBuilder(context, DIALOG_THEME_CENTERED)
.setTitle(R.string.clear_search_history) .setTitle(R.string.clear_search_history)
.setIcon(R.drawable.ic_clear_all) .setIcon(R.drawable.ic_clear_all)
.setMessage(R.string.text_clear_search_history_prompt) .setMessage(R.string.text_clear_search_history_prompt)

@ -16,8 +16,8 @@ import io.noties.markwon.Markwon
import org.koitharu.kotatsu.R import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.github.AppVersion import org.koitharu.kotatsu.core.github.AppVersion
import org.koitharu.kotatsu.core.util.FileSize import org.koitharu.kotatsu.core.util.FileSize
import org.koitharu.kotatsu.core.util.ext.DIALOG_THEME_CENTERED
import org.koitharu.kotatsu.core.util.ext.getDisplayMessage import org.koitharu.kotatsu.core.util.ext.getDisplayMessage
import com.google.android.material.R as materialR
class AppUpdateDialog(private val activity: AppCompatActivity) { class AppUpdateDialog(private val activity: AppCompatActivity) {
@ -43,10 +43,7 @@ class AppUpdateDialog(private val activity: AppCompatActivity) {
appendLine() appendLine()
append(Markwon.create(activity).toMarkdown(version.description)) append(Markwon.create(activity).toMarkdown(version.description))
} }
MaterialAlertDialogBuilder( MaterialAlertDialogBuilder(activity, DIALOG_THEME_CENTERED)
activity,
materialR.style.ThemeOverlay_Material3_MaterialAlertDialog_Centered,
)
.setTitle(R.string.app_update_available) .setTitle(R.string.app_update_available)
.setMessage(message) .setMessage(message)
.setIcon(R.drawable.ic_app_update) .setIcon(R.drawable.ic_app_update)

@ -1,13 +1,22 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<menu <menu
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"> xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:ignore="AlwaysShowAction">
<item <item
android:id="@+id/action_chapters" android:id="@+id/action_chapters"
android:icon="@drawable/ic_expand_more" android:icon="@drawable/ic_expand_more"
android:title="@string/chapters"
android:orderInCategory="0" android:orderInCategory="0"
android:title="@string/chapters"
app:showAsAction="always" />
<item
android:id="@+id/action_incognito"
android:icon="@drawable/ic_incognito"
android:title="@string/incognito_mode"
android:visible="false"
app:showAsAction="always" /> app:showAsAction="always" />
</menu> </menu>

@ -564,4 +564,5 @@
<string name="remaining_time_pattern">%1$s %2$s</string> <string name="remaining_time_pattern">%1$s %2$s</string>
<string name="volume_">Volume %d</string> <string name="volume_">Volume %d</string>
<string name="volume_unknown">Unknown volume</string> <string name="volume_unknown">Unknown volume</string>
<string name="incognito_mode_hint">Your reading progress will not be saved</string>
</resources> </resources>

Loading…
Cancel
Save