Skip to content

Commit e35445b

Browse files
committed
Bloatware is my passion.
1 parent 3ba7337 commit e35445b

File tree

10 files changed

+120
-212
lines changed

10 files changed

+120
-212
lines changed

nameless/custom/ui/__init__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
from .dropdown import *
22
from .modal import *
3-
from .view import *
3+
from .paginated_view import *
44
from .yes_no import *

nameless/custom/ui/dropdown/custom_dropdown.py nameless/custom/ui/dropdown.py

+17-10
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,32 @@
11
import os
22
from collections.abc import Callable
3-
from typing import override
3+
from typing import Self, override
44

55
import discord
66
from discord import ui
77

8-
__all__ = ["CustomDropdown"]
8+
__all__ = ["NamelessDropdown"]
99

1010

11-
DropdownCallback = Callable[[discord.Interaction], str | None]
11+
_DropdownCallback = Callable[[discord.Interaction], str | None]
1212
"""
1313
A callback for a dropdown.
1414
1515
Parameters:
1616
-----------
17-
interaction: discord.Interaction
17+
interaction: `discord.Interaction`
1818
The interaction object.
1919
2020
Returns:
2121
--------
22-
``str`` | ``None``
22+
`str` | `None`
2323
Return with a string to mark it as an error message, otherwise None.
2424
"""
2525

2626

