Skip to content

Commit 7ca7c9f

Browse files
committed
Brought back ButtonMenu, added style to ButtonMenuPages
1 parent bf76a3a commit 7ca7c9f

File tree

1 file changed

+54
-42
lines changed

1 file changed

+54
-42
lines changed

nextcord/ext/menus/__init__.py

Lines changed: 54 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import logging
77
import re
88
from collections import OrderedDict, namedtuple
9-
from typing import List, Optional
9+
from typing import List, Union
1010

1111
# Needed for the setup.py script
1212
__version__ = '1.0.0'
@@ -281,7 +281,7 @@ def get_buttons(cls):
281281
return buttons
282282

283283

284-
class Menu(nextcord.ui.View, metaclass=_MenuMeta):
284+
class Menu(metaclass=_MenuMeta):
285285
r"""An interface that allows handling menus by using reactions as buttons.
286286
287287
Buttons should be marked with the :func:`button` decorator. Please note that
@@ -316,7 +316,6 @@ class Menu(nextcord.ui.View, metaclass=_MenuMeta):
316316
def __init__(self, *, timeout=DEFAULT_TIMEOUT, delete_message_after=False,
317317
clear_reactions_after=False, check_embeds=False, message=None):
318318

319-
super().__init__(timeout=timeout)
320319
self.timeout = timeout
321320
self.delete_message_after = delete_message_after
322321
self.clear_reactions_after = clear_reactions_after
@@ -757,6 +756,25 @@ async def send_initial_message(self, ctx, channel):
757756
"""
758757
raise NotImplementedError
759758

759+
def stop(self):
760+
"""Stops the internal loop."""
761+
self._running = False
762+
for task in self.__tasks:
763+
task.cancel()
764+
self.__tasks.clear()
765+
766+
class ButtonMenu(Menu, nextcord.ui.View):
767+
r"""An interface that allows handling menus by using button interaction components.
768+
769+
Buttons should be marked with the :func:`nextcord.ui.button` decorator. Please note that
770+
this expects the methods to have two parameters, the ``button`` and the ``interaction``.
771+
The ``button`` is of type :class:`nextcord.ui.Button`.
772+
The ``interaction`` is of type :class:`nextcord.Interaction`.
773+
"""
774+
def __init__(self, timeout=DEFAULT_TIMEOUT, *args, **kwargs):
775+
Menu.__init__(self, timeout=timeout, *args, **kwargs)
776+
nextcord.ui.View.__init__(self, timeout=timeout)
777+
760778
async def _set_all_disabled(self, disable: bool):
761779
"""|coro|
762780
@@ -786,11 +804,11 @@ async def disable(self):
786804
await self._set_all_disabled(True)
787805

788806
def stop(self):
789-
"""Stops the internal loop."""
790-
self._running = False
791-
for task in self.__tasks:
792-
task.cancel()
793-
self.__tasks.clear()
807+
"""Stops the internal loop and view interactions."""
808+
# stop the menu loop
809+
Menu.stop(self)
810+
# stop view interactions
811+
nextcord.ui.View.stop(self)
794812

795813

796814
class PageSource:
@@ -914,7 +932,7 @@ async def format_page(self, menu, page):
914932
raise NotImplementedError
915933

916934

917-
class MenuPagesBase(Menu):
935+
class MenuPagesBase(ButtonMenu):
918936
"""A base class dedicated to pagination for reaction and button menus.
919937
920938
Attributes
@@ -927,7 +945,7 @@ class MenuPagesBase(Menu):
927945
PREVIOUS_PAGE = '\N{BLACK LEFT-POINTING TRIANGLE}\ufe0f'
928946
NEXT_PAGE = '\N{BLACK RIGHT-POINTING TRIANGLE}\ufe0f'
929947
LAST_PAGE = '\N{BLACK RIGHT-POINTING DOUBLE TRIANGLE WITH VERTICAL BAR}\ufe0f'
930-
STOP_PAGINATION = '\N{BLACK SQUARE FOR STOP}\ufe0f'
948+
STOP = '\N{BLACK SQUARE FOR STOP}\ufe0f'
931949

932950
def __init__(self, source, **kwargs):
933951
self._source = source
@@ -1065,8 +1083,8 @@ class MenuPaginationButton(nextcord.ui.Button['MenuPaginationButton']):
10651083
"""
10661084
A custom button for pagination that will be disabled when unavailable.
10671085
"""
1068-
def __init__(self, emoji):
1069-
super().__init__(style=nextcord.ButtonStyle.primary, emoji=emoji)
1086+
def __init__(self, style: nextcord.ButtonStyle, emoji: Union[str, nextcord.Emoji, nextcord.PartialEmoji]):
1087+
super().__init__(style=style, emoji=emoji)
10701088
self._emoji = _cast_emoji(emoji)
10711089

