-
-
Notifications
You must be signed in to change notification settings - Fork 477
feat: Modal Selects #2858
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
feat: Modal Selects #2858
Changes from all commits
827524e
48e1557
dcdea3f
6e68e6a
4686ea0
be6f1c0
5dd4026
e76fd92
20f1096
e1c3760
cf33b2b
132a63f
bf614aa
20b39bf
24f018b
7dd44f5
4be7d14
2c3ab0d
9a75635
0ddc5d2
68ecdd4
a54c449
5b53a3a
e70b067
d9e6939
db08582
a1ded7e
4455bda
0cf4938
ac8b012
f6b0d59
64f2406
2332b87
18cf7fa
9e29a09
7dfe5c2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -50,6 +50,7 @@ | |||||
from .types.components import ContainerComponent as ContainerComponentPayload | ||||||
from .types.components import FileComponent as FileComponentPayload | ||||||
from .types.components import InputText as InputTextComponentPayload | ||||||
from .types.components import LabelComponent as LabelComponentPayload | ||||||
from .types.components import MediaGalleryComponent as MediaGalleryComponentPayload | ||||||
from .types.components import MediaGalleryItem as MediaGalleryItemPayload | ||||||
from .types.components import SectionComponent as SectionComponentPayload | ||||||
|
@@ -76,6 +77,7 @@ | |||||
"FileComponent", | ||||||
"Separator", | ||||||
"Container", | ||||||
"Label", | ||||||
) | ||||||
|
||||||
C = TypeVar("C", bound="Component") | ||||||
|
@@ -375,6 +377,10 @@ class SelectMenu(Component): | |||||
Added support for :attr:`ComponentType.user_select`, :attr:`ComponentType.role_select`, | ||||||
:attr:`ComponentType.mentionable_select`, and :attr:`ComponentType.channel_select`. | ||||||
|
||||||
.. versionchanged:: 2.7 | ||||||
|
||||||
Added the :attr:`required` attribute for use in modals. | ||||||
|
||||||
Attributes | ||||||
---------- | ||||||
type: :class:`ComponentType` | ||||||
|
@@ -399,6 +405,8 @@ class SelectMenu(Component): | |||||
except for :attr:`ComponentType.channel_select`. | ||||||
disabled: :class:`bool` | ||||||
Whether the select is disabled or not. | ||||||
required: Optional[:class:`bool`] | ||||||
Whether the select is required or not. Only useable in modals. Defaults to ``False``. | ||||||
""" | ||||||
|
||||||
__slots__: tuple[str, ...] = ( | ||||||
|
@@ -409,6 +417,7 @@ class SelectMenu(Component): | |||||
"options", | ||||||
"channel_types", | ||||||
"disabled", | ||||||
"required", | ||||||
) | ||||||
|
||||||
__repr_info__: ClassVar[tuple[str, ...]] = __slots__ | ||||||
|
@@ -428,6 +437,9 @@ def __init__(self, data: SelectMenuPayload): | |||||
self.channel_types: list[ChannelType] = [ | ||||||
try_enum(ChannelType, ct) for ct in data.get("channel_types", []) | ||||||
] | ||||||
self.required: bool | None = data.get( | ||||||
"required" | ||||||
) # Currently defaults to False, pending change | ||||||
|
||||||
def to_dict(self) -> SelectMenuPayload: | ||||||
payload: SelectMenuPayload = { | ||||||
|
@@ -445,6 +457,8 @@ def to_dict(self) -> SelectMenuPayload: | |||||
payload["channel_types"] = [ct.value for ct in self.channel_types] | ||||||
if self.placeholder: | ||||||
payload["placeholder"] = self.placeholder | ||||||
if self.required is not None: | ||||||
payload["required"] = self.required | ||||||
|
||||||
return payload | ||||||
|
||||||
|
@@ -1037,6 +1051,55 @@ def walk_components(self) -> Iterator[Component]: | |||||
yield c | ||||||
|
||||||
|
||||||
class Label(Component): | ||||||
"""Represents a Label used in modals as the top-level component. | ||||||
|
||||||
This is a component that holda another component alongside additional text in modals. | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No plsplspls keep that one lol |
||||||
``component`` may only be: | ||||||
|
||||||
- :class:`InputText` | ||||||
- :class:`SelectMenu` (string) | ||||||
|
||||||
This inherits from :class:`Component`. | ||||||
|
||||||
.. versionadded:: 2.7 | ||||||
|
||||||
Attributes | ||||||
---------- | ||||||
component: :class:`Component` | ||||||
The component contained in this label. Currently supports :class:`InputText` and :class:`SelectMenu`. | ||||||
label: :class:`str` | ||||||
The main text associated with this label's ``component``, up to 45 characters. | ||||||
description: Optional[:class:`str`] | ||||||
The description associated with this label's ``component``, up to 100 characters. | ||||||
""" | ||||||
|
||||||
__slots__: tuple[str, ...] = ("component", "label", "description") | ||||||
|
||||||
__repr_info__: ClassVar[tuple[str, ...]] = __slots__ | ||||||
versions: tuple[int, ...] = () | ||||||
|
||||||
def __init__(self, data: LabelComponentPayload): | ||||||
self.type: ComponentType = try_enum(ComponentType, data["type"]) | ||||||
self.id: int = data["id"] | ||||||
self.component: Component = _component_factory(data["component"]) | ||||||
self.label: str = data["label"] | ||||||
self.description: str | None = data.get("description") | ||||||
|
||||||
def to_dict(self) -> LabelComponentPayload: | ||||||
payload = { | ||||||
"type": int(self.type), | ||||||
"id": self.id, | ||||||
"component": self.component.to_dict(), | ||||||
"label": self.label, | ||||||
"description": self.description, | ||||||
} | ||||||
return payload | ||||||
|
||||||
def walk_components(self) -> Iterator[Component]: | ||||||
yield from [self.component] | ||||||
|
||||||
|
||||||
COMPONENT_MAPPINGS = { | ||||||
1: ActionRow, | ||||||
2: Button, | ||||||
|
@@ -1053,6 +1116,7 @@ def walk_components(self) -> Iterator[Component]: | |||||
13: FileComponent, | ||||||
14: Separator, | ||||||
17: Container, | ||||||
18: Label, | ||||||
} | ||||||
|
||||||
STATE_COMPONENTS = (Section, Container, Thumbnail, MediaGallery, FileComponent) | ||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -193,6 +193,7 @@ class Interaction: | |
"view", | ||
"modal", | ||
"attachment_size_limit", | ||
"_raw_data", | ||
"_channel_data", | ||
"_message_data", | ||
"_guild_data", | ||
|
@@ -215,6 +216,7 @@ def __init__(self, *, data: InteractionPayload, state: ConnectionState): | |
self._from_data(data) | ||
|
||
def _from_data(self, data: InteractionPayload): | ||
self._raw_data: InteractionPayload = data | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. tbf we might want to pr that to keep it not just for testing lol There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. pls |
||
self.id: int = int(data["id"]) | ||
self.type: InteractionType = try_enum(InteractionType, data["type"]) | ||
self.data: InteractionData | None = data.get("data") | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pending change?
Also why
Optional[bool]
defaulting toNone
instead ofbool
defaulting toFalse
?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
because required is only for string selects in modals. it doesn't work in message components
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
and pending cause advaith is still working on stuff