checkbox_list/
checkbox_list.rs

1/*
2    This example demonstrates how to use the `CheckboxList` widget.
3*/
4use derive_more::Display;
5use serde::{Deserialize, Serialize};
6use teloxide::{dispatching::dialogue::InMemStorage, prelude::*, types::InlineKeyboardMarkup};
7use teloxide_inline_widgets::prelude::*;
8
9type Bot = teloxide::Bot;
10type Error = Box<dyn std::error::Error + Send + Sync + 'static>;
11type HandlerResult = Result<(), Error>;
12type UpdateHandler = teloxide::dispatching::UpdateHandler<Error>;
13type Storage = InMemStorage<State>;
14type Dialogue = teloxide::dispatching::dialogue::Dialogue<State, Storage>;
15
16type OptionsCheckboxList = CheckboxList<Options, OptionsCLS>;
17
18#[derive(Debug, Default, Clone, Deserialize, Serialize)]
19enum State {
20    #[default]
21    Idle,
22    EditingWidget(Widget),
23}
24
25#[derive(Debug, Clone, Deserialize, Serialize)]
26struct Widget {
27    pub options: OptionsCheckboxList,
28}
29
30#[derive(Debug, Display, Clone, Deserialize, Serialize)]
31enum Options {
32    A,
33    B,
34    C,
35}
36
37#[derive(Debug, Clone, Copy, Deserialize, Serialize)]
38pub struct OptionsCLS;
39
40impl CheckboxListSettings for OptionsCLS {
41    fn prefix() -> &'static str {
42        "o_"
43    }
44
45    fn size() -> (u8, u8) {
46        // Try to change it to (1, 3)
47        (3, 1)
48    }
49}
50
51impl UserDefinedWidget for Widget {
52    type Err = Error;
53    type Bot = Bot;
54    type Dialogue = Dialogue;
55
56    fn schema() -> UpdateHandler {
57        dptree::entry().branch(OptionsCheckboxList::schema::<Self>())
58    }
59
60    fn inline_keyboard_markup(&self) -> InlineKeyboardMarkup {
61        InlineKeyboardMarkup::new(self.options.keyboard())
62    }
63
64    async fn update_state(self, dialogue: &Self::Dialogue) -> Result<(), Self::Err> {
65        dialogue.update(State::EditingWidget(self)).await?;
66
67        Ok(())
68    }
69}
70
71impl WidgetContainer<OptionsCheckboxList> for Widget {
72    fn get_widget(&mut self) -> &mut OptionsCheckboxList {
73        &mut self.options
74    }
75}
76
77#[tokio::main]
78async fn main() {
79    pretty_env_logger::init();
80
81    log::info!("Example \"checkbox_list\" started..");
82
83    let state_storage = InMemStorage::<State>::new();
84
85    Dispatcher::builder(Bot::from_env(), schema())
86        .dependencies(dptree::deps![state_storage])
87        .build()
88        .dispatch()
89        .await;
90}
91
92fn schema() -> UpdateHandler {
93    dptree::entry()
94        .branch(
95            Update::filter_message()
96                .enter_dialogue::<Message, Storage, State>()
97                .endpoint(send_widget),
98        )
99        .branch(
100            Update::filter_callback_query()
101                .enter_dialogue::<CallbackQuery, Storage, State>()
102                .branch(dptree::case![State::EditingWidget(_w)].branch(Widget::schema())),
103        )
104}
105
106async fn send_widget(bot: Bot, dialogue: Dialogue, message: Message) -> HandlerResult {
107    let options = CheckboxList::new([Options::A, Options::B, Options::C]);
108
109    let widget = Widget { options };
110
111    bot.send_message(message.chat.id, "Choose options:")
112        .reply_markup(widget.inline_keyboard_markup())
113        .await?;
114
115    dialogue.update(State::EditingWidget(widget)).await?;
116
117    Ok(())
118}