fix: allow compact mode while media is loading

This commit is contained in:
2026-10-12 12:00:56 +02:00
parent f495c8b719
commit 1e75f554f0
6 changed files with 93 additions and 25 deletions
+6
View File
@@ -190,6 +190,8 @@ Opening video fits the window to its display aspect ratio, including non-square
**Compact mode** uses the same window, Metal view, and playback session—not a second window or macOS system PiP. Use the PiP-shaped button in the normal playback controls, **⌃⌘P**, or **Playback Actions → Enter Compact Mode**. The compact-mode button replaces the fullscreen button; fullscreen remains available through its menu, keyboard shortcuts, and double-clicking normal-mode video. Compact mode starts at the current screen's top-right corner with a 16-point inset and a preferred width of 320 points, preserving display aspect where usable screen bounds and the 160 × 90-point minimum allow; extreme ratios retain letterboxing. Compact mode floats above ordinary windows, joins all Spaces, and is configured to join eligible other-app fullscreen spaces and Stage Manager sets. Small hover controls provide play/pause, restore, and Playback Actions; keyboard playback controls remain available.
Compact-mode shortcuts and menu actions remain available during YouTube URL resolution, media opening, and network buffering. While metadata is unavailable, the window uses a provisional video ratio; decoded metadata then updates its geometry without leaving compact mode.
Entry and restoration animate the same window's position and size over **250 ms** with ease-in/ease-out timing while normal and compact controls cross-fade; playback and the Metal view stay in place. macOS **Reduce Motion** disables both animations. Rapid toggles keep the latest destination and finish the current native frame animation before changing direction; native fullscreen transitions are also serialized. Media close, errors, shutdown, and explicit fullscreen handoff restore immediately rather than leave a frame animation pending.
Drag the compact video to move the window; on release, each axis snaps independently when within 24 points of an inset usable-screen edge. **Snap to Screen Edges** is enabled by default, configurable with `[ui].compact_snap_to_edges`, and its toggle is session-only. Disabling snapping permits free placement. Exiting compact mode restores the previous normal geometry and window behavior, including keep-on-top; entry from fullscreen waits for the native exit animation, and restoring that session returns to fullscreen. Double-clicking compact video also restores the previous mode. Video replacement updates the compact aspect; audio-only replacement, playback errors, and closing the file leave compact mode. Closing the window still quits the app.
@@ -258,6 +260,8 @@ The network check also disconnects combined, secondary-audio and primary-video r
Adaptive transition checks also gate a real extraction, cancel it by pausing, and verify that late completion cannot reopen quality or resume paused playback. Failed manual quality changes preserve the original media, position, and prior playing/paused state.
The gated YouTube check also exercises compact shortcut/control entry and restoration during initial resolution, staying compact across empty playback updates and loading completion, and switching modes while network playback is buffering.
`make check-progress` verifies persisted fractional positions, independent local/YouTube identities, symlink aliases, completion clearing, invalid-position rejection, isolated preference domains, independently initialized writers preserving each other's videos, and migration of existing bookmarks. It is included in `make check` and does not touch real playback history.
`make check-reporting` decodes real JSONL files with an injected clock: initial/period boundaries, pending versus acknowledged seeks, threshold/pause/end/close facts, quality/replacement identity, nullable duration and eligibility, exclusive private creation, existing/symlink/concurrent rejection, and isolated OS write failure. `make check-network` also exercises the real backend's acknowledged initial restoration, audio-only/live eligibility, failed/cancelled opens, final drain, and continued playback/seek/replacement after a failed writer. Both are included in `make check`.
@@ -272,6 +276,8 @@ Adaptive transition checks also gate a real extraction, cancel it by pausing, an
Playback transition checks wait for native acknowledgement of rapid opposite intents, restore local bookmarks before autoplay, persist/resume the acknowledged position across close/reopen, and discard duration-exceeded bookmarks without preventing playback.
Native opening checks enter compact before playback acknowledges the request, then verify that anamorphic video metadata replaces the provisional ratio and that closing restores normal mode.
`make check-startup` launches an isolated app bundle through LaunchServices using the production bootstrap and a check-only player library with actual native playback. It verifies the registered app PID/bundle identity, then runs the real CLI against the production startup/SwiftUI scene/delegate: missing-config defaults without creation, nested settings/key overrides, actual plain/modified shortcuts, rapid opposite intents and held-key suppression, same-window compact entry/restoration, removed old bindings, real text insertion without playback interception, native menu equivalents and Play/Pause selections, malformed-file exit 78, cold/warm `--no-config`, unchanged file bytes and existing session settings, cold/default reuse, independent empty/local/YouTube launches, exactly one player window per PID, targeted media, retained original playback, help without launch, and warm default replacement. YouTube uses loopback media and actual offline yt-dlp selection; that portion requires yt-dlp and a supported JS runtime but no external network. It is included in `make check`; windows are transparent and ignore mouse input, audio muted, and configuration/bundle/history isolated. Native menus receive their normal lazy-population/validation callbacks before direct selection. Finder/Space behavior, visible controls/menu presentation and Vorssaint discovery still need a check in the app.
Startup checks also exercise actual CLI-to-GUI reporting after the launcher exits: two independent private streams, canonical identities, acknowledged resume/seek/pause, quality reopenings, replacement/end/close/quit, failed resolution, local-media exclusions, and existing/dangling-destination preflight errors. Report readers tolerate duplicates and partial trailing lines; watched facts are derived from eligible native positions, not launcher success.