2 Commits

Author SHA1 Message Date
samuel127849 51f05593ac Refactor ProxyOverides to be optional
Build Mumble Web 2 / linux_build (push) Successful in 1m37s
Build Mumble Web 2 / windows_build (push) Successful in 2m26s
2026-01-10 17:29:49 -07:00
samuel127849 eab8f1d6a7 Rename client config
Build Mumble Web 2 / linux_build (push) Successful in 1m28s
Build Mumble Web 2 / windows_build (push) Successful in 2m36s
2026-01-10 17:11:50 -07:00
6 changed files with 47 additions and 46 deletions
+3 -4
View File
@@ -1,10 +1,9 @@
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Deserialize, Serialize, Default)] #[derive(Debug, Clone, Deserialize, Serialize, Default)]
pub struct ClientConfig { pub struct ProxyOverides {
pub proxy_url: Option<String>, pub proxy_url: String,
pub cert_hash: Option<Vec<u8>>, pub cert_hash: Vec<u8>,
pub any_server: bool,
} }
#[derive(Debug, Clone, Deserialize, Serialize, Default)] #[derive(Debug, Clone, Deserialize, Serialize, Default)]
+18 -12
View File
@@ -2,7 +2,7 @@
use dioxus::prelude::*; use dioxus::prelude::*;
use mime_guess::Mime; use mime_guess::Mime;
use mumble_web2_common::{ClientConfig, ServerStatus}; use mumble_web2_common::{ProxyOverides, ServerStatus};
use ordermap::OrderSet; use ordermap::OrderSet;
use std::collections::HashMap; use std::collections::HashMap;
@@ -23,7 +23,7 @@ pub enum Command {
Connect { Connect {
address: String, address: String,
username: String, username: String,
config: ClientConfig, config: ProxyOverides,
}, },
SendChat { SendChat {
markdown: String, markdown: String,
@@ -309,7 +309,7 @@ pub fn ChatView() -> Element {
} }
#[component] #[component]
pub fn ControlView(config: Resource<ClientConfig>) -> Element { pub fn ControlView(config: Resource<Option<ProxyOverides>>) -> Element {
let net: Coroutine<Command> = use_coroutine_handle(); let net: Coroutine<Command> = use_coroutine_handle();
let status = &STATE.status; let status = &STATE.status;
let server = STATE.server.read(); let server = STATE.server.read();
@@ -331,7 +331,8 @@ pub fn ControlView(config: Resource<ClientConfig>) -> Element {
let proxy_url = config let proxy_url = config
.read_unchecked() .read_unchecked()
.as_ref() .as_ref()
.and_then(|gui_config| gui_config.proxy_url.clone()); .and_then(|opt| opt.as_ref())
.map(|gui_config| gui_config.proxy_url.clone());
let connecting_color = "yellow"; let connecting_color = "yellow";
let connected_color = "oklch(0.55 0.1184 141.35)"; let connected_color = "oklch(0.55 0.1184 141.35)";
@@ -508,7 +509,7 @@ pub fn ControlView(config: Resource<ClientConfig>) -> Element {
} }
#[component] #[component]
pub fn ServerView(config: Resource<ClientConfig>) -> Element { pub fn ServerView(config: Resource<Option<ProxyOverides>>) -> Element {
let net: Coroutine<Command> = use_coroutine_handle(); let net: Coroutine<Command> = use_coroutine_handle();
let server = STATE.server.read(); let server = STATE.server.read();
let Some(&UserState { let Some(&UserState {
@@ -546,7 +547,7 @@ pub fn ServerView(config: Resource<ClientConfig>) -> Element {
} }
#[component] #[component]
pub fn LoginView(config: Resource<ClientConfig>) -> Element { pub fn LoginView(config: Resource<Option<ProxyOverides>>) -> Element {
let net: Coroutine<Command> = use_coroutine_handle(); let net: Coroutine<Command> = use_coroutine_handle();
let last_status = use_signal(|| None::<color_eyre::Result<ServerStatus>>); let last_status = use_signal(|| None::<color_eyre::Result<ServerStatus>>);
@@ -564,7 +565,8 @@ pub fn LoginView(config: Resource<ClientConfig>) -> Element {
addr.clone() addr.clone()
} else { } else {
config() config()
.and_then(|c| c.proxy_url.clone()) .flatten()
.map(|c| c.proxy_url.clone())
.unwrap_or_default() .unwrap_or_default()
} }
}); });
@@ -575,13 +577,13 @@ pub fn LoginView(config: Resource<ClientConfig>) -> Element {
let do_connect = move |_| { let do_connect = move |_| {
//let _ = set_default_username(&username.read()); //let _ = set_default_username(&username.read());
let _ = imp::set_default_username(&username.read()); let _ = imp::set_default_username(&username.read());
if config.read().as_ref().is_some_and(|cfg| cfg.any_server) { if config.read().as_ref().is_some_and(|opt| opt.is_none()) {
imp::set_default_server(&address.read()); imp::set_default_server(&address.read());
} }
net.send(Connect { net.send(Connect {
address: address.read().clone(), address: address.read().clone(),
username: username.read().clone(), username: username.read().clone(),
config: config.read().clone().unwrap_or_default(), config: config.read().clone().flatten().unwrap_or_default(),
}) })
}; };
let status = &STATE.status; let status = &STATE.status;
@@ -626,7 +628,7 @@ pub fn LoginView(config: Resource<ClientConfig>) -> Element {
None => rsx!(), None => rsx!(),
} }
} }
if config.read().as_ref().is_some_and(|cfg| cfg.any_server) { if config.read().as_ref().is_some_and(|opt| opt.is_none()) {
div { div {
label { label {
for: "address-entry", for: "address-entry",
@@ -723,9 +725,9 @@ pub fn app() -> Element {
use_coroutine(|rx: UnboundedReceiver<Command>| super::network_entrypoint(rx)); use_coroutine(|rx: UnboundedReceiver<Command>| super::network_entrypoint(rx));
let config = use_resource(|| async move { let config = use_resource(|| async move {
match imp::load_config().await { match imp::load_proxy_overides().await {
Ok(config) => config, Ok(config) => config,
Err(_) => ClientConfig::default(), Err(_) => None,
} }
}); });
@@ -734,9 +736,13 @@ pub fn app() -> Element {
document::Link{ rel: "stylesheet", href: "https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200" } document::Link{ rel: "stylesheet", href: "https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200" }
document::Link{ rel: "stylesheet", href: STYLE } document::Link{ rel: "stylesheet", href: STYLE }
if config.read().is_none() {
div { class: "loading", "Loading..." }
} else {
match *STATE.status.read() { match *STATE.status.read() {
Connected => rsx!(ServerView { config }), Connected => rsx!(ServerView { config }),
_ => rsx!(LoginView { config }), _ => rsx!(LoginView { config }),
} }
}
) )
} }
+4 -8
View File
@@ -6,7 +6,7 @@ use dioxus::hooks::UnboundedReceiver;
use etcetera::{choose_app_strategy, AppStrategy, AppStrategyArgs}; use etcetera::{choose_app_strategy, AppStrategy, AppStrategyArgs};
use futures::io::{AsyncRead, AsyncWrite}; use futures::io::{AsyncRead, AsyncWrite};
use mumble_protocol::control::ClientControlCodec; use mumble_protocol::control::ClientControlCodec;
use mumble_web2_common::{ClientConfig, ServerStatus}; use mumble_web2_common::{ProxyOverides, ServerStatus};
use std::collections::HashMap; use std::collections::HashMap;
use std::mem::replace; use std::mem::replace;
use std::net::ToSocketAddrs; use std::net::ToSocketAddrs;
@@ -284,7 +284,7 @@ pub async fn network_connect(
address: String, address: String,
username: String, username: String,
event_rx: &mut UnboundedReceiver<Command>, event_rx: &mut UnboundedReceiver<Command>,
gui_config: &ClientConfig, gui_config: &ProxyOverides,
) -> Result<(), Error> { ) -> Result<(), Error> {
info!("connecting"); info!("connecting");
@@ -366,12 +366,8 @@ pub fn load_server_url() -> Option<String> {
config.get("server").cloned() config.get("server").cloned()
} }
pub async fn load_config() -> color_eyre::Result<ClientConfig> { pub async fn load_proxy_overides() -> color_eyre::Result<Option<ProxyOverides>> {
Ok(ClientConfig { Ok(None)
proxy_url: None,
cert_hash: None,
any_server: true,
})
} }
pub async fn get_status(client: &reqwest::Client) -> color_eyre::Result<ServerStatus> { pub async fn get_status(client: &reqwest::Client) -> color_eyre::Result<ServerStatus> {
+7 -7
View File
@@ -6,7 +6,7 @@ use futures::{AsyncRead, AsyncWrite};
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::{ProxyOverides, ServerStatus};
use reqwest::Url; use reqwest::Url;
use std::future::Future; use std::future::Future;
use std::time::Duration; use std::time::Duration;
@@ -329,7 +329,7 @@ pub async fn network_connect(
address: String, address: String,
username: String, username: String,
event_rx: &mut UnboundedReceiver<Command>, event_rx: &mut UnboundedReceiver<Command>,
gui_config: &ClientConfig, gui_config: &ProxyOverides,
) -> Result<(), Error> { ) -> Result<(), Error> {
info!("connecting"); info!("connecting");
@@ -342,8 +342,8 @@ pub async fn network_connect(
) )
.ey()?; .ey()?;
if let Some(server_hash) = &gui_config.cert_hash { if !gui_config.cert_hash.is_empty() {
let hash = web_sys::js_sys::Uint8Array::from(server_hash.as_slice()); let hash = web_sys::js_sys::Uint8Array::from(gui_config.cert_hash.as_slice());
web_sys::js_sys::Reflect::set(&object, &"value".into(), &hash).ey()?; web_sys::js_sys::Reflect::set(&object, &"value".into(), &hash).ey()?;
} }
@@ -422,7 +422,7 @@ pub fn absolute_url(path: &str) -> Result<Url, Error> {
Ok(Url::parse(&location.href().ey()?)?.join(path)?) Ok(Url::parse(&location.href().ey()?)?.join(path)?)
} }
pub async fn load_config() -> color_eyre::Result<ClientConfig> { pub async fn load_proxy_overides() -> color_eyre::Result<Option<ProxyOverides>> {
let config_url = match option_env!("MUMBLE_WEB2_GUI_CONFIG_URL") { let config_url = match option_env!("MUMBLE_WEB2_GUI_CONFIG_URL") {
Some(url) => Url::parse(url)?, Some(url) => Url::parse(url)?,
None => absolute_url("config")?, None => absolute_url("config")?,
@@ -431,10 +431,10 @@ pub async fn load_config() -> color_eyre::Result<ClientConfig> {
let config = reqwest::get(config_url) let config = reqwest::get(config_url)
.await? .await?
.json::<ClientConfig>() .json::<ProxyOverides>()
.await?; .await?;
Ok(config) Ok(Some(config))
} }
pub async fn get_status(client: &reqwest::Client) -> color_eyre::Result<ServerStatus> { pub async fn get_status(client: &reqwest::Client) -> color_eyre::Result<ServerStatus> {
+1 -1
View File
@@ -20,7 +20,7 @@ use mumble_protocol::voice::VoicePacket;
use mumble_protocol::voice::VoicePacketPayload; use mumble_protocol::voice::VoicePacketPayload;
use mumble_protocol::Clientbound; use mumble_protocol::Clientbound;
use mumble_protocol::Serverbound; use mumble_protocol::Serverbound;
use mumble_web2_common::ClientConfig; use mumble_web2_common::ProxyOverides;
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
use std::collections::hash_map::Entry; use std::collections::hash_map::Entry;
use std::collections::HashMap; use std::collections::HashMap;
+11 -11
View File
@@ -1,5 +1,5 @@
use color_eyre::eyre::{anyhow, bail, Context, Result}; use color_eyre::eyre::{anyhow, bail, Context, Result};
use mumble_web2_common::{ClientConfig, ServerStatus}; use mumble_web2_common::{ProxyOverides, ServerStatus};
use rand::Rng; use rand::Rng;
use salvo::conn::rustls::{Keycert, RustlsConfig}; use salvo::conn::rustls::{Keycert, RustlsConfig};
use salvo::cors::{AllowOrigin, Cors}; use salvo::cors::{AllowOrigin, Cors};
@@ -77,13 +77,13 @@ async fn main() -> Result<()> {
.install_default() .install_default()
.map_err(|e| anyhow!("could not install crypto provider {e:?}"))?; .map_err(|e| anyhow!("could not install crypto provider {e:?}"))?;
let mut client_config = ClientConfig { let mut client_config = ProxyOverides {
proxy_url: match &server_config.proxy_url { proxy_url: server_config
Some(url) => Some(url.to_string()), .proxy_url
None => None, .as_ref()
}, .map(|url| url.to_string())
cert_hash: None, .unwrap_or_default(),
any_server: false, cert_hash: Vec::new(),
}; };
let (cert, key) = match (&server_config.cert_path, &server_config.key_path) { let (cert, key) = match (&server_config.cert_path, &server_config.key_path) {
@@ -102,7 +102,7 @@ async fn main() -> Result<()> {
let cert = cert_params.self_signed(&key_pair)?; let cert = cert_params.self_signed(&key_pair)?;
let hash = hmac_sha256::Hash::hash(cert.der().as_ref()); let hash = hmac_sha256::Hash::hash(cert.der().as_ref());
client_config.cert_hash = Some(hash.into()); client_config.cert_hash = hash.into();
(cert.pem().into(), key_pair.serialize_pem().into()) (cert.pem().into(), key_pair.serialize_pem().into())
} }
@@ -252,13 +252,13 @@ impl StatusCraft {
#[derive(Clone)] #[derive(Clone)]
pub struct ConfigCraft { pub struct ConfigCraft {
server_config: Arc<Config>, server_config: Arc<Config>,
client_config: ClientConfig, client_config: ProxyOverides,
} }
#[craft] #[craft]
impl ConfigCraft { impl ConfigCraft {
#[craft(handler)] #[craft(handler)]
async fn get_config(&self) -> Json<ClientConfig> { async fn get_config(&self) -> Json<ProxyOverides> {
Json(self.client_config.clone()) Json(self.client_config.clone())
} }