Add web UI, AGPL3, notifications, continue watching, bulk watched, storage stats, scheduler

License:
- GPL3 → AGPL3

New features:
- Web interface (--web [port]): axum/tokio server with SSE progress, library browser,
  download trigger, watched toggle; embedded single-page HTML/JS UI
- Desktop notifications via notify-rust when downloads complete or fail
- Continue Watching sidebar entry showing videos with saved resume positions
- Bulk select mode: select multiple videos, mark all watched/unwatched at once
- Storage stats: channel disk usage shown in sidebar next to video count
- Scheduled channel checks: configurable interval (hours), auto re-downloads all
  tracked channels using channel_url from info.json; enabled in Settings

Theme fixes:
- Scene Queen: remove override_text_color so active button text uses fg_stroke
  (dark navy on neon green) instead of near-white — fixes unreadable contrast
- Trans: override_text_color → hot pink #cc0066 for pink-tinted text throughout

Settings additions:
- Auto-check channels toggle + interval_hours DragValue
- Web UI port setting

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
This commit is contained in:
Luna 2026-05-11 04:27:04 -07:00
parent 5b3b8fc901
commit 80cce00b99
8 changed files with 1526 additions and 211 deletions

View file

@ -7,8 +7,27 @@ mod downloader;
mod library;
mod theme;
mod tray;
mod web;
fn main() -> eframe::Result<()> {
let args: Vec<String> = std::env::args().collect();
// --web [port] → run the web interface instead of the GUI
if let Some(pos) = args.iter().position(|a| a == "--web") {
let mut cfg = {
let cwd = std::env::current_dir().unwrap_or_else(|_| std::path::PathBuf::from("."));
config::Config::load(&cwd.join("config.toml"))
.unwrap_or_else(|_| config::Config::default_with_dir(cwd.join("channels")))
};
// Override port if provided after --web
if let Some(port_str) = args.get(pos + 1) {
if let Ok(port) = port_str.parse::<u16>() {
cfg.web.port = port;
}
}
web::run(cfg);
}
let native_options = eframe::NativeOptions {
viewport: eframe::egui::ViewportBuilder::default()
.with_inner_size([1280.0, 820.0])