148 lines
5.2 KiB
Rust
148 lines
5.2 KiB
Rust
use adw::prelude::*;
|
|
use gtk::gio;
|
|
use std::rc::Rc;
|
|
use crate::core::database::{AppImageRecord, Database};
|
|
use crate::core::updater;
|
|
|
|
/// Show an update check + apply dialog for a single AppImage.
|
|
pub fn show_update_dialog(
|
|
parent: &impl IsA<gtk::Widget>,
|
|
record: &AppImageRecord,
|
|
db: &Rc<Database>,
|
|
) {
|
|
let dialog = adw::AlertDialog::builder()
|
|
.heading("Check for Updates")
|
|
.body(&format!(
|
|
"Checking for updates for {}...",
|
|
record.app_name.as_deref().unwrap_or(&record.filename)
|
|
))
|
|
.build();
|
|
dialog.add_response("close", "Close");
|
|
dialog.set_default_response(Some("close"));
|
|
dialog.set_close_response("close");
|
|
|
|
let record_clone = record.clone();
|
|
let db_ref = db.clone();
|
|
let dialog_ref = dialog.clone();
|
|
|
|
// Start the update check in the background
|
|
let record_id = record.id;
|
|
let path = record.path.clone();
|
|
let current_version = record.app_version.clone();
|
|
|
|
glib::spawn_future_local(async move {
|
|
let result = gio::spawn_blocking(move || {
|
|
let appimage_path = std::path::Path::new(&path);
|
|
updater::check_appimage_for_update(
|
|
appimage_path,
|
|
current_version.as_deref(),
|
|
)
|
|
})
|
|
.await;
|
|
|
|
match result {
|
|
Ok((type_label, raw_info, Some(check_result))) => {
|
|
// Store update info in DB
|
|
let now = chrono::Utc::now().format("%Y-%m-%d %H:%M:%S").to_string();
|
|
db_ref
|
|
.update_update_info(
|
|
record_id,
|
|
raw_info.as_deref(),
|
|
type_label.as_deref(),
|
|
)
|
|
.ok();
|
|
|
|
if check_result.update_available {
|
|
if let Some(ref version) = check_result.latest_version {
|
|
db_ref.set_update_available(record_id, Some(version), check_result.download_url.as_deref()).ok();
|
|
}
|
|
|
|
let body = format!(
|
|
"{} -> {}\n\nA new version is available.",
|
|
record_clone.app_version.as_deref().unwrap_or("unknown"),
|
|
check_result.latest_version.as_deref().unwrap_or("unknown"),
|
|
);
|
|
dialog_ref.set_heading(Some("Update Available"));
|
|
dialog_ref.set_body(&body);
|
|
// Future: add "Update" response to trigger download
|
|
} else {
|
|
dialog_ref.set_heading(Some("Up to Date"));
|
|
dialog_ref.set_body(&format!(
|
|
"{} is already at the latest version ({}).",
|
|
record_clone.app_name.as_deref().unwrap_or(&record_clone.filename),
|
|
record_clone.app_version.as_deref().unwrap_or("unknown"),
|
|
));
|
|
db_ref.clear_update_available(record_id).ok();
|
|
}
|
|
}
|
|
Ok((type_label, raw_info, None)) => {
|
|
if raw_info.is_some() {
|
|
db_ref.update_update_info(record_id, raw_info.as_deref(), type_label.as_deref()).ok();
|
|
dialog_ref.set_heading(Some("Check Failed"));
|
|
dialog_ref.set_body("Could not reach the update server. Try again later.");
|
|
} else {
|
|
dialog_ref.set_heading(Some("No Update Info"));
|
|
dialog_ref.set_body(
|
|
"This AppImage does not contain update information. \
|
|
Updates must be downloaded manually.",
|
|
);
|
|
}
|
|
}
|
|
Err(_) => {
|
|
dialog_ref.set_heading(Some("Error"));
|
|
dialog_ref.set_body("An error occurred while checking for updates.");
|
|
}
|
|
}
|
|
});
|
|
|
|
dialog.present(Some(parent));
|
|
}
|
|
|
|
/// Batch check all AppImages for updates. Returns count of updates found.
|
|
pub fn batch_check_updates(db: &Database) -> u32 {
|
|
let records = match db.get_all_appimages() {
|
|
Ok(r) => r,
|
|
Err(e) => {
|
|
log::error!("Failed to get appimages for update check: {}", e);
|
|
return 0;
|
|
}
|
|
};
|
|
|
|
let mut updates_found = 0u32;
|
|
|
|
for record in &records {
|
|
let appimage_path = std::path::Path::new(&record.path);
|
|
if !appimage_path.exists() {
|
|
continue;
|
|
}
|
|
|
|
let (type_label, raw_info, check_result) = updater::check_appimage_for_update(
|
|
appimage_path,
|
|
record.app_version.as_deref(),
|
|
);
|
|
|
|
// Store update info
|
|
if raw_info.is_some() || type_label.is_some() {
|
|
db.update_update_info(
|
|
record.id,
|
|
raw_info.as_deref(),
|
|
type_label.as_deref(),
|
|
)
|
|
.ok();
|
|
}
|
|
|
|
if let Some(result) = check_result {
|
|
if result.update_available {
|
|
if let Some(ref version) = result.latest_version {
|
|
db.set_update_available(record.id, Some(version), result.download_url.as_deref()).ok();
|
|
updates_found += 1;
|
|
}
|
|
} else {
|
|
db.clear_update_available(record.id).ok();
|
|
}
|
|
}
|
|
}
|
|
|
|
updates_found
|
|
}
|