telegram_webapp_sdk/api/
gyroscope.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 AngularVelocity {
13 pub x: f64,
15 pub y: f64,
17 pub z: f64
19}
20
21impl AngularVelocity {
22 #[allow(dead_code)]
23 const fn new(x: f64, y: f64, z: f64) -> Self {
24 Self {
25 x,
26 y,
27 z
28 }
29 }
30}
31
32pub fn start() -> Result<(), JsValue> {
45 let gyro = gyroscope_object()?;
46 let func = Reflect::get(&gyro, &"start".into())?.dyn_into::<Function>()?;
47 func.call0(&gyro)?;
48 Ok(())
49}
50
51pub fn stop() -> Result<(), JsValue> {
64 let gyro = gyroscope_object()?;
65 let func = Reflect::get(&gyro, &"stop".into())?.dyn_into::<Function>()?;
66 func.call0(&gyro)?;
67 Ok(())
68}
69
70pub fn get_angular_velocity() -> Option<AngularVelocity> {
78 let gyro = gyroscope_object().ok()?;
79 let x = Reflect::get(&gyro, &"x".into()).ok()?.as_f64()?;
80 let y = Reflect::get(&gyro, &"y".into()).ok()?.as_f64()?;
81 let z = Reflect::get(&gyro, &"z".into()).ok()?.as_f64()?;
82 Some(AngularVelocity {
83 x,
84 y,
85 z
86 })
87}
88
89pub fn on_started(callback: &Closure<dyn Fn()>) -> Result<(), JsValue> {
91 events::on_event("gyroscopeStarted", callback)
92}
93
94pub fn on_changed(callback: &Closure<dyn Fn()>) -> Result<(), JsValue> {
96 events::on_event("gyroscopeChanged", callback)
97}
98
99pub fn on_stopped(callback: &Closure<dyn Fn()>) -> Result<(), JsValue> {
101 events::on_event("gyroscopeStopped", callback)
102}
103
104pub fn on_failed(callback: &Closure<dyn Fn()>) -> Result<(), JsValue> {
106 events::on_event("gyroscopeFailed", callback)
107}
108
109fn gyroscope_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, &"Gyroscope".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_gyroscope() -> (Object, Object) {
130 let win = window().unwrap();
131 let telegram = Object::new();
132 let webapp = Object::new();
133 let gyro = Object::new();
134 let _ = Reflect::set(&win, &"Telegram".into(), &telegram);
135 let _ = Reflect::set(&telegram, &"WebApp".into(), &webapp);
136 let _ = Reflect::set(&webapp, &"Gyroscope".into(), &gyro);
137 (webapp, gyro)
138 }
139
140 #[wasm_bindgen_test]
141 #[allow(clippy::unused_unit)]
142 fn start_ok() {
143 let (_webapp, gyro) = setup_gyroscope();
144 let func = Function::new_no_args("this.called = true;");
145 let _ = Reflect::set(&gyro, &"start".into(), &func);
146 assert!(start().is_ok());
147 let called = Reflect::get(&gyro, &"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, gyro) = setup_gyroscope();
155 let _ = Reflect::set(&gyro, &"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, gyro) = setup_gyroscope();
163 let func = Function::new_no_args("this.stopped = true;");
164 let _ = Reflect::set(&gyro, &"stop".into(), &func);
165 assert!(stop().is_ok());
166 let stopped = Reflect::get(&gyro, &"stopped".into()).unwrap();
167 assert_eq!(stopped.as_bool(), Some(true));
168 }
169
170 #[wasm_bindgen_test]
171 fn get_angular_velocity_ok() {
172 let (_webapp, gyro) = setup_gyroscope();
173 let _ = Reflect::set(&gyro, &"x".into(), &JsValue::from_f64(0.1));
174 let _ = Reflect::set(&gyro, &"y".into(), &JsValue::from_f64(0.2));
175 let _ = Reflect::set(&gyro, &"z".into(), &JsValue::from_f64(0.3));
176 let result = get_angular_velocity().unwrap();
177 assert_eq!(
178 result,
179 AngularVelocity {
180 x: 0.1,
181 y: 0.2,
182 z: 0.3
183 }
184 );
185 }
186
187 #[wasm_bindgen_test]
188 fn registers_callbacks() {
189 let (webapp, _gyro) = setup_gyroscope();
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, &"gyroscopeStarted".into()).unwrap());
198 assert!(Reflect::has(&webapp, &"gyroscopeChanged".into()).unwrap());
199 assert!(Reflect::has(&webapp, &"gyroscopeStopped".into()).unwrap());
200 assert!(Reflect::has(&webapp, &"gyroscopeFailed".into()).unwrap());
201 cb.forget();
202 }
203}