telegram_webapp_sdk/api/
device_orientation.rs1use js_sys::{Function, Reflect};
5use wasm_bindgen::{JsCast, prelude::*};
6use web_sys::window;
7
8use super::events;
9
10#[derive(Debug, Clone, Copy, PartialEq)]
12pub struct Orientation {
13 pub alpha: f64,
15 pub beta: f64,
17 pub gamma: f64
19}
20
21impl Orientation {
22 #[allow(dead_code)]
23 const fn new(alpha: f64, beta: f64, gamma: f64) -> Self {
24 Self {
25 alpha,
26 beta,
27 gamma
28 }
29 }
30}
31
32pub fn start() -> Result<(), JsValue> {
45 let orientation = device_orientation_object()?;
46 let func = Reflect::get(&orientation, &"start".into())?.dyn_into::<Function>()?;
47 func.call0(&orientation)?;
48 Ok(())
49}
50
51pub fn stop() -> Result<(), JsValue> {
64 let orientation = device_orientation_object()?;
65 let func = Reflect::get(&orientation, &"stop".into())?.dyn_into::<Function>()?;
66 func.call0(&orientation)?;
67 Ok(())
68}
69
70pub fn get_orientation() -> Option<Orientation> {
78 let orientation = device_orientation_object().ok()?;
79 let alpha = Reflect::get(&orientation, &"alpha".into()).ok()?.as_f64()?;
80 let beta = Reflect::get(&orientation, &"beta".into()).ok()?.as_f64()?;
81 let gamma = Reflect::get(&orientation, &"gamma".into()).ok()?.as_f64()?;
82 Some(Orientation {
83 alpha,
84 beta,
85 gamma
86 })
87}
88
89pub fn on_started(callback: &Closure<dyn Fn()>) -> Result<(), JsValue> {
91 events::on_event("deviceOrientationStarted", callback)
92}
93
94pub fn on_changed(callback: &Closure<dyn Fn()>) -> Result<(), JsValue> {
96 events::on_event("deviceOrientationChanged", callback)
97}
98
99pub fn on_stopped(callback: &Closure<dyn Fn()>) -> Result<(), JsValue> {
101 events::on_event("deviceOrientationStopped", callback)
102}
103
104pub fn on_failed(callback: &Closure<dyn Fn()>) -> Result<(), JsValue> {
106 events::on_event("deviceOrientationFailed", callback)
107}
108
109fn device_orientation_object() -> Result<JsValue, JsValue> {
110 let win = window().ok_or_else(|| JsValue::from_str("no window"))?;
111 let tg = Reflect::get(&win, &"Telegram".into())?;
112 let webapp = Reflect::get(&tg, &"WebApp".into())?;
113 Reflect::get(&webapp, &"DeviceOrientation".into())
114}
115
116#[cfg(test)]
117#[allow(dead_code)]
118mod tests {
119 use js_sys::{Function, Object, Reflect};
120 use wasm_bindgen::{JsValue, closure::Closure};
121 use wasm_bindgen_test::{wasm_bindgen_test, wasm_bindgen_test_configure};
122 use web_sys::window;
123
124 use super::*;
125
126 wasm_bindgen_test_configure!(run_in_browser);
127
128 #[allow(dead_code)]
129 fn setup_device_orientation() -> (Object, Object) {
130 let win = window().unwrap();
131 let telegram = Object::new();
132 let webapp = Object::new();
133 let orientation = Object::new();
134 let _ = Reflect::set(&win, &"Telegram".into(), &telegram);
135 let _ = Reflect::set(&telegram, &"WebApp".into(), &webapp);
136 let _ = Reflect::set(&webapp, &"DeviceOrientation".into(), &orientation);
137 (webapp, orientation)
138 }
139
140 #[wasm_bindgen_test]
141 #[allow(clippy::unused_unit)]
142 fn start_ok() {
143 let (_webapp, orientation) = setup_device_orientation();
144 let func = Function::new_no_args("this.called = true;");
145 let _ = Reflect::set(&orientation, &"start".into(), &func);
146 assert!(start().is_ok());
147 let called = Reflect::get(&orientation, &"called".into()).unwrap();
148 assert_eq!(called.as_bool(), Some(true));
149 }
150
151 #[wasm_bindgen_test]
152 #[allow(clippy::unused_unit)]
153 fn start_err() {
154 let (_webapp, orientation) = setup_device_orientation();
155 let _ = Reflect::set(&orientation, &"start".into(), &JsValue::from_f64(1.0));
156 assert!(start().is_err());
157 }
158
159 #[wasm_bindgen_test]
160 #[allow(clippy::unused_unit)]
161 fn stop_ok() {
162 let (_webapp, orientation) = setup_device_orientation();
163 let func = Function::new_no_args("this.stopped = true;");
164 let _ = Reflect::set(&orientation, &"stop".into(), &func);
165 assert!(stop().is_ok());
166 let stopped = Reflect::get(&orientation, &"stopped".into()).unwrap();
167 assert_eq!(stopped.as_bool(), Some(true));
168 }
169
170 #[wasm_bindgen_test]
171 fn get_orientation_ok() {
172 let (_webapp, orientation) = setup_device_orientation();
173 let _ = Reflect::set(&orientation, &"alpha".into(), &JsValue::from_f64(10.0));
174 let _ = Reflect::set(&orientation, &"beta".into(), &JsValue::from_f64(20.0));
175 let _ = Reflect::set(&orientation, &"gamma".into(), &JsValue::from_f64(30.0));
176 let result = get_orientation().unwrap();
177 assert_eq!(
178 result,
179 Orientation {
180 alpha: 10.0,
181 beta: 20.0,
182 gamma: 30.0
183 }
184 );
185 }
186
187 #[wasm_bindgen_test]
188 fn registers_callbacks() {
189 let (webapp, _orientation) = setup_device_orientation();
190 let on_event = Function::new_with_args("name, cb", "this[name] = cb;");
191 let _ = Reflect::set(&webapp, &"onEvent".into(), &on_event);
192 let cb = Closure::wrap(Box::new(|| {}) as Box<dyn Fn()>);
193 on_started(&cb).expect("on_started");
194 on_changed(&cb).expect("on_changed");
195 on_stopped(&cb).expect("on_stopped");
196 on_failed(&cb).expect("on_failed");
197 assert!(Reflect::has(&webapp, &"deviceOrientationStarted".into()).unwrap());
198 assert!(Reflect::has(&webapp, &"deviceOrientationChanged".into()).unwrap());
199 assert!(Reflect::has(&webapp, &"deviceOrientationStopped".into()).unwrap());
200 assert!(Reflect::has(&webapp, &"deviceOrientationFailed".into()).unwrap());
201 cb.forget();
202 }
203}