-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(BMNR) :: {menu_state, binary(), BMNR, integer(), list(binary()), gleam@dict:dict(binary(), binary())}. -opaque menu(BMNS) :: {menu, binary(), gleam@option:option(binary()), list(menu_section()), menu_layout(), gleam@option:option(pagination_config()), navigation_config(), gleam@option:option(menu_state(BMNS)), gleam@dict:dict(binary(), fun((menu_state(BMNS), binary()) -> menu_state(BMNS))), telega@keyboard:keyboard_callback_data(binary())}. -opaque menu_builder(BMNT) :: {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(BMNT)), gleam@dict:dict(binary(), fun((menu_state(BMNT), binary()) -> menu_state(BMNT)))}. -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(), BMNY) -> menu_builder(BMNY). 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(BMOA), binary()) -> menu_builder(BMOA). 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(BMOD), binary(), binary()) -> menu_builder(BMOD). 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(BMOG), binary(), binary()) -> menu_builder(BMOG). 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(BMOJ), gleam@option:option(binary())) -> menu_builder(BMOJ). 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(BMON), integer(), gleam@option:option(integer()), boolean() ) -> menu_builder(BMON). 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(BMOR), integer(), boolean()) -> menu_builder(BMOR). 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(BMOU), integer(), boolean(), binary(), binary(), binary() ) -> menu_builder(BMOU). 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(BMOX), binary()) -> menu_builder(BMOX). 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(BMPA), binary(), binary()) -> menu_builder(BMPA). 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(BMPD), binary()) -> menu_builder(BMPD). 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(BMPG), binary(), binary()) -> menu_builder(BMPG). 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(BMPJ), binary(), fun((menu_state(BMPJ), binary()) -> menu_state(BMPJ)) ) -> menu_builder(BMPJ). 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(BMPN)) -> menu(BMPN). 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(BMPQ), list(BMPS), fun((BMPS, integer()) -> {binary(), binary()}) ) -> menu_builder(BMPQ). 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(BMPV), list(BMPX), fun((BMPX, integer(), BMPV) -> {binary(), binary(), boolean()}) ) -> menu_builder(BMPV). 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(BMQA), binary(), binary()) -> menu_builder(BMQA). 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(BMQD), binary(), binary(), boolean()) -> menu_builder(BMQD). 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(BMQV), binary()) -> {ok, menu(BMQV)} | {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(BMRA)) -> gleam@option:option(menu_state(BMRA)). get_state(Menu) -> erlang:element(8, Menu). -file("src/telega/menu_builder.gleam", 644). ?DOC(" Update menu state\n"). -spec update_state(menu(BMRE), fun((menu_state(BMRE)) -> menu_state(BMRE))) -> menu(BMRE). 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, <>, Action, Value ) end ), build(_pipe@1).