From 40a909c991a9e08f44faa8a7e38423b2332ccfd2 Mon Sep 17 00:00:00 2001 From: ghost Date: Tue, 30 Sep 2025 14:19:50 +0200 Subject: [PATCH] webrtc: add runtime config README example; provider/consumer docs; minor fixes --- Cargo.lock | 1 + Cargo.toml | 3 ++ README.md | 90 ++++++++++++++++++++++++++++++++++++++ src/config.rs | 63 +++++++++++++++++++++++++- src/lib.rs | 10 +++++ src/main.rs | 65 +++++++++++++++------------ src/utils/media_manager.rs | 19 +++----- tests/config_sync_tests.rs | 19 ++++++++ tests/config_tests.rs | 17 +++++++ 9 files changed, 246 insertions(+), 41 deletions(-) create mode 100644 src/lib.rs create mode 100644 tests/config_sync_tests.rs create mode 100644 tests/config_tests.rs diff --git a/Cargo.lock b/Cargo.lock index 3562cc6..e3eeb7e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2686,6 +2686,7 @@ dependencies = [ "log", "serde", "serde_json", + "tempfile", "tracing", "wasm-bindgen", "wasm-bindgen-futures", diff --git a/Cargo.toml b/Cargo.toml index 9634a70..1cc776f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -53,6 +53,9 @@ serde_json = "1.0.100" futures = "0.3.31" gloo-net = "0.6" +[dev-dependencies] +tempfile = "3.6" + [features] default = ["web"] web = ["dioxus/web"] diff --git a/README.md b/README.md index 1e629b6..129fad2 100644 --- a/README.md +++ b/README.md @@ -23,3 +23,93 @@ To run for a different platform, use the `--platform platform` flag. E.g. dx serve --platform desktop ``` +## Configuration (appsettings.json and WASM fast-path) + +This project supports an `appsettings.json`-style configuration that is loaded at runtime. + +- Native (desktop/server): the app tries to read `appsettings.json` from the working directory. +- WASM (web): the loader will first try a small HTML-injection fast-path (see below). If that + is not present it will fetch `appsettings.json` from the hosting origin. + +Example `appsettings.json`: + +```json +{ + "server": { + "stun_server": "stun:stun.l.google.com:19302" + } +} +``` + +HTML injection fast-path (for embedding a small config directly in `index.html`): + +```html + +``` + +This is useful for static hosting scenarios where you want to provide a different runtime +configuration without rebuilding the WASM artifact. + +## Consuming the Config in the UI (Dioxus) + +The Dioxus app provides a `Signal` via the hooks context. Child components can consume +it with: + +```rust +let cfg_signal = use_context::>(); +let cfg = cfg_signal.get(); // or cfg_signal.read()/() depending on the signal API +// use cfg.server.stun_server +``` + +The app uses an async loader (via `use_resource`) and overwrites the initial default config when +the runtime-loaded config becomes available. This gives instant sensible defaults while still +allowing runtime overrides. + +### Example: Provider + Consumer (Dioxus) + +Below is a minimal example showing how the app creates a `Signal` provider and how a +child component consumes it. This pattern gives children an immediately-available default +config while an async fetch can replace it at runtime. + +```rust +use dioxus::prelude::*; +use dioxus_hooks::use_resource; +use niom_webrtc::config; + +#[allow(non_snake_case)] +fn ConfigProvider(cx: Scope) -> Element { + // synchronous immediate default + let default_cfg = config::load_config_sync_or_default(); + + // a reactive signal holding the current config + let cfg_signal = use_state(cx, || default_cfg.clone()); + + // async resource that loads runtime config (WASM fetch or native file) + let resource = use_resource(cx, (), |_| async move { config::load_config_or_default().await }); + + // when resource completes, update the signal so children react + if let Some(cfg) = resource.value() { + cfg_signal.set(cfg.clone()); + } + + // provide the signal to descendants + use_context_provider(cx, || cfg_signal.clone()); + + cx.render(rsx! { children(&cx) }) +} + +fn SomeChild(cx: Scope) -> Element { + let cfg_signal = use_context::>(cx); + let cfg = cfg_signal.get(); + + cx.render(rsx!(div { "STUN: {cfg.server.stun_server}" })) +} +``` + +Notes: +- `load_config_sync_or_default()` returns a sensible default immediately (plus HTML fast-path on WASM). +- `load_config_or_default()` is async and will perform a network fetch on WASM if the HTML fast-path wasn't present. + + diff --git a/src/config.rs b/src/config.rs index ea9114f..7a3493b 100644 --- a/src/config.rs +++ b/src/config.rs @@ -26,13 +26,74 @@ impl Config { // WASM runtime loader: fetch `appsettings.json` from the hosting origin #[cfg(target_arch = "wasm32")] pub async fn load_config_from_server() -> Result> { - // lazy import gloo-net to avoid non-wasm compile errors + // First try HTML-injection fast-path: look for a