From f4e6b7fef16a026403cec26e9ac49ff6b6851df0 Mon Sep 17 00:00:00 2001 From: tapframe <85391825+tapframe@users.noreply.github.com> Date: Tue, 7 Apr 2026 01:24:39 +0530 Subject: [PATCH] feat: implement guarded back navigation for settings screens --- .../commonMain/kotlin/com/nuvio/app/App.kt | 77 +++++++++++++++---- 1 file changed, 64 insertions(+), 13 deletions(-) diff --git a/composeApp/src/commonMain/kotlin/com/nuvio/app/App.kt b/composeApp/src/commonMain/kotlin/com/nuvio/app/App.kt index 8e45aaad..610bf5d2 100644 --- a/composeApp/src/commonMain/kotlin/com/nuvio/app/App.kt +++ b/composeApp/src/commonMain/kotlin/com/nuvio/app/App.kt @@ -58,8 +58,11 @@ import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.compose.ui.zIndex import androidx.lifecycle.compose.collectAsStateWithLifecycle +import androidx.navigation.NavBackStackEntry +import androidx.navigation.NavHostController import androidx.navigation.compose.NavHost import androidx.navigation.compose.composable +import androidx.navigation.compose.currentBackStackEntryAsState import androidx.navigation.compose.rememberNavController import androidx.navigation.toRoute import coil3.ImageLoader @@ -1096,40 +1099,68 @@ private fun MainAppContent( ) } composable { + val onBack = rememberGuardedPopBackStack( + navController = navController, + backStackEntry = it, + ) HomescreenSettingsScreen( - onBack = { navController.popBackStack() }, + onBack = onBack, ) } - composable { + composable { backStackEntry -> + val onBack = rememberGuardedPopBackStack( + navController = navController, + backStackEntry = backStackEntry, + ) MetaScreenSettingsScreen( - onBack = { navController.popBackStack() }, + onBack = onBack, ) } - composable { + composable { backStackEntry -> + val onBack = rememberGuardedPopBackStack( + navController = navController, + backStackEntry = backStackEntry, + ) ContinueWatchingSettingsScreen( - onBack = { navController.popBackStack() }, + onBack = onBack, ) } - composable { + composable { backStackEntry -> + val onBack = rememberGuardedPopBackStack( + navController = navController, + backStackEntry = backStackEntry, + ) AddonsSettingsScreen( - onBack = { navController.popBackStack() }, + onBack = onBack, ) } if (AppFeaturePolicy.pluginsEnabled) { - composable { + composable { backStackEntry -> + val onBack = rememberGuardedPopBackStack( + navController = navController, + backStackEntry = backStackEntry, + ) PluginsSettingsScreen( - onBack = { navController.popBackStack() }, + onBack = onBack, ) } } - composable { + composable { backStackEntry -> + val onBack = rememberGuardedPopBackStack( + navController = navController, + backStackEntry = backStackEntry, + ) AccountSettingsScreen( - onBack = { navController.popBackStack() }, + onBack = onBack, ) } - composable { + composable { backStackEntry -> + val onBack = rememberGuardedPopBackStack( + navController = navController, + backStackEntry = backStackEntry, + ) CollectionManagementScreen( - onBack = { navController.popBackStack() }, + onBack = onBack, onNavigateToEditor = { collectionId -> navController.navigate(CollectionEditorRoute(collectionId = collectionId)) }, @@ -1273,6 +1304,26 @@ private fun MainAppContent( } } +@Composable +private fun rememberGuardedPopBackStack( + navController: NavHostController, + backStackEntry: NavBackStackEntry, + beforePop: () -> Unit = {}, +): () -> Unit { + val currentBackStackEntry by navController.currentBackStackEntryAsState() + var popHandled by remember(backStackEntry) { mutableStateOf(false) } + + return remember(navController, backStackEntry, currentBackStackEntry, popHandled, beforePop) { + { + if (!popHandled && currentBackStackEntry == backStackEntry) { + popHandled = true + beforePop() + navController.popBackStack() + } + } + } +} + @Composable private fun AppTabHost( selectedTab: AppScreenTab,