Add background update checks with configurable interval
This commit is contained in:
@@ -61,6 +61,17 @@
|
||||
<summary>Auto check updates</summary>
|
||||
<description>Automatically check for AppImage updates periodically.</description>
|
||||
</key>
|
||||
<key name="update-check-interval-hours" type="i">
|
||||
<range min="1" max="168"/>
|
||||
<default>24</default>
|
||||
<summary>Update check interval</summary>
|
||||
<description>Hours between automatic update checks.</description>
|
||||
</key>
|
||||
<key name="last-update-check" type="s">
|
||||
<default>''</default>
|
||||
<summary>Last update check timestamp</summary>
|
||||
<description>ISO timestamp of the last automatic update check.</description>
|
||||
</key>
|
||||
<key name="auto-integrate" type="b">
|
||||
<default>false</default>
|
||||
<summary>Auto integrate</summary>
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
use adw::prelude::*;
|
||||
use gtk::gio;
|
||||
use std::rc::Rc;
|
||||
|
||||
use crate::config::APP_ID;
|
||||
use crate::core::database::Database;
|
||||
use crate::core::duplicates;
|
||||
use crate::core::fuse;
|
||||
@@ -267,6 +269,32 @@ fn build_updates_summary_group(db: &Rc<Database>) -> adw::PreferencesGroup {
|
||||
updates_row.add_suffix(&updates_arrow);
|
||||
group.add(&updates_row);
|
||||
|
||||
// Last checked timestamp
|
||||
let settings = gio::Settings::new(APP_ID);
|
||||
let last_check = settings.string("last-update-check");
|
||||
let last_label = if last_check.is_empty() {
|
||||
"Never".to_string()
|
||||
} else if let Ok(ts) = chrono::NaiveDateTime::parse_from_str(last_check.as_str(), "%Y-%m-%d %H:%M:%S") {
|
||||
let now = chrono::Utc::now().naive_utc();
|
||||
let elapsed = now.signed_duration_since(ts);
|
||||
if elapsed.num_minutes() < 1 {
|
||||
"Just now".to_string()
|
||||
} else if elapsed.num_hours() < 1 {
|
||||
format!("{}m ago", elapsed.num_minutes())
|
||||
} else if elapsed.num_hours() < 24 {
|
||||
format!("{}h ago", elapsed.num_hours())
|
||||
} else {
|
||||
format!("{}d ago", elapsed.num_days())
|
||||
}
|
||||
} else {
|
||||
"Unknown".to_string()
|
||||
};
|
||||
let last_row = adw::ActionRow::builder()
|
||||
.title("Last checked")
|
||||
.subtitle(&last_label)
|
||||
.build();
|
||||
group.add(&last_row);
|
||||
|
||||
group
|
||||
}
|
||||
|
||||
|
||||
@@ -235,6 +235,25 @@ fn build_behavior_page(settings: &gio::Settings) -> adw::PreferencesPage {
|
||||
});
|
||||
automation_group.add(&auto_update_row);
|
||||
|
||||
let interval_row = adw::SpinRow::builder()
|
||||
.title(&i18n("Update check interval"))
|
||||
.subtitle(&i18n("Hours between automatic update checks"))
|
||||
.build();
|
||||
let interval_adj = gtk::Adjustment::new(
|
||||
settings.int("update-check-interval-hours") as f64,
|
||||
1.0,
|
||||
168.0,
|
||||
1.0,
|
||||
6.0,
|
||||
0.0,
|
||||
);
|
||||
interval_row.set_adjustment(Some(&interval_adj));
|
||||
let settings_interval = settings.clone();
|
||||
interval_row.connect_value_notify(move |row| {
|
||||
settings_interval.set_int("update-check-interval-hours", row.value() as i32).ok();
|
||||
});
|
||||
automation_group.add(&interval_row);
|
||||
|
||||
let auto_integrate_row = adw::SwitchRow::builder()
|
||||
.title(&i18n("Auto-integrate new AppImages"))
|
||||
.subtitle(&i18n("Automatically add newly discovered AppImages to the desktop menu"))
|
||||
|
||||
@@ -961,6 +961,37 @@ impl DriftwoodWindow {
|
||||
});
|
||||
}
|
||||
|
||||
// Scheduled background update check
|
||||
let settings_upd = self.settings().clone();
|
||||
if settings_upd.boolean("auto-check-updates") {
|
||||
let last_check = settings_upd.string("last-update-check").to_string();
|
||||
let interval_hours = settings_upd.int("update-check-interval-hours") as i64;
|
||||
let should_check = if last_check.is_empty() {
|
||||
true
|
||||
} else if let Ok(last) = chrono::NaiveDateTime::parse_from_str(&last_check, "%Y-%m-%d %H:%M:%S") {
|
||||
let now = chrono::Utc::now().naive_utc();
|
||||
let elapsed = now.signed_duration_since(last);
|
||||
elapsed.num_hours() >= interval_hours
|
||||
} else {
|
||||
true
|
||||
};
|
||||
if should_check {
|
||||
let settings_save = settings_upd.clone();
|
||||
glib::spawn_future_local(async move {
|
||||
let result = gio::spawn_blocking(move || {
|
||||
let bg_db = Database::open().expect("DB open failed");
|
||||
update_dialog::batch_check_updates(&bg_db)
|
||||
})
|
||||
.await;
|
||||
if let Ok(count) = result {
|
||||
log::info!("Background update check: {} updates available", count);
|
||||
}
|
||||
let now = chrono::Utc::now().format("%Y-%m-%d %H:%M:%S").to_string();
|
||||
settings_save.set_string("last-update-check", &now).ok();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Check for orphaned desktop entries in the background
|
||||
let toast_overlay = self.imp().toast_overlay.get().unwrap().clone();
|
||||
glib::spawn_future_local(async move {
|
||||
|
||||
Reference in New Issue
Block a user