mirror of
https://github.com/tapframe/NuvioStreaming.git
synced 2026-05-17 07:21:58 +00:00
fix(nav): prevent back-stack crash on rapid presses
- Replace raw popBackStack() with rememberGuardedPopBackStack() on detail, person, browse, stream, player, catalog, collection, and folder routes - Add PlatformBackHandler to affected full-screen routes - Enable android:enableOnBackInvokedCallback in the manifest
This commit is contained in:
parent
8a58fabfdd
commit
280f6c2aae
2 changed files with 77 additions and 26 deletions
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
<application
|
<application
|
||||||
android:allowBackup="true"
|
android:allowBackup="true"
|
||||||
|
android:enableOnBackInvokedCallback="true"
|
||||||
android:icon="@mipmap/ic_launcher"
|
android:icon="@mipmap/ic_launcher"
|
||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
android:usesCleartextTraffic="true"
|
android:usesCleartextTraffic="true"
|
||||||
|
|
|
||||||
|
|
@ -1005,15 +1005,21 @@ private fun MainAppContent(
|
||||||
}
|
}
|
||||||
composable<DetailRoute> { backStackEntry ->
|
composable<DetailRoute> { backStackEntry ->
|
||||||
val route = backStackEntry.toRoute<DetailRoute>()
|
val route = backStackEntry.toRoute<DetailRoute>()
|
||||||
|
val onBack = rememberGuardedPopBackStack(
|
||||||
|
navController = navController,
|
||||||
|
backStackEntry = backStackEntry,
|
||||||
|
)
|
||||||
|
PlatformBackHandler(
|
||||||
|
enabled = true,
|
||||||
|
onBack = onBack,
|
||||||
|
)
|
||||||
val directorRole = stringResource(Res.string.person_role_director)
|
val directorRole = stringResource(Res.string.person_role_director)
|
||||||
val writerRole = stringResource(Res.string.person_role_writer)
|
val writerRole = stringResource(Res.string.person_role_writer)
|
||||||
val creatorRole = stringResource(Res.string.person_role_creator)
|
val creatorRole = stringResource(Res.string.person_role_creator)
|
||||||
MetaDetailsScreen(
|
MetaDetailsScreen(
|
||||||
type = route.type,
|
type = route.type,
|
||||||
id = route.id,
|
id = route.id,
|
||||||
onBack = {
|
onBack = onBack,
|
||||||
navController.popBackStack()
|
|
||||||
},
|
|
||||||
onPlay = onPlay,
|
onPlay = onPlay,
|
||||||
onPlayManually = onPlayManually,
|
onPlayManually = onPlayManually,
|
||||||
onOpenMeta = { preview ->
|
onOpenMeta = { preview ->
|
||||||
|
|
@ -1078,13 +1084,21 @@ private fun MainAppContent(
|
||||||
}
|
}
|
||||||
composable<PersonDetailRoute> { backStackEntry ->
|
composable<PersonDetailRoute> { backStackEntry ->
|
||||||
val route = backStackEntry.toRoute<PersonDetailRoute>()
|
val route = backStackEntry.toRoute<PersonDetailRoute>()
|
||||||
|
val onBack = rememberGuardedPopBackStack(
|
||||||
|
navController = navController,
|
||||||
|
backStackEntry = backStackEntry,
|
||||||
|
)
|
||||||
|
PlatformBackHandler(
|
||||||
|
enabled = true,
|
||||||
|
onBack = onBack,
|
||||||
|
)
|
||||||
PersonDetailScreen(
|
PersonDetailScreen(
|
||||||
personId = route.personId,
|
personId = route.personId,
|
||||||
personName = route.personName,
|
personName = route.personName,
|
||||||
initialProfilePhoto = route.personPhoto,
|
initialProfilePhoto = route.personPhoto,
|
||||||
avatarTransitionKey = route.castAvatarTransitionKey,
|
avatarTransitionKey = route.castAvatarTransitionKey,
|
||||||
preferCrew = route.preferCrew,
|
preferCrew = route.preferCrew,
|
||||||
onBack = { navController.popBackStack() },
|
onBack = onBack,
|
||||||
onOpenMeta = { preview ->
|
onOpenMeta = { preview ->
|
||||||
coroutineScope.launch {
|
coroutineScope.launch {
|
||||||
val resolvedId = if (preview.id.startsWith("tmdb:")) {
|
val resolvedId = if (preview.id.startsWith("tmdb:")) {
|
||||||
|
|
@ -1113,12 +1127,20 @@ private fun MainAppContent(
|
||||||
}
|
}
|
||||||
composable<EntityBrowseRoute> { backStackEntry ->
|
composable<EntityBrowseRoute> { backStackEntry ->
|
||||||
val route = backStackEntry.toRoute<EntityBrowseRoute>()
|
val route = backStackEntry.toRoute<EntityBrowseRoute>()
|
||||||
|
val onBack = rememberGuardedPopBackStack(
|
||||||
|
navController = navController,
|
||||||
|
backStackEntry = backStackEntry,
|
||||||
|
)
|
||||||
|
PlatformBackHandler(
|
||||||
|
enabled = true,
|
||||||
|
onBack = onBack,
|
||||||
|
)
|
||||||
TmdbEntityBrowseScreen(
|
TmdbEntityBrowseScreen(
|
||||||
entityKind = TmdbEntityKind.fromRouteValue(route.entityKind),
|
entityKind = TmdbEntityKind.fromRouteValue(route.entityKind),
|
||||||
entityId = route.entityId,
|
entityId = route.entityId,
|
||||||
entityName = route.entityName,
|
entityName = route.entityName,
|
||||||
sourceType = route.sourceType,
|
sourceType = route.sourceType,
|
||||||
onBack = { navController.popBackStack() },
|
onBack = onBack,
|
||||||
onOpenMeta = { preview ->
|
onOpenMeta = { preview ->
|
||||||
coroutineScope.launch {
|
coroutineScope.launch {
|
||||||
val resolvedId = if (preview.id.startsWith("tmdb:")) {
|
val resolvedId = if (preview.id.startsWith("tmdb:")) {
|
||||||
|
|
@ -1145,6 +1167,15 @@ private fun MainAppContent(
|
||||||
}
|
}
|
||||||
composable<StreamRoute> { backStackEntry ->
|
composable<StreamRoute> { backStackEntry ->
|
||||||
val route = backStackEntry.toRoute<StreamRoute>()
|
val route = backStackEntry.toRoute<StreamRoute>()
|
||||||
|
val onBack = rememberGuardedPopBackStack(
|
||||||
|
navController = navController,
|
||||||
|
backStackEntry = backStackEntry,
|
||||||
|
beforePop = { StreamsRepository.clear() },
|
||||||
|
)
|
||||||
|
PlatformBackHandler(
|
||||||
|
enabled = true,
|
||||||
|
onBack = onBack,
|
||||||
|
)
|
||||||
val launch = remember(route.launchId) {
|
val launch = remember(route.launchId) {
|
||||||
StreamLaunchStore.get(route.launchId)
|
StreamLaunchStore.get(route.launchId)
|
||||||
}
|
}
|
||||||
|
|
@ -1410,10 +1441,7 @@ private fun MainAppContent(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onBack = {
|
onBack = onBack,
|
||||||
StreamsRepository.clear()
|
|
||||||
navController.popBackStack()
|
|
||||||
},
|
|
||||||
modifier = Modifier.fillMaxSize(),
|
modifier = Modifier.fillMaxSize(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -1432,6 +1460,18 @@ private fun MainAppContent(
|
||||||
},
|
},
|
||||||
) { backStackEntry ->
|
) { backStackEntry ->
|
||||||
val route = backStackEntry.toRoute<PlayerRoute>()
|
val route = backStackEntry.toRoute<PlayerRoute>()
|
||||||
|
val onBack = rememberGuardedPopBackStack(
|
||||||
|
navController = navController,
|
||||||
|
backStackEntry = backStackEntry,
|
||||||
|
beforePop = {
|
||||||
|
ResumePromptRepository.markPlayerExitedNormally()
|
||||||
|
PlayerLaunchStore.remove(route.launchId)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
PlatformBackHandler(
|
||||||
|
enabled = true,
|
||||||
|
onBack = onBack,
|
||||||
|
)
|
||||||
val launch = remember(route.launchId) { PlayerLaunchStore.get(route.launchId) }
|
val launch = remember(route.launchId) { PlayerLaunchStore.get(route.launchId) }
|
||||||
if (launch == null) {
|
if (launch == null) {
|
||||||
LaunchedEffect(route.launchId) {
|
LaunchedEffect(route.launchId) {
|
||||||
|
|
@ -1468,16 +1508,21 @@ private fun MainAppContent(
|
||||||
parentMetaType = launch.parentMetaType,
|
parentMetaType = launch.parentMetaType,
|
||||||
initialPositionMs = launch.initialPositionMs,
|
initialPositionMs = launch.initialPositionMs,
|
||||||
initialProgressFraction = launch.initialProgressFraction,
|
initialProgressFraction = launch.initialProgressFraction,
|
||||||
onBack = {
|
onBack = onBack,
|
||||||
ResumePromptRepository.markPlayerExitedNormally()
|
|
||||||
PlayerLaunchStore.remove(route.launchId)
|
|
||||||
navController.popBackStack()
|
|
||||||
},
|
|
||||||
modifier = Modifier.fillMaxSize(),
|
modifier = Modifier.fillMaxSize(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
composable<CatalogRoute> { backStackEntry ->
|
composable<CatalogRoute> { backStackEntry ->
|
||||||
val route = backStackEntry.toRoute<CatalogRoute>()
|
val route = backStackEntry.toRoute<CatalogRoute>()
|
||||||
|
val onBack = rememberGuardedPopBackStack(
|
||||||
|
navController = navController,
|
||||||
|
backStackEntry = backStackEntry,
|
||||||
|
beforePop = { CatalogRepository.clear() },
|
||||||
|
)
|
||||||
|
PlatformBackHandler(
|
||||||
|
enabled = true,
|
||||||
|
onBack = onBack,
|
||||||
|
)
|
||||||
CatalogScreen(
|
CatalogScreen(
|
||||||
title = route.title,
|
title = route.title,
|
||||||
subtitle = route.subtitle,
|
subtitle = route.subtitle,
|
||||||
|
|
@ -1486,10 +1531,7 @@ private fun MainAppContent(
|
||||||
catalogId = route.catalogId,
|
catalogId = route.catalogId,
|
||||||
supportsPagination = route.supportsPagination,
|
supportsPagination = route.supportsPagination,
|
||||||
genre = route.genre,
|
genre = route.genre,
|
||||||
onBack = {
|
onBack = onBack,
|
||||||
CatalogRepository.clear()
|
|
||||||
navController.popBackStack()
|
|
||||||
},
|
|
||||||
onPosterClick = { meta ->
|
onPosterClick = { meta ->
|
||||||
navController.navigate(DetailRoute(type = meta.type, id = meta.id))
|
navController.navigate(DetailRoute(type = meta.type, id = meta.id))
|
||||||
},
|
},
|
||||||
|
|
@ -1618,24 +1660,32 @@ private fun MainAppContent(
|
||||||
}
|
}
|
||||||
composable<CollectionEditorRoute> { backStackEntry ->
|
composable<CollectionEditorRoute> { backStackEntry ->
|
||||||
val route = backStackEntry.toRoute<CollectionEditorRoute>()
|
val route = backStackEntry.toRoute<CollectionEditorRoute>()
|
||||||
|
val onBack = rememberGuardedPopBackStack(
|
||||||
|
navController = navController,
|
||||||
|
backStackEntry = backStackEntry,
|
||||||
|
beforePop = { CollectionEditorRepository.clear() },
|
||||||
|
)
|
||||||
CollectionEditorScreen(
|
CollectionEditorScreen(
|
||||||
collectionId = route.collectionId,
|
collectionId = route.collectionId,
|
||||||
onBack = {
|
onBack = onBack,
|
||||||
CollectionEditorRepository.clear()
|
|
||||||
navController.popBackStack()
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
composable<FolderDetailRoute> { backStackEntry ->
|
composable<FolderDetailRoute> { backStackEntry ->
|
||||||
val route = backStackEntry.toRoute<FolderDetailRoute>()
|
val route = backStackEntry.toRoute<FolderDetailRoute>()
|
||||||
|
val onBack = rememberGuardedPopBackStack(
|
||||||
|
navController = navController,
|
||||||
|
backStackEntry = backStackEntry,
|
||||||
|
beforePop = { FolderDetailRepository.clear() },
|
||||||
|
)
|
||||||
|
PlatformBackHandler(
|
||||||
|
enabled = true,
|
||||||
|
onBack = onBack,
|
||||||
|
)
|
||||||
LaunchedEffect(route.collectionId, route.folderId) {
|
LaunchedEffect(route.collectionId, route.folderId) {
|
||||||
FolderDetailRepository.initialize(route.collectionId, route.folderId)
|
FolderDetailRepository.initialize(route.collectionId, route.folderId)
|
||||||
}
|
}
|
||||||
FolderDetailScreen(
|
FolderDetailScreen(
|
||||||
onBack = {
|
onBack = onBack,
|
||||||
FolderDetailRepository.clear()
|
|
||||||
navController.popBackStack()
|
|
||||||
},
|
|
||||||
onCatalogClick = onCatalogClick,
|
onCatalogClick = onCatalogClick,
|
||||||
onPosterClick = { meta ->
|
onPosterClick = { meta ->
|
||||||
navController.navigate(DetailRoute(type = meta.type, id = meta.id))
|
navController.navigate(DetailRoute(type = meta.type, id = meta.id))
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue