Skip to content

Commit 4dadb69

Browse files
authored
Merge pull request #895 from krittick/ext-pages-stop-remove
[ext.pages] Add disable/cancel methods to `Paginator` class
2 parents bcc5f7e + 03c7bc7 commit 4dadb69

File tree

2 files changed

+97
-15
lines changed

2 files changed

+97
-15
lines changed

discord/ext/pages/pagination.py

Lines changed: 77 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ def __init__(
8080
)
8181
self.button_type = button_type
8282
self.label = label if label or emoji else button_type.capitalize()
83-
self.emoji = emoji
83+
self.emoji: Union[str, discord.Emoji, discord.PartialEmoji] = emoji
8484
self.style = style
8585
self.disabled = disabled
8686
self.loop_label = self.label if not loop_label else loop_label
@@ -170,18 +170,20 @@ def __init__(
170170
):
171171
self.label = label
172172
self.description = description
173-
self.emoji = emoji
174-
self.pages = pages
173+
self.emoji: Union[str, discord.Emoji, discord.PartialEmoji] = emoji
174+
self.pages: Union[
175+
List[str], List[Union[List[discord.Embed], discord.Embed]]
176+
] = pages
175177
self.show_disabled = show_disabled
176178
self.show_indicator = show_indicator
177179
self.author_check = author_check
178180
self.disable_on_timeout = disable_on_timeout
179181
self.use_default_buttons = use_default_buttons
180182
self.default_button_row = default_button_row
181183
self.loop_pages = loop_pages
182-
self.custom_view = custom_view
183-
self.timeout = timeout
184-
self.custom_buttons = custom_buttons
184+
self.custom_view: discord.ui.View = custom_view
185+
self.timeout: float = timeout
186+
self.custom_buttons: List = custom_buttons
185187

186188

187189
class Paginator(discord.ui.View):
@@ -252,27 +254,31 @@ def __init__(
252254
custom_buttons: Optional[List[PaginatorButton]] = None,
253255
) -> None:
254256
super().__init__(timeout=timeout)
255-
self.timeout = timeout
256-
self.pages = pages
257+
self.timeout: float = timeout
258+
self.pages: Union[
259+
List[PageGroup], List[str], List[Union[List[discord.Embed], discord.Embed]]
260+
] = pages
257261
self.current_page = 0
258262
self.menu: Optional[PaginatorMenu] = None
259263
self.show_menu = show_menu
260264
self.page_groups: Optional[List[PageGroup]] = None
261265

262266
if all(isinstance(pg, PageGroup) for pg in pages):
263267
self.page_groups = self.pages if show_menu else None
264-
self.pages = self.page_groups[0].pages
268+
self.pages: Union[
269+
List[str], List[Union[List[discord.Embed], discord.Embed]]
270+
] = self.page_groups[0].pages
265271

266272
self.page_count = len(self.pages) - 1
267273
self.buttons = {}
268-
self.custom_buttons = custom_buttons
274+
self.custom_buttons: List = custom_buttons
269275
self.show_disabled = show_disabled
270276
self.show_indicator = show_indicator
271277
self.disable_on_timeout = disable_on_timeout
272278
self.use_default_buttons = use_default_buttons
273279
self.default_button_row = default_button_row
274280
self.loop_pages = loop_pages
275-
self.custom_view = custom_view
281+
self.custom_view: discord.ui.View = custom_view
276282
self.message: Union[discord.Message, discord.WebhookMessage, None] = None
277283

