Skip to main content

dioxus_cameras/
component.rs

1use dioxus::prelude::*;
2
3use crate::PREVIEW_JS;
4
5/// The preview server's port, injected into the Dioxus context by
6/// [`PreviewServer::register_with`](crate::PreviewServer::register_with).
7///
8/// Crate-private because `register_with` is the only intended entry point:
9/// users should not have to know the context type name.
10#[derive(Clone, Copy)]
11pub(crate) struct PreviewPort(pub(crate) u16);
12
13/// A `<canvas>` bound to the preview server for `id`.
14///
15/// Reads the preview port from context (see
16/// [`PreviewServer::register_with`](crate::PreviewServer::register_with)),
17/// emits the `data-stream-id` and `data-preview-url` attributes that
18/// [`PREVIEW_JS`](crate::PREVIEW_JS) scans for, and applies the
19/// `cameras-preview-canvas` class so that user CSS can target it.
20///
21/// Wrap it in your own sized container, the JS renderer resizes to the
22/// parent's bounding rect.
23///
24/// # Panics
25///
26/// Panics at render time if called outside an app that has been wired up with
27/// [`PreviewServer::register_with`](crate::PreviewServer::register_with).
28#[component]
29pub fn StreamPreview(id: u32) -> Element {
30    let port = try_consume_context::<PreviewPort>()
31        .expect(
32            "`StreamPreview` requires `PreviewServer::register_with` to be called at launch, \
33             see the dioxus-cameras crate docs",
34        )
35        .0;
36    let url = format!("http://127.0.0.1:{port}/preview/{id}.bin");
37    rsx! {
38        canvas {
39            id: "cameras-preview-{id}",
40            class: "cameras-preview-canvas",
41            "data-stream-id": "{id}",
42            "data-preview-url": "{url}",
43        }
44    }
45}
46
47/// Injects the WebGL2 preview renderer script once into the page.
48///
49/// Render this exactly once, typically as the last child of your root
50/// component. Every [`StreamPreview`] in the DOM is discovered and driven by
51/// this script; without it the preview canvases stay blank.
52///
53/// Equivalent to:
54///
55/// ```ignore
56/// rsx! { script { dangerous_inner_html: "{PREVIEW_JS}" } }
57/// ```
58#[component]
59pub fn PreviewScript() -> Element {
60    rsx! { script { dangerous_inner_html: "{PREVIEW_JS}" } }
61}