feat(desktop): instant startup from persisted library snapshot
Seed self.library from load_library_snapshot before spawning the scan thread, so a warm launch renders the library immediately (status '… refreshing…') instead of a blank/scanning window. Write the snapshot after every scan (the startup thread and rescan). The background scan is unchanged and still swaps in authoritative data; the snapshot only ever shows briefly-stale state. Verified live against the real 5574-video library: second launch renders the full list within 2s (well under the ~64s cold scan) with the refreshing status; deleting the snapshot row falls back to the scanning spinner. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
5a55c15209
commit
3e6bcfb564
1 changed files with 17 additions and 2 deletions
19
src/app.rs
19
src/app.rs
|
|
@ -482,7 +482,20 @@ impl App {
|
|||
// DB lookups that don't depend on the scan, so they stay synchronous.
|
||||
let (library_load_tx, library_load_rx) =
|
||||
std::sync::mpsc::channel::<Vec<library::Channel>>();
|
||||
let status = "Scanning library…".to_string();
|
||||
// Instant startup: if we persisted the library last run, show it
|
||||
// immediately while the (slow, disk-bound) rescan runs in the
|
||||
// background and swaps in fresh data via `library_load_rx`.
|
||||
let seeded_library: Vec<library::Channel> =
|
||||
db.load_library_snapshot(&channels_root).unwrap_or_default();
|
||||
let status = if seeded_library.is_empty() {
|
||||
"Scanning library…".to_string()
|
||||
} else {
|
||||
format!(
|
||||
"{} channels, {} videos (refreshing…)",
|
||||
seeded_library.len(),
|
||||
seeded_library.iter().map(|c| c.total_videos()).sum::<usize>()
|
||||
)
|
||||
};
|
||||
{
|
||||
let db = db.clone();
|
||||
let channels_root = channels_root.clone();
|
||||
|
|
@ -502,12 +515,13 @@ impl App {
|
|||
if let Err(e) = db.sync_search_index(&library::build_search_entries(&library)) {
|
||||
eprintln!("search index sync failed: {e}");
|
||||
}
|
||||
db.save_library_snapshot(&channels_root, &library);
|
||||
let _ = library_load_tx.send(library);
|
||||
ctx.request_repaint(); // wake update() to swap the result in
|
||||
})
|
||||
.ok();
|
||||
}
|
||||
let library: Vec<library::Channel> = Vec::new();
|
||||
let library: Vec<library::Channel> = seeded_library;
|
||||
let folders = db.list_folders().unwrap_or_default();
|
||||
let watched = db.get_watched().unwrap_or_default();
|
||||
let flags = db.get_video_flags().unwrap_or_default();
|
||||
|
|
@ -804,6 +818,7 @@ impl App {
|
|||
self.thumb_pending.retain(|p| valid.contains(p));
|
||||
// Bump the generation so the card cache recomputes against the new library.
|
||||
self.library_generation += 1;
|
||||
self.db.save_library_snapshot(&self.channels_root, &self.library);
|
||||
self.status = format!(
|
||||
"Rescanned: {} channels, {} videos",
|
||||
self.library.len(),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue