Skip to main content

brep_app/
lib.rs

1//! Shared eframe application for native windows and WebAssembly canvases.
2//! [`app::BrepApp`] hosts the renderer and egui in one wgpu frame.
3
4pub mod app;
5pub mod automation;
6mod color;
7pub mod column_tree;
8pub mod diagnostics;
9pub mod document;
10pub mod fonts;
11pub mod form;
12pub mod form_view;
13pub mod icon_text;
14pub mod icons;
15mod http;
16/// The native binary's `log` sink (`main.rs`): `RUST_LOG` to stderr. Replaces
17/// `env_logger`; the wasm build logs through the browser console instead.
18#[cfg(not(target_arch = "wasm32"))]
19pub mod logger;
20/// The embedded MCP server (`brep-app --mcp`); native builds with `mcp`.
21#[cfg(all(not(target_arch = "wasm32"), feature = "mcp"))]
22pub mod mcp;
23pub mod palette;
24pub mod panels;
25pub mod recovery;
26pub mod store;
27pub mod viewport;
28pub mod workbench;
29
30// BREP private tests: ce00ab869d6779c8
31
32// The wasm history runner: a dedicated web worker so a history run stays OFF the
33// browser main thread (single-threaded wasm) and the UI never freezes during a run.
34// Its `worker_entry` is the worker-side onmessage loop. wasm only.
35#[cfg(target_arch = "wasm32")]
36pub mod worker;
37
38// --- wasm entry ----------------------------------------------------------------
39#[cfg(target_arch = "wasm32")]
40mod web {
41    use wasm_bindgen::prelude::*;
42    use wasm_bindgen::JsCast;
43
44    /// Start the eframe app on the given `<canvas>` element id. Called from JS.
45    #[wasm_bindgen]
46    pub async fn start(canvas_id: String) -> Result<(), JsValue> {
47        brep_render::brep_kernel::panic_hook::set_once();
48
49        // Bring up browser persistence FIRST. `ModelStore` is synchronous but every
50        // browser store large enough for a native BREP payload is async, so the
51        // whole key space is pulled into an in-memory mirror here — inside the one
52        // async seam the app has — BEFORE `BrepApp::new` performs its first read.
53        // See store.rs `mirror_store`.
54        crate::store::hydrate_web_store().await;
55
56        let document = web_sys::window()
57            .ok_or_else(|| JsValue::from_str("no window"))?
58            .document()
59            .ok_or_else(|| JsValue::from_str("no document"))?;
60        let canvas = document
61            .get_element_by_id(&canvas_id)
62            .ok_or_else(|| JsValue::from_str("canvas element not found"))?
63            .dyn_into::<web_sys::HtmlCanvasElement>()
64            .map_err(|_| JsValue::from_str("element is not a <canvas>"))?;
65
66        eframe::WebRunner::new()
67            .start(
68                canvas,
69                eframe::WebOptions::default(),
70                Box::new(|cc| {
71                    crate::fonts::install(&cc.egui_ctx);
72                    crate::app::BrepApp::new(cc)
73                        .map(|app| Box::new(app) as Box<dyn eframe::App>)
74                        .map_err(|e| e.into())
75                }),
76            )
77            .await
78    }
79}