diff --git a/Cargo.toml b/Cargo.toml index 593722e..d269d4e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,7 +25,7 @@ tauri-sys = { path = ".", features = ["all"] } all-features = true [features] -all = ["app", "clipboard", "event", "mocks", "tauri", "window", "process", "dialog", "os", "notification", "path"] +all = ["app", "clipboard", "event", "mocks", "tauri", "window", "process", "dialog", "os", "notification", "path", "updater"] app = ["dep:semver"] clipboard = [] dialog = [] @@ -37,6 +37,7 @@ process = [] os = ["dep:semver"] notification = [] path = [] +updater = [] [workspace] members = ["examples/test", "examples/test/src-tauri"] diff --git a/src/updater.rs b/src/updater.rs index 937c517..f879913 100644 --- a/src/updater.rs +++ b/src/updater.rs @@ -1,61 +1,133 @@ use serde::Deserialize; +use wasm_bindgen::{prelude::Closure, JsValue}; -#[derive(Deserialize, Debug)] +#[derive(Deserialize, Debug, Clone)] pub struct UpdateManifest { pub body: String, pub date: String, pub version: String } -#[derive(Deserialize, Debug)] +#[derive(Deserialize, Debug, Clone)] pub struct UpdateResult { pub manifest: Option, pub should_update: bool } #[derive(Deserialize)] -pub enum UpdateStatus { - PENDING, - ERROR, - DONE, - UPTODATE +struct UpdateStatusResult { + error: Option, + status: UpdateStatus } -/// Install the update if there's one available. -/// -/// # Example -/// -/// ```rust,no_run -/// use tauri_api::updater::install_update; -/// -/// install_update().await; -/// ``` -#[inline(always)] -pub async fn install_update() { - inner::installUpdate().await +#[derive(Deserialize)] +pub enum UpdateStatus { + #[serde(rename = "PENDING")] + Pending, + #[serde(rename = "DONE")] + Done, + #[serde(rename = "UPTODATE")] + UpToDate } /// Checks if an update is available. -/// +/// /// # Example -/// +/// /// ```rust,no_run -/// use tauri_api::updater::{check_update, UpdateResult}; -/// -/// let update: UpdateResult = check_update().await; +/// use tauri_sys::updater::check_update; +/// +/// # async fn main() -> Result<(), Box> { +/// let update = check_update().await?; +/// // now run installUpdate() if needed +/// # Ok(()) +/// # } /// ``` +pub async fn check_update() -> crate::Result { + let raw = inner::checkUpdate().await?; + + Ok(serde_wasm_bindgen::from_value(raw)?) +} + +/// Install the update if there's one available. +/// +/// # Example +/// +/// ```rust,no_run +/// use tauri_sys::updater::{check_update, install_update}; +/// +/// # async fn main() -> Result<(), Box> { +/// let update = check_update().await?; +/// +/// if update.should_update { +/// log::info("Installing update {:?}", update.manifest); +/// install_update().await?; +/// } +/// # Ok(()) +/// # } +/// ``` +pub async fn install_update() -> crate::Result<()> { + inner::installUpdate().await?; + Ok(()) +} + +/// Listen to an updater event. +/// +/// # Example +/// +/// ```rust,no_run +/// use tauri_sys::updater::on_updater_event; +/// +/// # async fn main() -> Result<(), Box> { +/// let unlisten = on_updater_event(|event| { +/// log::debug!("Updater event {:?}", event); +/// }).await?; +/// +/// // you need to call unlisten if your handler goes out of scope e.g. the component is unmounted +/// unlisten(); +/// # Ok(()) +/// # } +/// ``` +/// Note that removing the listener is required if your listener goes out of scope e.g. the component is unmounted. #[inline(always)] -pub async fn check_update() -> UpdateResult { - let update = inner::checkUpdate().await; - serde_wasm_bindgen::from_value(update).unwrap() +pub async fn on_updater_event(mut handler: H) -> crate::Result +where + H: FnMut(Result) + 'static, +{ + let closure = Closure::::new(move |raw| { + let raw: UpdateStatusResult = serde_wasm_bindgen::from_value(raw).unwrap(); + + let result = if let Some(error) = raw.error { + Err(error) + } else { + Ok(raw.status) + }; + + (handler)(result) + }); + + let unlisten = inner::onUpdaterEvent(&closure).await?; + + closure.forget(); + + let unlisten = js_sys::Function::from(unlisten); + Ok(move || { + unlisten.call0(&wasm_bindgen::JsValue::NULL).unwrap(); + }) } mod inner { - use wasm_bindgen::{prelude::wasm_bindgen, JsValue}; + use wasm_bindgen::prelude::*; - #[wasm_bindgen(module = "/dist/updater.js")] + #[wasm_bindgen(module = "/src/updater.js")] extern "C" { - pub async fn installUpdate(); - pub async fn checkUpdate() -> JsValue; + #[wasm_bindgen(catch)] + pub async fn checkUpdate() -> Result; + #[wasm_bindgen(catch)] + pub async fn installUpdate() -> Result; + #[wasm_bindgen(catch)] + pub async fn onUpdaterEvent( + handler: &Closure, + ) -> Result; } }