Add support for scroller with more than 25 pages. Fixes #79

This commit is contained in:
Ev-1 committed 2023-04-28 23:35:52 +02:00
1 parent 6eb360de5b
commit 74cf9519a8
3 files changed
+121 -4

No files matched your search

@@ -0,0 +1,28 @@
class NavBarRange:
def __init__(self, num_items: int, current_item: int, max_iter_length: int, add_ends: bool = True):
self.num_items = num_items
self.current_item = current_item
self.max_iter_length = max_iter_length
self.add_ends = add_ends
def __iter__(self):
if (self.max_iter_length > self.num_items):
return iter(range(0, self.num_items))
# Start can not be before 0
start = max(0, self.current_item - self.max_iter_length // 2)
# Start can not be closer to end than max_iter_length
start = min(start, self.num_items - self.max_iter_length)
end = start + self.max_iter_length
mid_select_items = list(range(start, end))
if self.add_ends:
mid_select_items[0] = 0
mid_select_items[-1] = self.num_items - 1
return iter(mid_select_items)
def _make_truncated_range(self, start, end):
actual_start = max(start, 0)
actual_end = min(self.max_iter_length, end)
return range(actual_start, actual_end)
+29 -4
View File
@@ -8,8 +8,11 @@ import discord
from bot import MusicBot
from .navbar_range import NavBarRange
from .paginators import BasePaginator, CantScrollError
DISCORD_MAX_SELECTOR_OPTIONS = 25
class ClearMode(Flag):
Timeout = auto()
@@ -109,7 +112,7 @@ class Scroller:
def update_view(self):
if self.use_nav_bar:
self.navigator.placeholder = f"Page: {self.page_number + 1}/{len(self.paginator.pages)}"
self._update_navbar_items()
if self.is_scrolling_paginator:
self.back_button.disabled = self.page_number == 0
@@ -120,10 +123,32 @@ class Scroller:
self.view.add_item(item=button)
if self.use_nav_bar:
self.navigator = ScrollerNav(self.navigate, placeholder="Navigate to page", row=4)
self.navigator = None
self._update_navbar_items()
def _update_navbar_items(self):
placeholder = f"Page: {self.page_number + 1}/{len(self.paginator.pages)}"
did_exist = False
# If we have more than 25 items, the navigator needs to be re-created.
num_selectable_items = len(self.paginator.pages)
if num_selectable_items > DISCORD_MAX_SELECTOR_OPTIONS and self.navigator is not None:
self.view.remove_item(self.navigator)
self.navigator = None
did_exist = True
if self.navigator is None:
if not did_exist:
placeholder = "Navigate to page"
self.navigator = ScrollerNav(self.navigate, placeholder=placeholder, row=4)
self.view.add_item(item=self.navigator)
for (i, _) in enumerate(self.paginator.pages):
self.navigator.add_option(label=str(i+1), value=str(i))
navigatable_items = NavBarRange(num_items=num_selectable_items,
current_item=self.page_number,
max_iter_length=DISCORD_MAX_SELECTOR_OPTIONS,
add_ends=True)
for page in navigatable_items:
self.navigator.add_option(label=str(page+1), value=str(page))
else:
self.navigator.placeholder = placeholder
async def stop(self, was_timeout: bool, clear_scroller_view: bool = True):
self.is_scrolling_paginator = False
@@ -0,0 +1,64 @@
from .navbar_range import NavBarRange
class TestCenteredRange():
def test_centered_basic_range(self):
nav_range = NavBarRange(num_items=15, current_item=6, max_iter_length=7, add_ends=False)
assert list(nav_range) == [3, 4, 5, 6, 7, 8, 9]
def test_centered_padded_range(self):
nav_range = NavBarRange(num_items=15, current_item=6, max_iter_length=7, add_ends=True)
assert list(nav_range) == [0, 4, 5, 6, 7, 8, 14]
def test_beginning_basic_range(self):
nav_range = NavBarRange(num_items=15, current_item=0, max_iter_length=7, add_ends=False)
assert list(nav_range) == [0, 1, 2, 3, 4, 5, 6]
nav_range = NavBarRange(num_items=15, current_item=1, max_iter_length=7, add_ends=False)
assert list(nav_range) == [0, 1, 2, 3, 4, 5, 6]
nav_range = NavBarRange(num_items=15, current_item=3, max_iter_length=7, add_ends=False)
assert list(nav_range) == [0, 1, 2, 3, 4, 5, 6]
# Should be shifted
nav_range = NavBarRange(num_items=15, current_item=4, max_iter_length=7, add_ends=False)
assert list(nav_range) == [1, 2, 3, 4, 5, 6, 7]
def test_beginning_padded_range(self):
nav_range = NavBarRange(num_items=15, current_item=0, max_iter_length=7, add_ends=True)
assert list(nav_range) == [0, 1, 2, 3, 4, 5, 14]
nav_range = NavBarRange(num_items=15, current_item=1, max_iter_length=7, add_ends=True)
assert list(nav_range) == [0, 1, 2, 3, 4, 5, 14]
nav_range = NavBarRange(num_items=15, current_item=3, max_iter_length=7, add_ends=True)
assert list(nav_range) == [0, 1, 2, 3, 4, 5, 14]
# Should be shifted
nav_range = NavBarRange(num_items=15, current_item=4, max_iter_length=7, add_ends=True)
assert list(nav_range) == [0, 2, 3, 4, 5, 6, 14]
def test_end_basic_range(self):
nav_range = NavBarRange(num_items=15, current_item=14, max_iter_length=7, add_ends=False)
assert list(nav_range) == [8, 9, 10, 11, 12, 13, 14]
nav_range = NavBarRange(num_items=15, current_item=13, max_iter_length=7, add_ends=False)
assert list(nav_range) == [8, 9, 10, 11, 12, 13, 14]
nav_range = NavBarRange(num_items=15, current_item=11, max_iter_length=7, add_ends=False)
assert list(nav_range) == [8, 9, 10, 11, 12, 13, 14]
# Should be shifted
nav_range = NavBarRange(num_items=15, current_item=10, max_iter_length=7, add_ends=False)
assert list(nav_range) == [7, 8, 9, 10, 11, 12, 13]
def test_end_padded_range(self):
nav_range = NavBarRange(num_items=15, current_item=14, max_iter_length=7, add_ends=True)
assert list(nav_range) == [0, 9, 10, 11, 12, 13, 14]
nav_range = NavBarRange(num_items=15, current_item=13, max_iter_length=7, add_ends=True)
assert list(nav_range) == [0, 9, 10, 11, 12, 13, 14]
nav_range = NavBarRange(num_items=15, current_item=11, max_iter_length=7, add_ends=True)
assert list(nav_range) == [0, 9, 10, 11, 12, 13, 14]
# Should be shifted
nav_range = NavBarRange(num_items=15, current_item=10, max_iter_length=7, add_ends=True)
assert list(nav_range) == [0, 8, 9, 10, 11, 12, 14]
def test_short_range(self):
nav_range = NavBarRange(num_items=15, current_item=7, max_iter_length=25)
assert list(nav_range) == list(range(15))