docs: add #424 lessons — drawer scrim fix, ViewModel state cleanup, WS lifecycle patterns

This commit is contained in:
M57 committed 2026-06-30 17:13:29 +03:00
1 parent d4320a9289
commit d80e4dc7b1
1 file changed
+40
+40
View File
@@ -73,6 +73,46 @@ Uses `androidx.navigation3` (`NavKey`, `NavBackStack`, `NavDisplay`, `entry<T>`)
deduplication guard. Bypassing it stacks duplicate screen entries that compete for deduplication guard. Bypassing it stacks duplicate screen entries that compete for
touch events and become unresponsive. touch events and become unresponsive.
**⚠ Drawer scrim gets stuck when navigating to a non-gesture screen.** Screens
not in `DRAWER_GESTURE_SCREENS` disable drawer gestures. If the drawer is open
when this happens, the scrim stays visible and blocks touch. Always pair gesture
transitions with a `LaunchedEffect`:
```kotlin
LaunchedEffect(gesturesEnabled) {
if (!gesturesEnabled && drawerState.isOpen) {
drawerState.snapTo(DrawerValue.Closed)
}
}
```
### Activity-Scoped ViewModels
Some ViewModels (e.g. `AuthLoginViewModel`) are created at the Activity scope via
`viewModel()` at the navigation entry level. This means they **survive navigation**
and cached state like `connectionSuccess` persists across screen entries.
Always pair transient state flags with a `DisposableEffect` cleanup:
```kotlin
DisposableEffect(Unit) {
onDispose { viewModel.clearTransientState() }
}
```
The cleanup function should reset self-transitioning flags (`connectionSuccess`,
`isLoading`, `errorMessage`) so the screen can re-enter cleanly.
### WebSocket Lifecycle
`HermesWsClient` is a singleton that outlives individual screens. It must be
explicitly disconnected on logout and reconnected after login:
| Event | Action |
|-------|--------|
| Logout | `HermesWsClient.disconnect()` before clearing tokens |
| Login success | `HermesWsClient.connect()` after `ApiClient.rebuild()` |
The singleton's `connect()` has a guard (`if connected → skip`) so it's safe to
call unconditionally.
### Shared Components ### Shared Components
- **`HermesScaffold`** — drawer-aware Scaffold + TopAppBar with refresh slot, - **`HermesScaffold`** — drawer-aware Scaffold + TopAppBar with refresh slot,