Skip to main content

brep_app/
lib.rs

1//! brep-app — engine-native UI spike (an eframe host for the brep-render engine).
2//!
3//! The same [`app::BrepApp`] runs on native (`main.rs` → `run_native`) and on
4//! the web (`start` below → `eframe::WebRunner`), sharing one wgpu frame with
5//! egui. Additive spike: it does NOT touch the previous app or the render wasm build.
6
7pub mod app;
8pub mod column_tree;
9pub mod document;
10pub mod fonts;
11pub mod form;
12pub mod form_view;
13pub mod icon_text;
14pub mod icons;
15pub mod palette;
16pub mod panels;
17pub mod recovery;
18pub mod store;
19pub mod viewport;
20pub mod workbench;
21
22// The wasm history runner: a dedicated web worker so a history run stays OFF the
23// browser main thread (single-threaded wasm) and the UI never freezes during a run.
24// Its `worker_entry` is the worker-side onmessage loop. wasm only.
25#[cfg(target_arch = "wasm32")]
26pub mod worker;
27
28// --- wasm entry ----------------------------------------------------------------
29#[cfg(target_arch = "wasm32")]
30mod web {
31    use wasm_bindgen::prelude::*;
32    use wasm_bindgen::JsCast;
33
34    /// Start the eframe app on the given `<canvas>` element id. Called from JS.
35    #[wasm_bindgen]
36    pub async fn start(canvas_id: String) -> Result<(), JsValue> {
37        console_error_panic_hook::set_once();
38
39        // Bring up browser persistence FIRST. `ModelStore` is synchronous but every
40        // browser store large enough for a native BREP payload is async, so the
41        // whole key space is pulled into an in-memory mirror here — inside the one
42        // async seam the app has — BEFORE `BrepApp::new` performs its first read.
43        // See store.rs `mirror_store`.
44        crate::store::hydrate_web_store().await;
45
46        let document = web_sys::window()
47            .ok_or_else(|| JsValue::from_str("no window"))?
48            .document()
49            .ok_or_else(|| JsValue::from_str("no document"))?;
50        let canvas = document
51            .get_element_by_id(&canvas_id)
52            .ok_or_else(|| JsValue::from_str("canvas element not found"))?
53            .dyn_into::<web_sys::HtmlCanvasElement>()
54            .map_err(|_| JsValue::from_str("element is not a <canvas>"))?;
55
56        eframe::WebRunner::new()
57            .start(
58                canvas,
59                eframe::WebOptions::default(),
60                Box::new(|cc| {
61                    crate::fonts::install(&cc.egui_ctx);
62                    crate::app::BrepApp::new(cc)
63                        .map(|app| Box::new(app) as Box<dyn eframe::App>)
64                        .map_err(|e| e.into())
65                }),
66            )
67            .await
68    }
69}