yew_hooks/hooks/
use_permission.rs

1use gloo::utils::window;
2use js_sys::{Object, Reflect};
3use wasm_bindgen::{prelude::*, JsCast};
4use wasm_bindgen_futures::{spawn_local, JsFuture};
5use web_sys::{PermissionState, PermissionStatus};
6use yew::prelude::*;
7
8use crate::use_effect_once;
9
10/// A sensor hook that tracks browser's permission changes
11///
12/// # Example
13///
14/// ```rust
15/// # use yew::prelude::*;
16/// #
17/// use yew_hooks::prelude::*;
18///
19/// #[function_component(UsePermission)]
20/// fn permission() -> Html {
21///     let state = use_permission("notifications".to_owned());
22///
23///     html! {
24///         <>
25///             <b>{ " state: " }</b>
26///             { format!("{state:?}") }
27///         </>
28///     }
29/// }
30/// ```
31#[hook]
32pub fn use_permission(name: String) -> UseStateHandle<Option<PermissionState>> {
33    let state = use_state(Option::<PermissionState>::default);
34
35    {
36        let state = state.clone();
37
38        use_effect_once(move || {
39            let state = state.clone();
40
41            spawn_local(async move {
42                let permissions = window().navigator().permissions().unwrap_throw();
43
44                let obj = Object::new();
45                Reflect::set(&obj, &"name".into(), &name.into()).unwrap_throw();
46
47                let fut = JsFuture::from(permissions.query(&obj).unwrap_throw());
48                let stat = PermissionStatus::from(fut.await.unwrap_throw());
49
50                let onchange = {
51                    let state = state.clone();
52
53                    Closure::wrap(Box::new(move |event: Event| {
54                        if let Some(target) = event.target() {
55                            let stat: PermissionStatus = target.dyn_into().unwrap_throw();
56
57                            state.set(Some(stat.state()));
58                        }
59                    }) as Box<dyn FnMut(Event)>)
60                };
61
62                stat.set_onchange(Some(onchange.as_ref().unchecked_ref()));
63                onchange.forget();
64
65                state.set(Some(stat.state()));
66            });
67
68            move || {}
69        });
70    }
71
72    state
73}