Three asks the user surfaced after this session's web-UI wave: bring
the desktop UI to parity with what shipped over there, and fix the
theme contrast bugs where button labels disappeared on certain
themes.
Shuffle (desktop)
- 🎲 button next to ⟳ Rescan in the top bar.
- New `App::shuffle_play` mirrors the web logic: pick a random video
from {unwatched + has video_path}, fall back to {any downloaded
video} when everything's been watched, status message either way.
- Uses `rand::seq::SliceRandom::choose` — `rand` was already a
dependency (via hash_password).
- Plays via the existing `play_with_tracking` path so mpv IPC +
resume position both work.
Library backup (desktop)
- New "💾 Save library backup…" button under a new "Backup" section
in the Settings panel.
- Opens an rfd save dialog off the UI thread (mirroring the existing
cookies file-picker pattern), default filename
`yt-offline-<unix-ts>.db`.
- New `backup_save_tx/rx` mpsc channel; `update()` polls it and
`std::fs::copy`s `yt-offline.db` into the chosen destination,
surfacing the byte count in the status line.
Theme contrast
- Root cause: four of the seven themes set `override_text_color`
globally, which shadows the per-widget `fg_stroke.color`. That
meant the "active" widget state (e.g. Dracula's light-purple
button) rendered light-grey text on a light background —
invisible. Trans was the worst offender: hot-pink override on
a light-pink inactive button.
- Fix: set `override_text_color = None` on dracula, trans,
emo_nocturnal, and emo_coffin. Each already had per-widget
fg_stroke colours tuned for high contrast against the matching
bg_fill — those just weren't being used.
- Trans theme additionally gets a pure-black `inactive.fg_stroke`
(over the light pink button) and a darker `noninteractive.fg_stroke`
(over the pale pink panel) for maximum legibility. Emo Scene Queen
was already correct (no override) and stays as-is.
55 unit tests still pass.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>