@@ -849,11 +849,9 @@ async def send_genesis_message():
849849 if getattr (self , "_selected_thread_creation_menu_option" , None ) and self .bot .config .get (
850850 "thread_creation_menu_selection_log"
851851 ):
852- opt = self ._selected_thread_creation_menu_option
852+ path = self ._selected_thread_creation_menu_option
853853 try :
854- log_txt = f"Selected menu option: { opt .get ('label' )} ({ opt .get ('type' )} )"
855- if opt .get ("type" ) == "command" :
856- log_txt += f" -> { opt .get ('callback' )} "
854+ log_txt = f"Selected menu path: { ' -> ' .join (path )} "
857855 await channel .send (embed = discord .Embed (description = log_txt , color = self .bot .mod_color ))
858856 except Exception :
859857 logger .warning (
@@ -2659,29 +2657,32 @@ async def create(
26592657 placeholder = "Select an option to contact the staff team."
26602658 timeout = 20
26612659
2662- options = self .bot .config .get ("thread_creation_menu_options" ) or {}
2663- submenus = self .bot .config .get ("thread_creation_menu_submenus" ) or {}
2664-
26652660 # Minimal inline view implementation (avoid importing plugin code)
26662661
26672662 thread .ready = False # not ready yet
26682663
26692664 class _ThreadCreationMenuSelect (discord .ui .Select ):
2670- def __init__ (self , outer_thread : Thread ):
2665+ def __init__ (self , bot , outer_thread : Thread , option_data : dict , menu_msg : discord .Message , path : list , is_home : bool = True ):
2666+ self .bot = bot
26712667 self .outer_thread = outer_thread
2672- opts = [
2668+ self .option_data = option_data
2669+ self .menu_msg = menu_msg
2670+ self .path = path
2671+ options = [
26732672 discord .SelectOption (
26742673 label = o ["label" ],
26752674 description = o ["description" ],
26762675 emoji = o ["emoji" ],
26772676 )
2678- for o in options .values ()
2677+ for o in option_data .values ()
26792678 ]
2679+ if not is_home :
2680+ options .append (discord .SelectOption (label = "main menu" , description = "Return to the main menu" , emoji = "🏠" ))
26802681 super ().__init__ (
26812682 placeholder = placeholder ,
26822683 min_values = 1 ,
26832684 max_values = 1 ,
2684- options = opts ,
2685+ options = options ,
26852686 )
26862687
26872688 async def callback (self , interaction : discord .Interaction ):
@@ -2694,10 +2695,37 @@ async def callback(self, interaction: discord.Interaction):
26942695 except Exception :
26952696 logger .warning ("Failed unsnoozing thread prior to menu selection; continuing." )
26962697 chosen_label = self .values [0 ]
2698+ self .path .append (chosen_label )
26972699 # Resolve option key
26982700 key = chosen_label .lower ().replace (" " , "_" )
2699- selected = options .get (key )
2700- self .outer_thread ._selected_thread_creation_menu_option = selected
2701+ if key == "main_menu" :
2702+ # From a submenu, go back to main menu. This is achieved by rebuilding the view.
2703+ option_data = self .bot .config .get ("thread_creation_menu_options" ) or {}
2704+ new_view = _ThreadCreationMenuView (
2705+ self .bot ,
2706+ self .outer_thread ,
2707+ option_data ,
2708+ self .menu_msg ,
2709+ path = [],
2710+ is_home = True ,
2711+ )
2712+ return await self .menu_msg .edit (view = new_view )
2713+ selected : dict = self .option_data .get (key , {})
2714+ if selected ["type" ] == "submenu" :
2715+ # Build new view for submenu
2716+ submenu_data = self .bot .config .get ("thread_creation_menu_submenus" ) or {}
2717+ option_data = submenu_data .get (key , {})
2718+ new_view = _ThreadCreationMenuView (
2719+ self .bot ,
2720+ self .outer_thread ,
2721+ option_data ,
2722+ self .menu_msg ,
2723+ path = self .path ,
2724+ is_home = False ,
2725+ )
2726+ return await self .menu_msg .edit (view = new_view )
2727+
2728+ self .outer_thread ._selected_thread_creation_menu_option = self .path
27012729 # Reflect the selection in the original DM by editing the embed/body
27022730 try :
27032731 msg = getattr (interaction , "message" , None )
@@ -2936,10 +2964,13 @@ async def callback(self, interaction: discord.Interaction):
29362964 ctx_ .command .checks = old_checks
29372965
29382966 class _ThreadCreationMenuView (discord .ui .View ):
2939- def __init__ (self , outer_thread : Thread ):
2967+ def __init__ (self , bot , outer_thread : Thread , option_data : dict , menu_msg : discord . Message , path : list = [], is_home : bool = True ):
29402968 super ().__init__ (timeout = timeout )
29412969 self .outer_thread = outer_thread
2942- self .add_item (_ThreadCreationMenuSelect (outer_thread ))
2970+ self .path = [] if is_home else path
2971+ self .menu_msg = menu_msg
2972+ self .option_data = option_data
2973+ self .add_item (_ThreadCreationMenuSelect (bot , outer_thread , option_data = option_data , menu_msg = menu_msg , path = self .path , is_home = is_home ))
29432974
29442975 async def on_timeout (self ):
29452976 # Timeout -> abort thread creation
@@ -3061,8 +3092,10 @@ async def on_timeout(self):
30613092 embed .set_thumbnail (url = embed_thumb )
30623093 except Exception as e :
30633094 logger .debug ("Thumbnail set failed (ignored): %s" , e )
3064- menu_view = _ThreadCreationMenuView (thread )
3065- menu_msg = await recipient .send (embed = embed , view = menu_view )
3095+ menu_msg = await recipient .send (embed = embed )
3096+ option_data = self .bot .config .get ("thread_creation_menu_options" ) or {}
3097+ menu_view = _ThreadCreationMenuView (self .bot , thread , option_data , menu_msg )
3098+ menu_msg = await menu_msg .edit (view = menu_view )
30663099 # mark thread as pending menu selection
30673100 thread ._pending_menu = True
30683101 # Explicitly attach the message to the view for safety in callbacks
@@ -3135,10 +3168,6 @@ async def callback(self, interaction: discord.Interaction):
31353168 "Failed unsnoozing thread prior to precreate menu selection; continuing." ,
31363169 exc_info = True ,
31373170 )
3138- chosen_label = self .values [0 ]
3139- key = chosen_label .lower ().replace (" " , "_" )
3140- selected = options .get (key )
3141- self .outer_thread ._selected_thread_creation_menu_option = selected
31423171 # Remove the view
31433172 try :
31443173 msg = getattr (interaction , "message" , None )
0 commit comments