feat(updater): wire tauri-plugin-updater with GitHub releases endpoint + update toast
This commit is contained in:
@@ -27,6 +27,7 @@ tauri = { version = "2", features = ["tray-icon"] }
|
|||||||
tauri-plugin-opener = "2"
|
tauri-plugin-opener = "2"
|
||||||
tauri-plugin-dialog = "2"
|
tauri-plugin-dialog = "2"
|
||||||
tauri-plugin-global-shortcut = "2"
|
tauri-plugin-global-shortcut = "2"
|
||||||
|
tauri-plugin-updater = "2"
|
||||||
|
|
||||||
# Serialisation
|
# Serialisation
|
||||||
serde = { version = "1", features = ["derive"] }
|
serde = { version = "1", features = ["derive"] }
|
||||||
|
|||||||
@@ -7,4 +7,5 @@ pub mod live;
|
|||||||
pub mod models;
|
pub mod models;
|
||||||
pub mod transcription;
|
pub mod transcription;
|
||||||
pub mod transcripts;
|
pub mod transcripts;
|
||||||
|
pub mod update;
|
||||||
pub mod windows;
|
pub mod windows;
|
||||||
|
|||||||
38
src-tauri/src/commands/update.rs
Normal file
38
src-tauri/src/commands/update.rs
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
use tauri::AppHandle;
|
||||||
|
use tauri_plugin_updater::UpdaterExt;
|
||||||
|
|
||||||
|
/// Check for an available update. Returns Some(version_string) if one is
|
||||||
|
/// available, None if already up to date, and Err if the check fails.
|
||||||
|
#[tauri::command]
|
||||||
|
pub async fn check_for_update(app: AppHandle) -> Result<Option<String>, String> {
|
||||||
|
let update = app
|
||||||
|
.updater()
|
||||||
|
.map_err(|e| format!("Updater not available: {e}"))?
|
||||||
|
.check()
|
||||||
|
.await
|
||||||
|
.map_err(|e| format!("Update check failed: {e}"))?;
|
||||||
|
|
||||||
|
match update {
|
||||||
|
Some(u) => Ok(Some(u.version.to_string())),
|
||||||
|
None => Ok(None),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Download and stage the update. The app will install it on next launch.
|
||||||
|
#[tauri::command]
|
||||||
|
pub async fn install_update(app: AppHandle) -> Result<(), String> {
|
||||||
|
let update = app
|
||||||
|
.updater()
|
||||||
|
.map_err(|e| format!("Updater not available: {e}"))?
|
||||||
|
.check()
|
||||||
|
.await
|
||||||
|
.map_err(|e| format!("Update check failed: {e}"))?
|
||||||
|
.ok_or_else(|| "No update available".to_string())?;
|
||||||
|
|
||||||
|
update
|
||||||
|
.download_and_install(|_, _| {}, || {})
|
||||||
|
.await
|
||||||
|
.map_err(|e| format!("Install failed: {e}"))?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
@@ -123,6 +123,7 @@ pub fn run() {
|
|||||||
.plugin(tauri_plugin_opener::init())
|
.plugin(tauri_plugin_opener::init())
|
||||||
.plugin(tauri_plugin_dialog::init())
|
.plugin(tauri_plugin_dialog::init())
|
||||||
.plugin(tauri_plugin_global_shortcut::Builder::new().build())
|
.plugin(tauri_plugin_global_shortcut::Builder::new().build())
|
||||||
|
.plugin(tauri_plugin_updater::Builder::new().build())
|
||||||
.setup(|app| {
|
.setup(|app| {
|
||||||
// Initialise database (blocking in setup — runs once at startup)
|
// Initialise database (blocking in setup — runs once at startup)
|
||||||
let db_path = database_path();
|
let db_path = database_path();
|
||||||
@@ -285,6 +286,9 @@ pub fn run() {
|
|||||||
commands::hotkey::start_evdev_hotkey,
|
commands::hotkey::start_evdev_hotkey,
|
||||||
commands::hotkey::update_evdev_hotkey,
|
commands::hotkey::update_evdev_hotkey,
|
||||||
commands::hotkey::stop_evdev_hotkey,
|
commands::hotkey::stop_evdev_hotkey,
|
||||||
|
// Updater
|
||||||
|
commands::update::check_for_update,
|
||||||
|
commands::update::install_update,
|
||||||
])
|
])
|
||||||
.run(tauri::generate_context!())
|
.run(tauri::generate_context!())
|
||||||
.expect("error while running Kon");
|
.expect("error while running Kon");
|
||||||
|
|||||||
@@ -26,6 +26,15 @@
|
|||||||
"csp": "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' asset: https://asset.localhost; connect-src ipc: http://ipc.localhost asset: https://asset.localhost http://localhost:* ws://localhost:*; media-src 'self' asset: https://asset.localhost"
|
"csp": "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' asset: https://asset.localhost; connect-src ipc: http://ipc.localhost asset: https://asset.localhost http://localhost:* ws://localhost:*; media-src 'self' asset: https://asset.localhost"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"plugins": {
|
||||||
|
"updater": {
|
||||||
|
"endpoints": [
|
||||||
|
"https://github.com/jakejars/kon/releases/latest/download/latest.json"
|
||||||
|
],
|
||||||
|
"dialog": false,
|
||||||
|
"pubkey": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
"bundle": {
|
"bundle": {
|
||||||
"active": true,
|
"active": true,
|
||||||
"targets": "all",
|
"targets": "all",
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
import { loadOsInfo } from "$lib/utils/osInfo.js";
|
import { loadOsInfo } from "$lib/utils/osInfo.js";
|
||||||
import { page, settings, saveSettings } from "$lib/stores/page.svelte.js";
|
import { page, settings, saveSettings } from "$lib/stores/page.svelte.js";
|
||||||
import { getPreferences, updatePreferences } from "$lib/stores/preferences.svelte.js";
|
import { getPreferences, updatePreferences } from "$lib/stores/preferences.svelte.js";
|
||||||
|
import { toasts } from "$lib/stores/toasts.svelte.js";
|
||||||
|
|
||||||
import { page as sveltePage } from "$app/stores";
|
import { page as sveltePage } from "$app/stores";
|
||||||
|
|
||||||
@@ -230,6 +231,15 @@
|
|||||||
} catch {
|
} catch {
|
||||||
// If commands fail, skip first-run check
|
// If commands fail, skip first-run check
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Background update check — non-blocking, silent on failure
|
||||||
|
invoke("check_for_update")
|
||||||
|
.then((version) => {
|
||||||
|
if (version) {
|
||||||
|
toasts.info(`Kon ${version} is available. Restart to install.`);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(() => { /* update check failure must not affect the app */ });
|
||||||
});
|
});
|
||||||
|
|
||||||
onDestroy(() => {
|
onDestroy(() => {
|
||||||
|
|||||||
Reference in New Issue
Block a user