yew_stdweb/services/
resize.rs

1//! This module contains Yew's implementation of a service which listens for browser window resize events.
2use crate::services::Task;
3use cfg_if::cfg_if;
4use cfg_match::cfg_match;
5use std::fmt;
6use yew::callback::Callback;
7cfg_if! {
8    if #[cfg(feature = "std_web")] {
9        use stdweb::js;
10        use stdweb::web::{event::ResizeEvent, window, Window};
11        use stdweb::Value;
12    } else if #[cfg(feature = "web_sys")] {
13        use gloo::events::EventListener;
14        use web_sys::{Event, Window};
15    }
16}
17
18/// A service which fires events when the browser window is resized.
19#[derive(Default, Debug)]
20pub struct ResizeService {}
21
22/// A handle for the event listener listening for resize events.
23#[must_use = "the listener is only active until the task is dropped"]
24pub struct ResizeTask(
25    #[cfg(feature = "std_web")] Value,
26    #[cfg(feature = "web_sys")] EventListener,
27);
28
29impl fmt::Debug for ResizeTask {
30    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
31        f.write_str("ResizeTask")
32    }
33}
34
35/// Dimensions of the window.
36#[derive(Copy, Clone, Debug)]
37pub struct WindowDimensions {
38    /// The width of the viewport of the browser window.
39    pub width: i32,
40    /// The height of the viewport of the browser window.
41    pub height: i32,
42}
43
44impl WindowDimensions {
45    /// Gets the dimensions of the browser window.
46    pub fn get_dimensions(window: &Window) -> Self {
47        let width = window.inner_width();
48        let height = window.inner_height();
49        #[cfg(feature = "web_sys")]
50        let (width, height) = {
51            (
52                width.unwrap().as_f64().unwrap() as _,
53                height.unwrap().as_f64().unwrap() as _,
54            )
55        };
56        WindowDimensions { width, height }
57    }
58}
59
60impl ResizeService {
61    /// Register a callback that will be called when the browser window resizes.
62    pub fn register(callback: Callback<WindowDimensions>) -> ResizeTask {
63        let callback =
64            move |#[cfg(feature = "web_sys")] _event: &Event,
65                  #[cfg(feature = "std_web")] _event: ResizeEvent| {
66                let window = cfg_match! {
67                    feature = "std_web" => window(),
68                    feature = "web_sys" => web_sys::window().unwrap(),
69                };
70                let dimensions = WindowDimensions::get_dimensions(&window);
71                callback.emit(dimensions);
72            };
73        let handle = cfg_match! {
74            feature = "std_web" => js! {
75                var handle = @{callback};
76                window.addEventListener("resize", handle);
77                return handle;
78            },
79            feature = "web_sys" => EventListener::new(&web_sys::window().unwrap(), "resize", callback),
80        };
81        ResizeTask(handle)
82    }
83}
84
85impl Task for ResizeTask {
86    fn is_active(&self) -> bool {
87        true
88    }
89}
90
91impl Drop for ResizeTask {
92    fn drop(&mut self) {
93        #[cfg(feature = "std_web")]
94        {
95            let handle = &self.0;
96            js! {
97                @(no_return)
98                var handle = @{handle};
99                window.removeEventListener("resize", handle);
100            }
101        }
102    }
103}