Parent: #108
Problem
crates/web/src/ has ~46 .unwrap() calls on browser APIs. Any browser failure (sandboxed iframe, denied permissions, blocked AudioContext, broken FileReader) panics the entire WASM module.
Hotspots:
crates/web/src/voice.rs:149, 155, 366, 505, 524 — VoiceManager critical paths
crates/web/src/components/file_share.rs:47, 56, 60-61 — file upload / FileReader / ArrayBuffer
crates/web/src/components/member_list.rs:24-25 — context access
crates/web/src/components/sidebar.rs:46-47 — context access
Fix
-
Create a small web_helpers module (or util.rs) with Result-returning getters for the common browser APIs:
pub fn window() -> Result<web_sys::Window, WebError> {
web_sys::window().ok_or(WebError::NoWindow)
}
pub fn document() -> Result<web_sys::Document, WebError> {
window()?.document().ok_or(WebError::NoDocument)
}
pub fn media_devices() -> Result<web_sys::MediaDevices, WebError> {
window()?
.navigator()
.media_devices()
.map_err(|_| WebError::NoMediaDevices)
}
-
Replace each .unwrap() on those APIs with ? propagation.
-
For file upload errors, surface a user-visible toast notification instead of panicking.
-
For context access (member_list.rs, sidebar.rs), the context should always be provided by the parent App — if it's missing, that's a bug, but it should at least render an error state rather than crashing the whole app.
Scope control
This is a medium-size refactor. Scope it to the voice and file_share modules in the first PR (the highest-impact sites). Component context access can be a follow-up.
Test
Browser tests in crates/web/tests/browser.rs:
- Mount
CallPage in a context where getUserMedia fails (mock or simulate rejection). Assert the app does not panic and shows an error state.
- Mount
FileShare with an oversized/corrupt file. Assert the app does not panic and shows an error toast.
Parent: #108
Problem
crates/web/src/has ~46.unwrap()calls on browser APIs. Any browser failure (sandboxed iframe, denied permissions, blocked AudioContext, broken FileReader) panics the entire WASM module.Hotspots:
crates/web/src/voice.rs:149, 155, 366, 505, 524— VoiceManager critical pathscrates/web/src/components/file_share.rs:47, 56, 60-61— file upload / FileReader / ArrayBuffercrates/web/src/components/member_list.rs:24-25— context accesscrates/web/src/components/sidebar.rs:46-47— context accessFix
Create a small
web_helpersmodule (orutil.rs) withResult-returning getters for the common browser APIs:Replace each
.unwrap()on those APIs with?propagation.For file upload errors, surface a user-visible toast notification instead of panicking.
For context access (
member_list.rs,sidebar.rs), the context should always be provided by the parentApp— if it's missing, that's a bug, but it should at least render an error state rather than crashing the whole app.Scope control
This is a medium-size refactor. Scope it to the voice and file_share modules in the first PR (the highest-impact sites). Component context access can be a follow-up.
Test
Browser tests in
crates/web/tests/browser.rs:CallPagein a context wheregetUserMediafails (mock or simulate rejection). Assert the app does not panic and shows an error state.FileSharewith an oversized/corrupt file. Assert the app does not panic and shows an error toast.