// Copyright 2019-2023 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT use crate::{PendingUpdate, Result, UpdaterExt}; use serde::Serialize; use tauri::{ipc::Channel, AppHandle, Runtime, State}; use std::{ sync::atomic::{AtomicBool, Ordering}, time::Duration, }; #[derive(Debug, Serialize)] #[serde(tag = "event", content = "data")] pub enum DownloadEvent { #[serde(rename_all = "camelCase")] Started { content_length: Option, }, #[serde(rename_all = "camelCase")] Progress { chunk_length: usize, }, Finished, } #[derive(Serialize, Default)] #[serde(rename_all = "camelCase")] pub(crate) struct Metadata { available: bool, current_version: String, version: String, date: Option, body: Option, } #[tauri::command] pub(crate) async fn check( app: AppHandle, pending: State<'_, PendingUpdate>, headers: Option>, timeout: Option, target: Option, ) -> Result { let mut builder = app.updater_builder(); if let Some(headers) = headers { for (k, v) in headers { builder = builder.header(k, v)?; } } if let Some(timeout) = timeout { builder = builder.timeout(Duration::from_secs(timeout)); } if let Some(target) = target { builder = builder.target(target); } let updater = builder.build()?; let update = updater.check().await?; let mut metadata = Metadata::default(); if let Some(update) = update { metadata.available = true; metadata.current_version = update.current_version.clone(); metadata.version = update.version.clone(); metadata.date = update.date.map(|d| d.to_string()); metadata.body = update.body.clone(); pending.0.lock().await.replace(update); } Ok(metadata) } #[tauri::command] pub(crate) async fn download_and_install( _app: AppHandle, pending: State<'_, PendingUpdate>, on_event: Channel, ) -> Result<()> { if let Some(pending) = &*pending.0.lock().await { let first_chunk = AtomicBool::new(false); let on_event_c = on_event.clone(); pending .download_and_install( move |chunk_length, content_length| { if first_chunk.swap(false, Ordering::Acquire) { on_event .send(DownloadEvent::Started { content_length }) .unwrap(); } on_event .send(DownloadEvent::Progress { chunk_length }) .unwrap(); }, move || { on_event_c.send(&DownloadEvent::Finished).unwrap(); }, ) .await?; } Ok(()) }