telegram_webapp_sdk/webapp/
navigation.rs1use js_sys::{Function, Reflect};
5use serde_wasm_bindgen::to_value;
6use wasm_bindgen::{JsCast, JsValue, prelude::Closure};
7
8use crate::webapp::{
9 TelegramWebApp,
10 core::{await_one_shot, one_shot_promise},
11 types::OpenLinkOptions
12};
13
14impl TelegramWebApp {
15 pub fn open_link(&self, url: &str, options: Option<&OpenLinkOptions>) -> Result<(), JsValue> {
24 let f = Reflect::get(&self.inner, &"openLink".into())?;
25 let func = f
26 .dyn_ref::<Function>()
27 .ok_or_else(|| JsValue::from_str("openLink is not a function"))?;
28 match options {
29 Some(opts) => {
30 let value = to_value(opts).map_err(|err| JsValue::from_str(&err.to_string()))?;
31 func.call2(&self.inner, &url.into(), &value)?;
32 }
33 None => {
34 func.call1(&self.inner, &url.into())?;
35 }
36 }
37 Ok(())
38 }
39
40 pub fn open_telegram_link(&self, url: &str) -> Result<(), JsValue> {
49 Reflect::get(&self.inner, &"openTelegramLink".into())?
50 .dyn_into::<Function>()?
51 .call1(&self.inner, &url.into())?;
52 Ok(())
53 }
54
55 pub fn switch_inline_query(
67 &self,
68 query: &str,
69 choose_chat_types: Option<&JsValue>
70 ) -> Result<(), JsValue> {
71 let f = Reflect::get(&self.inner, &"switchInlineQuery".into())?;
72 let func = f
73 .dyn_ref::<Function>()
74 .ok_or_else(|| JsValue::from_str("switchInlineQuery is not a function"))?;
75 match choose_chat_types {
76 Some(types) => func.call2(&self.inner, &query.into(), types)?,
77 None => func.call1(&self.inner, &query.into())?
78 };
79 Ok(())
80 }
81
82 pub fn share_message_with_callback<F>(&self, msg_id: &str, callback: F) -> Result<(), JsValue>
87 where
88 F: 'static + FnOnce(bool)
89 {
90 let cb = Closure::once_into_js(move |v: JsValue| {
91 callback(v.as_bool().unwrap_or(false));
92 });
93 let f = Reflect::get(&self.inner, &"shareMessage".into())?;
94 let func = f
95 .dyn_ref::<Function>()
96 .ok_or_else(|| JsValue::from_str("shareMessage is not a function"))?;
97 func.call2(&self.inner, &msg_id.into(), &cb)?;
98 Ok(())
99 }
100
101 pub async fn share_message(&self, msg_id: &str) -> Result<bool, JsValue> {
118 let webapp = self.inner.clone();
119 let msg_id = msg_id.to_owned();
120 let promise = one_shot_promise(move |resolve, _reject| {
121 let cb = Closure::once_into_js(move |v: JsValue| {
122 let _ = resolve.call1(&JsValue::NULL, &v);
123 });
124 let f = Reflect::get(&webapp, &"shareMessage".into())?;
125 let func = f
126 .dyn_ref::<Function>()
127 .ok_or_else(|| JsValue::from_str("shareMessage is not a function"))?;
128 func.call2(&webapp, &msg_id.into(), &cb)?;
129 Ok(())
130 });
131 let value = await_one_shot(promise).await?;
132 Ok(value.as_bool().unwrap_or(false))
133 }
134
135 pub fn share_to_story(
150 &self,
151 media_url: &str,
152 params: Option<&JsValue>
153 ) -> Result<(), JsValue> {
154 let f = Reflect::get(&self.inner, &"shareToStory".into())?;
155 let func = f
156 .dyn_ref::<Function>()
157 .ok_or_else(|| JsValue::from_str("shareToStory is not a function"))?;
158 match params {
159 Some(p) => func.call2(&self.inner, &media_url.into(), p)?,
160 None => func.call1(&self.inner, &media_url.into())?
161 };
162 Ok(())
163 }
164
165 pub fn share_url(&self, url: &str, text: Option<&str>) -> Result<(), JsValue> {
178 let f = Reflect::get(&self.inner, &"shareURL".into())?;
179 let func = f
180 .dyn_ref::<Function>()
181 .ok_or_else(|| JsValue::from_str("shareURL is not a function"))?;
182 match text {
183 Some(t) => func.call2(&self.inner, &url.into(), &t.into())?,
184 None => func.call1(&self.inner, &url.into())?
185 };
186 Ok(())
187 }
188
189 pub fn request_chat_with_callback<F>(&self, req_id: i32, callback: F) -> Result<(), JsValue>
194 where
195 F: 'static + FnOnce(bool)
196 {
197 let cb = Closure::once_into_js(move |v: JsValue| {
198 callback(v.as_bool().unwrap_or(false));
199 });
200 let f = Reflect::get(&self.inner, &"requestChat".into())?;
201 let func = f
202 .dyn_ref::<Function>()
203 .ok_or_else(|| JsValue::from_str("requestChat is not a function"))?;
204 func.call2(&self.inner, &req_id.into(), &cb)?;
205 Ok(())
206 }
207
208 pub async fn request_chat(&self, req_id: i32) -> Result<bool, JsValue> {
226 let webapp = self.inner.clone();
227 let promise = one_shot_promise(move |resolve, _reject| {
228 let cb = Closure::once_into_js(move |v: JsValue| {
229 let _ = resolve.call1(&JsValue::NULL, &v);
230 });
231 let f = Reflect::get(&webapp, &"requestChat".into())?;
232 let func = f
233 .dyn_ref::<Function>()
234 .ok_or_else(|| JsValue::from_str("requestChat is not a function"))?;
235 func.call2(&webapp, &req_id.into(), &cb)?;
236 Ok(())
237 });
238 let value = await_one_shot(promise).await?;
239 Ok(value.as_bool().unwrap_or(false))
240 }
241
242 pub fn add_to_home_screen(&self) -> Result<bool, JsValue> {
251 let f = Reflect::get(&self.inner, &"addToHomeScreen".into())?;
252 let func = f
253 .dyn_ref::<Function>()
254 .ok_or_else(|| JsValue::from_str("addToHomeScreen is not a function"))?;
255 let result = func.call0(&self.inner)?;
256 Ok(result.as_bool().unwrap_or(false))
257 }
258
259 pub fn check_home_screen_status_with_callback<F>(&self, callback: F) -> Result<(), JsValue>
261 where
262 F: 'static + FnOnce(String)
263 {
264 let cb = Closure::once_into_js(move |status: JsValue| {
265 callback(status.as_string().unwrap_or_default());
266 });
267 let f = Reflect::get(&self.inner, &"checkHomeScreenStatus".into())?;
268 let func = f
269 .dyn_ref::<Function>()
270 .ok_or_else(|| JsValue::from_str("checkHomeScreenStatus is not a function"))?;
271 func.call1(&self.inner, &cb)?;
272 Ok(())
273 }
274
275 pub async fn check_home_screen_status(&self) -> Result<String, JsValue> {
281 let webapp = self.inner.clone();
282 let promise = one_shot_promise(move |resolve, _reject| {
283 let cb = Closure::once_into_js(move |status: JsValue| {
284 let _ = resolve.call1(&JsValue::NULL, &status);
285 });
286 let f = Reflect::get(&webapp, &"checkHomeScreenStatus".into())?;
287 let func = f
288 .dyn_ref::<Function>()
289 .ok_or_else(|| JsValue::from_str("checkHomeScreenStatus is not a function"))?;
290 func.call1(&webapp, &cb)?;
291 Ok(())
292 });
293 let value = await_one_shot(promise).await?;
294 Ok(value.as_string().unwrap_or_default())
295 }
296}