use std::rc::Rc;
use gloo::events::EventListener;
use gloo::utils::document;
use wasm_bindgen::prelude::*;
use web_sys::HtmlElement;
use yew::prelude::*;
use super::{use_state_ptr_eq, UseStatePtrEqHandle};
pub struct UseFullscreenHandle {
pub is_fullscreen: UseStatePtrEqHandle<bool>,
pub is_supported: Rc<bool>,
enter: Rc<dyn Fn()>,
exit: Rc<dyn Fn()>,
toggle: Rc<dyn Fn()>,
}
impl UseFullscreenHandle {
pub fn enter(&self) {
(self.enter)();
}
pub fn exit(&self) {
(self.exit)();
}
pub fn toggle(&self) {
(self.toggle)();
}
}
impl Clone for UseFullscreenHandle {
fn clone(&self) -> Self {
Self {
is_fullscreen: self.is_fullscreen.clone(),
is_supported: self.is_supported.clone(),
enter: self.enter.clone(),
exit: self.exit.clone(),
toggle: self.toggle.clone(),
}
}
}
#[hook]
pub fn use_fullscreen(node: NodeRef) -> UseFullscreenHandle {
let is_fullscreen = use_state_ptr_eq(|| false);
let is_supported = use_memo((), |_| {
let doc = document();
js_sys::Reflect::has(&doc, &JsValue::from("fullscreenEnabled")).unwrap_or(false)
});
let get_fullscreen_element = || {
let doc = document();
js_sys::Reflect::get(&doc, &JsValue::from("fullscreenElement"))
.ok()
.and_then(|v| v.dyn_into::<web_sys::Element>().ok())
};
let update_fullscreen_state = {
let is_fullscreen = is_fullscreen.clone();
move || {
let fullscreen_element = get_fullscreen_element();
let is_fs = fullscreen_element.is_some();
is_fullscreen.set(is_fs);
}
};
{
let update_fullscreen_state1 = update_fullscreen_state.clone();
let update_fullscreen_state2 = update_fullscreen_state.clone();
use_effect_with((), move |_| {
let doc = document();
let listener = EventListener::new(&doc, "fullscreenchange", move |_| {
update_fullscreen_state1();
});
let webkit_listener = EventListener::new(&doc, "webkitfullscreenchange", move |_| {
update_fullscreen_state2();
});
Box::new(move || {
drop(listener);
drop(webkit_listener);
})
});
}
{
let update_fullscreen_state = update_fullscreen_state.clone();
use_effect_with((), move |_| {
update_fullscreen_state();
|| ()
});
}
let enter = {
let is_supported = is_supported.clone();
let node = node.clone();
Rc::new(move || {
if !*is_supported {
return;
}
let Some(element) = node.cast::<HtmlElement>() else {
return;
};
let result = js_sys::Reflect::get(&element, &JsValue::from("requestFullscreen"));
if let Ok(func) = result {
if func.is_function() {
let func = js_sys::Function::from(func);
let _ = func.call0(&element);
} else {
let func =
js_sys::Reflect::get(&element, &JsValue::from("webkitRequestFullscreen"));
if let Ok(func) = func {
if func.is_function() {
let func = js_sys::Function::from(func);
let _ = func.call0(&element);
}
}
}
} else {
let func =
js_sys::Reflect::get(&element, &JsValue::from("webkitRequestFullscreen"));
if let Ok(func) = func {
if func.is_function() {
let func = js_sys::Function::from(func);
let _ = func.call0(&element);
}
}
}
})
};
let exit = {
let is_supported = is_supported.clone();
Rc::new(move || {
if !*is_supported {
return;
}
let doc = document();
let result = js_sys::Reflect::get(&doc, &JsValue::from("exitFullscreen"));
if let Ok(func) = result {
if func.is_function() {
let func = js_sys::Function::from(func);
let _ = func.call0(&doc);
} else {
let func = js_sys::Reflect::get(&doc, &JsValue::from("webkitExitFullscreen"));
if let Ok(func) = func {
if func.is_function() {
let func = js_sys::Function::from(func);
let _ = func.call0(&doc);
}
}
}
} else {
let func = js_sys::Reflect::get(&doc, &JsValue::from("webkitExitFullscreen"));
if let Ok(func) = func {
if func.is_function() {
let func = js_sys::Function::from(func);
let _ = func.call0(&doc);
}
}
}
})
};
let toggle = {
let is_fullscreen = is_fullscreen.clone();
let enter = enter.clone();
let exit = exit.clone();
Rc::new(move || {
if *is_fullscreen {
exit();
} else {
enter();
}
})
};
UseFullscreenHandle {
is_fullscreen,
is_supported,
enter,
exit,
toggle,
}
}