Forráskód Böngészése

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

(cherry picked from commit d3dadf71e8d7d029fdb87b44217e001f95f21c1a)
Ivan Iskandar 2 éve
szülő
commit
c58b495433

+ 39 - 30
app/src/main/java/eu/kanade/tachiyomi/ui/main/MainActivity.kt

@@ -3,12 +3,14 @@ package eu.kanade.tachiyomi.ui.main
 import android.animation.ValueAnimator
 import android.app.SearchManager
 import android.app.assist.AssistContent
+import android.content.Context
 import android.content.Intent
 import android.graphics.Color
 import android.os.Build
 import android.os.Bundle
 import android.view.View
 import android.widget.Toast
+import androidx.activity.ComponentActivity
 import androidx.activity.compose.BackHandler
 import androidx.compose.foundation.isSystemInDarkTheme
 import androidx.compose.foundation.layout.Box
@@ -41,6 +43,7 @@ import androidx.core.animation.doOnEnd
 import androidx.core.net.toUri
 import androidx.core.splashscreen.SplashScreen
 import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
+import androidx.core.util.Consumer
 import androidx.core.view.WindowCompat
 import androidx.interpolator.view.animation.FastOutSlowInInterpolator
 import androidx.interpolator.view.animation.LinearOutSlowInInterpolator
@@ -85,7 +88,10 @@ import eu.kanade.tachiyomi.util.system.openInBrowser
 import eu.kanade.tachiyomi.util.system.toast
 import eu.kanade.tachiyomi.util.view.setComposeContent
 import kotlinx.coroutines.cancel
+import kotlinx.coroutines.channels.awaitClose
 import kotlinx.coroutines.delay
+import kotlinx.coroutines.flow.callbackFlow
+import kotlinx.coroutines.flow.collectLatest
 import kotlinx.coroutines.flow.drop
 import kotlinx.coroutines.flow.filter
 import kotlinx.coroutines.flow.launchIn
@@ -119,8 +125,7 @@ class MainActivity : BaseActivity() {
      */
     private var settingsSheet: LibrarySettingsSheet? = null
 
-    private var isHandlingShortcut: Boolean = false
-    private lateinit var navigator: Navigator
+    private var navigator: Navigator? = null
 
     override fun onCreate(savedInstanceState: Bundle?) {
         // Prevent splash screen showing up on configuration changes
@@ -210,7 +215,7 @@ class MainActivity : BaseActivity() {
 
                     if (savedInstanceState == null) {
                         // Set start screen
-                        handleIntentAction(intent)
+                        handleIntentAction(intent, navigator)
 
                         // Reset Incognito Mode on relaunch
                         preferences.incognitoMode().set(false)
@@ -257,6 +262,7 @@ class MainActivity : BaseActivity() {
                 }
 
                 CheckForUpdate()
+                HandleOnNewIntent(context = context, navigator = navigator)
             }
 
             var showChangelog by remember { mutableStateOf(didMigration && !BuildConfig.DEBUG) }
@@ -288,7 +294,7 @@ class MainActivity : BaseActivity() {
 
     override fun onProvideAssistContent(outContent: AssistContent) {
         super.onProvideAssistContent(outContent)
-        when (val screen = navigator.lastItem) {
+        when (val screen = navigator?.lastItem) {
             is AssistContentScreen -> {
                 screen.onProvideAssistUrl()?.let { outContent.webUri = it.toUri() }
             }
@@ -319,6 +325,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
     private fun CheckForUpdate() {
         val context = LocalContext.current
@@ -387,37 +405,26 @@ class MainActivity : BaseActivity() {
         }
     }
 
-    override fun onNewIntent(intent: Intent) {
-        lifecycleScope.launch {
-            val handle = handleIntentAction(intent)
-            if (!handle) {
-                super.onNewIntent(intent)
-            }
-        }
-    }
-
-    private suspend fun handleIntentAction(intent: Intent): Boolean {
+    private fun handleIntentAction(intent: Intent, navigator: Navigator): Boolean {
         val notificationId = intent.getIntExtra("notificationId", -1)
         if (notificationId > -1) {
             NotificationReceiver.dismissNotification(applicationContext, notificationId, intent.getIntExtra("groupId", 0))
         }
 
-        isHandlingShortcut = true
-
-        when (intent.action) {
-            Constants.SHORTCUT_LIBRARY -> HomeScreen.openTab(HomeScreen.Tab.Library())
+        val tabToOpen = when (intent.action) {
+            Constants.SHORTCUT_LIBRARY -> HomeScreen.Tab.Library()
             Constants.SHORTCUT_MANGA -> {
                 val idToOpen = intent.extras?.getLong(Constants.MANGA_EXTRA) ?: return false
                 navigator.popUntilRoot()
-                HomeScreen.openTab(HomeScreen.Tab.Library(idToOpen))
+                HomeScreen.Tab.Library(idToOpen)
             }
-            Constants.SHORTCUT_UPDATES -> HomeScreen.openTab(HomeScreen.Tab.Updates)
-            Constants.SHORTCUT_HISTORY -> HomeScreen.openTab(HomeScreen.Tab.History)
-            Constants.SHORTCUT_SOURCES -> HomeScreen.openTab(HomeScreen.Tab.Browse(false))
-            Constants.SHORTCUT_EXTENSIONS -> HomeScreen.openTab(HomeScreen.Tab.Browse(true))
+            Constants.SHORTCUT_UPDATES -> HomeScreen.Tab.Updates
+            Constants.SHORTCUT_HISTORY -> HomeScreen.Tab.History
+            Constants.SHORTCUT_SOURCES -> HomeScreen.Tab.Browse(false)
+            Constants.SHORTCUT_EXTENSIONS -> HomeScreen.Tab.Browse(true)
             Constants.SHORTCUT_DOWNLOADS -> {
                 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" -> {
                 // If the intent match the "standard" Android search intent
@@ -429,6 +436,7 @@ class MainActivity : BaseActivity() {
                     navigator.popUntilRoot()
                     navigator.push(GlobalSearchScreen(query))
                 }
+                null
             }
             INTENT_SEARCH -> {
                 val query = intent.getStringExtra(INTENT_SEARCH_QUERY)
@@ -437,15 +445,16 @@ class MainActivity : BaseActivity() {
                     navigator.popUntilRoot()
                     navigator.push(GlobalSearchScreen(query, filter))
                 }
+                null
             }
-            else -> {
-                isHandlingShortcut = false
-                return false
-            }
+            else -> return false
+        }
+
+        if (tabToOpen != null) {
+            lifecycleScope.launch { HomeScreen.openTab(tabToOpen) }
         }
 
         ready = true
-        isHandlingShortcut = false
         return true
     }
 
@@ -456,7 +465,7 @@ class MainActivity : BaseActivity() {
     }
 
     override fun onBackPressed() {
-        if (navigator.size == 1 &&
+        if (navigator?.size == 1 &&
             !onBackPressedDispatcher.hasEnabledCallbacks() &&
             libraryPreferences.autoClearChapterCache().get()
         ) {