Интеграция с фреймворками
Крейт поставляет опциональные интеграции для Leptos (фича
leptos) и Yew (фича yew). Обе предоставляют одни и те же
три реактивных хука и три компонента системных кнопок. Хуки инициализируются
текущими значениями и перерисовывают компонент, когда Telegram присылает события
viewportChanged, themeChanged, safeAreaChanged или
contentSafeAreaChanged. Подписки очищаются автоматически при размонтировании /
уничтожении скоупа.
Leptos
Предоставьте контекст один раз рядом с корнем, затем читайте через
use_context:
use leptos::prelude::*;
use telegram_webapp_sdk::{core::context::TelegramContext, leptos::provide_telegram_context};
#[component]
fn App() -> impl IntoView {
provide_telegram_context().expect("context");
let ctx = use_context::<TelegramContext>().expect("context");
view! { <span>{ ctx.init_data.auth_date }</span> }
}
Реактивные хуки
В Leptos хуки возвращают ReadSignal<T>, поэтому читайте их через .get()
внутри замыкания:
use leptos::prelude::*;
use telegram_webapp_sdk::leptos::{use_safe_area, use_theme, use_viewport};
#[component]
fn Status() -> impl IntoView {
let viewport = use_viewport(); // ReadSignal<ViewportState>
let theme = use_theme(); // ReadSignal<ThemeState>
let safe = use_safe_area(); // ReadSignal<SafeAreaState>
view! {
<div>
{ move || viewport.get().height }
{ move || theme.get().color_scheme.unwrap_or_default() }
{ move || safe.get().area.map(|i| i.top).unwrap_or(0.0) }
</div>
}
}
ViewportState содержит height, stable_height и is_expanded. ThemeState
содержит color_scheme: Option<String> и разобранную палитру params.
SafeAreaState содержит area и content как Option<SafeAreaInset>.
Компоненты
BottomButton принимает селектор button и реактивный text (и опциональные
color / text_color / on_click). BackButton и SettingsButton принимают
реактивный сигнал visible и опциональное замыкание on_click. Все три
управляют нативными кнопками Telegram и очищаются при размонтировании.
use leptos::prelude::*;
use telegram_webapp_sdk::{
leptos::{provide_telegram_context, BackButton, BottomButton, SettingsButton},
webapp::BottomButton as Btn,
};
#[component]
fn App() -> impl IntoView {
provide_telegram_context().expect("context");
let (text, _set_text) = signal("Отправить".to_owned());
let visible = RwSignal::new(true);
view! {
<BottomButton button=Btn::Main text on_click=move || { /* отправка */ } />
<BackButton visible=visible on_click=move || { /* назад */ } />
<SettingsButton visible=visible on_click=move || { /* настройки */ } />
}
}
Yew
Читайте контекст хуком use_telegram_context. Он возвращает
Result<TelegramContext, JsValue> и реактивно резолвится, как только контекст
инициализирован:
use telegram_webapp_sdk::yew::use_telegram_context;
use yew::prelude::*;
#[function_component(App)]
fn app() -> Html {
match use_telegram_context() {
Ok(ctx) => html! { <span>{ ctx.init_data.auth_date }</span> },
Err(_) => html! { <div>{ "Загрузка контекста Telegram..." }</div> },
}
}
Реактивные хуки
В Yew хуки возвращают значение состояния напрямую (не сигнал), поэтому читайте поля прямо с него:
use telegram_webapp_sdk::yew::{use_safe_area, use_theme, use_viewport};
use yew::prelude::*;
#[function_component(Status)]
fn status() -> Html {
let viewport = use_viewport(); // ViewportState
let theme = use_theme(); // ThemeState
let safe = use_safe_area(); // SafeAreaState
html! {
<div>
{ viewport.height }
{ theme.color_scheme.clone().unwrap_or_default() }
{ safe.area.map(|i| i.top).unwrap_or(0.0) }
</div>
}
}
Компоненты
Компоненты Yew принимают обычные пропсы: BottomButton использует text /
color / text_color / on_click (всегда управляет кнопкой Main), а
BackButton и SettingsButton принимают проп visible: bool и
on_click: Callback<()>.
use telegram_webapp_sdk::yew::{BackButton, BottomButton, SettingsButton};
use yew::prelude::*;
#[function_component(App)]
fn app() -> Html {
let on_main = Callback::from(|_| {});
let on_back = Callback::from(|_| {});
let on_settings = Callback::from(|_| {});
html! {
<>
<BottomButton text="Отправить" color="#000" text_color="#fff" on_click={on_main} />
<BackButton visible={true} on_click={on_back} />
<SettingsButton visible={true} on_click={on_settings} />
</>
}
}
См. также
- Быстрый старт — vanilla-подход без фреймворка
- Мок и тестирование — рендер компонентов против мока
- Примеры — запускаемое демо на Trunk