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
pull/5005/head
Ivan Iskandar 3 years ago committed by GitHub
parent 908c9bc624
commit cb203ef02c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -2,14 +2,20 @@ package eu.kanade.tachiyomi
import android.app.ActivityManager
import android.app.Application
import android.app.PendingIntent
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.content.res.Configuration
import android.os.Build
import androidx.core.app.NotificationManagerCompat
import androidx.core.content.getSystemService
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleObserver
import androidx.lifecycle.OnLifecycleEvent
import androidx.lifecycle.ProcessLifecycleOwner
import androidx.lifecycle.lifecycleScope
import androidx.multidex.MultiDex
import coil.ImageLoader
import coil.ImageLoaderFactory
@ -22,6 +28,9 @@ import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.network.NetworkHelper
import eu.kanade.tachiyomi.ui.security.SecureActivityDelegate
import eu.kanade.tachiyomi.util.system.LocaleHelper
import eu.kanade.tachiyomi.util.system.notification
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import org.acra.ACRA
import org.acra.annotation.AcraCore
import org.acra.annotation.AcraHttpSender
@ -45,6 +54,8 @@ open class App : Application(), LifecycleObserver, ImageLoaderFactory {
private val preferences: PreferencesHelper by injectLazy()
private val disableIncognitoReceiver = DisableIncognitoReceiver()
override fun onCreate() {
super.onCreate()
if (BuildConfig.DEBUG) Timber.plant(Timber.DebugTree())
@ -65,6 +76,34 @@ open class App : Application(), LifecycleObserver, ImageLoaderFactory {
// Reset Incognito Mode on relaunch
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) {
@ -111,4 +150,30 @@ open class App : Application(), LifecycleObserver, ImageLoaderFactory {
protected open fun setupNotificationChannels() {
Notifications.createChannels(this)
}
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 ID_CRASH_LOGS = -601
/**
* Notification channel used for Incognito Mode
*/
const val CHANNEL_INCOGNITO_MODE = "incognito_mode_channel"
const val ID_INCOGNITO_MODE = -701
private val deprecatedChannels = listOf(
"downloader_channel",
"backup_restore_complete_channel"
@ -154,6 +160,11 @@ object Notifications {
CHANNEL_CRASH_LOGS,
context.getString(R.string.channel_crash_logs),
NotificationManager.IMPORTANCE_HIGH
),
NotificationChannel(
CHANNEL_INCOGNITO_MODE,
context.getString(R.string.pref_incognito_mode),
NotificationManager.IMPORTANCE_LOW
)
).forEach(context.notificationManager::createNotificationChannel)

@ -41,6 +41,7 @@ import eu.kanade.tachiyomi.ui.base.controller.TabbedController
import eu.kanade.tachiyomi.ui.base.controller.ToolbarLiftOnScrollController
import eu.kanade.tachiyomi.ui.base.controller.withFadeTransaction
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.download.DownloadController
import eu.kanade.tachiyomi.ui.library.LibraryController
@ -224,7 +225,17 @@ class MainActivity : BaseViewBindingActivity<MainActivityBinding>() {
.launchIn(lifecycleScope)
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)
}

@ -127,7 +127,7 @@ class MangaController :
var source: Source? = null
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 coverCache: CoverCache by injectLazy()

@ -167,6 +167,12 @@ class ReaderActivity : BaseRxActivity<ReaderActivityBinding, ReaderPresenter>()
window.decorView.setOnSystemUiVisibilityChangeListener {
setMenuVisibility(menuVisible, animate = false)
}
// Finish when incognito mode is disabled
preferences.incognitoMode().asFlow()
.drop(1)
.onEach { if (!it) finish() }
.launchIn(lifecycleScope)
}
/**

@ -144,6 +144,8 @@ class ReaderPresenter(
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
* was restored.
@ -375,7 +377,7 @@ class ReaderPresenter(
// Save last page read and mark as read if needed
selectedChapter.chapter.last_page_read = page.index
val shouldTrack = !preferences.incognitoMode().get() || hasTrackers
val shouldTrack = !incognitoMode || hasTrackers
if (selectedChapter.pages?.lastIndex == page.index && shouldTrack) {
selectedChapter.chapter.read = true
updateTrackChapterRead(selectedChapter)
@ -430,7 +432,7 @@ class ReaderPresenter(
* If incognito mode isn't on or has at least 1 tracker
*/
private fun saveChapterProgress(chapter: ReaderChapter) {
if (!preferences.incognitoMode().get() || hasTrackers) {
if (!incognitoMode || hasTrackers) {
db.updateChapterProgress(chapter.chapter).asRxCompletable()
.onErrorComplete()
.subscribeOn(Schedulers.io())
@ -442,7 +444,7 @@ class ReaderPresenter(
* Saves this [chapter] last read history if incognito mode isn't on.
*/
private fun saveChapterHistory(chapter: ReaderChapter) {
if (!preferences.incognitoMode().get()) {
if (!incognitoMode) {
val history = History.create(chapter.chapter).apply { last_read = Date().time }
db.updateHistoryLastRead(history).asRxCompletable()
.onErrorComplete()

@ -467,6 +467,7 @@
<string name="label_downloaded_only">Downloaded only</string>
<string name="pref_incognito_mode">Incognito mode</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>
<plurals name="download_queue_summary">
<item quantity="one">1 remaining</item>
@ -776,5 +777,4 @@
<!-- S Pen actions -->
<string name="spen_previous_page">Previous page</string>
<string name="spen_next_page">Next page</string>
</resources>

Loading…
Cancel
Save