use std::{cell::RefCell, rc::Rc};
use wasm_bindgen::{JsCast, JsValue, closure::Closure};
use yew::prelude::{hook, use_effect, use_state};
use crate::core::{context::TelegramContext, safe_context::get_context};
pub mod bottom_button;
pub use bottom_button::BottomButton;
type ClosureCell = Rc<RefCell<Option<Closure<dyn FnMut()>>>>;
#[hook]
pub fn use_telegram_context() -> Result<TelegramContext, JsValue> {
let context_state = use_state(|| get_context(|c| c.clone()));
{
let context_state = context_state.clone();
use_effect(move || {
let handle: Rc<RefCell<Option<i32>>> = Rc::new(RefCell::new(None));
let closure: ClosureCell = Rc::new(RefCell::new(None));
if context_state.is_err()
&& let Some(win) = web_sys::window()
{
let handle_clone = handle.clone();
let closure_clone = closure.clone();
let ctx_state = context_state.clone();
let check_fn = Closure::wrap(Box::new(move || {
if let Ok(ctx) = get_context(|c| c.clone()) {
ctx_state.set(Ok(ctx));
if let Some(id) = handle_clone.borrow_mut().take()
&& let Some(w) = web_sys::window()
{
let _ = w.cancel_animation_frame(id);
}
closure_clone.borrow_mut().take();
} else if let Some(w) = web_sys::window()
&& let Some(cb) = closure_clone.borrow().as_ref()
&& let Ok(id) = w.request_animation_frame(cb.as_ref().unchecked_ref())
{
*handle_clone.borrow_mut() = Some(id);
}
}) as Box<dyn FnMut()>);
if let Ok(id) = win.request_animation_frame(check_fn.as_ref().unchecked_ref()) {
*handle.borrow_mut() = Some(id);
}
*closure.borrow_mut() = Some(check_fn);
}
let cleanup_handle = handle;
let cleanup_closure = closure;
move || {
if let Some(id) = cleanup_handle.borrow_mut().take()
&& let Some(w) = web_sys::window()
{
let _ = w.cancel_animation_frame(id);
}
cleanup_closure.borrow_mut().take();
}
});
}
(*context_state).clone()
}
#[cfg(test)]
mod tests {
#[cfg(target_arch = "wasm32")]
mod wasm {
use wasm_bindgen_test::{wasm_bindgen_test, wasm_bindgen_test_configure};
use yew::prelude::*;
use super::super::use_telegram_context;
use crate::core::{
context::TelegramContext,
types::{
init_data::TelegramInitData, theme_params::TelegramThemeParams, user::TelegramUser
}
};
wasm_bindgen_test_configure!(run_in_browser);
#[component]
fn TestComponent() -> Html {
let ctx_result = use_telegram_context();
match ctx_result.as_ref() {
Ok(ctx) => html! {
<div id="success">{ format!("auth_date: {}", ctx.init_data.auth_date) }</div>
},
Err(e) => html! {
<div id="error">{ format!("Error: {:?}", e) }</div>
}
}
}
#[wasm_bindgen_test]
fn hook_renders_component_with_context_result() {
if let Some(window) = web_sys::window() {
if let Some(document) = window.document() {
if let Ok(container) = document.create_element("div") {
yew::Renderer::<TestComponent>::with_root(container).render();
}
}
}
}
#[wasm_bindgen_test]
fn hook_works_with_initialized_context() {
let init_data = TelegramInitData {
query_id: Some(String::from("test_query_2")),
user: Some(TelegramUser {
id: 987654321,
is_bot: Some(false),
first_name: String::from("Test2"),
last_name: Some(String::from("User2")),
username: Some(String::from("testuser2")),
language_code: Some(String::from("en")),
is_premium: Some(false),
added_to_attachment_menu: Some(false),
allows_write_to_pm: Some(true),
photo_url: None
}),
receiver: None,
chat: None,
chat_type: None,
chat_instance: None,
start_param: None,
can_send_after: None,
auth_date: 9876543210,
hash: String::from("test_hash_2"),
signature: None
};
let theme_params = TelegramThemeParams {
bg_color: Some(String::from("#000000")),
text_color: Some(String::from("#ffffff")),
hint_color: Some(String::from("#666666")),
link_color: Some(String::from("#00aaff")),
button_color: Some(String::from("#00aaff")),
button_text_color: Some(String::from("#000000")),
secondary_bg_color: Some(String::from("#1a1a1a")),
header_bg_color: None,
bottom_bar_bg_color: None,
accent_text_color: None,
section_bg_color: None,
section_header_text_color: None,
section_separator_color: None,
subtitle_text_color: None,
destructive_text_color: None
};
let raw_init_data = String::from(
"query_id=test_query_2&user=%7B%22id%22%3A987654321%7D&auth_date=9876543210&hash=test_hash_2"
);
let _ = TelegramContext::init(init_data, theme_params, raw_init_data);
if let Some(window) = web_sys::window() {
if let Some(document) = window.document() {
if let Ok(container) = document.create_element("div") {
yew::Renderer::<TestComponent>::with_root(container).render();
}
}
}
}
}
}