Add web themes, network binding, UI auth, library maintenance; optimize + fix rescan

Features:
- Port all 7 desktop themes (Dracula, Trans, Emo variants, etc.) to the web UI
- Configurable bind interface (localhost/Tailscale/LAN/all) with detected IPs,
  settable from both the web UI and desktop GUI
- Optional password that gates the whole UI and all API access via session
  cookies (Argon2), with a login page, logout, and middleware; settable from
  both UIs
- Library maintenance: scan for duplicate video IDs and missing assets
  (thumbnail/info.json/description), remove duplicates (scan-and-confirm, with
  out-of-library path guard), and re-fetch missing sidecars via yt-dlp.
  Surfaced in both the web UI and a desktop GUI window.

Optimizations / cleanup:
- Cache has_chapters at scan time (library.rs) instead of re-reading and
  parsing every info.json on each /api/library request
- Use the cached channel size in get_library
- Pool a single SQLite connection in WebState instead of opening one per request
- Remove a 1.2 GB stray nested src/yt-offline duplicate tree

Fixes:
- Rescan no longer clears all thumbnail textures (caused thumbnails to unload);
  prune only removed entries and bump library_generation so the card grid
  refreshes correctly

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Luna 2026-05-21 02:58:09 -07:00
parent 74b3efd990
commit 1ef3fe56c6
10 changed files with 1126 additions and 89 deletions

View file

@ -42,6 +42,8 @@ impl Default for PlayerSection {
}
/// `[ui]` table — egui desktop theme.
///
/// Available themes: `dark`, `light`, `dracula`, `trans`, `emo-nocturnal`, `emo-coffin`, `emo-scene-queen`.
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct UiSection {
#[serde(default = "default_theme")]
@ -86,6 +88,9 @@ pub struct WebSection {
pub transcode: bool,
/// Public URL to the source repository, shown in the web UI per AGPL §13.
pub source_url: Option<String>,
/// Optional plaintext password required for downloads via web UI.
/// If set, users must provide this password to queue downloads.
pub download_password: Option<String>,
}
impl Default for WebSection {
@ -95,6 +100,7 @@ impl Default for WebSection {
bind: default_web_bind(),
transcode: false,
source_url: None,
download_password: None,
}
}
}