logicaffeine_web/ui/hooks/
use_visual_viewport.rs1use dioxus::prelude::*;
4
5pub fn use_keyboard_inset() -> Signal<f64> {
10 #[cfg(target_arch = "wasm32")]
11 {
12 use std::rc::Rc;
13 use wasm_bindgen::prelude::*;
14 use wasm_bindgen::JsCast;
15
16 fn measure() -> Option<f64> {
17 let window = web_sys::window()?;
18 let layout = window.inner_height().ok()?.as_f64()?;
19 let visual = window.visual_viewport()?;
20 Some((layout - visual.height() - visual.offset_top()).max(0.0))
21 }
22
23 let mut inset = use_signal(|| measure().unwrap_or(0.0));
24 let on_resize = use_hook(move || {
25 let on_resize = Closure::<dyn FnMut()>::new(move || {
26 if let Some(now) = measure() {
27 if (*inset.peek() - now).abs() >= 1.0 {
28 inset.set(now);
29 }
30 }
31 });
32 if let Some(visual) = web_sys::window().and_then(|w| w.visual_viewport()) {
33 let _ = visual.add_event_listener_with_callback("resize", on_resize.as_ref().unchecked_ref());
34 let _ = visual.add_event_listener_with_callback("scroll", on_resize.as_ref().unchecked_ref());
35 }
36 Rc::new(on_resize)
37 });
38 use_drop(move || {
39 if let Some(visual) = web_sys::window().and_then(|w| w.visual_viewport()) {
40 let _ = visual.remove_event_listener_with_callback("resize", (*on_resize).as_ref().unchecked_ref());
41 let _ = visual.remove_event_listener_with_callback("scroll", (*on_resize).as_ref().unchecked_ref());
42 }
43 });
44 inset
45 }
46 #[cfg(not(target_arch = "wasm32"))]
47 {
48 use_signal(|| 0.0)
49 }
50}