Current section
Files
Jump to
Current section
Files
src/telega@menu_builder.erl
-module(telega@menu_builder).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/telega/menu_builder.gleam").
-export([new/1, new_stateful/2, title/2, add_item/3, add_disabled_item/3, section/2, layout/4, paginate/3, paginate_with_text/6, with_back_button/2, with_back_button_text/3, with_home_button/2, with_home_button_text/3, on_action/3, build/1, add_items_from_list/3, add_stateful_items/3, add_submenu/3, add_toggle/4, to_keyboard/1, handle_action/2, get_state/1, update_state/2, get_callback_data/1, get_title/1, confirmation/6, settings_menu/3]).
-export_type([menu_item/0, menu_section/0, pagination_config/0, menu_layout/0, navigation_config/0, menu_state/1, menu/1, menu_builder/1]).
-if(?OTP_RELEASE >= 27).
-define(MODULEDOC(Str), -moduledoc(Str)).
-define(DOC(Str), -doc(Str)).
-else.
-define(MODULEDOC(Str), -compile([])).
-define(DOC(Str), -compile([])).
-endif.
?MODULEDOC(
" # Menu Builder Module\n"
"\n"
" This module provides an advanced menu system for Telegram bots, extending beyond basic keyboards\n"
" to create rich, interactive menu experiences with state management, navigation, and pagination.\n"
"\n"
" ## Key Features\n"
"\n"
" - **Stateful Menus**: Menus that maintain state across interactions\n"
" - **Navigation System**: Back/forward navigation with breadcrumbs\n"
" - **Pagination**: Built-in pagination for large datasets\n"
" - **Dynamic Menus**: Menus that update based on data changes\n"
" - **Context Actions**: Actions that can modify menu state\n"
" - **Nested Menus**: Support for hierarchical menu structures\n"
"\n"
" ## Quick Start\n"
"\n"
" ### Simple Menu\n"
" ```gleam\n"
" let menu = menu_builder.new(\"main_menu\")\n"
" |> menu_builder.title(\"🏠 Main Menu\")\n"
" |> menu_builder.add_item(\"📋 View Items\", \"view_items\")\n"
" |> menu_builder.add_item(\"➕ Add Item\", \"add_item\")\n"
" |> menu_builder.add_item(\"⚙️ Settings\", \"settings\")\n"
" |> menu_builder.build()\n"
" ```\n"
"\n"
" ### Paginated Menu\n"
" ```gleam\n"
" let items = [\"Item 1\", \"Item 2\", \"Item 3\", ..., \"Item 100\"]\n"
" let menu = menu_builder.new(\"item_list\")\n"
" |> menu_builder.title(\"📋 Items\")\n"
" |> menu_builder.paginate(items, page: 1, items_per_page: 10)\n"
" |> menu_builder.with_back_button(\"main_menu\")\n"
" |> menu_builder.build()\n"
" ```\n"
"\n"
" ### Stateful Menu with Actions\n"
" ```gleam\n"
" pub type MenuState {\n"
" MenuState(items: List(String), selected: Option(Int))\n"
" }\n"
"\n"
" let menu = menu_builder.new_stateful(\"item_selector\", initial_state)\n"
" |> menu_builder.title(\"Select an Item\")\n"
" |> menu_builder.add_stateful_items(state.items, fn(item, index) {\n"
" let selected = case state.selected {\n"
" Some(i) if i == index -> \"✅ \"\n"
" _ -> \"\"\n"
" }\n"
" #(selected <> item, \"select:\" <> int.to_string(index))\n"
" })\n"
" |> menu_builder.on_action(\"select\", fn(state, data) {\n"
" let index = int.parse(data) |> result.unwrap(0)\n"
" MenuState(..state, selected: Some(index))\n"
" })\n"
" |> menu_builder.build()\n"
" ```\n"
).
-type menu_item() :: {menu_item, binary(), binary(), boolean()}.
-type menu_section() :: {menu_section,
gleam@option:option(binary()),
list(menu_item())}.
-type pagination_config() :: {pagination_config,
integer(),
boolean(),
binary(),
binary(),
binary()}.
-type menu_layout() :: {menu_layout,
integer(),
gleam@option:option(integer()),
boolean()}.
-type navigation_config() :: {navigation_config,
gleam@option:option(binary()),
binary(),
gleam@option:option(binary()),
binary(),
boolean()}.
-type menu_state(BBQU) :: {menu_state,
binary(),
BBQU,
integer(),
list(binary()),
gleam@dict:dict(binary(), binary())}.
-opaque menu(BBQV) :: {menu,
binary(),
gleam@option:option(binary()),
list(menu_section()),
menu_layout(),
gleam@option:option(pagination_config()),
navigation_config(),
gleam@option:option(menu_state(BBQV)),
gleam@dict:dict(binary(), fun((menu_state(BBQV), binary()) -> menu_state(BBQV))),
telega@keyboard:keyboard_callback_data(binary())}.
-opaque menu_builder(BBQW) :: {menu_builder,
binary(),
gleam@option:option(binary()),
list(menu_section()),
menu_section(),
menu_layout(),
gleam@option:option(pagination_config()),
navigation_config(),
gleam@option:option(menu_state(BBQW)),
gleam@dict:dict(binary(), fun((menu_state(BBQW), binary()) -> menu_state(BBQW)))}.
-file("src/telega/menu_builder.gleam", 159).
?DOC(" Create a new stateless menu builder\n").
-spec new(binary()) -> menu_builder(nil).
new(Id) ->
{menu_builder,
Id,
none,
[],
{menu_section, none, []},
{menu_layout, 1, none, true},
none,
{navigation_config, none, <<""/utf8>>, none, <<""/utf8>>, false},
none,
maps:new()}.
-file("src/telega/menu_builder.gleam", 184).
?DOC(" Create a new stateful menu builder\n").
-spec new_stateful(binary(), BBRB) -> menu_builder(BBRB).
new_stateful(Id, Initial_state) ->
State = {menu_state, Id, Initial_state, 1, [], maps:new()},
{menu_builder,
Id,
none,
[],
{menu_section, none, []},
{menu_layout, 1, none, true},
none,
{navigation_config, none, <<""/utf8>>, none, <<""/utf8>>, false},
{some, State},
maps:new()}.
-file("src/telega/menu_builder.gleam", 218).
?DOC(" Set the menu title\n").
-spec title(menu_builder(BBRD), binary()) -> menu_builder(BBRD).
title(Builder, Title) ->
{menu_builder,
erlang:element(2, Builder),
{some, Title},
erlang:element(4, Builder),
erlang:element(5, Builder),
erlang:element(6, Builder),
erlang:element(7, Builder),
erlang:element(8, Builder),
erlang:element(9, Builder),
erlang:element(10, Builder)}.
-file("src/telega/menu_builder.gleam", 223).
?DOC(" Add a simple menu item\n").
-spec add_item(menu_builder(BBRG), binary(), binary()) -> menu_builder(BBRG).
add_item(Builder, Text, Action) ->
Item = {menu_item, Text, Action, true},
Updated_section = begin
_record = erlang:element(5, Builder),
{menu_section,
erlang:element(2, _record),
[Item | erlang:element(3, erlang:element(5, Builder))]}
end,
{menu_builder,
erlang:element(2, Builder),
erlang:element(3, Builder),
erlang:element(4, Builder),
Updated_section,
erlang:element(6, Builder),
erlang:element(7, Builder),
erlang:element(8, Builder),
erlang:element(9, Builder),
erlang:element(10, Builder)}.
-file("src/telega/menu_builder.gleam", 238).
?DOC(" Add a disabled menu item\n").
-spec add_disabled_item(menu_builder(BBRJ), binary(), binary()) -> menu_builder(BBRJ).
add_disabled_item(Builder, Text, Action) ->
Item = {menu_item, Text, Action, false},
Updated_section = begin
_record = erlang:element(5, Builder),
{menu_section,
erlang:element(2, _record),
[Item | erlang:element(3, erlang:element(5, Builder))]}
end,
{menu_builder,
erlang:element(2, Builder),
erlang:element(3, Builder),
erlang:element(4, Builder),
Updated_section,
erlang:element(6, Builder),
erlang:element(7, Builder),
erlang:element(8, Builder),
erlang:element(9, Builder),
erlang:element(10, Builder)}.
-file("src/telega/menu_builder.gleam", 253).
?DOC(" Start a new section with optional title\n").
-spec section(menu_builder(BBRM), gleam@option:option(binary())) -> menu_builder(BBRM).
section(Builder, Title) ->
Current_section = begin
_record = erlang:element(5, Builder),
{menu_section,
erlang:element(2, _record),
lists:reverse(erlang:element(3, erlang:element(5, Builder)))}
end,
New_section = {menu_section, Title, []},
{menu_builder,
erlang:element(2, Builder),
erlang:element(3, Builder),
[Current_section | erlang:element(4, Builder)],
New_section,
erlang:element(6, Builder),
erlang:element(7, Builder),
erlang:element(8, Builder),
erlang:element(9, Builder),
erlang:element(10, Builder)}.
-file("src/telega/menu_builder.gleam", 272).
?DOC(" Configure menu layout\n").
-spec layout(
menu_builder(BBRQ),
integer(),
gleam@option:option(integer()),
boolean()
) -> menu_builder(BBRQ).
layout(Builder, Columns, Max_rows_per_section, Section_separator) ->
Layout = {menu_layout, Columns, Max_rows_per_section, Section_separator},
{menu_builder,
erlang:element(2, Builder),
erlang:element(3, Builder),
erlang:element(4, Builder),
erlang:element(5, Builder),
Layout,
erlang:element(7, Builder),
erlang:element(8, Builder),
erlang:element(9, Builder),
erlang:element(10, Builder)}.
-file("src/telega/menu_builder.gleam", 288).
?DOC(" Configure pagination\n").
-spec paginate(menu_builder(BBRU), integer(), boolean()) -> menu_builder(BBRU).
paginate(Builder, Items_per_page, Show_page_info) ->
Pagination = {pagination_config,
Items_per_page,
Show_page_info,
<<""/utf8>>,
<<""/utf8>>,
<<"{current}/{total}"/utf8>>},
{menu_builder,
erlang:element(2, Builder),
erlang:element(3, Builder),
erlang:element(4, Builder),
erlang:element(5, Builder),
erlang:element(6, Builder),
{some, Pagination},
erlang:element(8, Builder),
erlang:element(9, Builder),
erlang:element(10, Builder)}.
-file("src/telega/menu_builder.gleam", 305).
?DOC(" Configure pagination with custom texts\n").
-spec paginate_with_text(
menu_builder(BBRX),
integer(),
boolean(),
binary(),
binary(),
binary()
) -> menu_builder(BBRX).
paginate_with_text(
Builder,
Items_per_page,
Show_page_info,
Prev_text,
Next_text,
Page_info_template
) ->
Pagination = {pagination_config,
Items_per_page,
Show_page_info,
Prev_text,
Next_text,
Page_info_template},
{menu_builder,
erlang:element(2, Builder),
erlang:element(3, Builder),
erlang:element(4, Builder),
erlang:element(5, Builder),
erlang:element(6, Builder),
{some, Pagination},
erlang:element(8, Builder),
erlang:element(9, Builder),
erlang:element(10, Builder)}.
-file("src/telega/menu_builder.gleam", 325).
?DOC(" Add back button navigation\n").
-spec with_back_button(menu_builder(BBSA), binary()) -> menu_builder(BBSA).
with_back_button(Builder, Back_action) ->
Navigation = begin
_record = erlang:element(8, Builder),
{navigation_config,
{some, Back_action},
erlang:element(3, _record),
erlang:element(4, _record),
erlang:element(5, _record),
erlang:element(6, _record)}
end,
{menu_builder,
erlang:element(2, Builder),
erlang:element(3, Builder),
erlang:element(4, Builder),
erlang:element(5, Builder),
erlang:element(6, Builder),
erlang:element(7, Builder),
Navigation,
erlang:element(9, Builder),
erlang:element(10, Builder)}.
-file("src/telega/menu_builder.gleam", 335).
?DOC(" Add back button navigation with custom text\n").
-spec with_back_button_text(menu_builder(BBSD), binary(), binary()) -> menu_builder(BBSD).
with_back_button_text(Builder, Back_action, Back_text) ->
Navigation = begin
_record = erlang:element(8, Builder),
{navigation_config,
{some, Back_action},
Back_text,
erlang:element(4, _record),
erlang:element(5, _record),
erlang:element(6, _record)}
end,
{menu_builder,
erlang:element(2, Builder),
erlang:element(3, Builder),
erlang:element(4, Builder),
erlang:element(5, Builder),
erlang:element(6, Builder),
erlang:element(7, Builder),
Navigation,
erlang:element(9, Builder),
erlang:element(10, Builder)}.
-file("src/telega/menu_builder.gleam", 350).
?DOC(" Add home button navigation\n").
-spec with_home_button(menu_builder(BBSG), binary()) -> menu_builder(BBSG).
with_home_button(Builder, Home_action) ->
Navigation = begin
_record = erlang:element(8, Builder),
{navigation_config,
erlang:element(2, _record),
erlang:element(3, _record),
{some, Home_action},
erlang:element(5, _record),
erlang:element(6, _record)}
end,
{menu_builder,
erlang:element(2, Builder),
erlang:element(3, Builder),
erlang:element(4, Builder),
erlang:element(5, Builder),
erlang:element(6, Builder),
erlang:element(7, Builder),
Navigation,
erlang:element(9, Builder),
erlang:element(10, Builder)}.
-file("src/telega/menu_builder.gleam", 360).
?DOC(" Add home button navigation with custom text\n").
-spec with_home_button_text(menu_builder(BBSJ), binary(), binary()) -> menu_builder(BBSJ).
with_home_button_text(Builder, Home_action, Home_text) ->
Navigation = begin
_record = erlang:element(8, Builder),
{navigation_config,
erlang:element(2, _record),
erlang:element(3, _record),
{some, Home_action},
Home_text,
erlang:element(6, _record)}
end,
{menu_builder,
erlang:element(2, Builder),
erlang:element(3, Builder),
erlang:element(4, Builder),
erlang:element(5, Builder),
erlang:element(6, Builder),
erlang:element(7, Builder),
Navigation,
erlang:element(9, Builder),
erlang:element(10, Builder)}.
-file("src/telega/menu_builder.gleam", 375).
?DOC(" Register an action handler for stateful menus\n").
-spec on_action(
menu_builder(BBSM),
binary(),
fun((menu_state(BBSM), binary()) -> menu_state(BBSM))
) -> menu_builder(BBSM).
on_action(Builder, Action_name, Handler) ->
Actions = gleam@dict:insert(
erlang:element(10, Builder),
Action_name,
Handler
),
{menu_builder,
erlang:element(2, Builder),
erlang:element(3, Builder),
erlang:element(4, Builder),
erlang:element(5, Builder),
erlang:element(6, Builder),
erlang:element(7, Builder),
erlang:element(8, Builder),
erlang:element(9, Builder),
Actions}.
-file("src/telega/menu_builder.gleam", 385).
?DOC(" Build the final menu\n").
-spec build(menu_builder(BBSQ)) -> menu(BBSQ).
build(Builder) ->
Current_section = begin
_record = erlang:element(5, Builder),
{menu_section,
erlang:element(2, _record),
lists:reverse(erlang:element(3, erlang:element(5, Builder)))}
end,
All_sections = case erlang:element(3, Current_section) of
[] ->
lists:reverse(erlang:element(4, Builder));
_ ->
lists:reverse([Current_section | erlang:element(4, Builder)])
end,
Callback_data = telega@keyboard:string_callback_data(
<<"menu:"/utf8, (erlang:element(2, Builder))/binary>>
),
{menu,
erlang:element(2, Builder),
erlang:element(3, Builder),
All_sections,
erlang:element(6, Builder),
erlang:element(7, Builder),
erlang:element(8, Builder),
erlang:element(9, Builder),
erlang:element(10, Builder),
Callback_data}.
-file("src/telega/menu_builder.gleam", 412).
?DOC(" Add multiple items from a list with custom formatting\n").
-spec add_items_from_list(
menu_builder(BBST),
list(BBSV),
fun((BBSV, integer()) -> {binary(), binary()})
) -> menu_builder(BBST).
add_items_from_list(Builder, Items, Formatter) ->
gleam@list:index_fold(
Items,
Builder,
fun(Builder@1, Item, Index) ->
{Text, Action} = Formatter(Item, Index),
add_item(Builder@1, Text, Action)
end
).
-file("src/telega/menu_builder.gleam", 423).
?DOC(" Add items for stateful menus that can access state\n").
-spec add_stateful_items(
menu_builder(BBSY),
list(BBTA),
fun((BBTA, integer(), BBSY) -> {binary(), binary(), boolean()})
) -> menu_builder(BBSY).
add_stateful_items(Builder, Items, Formatter) ->
case erlang:element(9, Builder) of
none ->
Builder;
{some, Menu_state} ->
gleam@list:index_fold(
Items,
Builder,
fun(Builder@1, Item, Index) ->
{Text, Action, Enabled} = Formatter(
Item,
Index,
erlang:element(3, Menu_state)
),
case Enabled of
true ->
add_item(Builder@1, Text, Action);
false ->
add_disabled_item(Builder@1, Text, Action)
end
end
)
end.
-file("src/telega/menu_builder.gleam", 442).
?DOC(" Create a submenu item that navigates to another menu\n").
-spec add_submenu(menu_builder(BBTD), binary(), binary()) -> menu_builder(BBTD).
add_submenu(Builder, Text, Submenu_id) ->
add_item(Builder, Text, <<"nav:"/utf8, Submenu_id/binary>>).
-file("src/telega/menu_builder.gleam", 451).
?DOC(" Create a toggle item for boolean settings\n").
-spec add_toggle(menu_builder(BBTG), binary(), binary(), boolean()) -> menu_builder(BBTG).
add_toggle(Builder, Text_template, Action, Current_value) ->
Status = case Current_value of
true ->
<<"✅"/utf8>>;
false ->
<<"❌"/utf8>>
end,
Text = gleam@string:replace(Text_template, <<"{status}"/utf8>>, Status),
add_item(Builder, Text, Action).
-file("src/telega/menu_builder.gleam", 551).
-spec build_pagination_buttons(menu(any()), pagination_config(), integer()) -> list(telega@model@types:inline_keyboard_button()).
build_pagination_buttons(Menu, Config, Current_page) ->
All_items = gleam@list:flat_map(
erlang:element(4, Menu),
fun(Section) -> erlang:element(3, Section) end
),
Total_items = erlang:length(All_items),
Total_pages = case Total_items of
0 ->
1;
_ ->
case erlang:element(2, Config) of
0 -> 0;
Gleam@denominator -> ((Total_items + erlang:element(2, Config))
- 1)
div Gleam@denominator
end
end,
Buttons = [],
Buttons@1 = case Current_page > 1 of
true ->
Action = <<"page:"/utf8,
(erlang:integer_to_binary(Current_page - 1))/binary>>,
Callback = telega@keyboard:pack_callback(
erlang:element(10, Menu),
Action
),
case telega@keyboard:inline_button(
erlang:element(4, Config),
Callback
) of
{ok, Button} ->
[Button | Buttons];
{error, _} ->
Buttons
end;
false ->
Buttons
end,
Buttons@2 = case erlang:element(3, Config) of
true ->
Page_info = begin
_pipe = erlang:element(6, Config),
_pipe@1 = gleam@string:replace(
_pipe,
<<"{current}"/utf8>>,
erlang:integer_to_binary(Current_page)
),
gleam@string:replace(
_pipe@1,
<<"{total}"/utf8>>,
erlang:integer_to_binary(Total_pages)
)
end,
Info_button = telega@keyboard:inline_copy_text_button(
Page_info,
Page_info
),
[Info_button | Buttons@1];
false ->
Buttons@1
end,
Buttons@3 = case Current_page < Total_pages of
true ->
Action@1 = <<"page:"/utf8,
(erlang:integer_to_binary(Current_page + 1))/binary>>,
Callback@1 = telega@keyboard:pack_callback(
erlang:element(10, Menu),
Action@1
),
case telega@keyboard:inline_button(
erlang:element(5, Config),
Callback@1
) of
{ok, Button@1} ->
[Button@1 | Buttons@2];
{error, _} ->
Buttons@2
end;
false ->
Buttons@2
end,
lists:reverse(Buttons@3).
-file("src/telega/menu_builder.gleam", 520).
-spec build_navigation_buttons(menu(any()), integer()) -> list(telega@model@types:inline_keyboard_button()).
build_navigation_buttons(Menu, _) ->
Nav_buttons = [],
Nav_buttons@1 = case erlang:element(2, erlang:element(7, Menu)) of
{some, Action} ->
Callback = telega@keyboard:pack_callback(
erlang:element(10, Menu),
Action
),
case telega@keyboard:inline_button(
erlang:element(3, erlang:element(7, Menu)),
Callback
) of
{ok, Button} ->
[Button | Nav_buttons];
{error, _} ->
Nav_buttons
end;
none ->
Nav_buttons
end,
Nav_buttons@2 = case erlang:element(4, erlang:element(7, Menu)) of
{some, Action@1} ->
Callback@1 = telega@keyboard:pack_callback(
erlang:element(10, Menu),
Action@1
),
case telega@keyboard:inline_button(
erlang:element(5, erlang:element(7, Menu)),
Callback@1
) of
{ok, Button@1} ->
[Button@1 | Nav_buttons@1];
{error, _} ->
Nav_buttons@1
end;
none ->
Nav_buttons@1
end,
lists:reverse(Nav_buttons@2).
-file("src/telega/menu_builder.gleam", 491).
-spec build_main_buttons(menu(any()), integer()) -> {ok,
list(telega@model@types:inline_keyboard_button())} |
{error, binary()}.
build_main_buttons(Menu, Current_page) ->
All_items = gleam@list:flat_map(
erlang:element(4, Menu),
fun(Section) -> erlang:element(3, Section) end
),
Items_to_show = case erlang:element(6, Menu) of
{some, Config} ->
Start_index = (Current_page - 1) * erlang:element(2, Config),
_ = Start_index + erlang:element(2, Config),
_pipe = gleam@list:drop(All_items, Start_index),
gleam@list:take(_pipe, erlang:element(2, Config));
none ->
All_items
end,
gleam@result:'try'(
gleam@list:try_map(
Items_to_show,
fun(Item) ->
Text = case erlang:element(4, Item) of
true ->
erlang:element(2, Item);
false ->
<<"🚫 "/utf8, (erlang:element(2, Item))/binary>>
end,
Callback = telega@keyboard:pack_callback(
erlang:element(10, Menu),
erlang:element(3, Item)
),
telega@keyboard:inline_button(Text, Callback)
end
),
fun(Buttons) -> {ok, Buttons} end
).
-file("src/telega/menu_builder.gleam", 466).
?DOC(" Convert menu to inline keyboard\n").
-spec to_keyboard(menu(any())) -> {ok, telega@keyboard:inline_keyboard()} |
{error, binary()}.
to_keyboard(Menu) ->
Current_page = case erlang:element(8, Menu) of
{some, State} ->
erlang:element(4, State);
none ->
1
end,
gleam@result:'try'(
build_main_buttons(Menu, Current_page),
fun(Main_buttons) ->
Nav_buttons = build_navigation_buttons(Menu, Current_page),
Pagination_buttons = case erlang:element(6, Menu) of
{some, Config} ->
build_pagination_buttons(Menu, Config, Current_page);
none ->
[]
end,
All_buttons = lists:append(
[Main_buttons, Nav_buttons, Pagination_buttons]
),
Keyboard = case erlang:element(2, erlang:element(5, Menu)) of
1 ->
telega@keyboard:new_inline(
gleam@list:map(All_buttons, fun(Btn) -> [Btn] end)
);
Cols ->
telega@keyboard:inline_grid(All_buttons, Cols)
end,
{ok, Keyboard}
end
).
-file("src/telega/menu_builder.gleam", 606).
?DOC(" Handle menu action and return updated menu\n").
-spec handle_action(menu(BBTY), binary()) -> {ok, menu(BBTY)} |
{error, binary()}.
handle_action(Menu, Action) ->
case erlang:element(8, Menu) of
none ->
{error, <<"Cannot handle action on stateless menu"/utf8>>};
{some, Menu_state} ->
case gleam_stdlib:string_starts_with(Action, <<"page:"/utf8>>) of
true ->
Page_str = gleam@string:drop_start(Action, 5),
case gleam_stdlib:parse_int(Page_str) of
{ok, Page} ->
Updated_state = {menu_state,
erlang:element(2, Menu_state),
erlang:element(3, Menu_state),
Page,
erlang:element(5, Menu_state),
erlang:element(6, Menu_state)},
{ok,
{menu,
erlang:element(2, Menu),
erlang:element(3, Menu),
erlang:element(4, Menu),
erlang:element(5, Menu),
erlang:element(6, Menu),
erlang:element(7, Menu),
{some, Updated_state},
erlang:element(9, Menu),
erlang:element(10, Menu)}};
{error, _} ->
{error, <<"Invalid page number"/utf8>>}
end;
false ->
case gleam_stdlib:map_get(erlang:element(9, Menu), Action) of
{ok, Handler} ->
Updated_state@1 = Handler(Menu_state, Action),
{ok,
{menu,
erlang:element(2, Menu),
erlang:element(3, Menu),
erlang:element(4, Menu),
erlang:element(5, Menu),
erlang:element(6, Menu),
erlang:element(7, Menu),
{some, Updated_state@1},
erlang:element(9, Menu),
erlang:element(10, Menu)}};
{error, _} ->
{error, <<"Unknown action: "/utf8, Action/binary>>}
end
end
end.
-file("src/telega/menu_builder.gleam", 639).
?DOC(" Get menu state\n").
-spec get_state(menu(BBUD)) -> gleam@option:option(menu_state(BBUD)).
get_state(Menu) ->
erlang:element(8, Menu).
-file("src/telega/menu_builder.gleam", 644).
?DOC(" Update menu state\n").
-spec update_state(menu(BBUH), fun((menu_state(BBUH)) -> menu_state(BBUH))) -> menu(BBUH).
update_state(Menu, Updater) ->
case erlang:element(8, Menu) of
{some, State} ->
{menu,
erlang:element(2, Menu),
erlang:element(3, Menu),
erlang:element(4, Menu),
erlang:element(5, Menu),
erlang:element(6, Menu),
erlang:element(7, Menu),
{some, Updater(State)},
erlang:element(9, Menu),
erlang:element(10, Menu)};
none ->
Menu
end.
-file("src/telega/menu_builder.gleam", 655).
?DOC(" Get menu callback data for filtering\n").
-spec get_callback_data(menu(any())) -> telega@keyboard:keyboard_callback_data(binary()).
get_callback_data(Menu) ->
erlang:element(10, Menu).
-file("src/telega/menu_builder.gleam", 660).
?DOC(" Helper to get menu title with optional state formatting\n").
-spec get_title(menu(any())) -> binary().
get_title(Menu) ->
case erlang:element(3, Menu) of
{some, Title} ->
Title;
none ->
<<""/utf8>>
end.
-file("src/telega/menu_builder.gleam", 668).
?DOC(" Create a confirmation menu\n").
-spec confirmation(binary(), binary(), binary(), binary(), binary(), binary()) -> menu(nil).
confirmation(
Id,
Message,
Confirm_action,
Cancel_action,
Confirm_text,
Cancel_text
) ->
_pipe = new(Id),
_pipe@1 = title(_pipe, Message),
_pipe@2 = add_item(_pipe@1, Confirm_text, Confirm_action),
_pipe@3 = add_item(_pipe@2, Cancel_text, Cancel_action),
_pipe@4 = layout(_pipe@3, 2, none, false),
build(_pipe@4).
-file("src/telega/menu_builder.gleam", 685).
?DOC(" Create a settings menu with toggles\n").
-spec settings_menu(binary(), binary(), list({binary(), binary(), boolean()})) -> menu(nil).
settings_menu(Id, Menu_title, Settings) ->
Initial_builder = begin
_pipe = new(Id),
title(_pipe, Menu_title)
end,
_pipe@1 = gleam@list:fold(
Settings,
Initial_builder,
fun(Builder, Setting) ->
{Name, Action, Value} = Setting,
add_toggle(
Builder,
<<Name/binary, " {status}"/utf8>>,
Action,
Value
)
end
),
build(_pipe@1).