From a7c307959cf43ae797f004aa79257db5fd877178 Mon Sep 17 00:00:00 2001 From: Sam Warfield Date: Sat, 10 Jan 2026 15:51:36 -0700 Subject: [PATCH] Added persistant settings on desktop --- Cargo.lock | 21 ++++++++++++++++++ gui/Cargo.toml | 2 ++ gui/src/app.rs | 3 +++ gui/src/imp/desktop.rs | 48 ++++++++++++++++++++++++++++++++++++++---- gui/src/imp/web.rs | 4 ++++ 5 files changed, 74 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 66c8440..3b6252c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2270,6 +2270,17 @@ dependencies = [ "xxhash-rust", ] +[[package]] +name = "etcetera" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26c7b13d0780cb82722fd59f6f57f925e143427e4a75313a6c77243bf5326ae6" +dependencies = [ + "cfg-if", + "home", + "windows-sys 0.59.0", +] + [[package]] name = "euclid" version = "0.22.11" @@ -3157,6 +3168,15 @@ version = "1.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ad6880c8d4a9ebf39c6e8b77007ce223f646a4d21ce29d99f70cb16420545425" +[[package]] +name = "home" +version = "0.5.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc627f471c528ff0c4a49e1d5e60450c8f6461dd6d10ba9dcd3a61d3dff7728d" +dependencies = [ + "windows-sys 0.61.2", +] + [[package]] name = "html-purifier" version = "0.3.0" @@ -4261,6 +4281,7 @@ dependencies = [ "dioxus", "dioxus-asset-resolver", "dioxus-web", + "etcetera", "futures", "futures-channel", "gloo-timers", diff --git a/gui/Cargo.toml b/gui/Cargo.toml index e936d38..a7337ee 100644 --- a/gui/Cargo.toml +++ b/gui/Cargo.toml @@ -63,6 +63,7 @@ tokio-rustls = { version = "^0.26.0", optional = true } opus = { version = "0.3.0", optional = true } cpal = { version = "0.15.3", optional = true } dasp_ring_buffer = { version = "0.11.0", optional = true } +etcetera = { version = "0.10.0", optional = true } # Base Dependencies # ================ @@ -130,4 +131,5 @@ desktop = [ "cpal", "dasp_ring_buffer", "rfd/xdg-portal", + "etcetera", ] diff --git a/gui/src/app.rs b/gui/src/app.rs index efe2ff8..484aa11 100644 --- a/gui/src/app.rs +++ b/gui/src/app.rs @@ -575,6 +575,9 @@ pub fn LoginView(config: Resource) -> Element { let do_connect = move |_| { //let _ = set_default_username(&username.read()); let _ = imp::set_default_username(&username.read()); + if config.read().as_ref().is_some_and(|cfg| cfg.any_server) { + imp::set_default_server(&address.read()); + } net.send(Connect { address: address.read().clone(), username: username.read().clone(), diff --git a/gui/src/imp/desktop.rs b/gui/src/imp/desktop.rs index 2e9faf2..330c0d4 100644 --- a/gui/src/imp/desktop.rs +++ b/gui/src/imp/desktop.rs @@ -1,11 +1,13 @@ use crate::app::Command; use crate::effects::{AudioProcessor, AudioProcessorSender}; -use color_eyre::eyre::{bail, eyre, Context, Error}; +use color_eyre::eyre::{bail, eyre, Error}; use cpal::traits::{DeviceTrait, HostTrait, StreamTrait as _}; use dioxus::hooks::UnboundedReceiver; +use etcetera::{choose_app_strategy, AppStrategy, AppStrategyArgs}; use futures::io::{AsyncRead, AsyncWrite}; use mumble_protocol::control::ClientControlCodec; use mumble_web2_common::{ClientConfig, ServerStatus}; +use std::collections::HashMap; use std::mem::replace; use std::net::ToSocketAddrs; use std::sync::Arc; @@ -314,17 +316,55 @@ pub async fn network_connect( crate::network_loop(username, event_rx, reader, writer).await } +fn get_config_path() -> std::path::PathBuf { + let strategy = choose_app_strategy(AppStrategyArgs { + top_level_domain: "com".to_string(), + author: "Ohea Corp".to_string(), + app_name: "Mumble Web2".to_string(), + }) + .expect("failed to choose app strategy"); + strategy.config_dir().join("config.json") +} + +fn load_config_map() -> HashMap { + let config_path = get_config_path(); + match std::fs::read_to_string(&config_path) { + Ok(contents) => serde_json::from_str(&contents).unwrap_or_default(), + Err(_) => HashMap::new(), + } +} + +fn save_config_map(config: &HashMap) -> color_eyre::Result<()> { + let config_path = get_config_path(); + if let Some(parent) = config_path.parent() { + std::fs::create_dir_all(parent)?; + } + let contents = serde_json::to_string_pretty(config)?; + std::fs::write(&config_path, contents)?; + Ok(()) +} + pub fn set_default_username(username: &str) -> Option<()> { - None + let mut config = load_config_map(); + config.insert("username".to_string(), username.to_string()); + save_config_map(&config).ok() +} + +pub fn set_default_server(server: &str) -> Option<()> { + let mut config = load_config_map(); + config.insert("server".to_string(), server.to_string()); + save_config_map(&config).ok() } pub fn load_username() -> Option { - return None; + let config = load_config_map(); + config.get("username").cloned() } pub async fn load_config() -> color_eyre::Result { + let config = load_config_map(); Ok(ClientConfig { - proxy_url: None, + proxy_url: config.get("server").cloned(), cert_hash: None, any_server: true, }) diff --git a/gui/src/imp/web.rs b/gui/src/imp/web.rs index 74f2321..ade2576 100644 --- a/gui/src/imp/web.rs +++ b/gui/src/imp/web.rs @@ -399,6 +399,10 @@ pub fn set_default_username(username: &str) -> Option<()> { .ok() } +pub fn set_default_server(username: &str) -> Option<()> { + None +} + pub fn load_username() -> Option { web_sys::window() .unwrap()