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