fix(sheets): size sheets to their content instead of 75% of the window

Sheets rendered at the host's maximum height regardless of content, so a
one-item player queue or a two-track picker filled ~75% of a desktop window
with empty space.

BottomSheetPageScaffold now always lays out Column(mainAxisSize: .min) plus
Flexible(child:), and each sheet body shrink-wraps its own scrollable. The
scaffold's shrinkWrap flag is gone: its old true branch put the child on an
unbounded axis, where an over-tall list overflowed instead of clamping and
scrolling. Measured on a 1600x1000 window, the chapter sheet goes from 750px
to 118px for one chapter and the two-column track sheet from 750px to 154px
for one audio and one subtitle track, both still clamping at the cap.

Add SheetSplitColumns for the three side-by-side sheet layouts. A bare
VerticalDivider has no intrinsic height, so it inflated those rows to the cap
on its own; the rule now paints from a Positioned.fill that cannot size the
Stack. IntrinsicHeight is not an option because a Viewport has no intrinsics.

Because sheets are bottom-anchored, a content-driven height moves the sheet's
top edge and everything above the change point. Three surfaces opt out for
that reason and say so at the call site: SubtitleSearchSheet and its language
picker keep filling, since both refilter under an autofocused field;
FiltersBottomSheet holds the outgoing page's height through its loading
transient; and RatingBottomSheet no longer hides MAL/AniList rows
asynchronously, which used to slide live rating controls down two rows several
hundred ms after open. Wrap the shared StateMessageWidget at the filters sheet
boundary rather than editing a widget with 33 filling call sites.

The host gains an AnimatedSize keyed per sheet session so nested pushes ease
while a replacing show adopts its own height, a 720px absolute height ceiling
on desktop windows only, and a min(max(25%, 96px), 60%) drag-dismiss threshold
so short sheets neither close on a nudge nor become undismissable.

Add videoControls.noAudioDevicesAvailable so the audio output page shows a
placeholder instead of a bare header while devices load.
This commit is contained in:
edde746
2026-08-08 00:37:17 +02:00
parent e3703892b3
commit 24a041977b
71 changed files with 1210 additions and 207 deletions
+6 -2
View File
@@ -2026,6 +2026,9 @@ class Translations$videoControls$en {
/// en: 'No items in queue'
String get noQueueItems => 'No items in queue';
/// en: 'No audio devices available'
String get noAudioDevicesAvailable => 'No audio devices available';
/// en: 'Search Subtitles'
String get searchSubtitles => 'Search Subtitles';
@@ -6758,6 +6761,7 @@ extension on Translations {
'videoControls.noChaptersAvailable' => 'No chapters available',
'videoControls.queue' => 'Queue',
'videoControls.noQueueItems' => 'No items in queue',
'videoControls.noAudioDevicesAvailable' => 'No audio devices available',
'videoControls.searchSubtitles' => 'Search Subtitles',
'videoControls.language' => 'Language',
'videoControls.noSubtitlesFound' => 'No subtitles found',
@@ -7143,9 +7147,9 @@ extension on Translations {
'explore.badge.requested' => 'Requested',
'explore.badge.pendingApproval' => 'Pending approval',
'explore.badge.processing' => 'Processing',
'explore.badge.declined' => 'Declined',
_ => null,
} ?? switch (path) {
'explore.badge.declined' => 'Declined',
'explore.badge.requestFailed' => 'Request failed',
'explore.badge.requested4k' => '4K requested',
'explore.badge.seasonsAvailable' => ({required Object available, required Object total}) => '${available}/${total} seasons',
@@ -7657,9 +7661,9 @@ extension on Translations {
'performanceOverlay.dropped' => 'Dropped',
'performanceOverlay.dvRpus' => 'DV RPUs',
'performanceOverlay.dvRpuAverage' => 'DV RPU Avg',
'performanceOverlay.dvSampleAverage' => 'DV Sample Avg',
_ => null,
} ?? switch (path) {
'performanceOverlay.dvSampleAverage' => 'DV Sample Avg',
'performanceOverlay.maxLuma' => 'Max Luma',
'performanceOverlay.minLuma' => 'Min Luma',
'performanceOverlay.maxCll' => 'MaxCLL',