refactor(#619): kill DRAWER_GESTURE_SCREENS — screen-owned drawer gestures via HermesScaffold (#624)

Replaces the fragile DRAWER_GESTURE_SCREENS global set + defensive
LaunchedEffect(snapTo(Closed)) + closeDrawer callback workaround with a
single source of truth: each screen declares its drawer-gesture preference
via HermesScaffold's new drawerGesturesEnabled parameter (default true).

Architecture:
- DrawerGestureController holds the active gesture state. HermesScaffold
  reconciles each screen's preference into it via SideEffect; when a screen
  opts out while the drawer is open, the controller closes the drawer itself.
- LocalDrawerGestureController CompositionLocal flows the controller from
  MainNavigation down to ModalNavigationDrawer, which reads .enabled and
  passes it to Material's gesturesEnabled parameter.
- DisableDrawerGestures() helper for entry screens that don't use
  HermesScaffold (Landing, AuthLogin, PairingCodeEntry).
- All 6 Settings drill-down sub-pages pass drawerGesturesEnabled = false.
- NavigationController.closeDrawer removed; navigateTo no longer needs a
  synchronous drawer-dismiss hook.

Removes: DRAWER_GESTURE_SCREENS set, both LaunchedEffect(gesturesEnabled)
and LaunchedEffect(drawerGesturesEnabled) blocks, drawerGesturesEnabled
local state, closeDrawer callback on NavigationController.

Fixes the recurring drawer-scrim stuck-open bug class (PRs #445, #454, #455).

Verified: ktlintCheck, assembleDebug, testDebugUnitTest all green locally.

Co-authored-by: Hy4ri <hy4ri@users.noreply.github.com>
This commit is contained in:
M57andHy4ri authored and GitHub committed 2026-07-18 14:25:23 +03:00
1 parent 0c2b9679b7
commit 0a0b612d3a
5 files changed
+297 -204

No files matched your search

@@ -39,6 +39,10 @@ import com.m57.hermescontrol.ui.settings.components.TestResultCard
* Drill-down sub-pages for Settings. Each is its own NavKey destination
* (see Navigation.kt) so the native back stack handles navigation — no
* manual routing. The SettingsViewModel stays the single source of truth.
*
* All sub-pages pass `drawerGesturesEnabled = false` to [HermesScaffold] so the
* modal drawer's swipe gestures are disabled and the drawer auto-closes when a
* sub-page is entered — the single source of truth introduced in issue #619.
*/
@Composable
@@ -53,6 +57,9 @@ internal fun SettingsConnectionPage(
HermesScaffold(
title = { Text(stringResource(R.string.settings_sec_connection)) },
navigationIcon = NavIcon.Back(onBack),
// Non-primary drill-down: opt out of drawer gestures so the scrim can't
// get stuck open (issue #619). DrawerGestureController handles the close.
drawerGesturesEnabled = false,
) {
Column(
modifier =
@@ -104,6 +111,7 @@ internal fun SettingsAppearancePage(
HermesScaffold(
title = { Text(stringResource(R.string.settings_sec_appearance)) },
navigationIcon = NavIcon.Back(onBack),
drawerGesturesEnabled = false,
) {
Column(
modifier =
@@ -137,6 +145,7 @@ internal fun SettingsChatPage(
HermesScaffold(
title = { Text(stringResource(R.string.settings_sec_chat)) },
navigationIcon = NavIcon.Back(onBack),
drawerGesturesEnabled = false,
) {
Column(
modifier =
@@ -166,6 +175,7 @@ internal fun SettingsNavBarPage(
HermesScaffold(
title = { Text(stringResource(R.string.settings_sec_nav_bar)) },
navigationIcon = NavIcon.Back(onBack),
drawerGesturesEnabled = false,
) {
Column(
modifier =
@@ -198,6 +208,7 @@ internal fun SettingsBehaviorPage(
HermesScaffold(
title = { Text(stringResource(R.string.settings_sec_behavior)) },
navigationIcon = NavIcon.Back(onBack),
drawerGesturesEnabled = false,
) {
Column(
modifier =
@@ -224,6 +235,7 @@ internal fun SettingsAboutPage(
HermesScaffold(
title = { Text(stringResource(R.string.settings_sec_about)) },
navigationIcon = NavIcon.Back(onBack),
drawerGesturesEnabled = false,
) {
Column(
modifier =