10721090
async def callback(self, interaction: nextcord.Interaction):
@@ -1075,7 +1093,6 @@ async def callback(self, interaction: nextcord.Interaction):
10751093
"""
10761094
assert self.view is not None
10771095
view: ButtonMenuPages = self.view
1078-
stopped = False
10791096

10801097
# change the current page
10811098
if self._emoji.name == view.FIRST_PAGE:
@@ -1086,57 +1103,52 @@ async def callback(self, interaction: nextcord.Interaction):
10861103
await view.show_checked_page(view.current_page + 1)
10871104
elif self._emoji.name == view.LAST_PAGE:
10881105
await view.show_page(view._source.get_max_pages() - 1)
1089-
elif self._emoji.name == view.STOP_PAGINATION:
1090-
nextcord.ui.View.stop(view)
1091-
stopped = True
1106+
1107+
# disable buttons that are unavailable
1108+
view._disable_unavailable_buttons()
10921109

1093-
# disable the buttons that are unavailable
1094-
view._disable_unavailable_buttons(stopped)
1110+
# disable all buttons if stop is pressed
1111+
if self._emoji.name == view.STOP:
1112+
await view.disable()
1113+
view.stop()
10951114

10961115
# update the view
10971116
await interaction.response.edit_message(view=view)
10981117

10991118

1100-
class ButtonMenuPages(MenuPagesBase, nextcord.ui.View):
1119+
class ButtonMenuPages(MenuPagesBase):
11011120
"""A special type of Menu dedicated to pagination with button components.
11021121
11031122
Parameters
11041123
-----------
1105-
timeout: Optional[:class:`float`]
1106-
Timeout in seconds from last interaction with the UI before no longer accepting input.
1107-
If ``None`` then there is no timeout.
1124+
style: :class:`nextcord.ui.ButtonStyle`
1125+
The button style to use for the pagination buttons.
11081126
11091127
Attributes
11101128
------------
11111129
current_page: :class:`int`
11121130
The current page that we are in. Zero-indexed
11131131
between [0, :attr:`PageSource.max_pages`).
11141132
"""
1115-
def __init__(self, source, timeout=DEFAULT_TIMEOUT, **kwargs):
1116-
MenuPagesBase.__init__(self, source, **kwargs)
1117-
nextcord.ui.View.__init__(self, timeout=timeout)
1118-
skip_double_triangle_buttons = self._skip_double_triangle_buttons()
1119-
if not skip_double_triangle_buttons:
1120-
nextcord.ui.View.add_item(self, MenuPaginationButton(self.FIRST_PAGE))
1121-
nextcord.ui.View.add_item(self, MenuPaginationButton(self.PREVIOUS_PAGE))
1122-
nextcord.ui.View.add_item(self, MenuPaginationButton(self.NEXT_PAGE))
1123-
if not skip_double_triangle_buttons:
1124-
nextcord.ui.View.add_item(self, MenuPaginationButton(self.LAST_PAGE))
1125-
nextcord.ui.View.add_item(self, MenuPaginationButton(self.STOP_PAGINATION))
1133+
def __init__(self, source: PageSource, style: nextcord.ButtonStyle = nextcord.ButtonStyle.primary, **kwargs):
1134+
super().__init__(source, **kwargs)
1135+
# add buttons to the view
1136+
for emoji in (self.FIRST_PAGE, self.PREVIOUS_PAGE, self.NEXT_PAGE, self.LAST_PAGE, self.STOP):
1137+
if emoji in (self.FIRST_PAGE, self.LAST_PAGE) and self._skip_double_triangle_buttons():
1138+
continue
1139+
self.add_item(MenuPaginationButton(style=style, emoji=emoji))
11261140
self._disable_unavailable_buttons()
11271141

1128-
def _disable_unavailable_buttons(self, stopped: bool = False):
1142+
def _disable_unavailable_buttons(self):
11291143
"""
11301144
Disables buttons that are unavailable to be pressed.
11311145
"""
1132-
children: List[MenuPaginationButton] = self.children
1133-
for child in children:
1134-
if stopped:
1135-
child.disabled = True
1136-
elif child.emoji.name in (self.FIRST_PAGE, self.PREVIOUS_PAGE):
1137-
child.disabled = self.current_page == 0
1138-
elif child.emoji.name in (self.LAST_PAGE, self.NEXT_PAGE):
1139-
child.disabled = self.current_page == self._source.get_max_pages() - 1
1146+
buttons: List[MenuPaginationButton] = self.children
1147+
for button in buttons:
1148+
if button.emoji.name in (self.FIRST_PAGE, self.PREVIOUS_PAGE):
1149+
button.disabled = self.current_page == 0
1150+
elif button.emoji.name in (self.LAST_PAGE, self.NEXT_PAGE):
1151+
button.disabled = self.current_page == self._source.get_max_pages() - 1
11401152

11411153

11421154

0 commit comments

Comments
 (0)