#![allow(non_snake_case)] use console_log::init_with_level; use dioxus::prelude::*; use log::Level; use niom_webrtc::components::VoiceChannelLayout; use niom_webrtc::models::Participant; use niom_webrtc::services::signaling::SignalingProvider; // config functions used via fully-qualified paths below const FAVICON: Asset = asset!("/assets/favicon.ico"); const MAIN_CSS: Asset = asset!("/assets/main.css"); fn main() { init_with_level(Level::Info).expect("console_log initialization failed"); console_error_panic_hook::set_once(); dioxus::launch(App); } #[component] fn App() -> Element { rsx! { document::Link { rel: "icon", href: FAVICON } document::Link { rel: "stylesheet", href: MAIN_CSS } ConfigProvider {} } } #[component] fn ConfigProvider() -> Element { // Start with a synchronous default so the UI has a sensible config immediately. let default_cfg = niom_webrtc::config::load_config_sync_or_default(); // A signal holding the active config; children will consume a Signal via use_context. let mut cfg_signal = use_signal(|| default_cfg.clone()); // Spawn an async resource to load the config at runtime (WASM fetch / native file). When it // finishes, overwrite the signal so the rest of the app sees the updated config. let resource = use_resource(|| async move { // load_config_or_default is async and returns a Config niom_webrtc::config::load_config_or_default().await }); // When the resource value becomes available, update the cfg_signal. This effect will run // reactively whenever the resource's value changes. // If the async resource has produced a value, apply it to the signal immediately so // downstream consumers see the updated configuration. if let Some(cfg) = resource.value().read_unchecked().as_ref() { cfg_signal.set(cfg.clone()); } // Provide the Signal to downstream components. use_context_provider(|| cfg_signal.clone()); rsx! { Content {} } } #[component] pub fn Content() -> Element { // Config is provided by ConfigProvider via provide_context; components can use use_context to read it. let participants = use_signal(|| { vec![ Participant::new("self", "Ghost", "#5865F2", true, false, true), Participant::new("mod-1", "Nia Moderator", "#43B581", false, false, true), Participant::new("listener-1", "Amber", "#FAA61A", false, true, false), Participant::new("listener-2", "Basil", "#EB459E", false, false, false), Participant::new("listener-3", "Colt", "#5865F2", false, true, false), Participant::new("listener-4", "Delta", "#99AAB5", false, false, false), ] }); rsx! { SignalingProvider { VoiceChannelLayout { channel_name: "Project Alpha / Voice Lounge".to_string(), channel_topic: "Team sync & architecture deep dive".to_string(), participants, } } } }