Skip to content

Commit 0b58904

Browse files
authored
attempt splitting into ViewItem and ModalItem
1 parent 43df60f commit 0b58904

File tree

3 files changed

+99
-44
lines changed

3 files changed

+99
-44
lines changed

discord/ui/input_text.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
from ..components import InputText as InputTextComponent
77
from ..enums import ComponentType, InputTextStyle
8+
from .item import ModalItem
89

910
__all__ = ("InputText", "TextInput")
1011

@@ -13,7 +14,7 @@
1314
from ..types.components import InputText as InputTextComponentPayload
1415

1516

16-
class InputText:
17+
class InputText(ModalItem):
1718
"""Represents a UI text input field.
1819
1920
.. versionadded:: 2.0

discord/ui/item.py

Lines changed: 95 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -29,19 +29,23 @@
2929

3030
from ..interactions import Interaction
3131

32-
__all__ = ("Item",)
32+
__all__ = ("Item", "ViewItem", "ModalItem", )
3333

3434
if TYPE_CHECKING:
3535
from ..components import Component
3636
from ..enums import ComponentType
37+
from .core import ItemInterface
38+
from .modal import BaseModal
3739
from .view import BaseView
3840

3941
I = TypeVar("I", bound="Item")
42+
T = TypeVar("IF", bound="ItemInterface", covariant=True)
4043
V = TypeVar("V", bound="BaseView", covariant=True)
44+
M = TypeVar("M", bound="BaseModal", covariant=True)
4145
ItemCallbackType = Callable[[Any, I, Interaction], Coroutine[Any, Any, Any]]
4246

4347

44-
class Item(Generic[V]):
48+
class Item(Generic[T]):
4549
"""Represents the base UI item that all UI components inherit from.
4650
4751
The following are the original items supported in :class:`discord.ui.View`:
@@ -65,21 +69,12 @@ class Item(Generic[V]):
6569
Added V2 Components.
6670
"""
6771

68-
__item_repr_attributes__: tuple[str, ...] = ("row",)
72+
__item_repr_attributes__: tuple[str, ...] = ("id",)
6973

7074
def __init__(self):
71-
self._view: V | None = None
72-
self._row: int | None = None
73-
self._rendered_row: int | None = None
7475
self._underlying: Component | None = None
75-
# This works mostly well but there is a gotcha with
76-
# the interaction with from_component, since that technically provides
77-
# a custom_id most dispatchable items would get this set to True even though
78-
# it might not be provided by the library user. However, this edge case doesn't
79-
# actually affect the intended purpose of this check because from_component is
80-
# only called upon edit and we're mainly interested during initial creation time.
8176
self._provided_custom_id: bool = False
82-
self.parent: Item | BaseView | None = self.view
77+
self.parent: Item | ItemInterface | None = None
8378

8479
def to_component_dict(self) -> dict[str, Any]:
8580
raise NotImplementedError
@@ -90,9 +85,6 @@ def refresh_component(self, component: Component) -> None:
9085
def refresh_state(self, interaction: Interaction) -> None:
9186
return None
9287

93-
def refresh_from_modal(self, interaction: Interaction, data: dict) -> None:
94-
return None
95-
9688
@classmethod
9789
def from_component(cls: type[I], component: Component) -> I:
9890
return cls()
@@ -110,9 +102,6 @@ def is_storable(self) -> bool:
110102
def is_persistent(self) -> bool:
111103
return not self.is_dispatchable() or self._provided_custom_id
112104

113-
def uses_label(self) -> bool:
114-
return False
115-
116105
def copy_text(self) -> str:
117106
return ""
118107

@@ -122,6 +111,55 @@ def __repr__(self) -> str:
122111
)
123112
return f"<{self.__class__.__name__} {attrs}>"
124113

114+
@property
115+
def id(self) -> int | None:
116+
"""Gets this item's ID.
117+
118+
This can be set by the user when constructing an Item. If not, Discord will automatically provide one when the item's parent is sent.
119+
120+
Returns
121+
-------
122+
Optional[:class:`int`]
123+
The ID of this item, or ``None`` if the user didn't set one.
124+
"""
125+
return self._underlying and self._underlying.id
126+
127+
@id.setter
128+
def id(self, value) -> None:
129+
if not self._underlying:
130+
return
131+
self._underlying.id = value
132+
133+
class ViewItem(Item[V]):
134+
"""Represents an item used in Views.
135+
136+
The following are the original items supported in :class:`discord.ui.View`:
137+
138+
- :class:`discord.ui.Button`
139+
- :class:`discord.ui.Select`
140+
141+
And the following are new items under the "Components V2" specification for use in :class:`discord.ui.DesignerView`:
142+
143+
- :class:`discord.ui.Section`
144+
- :class:`discord.ui.TextDisplay`
145+
- :class:`discord.ui.Thumbnail`
146+
- :class:`discord.ui.MediaGallery`
147+
- :class:`discord.ui.File`
148+
- :class:`discord.ui.Separator`
149+
- :class:`discord.ui.Container`
150+
151+
Additionally, :class:`discord.ui.ActionRow` should be used in :class:`discord.ui.DesignerView` to support :class:`discord.ui.Button` and :class:`discord.ui.Select`.
152+
153+
.. versionadded:: 2.7
154+
"""
155+
156+
def __init__(self):
157+
super().__init__()
158+
self._view: V | None = None
159+
self._row: int | None = None
160+
self._rendered_row: int | None = None
161+
self.parent: Item | BaseView | None = self.view
162+
125163
@property
126164
def row(self) -> int | None:
127165
"""Gets or sets the row position of this item within its parent view.
@@ -164,30 +202,11 @@ def width(self) -> int:
164202
"""
165203
return 1
166204

167-
@property
168-
def id(self) -> int | None:
169-
"""Gets this item's ID.
170-
171-
This can be set by the user when constructing an Item. If not, Discord will automatically provide one when the View is sent.
172-
173-
Returns
174-
-------
175-
Optional[:class:`int`]
176-
The ID of this item, or ``None`` if the user didn't set one.
177-
"""
178-
return self._underlying and self._underlying.id
179-
180-
@id.setter
181-
def id(self, value) -> None:
182-
if not self._underlying:
183-
return
184-
self._underlying.id = value
185-
186205
@property
187206
def view(self) -> V | None:
188207
"""Gets the parent view associated with this item.
189208
190-
The view refers to the container that holds this item. This is typically set
209+
The view refers to the structure that holds this item. This is typically set
191210
automatically when the item is added to a view.
192211
193212
Returns
@@ -213,3 +232,40 @@ async def callback(self, interaction: Interaction):
213232
interaction: :class:`.Interaction`
214233
The interaction that triggered this UI item.
215234
"""
235+
236+
class ModalItem(Item[M]):
237+
"""Represents an item used in Modals.
238+
239+
:class:`discord.ui.InputText` is the original item supported in :class:`discord.ui.Modal`.
240+
241+
The following are newly available in :class:`discord.ui.DesignerModal`:
242+
243+
- :class:`discord.ui.Label`
244+
- :class:`discord.ui.TextDisplay`
245+
246+
.. versionadded:: 2.7
247+
"""
248+
249+
def __init__(self):
250+
super().__init__()
251+
self._modal: V | None = None
252+
self.parent: Item | BaseModal | None = self.modal
253+
254+
def refresh_from_modal(self, interaction: Interaction, data: dict) -> None:
255+
return None
256+
257+
@property
258+
def modal(self) -> V | None:
259+
"""Gets the parent modal associated with this item. This is typically set
260+
automatically when the item is added to a modal.
261+
262+
Returns
263+
-------
264+
Optional[:class:`BaseModal`]
265+
The parent modal of this item, or ``None`` if the item is not attached to any modal.
266+
"""
267+
return self._modal
268+
269+
@modal.setter
270+
def modal(self, value) -> None:
271+
self._modal = value

discord/ui/label.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
from ..utils import find, get
1010
from .button import Button
1111
from .input_text import InputText
12-
from .item import Item, ItemCallbackType
12+
from .item import ModalItem, ItemCallbackType
1313
from .select import Select
1414

1515
__all__ = ("Label",)
@@ -28,7 +28,7 @@
2828
M = TypeVar("M", bound="DesignerModal", covariant=True)
2929

3030

31-
class Label(Item[M]):
31+
class Label(ModalItem[M]):
3232
"""Represents a UI Label used in :class:`discord.ui.DesignerModal`.
3333
3434
The items currently supported are as follows:
@@ -351,5 +351,3 @@ def from_component(cls: type[L], component: LabelComponent) -> L:
351351
label=component.label,
352352
description=component.description,
353353
)
354-
355-
callback = None

0 commit comments

Comments
 (0)