feat: Tauri commands, concurrent refresh, download manager
Refresh fetches 8 channel feeds concurrently and mirrors thumbnails to disk so the offline feed still renders. Downloads are capped at 2 and shell out to yt-dlp with an absolute binary path, since GUI apps do not inherit a login shell PATH.
This commit is contained in:
@@ -0,0 +1,55 @@
|
||||
//! Local thumbnail cache.
|
||||
//!
|
||||
//! Feed thumbnails are remote `ytimg.com` URLs. Offline — the whole point of
|
||||
//! this app — those fail to load and the feed becomes a wall of broken images.
|
||||
//! So every thumbnail we learn about gets mirrored to disk.
|
||||
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
pub fn cache_dir(app_data: &Path) -> PathBuf {
|
||||
app_data.join("thumbs")
|
||||
}
|
||||
|
||||
/// Downloads one thumbnail if it isn't already cached. Returns its path.
|
||||
pub async fn cache_one(
|
||||
client: &reqwest::Client,
|
||||
video_id: &str,
|
||||
url: &str,
|
||||
dir: &Path,
|
||||
) -> Result<PathBuf, String> {
|
||||
let dest = dir.join(format!("{video_id}.jpg"));
|
||||
if dest.exists() {
|
||||
return Ok(dest);
|
||||
}
|
||||
|
||||
tokio::fs::create_dir_all(dir)
|
||||
.await
|
||||
.map_err(|e| format!("Cannot create thumbnail cache dir: {e}"))?;
|
||||
|
||||
let resp = client
|
||||
.get(url)
|
||||
.send()
|
||||
.await
|
||||
.map_err(|e| format!("Thumbnail request failed: {e}"))?;
|
||||
|
||||
if !resp.status().is_success() {
|
||||
return Err(format!("Thumbnail returned HTTP {}", resp.status()));
|
||||
}
|
||||
|
||||
let bytes = resp
|
||||
.bytes()
|
||||
.await
|
||||
.map_err(|e| format!("Cannot read thumbnail body: {e}"))?;
|
||||
|
||||
// Write to a temp name then rename, so an interrupted download never leaves
|
||||
// a half-written JPEG that later looks cached.
|
||||
let tmp = dir.join(format!("{video_id}.jpg.part"));
|
||||
tokio::fs::write(&tmp, &bytes)
|
||||
.await
|
||||
.map_err(|e| format!("Cannot write thumbnail: {e}"))?;
|
||||
tokio::fs::rename(&tmp, &dest)
|
||||
.await
|
||||
.map_err(|e| format!("Cannot finalize thumbnail: {e}"))?;
|
||||
|
||||
Ok(dest)
|
||||
}
|
||||
Reference in New Issue
Block a user