diff --git a/nextcord/ext/menus/menu_pages.py b/nextcord/ext/menus/menu_pages.py index aad735c..f869ac4 100644 --- a/nextcord/ext/menus/menu_pages.py +++ b/nextcord/ext/menus/menu_pages.py @@ -125,6 +125,9 @@ async def send_initial_message( kwargs = await self._get_kwargs_from_page(page) # filter out kwargs that are "None" kwargs = {k: v for k, v in kwargs.items() if v is not None} + # if we're not paginating, we can remove the pagination buttons + if not self._source.is_paginating(): + await self.clear() # if there is an interaction, send an interaction response if self.interaction is not None: message = await self.interaction.send(ephemeral=self.ephemeral, **kwargs) @@ -149,9 +152,6 @@ async def start( wait=wait, ephemeral=ephemeral, ) - # If we're not paginating, we can remove the pagination buttons - if not self._source.is_paginating(): - await self.clear() async def show_checked_page(self, page_number: int): max_pages = self._source.get_max_pages() diff --git a/nextcord/ext/menus/menus.py b/nextcord/ext/menus/menus.py index 2110a4c..32833c3 100644 --- a/nextcord/ext/menus/menus.py +++ b/nextcord/ext/menus/menus.py @@ -840,44 +840,82 @@ def __init__( self.disable_buttons_after = disable_buttons_after async def _update_view(self): + """|coro| + + Updates the :class:`nextcord.ui.View` of the menu. + + Raises + -------- + AssertionError + The message is None. + """ + assert self.message is not None, "No message to update" await self.message.edit(view=self) async def _set_all_disabled(self, disable: bool): """|coro| - Enables or disable all :class:`nextcord.ui.Button` components in the menu. + Enables or disables all :class:`nextcord.ui.Button` components in the menu. If the :attr:`message` is set, + it will be edited with the new :class:`~nextcord.ui.View`. + + If no buttons are enabled or disabled, the message will not be edited. Parameters ------------ disable: :class:`bool` Whether to disable or enable the buttons. """ + # if all buttons are already set to `disable` then we don't need to do anything + modified = False + # disable or enable all buttons for child in self.children: - if isinstance(child, nextcord.ui.Button): + if isinstance(child, nextcord.ui.Button) and child.disabled != disable: child.disabled = disable - await self._update_view() + modified = True + # update the view + if modified and self.message is not None: + await self._update_view() async def enable(self): """|coro| - Enables all :class:`nextcord.ui.Button` components in the menu. + Enables all :class:`nextcord.ui.Button` components in the menu. If the :attr:`message` is set, + it will be edited with the new :class:`~nextcord.ui.View`. + + If all buttons are already enabled, the message will not be edited. """ await self._set_all_disabled(False) async def disable(self): """|coro| - Disables all :class:`nextcord.ui.Button` components in the menu. + Disables all :class:`nextcord.ui.Button` components in the menu. If the :attr:`message` is set, + it will be edited with the new :class:`~nextcord.ui.View`. + + If all buttons are already disabled, the message will not be edited. """ await self._set_all_disabled(True) async def clear(self): """|coro| - Removes all :class:`nextcord.ui.Button` components in the menu. + Removes all :class:`nextcord.ui.Button` components in the menu. If the :attr:`message` is set, + it will be edited with the new :class:`~nextcord.ui.View`. + + If there are already no buttons in the view, the message will not be edited. """ - self.clear_items() - await self._update_view() + # if there are no buttons, then we don't need to do anything + modified = False + # remove all buttons + # copy is required since we are removing during iteration in remove_item + # which needs to be called in order to update the view weights + for child in self.children.copy(): + if isinstance(child, nextcord.ui.Button): + self.remove_item(child) + modified = True + # update the view + if modified and self.message is not None: + await self._update_view() def stop(self): """Stops the internal loop and view interactions."""