From 92761f6046320cb84c0583983c8322e237a521c3 Mon Sep 17 00:00:00 2001 From: fabiodalez-dev Date: Fri, 26 Jun 2026 00:21:33 +0200 Subject: [PATCH] fix(app): readable system bars + reservation error no longer hidden by the calendar - System bars: with edge-to-edge the status/navigation bar icons followed the SYSTEM dark mode, so a light app under a dark-mode phone showed white soft- button/status icons on a light background (invisible). PinakesTheme now sets isAppearanceLight{Status,Navigation}Bars from the APP theme. - Reserve error: on a failed reservation (e.g. "you already have an active request") the calendar DatePickerDialog stayed open, so the error snackbar rendered behind it. Close the loan sheet on failure too, so the message shows. --- .../ui/screens/detail/BookDetailViewModel.kt | 8 +++++--- .../java/com/pinakes/app/ui/theme/Theme.kt | 19 +++++++++++++++++++ 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/com/pinakes/app/ui/screens/detail/BookDetailViewModel.kt b/app/src/main/java/com/pinakes/app/ui/screens/detail/BookDetailViewModel.kt index 0511b01..55e316c 100644 --- a/app/src/main/java/com/pinakes/app/ui/screens/detail/BookDetailViewModel.kt +++ b/app/src/main/java/com/pinakes/app/ui/screens/detail/BookDetailViewModel.kt @@ -136,13 +136,15 @@ class BookDetailViewModel( load() } is ApiResult.Failure -> { + // Close the calendar dialog so the error is visible: the snackbar + // lives at the screen Scaffold level, behind the open DatePickerDialog. when { res.code == ErrorCodes.CONFLICT -> - _state.update { it.copy(reserveBusy = false, snackbar = null, snackbarRes = R.string.snackbar_request_conflict) } + _state.update { it.copy(reserveBusy = false, showLoanSheet = false, snackbar = null, snackbarRes = R.string.snackbar_request_conflict) } res.message.isNotBlank() -> - _state.update { it.copy(reserveBusy = false, snackbar = res.message, snackbarRes = null) } + _state.update { it.copy(reserveBusy = false, showLoanSheet = false, snackbar = res.message, snackbarRes = null) } else -> - _state.update { it.copy(reserveBusy = false, snackbar = null, snackbarRes = R.string.snackbar_request_error) } + _state.update { it.copy(reserveBusy = false, showLoanSheet = false, snackbar = null, snackbarRes = R.string.snackbar_request_error) } } } } diff --git a/app/src/main/java/com/pinakes/app/ui/theme/Theme.kt b/app/src/main/java/com/pinakes/app/ui/theme/Theme.kt index 09cc867..890bfc0 100644 --- a/app/src/main/java/com/pinakes/app/ui/theme/Theme.kt +++ b/app/src/main/java/com/pinakes/app/ui/theme/Theme.kt @@ -1,8 +1,12 @@ package com.pinakes.app.ui.theme +import android.app.Activity import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable +import androidx.compose.runtime.SideEffect +import androidx.compose.ui.platform.LocalView +import androidx.core.view.WindowCompat /** User-selectable theme. Default is [LIGHT] (DESIGN.md: "Light is the default theme"). */ enum class ThemeMode { LIGHT, DARK, SYSTEM } @@ -17,6 +21,21 @@ fun PinakesTheme( ThemeMode.DARK -> true ThemeMode.SYSTEM -> isSystemInDarkTheme() } + + // With edge-to-edge the status/navigation bars are transparent, so the system + // soft-button + status icons must follow the APP theme, not the system dark + // mode — otherwise a light app under a dark-mode system shows white icons on a + // light background (invisible). Light theme → dark icons; dark theme → light. + val view = LocalView.current + if (!view.isInEditMode) { + SideEffect { + val window = (view.context as Activity).window + val controller = WindowCompat.getInsetsController(window, view) + controller.isAppearanceLightStatusBars = !dark + controller.isAppearanceLightNavigationBars = !dark + } + } + MaterialTheme( colorScheme = if (dark) DarkColors else LightColors, typography = PinakesTypography,