MainActivity: Avoid navigator-related crash when handling onNewIntent (#9104)

(cherry picked from commit d3dadf71e8d7d029fdb87b44217e001f95f21c1a)
This commit is contained in:
Ivan Iskandar 2023-02-18 22:08:37 +07:00 committed by Jobobby04
parent 725a66f078
commit a163223d83

View File

@ -3,6 +3,7 @@ package eu.kanade.tachiyomi.ui.main
import android.animation.ValueAnimator import android.animation.ValueAnimator
import android.app.SearchManager import android.app.SearchManager
import android.app.assist.AssistContent import android.app.assist.AssistContent
import android.content.Context
import android.content.Intent import android.content.Intent
import android.graphics.Color import android.graphics.Color
import android.os.Build import android.os.Build
@ -10,6 +11,7 @@ import android.os.Bundle
import android.os.Looper import android.os.Looper
import android.view.View import android.view.View
import android.widget.Toast import android.widget.Toast
import androidx.activity.ComponentActivity
import androidx.activity.compose.BackHandler import androidx.activity.compose.BackHandler
import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
@ -38,6 +40,7 @@ import androidx.core.animation.doOnEnd
import androidx.core.net.toUri import androidx.core.net.toUri
import androidx.core.splashscreen.SplashScreen import androidx.core.splashscreen.SplashScreen
import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
import androidx.core.util.Consumer
import androidx.core.view.WindowCompat import androidx.core.view.WindowCompat
import androidx.interpolator.view.animation.FastOutSlowInInterpolator import androidx.interpolator.view.animation.FastOutSlowInInterpolator
import androidx.interpolator.view.animation.LinearOutSlowInInterpolator import androidx.interpolator.view.animation.LinearOutSlowInInterpolator
@ -90,7 +93,10 @@ import exh.source.BlacklistedSources
import exh.source.EH_SOURCE_ID import exh.source.EH_SOURCE_ID
import exh.source.EXH_SOURCE_ID import exh.source.EXH_SOURCE_ID
import kotlinx.coroutines.cancel import kotlinx.coroutines.cancel
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.callbackFlow
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.drop import kotlinx.coroutines.flow.drop
import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.launchIn
@ -129,8 +135,7 @@ class MainActivity : BaseActivity() {
*/ */
private var settingsSheet: LibrarySettingsSheet? = null private var settingsSheet: LibrarySettingsSheet? = null
private var isHandlingShortcut: Boolean = false private var navigator: Navigator? = null
private lateinit var navigator: Navigator
// SY --> // SY -->
// Idle-until-urgent // Idle-until-urgent
@ -246,7 +251,7 @@ class MainActivity : BaseActivity() {
if (savedInstanceState == null) { if (savedInstanceState == null) {
// Set start screen // Set start screen
handleIntentAction(intent) handleIntentAction(intent, navigator)
// Reset Incognito Mode on relaunch // Reset Incognito Mode on relaunch
preferences.incognitoMode().set(false) preferences.incognitoMode().set(false)
@ -306,6 +311,8 @@ class MainActivity : BaseActivity() {
.launchIn(this) .launchIn(this)
} }
HandleOnNewIntent(context = context, navigator = navigator)
CheckForUpdates() CheckForUpdates()
} }
@ -349,7 +356,7 @@ class MainActivity : BaseActivity() {
override fun onProvideAssistContent(outContent: AssistContent) { override fun onProvideAssistContent(outContent: AssistContent) {
super.onProvideAssistContent(outContent) super.onProvideAssistContent(outContent)
when (val screen = navigator.lastItem) { when (val screen = navigator?.lastItem) {
is AssistContentScreen -> { is AssistContentScreen -> {
screen.onProvideAssistUrl()?.let { outContent.webUri = it.toUri() } screen.onProvideAssistUrl()?.let { outContent.webUri = it.toUri() }
} }
@ -380,6 +387,18 @@ class MainActivity : BaseActivity() {
} }
} }
@Composable
fun HandleOnNewIntent(context: Context, navigator: Navigator) {
LaunchedEffect(Unit) {
callbackFlow<Intent> {
val componentActivity = context as ComponentActivity
val consumer = Consumer<Intent> { trySend(it) }
componentActivity.addOnNewIntentListener(consumer)
awaitClose { componentActivity.removeOnNewIntentListener(consumer) }
}.collectLatest { handleIntentAction(it, navigator) }
}
}
@Composable @Composable
private fun CheckForUpdates() { private fun CheckForUpdates() {
val context = LocalContext.current val context = LocalContext.current
@ -458,37 +477,26 @@ class MainActivity : BaseActivity() {
} }
} }
override fun onNewIntent(intent: Intent) { private fun handleIntentAction(intent: Intent, navigator: Navigator): Boolean {
lifecycleScope.launch {
val handle = handleIntentAction(intent)
if (!handle) {
super.onNewIntent(intent)
}
}
}
private suspend fun handleIntentAction(intent: Intent): Boolean {
val notificationId = intent.getIntExtra("notificationId", -1) val notificationId = intent.getIntExtra("notificationId", -1)
if (notificationId > -1) { if (notificationId > -1) {
NotificationReceiver.dismissNotification(applicationContext, notificationId, intent.getIntExtra("groupId", 0)) NotificationReceiver.dismissNotification(applicationContext, notificationId, intent.getIntExtra("groupId", 0))
} }
isHandlingShortcut = true val tabToOpen = when (intent.action) {
Constants.SHORTCUT_LIBRARY -> HomeScreen.Tab.Library()
when (intent.action) {
Constants.SHORTCUT_LIBRARY -> HomeScreen.openTab(HomeScreen.Tab.Library())
Constants.SHORTCUT_MANGA -> { Constants.SHORTCUT_MANGA -> {
val idToOpen = intent.extras?.getLong(Constants.MANGA_EXTRA) ?: return false val idToOpen = intent.extras?.getLong(Constants.MANGA_EXTRA) ?: return false
navigator.popUntilRoot() navigator.popUntilRoot()
HomeScreen.openTab(HomeScreen.Tab.Library(idToOpen)) HomeScreen.Tab.Library(idToOpen)
} }
Constants.SHORTCUT_UPDATES -> HomeScreen.openTab(HomeScreen.Tab.Updates) Constants.SHORTCUT_UPDATES -> HomeScreen.Tab.Updates
Constants.SHORTCUT_HISTORY -> HomeScreen.openTab(HomeScreen.Tab.History) Constants.SHORTCUT_HISTORY -> HomeScreen.Tab.History
Constants.SHORTCUT_SOURCES -> HomeScreen.openTab(HomeScreen.Tab.Browse(false)) Constants.SHORTCUT_SOURCES -> HomeScreen.Tab.Browse(false)
Constants.SHORTCUT_EXTENSIONS -> HomeScreen.openTab(HomeScreen.Tab.Browse(true)) Constants.SHORTCUT_EXTENSIONS -> HomeScreen.Tab.Browse(true)
Constants.SHORTCUT_DOWNLOADS -> { Constants.SHORTCUT_DOWNLOADS -> {
navigator.popUntilRoot() navigator.popUntilRoot()
HomeScreen.openTab(HomeScreen.Tab.More(toDownloads = true)) HomeScreen.Tab.More(toDownloads = true)
} }
Intent.ACTION_SEARCH, Intent.ACTION_SEND, "com.google.android.gms.actions.SEARCH_ACTION" -> { Intent.ACTION_SEARCH, Intent.ACTION_SEND, "com.google.android.gms.actions.SEARCH_ACTION" -> {
// If the intent match the "standard" Android search intent // If the intent match the "standard" Android search intent
@ -500,6 +508,7 @@ class MainActivity : BaseActivity() {
navigator.popUntilRoot() navigator.popUntilRoot()
navigator.push(GlobalSearchScreen(query)) navigator.push(GlobalSearchScreen(query))
} }
null
} }
INTENT_SEARCH -> { INTENT_SEARCH -> {
val query = intent.getStringExtra(INTENT_SEARCH_QUERY) val query = intent.getStringExtra(INTENT_SEARCH_QUERY)
@ -508,15 +517,16 @@ class MainActivity : BaseActivity() {
navigator.popUntilRoot() navigator.popUntilRoot()
navigator.push(GlobalSearchScreen(query, filter)) navigator.push(GlobalSearchScreen(query, filter))
} }
null
} }
else -> { else -> return false
isHandlingShortcut = false }
return false
} if (tabToOpen != null) {
lifecycleScope.launch { HomeScreen.openTab(tabToOpen) }
} }
ready = true ready = true
isHandlingShortcut = false
return true return true
} }
@ -527,7 +537,7 @@ class MainActivity : BaseActivity() {
} }
override fun onBackPressed() { override fun onBackPressed() {
if (navigator.size == 1 && if (navigator?.size == 1 &&
!onBackPressedDispatcher.hasEnabledCallbacks() && !onBackPressedDispatcher.hasEnabledCallbacks() &&
libraryPreferences.autoClearChapterCache().get() libraryPreferences.autoClearChapterCache().get()
) { ) {