MainActivity: Avoid navigator-related crash when handling onNewIntent (#9104)
This commit is contained in:
parent
ffa8c8fd07
commit
d3dadf71e8
1 changed files with 40 additions and 30 deletions
|
@ -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()
|
||||||
) {
|
) {
|
||||||
|
|
Reference in a new issue