wasm_toolkit/window_ops/
match_media.rs1use std::{cell::RefCell, rc::Rc};
2
3use async_channel::{Receiver, bounded};
4use wasm_bindgen::{JsCast, prelude::Closure};
5use web_sys::{Event, MediaQueryList};
6
7use crate::{WasmToolkitCommon, WasmToolkitError, WasmToolkitResult, WasmWindow};
8
9impl WasmWindow {
10 pub fn match_media(&self, query: &str) -> WasmToolkitResult<MediaQueryList> {
11 self.inner()
12 .match_media(query)
13 .map_err(|error| {
14 let outcome = WasmToolkitCommon::exception_or_stringify(&error);
15
16 WasmToolkitError::Op(outcome)
17 })?
18 .ok_or(WasmToolkitError::MatchMediaQueryUnsupported)
19 }
20
21 pub fn query_dark_mode(&self) -> WasmToolkitResult<MediaQueryList> {
22 self.match_media("(prefers-color-scheme: dark)")
23 }
24
25 pub fn is_dark_mode(&self) -> WasmToolkitResult<bool> {
26 Ok(self.query_dark_mode()?.matches())
27 }
28
29 pub async fn watch_dark_mode(&self) -> WasmToolkitResult<Receiver<bool>> {
30 let (sender, receiver) = bounded::<bool>(1);
31
32 let query = Rc::new(RefCell::new(self.query_dark_mode()?));
33 let query_spawned = query.clone();
34
35 let callback = Closure::wrap(Box::new(move |_value: Event| {
36 let sender = sender.clone();
37 let query_spawned = query_spawned.clone();
38
39 wasm_bindgen_futures::spawn_local(async move {
40 let is_dark_mode = query_spawned.borrow().matches();
41
42 if let Err(error) = sender.send(is_dark_mode).await {
43 web_sys::console::error_2(
44 &"Dark mode listener error: ".into(),
45 &error.to_string().into(),
46 );
47 }
48 });
49 }) as Box<dyn Fn(_)>);
50
51 if let Ok(callback_fn) = callback.as_ref().clone().dyn_into::<js_sys::Function>() {
52 wasm_bindgen_futures::spawn_local(async move {
53 query.borrow_mut().set_onchange(Some(&callback_fn));
54 });
55 callback.forget();
56
57 Ok(receiver)
58 } else {
59 web_sys::console::error_1(
60 &"Unable to set `onchange` event lister for event checking when a user switches from dark mode to light mode and vise-versa!".into(),
61 );
62
63 Err(WasmToolkitError::AddEventListener(
64 "`onchange` event listener for checking dark and light modes".to_string(),
65 ))
66 }
67 }
68}