telegram_webapp_sdk/api/
settings_button.rs1use js_sys::{Function, Reflect};
2use wasm_bindgen::{JsCast, prelude::*};
3use web_sys::window;
4
5pub fn show() -> Result<(), JsValue> {
19 let button = settings_button_object()?;
20 let func = Reflect::get(&button, &"show".into())?.dyn_into::<Function>()?;
21 func.call0(&button)?;
22 Ok(())
23}
24
25pub fn hide() -> Result<(), JsValue> {
39 let button = settings_button_object()?;
40 let func = Reflect::get(&button, &"hide".into())?.dyn_into::<Function>()?;
41 func.call0(&button)?;
42 Ok(())
43}
44
45pub fn on_click(callback: &Closure<dyn Fn()>) -> Result<(), JsValue> {
63 let button = settings_button_object()?;
64 let func = Reflect::get(&button, &"onClick".into())?.dyn_into::<Function>()?;
65 func.call1(&button, callback.as_ref())?;
66 Ok(())
67}
68
69pub fn off_click(callback: &Closure<dyn Fn()>) -> Result<(), JsValue> {
85 let button = settings_button_object()?;
86 let func = Reflect::get(&button, &"offClick".into())?.dyn_into::<Function>()?;
87 func.call1(&button, callback.as_ref())?;
88 Ok(())
89}
90
91fn settings_button_object() -> Result<JsValue, JsValue> {
92 let win = window().ok_or_else(|| JsValue::from_str("no window"))?;
93 let tg = Reflect::get(&win, &"Telegram".into())?;
94 let webapp = Reflect::get(&tg, &"WebApp".into())?;
95 Reflect::get(&webapp, &"SettingsButton".into())
96}
97
98#[cfg(test)]
99mod tests {
100 use js_sys::{Function, Object, Reflect};
101 use wasm_bindgen::closure::Closure;
102 use wasm_bindgen_test::{wasm_bindgen_test, wasm_bindgen_test_configure};
103 use web_sys::window;
104
105 use super::*;
106
107 wasm_bindgen_test_configure!(run_in_browser);
108
109 #[allow(dead_code)]
110 fn setup_button() -> Object {
111 let win = window().unwrap();
112 let telegram = Object::new();
113 let webapp = Object::new();
114 let button = Object::new();
115 let _ = Reflect::set(&win, &"Telegram".into(), &telegram);
116 let _ = Reflect::set(&telegram, &"WebApp".into(), &webapp);
117 let _ = Reflect::set(&webapp, &"SettingsButton".into(), &button);
118 button
119 }
120
121 #[wasm_bindgen_test]
122 #[allow(dead_code, clippy::unused_unit)]
123 fn show_calls_js() {
124 let button = setup_button();
125 let func = Function::new_no_args("this.called = true;");
126 let _ = Reflect::set(&button, &"show".into(), &func);
127 assert!(show().is_ok());
128 assert!(
129 Reflect::get(&button, &"called".into())
130 .unwrap()
131 .as_bool()
132 .unwrap()
133 );
134 }
135
136 #[wasm_bindgen_test]
137 #[allow(dead_code, clippy::unused_unit)]
138 fn hide_calls_js() {
139 let button = setup_button();
140 let func = Function::new_no_args("this.called = true;");
141 let _ = Reflect::set(&button, &"hide".into(), &func);
142 assert!(hide().is_ok());
143 assert!(
144 Reflect::get(&button, &"called".into())
145 .unwrap()
146 .as_bool()
147 .unwrap()
148 );
149 }
150
151 #[wasm_bindgen_test]
152 #[allow(dead_code, clippy::unused_unit)]
153 fn click_callbacks() {
154 let button = setup_button();
155 let on = Function::new_with_args("cb", "this.cb = cb;");
156 let off = Function::new_with_args("cb", "delete this.cb;");
157 let _ = Reflect::set(&button, &"onClick".into(), &on);
158 let _ = Reflect::set(&button, &"offClick".into(), &off);
159 let cb = Closure::wrap(Box::new(|| {}) as Box<dyn Fn()>);
160 on_click(&cb).expect("on");
161 assert!(Reflect::has(&button, &"cb".into()).unwrap());
162 off_click(&cb).expect("off");
163 assert!(!Reflect::has(&button, &"cb".into()).unwrap());
164 }
165
166 #[wasm_bindgen_test]
167 #[allow(dead_code, clippy::unused_unit)]
168 fn show_err() {
169 let _ = setup_button();
170 assert!(show().is_err());
171 }
172
173 #[wasm_bindgen_test]
174 #[allow(dead_code, clippy::unused_unit)]
175 fn on_click_err() {
176 let _ = setup_button();
177 let cb = Closure::wrap(Box::new(|| {}) as Box<dyn Fn()>);
178 assert!(on_click(&cb).is_err());
179 }
180}