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

This commit is contained in:
Ivan Iskandar 2023-02-18 22:08:37 +07:00 committed by GitHub
parent ffa8c8fd07
commit d3dadf71e8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -3,12 +3,14 @@ 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
import android.os.Bundle import android.os.Bundle
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
@ -41,6 +43,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
@ -86,7 +89,10 @@ import eu.kanade.tachiyomi.util.system.openInBrowser
import eu.kanade.tachiyomi.util.system.toast import eu.kanade.tachiyomi.util.system.toast
import eu.kanade.tachiyomi.util.view.setComposeContent import eu.kanade.tachiyomi.util.view.setComposeContent
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
@ -120,8 +126,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
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
// Prevent splash screen showing up on configuration changes // Prevent splash screen showing up on configuration changes
@ -211,7 +216,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)
@ -257,6 +262,8 @@ class MainActivity : BaseActivity() {
.launchIn(this) .launchIn(this)
} }
HandleOnNewIntent(context = context, navigator = navigator)
CheckForUpdates() CheckForUpdates()
} }
@ -289,7 +296,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() }
} }
@ -320,6 +327,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
@ -398,37 +417,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
@ -440,6 +448,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)
@ -448,15 +457,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
} }
@ -467,7 +477,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()
) { ) {