Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Clear buttons before sending if one page async iterator source #39

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions nextcord/ext/menus/menu_pages.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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()
Expand Down
54 changes: 46 additions & 8 deletions nextcord/ext/menus/menus.py
Original file line number Diff line number Diff line change
Expand Up @@ -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."""
Expand Down