Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
"@tauri-apps/plugin-dialog": "^2.4.2",
"@tauri-apps/plugin-fs": "^2.4.4",
"@tauri-apps/plugin-os": "^2.3.2",
"@tauri-apps/plugin-process": "^2.3.1",
"@tauri-apps/plugin-sql": "^2.3.1",
"@tauri-apps/plugin-store": "^2.4.1",
"@tauri-apps/plugin-updater": "^2.9.0",
Expand Down
11 changes: 11 additions & 0 deletions src-tauri/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions src-tauri/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,5 @@ image = "0.25.9"

[target.'cfg(not(any(target_os = "android", target_os = "ios")))'.dependencies]
tauri-plugin-updater = "2"
tauri-plugin-process = "2"

3 changes: 2 additions & 1 deletion src-tauri/capabilities/default.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
"core:path:default",
"os:default",
"clipboard-manager:allow-write-image",
"clipboard-manager:allow-write-text"
"clipboard-manager:allow-write-text",
"process:allow-restart"
]
}
46 changes: 38 additions & 8 deletions src-tauri/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
use tauri_plugin_updater::UpdaterExt;
use arboard::Clipboard;
use image::ImageReader;
use std::sync::Mutex;
use tauri::{Emitter, Manager};
use tauri_plugin_updater::UpdaterExt;

mod ssh_tunnel;

use ssh_tunnel::TunnelManager;

struct PendingUpdate {
bytes: Mutex<Option<Vec<u8>>>,
}

// Learn more about Tauri commands at https://tauri.app/develop/calling-rust/
#[tauri::command]
fn greet(name: &str) -> String {
Expand Down Expand Up @@ -37,12 +43,30 @@ fn copy_image_to_clipboard(path: String) -> Result<(), String> {
Ok(())
}

#[tauri::command]
async fn install_update(
app: tauri::AppHandle,
pending: tauri::State<'_, PendingUpdate>,
) -> Result<(), String> {
let bytes = pending.bytes.lock().unwrap().take();
if let Some(bytes) = bytes {
// Re-check for update to get the Update object needed for install
if let Some(update) = app.updater().map_err(|e| e.to_string())?.check().await.map_err(|e| e.to_string())? {
update.install(&bytes).map_err(|e| e.to_string())?;
app.restart();
}
}
Ok(())
}

#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
tauri::Builder::default()
.plugin(tauri_plugin_os::init())
.manage(TunnelManager::new())
.manage(PendingUpdate { bytes: Mutex::new(None) })
.plugin(tauri_plugin_updater::Builder::new().build())
.plugin(tauri_plugin_process::init())
.plugin(tauri_plugin_store::Builder::new().build())
.plugin(tauri_plugin_sql::Builder::new().build())
.plugin(tauri_plugin_dialog::init())
Expand All @@ -51,6 +75,7 @@ pub fn run() {
.invoke_handler(tauri::generate_handler![
greet,
copy_image_to_clipboard,
install_update,
ssh_tunnel::create_ssh_tunnel,
ssh_tunnel::close_ssh_tunnel,
ssh_tunnel::check_tunnel_status,
Expand All @@ -59,21 +84,21 @@ pub fn run() {
.setup(|app| {
let handle = app.handle().clone();
tauri::async_runtime::spawn(async move {
update(handle).await.unwrap();
let _ = check_for_update(handle).await;
});
Ok(())
})
.run(tauri::generate_context!())
.expect("error while running tauri application");
}

async fn update(app: tauri::AppHandle) -> tauri_plugin_updater::Result<()> {
async fn check_for_update(app: tauri::AppHandle) -> tauri_plugin_updater::Result<()> {
if let Some(update) = app.updater()?.check().await? {
let mut downloaded = 0;
let version = update.version.clone();

// alternatively we could also call update.download() and update.install() separately
update
.download_and_install(
let bytes = update
.download(
|chunk_length, content_length| {
downloaded += chunk_length;
println!("downloaded {downloaded} from {content_length:?}");
Expand All @@ -84,8 +109,13 @@ async fn update(app: tauri::AppHandle) -> tauri_plugin_updater::Result<()> {
)
.await?;

println!("update installed");
app.restart();
println!("update downloaded, notifying frontend");

// Store the bytes for later installation
let pending = app.state::<PendingUpdate>();
*pending.bytes.lock().unwrap() = Some(bytes);

let _ = app.emit("update-downloaded", version);
}

Ok(())
Expand Down
18 changes: 18 additions & 0 deletions src/routes/+layout.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
import { setShortcuts } from "$lib/shortcuts/index.js";
import KeyboardShortcutsDialog from "$lib/components/keyboard-shortcuts-dialog.svelte";
import CommandPalette from "$lib/components/command-palette.svelte";
import { listen } from "@tauri-apps/api/event";
import { invoke } from "@tauri-apps/api/core";
import { toast } from "svelte-sonner";

setDatabase();
const db = useDatabase();
Expand All @@ -18,6 +21,21 @@
function handleBeforeUnload() {
db.flushPersistence();
}

$effect(() => {
const unlisten = listen<string>("update-downloaded", (event) => {
toast.success(`Update v${event.payload} downloaded`, {
action: {
label: "Install & Restart",
onClick: () => invoke("install_update"),
},
duration: Infinity,
});
});
return () => {
unlisten.then((fn) => fn());
};
});
</script>

<svelte:window onkeydown={shortcuts.handleKeydown} onbeforeunload={handleBeforeUnload} />
Expand Down
Loading