-
-
Notifications
You must be signed in to change notification settings - Fork 482
feat: redo CV2 and New Modal implementation #2904
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
Open
NeloBlivion
wants to merge
100
commits into
Pycord-Development:master
Choose a base branch
from
NeloBlivion:cv2_fixes
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 12 commits
Commits
Show all changes
100 commits
Select commit
Hold shift + click to select a range
2fcd3a9
downgrade view
NeloBlivion 027527d
Merge branch 'master' into cv2_fixes
NeloBlivion b319d13
skeleton for actionrow
NeloBlivion fcb0849
style(pre-commit): auto fixes from pre-commit.com hooks
pre-commit-ci[bot] d1f33ea
cleanup
NeloBlivion 8efedd3
style(pre-commit): auto fixes from pre-commit.com hooks
pre-commit-ci[bot] 54afda3
Merge branch 'master' into cv2_fixes
Lulalaby 6d6ce3e
eh..... going through it... don't judge yet................
NeloBlivion f13f5e0
style(pre-commit): auto fixes from pre-commit.com hooks
pre-commit-ci[bot] b322b42
correct
NeloBlivion c0022f1
v2
NeloBlivion e830df4
style(pre-commit): auto fixes from pre-commit.com hooks
pre-commit-ci[bot] be236bf
Merge branch 'master' into cv2_fixes
NeloBlivion 23f296d
better separation of views
NeloBlivion 57a0d98
style(pre-commit): auto fixes from pre-commit.com hooks
pre-commit-ci[bot] eaa2c30
import
NeloBlivion c6c4fbf
)
NeloBlivion 57282b8
))
NeloBlivion 1da73f6
style(pre-commit): auto fixes from pre-commit.com hooks
pre-commit-ci[bot] 2b981d3
attempt modal conversion
NeloBlivion c929c67
style(pre-commit): auto fixes from pre-commit.com hooks
pre-commit-ci[bot] e61064d
types
NeloBlivion d8e3d4f
style(pre-commit): auto fixes from pre-commit.com hooks
pre-commit-ci[bot] 057a26b
container uses actionrow instead of button/select, remove decorator s…
NeloBlivion b7a8f6b
style(pre-commit): auto fixes from pre-commit.com hooks
pre-commit-ci[bot] 166f540
types
NeloBlivion a7346cd
style(pre-commit): auto fixes from pre-commit.com hooks
pre-commit-ci[bot] 836998d
imports
NeloBlivion 16b4886
style(pre-commit): auto fixes from pre-commit.com hooks
pre-commit-ci[bot] 5255da1
remove Select.label & Select.description
NeloBlivion a1068fb
update refresh logic
NeloBlivion e199c8c
style(pre-commit): auto fixes from pre-commit.com hooks
pre-commit-ci[bot] 0dc7522
typext
NeloBlivion bfd4aed
reduce further
NeloBlivion 1223dea
fix __all__
NeloBlivion 3a82843
style(pre-commit): auto fixes from pre-commit.com hooks
pre-commit-ci[bot] 25fbd2a
typecheck
NeloBlivion 3ee00e0
style(pre-commit): auto fixes from pre-commit.com hooks
pre-commit-ci[bot] 61a1433
__
NeloBlivion edb4951
dispatch
NeloBlivion d9c465b
ComponentType
NeloBlivion 1ae1c77
types ?
NeloBlivion bd60e9b
style(pre-commit): auto fixes from pre-commit.com hooks
pre-commit-ci[bot] 090af2e
typecheck again
NeloBlivion 00faca4
attrs
NeloBlivion 5c7a02b
fixes
NeloBlivion 1975f6d
adjust
NeloBlivion 2816b1b
style(pre-commit): auto fixes from pre-commit.com hooks
pre-commit-ci[bot] e615190
actionrow components
NeloBlivion 93fb09a
arc
NeloBlivion 0517d2e
button priority
NeloBlivion e32fdad
style(pre-commit): auto fixes from pre-commit.com hooks
pre-commit-ci[bot] bdb6d21
maybe?
NeloBlivion 20aae0f
no
NeloBlivion a846b43
update examples
NeloBlivion 7caf4f5
style(pre-commit): auto fixes from pre-commit.com hooks
pre-commit-ci[bot] 0060e0f
remove v2 from weights
NeloBlivion 8308615
misc
NeloBlivion 5410e00
adjust Label args (first arg label)
NeloBlivion d4dc1c5
add select overloads
NeloBlivion b619025
actionrow clarification
NeloBlivion f90a3bc
style(pre-commit): auto fixes from pre-commit.com hooks
pre-commit-ci[bot] 35e4cb1
all items in actionrow have the disabled attribute
NeloBlivion 65a1116
fixes
NeloBlivion e453e01
style(pre-commit): auto fixes from pre-commit.com hooks
pre-commit-ci[bot] e9ac8bc
more imports
NeloBlivion b2ed0d1
style(pre-commit): auto fixes from pre-commit.com hooks
pre-commit-ci[bot] 9ca373a
docs and typing cleanup
NeloBlivion 0acb103
update _component_to_item
NeloBlivion 43df60f
fix to_component_dict
NeloBlivion 0b58904
attempt splitting into ViewItem and ModalItem
NeloBlivion 3a8bb10
style(pre-commit): auto fixes from pre-commit.com hooks
pre-commit-ci[bot] 64f3c4f
more
NeloBlivion 45a5c44
style(pre-commit): auto fixes from pre-commit.com hooks
pre-commit-ci[bot] 4ee4b70
guys don't you love typing changes
NeloBlivion fd67ea2
style(pre-commit): auto fixes from pre-commit.com hooks
pre-commit-ci[bot] 148535a
types
NeloBlivion bcc1a7a
style(pre-commit): auto fixes from pre-commit.com hooks
pre-commit-ci[bot] 712cd3c
this is required apparently
NeloBlivion ef78980
self.modal
NeloBlivion 9cf2886
set modal
NeloBlivion 62ffcdf
no weights in basemodal
NeloBlivion a961d49
undo on_modal_error change
NeloBlivion 8664272
style(pre-commit): auto fixes from pre-commit.com hooks
pre-commit-ci[bot] fbac652
define Item.type
NeloBlivion c2bd6b5
further consolidate
NeloBlivion 9255c39
style(pre-commit): auto fixes from pre-commit.com hooks
pre-commit-ci[bot] 8fdc3f1
oops
NeloBlivion 8a9fe8f
fix modal init
NeloBlivion 38352c2
actual fix
NeloBlivion 1d790da
forgot modal children thing
NeloBlivion 846b14d
clarify
NeloBlivion 157d8c7
adjust item docs
NeloBlivion fb01cfe
copyright
NeloBlivion 340b5d5
children
NeloBlivion 3f3ae31
Update discord/ui/action_row.py
NeloBlivion be9eb51
add Webhook.parent
NeloBlivion cf49aa3
style(pre-commit): auto fixes from pre-commit.com hooks
pre-commit-ci[bot] 017f15f
add Webhook.from_interaction
NeloBlivion bba29af
slots
NeloBlivion File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,346 @@ | ||
from __future__ import annotations | ||
|
||
from functools import partial | ||
from typing import TYPE_CHECKING, ClassVar, Iterator, TypeVar | ||
|
||
from ..components import ActionRow as ActionRowComponent | ||
from ..components import SelectOption, _component_factory | ||
from ..enums import ButtonStyle, ChannelType, ComponentType | ||
from ..utils import find, get | ||
from .button import Button | ||
from .file import File | ||
from .item import Item, ItemCallbackType | ||
from .select import Select | ||
|
||
__all__ = ("ActionRow",) | ||
|
||
if TYPE_CHECKING: | ||
from typing_extensions import Self | ||
|
||
from ..emoji import AppEmoji, GuildEmoji | ||
from ..partial_emoji import PartialEmoji, _EmojiTag | ||
from ..types.components import ActionRow as ActionRowPayload | ||
from .view import View | ||
|
||
|
||
A = TypeVar("A", bound="ActionRow") | ||
V = TypeVar("V", bound="View", covariant=True) | ||
|
||
|
||
class ActionRow(Item[V]): | ||
"""Represents a UI Action Row used in :class:`discord.ui.View`. | ||
|
||
The items supported are as follows: | ||
|
||
- :class:`discord.ui.Select` | ||
- :class:`discord.ui.Button` | ||
|
||
.. versionadded:: 2.7 | ||
|
||
Parameters | ||
---------- | ||
*items: :class:`Item` | ||
The initial items in this action row. | ||
id: Optional[:class:`int`] | ||
The action's ID. | ||
""" | ||
|
||
__item_repr_attributes__: tuple[str, ...] = ( | ||
"items", | ||
NeloBlivion marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
"id", | ||
) | ||
|
||
__row_children_items__: ClassVar[list[ItemCallbackType]] = [] | ||
|
||
def __init_subclass__(cls) -> None: | ||
children: list[ItemCallbackType] = [] | ||
for base in reversed(cls.__mro__): | ||
for member in base.__dict__.values(): | ||
if hasattr(member, "__discord_ui_model_type__"): | ||
children.append(member) | ||
|
||
cls.__row_children_items__ = children | ||
|
||
def __init__( | ||
self, | ||
*items: Item, | ||
id: int | None = None, | ||
): | ||
super().__init__() | ||
|
||
self.items: list[Item] = [] | ||
|
||
self._underlying = ActionRowComponent._raw_construct( | ||
type=ComponentType.action_row, | ||
id=id, | ||
components=[], | ||
) | ||
|
||
for func in self.__row_children_items__: | ||
item: Item = func.__discord_ui_model_type__( | ||
**func.__discord_ui_model_kwargs__ | ||
) | ||
item.callback = partial(func, self, item) | ||
self.add_item(item) | ||
setattr(self, func.__name__, item) | ||
for i in items: | ||
self.add_item(i) | ||
|
||
def _add_component_from_item(self, item: Item): | ||
self._underlying.components.append(item._underlying) | ||
|
||
def _set_components(self, items: list[Item]): | ||
self._underlying.components.clear() | ||
for item in items: | ||
self._add_component_from_item(item) | ||
|
||
def add_item(self, item: Item) -> Self: | ||
"""Adds an item to the action row. | ||
|
||
Parameters | ||
---------- | ||
item: :class:`Item` | ||
The item to add to the action row. | ||
|
||
Raises | ||
------ | ||
TypeError | ||
An :class:`Item` was not passed. | ||
""" | ||
|
||
if not isinstance(item, Item): | ||
raise TypeError(f"expected Item not {item.__class__!r}") | ||
|
||
item._view = self.view | ||
item.parent = self | ||
|
||
self.items.append(item) | ||
self._add_component_from_item(item) | ||
return self | ||
|
||
def remove_item(self, item: Item | str | int) -> Self: | ||
"""Removes an item from the action row. If an int or str is passed, it will remove by Item :attr:`id` or ``custom_id`` respectively. | ||
|
||
Parameters | ||
---------- | ||
item: Union[:class:`Item`, :class:`int`, :class:`str`] | ||
The item, ``id``, or item ``custom_id`` to remove from the action row. | ||
""" | ||
|
||
if isinstance(item, (str, int)): | ||
item = self.get_item(item) | ||
try: | ||
self.items.remove(item) | ||
except ValueError: | ||
pass | ||
return self | ||
|
||
def get_item(self, id: str | int) -> Item | None: | ||
"""Get an item from this action row. Roughly equivalent to `utils.get(row.items, ...)`. | ||
If an ``int`` is provided, the item will be retrieved by ``id``, otherwise by ``custom_id``. | ||
|
||
Parameters | ||
---------- | ||
id: Union[:class:`str`, :class:`int`] | ||
The id or custom_id of the item to get. | ||
|
||
Returns | ||
------- | ||
Optional[:class:`Item`] | ||
The item with the matching ``id`` or ``custom_id`` if it exists. | ||
""" | ||
if not id: | ||
return None | ||
attr = "id" if isinstance(id, int) else "custom_id" | ||
child = find(lambda i: getattr(i, attr, None) == id, self.items) | ||
return child | ||
|
||
def add_button( | ||
self, | ||
*, | ||
style: ButtonStyle = ButtonStyle.secondary, | ||
label: str | None = None, | ||
disabled: bool = False, | ||
custom_id: str | None = None, | ||
url: str | None = None, | ||
emoji: str | GuildEmoji | AppEmoji | PartialEmoji | None = None, | ||
sku_id: int | None = None, | ||
id: int | None = None, | ||
) -> Self: | ||
"""Adds a :class:`Button` to the action row. | ||
|
||
To append a pre-existing :class:`Button`, use the | ||
:meth:`add_item` method, instead. | ||
|
||
Parameters | ||
---------- | ||
style: :class:`discord.ButtonStyle` | ||
The style of the button. | ||
custom_id: Optional[:class:`str`] | ||
The custom ID of the button that gets received during an interaction. | ||
If this button is for a URL, it does not have a custom ID. | ||
url: Optional[:class:`str`] | ||
The URL this button sends you to. | ||
disabled: :class:`bool` | ||
Whether the button is disabled or not. | ||
label: Optional[:class:`str`] | ||
The label of the button, if any. Maximum of 80 chars. | ||
emoji: Optional[Union[:class:`.PartialEmoji`, :class:`GuildEmoji`, :class:`AppEmoji`, :class:`str`]] | ||
The emoji of the button, if any. | ||
sku_id: Optional[Union[:class:`int`]] | ||
The ID of the SKU this button refers to. | ||
id: Optional[:class:`int`] | ||
The button's ID. | ||
""" | ||
|
||
button = Button( | ||
style=style, | ||
label=label, | ||
disabled=disabled, | ||
custom_id=custom_id, | ||
url=url, | ||
emoji=emoji, | ||
sku_id=sku_id, | ||
id=id, | ||
) | ||
|
||
return self.add_item(button) | ||
|
||
def add_select( | ||
NeloBlivion marked this conversation as resolved.
Show resolved
Hide resolved
|
||
self, | ||
select_type: ComponentType = ComponentType.string_select, | ||
*, | ||
custom_id: str | None = None, | ||
placeholder: str | None = None, | ||
min_values: int = 1, | ||
max_values: int = 1, | ||
options: list[SelectOption] | None = None, | ||
channel_types: list[ChannelType] | None = None, | ||
disabled: bool = False, | ||
id: int | None = None, | ||
) -> Self: | ||
"""Adds a :class:`TextDisplay` to the container. | ||
NeloBlivion marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
||
Parameters | ||
---------- | ||
select_type: :class:`discord.ComponentType` | ||
The type of select to create. Must be one of | ||
:attr:`discord.ComponentType.string_select`, :attr:`discord.ComponentType.user_select`, | ||
:attr:`discord.ComponentType.role_select`, :attr:`discord.ComponentType.mentionable_select`, | ||
or :attr:`discord.ComponentType.channel_select`. | ||
custom_id: :class:`str` | ||
The custom ID of the select menu that gets received during an interaction. | ||
If not given then one is generated for you. | ||
placeholder: Optional[:class:`str`] | ||
The placeholder text that is shown if nothing is selected, if any. | ||
min_values: :class:`int` | ||
The minimum number of items that must be chosen for this select menu. | ||
Defaults to 1 and must be between 1 and 25. | ||
max_values: :class:`int` | ||
The maximum number of items that must be chosen for this select menu. | ||
Defaults to 1 and must be between 1 and 25. | ||
options: List[:class:`discord.SelectOption`] | ||
A list of options that can be selected in this menu. | ||
Only valid for selects of type :attr:`discord.ComponentType.string_select`. | ||
channel_types: List[:class:`discord.ChannelType`] | ||
A list of channel types that can be selected in this menu. | ||
Only valid for selects of type :attr:`discord.ComponentType.channel_select`. | ||
disabled: :class:`bool` | ||
Whether the select is disabled or not. Defaults to ``False``. | ||
id: Optional[:class:`int`] | ||
The select menu's ID. | ||
""" | ||
|
||
select = Select( | ||
select_type=select_type, | ||
custom_id=custom_id, | ||
placeholder=placeholder, | ||
min_values=min_values, | ||
max_values=max_values, | ||
options=options or [], | ||
channel_types=channel_types or [], | ||
disabled=disabled, | ||
id=id, | ||
) | ||
|
||
return self.add_item(select) | ||
|
||
@Item.view.setter | ||
def view(self, value): | ||
self._view = value | ||
for item in self.items: | ||
item.parent = self | ||
item._view = value | ||
|
||
@property | ||
def type(self) -> ComponentType: | ||
return self._underlying.type | ||
|
||
@property | ||
def width(self) -> int: | ||
return 5 | ||
|
||
def is_dispatchable(self) -> bool: | ||
return any(item.is_dispatchable() for item in self.items) | ||
|
||
def is_persistent(self) -> bool: | ||
return all(item.is_persistent() for item in self.items) | ||
|
||
def refresh_component(self, component: ActionRowComponent) -> None: | ||
self._underlying = component | ||
i = 0 | ||
for y in component.components: | ||
x = self.items[i] | ||
x.refresh_component(y) | ||
i += 1 | ||
|
||
def disable_all_items(self, *, exclusions: list[Item] | None = None) -> Self: | ||
""" | ||
Disables all items in the row. | ||
|
||
Parameters | ||
---------- | ||
exclusions: Optional[List[:class:`Item`]] | ||
A list of items in `self.items` to not disable. | ||
""" | ||
for item in self.walk_items(): | ||
if exclusions is None or item not in exclusions: | ||
Soheab marked this conversation as resolved.
Show resolved
Hide resolved
|
||
item.disabled = True | ||
return self | ||
|
||
def enable_all_items(self, *, exclusions: list[Item] | None = None) -> Self: | ||
""" | ||
Enables all items in the row. | ||
|
||
Parameters | ||
---------- | ||
exclusions: Optional[List[:class:`Item`]] | ||
A list of items in `self.items` to not enable. | ||
""" | ||
for item in self.walk_items(): | ||
if hasattr(item, "disabled") and ( | ||
exclusions is None or item not in exclusions | ||
): | ||
item.disabled = False | ||
return self | ||
|
||
def walk_items(self) -> Iterator[Item]: | ||
yield from self.items | ||
|
||
def to_component_dict(self) -> ActionRowPayload: | ||
self._set_components(self.items) | ||
return self._underlying.to_dict() | ||
|
||
@classmethod | ||
def from_component(cls: type[A], component: ActionRowComponent) -> A: | ||
from .view import _component_to_item, _walk_all_components | ||
|
||
items = [ | ||
_component_to_item(c) for c in _walk_all_components(component.components) | ||
] | ||
return cls( | ||
*items, | ||
id=component.id, | ||
) | ||
|
||
callback = None |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.