On shutdown the full article list (including current read/unread state) and the ID of the open article are saved to ~/.local/share/net.jeena.FeedTheMonkey/cache.json. On next launch: - The cached articles are loaded into the list immediately, before any network request, so the sidebar is populated and the previously open article is visible without waiting for the server. - The article content is injected into the WebView once its base HTML finishes loading (LoadEvent::Finished), avoiding a race where window.setArticle() did not yet exist. - A background refresh then fetches fresh data from the server; if the previously open article still exists its selection is preserved, otherwise the first item is selected. - Network errors during a background refresh show a toast instead of replacing the visible article list with an error page.
29 lines
971 B
Rust
29 lines
971 B
Rust
use crate::model::Article;
|
|
|
|
pub struct Cache {
|
|
pub articles: Vec<Article>,
|
|
pub selected_id: String,
|
|
}
|
|
|
|
pub fn save(articles: &[Article], selected_id: &str) {
|
|
let dir = glib::user_data_dir().join("net.jeena.FeedTheMonkey");
|
|
std::fs::create_dir_all(&dir).ok();
|
|
let data = serde_json::json!({
|
|
"articles": articles,
|
|
"selected_id": selected_id,
|
|
});
|
|
if let Ok(s) = serde_json::to_string(&data) {
|
|
std::fs::write(dir.join("cache.json"), s).ok();
|
|
}
|
|
}
|
|
|
|
pub fn load() -> Option<Cache> {
|
|
let path = glib::user_data_dir()
|
|
.join("net.jeena.FeedTheMonkey")
|
|
.join("cache.json");
|
|
let data = std::fs::read_to_string(path).ok()?;
|
|
let json: serde_json::Value = serde_json::from_str(&data).ok()?;
|
|
let articles: Vec<Article> = serde_json::from_value(json["articles"].clone()).ok()?;
|
|
let selected_id = json["selected_id"].as_str().unwrap_or("").to_string();
|
|
Some(Cache { articles, selected_id })
|
|
}
|