Add security, i18n, analysis, backup, notifications
This commit is contained in:
@@ -5,6 +5,7 @@ use std::rc::Rc;
|
||||
use crate::config::APP_ID;
|
||||
use crate::core::database::{AppImageRecord, Database};
|
||||
use crate::core::updater;
|
||||
use crate::i18n::{i18n, i18n_f};
|
||||
|
||||
/// Show an update check + apply dialog for a single AppImage.
|
||||
pub fn show_update_dialog(
|
||||
@@ -13,13 +14,13 @@ pub fn show_update_dialog(
|
||||
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)
|
||||
.heading(&i18n("Check for Updates"))
|
||||
.body(&i18n_f(
|
||||
"Checking for updates for {name}...",
|
||||
&[("{name}", record.app_name.as_deref().unwrap_or(&record.filename))],
|
||||
))
|
||||
.build();
|
||||
dialog.add_response("close", "Close");
|
||||
dialog.add_response("close", &i18n("Close"));
|
||||
dialog.set_default_response(Some("close"));
|
||||
dialog.set_close_response("close");
|
||||
|
||||
@@ -58,15 +59,17 @@ pub fn show_update_dialog(
|
||||
db_ref.set_update_available(record_id, Some(version), check_result.download_url.as_deref()).ok();
|
||||
}
|
||||
|
||||
let mut body = format!(
|
||||
"{} -> {}",
|
||||
record_clone.app_version.as_deref().unwrap_or("unknown"),
|
||||
check_result.latest_version.as_deref().unwrap_or("unknown"),
|
||||
let mut body = i18n_f(
|
||||
"{current} -> {latest}",
|
||||
&[
|
||||
("{current}", record_clone.app_version.as_deref().unwrap_or("unknown")),
|
||||
("{latest}", check_result.latest_version.as_deref().unwrap_or("unknown")),
|
||||
],
|
||||
);
|
||||
if let Some(size) = check_result.file_size {
|
||||
body.push_str(&format!(" ({})", humansize::format_size(size, humansize::BINARY)));
|
||||
}
|
||||
body.push_str("\n\nA new version is available.");
|
||||
body.push_str(&format!("\n\n{}", i18n("A new version is available.")));
|
||||
if let Some(ref notes) = check_result.release_notes {
|
||||
if !notes.is_empty() {
|
||||
// Truncate long release notes for the dialog
|
||||
@@ -75,12 +78,12 @@ pub fn show_update_dialog(
|
||||
body.push_str(&format!("\n\n{}{}", truncated, suffix));
|
||||
}
|
||||
}
|
||||
dialog_ref.set_heading(Some("Update Available"));
|
||||
dialog_ref.set_heading(Some(&i18n("Update Available")));
|
||||
dialog_ref.set_body(&body);
|
||||
|
||||
// Add "Update Now" button if we have a download URL
|
||||
if let Some(download_url) = check_result.download_url {
|
||||
dialog_ref.add_response("update", "Update Now");
|
||||
dialog_ref.add_response("update", &i18n("Update Now"));
|
||||
dialog_ref.set_response_appearance("update", adw::ResponseAppearance::Suggested);
|
||||
dialog_ref.set_default_response(Some("update"));
|
||||
|
||||
@@ -101,11 +104,13 @@ pub fn show_update_dialog(
|
||||
});
|
||||
}
|
||||
} 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"),
|
||||
dialog_ref.set_heading(Some(&i18n("Up to Date")));
|
||||
dialog_ref.set_body(&i18n_f(
|
||||
"{name} is already at the latest version ({version}).",
|
||||
&[
|
||||
("{name}", record_clone.app_name.as_deref().unwrap_or(&record_clone.filename)),
|
||||
("{version}", record_clone.app_version.as_deref().unwrap_or("unknown")),
|
||||
],
|
||||
));
|
||||
db_ref.clear_update_available(record_id).ok();
|
||||
}
|
||||
@@ -113,19 +118,18 @@ pub fn show_update_dialog(
|
||||
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.");
|
||||
dialog_ref.set_heading(Some(&i18n("Check Failed")));
|
||||
dialog_ref.set_body(&i18n("Could not reach the update server. Try again later."));
|
||||
} else {
|
||||
dialog_ref.set_heading(Some("No Update Info"));
|
||||
dialog_ref.set_heading(Some(&i18n("No Update Info")));
|
||||
dialog_ref.set_body(
|
||||
"This app does not support automatic updates. \
|
||||
Check the developer's website for newer versions.",
|
||||
&i18n("This app does not support automatic updates. Check the developer's website for newer versions."),
|
||||
);
|
||||
}
|
||||
}
|
||||
Err(_) => {
|
||||
dialog_ref.set_heading(Some("Error"));
|
||||
dialog_ref.set_body("An error occurred while checking for updates.");
|
||||
dialog_ref.set_heading(Some(&i18n("Error")));
|
||||
dialog_ref.set_body(&i18n("An error occurred while checking for updates."));
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -142,8 +146,8 @@ fn start_update(
|
||||
new_version: Option<&str>,
|
||||
db: &Rc<Database>,
|
||||
) {
|
||||
dialog.set_heading(Some("Updating..."));
|
||||
dialog.set_body("Downloading update. This may take a moment.");
|
||||
dialog.set_heading(Some(&i18n("Updating...")));
|
||||
dialog.set_body(&i18n("Downloading update. This may take a moment."));
|
||||
dialog.set_response_enabled("update", false);
|
||||
|
||||
let path = appimage_path.to_string();
|
||||
@@ -171,12 +175,14 @@ fn start_update(
|
||||
}
|
||||
db_ref.clear_update_available(record_id).ok();
|
||||
|
||||
let success_body = format!(
|
||||
"Updated to {}\nPath: {}",
|
||||
applied.new_version.as_deref().unwrap_or("latest"),
|
||||
applied.new_path.display(),
|
||||
let success_body = i18n_f(
|
||||
"Updated to {version}\nPath: {path}",
|
||||
&[
|
||||
("{version}", applied.new_version.as_deref().unwrap_or("latest")),
|
||||
("{path}", &applied.new_path.display().to_string()),
|
||||
],
|
||||
);
|
||||
dialog.set_heading(Some("Update Complete"));
|
||||
dialog.set_heading(Some(&i18n("Update Complete")));
|
||||
dialog.set_body(&success_body);
|
||||
dialog.set_response_enabled("update", false);
|
||||
|
||||
@@ -186,12 +192,15 @@ fn start_update(
|
||||
}
|
||||
}
|
||||
Ok(Err(e)) => {
|
||||
dialog.set_heading(Some("Update Failed"));
|
||||
dialog.set_body(&format!("The update could not be applied: {}", e));
|
||||
dialog.set_heading(Some(&i18n("Update Failed")));
|
||||
dialog.set_body(&i18n_f(
|
||||
"The update could not be applied: {error}",
|
||||
&[("{error}", &e.to_string())],
|
||||
));
|
||||
}
|
||||
Err(_) => {
|
||||
dialog.set_heading(Some("Update Failed"));
|
||||
dialog.set_body("An unexpected error occurred during the update.");
|
||||
dialog.set_heading(Some(&i18n("Update Failed")));
|
||||
dialog.set_body(&i18n("An unexpected error occurred during the update."));
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -215,18 +224,18 @@ fn handle_old_version_cleanup(dialog: &adw::AlertDialog, old_path: PathBuf) {
|
||||
}
|
||||
"never" => {
|
||||
// Keep the backup, just inform
|
||||
dialog.set_body(&format!(
|
||||
"Update complete. The old version is saved at:\n{}",
|
||||
old_path.display()
|
||||
dialog.set_body(&i18n_f(
|
||||
"Update complete. The old version is saved at:\n{path}",
|
||||
&[("{path}", &old_path.display().to_string())],
|
||||
));
|
||||
}
|
||||
_ => {
|
||||
// "ask" - prompt the user
|
||||
dialog.set_body(&format!(
|
||||
"Update complete.\n\nRemove the old version?\n{}",
|
||||
old_path.display()
|
||||
dialog.set_body(&i18n_f(
|
||||
"Update complete.\n\nRemove the old version?\n{path}",
|
||||
&[("{path}", &old_path.display().to_string())],
|
||||
));
|
||||
dialog.add_response("remove-old", "Remove Old Version");
|
||||
dialog.add_response("remove-old", &i18n("Remove Old Version"));
|
||||
dialog.set_response_appearance("remove-old", adw::ResponseAppearance::Destructive);
|
||||
|
||||
let path = old_path.clone();
|
||||
|
||||
Reference in New Issue
Block a user