leptos_use/
use_permission.rs1use leptos::prelude::*;
2use leptos::reactive::wrappers::read::Signal;
3use std::fmt::Display;
4
5pub fn use_permission(permission_name: &str) -> Signal<PermissionState> {
31 let (state, set_state) = signal(PermissionState::Unknown);
32
33 #[cfg(not(feature = "ssr"))]
34 {
35 use crate::use_event_listener;
36 use std::cell::RefCell;
37 use std::rc::Rc;
38
39 let permission_status = Rc::new(RefCell::new(None::<web_sys::PermissionStatus>));
40
41 let on_change = {
42 let permission_status = Rc::clone(&permission_status);
43
44 move || {
45 if let Some(permission_status) = permission_status.borrow().as_ref() {
46 set_state.set(PermissionState::from(permission_status.state()));
47 }
48 }
49 };
50
51 leptos::task::spawn_local({
52 let permission_name = permission_name.to_owned();
53
54 async move {
55 if let Ok(status) = query_permission(permission_name).await {
56 let _ = use_event_listener(status.clone(), leptos::ev::change, {
57 let on_change = on_change.clone();
58 move |_| on_change()
59 });
60 permission_status.replace(Some(status));
61 on_change();
62 } else {
63 set_state.set(PermissionState::Prompt);
64 }
65 }
66 });
67 }
68
69 #[cfg(feature = "ssr")]
70 {
71 let _ = set_state;
72 let _ = permission_name;
73 }
74
75 state.into()
76}
77
78#[derive(Copy, Clone, Default, Eq, PartialEq)]
80pub enum PermissionState {
81 #[default]
83 Unknown,
84
85 Granted,
87
88 Prompt,
90
91 Denied,
93}
94
95impl Display for PermissionState {
96 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
97 match *self {
98 PermissionState::Unknown => write!(f, "unknown"),
99 PermissionState::Granted => write!(f, "granted"),
100 PermissionState::Prompt => write!(f, "prompt"),
101 PermissionState::Denied => write!(f, "denied"),
102 }
103 }
104}
105
106impl From<web_sys::PermissionState> for PermissionState {
107 fn from(permission_state: web_sys::PermissionState) -> Self {
108 match permission_state {
109 web_sys::PermissionState::Granted => PermissionState::Granted,
110 web_sys::PermissionState::Prompt => PermissionState::Prompt,
111 web_sys::PermissionState::Denied => PermissionState::Denied,
112 _ => PermissionState::Unknown,
113 }
114 }
115}
116
117#[cfg(not(feature = "ssr"))]
118async fn query_permission(
119 permission: String,
120) -> Result<web_sys::PermissionStatus, wasm_bindgen::JsValue> {
121 use crate::{js, js_fut};
122 use wasm_bindgen::JsCast;
123
124 let permission_object = js_sys::Object::new();
125 js!(permission_object["name"] = permission);
126
127 let permission_state: web_sys::PermissionStatus = js_fut!(window()
128 .navigator()
129 .permissions()?
130 .query(&permission_object)?)
131 .await?
132 .unchecked_into();
133
134 Ok(permission_state)
135}