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}