@@ -15,11 +15,16 @@ import androidx.compose.foundation.layout.Row
1515import androidx.compose.foundation.layout.Spacer
1616import androidx.compose.foundation.layout.WindowInsets
1717import androidx.compose.foundation.layout.asPaddingValues
18+ import androidx.compose.foundation.layout.displayCutout
1819import androidx.compose.foundation.layout.displayCutoutPadding
1920import androidx.compose.foundation.layout.fillMaxSize
2021import androidx.compose.foundation.layout.fillMaxWidth
22+ import androidx.compose.foundation.layout.only
2123import androidx.compose.foundation.layout.padding
2224import androidx.compose.foundation.layout.statusBars
25+ import androidx.compose.foundation.layout.union
26+ import androidx.compose.foundation.layout.windowInsetsPadding
27+ import androidx.compose.foundation.layout.WindowInsetsSides
2328import androidx.compose.foundation.layout.width
2429import androidx.compose.foundation.lazy.LazyListState
2530import androidx.compose.foundation.lazy.rememberLazyListState
@@ -459,17 +464,25 @@ private fun LibraryScreenContent(
459464 }
460465
461466
462- // Apply top padding differently for list vs game detail pages.
463- // On the game page we want to hide the top padding when the status bar is hidden.
464- val safePaddingModifier = if (selectedLibraryItem != null ) {
465- // Detail (game) page: use actual status bar height when status bar is visible,
466- // or 0.dp when status bar is hidden
467- val topPadding = if (PrefManager .hideStatusBarWhenNotInGame) {
468- 0 .dp
469- } else {
470- WindowInsets .statusBars.asPaddingValues().calculateTopPadding()
471- }
472- Modifier .padding(top = topPadding)
467+ // Padding for the library *list* view (tab bar, grid, search bar) so content
468+ // never draws behind the display cutout. The window now opts in to
469+ // LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES via Theme.Pluvia, so:
470+ // * Status bar visible (portrait): statusBars insets already cover the top notch.
471+ // * Status bar hidden (portrait): statusBars insets are 0; displayCutout supplies
472+ // the notch height so content isn't behind the notch.
473+ // * Landscape (cutout on a side): statusBars is top-only; displayCutout supplies
474+ // the side inset so the tab bar isn't clipped.
475+ // Bottom is intentionally excluded so scroll content can reach the bottom edge.
476+ //
477+ // The detail (game) page deliberately does NOT use this — the hero image is meant
478+ // to bleed through the cutout, so AppScreenContent insets only the elements that
479+ // need to stay tappable (e.g. the back button) instead.
480+ val safePaddingModifier = if (selectedLibraryItem == null ) {
481+ Modifier .windowInsetsPadding(
482+ WindowInsets .statusBars
483+ .union(WindowInsets .displayCutout)
484+ .only(WindowInsetsSides .Top + WindowInsetsSides .Horizontal ),
485+ )
473486 } else {
474487 Modifier
475488 }
0 commit comments