Implement Driftwood AppImage manager
This commit is contained in:
147
src/ui/update_dialog.rs
Normal file
147
src/ui/update_dialog.rs
Normal file
@@ -0,0 +1,147 @@
|
||||
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
|
||||
}
|
||||
Reference in New Issue
Block a user