Show notification to disable Incognito Mode when it's enabled (#4976)
* Show notification to disable Incognito Mode when it's enabled * Finish ReaderActivity and BrowseSourceController when incognito is disabled * CLeanup strings * Only register DisableIncognitoReceiver when needed (cherry picked from commit cb203ef02cc3c078d5e5717b98ef1db1cf570586) # Conflicts: # app/src/main/java/eu/kanade/tachiyomi/App.kt # app/src/main/java/eu/kanade/tachiyomi/data/notification/Notifications.kt
This commit is contained in:
parent
6dad90e19c
commit
4f02f652d9
@ -2,16 +2,22 @@ package eu.kanade.tachiyomi
|
|||||||
|
|
||||||
import android.app.ActivityManager
|
import android.app.ActivityManager
|
||||||
import android.app.Application
|
import android.app.Application
|
||||||
|
import android.app.PendingIntent
|
||||||
|
import android.content.BroadcastReceiver
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import android.content.IntentFilter
|
||||||
import android.content.res.Configuration
|
import android.content.res.Configuration
|
||||||
import android.graphics.Color
|
import android.graphics.Color
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.Environment
|
import android.os.Environment
|
||||||
|
import androidx.core.app.NotificationManagerCompat
|
||||||
import androidx.core.content.getSystemService
|
import androidx.core.content.getSystemService
|
||||||
import androidx.lifecycle.Lifecycle
|
import androidx.lifecycle.Lifecycle
|
||||||
import androidx.lifecycle.LifecycleObserver
|
import androidx.lifecycle.LifecycleObserver
|
||||||
import androidx.lifecycle.OnLifecycleEvent
|
import androidx.lifecycle.OnLifecycleEvent
|
||||||
import androidx.lifecycle.ProcessLifecycleOwner
|
import androidx.lifecycle.ProcessLifecycleOwner
|
||||||
|
import androidx.lifecycle.lifecycleScope
|
||||||
import androidx.multidex.MultiDex
|
import androidx.multidex.MultiDex
|
||||||
import coil.ImageLoader
|
import coil.ImageLoader
|
||||||
import coil.ImageLoaderFactory
|
import coil.ImageLoaderFactory
|
||||||
@ -39,6 +45,7 @@ import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
|||||||
import eu.kanade.tachiyomi.network.NetworkHelper
|
import eu.kanade.tachiyomi.network.NetworkHelper
|
||||||
import eu.kanade.tachiyomi.ui.security.SecureActivityDelegate
|
import eu.kanade.tachiyomi.ui.security.SecureActivityDelegate
|
||||||
import eu.kanade.tachiyomi.util.system.LocaleHelper
|
import eu.kanade.tachiyomi.util.system.LocaleHelper
|
||||||
|
import eu.kanade.tachiyomi.util.system.notification
|
||||||
import exh.debug.DebugToggles
|
import exh.debug.DebugToggles
|
||||||
import exh.log.CrashlyticsPrinter
|
import exh.log.CrashlyticsPrinter
|
||||||
import exh.log.EHDebugModeOverlay
|
import exh.log.EHDebugModeOverlay
|
||||||
@ -49,6 +56,8 @@ import exh.log.xLogD
|
|||||||
import exh.log.xLogE
|
import exh.log.xLogE
|
||||||
import exh.syDebugVersion
|
import exh.syDebugVersion
|
||||||
import io.realm.Realm
|
import io.realm.Realm
|
||||||
|
import kotlinx.coroutines.flow.launchIn
|
||||||
|
import kotlinx.coroutines.flow.onEach
|
||||||
import org.conscrypt.Conscrypt
|
import org.conscrypt.Conscrypt
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import uy.kohesive.injekt.Injekt
|
import uy.kohesive.injekt.Injekt
|
||||||
@ -67,6 +76,8 @@ open class App : Application(), LifecycleObserver, ImageLoaderFactory {
|
|||||||
|
|
||||||
private val preferences: PreferencesHelper by injectLazy()
|
private val preferences: PreferencesHelper by injectLazy()
|
||||||
|
|
||||||
|
private val disableIncognitoReceiver = DisableIncognitoReceiver()
|
||||||
|
|
||||||
override fun onCreate() {
|
override fun onCreate() {
|
||||||
super.onCreate()
|
super.onCreate()
|
||||||
// if (BuildConfig.DEBUG) Timber.plant(Timber.DebugTree())
|
// if (BuildConfig.DEBUG) Timber.plant(Timber.DebugTree())
|
||||||
@ -95,6 +106,34 @@ open class App : Application(), LifecycleObserver, ImageLoaderFactory {
|
|||||||
|
|
||||||
// Reset Incognito Mode on relaunch
|
// Reset Incognito Mode on relaunch
|
||||||
preferences.incognitoMode().set(false)
|
preferences.incognitoMode().set(false)
|
||||||
|
|
||||||
|
// Show notification to disable Incognito Mode when it's enabled
|
||||||
|
preferences.incognitoMode().asFlow()
|
||||||
|
.onEach { enabled ->
|
||||||
|
val notificationManager = NotificationManagerCompat.from(this)
|
||||||
|
if (enabled) {
|
||||||
|
disableIncognitoReceiver.register()
|
||||||
|
val notification = notification(Notifications.CHANNEL_INCOGNITO_MODE) {
|
||||||
|
setContentTitle(getString(R.string.pref_incognito_mode))
|
||||||
|
setContentText(getString(R.string.notification_incognito_text))
|
||||||
|
setSmallIcon(R.drawable.ic_glasses_black_24dp)
|
||||||
|
setOngoing(true)
|
||||||
|
|
||||||
|
val pendingIntent = PendingIntent.getBroadcast(
|
||||||
|
this@App,
|
||||||
|
0,
|
||||||
|
Intent(ACTION_DISABLE_INCOGNITO_MODE),
|
||||||
|
PendingIntent.FLAG_ONE_SHOT
|
||||||
|
)
|
||||||
|
setContentIntent(pendingIntent)
|
||||||
|
}
|
||||||
|
notificationManager.notify(Notifications.ID_INCOGNITO_MODE, notification)
|
||||||
|
} else {
|
||||||
|
disableIncognitoReceiver.unregister()
|
||||||
|
notificationManager.cancel(Notifications.ID_INCOGNITO_MODE)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.launchIn(ProcessLifecycleOwner.get().lifecycleScope)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun attachBaseContext(base: Context) {
|
override fun attachBaseContext(base: Context) {
|
||||||
@ -245,4 +284,30 @@ open class App : Application(), LifecycleObserver, ImageLoaderFactory {
|
|||||||
xLogE("Failed to initialize debug overlay, app in background?", e)
|
xLogE("Failed to initialize debug overlay, app in background?", e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private inner class DisableIncognitoReceiver : BroadcastReceiver() {
|
||||||
|
private var registered = false
|
||||||
|
|
||||||
|
override fun onReceive(context: Context, intent: Intent) {
|
||||||
|
preferences.incognitoMode().set(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun register() {
|
||||||
|
if (!registered) {
|
||||||
|
registerReceiver(this, IntentFilter(ACTION_DISABLE_INCOGNITO_MODE))
|
||||||
|
registered = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun unregister() {
|
||||||
|
if (registered) {
|
||||||
|
unregisterReceiver(this)
|
||||||
|
registered = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val ACTION_DISABLE_INCOGNITO_MODE = "tachi.action.DISABLE_INCOGNITO_MODE"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -68,6 +68,12 @@ object Notifications {
|
|||||||
const val CHANNEL_CRASH_LOGS = "crash_logs_channel"
|
const val CHANNEL_CRASH_LOGS = "crash_logs_channel"
|
||||||
const val ID_CRASH_LOGS = -601
|
const val ID_CRASH_LOGS = -601
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notification channel used for Incognito Mode
|
||||||
|
*/
|
||||||
|
const val CHANNEL_INCOGNITO_MODE = "incognito_mode_channel"
|
||||||
|
const val ID_INCOGNITO_MODE = -701
|
||||||
|
|
||||||
// SY -->
|
// SY -->
|
||||||
/**
|
/**
|
||||||
* Notification channel and ids used for backup and restore.
|
* Notification channel and ids used for backup and restore.
|
||||||
@ -164,6 +170,11 @@ object Notifications {
|
|||||||
context.getString(R.string.channel_crash_logs),
|
context.getString(R.string.channel_crash_logs),
|
||||||
NotificationManager.IMPORTANCE_HIGH
|
NotificationManager.IMPORTANCE_HIGH
|
||||||
),
|
),
|
||||||
|
NotificationChannel(
|
||||||
|
CHANNEL_INCOGNITO_MODE,
|
||||||
|
context.getString(R.string.pref_incognito_mode),
|
||||||
|
NotificationManager.IMPORTANCE_LOW
|
||||||
|
),
|
||||||
NotificationChannel(
|
NotificationChannel(
|
||||||
CHANNEL_SIMILAR,
|
CHANNEL_SIMILAR,
|
||||||
context.getString(R.string.similar_manga),
|
context.getString(R.string.similar_manga),
|
||||||
|
@ -40,6 +40,7 @@ import eu.kanade.tachiyomi.ui.base.controller.TabbedController
|
|||||||
import eu.kanade.tachiyomi.ui.base.controller.ToolbarLiftOnScrollController
|
import eu.kanade.tachiyomi.ui.base.controller.ToolbarLiftOnScrollController
|
||||||
import eu.kanade.tachiyomi.ui.base.controller.withFadeTransaction
|
import eu.kanade.tachiyomi.ui.base.controller.withFadeTransaction
|
||||||
import eu.kanade.tachiyomi.ui.browse.BrowseController
|
import eu.kanade.tachiyomi.ui.browse.BrowseController
|
||||||
|
import eu.kanade.tachiyomi.ui.browse.source.browse.BrowseSourceController
|
||||||
import eu.kanade.tachiyomi.ui.browse.source.globalsearch.GlobalSearchController
|
import eu.kanade.tachiyomi.ui.browse.source.globalsearch.GlobalSearchController
|
||||||
import eu.kanade.tachiyomi.ui.download.DownloadController
|
import eu.kanade.tachiyomi.ui.download.DownloadController
|
||||||
import eu.kanade.tachiyomi.ui.library.LibraryController
|
import eu.kanade.tachiyomi.ui.library.LibraryController
|
||||||
@ -277,7 +278,17 @@ class MainActivity : BaseViewBindingActivity<MainActivityBinding>() {
|
|||||||
.launchIn(lifecycleScope)
|
.launchIn(lifecycleScope)
|
||||||
|
|
||||||
preferences.incognitoMode()
|
preferences.incognitoMode()
|
||||||
.asImmediateFlow { binding.incognitoMode.isVisible = it }
|
.asImmediateFlow {
|
||||||
|
binding.incognitoMode.isVisible = it
|
||||||
|
|
||||||
|
// Close BrowseSourceController and its MangaController child when incognito mode is disabled
|
||||||
|
if (!it) {
|
||||||
|
val fg = router.backstack.last().controller()
|
||||||
|
if (fg is BrowseSourceController || fg is MangaController && fg.fromSource) {
|
||||||
|
router.popToRoot()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
.launchIn(lifecycleScope)
|
.launchIn(lifecycleScope)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -181,7 +181,7 @@ class MangaController :
|
|||||||
var source: Source? = null
|
var source: Source? = null
|
||||||
private set
|
private set
|
||||||
|
|
||||||
private val fromSource = args.getBoolean(FROM_SOURCE_EXTRA, false)
|
val fromSource = args.getBoolean(FROM_SOURCE_EXTRA, false)
|
||||||
|
|
||||||
private val preferences: PreferencesHelper by injectLazy()
|
private val preferences: PreferencesHelper by injectLazy()
|
||||||
private val coverCache: CoverCache by injectLazy()
|
private val coverCache: CoverCache by injectLazy()
|
||||||
|
@ -202,6 +202,12 @@ class ReaderActivity : BaseRxActivity<ReaderActivityBinding, ReaderPresenter>()
|
|||||||
window.decorView.setOnSystemUiVisibilityChangeListener {
|
window.decorView.setOnSystemUiVisibilityChangeListener {
|
||||||
setMenuVisibility(menuVisible, animate = false)
|
setMenuVisibility(menuVisible, animate = false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Finish when incognito mode is disabled
|
||||||
|
preferences.incognitoMode().asFlow()
|
||||||
|
.drop(1)
|
||||||
|
.onEach { if (!it) finish() }
|
||||||
|
.launchIn(lifecycleScope)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SY -->
|
// SY -->
|
||||||
|
@ -177,6 +177,8 @@ class ReaderPresenter(
|
|||||||
hasTrackers = tracks.size > 0
|
hasTrackers = tracks.size > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private val incognitoMode = preferences.incognitoMode().get()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when the presenter is created. It retrieves the saved active chapter if the process
|
* Called when the presenter is created. It retrieves the saved active chapter if the process
|
||||||
* was restored.
|
* was restored.
|
||||||
@ -454,7 +456,7 @@ class ReaderPresenter(
|
|||||||
|
|
||||||
// Save last page read and mark as read if needed
|
// Save last page read and mark as read if needed
|
||||||
selectedChapter.chapter.last_page_read = page.index
|
selectedChapter.chapter.last_page_read = page.index
|
||||||
val shouldTrack = !preferences.incognitoMode().get() || hasTrackers
|
val shouldTrack = !incognitoMode || hasTrackers
|
||||||
if (selectedChapter.pages?.lastIndex == page.index && shouldTrack) {
|
if (selectedChapter.pages?.lastIndex == page.index && shouldTrack) {
|
||||||
selectedChapter.chapter.read = true
|
selectedChapter.chapter.read = true
|
||||||
// SY -->
|
// SY -->
|
||||||
@ -527,7 +529,7 @@ class ReaderPresenter(
|
|||||||
* If incognito mode isn't on or has at least 1 tracker
|
* If incognito mode isn't on or has at least 1 tracker
|
||||||
*/
|
*/
|
||||||
private fun saveChapterProgress(chapter: ReaderChapter) {
|
private fun saveChapterProgress(chapter: ReaderChapter) {
|
||||||
if (!preferences.incognitoMode().get() || hasTrackers) {
|
if (!incognitoMode || hasTrackers) {
|
||||||
db.updateChapterProgress(chapter.chapter).asRxCompletable()
|
db.updateChapterProgress(chapter.chapter).asRxCompletable()
|
||||||
.onErrorComplete()
|
.onErrorComplete()
|
||||||
.subscribeOn(Schedulers.io())
|
.subscribeOn(Schedulers.io())
|
||||||
@ -539,7 +541,7 @@ class ReaderPresenter(
|
|||||||
* Saves this [chapter] last read history if incognito mode isn't on.
|
* Saves this [chapter] last read history if incognito mode isn't on.
|
||||||
*/
|
*/
|
||||||
private fun saveChapterHistory(chapter: ReaderChapter) {
|
private fun saveChapterHistory(chapter: ReaderChapter) {
|
||||||
if (!preferences.incognitoMode().get()) {
|
if (!incognitoMode) {
|
||||||
val history = History.create(chapter.chapter).apply { last_read = Date().time }
|
val history = History.create(chapter.chapter).apply { last_read = Date().time }
|
||||||
db.updateHistoryLastRead(history).asRxCompletable()
|
db.updateHistoryLastRead(history).asRxCompletable()
|
||||||
.onErrorComplete()
|
.onErrorComplete()
|
||||||
|
@ -468,6 +468,7 @@
|
|||||||
<string name="label_downloaded_only">Downloaded only</string>
|
<string name="label_downloaded_only">Downloaded only</string>
|
||||||
<string name="pref_incognito_mode">Incognito mode</string>
|
<string name="pref_incognito_mode">Incognito mode</string>
|
||||||
<string name="pref_incognito_mode_summary">Pauses reading history</string>
|
<string name="pref_incognito_mode_summary">Pauses reading history</string>
|
||||||
|
<string name="notification_incognito_text">Disable incognito mode</string>
|
||||||
<string name="downloaded_only_summary">Filters all manga in your library</string>
|
<string name="downloaded_only_summary">Filters all manga in your library</string>
|
||||||
<plurals name="download_queue_summary">
|
<plurals name="download_queue_summary">
|
||||||
<item quantity="one">1 remaining</item>
|
<item quantity="one">1 remaining</item>
|
||||||
@ -777,5 +778,4 @@
|
|||||||
<!-- S Pen actions -->
|
<!-- S Pen actions -->
|
||||||
<string name="spen_previous_page">Previous page</string>
|
<string name="spen_previous_page">Previous page</string>
|
||||||
<string name="spen_next_page">Next page</string>
|
<string name="spen_next_page">Next page</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user