Skip to main content

euv_ui/hook/use_window_size/
impl.rs

1use super::*;
2
3/// Inherent implementation of [`UseWindowSize`].
4impl UseWindowSize {
5    /// Creates a handle with the size starting at zero.
6    ///
7    /// # Returns
8    ///
9    /// - `UseWindowSize` - The fresh handle.
10    pub(crate) fn new() -> Self {
11        Self {
12            width: Signal::create(0),
13            height: Signal::create(0),
14            teardown: Rc::new(RefCell::new(None)),
15        }
16    }
17
18    /// Returns the current width as a snapshot.
19    ///
20    /// # Returns
21    ///
22    /// - `i32` - The viewport width in CSS pixels.
23    pub fn current_width(&self) -> i32 {
24        self.get_width().get()
25    }
26
27    /// Returns the current height as a snapshot.
28    ///
29    /// # Returns
30    ///
31    /// - `i32` - The viewport height in CSS pixels.
32    pub fn current_height(&self) -> i32 {
33        self.get_height().get()
34    }
35
36    /// Subscribes to the window's `resize` event and seeds the size
37    /// with the browser's current values.
38    ///
39    /// On a host without a browser this is a no-op and the size stays at
40    /// zero.
41    pub(crate) fn attach(&self) {
42        #[cfg(target_arch = "wasm32")]
43        {
44            let Some(window) = browser_window() else {
45                return;
46            };
47            let width: Signal<i32> = self.get_width();
48            let height: Signal<i32> = self.get_height();
49            let resized: Window = window.clone();
50            let on_resize: Closure<dyn FnMut(Event)> =
51                Closure::wrap(Box::new(move |_event: Event| {
52                    width.set(read_dimension(&resized, true));
53                    height.set(read_dimension(&resized, false));
54                }));
55            if window
56                .add_event_listener_with_callback(EVENT_RESIZE, on_resize.as_ref().unchecked_ref())
57                .is_err()
58            {
59                return;
60            }
61            width.set(read_dimension(&window, true));
62            height.set(read_dimension(&window, false));
63            *self.get_teardown().borrow_mut() = Some(Box::new(move || {
64                let _: Result<(), JsValue> = window.remove_event_listener_with_callback(
65                    EVENT_RESIZE,
66                    on_resize.as_ref().unchecked_ref(),
67                );
68            }));
69        }
70    }
71
72    /// Removes the window listener.
73    pub(crate) fn detach(&self) {
74        let taken: Option<Box<dyn Fn()>> = self.get_teardown().borrow_mut().take();
75        if let Some(teardown) = taken {
76            teardown();
77        }
78    }
79}