From 7228ef64a58f1b41576b12bb3e72db1c751919f3 Mon Sep 17 00:00:00 2001 From: Maxikinz <57434374+ImAnAgent@users.noreply.github.com> Date: Sat, 9 Oct 2021 19:03:16 +0200 Subject: [PATCH] Create a working button paginator Simple Embed paginator that I've been using for a while. Thought it could help others too. --- examples/views/paginator.py | 105 ++++++++++++++++++++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 examples/views/paginator.py diff --git a/examples/views/paginator.py b/examples/views/paginator.py new file mode 100644 index 00000000..dfe3cfdc --- /dev/null +++ b/examples/views/paginator.py @@ -0,0 +1,105 @@ +#First we define 3 View subclasses that we will switch between depending on if we are viewing the first page, a page in the middle, or the last page. +#The first page has the "left" button disabled, because there is no left page to go to... +class FirstPageComps(View): + def __init__(self, author_id: int): + super().__init__() + self.value = None + self.author_id = author_id + + async def interaction_check(self, interaction: Interaction): + return interaction.user.id == self.author_id + + @discord.ui.button(style=ButtonStyle.primary, disabled=True, label='Left') + async def left(self, button: discord.ui.Button, interaction: Interaction): + self.value = "left" + self.stop() + + @discord.ui.button(style=ButtonStyle.primary, label='Right') + async def right(self, button: discord.ui.Button, interaction: Interaction): + self.value = "right" + self.stop() + +#The middle pages have both left and right buttons available +class MiddlePageComps(View): + def __init__(self, author_id: int): + super().__init__() + self.value = None + self.author_id = author_id + + async def interaction_check(self, interaction: Interaction): + return interaction.user.id == self.author_id + + @discord.ui.button(style=ButtonStyle.primary, label='Left') + async def left(self, button: discord.ui.Button, interaction: Interaction): + self.value = "left" + self.stop() + + @discord.ui.button(style=ButtonStyle.primary, label='Right') + async def right(self, button: discord.ui.Button, interaction: Interaction): + self.value = "right" + self.stop() + +#The last page has the right button disabled, because there's no right page to go to anymore... +class LastPageComps(View): + def __init__(self, author_id: int): + super().__init__() + self.value = None + self.author_id = author_id + + async def interaction_check(self, interaction: Interaction): + return interaction.user.id == self.author_id + + @discord.ui.button(style=ButtonStyle.primary, label='Left') + async def left(self, button: discord.ui.Button, interaction: Interaction): + self.value = "left" + self.stop() + + @discord.ui.button(style=ButtonStyle.primary, label='Right', disabled=True) + async def right(self, button: discord.ui.Button, interaction: Interaction): + self.value = "right" + self.stop() + + +#Now we define the function that will take care of the pagination for us. It will take a list of Embeds and allow the user to cycle between them using left/right buttons +#There is also an optional title parameter in case you want to give your paginator a title, it will display in the embed title, for example if the title is Book +#then the title will look like "Book | Page 1/2". This is very optional and can be removed +async def paginate(ctx, pages: list, title: str = None): + + total_pages = len(pages) + first_page = pages[0] + last_page = pages[-1] + current_page = first_page + index = 0 + + embed = first_page + if title: + embed.title = f'{title} | Page {index+1}/{total_pages}' + + view = FirstPageComps(ctx.author.id) + #Here we send the message with the view of the first page and the FirstPageComps buttons + msg = await ctx.send(embed=embed, view=view) + + #The default timeout for Views is 3 minutes, but if a user selects to scroll between pages the timer will be reset. + #If the timer reaches 0, though, the loop will just silently stop. + while True: + wait = await view.wait() + if wait: + return + + if view.value == "right": + index += 1 + current_page = pages[index] + view = MiddlePageComps(ctx.author.id) if current_page != last_page else LastPageComps(ctx.author.id) + embed = current_page + if title: + embed.title = f'{title} | Page {index+1}/{total_pages}' + + elif view.value == "left": + index -= 1 + current_page = pages[index] + view = MiddlePageComps(ctx.author.id) if current_page != first_page else FirstPageComps(ctx.author.id) + embed = current_page + if title: + embed.title = f'{title} | Page {index+1}/{total_pages}' + + await msg.edit(embed=embed, view=view)