The previous fix rebuilt the quality chain when converting persisted
models back to videos, but many consumers discarded it again by
rendering bestThumbnail (usually a maxresdefault.jpg that 404s for
older videos) as a single URL with no fallback.
Extract the retry logic from VideoThumbnailView into FallbackLazyImage
and use it at every in-app site that can iterate: player thumbnails
(mini bar, expanded sheet loaders, autoplay previews, tvOS audio-mode
artwork - previously a silent black screen), video info card and tvOS
header, and the tvOS playlist cover.
Sites that fetch or send exactly one URL are rewritten to the
always-available hqdefault variant via Thumbnail.reliableURL (exposed
as Video.reliableThumbnailURL): Now Playing artwork, Top Shelf
snapshots, remote control state, the frozen transition thumbnail,
blurred info background, navigation covers, and playlist covers
derived from a video's first thumbnail in Invidious/Yattee Server
responses.
Also invert RecentPlaylist's upgrade helper, which rewrote covers *to*
maxresdefault, walk the quality chain when caching download thumbnails
for offline artwork instead of giving up after one 404, and expand the
remaining single-thumbnail Piped conversions into full chains.
Persistent per-platform mode that plays only the audio track to save
bandwidth and speed up loads. When enabled, stream selection picks the
best audio-only stream (preferred language, codec, bitrate) and never
fetches the video URL; toggling mid-video reloads at the current
position using the quality-switch path (live vid=no toggling is avoided
due to A/V desync).
- Toggle row in the player quality/settings sheet on iOS, macOS and
tvOS, next to lock controls
- New audioMode control button type (red when active) for player
controls and mini player layouts
- Picking a video quality explicitly turns the mode off; audio track
picks keep it on and now work while audio-only is playing
- Stream URL refresh preserves audio-only playback instead of
resurrecting video
- Queue preloads and history entries resolved before a toggle are
discarded so selection re-runs with the current mode
- tvOS player shows the video thumbnail instead of a black screen
during audio-only playback
- PiP button hidden for audio-only streams
Live streams have no meaningful duration, so the mini player's bottom
progress line collapsed to nothing (or showed a misleading partial fill
on DVR streams). Hide the line for live playback and show a red dot +
LIVE indicator next to the author name instead, matching the expanded
player controls. Applies to both the macOS capsule and iOS overlay
layouts.
Add a queue-count badge to the macOS player controls queue button
(MacOSControlsSectionRenderer) and the shared mini player queue button
(MiniPlayerView), matching the iOS pill button behavior.
Tapping the mini bar video thumbnail (with tap action set to PiP) or its
PiP button while the expanded player window was open started PiP playing
alongside the window. Bring the player window to the front instead when
it is open or opening.
The capsule close button (and context-menu close) only stopped playback and
cleared the queue, leaving the separate macOS player window open on a black
frame. Route both through a shared closeVideo() that also sets
isPlayerExpanded = false, mirroring PlaybackCommands.closeVideo, so the
player window is dismissed.
- Replace the full-width material overlay bar with a compact, centered
capsule (Apple Music style) via a macOS-specific macOSCapsuleLayout
- Extend glassBackground() to use real Liquid Glass on macOS 26 with a
material fallback on macOS 15-25 (mirrors the PlayerOverlayButton pattern)
- Remove the duplicate close button (close now comes only from the
configurable button set)
- Keep the capsule visible in the main window while the separate player
window is open (window mode), still hidden in sheet mode
When PiP is active, the MPV render view shows a black frame since
rendering goes to the PiP sample buffer layer. Overlay the video
thumbnail (preferring DeArrow) on top to cover the black area,
fading it in/out smoothly when PiP starts/stops.