278284
if self.custom_buttons and not self.use_default_buttons:
@@ -333,7 +339,9 @@ async def update(
333339
"""
334340

335341
# Update pages and reset current_page to 0 (default)
336-
self.pages = pages if pages is not None else self.pages
342+
self.pages: Union[
343+
List[PageGroup], List[str], List[Union[List[discord.Embed], discord.Embed]]
344+
] = (pages if pages is not None else self.pages)
337345
self.page_count = len(self.pages) - 1
338346
self.current_page = 0
339347
# Apply config changes, if specified
@@ -360,8 +368,8 @@ async def update(
360368
else self.default_button_row
361369
)
362370
self.loop_pages = loop_pages if loop_pages is not None else self.loop_pages
363-
self.custom_view = None if custom_view is None else custom_view
364-
self.timeout = timeout if timeout is not None else self.timeout
371+
self.custom_view: discord.ui.View = None if custom_view is None else custom_view
372+
self.timeout: float = timeout if timeout is not None else self.timeout
365373
if custom_buttons and not self.use_default_buttons:
366374
self.buttons = {}
367375
for button in custom_buttons:
@@ -379,6 +387,61 @@ async def on_timeout(self) -> None:
379387
item.disabled = True
380388
await self.message.edit(view=self)
381389

390+
async def disable(
391+
self,
392+
include_custom: bool = False,
393+
page: Optional[Union[str, Union[List[discord.Embed], discord.Embed]]] = None,
394+
) -> None:
395+
"""Stops the paginator, disabling all of its components.
396+
397+
Parameters
398+
----------
399+
include_custom: :class:`bool`
400+
Whether to disable components added via custom views.
401+
page: Optional[Union[:class:`str`, Union[List[:class:`discord.Embed`], :class:`discord.Embed`]]]
402+
The page content to show after disabling the paginator.
403+
"""
404+
page = self.get_page_content(page)
405+
for item in self.children:
406+
if item not in self.custom_view.children or include_custom:
407+
item.disabled = True
408+
if page:
409+
await self.message.edit(
410+
content=page if isinstance(page, str) else None,
411+
embeds=[] if isinstance(page, str) else page,
412+
view=self,
413+
)
414+
else:
415+
await self.message.edit(view=self)
416+
417+
async def cancel(
418+
self,
419+
include_custom: bool = False,
420+
page: Optional[Union[str, Union[List[discord.Embed], discord.Embed]]] = None,
421+
) -> None:
422+
"""Cancels the paginator, removing all of its components from the message.
423+
424+
Parameters
425+
----------
426+
include_custom: :class:`bool`
427+
Whether to remove components added via custom views.
428+
page: Optional[Union[:class:`str`, Union[List[:class:`discord.Embed`], :class:`discord.Embed`]]]
429+
The page content to show after canceling the paginator.
430+
"""
431+
items = self.children.copy()
432+
page = self.get_page_content(page)
433+
for item in items:
434+
if item not in self.custom_view.children or include_custom:
435+
self.remove_item(item)
436+
if page:
437+
await self.message.edit(
438+
content=page if isinstance(page, str) else None,
439+
embeds=[] if isinstance(page, str) else page,
440+
view=self,
441+
)
442+
else:
443+
await self.message.edit(view=self)
444+
382445
async def goto_page(self, page_number=0) -> discord.Message:
383446
"""Updates the paginator message to show the specified page number.
384447
@@ -559,7 +622,6 @@ def update_buttons(self) -> Dict:
559622
if self.custom_view:
560623
for item in self.custom_view.children:
561624
self.add_item(item)
562-
563625
return self.buttons
564626

565627
@staticmethod

examples/views/paginator.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,26 @@ async def pagetest_custom_view(self, ctx: discord.ApplicationContext):
182182
paginator = pages.Paginator(pages=self.get_pages(), custom_view=view)
183183
await paginator.respond(ctx.interaction, ephemeral=False)
184184

185+
@pagetest.command(name="disable")
186+
async def pagetest_disable(self, ctx: discord.ApplicationContext):
187+
"""Demonstrates disabling the paginator buttons and showing a custom page when disabled."""
188+
paginator = pages.Paginator(pages=self.get_pages())
189+
await paginator.respond(ctx.interaction, ephemeral=False)
190+
await ctx.respond("Disabling paginator in 5 seconds...")
191+
await asyncio.sleep(5)
192+
disable_page = discord.Embed(title="Paginator Disabled!", description="This page is only shown when the paginator is disabled.")
193+
await paginator.disable(page=disable_page)
194+
195+
@pagetest.command(name="cancel")
196+
async def pagetest_cancel(self, ctx: discord.ApplicationContext):
197+
"""Demonstrates canceling (stopping) the paginator and showing a custom page when cancelled."""
198+
paginator = pages.Paginator(pages=self.get_pages())
199+
await paginator.respond(ctx.interaction, ephemeral=False)
200+
await ctx.respond("Canceling paginator in 5 seconds...")
201+
await asyncio.sleep(5)
202+
cancel_page = discord.Embed(title="Paginator Cancelled!", description="This page is only shown when the paginator is cancelled.")
203+
await paginator.cancel(page=cancel_page)
204+
185205
@pagetest.command(name="groups")
186206
async def pagetest_groups(self, ctx: discord.ApplicationContext):
187207
"""Demonstrates using page groups to switch between different sets of pages."""

0 commit comments

Comments
 (0)