Add ServerEntry model and server list persistence to platform trait
Introduces a ServerEntry struct in common with name, address, port, username, and optional password fields. Extends PlatformInterface with load_servers/save_servers methods, implemented across all platforms (desktop persists to JSON config, web uses localStorage, mobile/stub are stubs). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -16,3 +16,13 @@ pub struct ServerStatus {
|
|||||||
pub max_users: Option<u32>,
|
pub max_users: Option<u32>,
|
||||||
pub bandwidth: Option<u32>,
|
pub bandwidth: Option<u32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Deserialize, Serialize, Default, PartialEq)]
|
||||||
|
pub struct ServerEntry {
|
||||||
|
pub name: String,
|
||||||
|
pub address: String,
|
||||||
|
pub port: u16,
|
||||||
|
pub username: String,
|
||||||
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||||
|
pub password: Option<String>,
|
||||||
|
}
|
||||||
|
|||||||
+17
-1
@@ -2,7 +2,7 @@ use crate::app::Command;
|
|||||||
use color_eyre::eyre::Error;
|
use color_eyre::eyre::Error;
|
||||||
use dioxus::hooks::UnboundedReceiver;
|
use dioxus::hooks::UnboundedReceiver;
|
||||||
use etcetera::{choose_app_strategy, AppStrategy, AppStrategyArgs};
|
use etcetera::{choose_app_strategy, AppStrategy, AppStrategyArgs};
|
||||||
use mumble_web2_common::{ClientConfig, ServerStatus};
|
use mumble_web2_common::{ClientConfig, ServerEntry, ServerStatus};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
@@ -46,6 +46,22 @@ impl super::PlatformInterface for DesktopPlatform {
|
|||||||
save_config_map(&config).ok()
|
save_config_map(&config).ok()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn load_servers() -> Vec<ServerEntry> {
|
||||||
|
let config = load_config_map();
|
||||||
|
config
|
||||||
|
.get("servers")
|
||||||
|
.and_then(|s| serde_json::from_str(s).ok())
|
||||||
|
.unwrap_or_default()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn save_servers(servers: &[ServerEntry]) {
|
||||||
|
let mut config = load_config_map();
|
||||||
|
if let Ok(json) = serde_json::to_string(servers) {
|
||||||
|
config.insert("servers".to_string(), json);
|
||||||
|
let _ = save_config_map(&config);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async fn network_connect(
|
async fn network_connect(
|
||||||
address: String,
|
address: String,
|
||||||
username: String,
|
username: String,
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use crate::app::Command;
|
use crate::app::Command;
|
||||||
use color_eyre::eyre::Error;
|
use color_eyre::eyre::Error;
|
||||||
use dioxus::hooks::UnboundedReceiver;
|
use dioxus::hooks::UnboundedReceiver;
|
||||||
use mumble_web2_common::{ClientConfig, ServerStatus};
|
use mumble_web2_common::{ClientConfig, ServerEntry, ServerStatus};
|
||||||
use std::future::Future;
|
use std::future::Future;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
@@ -31,10 +31,16 @@ impl super::PlatformInterface for MobilePlatform {
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_default_server(server: &str) -> Option<()> {
|
fn set_default_server(_server: &str) -> Option<()> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn load_servers() -> Vec<ServerEntry> {
|
||||||
|
Vec::new()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn save_servers(_servers: &[ServerEntry]) {}
|
||||||
|
|
||||||
async fn network_connect(
|
async fn network_connect(
|
||||||
address: String,
|
address: String,
|
||||||
username: String,
|
username: String,
|
||||||
|
|||||||
+7
-1
@@ -7,7 +7,7 @@
|
|||||||
use crate::{app::Command, effects::AudioProcessor};
|
use crate::{app::Command, effects::AudioProcessor};
|
||||||
use color_eyre::eyre::Error;
|
use color_eyre::eyre::Error;
|
||||||
use dioxus::hooks::UnboundedReceiver;
|
use dioxus::hooks::UnboundedReceiver;
|
||||||
use mumble_web2_common::{ClientConfig, ServerStatus};
|
use mumble_web2_common::{ClientConfig, ServerEntry, ServerStatus};
|
||||||
use std::future::Future;
|
use std::future::Future;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
@@ -90,6 +90,12 @@ pub trait PlatformInterface {
|
|||||||
/// Save the default server URL.
|
/// Save the default server URL.
|
||||||
fn set_default_server(server: &str) -> Option<()>;
|
fn set_default_server(server: &str) -> Option<()>;
|
||||||
|
|
||||||
|
/// Load the saved server list.
|
||||||
|
fn load_servers() -> Vec<ServerEntry>;
|
||||||
|
|
||||||
|
/// Save the server list.
|
||||||
|
fn save_servers(servers: &[ServerEntry]);
|
||||||
|
|
||||||
/// Async sleep for the given duration.
|
/// Async sleep for the given duration.
|
||||||
fn sleep(duration: Duration) -> impl Future<Output = ()>;
|
fn sleep(duration: Duration) -> impl Future<Output = ()>;
|
||||||
}
|
}
|
||||||
|
|||||||
+9
-1
@@ -3,7 +3,7 @@
|
|||||||
use crate::effects::AudioProcessor;
|
use crate::effects::AudioProcessor;
|
||||||
use color_eyre::eyre::Error;
|
use color_eyre::eyre::Error;
|
||||||
use dioxus::hooks::UnboundedReceiver;
|
use dioxus::hooks::UnboundedReceiver;
|
||||||
use mumble_web2_common::{ClientConfig, ServerStatus};
|
use mumble_web2_common::{ClientConfig, ServerEntry, ServerStatus};
|
||||||
use std::future::Future;
|
use std::future::Future;
|
||||||
|
|
||||||
pub struct StubPlatform;
|
pub struct StubPlatform;
|
||||||
@@ -54,6 +54,14 @@ impl super::PlatformInterface for StubPlatform {
|
|||||||
panic!("stubbed platform")
|
panic!("stubbed platform")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn load_servers() -> Vec<ServerEntry> {
|
||||||
|
panic!("stubbed platform")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn save_servers(_servers: &[ServerEntry]) {
|
||||||
|
panic!("stubbed platform")
|
||||||
|
}
|
||||||
|
|
||||||
fn sleep(_duration: std::time::Duration) -> impl Future<Output = ()> {
|
fn sleep(_duration: std::time::Duration) -> impl Future<Output = ()> {
|
||||||
async { panic!("stubbed platform") }
|
async { panic!("stubbed platform") }
|
||||||
}
|
}
|
||||||
|
|||||||
+19
-1
@@ -6,7 +6,7 @@ use dioxus::prelude::*;
|
|||||||
use gloo_timers::future::TimeoutFuture;
|
use gloo_timers::future::TimeoutFuture;
|
||||||
use js_sys::Float32Array;
|
use js_sys::Float32Array;
|
||||||
use mumble_protocol::control::ClientControlCodec;
|
use mumble_protocol::control::ClientControlCodec;
|
||||||
use mumble_web2_common::{ClientConfig, ServerStatus};
|
use mumble_web2_common::{ClientConfig, ServerEntry, ServerStatus};
|
||||||
use reqwest::Url;
|
use reqwest::Url;
|
||||||
use std::future::Future;
|
use std::future::Future;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
@@ -129,6 +129,24 @@ impl super::PlatformInterface for WebPlatform {
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn load_servers() -> Vec<ServerEntry> {
|
||||||
|
web_sys::window()
|
||||||
|
.and_then(|w| w.local_storage().ok()?)
|
||||||
|
.and_then(|s| s.get_item("servers").ok()?)
|
||||||
|
.and_then(|json| serde_json::from_str(&json).ok())
|
||||||
|
.unwrap_or_default()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn save_servers(servers: &[ServerEntry]) {
|
||||||
|
if let Ok(json) = serde_json::to_string(servers) {
|
||||||
|
if let Some(storage) = web_sys::window()
|
||||||
|
.and_then(|w| w.local_storage().ok()?)
|
||||||
|
{
|
||||||
|
let _ = storage.set_item("servers", &json);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async fn network_connect(
|
async fn network_connect(
|
||||||
address: String,
|
address: String,
|
||||||
username: String,
|
username: String,
|
||||||
|
|||||||
Reference in New Issue
Block a user