use js_sys::{Function, Reflect};
use serde_wasm_bindgen::to_value;
use wasm_bindgen::{JsCast, JsValue, prelude::Closure};
use crate::{
core::types::download_file_params::DownloadFileParams,
webapp::{
TelegramWebApp,
core::{await_one_shot, one_shot_promise}
}
};
impl TelegramWebApp {
pub fn request_write_access_with_callback<F>(&self, callback: F) -> Result<(), JsValue>
where
F: 'static + FnOnce(bool)
{
let cb = Closure::once_into_js(move |v: JsValue| {
callback(v.as_bool().unwrap_or(false));
});
self.call1("requestWriteAccess", &cb)
}
pub async fn request_write_access(&self) -> Result<bool, JsValue> {
let webapp = self.inner.clone();
let promise = one_shot_promise(move |resolve, _reject| {
let cb = Closure::once_into_js(move |granted: JsValue| {
let _ = resolve.call1(&JsValue::NULL, &granted);
});
let f = Reflect::get(&webapp, &"requestWriteAccess".into())?;
let func = f
.dyn_ref::<Function>()
.ok_or_else(|| JsValue::from_str("requestWriteAccess is not a function"))?;
func.call1(&webapp, &cb)?;
Ok(())
});
let value = await_one_shot(promise).await?;
Ok(value.as_bool().unwrap_or(false))
}
pub fn request_emoji_status_access_with_callback<F>(&self, callback: F) -> Result<(), JsValue>
where
F: 'static + FnOnce(bool)
{
let cb = Closure::once_into_js(move |v: JsValue| {
callback(v.as_bool().unwrap_or(false));
});
let f = Reflect::get(&self.inner, &"requestEmojiStatusAccess".into())?;
let func = f
.dyn_ref::<Function>()
.ok_or_else(|| JsValue::from_str("requestEmojiStatusAccess is not a function"))?;
func.call1(&self.inner, &cb)?;
Ok(())
}
pub async fn request_emoji_status_access(&self) -> Result<bool, JsValue> {
let webapp = self.inner.clone();
let promise = one_shot_promise(move |resolve, _reject| {
let cb = Closure::once_into_js(move |granted: JsValue| {
let _ = resolve.call1(&JsValue::NULL, &granted);
});
let f = Reflect::get(&webapp, &"requestEmojiStatusAccess".into())?;
let func = f
.dyn_ref::<Function>()
.ok_or_else(|| JsValue::from_str("requestEmojiStatusAccess is not a function"))?;
func.call1(&webapp, &cb)?;
Ok(())
});
let value = await_one_shot(promise).await?;
Ok(value.as_bool().unwrap_or(false))
}
pub fn set_emoji_status_with_callback<F>(
&self,
status: &JsValue,
callback: F
) -> Result<(), JsValue>
where
F: 'static + FnOnce(bool)
{
let cb = Closure::once_into_js(move |v: JsValue| {
callback(v.as_bool().unwrap_or(false));
});
let f = Reflect::get(&self.inner, &"setEmojiStatus".into())?;
let func = f
.dyn_ref::<Function>()
.ok_or_else(|| JsValue::from_str("setEmojiStatus is not a function"))?;
func.call2(&self.inner, status, &cb)?;
Ok(())
}
pub async fn set_emoji_status(&self, status: &JsValue) -> Result<bool, JsValue> {
let webapp = self.inner.clone();
let status = status.clone();
let promise = one_shot_promise(move |resolve, _reject| {
let cb = Closure::once_into_js(move |v: JsValue| {
let _ = resolve.call1(&JsValue::NULL, &v);
});
let f = Reflect::get(&webapp, &"setEmojiStatus".into())?;
let func = f
.dyn_ref::<Function>()
.ok_or_else(|| JsValue::from_str("setEmojiStatus is not a function"))?;
func.call2(&webapp, &status, &cb)?;
Ok(())
});
let value = await_one_shot(promise).await?;
Ok(value.as_bool().unwrap_or(false))
}
pub fn open_invoice_with_callback<F>(&self, url: &str, callback: F) -> Result<(), JsValue>
where
F: 'static + FnOnce(String)
{
let cb = Closure::once_into_js(move |status: JsValue| {
callback(status.as_string().unwrap_or_default());
});
Reflect::get(&self.inner, &"openInvoice".into())?
.dyn_into::<Function>()?
.call2(&self.inner, &url.into(), &cb)?;
Ok(())
}
pub async fn open_invoice(&self, url: &str) -> Result<String, JsValue> {
let webapp = self.inner.clone();
let url = url.to_owned();
let promise = one_shot_promise(move |resolve, _reject| {
let cb = Closure::once_into_js(move |status: JsValue| {
let _ = resolve.call1(&JsValue::NULL, &status);
});
Reflect::get(&webapp, &"openInvoice".into())?
.dyn_into::<Function>()?
.call2(&webapp, &url.into(), &cb)?;
Ok(())
});
let value = await_one_shot(promise).await?;
Ok(value.as_string().unwrap_or_default())
}
pub fn download_file_with_callback<F>(
&self,
params: DownloadFileParams<'_>,
callback: F
) -> Result<(), JsValue>
where
F: 'static + FnOnce(String)
{
let js_params =
to_value(¶ms).map_err(|e| JsValue::from_str(&format!("serialize params: {e}")))?;
let cb = Closure::once_into_js(move |v: JsValue| {
callback(v.as_string().unwrap_or_default());
});
Reflect::get(&self.inner, &"downloadFile".into())?
.dyn_into::<Function>()?
.call2(&self.inner, &js_params, &cb)?;
Ok(())
}
pub async fn download_file(&self, params: DownloadFileParams<'_>) -> Result<String, JsValue> {
let js_params =
to_value(¶ms).map_err(|e| JsValue::from_str(&format!("serialize params: {e}")))?;
let webapp = self.inner.clone();
let promise = one_shot_promise(move |resolve, _reject| {
let cb = Closure::once_into_js(move |v: JsValue| {
let _ = resolve.call1(&JsValue::NULL, &v);
});
Reflect::get(&webapp, &"downloadFile".into())?
.dyn_into::<Function>()?
.call2(&webapp, &js_params, &cb)?;
Ok(())
});
let value = await_one_shot(promise).await?;
Ok(value.as_string().unwrap_or_default())
}
pub fn read_text_from_clipboard_with_callback<F>(&self, callback: F) -> Result<(), JsValue>
where
F: 'static + FnOnce(String)
{
let cb = Closure::once_into_js(move |text: JsValue| {
callback(text.as_string().unwrap_or_default());
});
let f = Reflect::get(&self.inner, &"readTextFromClipboard".into())?;
let func = f
.dyn_ref::<Function>()
.ok_or_else(|| JsValue::from_str("readTextFromClipboard is not a function"))?;
func.call1(&self.inner, &cb)?;
Ok(())
}
pub async fn read_text_from_clipboard(&self) -> Result<String, JsValue> {
let webapp = self.inner.clone();
let promise = one_shot_promise(move |resolve, _reject| {
let cb = Closure::once_into_js(move |text: JsValue| {
let _ = resolve.call1(&JsValue::NULL, &text);
});
let f = Reflect::get(&webapp, &"readTextFromClipboard".into())?;
let func = f
.dyn_ref::<Function>()
.ok_or_else(|| JsValue::from_str("readTextFromClipboard is not a function"))?;
func.call1(&webapp, &cb)?;
Ok(())
});
let value = await_one_shot(promise).await?;
Ok(value.as_string().unwrap_or_default())
}
}