layout and remote fix
🏗️ Build and Test JellyTau / Run Tests (push) Successful in 4m31s
Traceability Validation / Check Requirement Traces (push) Successful in 20s
Build & Release / Run Tests (push) Successful in 5m24s
🏗️ Build and Test JellyTau / Android Compile Check (push) Successful in 4m29s
Build & Release / Build Linux (push) Successful in 17m27s
Build & Release / Build Android (push) Successful in 22m14s
Build & Release / Create Release (push) Successful in 12s

This commit is contained in:
2026-07-16 22:53:03 +02:00
parent 532ffa661a
commit 1992a8187d
10 changed files with 272 additions and 192 deletions
+64
View File
@@ -0,0 +1,64 @@
<!--
BottomUi — the app's bottom UI (mini player stacked over the bottom nav).
Rendered as an IN-FLOW flex child at the bottom of a full-height flex column,
NOT a fixed overlay. This is the whole point: because it is a normal flex
sibling below the scroll container (which is `flex-1 min-h-0 overflow-y-auto`),
the scroller is physically bounded above it and can never render behind it.
This replaces the old ResizeObserver + `bottomUiHeight` + padding-reservation
scheme, which started at 0, updated async, and repeatedly regressed into the
"last row hidden behind the nav" bug. There is nothing to measure or reserve:
the browser's flex layout does it exactly, every frame.
The Android system gesture bar is cleared via `env(safe-area-inset-bottom)`.
TRACES: UR-005 | DR-009
-->
<script lang="ts">
import { goto } from "$app/navigation";
import { currentMedia, isPlaying, playbackPosition, playbackDuration } from "$lib/stores/player";
import { isShuffle, repeatMode, hasNext, hasPrevious } from "$lib/stores/queue";
import { showSleepTimerModal } from "$lib/stores/appState";
import MiniPlayer from "$lib/components/player/MiniPlayer.svelte";
import BottomNav from "$lib/components/BottomNav.svelte";
let {
showMiniPlayer = true,
showNav = true,
onExpand,
}: {
showMiniPlayer?: boolean;
showNav?: boolean;
// Where "expand mini player" goes. Defaults to the full player route.
onExpand?: () => void;
} = $props();
function expand() {
if (onExpand) return onExpand();
if ($currentMedia) goto(`/player/${$currentMedia.id}`);
}
</script>
<!-- flex-shrink-0 so it keeps its natural height; the scroller sibling flexes. -->
<div class="flex-shrink-0 pb-[env(safe-area-inset-bottom)] bg-[var(--color-surface)]">
{#if showMiniPlayer}
<MiniPlayer
media={$currentMedia}
isPlaying={$isPlaying}
position={$playbackPosition}
duration={$playbackDuration}
shuffle={$isShuffle}
repeat={$repeatMode}
hasNext={$hasNext}
hasPrevious={$hasPrevious}
className="flex-shrink-0"
onExpand={expand}
onSleepTimerClick={() => showSleepTimerModal.set(true)}
/>
{/if}
{#if showNav}
<BottomNav className="flex-shrink-0" />
{/if}
</div>