use js_sys::{Function, Reflect};
use wasm_bindgen::{JsCast, prelude::*};
use web_sys::window;
pub fn init() -> Result<(), JsValue> {
let manager = location_manager_object()?;
let func = Reflect::get(&manager, &JsValue::from_str("init"))?.dyn_into::<Function>()?;
func.call0(&manager)?;
Ok(())
}
pub fn get_location() -> Result<JsValue, JsValue> {
let manager = location_manager_object()?;
let func =
Reflect::get(&manager, &JsValue::from_str("getLocation"))?.dyn_into::<Function>()?;
func.call0(&manager)
}
pub fn open_settings() -> Result<(), JsValue> {
let manager = location_manager_object()?;
let func =
Reflect::get(&manager, &JsValue::from_str("openSettings"))?.dyn_into::<Function>()?;
func.call0(&manager)?;
Ok(())
}
pub fn on_location_manager_updated(callback: &Closure<dyn Fn()>) -> Result<(), JsValue> {
add_event_listener("locationManagerUpdated", callback)
}
pub fn on_location_requested(callback: &Closure<dyn Fn()>) -> Result<(), JsValue> {
add_event_listener("locationRequested", callback)
}
fn add_event_listener(event: &str, callback: &Closure<dyn Fn()>) -> Result<(), JsValue> {
let webapp = webapp_object()?;
let on_event = Reflect::get(&webapp, &JsValue::from_str("onEvent"))?.dyn_into::<Function>()?;
on_event.call2(&webapp, &JsValue::from_str(event), callback.as_ref())?;
Ok(())
}
fn location_manager_object() -> Result<JsValue, JsValue> {
let window = window().ok_or_else(|| JsValue::from_str("no window"))?;
let tg = Reflect::get(&window, &JsValue::from_str("Telegram"))?;
let webapp = Reflect::get(&tg, &JsValue::from_str("WebApp"))?;
Reflect::get(&webapp, &JsValue::from_str("locationManager"))
}
fn webapp_object() -> Result<JsValue, JsValue> {
let window = window().ok_or_else(|| JsValue::from_str("no window"))?;
let tg = Reflect::get(&window, &JsValue::from_str("Telegram"))?;
Reflect::get(&tg, &JsValue::from_str("WebApp"))
}
#[cfg(test)]
mod tests {
use js_sys::{Function, Object, Reflect};
use wasm_bindgen::{JsValue, closure::Closure};
use wasm_bindgen_test::{wasm_bindgen_test, wasm_bindgen_test_configure};
use web_sys::window;
use super::*;
wasm_bindgen_test_configure!(run_in_browser);
#[allow(dead_code)]
fn setup_location_manager() -> (Object, Object) {
let win = window().expect("window should be available");
let telegram = Object::new();
let webapp = Object::new();
let manager = Object::new();
let _ = Reflect::set(&win, &"Telegram".into(), &telegram);
let _ = Reflect::set(&telegram, &"WebApp".into(), &webapp);
let _ = Reflect::set(&webapp, &"locationManager".into(), &manager);
(webapp, manager)
}
#[wasm_bindgen_test]
#[allow(dead_code, clippy::unused_unit)]
fn init_ok() {
let (_webapp, manager) = setup_location_manager();
let func = Function::new_no_args("this.called = true;");
let _ = Reflect::set(&manager, &"init".into(), &func);
assert!(init().is_ok());
assert!(
Reflect::get(&manager, &"called".into())
.unwrap()
.as_bool()
.unwrap()
);
}
#[wasm_bindgen_test]
#[allow(dead_code, clippy::unused_unit)]
fn init_err() {
let _ = setup_location_manager();
assert!(init().is_err());
}
#[wasm_bindgen_test]
#[allow(dead_code, clippy::unused_unit)]
fn get_location_ok() {
let (_webapp, manager) = setup_location_manager();
let location = Object::new();
let func = Function::new_no_args("return this.loc;");
let _ = Reflect::set(&manager, &"getLocation".into(), &func);
let _ = Reflect::set(&manager, &"loc".into(), &location);
let result = get_location().expect("location");
assert!(result.is_object());
}
#[wasm_bindgen_test]
#[allow(dead_code, clippy::unused_unit)]
fn get_location_err() {
let _ = setup_location_manager();
assert!(get_location().is_err());
}
#[wasm_bindgen_test]
#[allow(dead_code, clippy::unused_unit)]
fn open_settings_ok() {
let (_webapp, manager) = setup_location_manager();
let func = Function::new_no_args("this.called = true;");
let _ = Reflect::set(&manager, &"openSettings".into(), &func);
assert!(open_settings().is_ok());
assert!(
Reflect::get(&manager, &"called".into())
.unwrap()
.as_bool()
.unwrap()
);
}
#[wasm_bindgen_test]
#[allow(dead_code, clippy::unused_unit)]
fn open_settings_err() {
let _ = setup_location_manager();
assert!(open_settings().is_err());
}
#[wasm_bindgen_test]
#[allow(dead_code)]
fn registers_location_manager_updated_callback() {
let (webapp, _manager) = setup_location_manager();
let on_event = Function::new_with_args("name, cb", "this[name] = cb;");
let _ = Reflect::set(&webapp, &"onEvent".into(), &on_event);
let cb = Closure::wrap(Box::new(|| {}) as Box<dyn Fn()>);
on_location_manager_updated(&cb).expect("register callback");
let has = Reflect::has(&webapp, &JsValue::from_str("locationManagerUpdated")).unwrap();
assert!(has);
}
#[wasm_bindgen_test]
#[allow(dead_code)]
fn registers_location_requested_callback() {
let (webapp, _manager) = setup_location_manager();
let on_event = Function::new_with_args("name, cb", "this[name] = cb;");
let _ = Reflect::set(&webapp, &"onEvent".into(), &on_event);
let cb = Closure::wrap(Box::new(|| {}) as Box<dyn Fn()>);
on_location_requested(&cb).expect("register callback");
let has = Reflect::has(&webapp, &JsValue::from_str("locationRequested")).unwrap();
assert!(has);
}
}