Skip to main content

telegram_webapp_sdk/yew/
settings_button.rs

1// SPDX-FileCopyrightText: 2025-2026 RAprogramm <andrey.rozanov.vl@gmail.com>
2// SPDX-License-Identifier: MIT
3
4use std::cell::RefCell;
5
6use yew::prelude::{Callback, Html, Properties, function_component, html, use_effect_with};
7
8use crate::{
9    logger,
10    webapp::{EventHandle, TelegramWebApp}
11};
12
13thread_local! {
14    static SETTINGS_BUTTON_HANDLE: RefCell<Option<EventHandle<dyn FnMut()>>> =
15        const { RefCell::new(None) };
16}
17
18/// Props for [`SettingsButton`].
19#[derive(Properties, PartialEq)]
20pub struct SettingsButtonProps {
21    /// Whether the native settings button is shown.
22    #[prop_or(true)]
23    pub visible:  bool,
24    /// Click handler.
25    #[prop_or_default]
26    pub on_click: Callback<()>
27}
28
29/// Yew component for the native settings button.
30///
31/// Shows or hides `WebApp.SettingsButton` based on the `visible` prop and
32/// routes clicks through the `on_click` callback. The subscription is removed
33/// and the button hidden on unmount.
34#[function_component(SettingsButton)]
35pub fn settings_button(props: &SettingsButtonProps) -> Html {
36    let visible = props.visible;
37    let on_click = props.on_click.clone();
38
39    use_effect_with(visible, move |&v| {
40        if let Some(app) = TelegramWebApp::instance() {
41            let result = if v {
42                app.show_settings_button()
43            } else {
44                app.hide_settings_button()
45            };
46            if let Err(err) = result {
47                logger::error(&format!("SettingsButton visibility toggle failed: {err:?}"));
48            }
49        }
50        || ()
51    });
52
53    use_effect_with((), move |()| {
54        if let Some(app) = TelegramWebApp::instance() {
55            match app.set_settings_button_callback(move || on_click.emit(())) {
56                Ok(handle) => SETTINGS_BUTTON_HANDLE.with(|c| {
57                    *c.borrow_mut() = Some(handle);
58                }),
59                Err(err) => logger::error(&format!("set_settings_button_callback failed: {err:?}"))
60            }
61        }
62        || {
63            if let Some(app) = TelegramWebApp::instance() {
64                SETTINGS_BUTTON_HANDLE.with(|c| {
65                    if let Some(handle) = c.borrow_mut().take()
66                        && let Err(err) = app.remove_settings_button_callback(handle)
67                    {
68                        logger::error(&format!("remove_settings_button_callback failed: {err:?}"));
69                    }
70                });
71                if let Err(err) = app.hide_settings_button() {
72                    logger::error(&format!("hide_settings_button failed: {err:?}"));
73                }
74            }
75        }
76    });
77
78    html! {}
79}