diff --git a/package-lock.json b/package-lock.json
index e96ea5a..a1fd806 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "zinnia",
- "version": "0.1.2",
+ "version": "0.1.4",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "zinnia",
- "version": "0.1.2",
+ "version": "0.1.4",
"dependencies": {
"@tauri-apps/api": "^2.0.0",
"@tauri-apps/plugin-dialog": "^2.6.0",
diff --git a/package.json b/package.json
index 6b32e04..f9baa5d 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "zinnia",
- "version": "0.1.3",
+ "version": "0.1.4",
"private": true,
"description": "Cross-platform 7z GUI built with Tauri.",
"type": "module",
diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs
index 5824688..002a5cf 100644
--- a/src-tauri/src/main.rs
+++ b/src-tauri/src/main.rs
@@ -680,6 +680,31 @@ fn cancel_7z(state: tauri::State<'_, RunningProcess>) -> Result<(), String> {
#[cfg(windows)]
const ARCHIVE_EXTENSIONS: &[&str] = SUPPORTED_ARCHIVE_EXTENSIONS;
+#[cfg(windows)]
+fn notify_shell_association_changed() {
+ #[allow(non_snake_case)]
+ unsafe extern "system" {
+ fn SHChangeNotify(
+ wEventId: u32,
+ uFlags: u32,
+ dwItem1: *const std::ffi::c_void,
+ dwItem2: *const std::ffi::c_void,
+ );
+ }
+
+ const SHCNE_ASSOCCHANGED: u32 = 0x0800_0000;
+ const SHCNF_IDLIST: u32 = 0x0000;
+
+ unsafe {
+ SHChangeNotify(
+ SHCNE_ASSOCCHANGED,
+ SHCNF_IDLIST,
+ std::ptr::null(),
+ std::ptr::null(),
+ );
+ }
+}
+
#[tauri::command]
fn register_windows_context_menu() -> Result<(), String> {
#[cfg(windows)]
@@ -699,7 +724,7 @@ fn register_windows_context_menu() -> Result<(), String> {
.create_subkey("Software\\Classes")
.map_err(|e| e.to_string())?;
- let icon_value = format!("{},0", exe_str);
+ let icon_value = format!("\"{}\",0", exe_str);
let compress_entries = [
("*\\shell\\Zinnia", "Compress with Zinnia"),
("Directory\\shell\\Zinnia", "Compress folder with Zinnia"),
@@ -758,6 +783,7 @@ fn register_windows_context_menu() -> Result<(), String> {
.map_err(|e| e.to_string())?;
}
+ notify_shell_association_changed();
Ok(())
}
@@ -807,6 +833,7 @@ fn unregister_windows_context_menu() -> Result<(), String> {
Err(e) => return Err(format!("Failed to remove Zinnia.Archive: {}", e)),
}
+ notify_shell_association_changed();
Ok(())
}
diff --git a/src/index.html b/src/index.html
index 454a45c..7e369bd 100644
--- a/src/index.html
+++ b/src/index.html
@@ -53,8 +53,8 @@
Settings
- Check for updates on startup
- Automatically check for new versions when the app opens.
+ Check and automatically download updates on startup
+ Automatically checks for updates when the app opens and downloads them in the background.
diff --git a/src/updater.ts b/src/updater.ts
index 1fd46e9..8aae881 100644
--- a/src/updater.ts
+++ b/src/updater.ts
@@ -1,6 +1,6 @@
import { check } from "@tauri-apps/plugin-updater";
import { relaunch } from "@tauri-apps/plugin-process";
-import { message, ask, confirm } from "@tauri-apps/plugin-dialog";
+import { message, ask } from "@tauri-apps/plugin-dialog";
import { isPermissionGranted, requestPermission, sendNotification } from "@tauri-apps/plugin-notification";
import { log, devLog, setStatus } from "./ui";
@@ -15,6 +15,22 @@ export async function notify(title: string, body: string) {
}
}
+async function promptInstallAndRestart(version: string, install: () => Promise) {
+ setStatus("Update ready");
+ const restart = await ask(
+ `Version ${version} has been downloaded and is ready to install.\n\nRestart now to apply the update?`,
+ { title: "Update ready", kind: "info", okLabel: "Restart now", cancelLabel: "Later" }
+ );
+ if (restart) {
+ setStatus("Installing update");
+ await install();
+ await relaunch();
+ } else {
+ await notify("Zinnia", "Update downloaded. Install it later from Check now.");
+ setStatus("Idle");
+ }
+}
+
export async function checkUpdates() {
try {
setStatus("Checking updates");
@@ -26,18 +42,10 @@ export async function checkUpdates() {
return;
}
log(`Update available: ${update.version}`);
- const confirmed = await confirm(
- `Version ${update.version} is available. Download and install now?\n\nThe app will restart after installation.`,
- { title: "Update available", kind: "info", okLabel: "Install" }
- );
- if (!confirmed) {
- setStatus("Idle");
- return;
- }
setStatus("Downloading update");
- await update.downloadAndInstall();
- log("Update installed. Relaunching...");
- await relaunch();
+ await update.download();
+ log(`Update ${update.version} downloaded and ready to install.`);
+ await promptInstallAndRestart(update.version, () => update.install());
} catch (err) {
const messageText = err instanceof Error ? err.message : String(err);
log(`Updater error: ${messageText}`);
@@ -56,19 +64,9 @@ export async function autoCheckUpdates() {
log(`Update available: ${update.version}`);
await notify("Zinnia Update Available", `Version ${update.version} is available. Downloading in the background...`);
setStatus("Downloading update");
- await update.downloadAndInstall();
- setStatus("Update ready");
+ await update.download();
log(`Update ${update.version} downloaded and ready to install.`);
- const restart = await ask(
- `Version ${update.version} has been downloaded and is ready to install.\n\nRestart now to apply the update?`,
- { title: "Update ready", kind: "info", okLabel: "Restart now", cancelLabel: "Later" }
- );
- if (restart) {
- await relaunch();
- } else {
- await notify("Zinnia", "Update will be applied next time you restart.");
- setStatus("Idle");
- }
+ await promptInstallAndRestart(update.version, () => update.install());
} catch (err) {
const messageText = err instanceof Error ? err.message : String(err);
devLog(`Auto-update error: ${messageText}`);