telegram_webapp_sdk/api/
accelerometer.rs1use js_sys::{Function, Reflect};
2use wasm_bindgen::{JsCast, prelude::*};
3use web_sys::window;
4
5use super::events;
6
7#[derive(Debug, Clone, Copy, PartialEq)]
9pub struct Acceleration {
10 pub x: f64,
12 pub y: f64,
14 pub z: f64
16}
17
18impl Acceleration {
19 #[allow(dead_code)]
21 const fn new(x: f64, y: f64, z: f64) -> Self {
22 Self {
23 x,
24 y,
25 z
26 }
27 }
28}
29
30pub fn start() -> Result<(), JsValue> {
43 let accel = accelerometer_object()?;
44 let func = Reflect::get(&accel, &"start".into())?.dyn_into::<Function>()?;
45 func.call0(&accel)?;
46 Ok(())
47}
48
49pub fn stop() -> Result<(), JsValue> {
62 let accel = accelerometer_object()?;
63 let func = Reflect::get(&accel, &"stop".into())?.dyn_into::<Function>()?;
64 func.call0(&accel)?;
65 Ok(())
66}
67
68pub fn get_acceleration() -> Option<Acceleration> {
76 let accel = accelerometer_object().ok()?;
77 let x = Reflect::get(&accel, &"x".into()).ok()?.as_f64()?;
78 let y = Reflect::get(&accel, &"y".into()).ok()?.as_f64()?;
79 let z = Reflect::get(&accel, &"z".into()).ok()?.as_f64()?;
80 Some(Acceleration {
81 x,
82 y,
83 z
84 })
85}
86
87pub fn on_started(callback: &Closure<dyn Fn()>) -> Result<(), JsValue> {
91 events::on_event("accelerometerStarted", callback)
92}
93
94pub fn on_changed(callback: &Closure<dyn Fn()>) -> Result<(), JsValue> {
98 events::on_event("accelerometerChanged", callback)
99}
100
101pub fn on_stopped(callback: &Closure<dyn Fn()>) -> Result<(), JsValue> {
105 events::on_event("accelerometerStopped", callback)
106}
107
108pub fn on_failed(callback: &Closure<dyn Fn()>) -> Result<(), JsValue> {
112 events::on_event("accelerometerFailed", callback)
113}
114
115fn accelerometer_object() -> Result<JsValue, JsValue> {
116 let win = window().ok_or_else(|| JsValue::from_str("no window"))?;
117 let tg = Reflect::get(&win, &"Telegram".into())?;
118 let webapp = Reflect::get(&tg, &"WebApp".into())?;
119 Reflect::get(&webapp, &"Accelerometer".into())
120}
121
122#[cfg(test)]
123#[allow(dead_code)]
124mod tests {
125 use js_sys::{Function, Object, Reflect};
126 use wasm_bindgen::{JsValue, closure::Closure};
127 use wasm_bindgen_test::{wasm_bindgen_test, wasm_bindgen_test_configure};
128 use web_sys::window;
129
130 use super::*;
131
132 wasm_bindgen_test_configure!(run_in_browser);
133
134 #[allow(dead_code)]
135 fn setup_accelerometer() -> (Object, Object) {
136 let win = window().unwrap();
137 let telegram = Object::new();
138 let webapp = Object::new();
139 let accel = Object::new();
140 let _ = Reflect::set(&win, &"Telegram".into(), &telegram);
141 let _ = Reflect::set(&telegram, &"WebApp".into(), &webapp);
142 let _ = Reflect::set(&webapp, &"Accelerometer".into(), &accel);
143 (webapp, accel)
144 }
145
146 #[wasm_bindgen_test]
147 #[allow(clippy::unused_unit)]
148 fn start_ok() {
149 let (_webapp, accel) = setup_accelerometer();
150 let func = Function::new_no_args("this.called = true;");
151 let _ = Reflect::set(&accel, &"start".into(), &func);
152 assert!(start().is_ok());
153 let called = Reflect::get(&accel, &"called".into()).unwrap();
154 assert_eq!(called.as_bool(), Some(true));
155 }
156
157 #[wasm_bindgen_test]
158 #[allow(clippy::unused_unit)]
159 fn start_err() {
160 let (_webapp, accel) = setup_accelerometer();
161 let _ = Reflect::set(&accel, &"start".into(), &JsValue::from_f64(1.0));
162 assert!(start().is_err());
163 }
164
165 #[wasm_bindgen_test]
166 #[allow(clippy::unused_unit)]
167 fn stop_ok() {
168 let (_webapp, accel) = setup_accelerometer();
169 let func = Function::new_no_args("this.stopped = true;");
170 let _ = Reflect::set(&accel, &"stop".into(), &func);
171 assert!(stop().is_ok());
172 let stopped = Reflect::get(&accel, &"stopped".into()).unwrap();
173 assert_eq!(stopped.as_bool(), Some(true));
174 }
175
176 #[wasm_bindgen_test]
177 fn get_acceleration_ok() {
178 let (_webapp, accel) = setup_accelerometer();
179 let _ = Reflect::set(&accel, &"x".into(), &JsValue::from_f64(1.0));
180 let _ = Reflect::set(&accel, &"y".into(), &JsValue::from_f64(2.0));
181 let _ = Reflect::set(&accel, &"z".into(), &JsValue::from_f64(3.0));
182 let result = get_acceleration().unwrap();
183 assert_eq!(
184 result,
185 Acceleration {
186 x: 1.0,
187 y: 2.0,
188 z: 3.0
189 }
190 );
191 }
192
193 #[wasm_bindgen_test]
194 fn registers_callbacks() {
195 let (webapp, _accel) = setup_accelerometer();
196 let on_event = Function::new_with_args("name, cb", "this[name] = cb;");
197 let _ = Reflect::set(&webapp, &"onEvent".into(), &on_event);
198 let cb = Closure::wrap(Box::new(|| {}) as Box<dyn Fn()>);
199 on_started(&cb).expect("on_started");
200 on_changed(&cb).expect("on_changed");
201 on_stopped(&cb).expect("on_stopped");
202 on_failed(&cb).expect("on_failed");
203 assert!(Reflect::has(&webapp, &"accelerometerStarted".into()).unwrap());
204 assert!(Reflect::has(&webapp, &"accelerometerChanged".into()).unwrap());
205 assert!(Reflect::has(&webapp, &"accelerometerStopped".into()).unwrap());
206 assert!(Reflect::has(&webapp, &"accelerometerFailed".into()).unwrap());
207 cb.forget();
208 }
209}