27-
class CustomDropdown(ui.Select[ui.View]):
27+
class NamelessDropdown(ui.Select[ui.View]):
28+
"""nameless* custom dropdown."""
29+
2830
def __init__(
2931
self,
3032
custom_id: str | None = None,
@@ -33,7 +35,12 @@ def __init__(
3335
max_values: int = 1,
3436
disabled: bool = False,
3537
):
36-
self._callback: list[DropdownCallback] = []
38+
assert min_values >= 1
39+
assert max_values >= 1
40+
assert min_values <= max_values
41+
42+
self._callback: list[_DropdownCallback] = []
43+
3744
if custom_id is None:
3845
custom_id = "nameless-dropdown-" + os.urandom(16).hex()
3946

@@ -46,7 +53,7 @@ def __init__(
4653
options=[],
4754
)
4855

49-
def add_callback(self, callback: DropdownCallback):
56+
def push_callback(self, callback: _DropdownCallback) -> Self:
5057
self._callback.append(callback)
5158
return self
5259

@@ -62,15 +69,15 @@ async def callback(self, interaction: discord.Interaction):
6269
if self.view is not None:
6370
self.view.stop()
6471

65-
def self_add_option(
72+
def push_option(
6673
self,
6774
*,
6875
label: str,
6976
value: str = "",
7077
description: str | None = None,
7178
emoji: str | discord.Emoji | discord.PartialEmoji | None = None,
7279
default: bool = False,
73-
):
80+
) -> Self:
7481
self.add_option(
7582
label=label,
7683
value=value,

nameless/custom/ui/dropdown/__init__.py

-3
This file was deleted.

nameless/custom/ui/modal/__init__.py

+2-4
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,2 @@
1-
from .custom_input import CustomInput
2-
from .custom_modal import BaseCustomModal
3-
4-
__all__ = ["CustomInput", "BaseCustomModal"]
1+
from .input import *
2+
from .modal import *

nameless/custom/ui/modal/custom_input.py nameless/custom/ui/modal/input.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,10 @@
55

66
V = TypeVar("V", bound=type, covariant=True)
77

8+
__all__ = ["NamelessModalInput"]
89

9-
class CustomInput(ui.TextInput[ui.Modal], Generic[V]):
10+
11+
class NamelessModalInput(ui.TextInput[ui.Modal], Generic[V]):
1012
def __init__(
1113
self, label: str, custom_id: str, default: str = "0", convert: V = str
1214
):

nameless/custom/ui/modal/custom_modal.py nameless/custom/ui/modal/modal.py

+7-5
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
1-
from typing import Generic, TypeVar, override
1+
from typing import Generic, TypeVar, cast, override
22

33
import discord
44

5-
from nameless.custom.ui.modal.custom_input import CustomInput
5+
from nameless.custom.ui.modal.input import NamelessModalInput
66

77
V = TypeVar("V", bound=type, covariant=True)
88

9+
__all__ = ["NamelessModal"]
910

10-
class BaseCustomModal(discord.ui.Modal, Generic[V]):
11+
12+
class NamelessModal(discord.ui.Modal, Generic[V]):
1113
def __init__(self, title: str) -> None:
1214
super().__init__(timeout=30, title=title)
1315

@@ -16,8 +18,8 @@ async def on_submit(self, interaction: discord.Interaction[discord.Client]) -> N
1618
await interaction.response.defer()
1719
self.stop()
1820

19-
def get_input(self) -> CustomInput[V]:
20-
return self.children[0] # pyright: ignore[reportReturnType]
21+
def get_input(self) -> NamelessModalInput[V]:
22+
return cast(NamelessModalInput[V], self.children[0])
2123

2224
@property
2325
def value(self) -> V:

nameless/custom/ui/view/view_button.py nameless/custom/ui/paginated_view.py

+90-21
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,106 @@
1-
# pyright: reportUnknownParameterType=false, reportMissingParameterType=false, reportUnknownArgumentType=false, reportUnknownMemberType=false
2-
from typing import override
1+
from collections.abc import Iterable
2+
from typing import Self, override
33

44
import discord
5-
from discord import ui
6-
from discord.ui import Button
5+
from discord.ext.commands import Bot, Context
6+
from discord.ui import Button, Modal, TextInput
77

8-
from nameless.custom.ui.view.base import BaseView
8+
__all__ = ["NamelessPaginatedView"]
99

10-
__all__ = ["ViewButton"]
1110

11+
class JumpToPageModal(Modal):
12+
"""Modal to ask for specific page."""
1213

13-
class ToPageModal(discord.ui.Modal):
14-
page: ui.TextInput[BaseView] = ui.TextInput(label="Page")
14+
page: TextInput[Self] = TextInput(
15+
label="Page number",
16+
default="0",
17+
placeholder="Any page number, will failsafe to '0' (zero).",
18+
)
1519

1620
@override
1721
async def on_submit(self, interaction: discord.Interaction) -> None:
1822
self.stop()
1923

20-
def get_values(self):
21-
return self.page.value
24+
def get_value(self) -> int:
25+
"""Get parsed page value. Will failsafe to 0."""
26+
try:
27+
return int(self.page.value)
28+
except ValueError:
29+
return 0
2230

2331

24-
class ViewButton(Button[BaseView]):
32+
class NamelessPaginatedView(discord.ui.View):
33+
"""nameless* custom paginated view."""
34+
35+
def __init__(self, ctx: Context[Bot], timeout: int = 60):
36+
super().__init__(timeout=timeout)
37+
self.ctx: Context[Bot] = ctx
38+
self.pages: list[discord.Embed] = []
39+
self.current_page: int = 0
40+
self._current_message: discord.Message | None = None
41+
42+
@property
43+
def message(self):
44+
if not self._current_message:
45+
return self.ctx.message
46+
47+
return self._current_message
48+
49+
@message.setter
50+
def message(self, value: discord.Message):
51+
self._current_message = value
52+
53+
def add_pages(self, pages: Iterable[discord.Embed]) -> None:
54+
self.pages.extend(pages)
55+
56+
def add_button(self, button: Button[Self]):
57+
self.add_item(button)
58+
59+
async def next_page(self):
60+
if self.current_page + 1 >= len(self.pages):
61+
self.current_page = 0
62+
else:
63+
self.current_page += 1
64+
await self.message.edit(embed=self.pages[self.current_page], view=self)
65+
66+
async def previous_page(self):
67+
if self.current_page - 1 < 0:
68+
self.current_page = len(self.pages) - 1
69+
else:
70+
self.current_page -= 1
71+
await self.message.edit(embed=self.pages[self.current_page], view=self)
72+
73+
async def go_to_first_page(self):
74+
await self.message.edit(embed=self.pages[0], view=self)
75+
76+
async def go_to_last_page(self):
77+
await self.message.edit(embed=self.pages[-1], view=self)
78+
79+
async def go_to_page(self, page: int):
80+
self.current_page = page
81+
await self.ctx.send(embed=self.pages[self.current_page], view=self)
82+
83+
async def start(self):
84+
self.message = await self.ctx.send(embed=self.pages[0], view=self)
85+
return await self.wait()
86+
87+
async def end(self):
88+
self.stop()
89+
# await self.__current_message.delete()
90+
await self.message.edit(view=None)
91+
92+
93+
class NavigationButton(Button[NamelessPaginatedView]):
2594
NEXT_PAGE_ID: str = "0"
2695
PREVIOUS_PAGE_ID: str = "1"
2796
GO_TO_FIRST_PAGE_ID: str = "2"
2897
GO_TO_LAST_PAGE_ID: str = "3"
2998
GO_TO_PAGE_ID: str = "4"
3099
END_ID: str = "5"
31100

32-
def __init__(self, *args, **kwargs):
101+
def __init__(self, *args: object, **kwargs: object):
33102
super().__init__(*args, **kwargs)
34-
self._view: BaseView | None = None
103+
self._view: NamelessPaginatedView | None = None
35104

36105
@override
37106
async def callback(self, interaction: discord.Interaction):
@@ -49,7 +118,7 @@ async def callback(self, interaction: discord.Interaction):
49118
case self.GO_TO_LAST_PAGE_ID:
50119
await self.view.go_to_last_page()
51120
case self.GO_TO_PAGE_ID:
52-
modal = ToPageModal()
121+
modal = JumpToPageModal()
53122
await interaction.response.send_modal(modal)
54123
if await modal.wait():
55124
return
@@ -71,7 +140,7 @@ def create_button(
71140
with_label: bool,
72141
with_emote: bool,
73142
with_disabled: bool,
74-
**kwargs,
143+
**kwargs: object,
75144
):
76145
return cls(
77146
style=discord.ButtonStyle.gray,
@@ -88,7 +157,7 @@ def back(
88157
with_label: bool = False,
89158
with_emote: bool = True,
90159
with_disabled: bool = False,
91-
**kwargs,
160+
**kwargs: object,
92161
):
93162
return cls.create_button(
94163
"Back",
@@ -106,7 +175,7 @@ def next(
106175
with_label: bool = False,
107176
with_emote: bool = True,
108177
with_disabled: bool = False,
109-
**kwargs,
178+
**kwargs: object,
110179
):
111180
return cls.create_button(
112181
"Next",
@@ -124,7 +193,7 @@ def go_to_first_page(
124193
with_label: bool = False,
125194
with_emote: bool = True,
126195
with_disabled: bool = False,
127-
**kwargs,
196+
**kwargs: object,
128197
):
129198
return cls.create_button(
130199
"First Page",
@@ -142,7 +211,7 @@ def go_to_last_page(
142211
with_label: bool = False,
143212
with_emote: bool = True,
144213
with_disabled: bool = False,
145-
**kwargs,
214+
**kwargs: object,
146215
):
147216
return cls.create_button(
148217
"Last Page",
@@ -160,7 +229,7 @@ def go_to_page(
160229
with_label: bool = False,
161230
with_emote: bool = True,
162231
with_disabled: bool = False,
163-
**kwargs,
232+
**kwargs: object,
164233
):
165234
return cls.create_button(
166235
"Page Selection",
@@ -178,7 +247,7 @@ def end(
178247
with_label: bool = False,
179248
with_emote: bool = True,
180249
with_disabled: bool = False,
181-
**kwargs,
250+
**kwargs: object,
182251
):
183252
return cls.create_button(
184253
"End", cls.END_ID, "⏹️", with_label, with_emote, with_disabled, **kwargs

nameless/custom/ui/view/__init__.py

-4
This file was deleted.

0 commit comments

Comments
 (0)