window: prefetch images and queue offline read/unread actions

After a successful article refresh, all images referenced in article
content are downloaded in the background so articles can be read
offline. The prefetch only runs when the cache-images setting is
enabled and the connection is not metered.

Read/unread state changes that fail to reach the server (e.g. when
offline) are now persisted to a local queue in
~/.cache/net.jeena.FeedTheMonkey/pending_sync.json. The queue is
flushed at the start of the next successful fetch.
This commit is contained in:
Jeena 2026-03-21 02:45:45 +00:00
parent 3f759bce2e
commit 9bed643023
4 changed files with 123 additions and 5 deletions

View file

@ -134,6 +134,34 @@ fn serve_file(request: webkit6::URISchemeRequest, path: PathBuf) {
}
}
/// Prefetch all images referenced in the articles into the cache directory.
/// Runs entirely in the background; already-cached files are skipped.
pub async fn prefetch(articles: Vec<Article>) {
let dir = images_dir();
std::fs::create_dir_all(&dir).ok();
let client = reqwest::Client::builder()
.timeout(std::time::Duration::from_secs(30))
.build()
.unwrap_or_default();
let re = regex::Regex::new(&format!(r#"src="{}([^"]+)""#, regex::escape(SCHEME_PREFIX))).unwrap();
for article in &articles {
for cap in re.captures_iter(&article.content) {
let original_url = percent_decode(&cap[1]);
let path = dir.join(url_to_filename(&original_url));
if !path.exists() {
if let Ok(resp) = client.get(&original_url).send().await {
if let Ok(bytes) = resp.bytes().await {
std::fs::write(&path, &bytes).ok();
}
}
}
}
}
}
/// Rewrite all remote image src attributes to feedthemonkey-img:// URIs.
/// No network requests are made here — images are downloaded lazily by the
/// URI scheme handler the first time the WebView requests them, then cached.