Skip to content

Commit 5d28571

Browse files
NeloBlivionpre-commit-ci[bot]Lulalabytibue99Paillat-dev
authored
feat: redo CV2 and New Modal implementation (#2904)
Signed-off-by: UK <[email protected]> Signed-off-by: Nelo <[email protected]> Signed-off-by: Paillat <[email protected]> Signed-off-by: Lala Sabathil <[email protected]> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Lala Sabathil <[email protected]> Co-authored-by: Timo <[email protected]> Co-authored-by: Paillat <[email protected]>
1 parent b190b7f commit 5d28571

31 files changed

+2561
-1018
lines changed

CHANGELOG.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@ These changes are available on the `master` branch, but have not yet been releas
3030
- Adds pre-typed and pre-constructed with select_type `ui.Select` aliases for the
3131
different select types: `ui.StringSelect`, `ui.UserSelect`, `ui.RoleSelect`,
3232
`ui.MentionableSelect`, and `ui.ChannelSelect`.
33+
- Added `store` parameter to `View` and `Modal` classes.
34+
([#2904](https://github.com/Pycord-Development/pycord/pull/2904/))
35+
- Added `Webhook.parent` and `Webhook.from_interaction`
36+
([#2904](https://github.com/Pycord-Development/pycord/pull/2904/))
3337
- Added the ability to use functions with any number of optional arguments and functions
3438
returning an awaitable as `Option.autocomplete`.
3539
([#2914](https://github.com/Pycord-Development/pycord/pull/2914))
@@ -41,6 +45,23 @@ These changes are available on the `master` branch, but have not yet been releas
4145

4246
### Changed
4347

48+
- Overhauled support for Components V2 and new Modal components
49+
([#2904](https://github.com/Pycord-Development/pycord/pull/2904/))
50+
- Revert `discord.ui.View` and `discord.ui.Modal` to 2.6.1 behavior; not compatible
51+
with new features.
52+
- Implemented `discord.ui.DesignerView` and `discord.ui.DesignerModal` to support new
53+
components.
54+
- `DesignerView` and `Container` do not support `Button` and `Select` directly; use
55+
`discord.ui.ActionRow` instead.
56+
- `DesignerModal` does not support `InputText` and `Select` directly; use
57+
`discord.ui.Label` instead.
58+
- Removed `InputText.description`, `Select.label` and `Select.description`; these are
59+
now attributes of `Label`.
60+
- `discord.ui.Item` is now a base class for `ViewItem` and `ModalItem`; all items
61+
inherit from these.
62+
- All view and modal classes now inherit from a base `ItemInterface` class, split into
63+
`BaseView` and `BaseModal`
64+
4465
### Fixed
4566

4667
- Manage silence for new SSRC with existing user_id.

discord/abc.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@
9595
from .types.channel import GuildChannel as GuildChannelPayload
9696
from .types.channel import OverwriteType
9797
from .types.channel import PermissionOverwrite as PermissionOverwritePayload
98-
from .ui.view import View
98+
from .ui.view import BaseView
9999
from .user import ClientUser
100100

101101
PartialMessageableChannel = Union[
@@ -1355,7 +1355,7 @@ async def send(
13551355
allowed_mentions: AllowedMentions = ...,
13561356
reference: Message | MessageReference | PartialMessage = ...,
13571357
mention_author: bool = ...,
1358-
view: View = ...,
1358+
view: BaseView = ...,
13591359
poll: Poll = ...,
13601360
suppress: bool = ...,
13611361
silent: bool = ...,
@@ -1376,7 +1376,7 @@ async def send(
13761376
allowed_mentions: AllowedMentions = ...,
13771377
reference: Message | MessageReference | PartialMessage = ...,
13781378
mention_author: bool = ...,
1379-
view: View = ...,
1379+
view: BaseView = ...,
13801380
poll: Poll = ...,
13811381
suppress: bool = ...,
13821382
silent: bool = ...,
@@ -1397,7 +1397,7 @@ async def send(
13971397
allowed_mentions: AllowedMentions = ...,
13981398
reference: Message | MessageReference | PartialMessage = ...,
13991399
mention_author: bool = ...,
1400-
view: View = ...,
1400+
view: BaseView = ...,
14011401
poll: Poll = ...,
14021402
suppress: bool = ...,
14031403
silent: bool = ...,
@@ -1418,7 +1418,7 @@ async def send(
14181418
allowed_mentions: AllowedMentions = ...,
14191419
reference: Message | MessageReference | PartialMessage = ...,
14201420
mention_author: bool = ...,
1421-
view: View = ...,
1421+
view: BaseView = ...,
14221422
poll: Poll = ...,
14231423
suppress: bool = ...,
14241424
silent: bool = ...,
@@ -1509,7 +1509,7 @@ async def send(
15091509
If set, overrides the :attr:`~discord.AllowedMentions.replied_user` attribute of ``allowed_mentions``.
15101510
15111511
.. versionadded:: 1.6
1512-
view: :class:`discord.ui.View`
1512+
view: :class:`discord.ui.BaseView`
15131513
A Discord UI View to add to the message.
15141514
embeds: List[:class:`~discord.Embed`]
15151515
A list of embeds to upload. Must be a maximum of 10.
@@ -1611,7 +1611,7 @@ async def send(
16111611
if view:
16121612
if not hasattr(view, "__discord_ui_view__"):
16131613
raise InvalidArgument(
1614-
f"view parameter must be View not {view.__class__!r}"
1614+
f"view parameter must be BaseView not {view.__class__!r}"
16151615
)
16161616

16171617
components = view.to_components()

discord/channel.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@
107107
from .types.channel import VoiceChannelEffectSendEvent as VoiceChannelEffectSend
108108
from .types.snowflake import SnowflakeList
109109
from .types.threads import ThreadArchiveDuration
110-
from .ui.view import View
110+
from .ui.view import BaseView
111111
from .user import BaseUser, ClientUser, User
112112
from .webhook import Webhook
113113

@@ -1217,7 +1217,7 @@ async def create_thread(
12171217
delete_message_after: float | None = None,
12181218
nonce: int | str | None = None,
12191219
allowed_mentions: AllowedMentions | None = None,
1220-
view: View | None = None,
1220+
view: BaseView | None = None,
12211221
applied_tags: list[ForumTag] | None = None,
12221222
suppress: bool = False,
12231223
silent: bool = False,
@@ -1262,7 +1262,7 @@ async def create_thread(
12621262
to the object, otherwise it uses the attributes set in :attr:`~discord.Client.allowed_mentions`.
12631263
If no object is passed at all then the defaults given by :attr:`~discord.Client.allowed_mentions`
12641264
are used instead.
1265-
view: :class:`discord.ui.View`
1265+
view: :class:`discord.ui.BaseView`
12661266
A Discord UI View to add to the message.
12671267
applied_tags: List[:class:`discord.ForumTag`]
12681268
A list of tags to apply to the new thread.
@@ -1328,7 +1328,7 @@ async def create_thread(
13281328
if view:
13291329
if not hasattr(view, "__discord_ui_view__"):
13301330
raise InvalidArgument(
1331-
f"view parameter must be View not {view.__class__!r}"
1331+
f"view parameter must be BaseView not {view.__class__!r}"
13321332
)
13331333

13341334
components = view.to_components()

discord/client.py

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@
6767
from .sticker import GuildSticker, StandardSticker, StickerPack, _sticker_factory
6868
from .template import Template
6969
from .threads import Thread
70-
from .ui.view import View
70+
from .ui.view import BaseView
7171
from .user import ClientUser, User
7272
from .utils import _D, _FETCHABLE, MISSING
7373
from .voice_client import VoiceClient
@@ -90,7 +90,7 @@
9090
from .poll import Poll
9191
from .soundboard import SoundboardSound
9292
from .threads import Thread, ThreadMember
93-
from .ui.item import Item
93+
from .ui.item import Item, ViewItem
9494
from .voice_client import VoiceProtocol
9595

9696
__all__ = ("Client",)
@@ -562,19 +562,19 @@ async def on_error(self, event_method: str, *args: Any, **kwargs: Any) -> None:
562562
traceback.print_exc()
563563

564564
async def on_view_error(
565-
self, error: Exception, item: Item, interaction: Interaction
565+
self, error: Exception, item: ViewItem, interaction: Interaction
566566
) -> None:
567567
"""|coro|
568568
569569
The default view error handler provided by the client.
570570
571-
This only fires for a view if you did not define its :func:`~discord.ui.View.on_error`.
571+
This only fires for a view if you did not define its :func:`~discord.ui.BaseView.on_error`.
572572
573573
Parameters
574574
----------
575575
error: :class:`Exception`
576576
The exception that was raised.
577-
item: :class:`Item`
577+
item: :class:`ViewItem`
578578
The item that the user interacted with.
579579
interaction: :class:`Interaction`
580580
The interaction that was received.
@@ -2100,8 +2100,8 @@ async def create_dm(self, user: Snowflake) -> DMChannel:
21002100
data = await state.http.start_private_message(user.id)
21012101
return state.add_dm_channel(data)
21022102

2103-
def add_view(self, view: View, *, message_id: int | None = None) -> None:
2104-
"""Registers a :class:`~discord.ui.View` for persistent listening.
2103+
def add_view(self, view: BaseView, *, message_id: int | None = None) -> None:
2104+
"""Registers a :class:`~discord.ui.BaseView` for persistent listening.
21052105
21062106
This method should be used for when a view is comprised of components
21072107
that last longer than the lifecycle of the program.
@@ -2110,7 +2110,7 @@ def add_view(self, view: View, *, message_id: int | None = None) -> None:
21102110
21112111
Parameters
21122112
----------
2113-
view: :class:`discord.ui.View`
2113+
view: :class:`discord.ui.BaseView`
21142114
The view to register for dispatching.
21152115
message_id: Optional[:class:`int`]
21162116
The message ID that the view is attached to. This is currently used to
@@ -2126,8 +2126,8 @@ def add_view(self, view: View, *, message_id: int | None = None) -> None:
21262126
and all their components have an explicitly provided ``custom_id``.
21272127
"""
21282128

2129-
if not isinstance(view, View):
2130-
raise TypeError(f"expected an instance of View not {view.__class__!r}")
2129+
if not isinstance(view, BaseView):
2130+
raise TypeError(f"expected an instance of BaseView not {view.__class__!r}")
21312131

21322132
if not view.is_persistent():
21332133
raise ValueError(
@@ -2138,7 +2138,7 @@ def add_view(self, view: View, *, message_id: int | None = None) -> None:
21382138
self._connection.store_view(view, message_id)
21392139

21402140
@property
2141-
def persistent_views(self) -> Sequence[View]:
2141+
def persistent_views(self) -> Sequence[BaseView]:
21422142
"""A sequence of persistent views added to the client.
21432143
21442144
.. versionadded:: 2.0

discord/components.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ def __init__(self, data: ComponentPayload):
178178

179179
@property
180180
def width(self):
181-
"""Return the sum of the children's widths."""
181+
"""Returns the sum of the item's widths."""
182182
t = 0
183183
for item in self.children:
184184
t += 1 if item.type is ComponentType.button else 5
@@ -194,6 +194,10 @@ def to_dict(self) -> ActionRowPayload:
194194
def walk_components(self) -> Iterator[Component]:
195195
yield from self.children
196196

197+
@property
198+
def components(self) -> list[Component]:
199+
return self.children
200+
197201
def get_component(self, id: str | int) -> Component | None:
198202
"""Get a component from this action row. Roughly equivalent to `utils.get(row.children, ...)`.
199203
If an ``int`` is provided, the component will be retrieved by ``id``, otherwise by ``custom_id``.
@@ -268,7 +272,7 @@ def __init__(self, data: InputTextComponentPayload):
268272
self.id: int | None = data.get("id")
269273
self.style: InputTextStyle = try_enum(InputTextStyle, data["style"])
270274
self.custom_id = data["custom_id"]
271-
self.label: str = data.get("label", None)
275+
self.label: str | None = data.get("label", None)
272276
self.placeholder: str | None = data.get("placeholder", None)
273277
self.min_length: int | None = data.get("min_length", None)
274278
self.max_length: int | None = data.get("max_length", None)
@@ -280,7 +284,6 @@ def to_dict(self) -> InputTextComponentPayload:
280284
"type": 4,
281285
"id": self.id,
282286
"style": self.style.value,
283-
"label": self.label,
284287
}
285288
if self.custom_id:
286289
payload["custom_id"] = self.custom_id
@@ -300,6 +303,9 @@ def to_dict(self) -> InputTextComponentPayload:
300303
if self.value:
301304
payload["value"] = self.value
302305

306+
if self.label:
307+
payload["label"] = self.label
308+
303309
return payload # type: ignore
304310

305311

@@ -1306,7 +1312,7 @@ class Label(Component):
13061312
``component`` may only be:
13071313
13081314
- :class:`InputText`
1309-
- :class:`SelectMenu` (string)
1315+
- :class:`SelectMenu`
13101316
13111317
This inherits from :class:`Component`.
13121318

0 commit comments

Comments
 (0)