fix(settings): route topbar Settings through NavigationController + Clear Token button

B7 (Jun 18 2026): user reported Settings page unresponsive when
reached via the ChatScreen topbar gear icon, but worked fine via
the drawer sidebar. Two fixes:

1. Route topbar gear through NavigationController.navigateTo()
   instead of raw backStack.add(). The NavigationController path
   (used by the drawer) deduplicates against the current top
   entry and matches the drawer's navigation flow exactly. The
   bypass path could stack duplicate SettingsScreen entries on
   rapid taps, which likely caused the unresponsive symptom.

2. Add 'Clear Token' OutlinedButton below the Auth Token field in
   Settings. One-tap wipes a corrupted / rejected token and saves
   immediately, without having to select-and-delete the masked
   password field character by character. Recovers from the
   'I gave you a bad token' scenario in seconds.
This commit is contained in:
ronia committed 2026-06-18 03:56:04 +03:00
1 parent 8d3894b7c7
commit f833005bec
2 files changed
+30 -1

No files matched your search

@@ -244,7 +244,19 @@ fun MainNavigation() {
entry<ChatScreen> {
ChatScreenContent(
onNavigateToSettings = {
backStack.add(SettingsScreen)
// B7 (Jun 18 2026): previously used
// `backStack.add(SettingsScreen)` directly,
// which bypasses NavigationController's
// navigation guard. The drawer Settings path
// goes through NavigationController which
// deduplicates and prevents stacking duplicate
// SettingsScreen entries when user rapidly
// taps the gear icon. Use the same path for
// consistency and to recover if a duplicate
// SettingsScreen entry was the source of the
// "page unresponsive" symptom reported when
// reaching Settings from the topbar.
NavigationController.navigateTo(SettingsScreen)
},
onOpenDrawer = { openDrawer() },
)
@@ -175,6 +175,23 @@ fun SettingsScreen(
cursorColor = MaterialTheme.colorScheme.primary,
),
)
Spacer(modifier = Modifier.height(8.dp))
// B7 (Jun 18 2026): one-tap escape hatch for when the stored
// token is corrupted / rejected. Clears the token field and
// persists the empty value immediately so a stress-free
// re-pair is possible without manually selecting-and-deleting
// the masked password field character by character.
OutlinedButton(
onClick = {
viewModel.onTokenChange("")
viewModel.save()
},
modifier = Modifier.fillMaxWidth(),
) {
Text("Clear Token")
}
}
// Behavior section