diff --git a/.idea/leptos-use.iml b/.idea/leptos-use.iml index 830c9eb..224ebd7 100644 --- a/.idea/leptos-use.iml +++ b/.idea/leptos-use.iml @@ -12,6 +12,7 @@ + @@ -67,7 +68,9 @@ + + @@ -90,4 +93,4 @@ - \ No newline at end of file + diff --git a/Cargo.toml b/Cargo.toml index 4c31f33..a4bcbda 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,6 +18,7 @@ cfg-if = "1" default-struct-builder = "0.5" futures-util = "0.3" gloo-timers = { version = "0.3.0", features = ["futures"] } +gloo-utils = { version = "0.2.0"} js-sys = "0.3" lazy_static = "1" leptos = "0.5" @@ -40,6 +41,7 @@ features = [ "CssStyleDeclaration", "CustomEvent", "CustomEventInit", + "DisplayMediaStreamConstraints", "DomRect", "DomRectReadOnly", "DataTransfer", @@ -57,7 +59,9 @@ features = [ "IntersectionObserver", "IntersectionObserverInit", "IntersectionObserverEntry", + "MediaDevices", "MediaQueryList", + "MediaStream", "MouseEvent", "MutationObserver", "MutationObserverInit", diff --git a/docs/book/src/browser/use_display_media.md b/docs/book/src/browser/use_display_media.md new file mode 100644 index 0000000..5d4219f --- /dev/null +++ b/docs/book/src/browser/use_display_media.md @@ -0,0 +1,3 @@ +# use_display_media + + diff --git a/examples/Cargo.toml b/examples/Cargo.toml index e61f920..d9f03b9 100644 --- a/examples/Cargo.toml +++ b/examples/Cargo.toml @@ -13,6 +13,7 @@ members = [ "use_css_var", "use_cycle_list", "use_debounce_fn", + "use_display_media", "use_document_visibility", "use_draggable", "use_drop_zone", diff --git a/examples/use_display_media/Cargo.toml b/examples/use_display_media/Cargo.toml new file mode 100644 index 0000000..32014f2 --- /dev/null +++ b/examples/use_display_media/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "use_display_media" +version = "0.1.0" +edition = "2021" + +[dependencies] +leptos = { version = "0.5", features = ["nightly", "csr"] } +console_error_panic_hook = "0.1" +console_log = "1" +log = "0.4" +leptos-use = { path = "../..", features = ["docs"] } +web-sys = "0.3" + +[dev-dependencies] +wasm-bindgen = "0.2" +wasm-bindgen-test = "0.3.0" diff --git a/examples/use_display_media/Trunk.toml b/examples/use_display_media/Trunk.toml new file mode 100644 index 0000000..3e4be08 --- /dev/null +++ b/examples/use_display_media/Trunk.toml @@ -0,0 +1,2 @@ +[build] +public_url = "/demo/" \ No newline at end of file diff --git a/examples/use_display_media/index.html b/examples/use_display_media/index.html new file mode 100644 index 0000000..25f83eb --- /dev/null +++ b/examples/use_display_media/index.html @@ -0,0 +1,5 @@ + + + + + diff --git a/examples/use_display_media/rust-toolchain.toml b/examples/use_display_media/rust-toolchain.toml new file mode 100644 index 0000000..271800c --- /dev/null +++ b/examples/use_display_media/rust-toolchain.toml @@ -0,0 +1,2 @@ +[toolchain] +channel = "nightly" \ No newline at end of file diff --git a/examples/use_display_media/src/main.rs b/examples/use_display_media/src/main.rs new file mode 100644 index 0000000..01cb48e --- /dev/null +++ b/examples/use_display_media/src/main.rs @@ -0,0 +1,30 @@ +use leptos::*; +use leptos_use::docs::{demo_or_body, Note}; +use leptos_use::use_display_media; + +#[component] +fn Demo() -> impl IntoView { + let stream = use_display_media(None); + let video_ref = create_node_ref::(); + + create_effect(move |_| match stream.get() { + Some(Ok(s)) => { + video_ref.get().expect("video element ref not created").set_src_object(Some(&s)); + video_ref.get().map(|v| v.play()); + } + Some(Err(e)) => log::error!("Failed to get media stream: {:?}", e), + None => log::debug!("No stream yet"), + }); + + view! { } +} + +fn main() { + _ = console_log::init_with_level(log::Level::Debug); + console_error_panic_hook::set_once(); + + mount_to(demo_or_body(), || { + view! { } + }) +} + diff --git a/src/lib.rs b/src/lib.rs index caf6dd5..d42079d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -22,6 +22,7 @@ mod use_color_mode; mod use_css_var; mod use_cycle_list; mod use_debounce_fn; +mod use_display_media; mod use_document; mod use_document_visibility; mod use_draggable; @@ -76,6 +77,7 @@ pub use use_color_mode::*; pub use use_css_var::*; pub use use_cycle_list::*; pub use use_debounce_fn::*; +pub use use_display_media::*; pub use use_document::*; pub use use_document_visibility::*; pub use use_draggable::*; diff --git a/src/use_display_media.rs b/src/use_display_media.rs new file mode 100644 index 0000000..c68dfc6 --- /dev/null +++ b/src/use_display_media.rs @@ -0,0 +1,29 @@ +use leptos::*; +use wasm_bindgen::{JsValue, JsCast}; +use web_sys::{DisplayMediaStreamConstraints, MediaStream}; +use crate::use_window::use_window; + +async fn create_media(opts: Option) -> Result { + let media = use_window() + .navigator() + .ok_or_else(|| JsValue::from_str("Failed to access window.navigator")) + .and_then(|n| n.media_devices())?; + + let promise = match opts { + Some(o) => media.get_display_media_with_constraints(&o), + None => media.get_display_media(), + }?; + let res = wasm_bindgen_futures::JsFuture::from(promise).await?; + Ok::<_, JsValue>(MediaStream::unchecked_from_js(res)) +} + +type UseDisplayReturn = Resource, Result>; + +pub fn use_display_media(options: S) -> UseDisplayReturn +where + S: Into>>, +{ + let opts: MaybeSignal> = options.into(); + create_local_resource(move || opts.with(|o| o.as_ref().cloned()), create_media) +} +