diff --git a/src-tauri/src/error.rs b/src-tauri/src/error.rs index 4986e86c..da590cb8 100644 --- a/src-tauri/src/error.rs +++ b/src-tauri/src/error.rs @@ -12,7 +12,7 @@ pub enum Error { #[error(transparent)] SyncError(#[from] yaak_sync::error::Error), - + #[error(transparent)] CryptoError(#[from] yaak_crypto::error::Error), @@ -28,18 +28,21 @@ pub enum Error { #[error(transparent)] PluginError(#[from] yaak_plugins::error::Error), + #[error(transparent)] + CommonError(#[from] yaak_common::error::Error), + #[error("Updater error: {0}")] UpdaterError(#[from] tauri_plugin_updater::Error), - + #[error("JSON error: {0}")] JsonError(#[from] serde_json::error::Error), - + #[error("Tauri error: {0}")] TauriError(#[from] tauri::Error), - + #[error("Event source error: {0}")] EventSourceError(#[from] eventsource_client::Error), - + #[error("I/O error: {0}")] IOError(#[from] io::Error), diff --git a/src-tauri/src/notifications.rs b/src-tauri/src/notifications.rs index 88b28577..d824e309 100644 --- a/src-tauri/src/notifications.rs +++ b/src-tauri/src/notifications.rs @@ -2,12 +2,12 @@ use std::time::SystemTime; use crate::error::Result; use crate::history::get_num_launches; -use chrono::{DateTime, Duration, Utc}; +use chrono::{DateTime, Utc}; use log::debug; use reqwest::Method; use serde::{Deserialize, Serialize}; -use serde_json::Value; use tauri::{AppHandle, Emitter, Manager, Runtime, WebviewWindow}; +use yaak_common::api_client::yaak_api_client; use yaak_common::platform::get_os; use yaak_license::{LicenseCheckStatus, check_license}; use yaak_models::query_manager::QueryManagerExt; @@ -28,6 +28,7 @@ pub struct YaakNotifier { #[serde(default, rename_all = "camelCase")] pub struct YaakNotification { timestamp: DateTime, + timeout: Option, id: String, message: String, action: Option, @@ -81,8 +82,8 @@ impl YaakNotifier { let settings = window.db().get_settings(); let num_launches = get_num_launches(app_handle).await; let info = app_handle.package_info().clone(); - let req = reqwest::Client::default() - .request(Method::GET, "https://notify.yaak.app/notifications") + let req = yaak_api_client(app_handle)? + .request(Method::GET, "http://localhost:9444/notifications") .query(&[ ("version", info.version.to_string().as_str()), ("launches", num_launches.to_string().as_str()), @@ -96,22 +97,9 @@ impl YaakNotifier { return Ok(()); } - let result = resp.json::().await?; - - // Support both single and multiple notifications. - // TODO: Remove support for single after April 2025 - let notifications = match result { - Value::Array(a) => a - .into_iter() - .map(|a| serde_json::from_value(a).unwrap()) - .collect::>(), - a @ _ => vec![serde_json::from_value(a).unwrap()], - }; - - for notification in notifications { - let age = notification.timestamp.signed_duration_since(Utc::now()); + for notification in resp.json::>().await? { let seen = get_kv(app_handle).await?; - if seen.contains(¬ification.id) || (age > Duration::days(2)) { + if seen.contains(¬ification.id) { debug!("Already seen notification {}", notification.id); continue; } diff --git a/src-tauri/yaak-common/src/api_client.rs b/src-tauri/yaak-common/src/api_client.rs index 79c40595..f7ef75f1 100644 --- a/src-tauri/yaak-common/src/api_client.rs +++ b/src-tauri/yaak-common/src/api_client.rs @@ -1,5 +1,5 @@ use crate::error::Result; -use crate::platform::get_ua_platform; +use crate::platform::{get_ua_arch, get_ua_platform}; use reqwest::Client; use std::time::Duration; use tauri::http::{HeaderMap, HeaderValue}; @@ -8,7 +8,8 @@ use tauri::{AppHandle, Runtime}; pub fn yaak_api_client(app_handle: &AppHandle) -> Result { let platform = get_ua_platform(); let version = app_handle.package_info().version.clone(); - let ua = format!("Yaak/{version} ({platform})"); + let arch = get_ua_arch(); + let ua = format!("Yaak/{version} ({platform}; {arch})"); let mut default_headers = HeaderMap::new(); default_headers.insert("Accept", HeaderValue::from_str("application/json").unwrap()); diff --git a/src-tauri/yaak-common/src/platform.rs b/src-tauri/yaak-common/src/platform.rs index 4e1f2587..0424e5bf 100644 --- a/src-tauri/yaak-common/src/platform.rs +++ b/src-tauri/yaak-common/src/platform.rs @@ -21,3 +21,16 @@ pub fn get_ua_platform() -> &'static str { "Unknown" } } + +pub fn get_ua_arch() -> &'static str { + if cfg!(target_arch = "x86_64") { + "x86_64" + } else if cfg!(target_arch = "x86") { + "i386" + } else if cfg!(target_arch = "arm") { + "ARM" + } else if cfg!(target_arch = "aarch64") { + "ARM64" + } else { + "Unknown" + }} diff --git a/src-tauri/yaak-license/src/error.rs b/src-tauri/yaak-license/src/error.rs index 81792690..8db9f5ce 100644 --- a/src-tauri/yaak-license/src/error.rs +++ b/src-tauri/yaak-license/src/error.rs @@ -15,6 +15,9 @@ pub enum Error { #[error(transparent)] ModelError(#[from] yaak_models::error::Error), + #[error(transparent)] + CommonError(#[from] yaak_common::error::Error), + #[error("Internal server error")] ServerError, } diff --git a/src-tauri/yaak-license/src/license.rs b/src-tauri/yaak-license/src/license.rs index 48c40635..dce35ebb 100644 --- a/src-tauri/yaak-license/src/license.rs +++ b/src-tauri/yaak-license/src/license.rs @@ -7,6 +7,7 @@ use std::ops::Add; use std::time::Duration; use tauri::{AppHandle, Emitter, Manager, Runtime, WebviewWindow, is_dev}; use ts_rs::TS; +use yaak_common::api_client::yaak_api_client; use yaak_common::platform::get_os; use yaak_models::query_manager::QueryManagerExt; use yaak_models::util::UpdateSource; @@ -170,7 +171,7 @@ pub async fn check_license(window: &WebviewWindow) -> Result { info!("Checking license activation"); // A license has been activated, so let's check the license server - let client = reqwest::Client::new(); + let client = yaak_api_client(window.app_handle())?; let path = format!("/licenses/activations/{activation_id}/check"); let response = client.post(build_url(&path)).json(&payload).send().await?; diff --git a/src-web/components/Toasts.tsx b/src-web/components/Toasts.tsx index d4c9458f..ec8f054a 100644 --- a/src-web/components/Toasts.tsx +++ b/src-web/components/Toasts.tsx @@ -10,7 +10,7 @@ export type ToastInstance = { id: string; uniqueKey: string; message: ReactNode; - timeout: 3000 | 5000 | 8000 | null; + timeout: 3000 | 5000 | 8000 | (number & {}) | null; onClose?: ToastProps['onClose']; } & Omit; diff --git a/src-web/hooks/useNotificationToast.tsx b/src-web/hooks/useNotificationToast.tsx index d7a25a99..e5651087 100644 --- a/src-web/hooks/useNotificationToast.tsx +++ b/src-web/hooks/useNotificationToast.tsx @@ -13,6 +13,7 @@ export function useNotificationToast() { id: string; timestamp: string; message: string; + timeout?: number | null; action?: null | { url: string; label: string; @@ -23,7 +24,7 @@ export function useNotificationToast() { const actionLabel = payload.action?.label; showToast({ id: payload.id, - timeout: null, + timeout: payload.timeout ?? undefined, message: payload.message, onClose: () => { markRead(payload.id)