telegram_webapp_sdk/api/
accelerometer.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 Acceleration {
13 pub x: f64,
15 pub y: f64,
17 pub z: f64
19}
20
21impl Acceleration {
22 #[allow(dead_code)]
24 const fn new(x: f64, y: f64, z: f64) -> Self {
25 Self {
26 x,
27 y,
28 z
29 }
30 }
31}
32
33pub fn start() -> Result<(), JsValue> {
46 let accel = accelerometer_object()?;
47 let func = Reflect::get(&accel, &"start".into())?.dyn_into::<Function>()?;
48 func.call0(&accel)?;
49 Ok(())
50}
51
52pub fn stop() -> Result<(), JsValue> {
65 let accel = accelerometer_object()?;
66 let func = Reflect::get(&accel, &"stop".into())?.dyn_into::<Function>()?;
67 func.call0(&accel)?;
68 Ok(())
69}
70
71pub fn get_acceleration() -> Option<Acceleration> {
79 let accel = accelerometer_object().ok()?;
80 let x = Reflect::get(&accel, &"x".into()).ok()?.as_f64()?;
81 let y = Reflect::get(&accel, &"y".into()).ok()?.as_f64()?;
82 let z = Reflect::get(&accel, &"z".into()).ok()?.as_f64()?;
83 Some(Acceleration {
84 x,
85 y,
86 z
87 })
88}
89
90pub fn on_started(callback: &Closure<dyn Fn()>) -> Result<(), JsValue> {
94 events::on_event("accelerometerStarted", callback)
95}
96
97pub fn on_changed(callback: &Closure<dyn Fn()>) -> Result<(), JsValue> {
101 events::on_event("accelerometerChanged", callback)
102}
103
104pub fn on_stopped(callback: &Closure<dyn Fn()>) -> Result<(), JsValue> {
108 events::on_event("accelerometerStopped", callback)
109}
110
111pub fn on_failed(callback: &Closure<dyn Fn()>) -> Result<(), JsValue> {
115 events::on_event("accelerometerFailed", callback)
116}
117
118fn accelerometer_object() -> Result<JsValue, JsValue> {
119 let win = window().ok_or_else(|| JsValue::from_str("no window"))?;
120 let tg = Reflect::get(&win, &"Telegram".into())?;
121 let webapp = Reflect::get(&tg, &"WebApp".into())?;
122 Reflect::get(&webapp, &"Accelerometer".into())
123}
124
125#[cfg(test)]
126#[allow(dead_code)]
127mod tests {
128 use js_sys::{Function, Object, Reflect};
129 use wasm_bindgen::{JsValue, closure::Closure};
130 use wasm_bindgen_test::{wasm_bindgen_test, wasm_bindgen_test_configure};
131 use web_sys::window;
132
133 use super::*;
134
135 wasm_bindgen_test_configure!(run_in_browser);
136
137 #[allow(dead_code)]
138 fn setup_accelerometer() -> (Object, Object) {
139 let win = window().unwrap();
140 let telegram = Object::new();
141 let webapp = Object::new();
142 let accel = Object::new();
143 let _ = Reflect::set(&win, &"Telegram".into(), &telegram);
144 let _ = Reflect::set(&telegram, &"WebApp".into(), &webapp);
145 let _ = Reflect::set(&webapp, &"Accelerometer".into(), &accel);
146 (webapp, accel)
147 }
148
149 #[wasm_bindgen_test]
150 #[allow(clippy::unused_unit)]
151 fn start_ok() {
152 let (_webapp, accel) = setup_accelerometer();
153 let func = Function::new_no_args("this.called = true;");
154 let _ = Reflect::set(&accel, &"start".into(), &func);
155 assert!(start().is_ok());
156 let called = Reflect::get(&accel, &"called".into()).unwrap();
157 assert_eq!(called.as_bool(), Some(true));
158 }
159
160 #[wasm_bindgen_test]
161 #[allow(clippy::unused_unit)]
162 fn start_err() {
163 let (_webapp, accel) = setup_accelerometer();
164 let _ = Reflect::set(&accel, &"start".into(), &JsValue::from_f64(1.0));
165 assert!(start().is_err());
166 }
167
168 #[wasm_bindgen_test]
169 #[allow(clippy::unused_unit)]
170 fn stop_ok() {
171 let (_webapp, accel) = setup_accelerometer();
172 let func = Function::new_no_args("this.stopped = true;");
173 let _ = Reflect::set(&accel, &"stop".into(), &func);
174 assert!(stop().is_ok());
175 let stopped = Reflect::get(&accel, &"stopped".into()).unwrap();
176 assert_eq!(stopped.as_bool(), Some(true));
177 }
178
179 #[wasm_bindgen_test]
180 fn get_acceleration_ok() {
181 let (_webapp, accel) = setup_accelerometer();
182 let _ = Reflect::set(&accel, &"x".into(), &JsValue::from_f64(1.0));
183 let _ = Reflect::set(&accel, &"y".into(), &JsValue::from_f64(2.0));
184 let _ = Reflect::set(&accel, &"z".into(), &JsValue::from_f64(3.0));
185 let result = get_acceleration().unwrap();
186 assert_eq!(
187 result,
188 Acceleration {
189 x: 1.0,
190 y: 2.0,
191 z: 3.0
192 }
193 );
194 }
195
196 #[wasm_bindgen_test]
197 fn registers_callbacks() {
198 let (webapp, _accel) = setup_accelerometer();
199 let on_event = Function::new_with_args("name, cb", "this[name] = cb;");
200 let _ = Reflect::set(&webapp, &"onEvent".into(), &on_event);
201 let cb = Closure::wrap(Box::new(|| {}) as Box<dyn Fn()>);
202 on_started(&cb).expect("on_started");
203 on_changed(&cb).expect("on_changed");
204 on_stopped(&cb).expect("on_stopped");
205 on_failed(&cb).expect("on_failed");
206 assert!(Reflect::has(&webapp, &"accelerometerStarted".into()).unwrap());
207 assert!(Reflect::has(&webapp, &"accelerometerChanged".into()).unwrap());
208 assert!(Reflect::has(&webapp, &"accelerometerStopped".into()).unwrap());
209 assert!(Reflect::has(&webapp, &"accelerometerFailed".into()).unwrap());
210 cb.forget();
211 }
212}