diff --git a/apps/desktop/src-tauri/Cargo.lock b/apps/desktop/src-tauri/Cargo.lock index 9e700cc5..1a04cf51 100644 --- a/apps/desktop/src-tauri/Cargo.lock +++ b/apps/desktop/src-tauri/Cargo.lock @@ -2738,6 +2738,7 @@ dependencies = [ "tauri-plugin-process", "tauri-plugin-shell", "tauri-plugin-single-instance", + "tauri-plugin-store", "tauri-plugin-updater", "tauri-plugin-websocket", "tauri-plugin-window-state", @@ -4510,6 +4511,21 @@ dependencies = [ "zbus", ] +[[package]] +name = "tauri-plugin-store" +version = "2.0.0-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e54ba1a0c0c60a6a08e711e184239f8a50354988b6fe1af8b5ce2215b2e79a2" +dependencies = [ + "dunce", + "log", + "serde", + "serde_json", + "tauri", + "tauri-plugin", + "thiserror", +] + [[package]] name = "tauri-plugin-updater" version = "2.0.0-rc.3" diff --git a/apps/desktop/src-tauri/Cargo.toml b/apps/desktop/src-tauri/Cargo.toml index 5f488fdc..7a261821 100644 --- a/apps/desktop/src-tauri/Cargo.toml +++ b/apps/desktop/src-tauri/Cargo.toml @@ -36,6 +36,7 @@ tauri-plugin-os = "2.0.0-rc.1" tauri-plugin-http = "2.0.0-rc.4" tauri-plugin-log = "2.0.0-rc.2" tauri-plugin-notification = "2.0.0-rc.5" +tauri-plugin-store = "2.0.0-rc" anyhow = "1.0.86" log = "0.4.22" diff --git a/apps/desktop/src-tauri/src/app_settings.rs b/apps/desktop/src-tauri/src/app_settings.rs new file mode 100644 index 00000000..bf6477e4 --- /dev/null +++ b/apps/desktop/src-tauri/src/app_settings.rs @@ -0,0 +1,85 @@ +use log::debug; +use serde::{Deserialize, Serialize}; +use serde_json::json; +use tauri::{AppHandle, Manager, Wry}; +use tauri_plugin_store::{Store, StoreBuilder}; + +#[derive(Deserialize, Serialize, Debug, Copy, Clone)] +#[serde(rename_all = "SCREAMING_SNAKE_CASE")] +pub enum WindowLayout { + Left, + Right, + Center, +} + +#[derive(Deserialize, Serialize, Debug)] +#[serde(rename_all = "camelCase")] +pub struct FeatureFlags { + hide_overlay_on_mouseover: bool, +} + +#[derive(Deserialize, Serialize, Debug)] +#[serde(rename_all = "camelCase")] +pub struct Settings { + pub pin: bool, + pub placment: WindowLayout, + pub telemetry: bool, + pub join_history_notifications: bool, + pub show_only_talking_users: bool, + pub feature_flags: FeatureFlags, +} + +// create a default config +impl Default for Settings { + fn default() -> Self { + Settings { + pin: false, + placment: WindowLayout::Center, + telemetry: true, + join_history_notifications: true, + show_only_talking_users: true, + feature_flags: FeatureFlags { + hide_overlay_on_mouseover: false, + }, + } + } +} + +const CONFIG_FILE_NAME: &str = "experimental_config.json"; +// create a helper function to seed the config with values +pub fn get_app_settings(app: &AppHandle) -> Store { + debug!("Creating or getting app settings..."); + // create the store + let mut appdir = app + .path() + .app_data_dir() + .expect("failed to get app data dir"); + appdir.push(CONFIG_FILE_NAME); + let config_exists = (appdir.clone()).exists(); + + let mut store = StoreBuilder::new(CONFIG_FILE_NAME) + .serialize(|cache| serde_json::to_vec_pretty(&cache).map_err(Into::into)) + .build(app.app_handle().clone()); + + // if the file exists we don't want to overwrite it + if config_exists { + debug!("Config file already exists, loading from file"); + // NOTE: we can get the config from the filesystem + store.load(); + + // add keys from the default confg + } else { + // NOTE: we need to create the config for the first time + store.insert("pin".to_string(), json!(false)); + store.insert("placement".to_string(), json!(WindowLayout::Center)); + store.insert("telemetry".to_string(), json!(true)); + store.insert("joinHistoryNotifications".to_string(), json!(true)); + store.insert("showOnlyTalkingUsers".to_string(), json!(true)); + store.insert("featureFlags".to_string(), json!({})); + + store.save(); + debug!("Config file created successfully"); + } + + store +} diff --git a/apps/desktop/src-tauri/src/commands.rs b/apps/desktop/src-tauri/src/commands.rs index 5cdb1cbf..dba1fba0 100644 --- a/apps/desktop/src-tauri/src/commands.rs +++ b/apps/desktop/src-tauri/src/commands.rs @@ -3,9 +3,11 @@ use std::{ sync::{atomic::AtomicBool, Mutex}, }; +use serde_json::json; use tauri::{image::Image, menu::Menu, AppHandle, Emitter, Manager, State, WebviewWindow, Wry}; +use tauri_plugin_store::Store; -use crate::{constants::*, Pinned, TrayMenu}; +use crate::{constants::*, AppSettings, Pinned, TrayMenu}; #[tauri::command] pub fn open_settings(window: WebviewWindow, update: bool) { @@ -34,7 +36,7 @@ pub fn close_settings(window: WebviewWindow) { #[tauri::command] pub fn get_pin(storage: State) -> bool { - storage.0.load(std::sync::atomic::Ordering::Relaxed) + storage.load(std::sync::atomic::Ordering::Relaxed) } #[tauri::command] @@ -43,16 +45,27 @@ pub fn open_devtools(window: WebviewWindow) { } #[tauri::command] -pub fn toggle_pin(window: WebviewWindow, pin: State, menu: State) { +pub fn toggle_pin( + window: WebviewWindow, + pin: State, + menu: State, + config: State, +) { let app = window.app_handle(); let value = !get_pin(app.state::()); - _set_pin(value, &window, pin, menu); + _set_pin(value, &window, pin, menu, config); } #[tauri::command] -pub fn set_pin(window: WebviewWindow, pin: State, menu: State, value: bool) { - _set_pin(value, &window, pin, menu); +pub fn set_pin( + window: WebviewWindow, + pin: State, + menu: State, + value: bool, + settings: State, +) { + _set_pin(value, &window, pin, menu, settings); } impl Deref for Pinned { @@ -63,6 +76,14 @@ impl Deref for Pinned { } } +impl Deref for AppSettings { + type Target = Mutex>; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + impl Deref for TrayMenu { type Target = Mutex>; @@ -71,7 +92,13 @@ impl Deref for TrayMenu { } } -fn _set_pin(value: bool, window: &WebviewWindow, pinned: State, menu: State) { +fn _set_pin( + value: bool, + window: &WebviewWindow, + pinned: State, + menu: State, + config: State, +) { // @d0nutptr cooked here pinned.store(value, std::sync::atomic::Ordering::Relaxed); @@ -103,6 +130,11 @@ fn _set_pin(value: bool, window: &WebviewWindow, pinned: State, menu: St } }); + if let Ok(mut c) = config.lock() { + c.insert("pin".to_owned(), json!(value)); + c.save(); + } + window.set_ignore_cursor_events(value); // update the tray icon diff --git a/apps/desktop/src-tauri/src/main.rs b/apps/desktop/src-tauri/src/main.rs index 8911c88f..bc7e2d8c 100644 --- a/apps/desktop/src-tauri/src/main.rs +++ b/apps/desktop/src-tauri/src/main.rs @@ -8,12 +8,14 @@ extern crate objc; mod app_handle; +mod app_settings; mod commands; mod constants; mod tray; mod window_custom; use crate::commands::*; +use app_settings::get_app_settings; use constants::*; use log::{debug, info}; use std::{ @@ -22,6 +24,7 @@ use std::{ }; use tauri::{generate_handler, menu::Menu, LogicalSize, Manager, Wry}; use tauri_plugin_log::{Target, TargetKind}; +use tauri_plugin_store::Store; use tauri_plugin_window_state::StateFlags; use tray::Tray; use window_custom::WebviewWindowExt; @@ -39,7 +42,7 @@ use system_notification::WorkspaceListener; use tauri::WebviewWindow; pub struct Pinned(AtomicBool); - +pub struct AppSettings(Mutex>); pub struct TrayMenu(Mutex>); #[cfg(target_os = "macos")] @@ -95,6 +98,7 @@ fn main() { .plugin(window_state_plugin.build()) .plugin(tauri_plugin_websocket::init()) .plugin(tauri_plugin_fs::init()) + .plugin(tauri_plugin_store::Builder::default().build()) .plugin(tauri_plugin_process::init()) .plugin(tauri_plugin_shell::init()) .plugin(tauri_plugin_os::init()) @@ -133,6 +137,10 @@ fn main() { window.set_decorations(false); window.set_shadow(false); + // we should call this to create the config file + let app_settings = get_app_settings(&app.app_handle()); + app.manage(AppSettings(Mutex::new(app_settings))); + // add mac things #[cfg(target_os = "macos")] apply_macos_specifics(&window); diff --git a/apps/desktop/src-tauri/src/tray.rs b/apps/desktop/src-tauri/src/tray.rs index cb775ed8..b7f9c74e 100644 --- a/apps/desktop/src-tauri/src/tray.rs +++ b/apps/desktop/src-tauri/src/tray.rs @@ -10,9 +10,9 @@ use anyhow::Result; use tauri_plugin_window_state::{AppHandleExt, StateFlags}; use crate::{ - commands, toggle_pin, Pinned, TrayMenu, MAIN_WINDOW_NAME, OVERLAYED, SETTINGS_WINDOW_NAME, - TRAY_OPEN_DEVTOOLS_MAIN, TRAY_OPEN_DEVTOOLS_SETTINGS, TRAY_QUIT, TRAY_RELOAD, TRAY_SETTINGS, - TRAY_SHOW_APP, TRAY_TOGGLE_PIN, + commands, toggle_pin, AppSettings, Pinned, TrayMenu, MAIN_WINDOW_NAME, OVERLAYED, + SETTINGS_WINDOW_NAME, TRAY_OPEN_DEVTOOLS_MAIN, TRAY_OPEN_DEVTOOLS_SETTINGS, TRAY_QUIT, + TRAY_RELOAD, TRAY_SETTINGS, TRAY_SHOW_APP, TRAY_TOGGLE_PIN, }; pub struct Tray; @@ -52,7 +52,12 @@ impl Tray { TRAY_TOGGLE_PIN => { let window = app.get_webview_window(MAIN_WINDOW_NAME).unwrap(); - toggle_pin(window, app.state::(), app.state::()) + toggle_pin( + window, + app.state::(), + app.state::(), + app.state::(), + ); } TRAY_SHOW_APP => { let window = app.get_webview_window(MAIN_WINDOW_NAME).unwrap(); diff --git a/turbo.json b/turbo.json index 5a9122f2..064811ea 100644 --- a/turbo.json +++ b/turbo.json @@ -11,6 +11,7 @@ "TAURI_SIGNING_PRIVATE_KEY", "TAURI_SIGNING_PUBLIC_KEY", "VITE_AXIOM_TOKEN", + "LOG_LEVEL", "R2_ACCOUNT_ID", "R2_ACCESS_KEY_ID", "R2_SECRET_ACCESS_KEY",