diff --git a/app/src/main/java/com/aicode/MainActivity.kt b/app/src/main/java/com/aicode/MainActivity.kt index 793eeceb..3654cfdd 100644 --- a/app/src/main/java/com/aicode/MainActivity.kt +++ b/app/src/main/java/com/aicode/MainActivity.kt @@ -389,6 +389,22 @@ fun AppNavigation( scope.launch { drawerState.close() } } + // 返回栈兑底:栈里只剩当前目的地、且当前不在聊天页时,返回键改为回聊天页, + // 而不是让系统把栈弹空(白屏)。 + // 背景:历史上终端/Git/设置都用裸 navigate 压栈,任何一处状态错乱都可能让用户 + // 站在一个「栈根不是 chat」的怪状态里;逐个修入口永远有漏网的(predictive back + // 的边缘手势还能把人带进设置),所以在最外层兑底,保证白屏不可能再出现。 + // 注意 enabled 条件里排除 chat:在聊天页返回就该退出应用,不能被兑底拦截。 + val canFallbackToChat = currentRoute != null && currentRoute != "chat" && + navController.currentBackStackEntry?.lifecycle?.currentState == androidx.lifecycle.Lifecycle.State.RESUMED && + navController.previousBackStackEntry == null // 再弹就空了(没有上一层) + BackHandler(enabled = canFallbackToChat) { + navController.navigate("chat") { + popUpTo(navController.graph.startDestinationRoute ?: "chat") { inclusive = true } + launchSingleTop = true + } + } + // 侧边栏需要的数据。 val currentWorkspace by workspaceViewModel.current.collectAsStateWithLifecycle() androidx.compose.runtime.LaunchedEffect(currentWorkspace) { @@ -516,6 +532,10 @@ fun AppNavigation( } // 终端 / Git:大屏在右栏内开合切换,窄窗跳全屏页。 + // 窄窗 navigate 用 popUpTo("chat") { saveState = true } + launchSingleTop:不这样, + // 每次开终端/Git 都往返回栈里压一层,用户连按几次返回会穿到空栈(白屏), + // 再从预览手势右滑反而能切到设置页,而设置页的 BackHandler 又把返回键全吞了 → 卡死。 + // popUpTo 折叠栈后,返回键从终端/Git 只会回聊天页,不会进入空栈。 val openWorkbench: (WorkbenchPaneKind) -> Unit = { target -> if (expanded) { paneKind = if (paneKind == target) WorkbenchPaneKind.NONE else target @@ -526,7 +546,10 @@ fun AppNavigation( WorkbenchPaneKind.BROWSER -> "browser" else -> "chat" } - navController.navigate(route) + navController.navigate(route) { + popUpTo("chat") { saveState = true } + launchSingleTop = true + } } } @@ -697,7 +720,17 @@ fun AppNavigation( SettingsScreen( viewModel = settingsViewModel, onNavigateBack = { - navController.popBackStack() + // 设置页内部的 BackHandler 在有上一层时会吞掉返回键(用于内部层级返回), + // 走到这里说明已在首页菜单层;若返回栈被弄乱导致栈里没有 "chat" 了 + // (终端/Git 历史上会把栈压穿),popBackStack 会无事发生且留在设置页 → + // 用户怎么按返回都出不去(卡死)。所以这里用 navigate 回聊天页, + // 不依赖返回栈是否完好。 + navController.navigate("chat") { + popUpTo(navController.graph.startDestinationRoute ?: "chat") { + inclusive = true + } + launchSingleTop = true + } // 大屏返回聊天页后侧栏本就常驻,不再弹 modal 抽屉。 if (!expanded) scope.launch { drawerState.open() } },