mirror of
https://github.com/Rapptz/discord.py.git
synced 2025-09-05 09:26:10 +00:00
Add support for components V2
Co-authored-by: Michael H <michael@michaelhall.tech> Co-authored-by: Soheab <33902984+Soheab@users.noreply.github.com> Co-authored-by: owocado <24418520+owocado@users.noreply.github.com> Co-authored-by: Jay3332 <40323796+jay3332@users.noreply.github.com> Co-authored-by: Danny <1695103+Rapptz@users.noreply.github.com>
This commit is contained in:
@ -24,6 +24,7 @@ DEALINGS IN THE SOFTWARE.
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import copy
|
||||
from typing import Any, Callable, Coroutine, Dict, Generic, Optional, TYPE_CHECKING, Tuple, Type, TypeVar
|
||||
|
||||
from ..interactions import Interaction
|
||||
@ -36,12 +37,14 @@ __all__ = (
|
||||
# fmt: on
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing_extensions import Self
|
||||
|
||||
from ..enums import ComponentType
|
||||
from .view import View
|
||||
from .view import BaseView
|
||||
from ..components import Component
|
||||
|
||||
I = TypeVar('I', bound='Item[Any]')
|
||||
V = TypeVar('V', bound='View', covariant=True)
|
||||
V = TypeVar('V', bound='BaseView', covariant=True)
|
||||
ItemCallbackType = Callable[[V, Interaction[Any], I], Coroutine[Any, Any, Any]]
|
||||
|
||||
|
||||
@ -53,11 +56,19 @@ class Item(Generic[V]):
|
||||
- :class:`discord.ui.Button`
|
||||
- :class:`discord.ui.Select`
|
||||
- :class:`discord.ui.TextInput`
|
||||
- :class:`discord.ui.ActionRow`
|
||||
- :class:`discord.ui.Container`
|
||||
- :class:`discord.ui.File`
|
||||
- :class:`discord.ui.MediaGallery`
|
||||
- :class:`discord.ui.Section`
|
||||
- :class:`discord.ui.Separator`
|
||||
- :class:`discord.ui.TextDisplay`
|
||||
- :class:`discord.ui.Thumbnail`
|
||||
|
||||
.. versionadded:: 2.0
|
||||
"""
|
||||
|
||||
__item_repr_attributes__: Tuple[str, ...] = ('row',)
|
||||
__item_repr_attributes__: Tuple[str, ...] = ('row', 'id')
|
||||
|
||||
def __init__(self):
|
||||
self._view: Optional[V] = None
|
||||
@ -70,6 +81,8 @@ class Item(Generic[V]):
|
||||
# actually affect the intended purpose of this check because from_component is
|
||||
# only called upon edit and we're mainly interested during initial creation time.
|
||||
self._provided_custom_id: bool = False
|
||||
self._id: Optional[int] = None
|
||||
self._parent: Optional[Item] = None
|
||||
|
||||
def to_component_dict(self) -> Dict[str, Any]:
|
||||
raise NotImplementedError
|
||||
@ -80,6 +93,9 @@ class Item(Generic[V]):
|
||||
def _refresh_state(self, interaction: Interaction, data: Dict[str, Any]) -> None:
|
||||
return None
|
||||
|
||||
def _is_v2(self) -> bool:
|
||||
return False
|
||||
|
||||
@classmethod
|
||||
def from_component(cls: Type[I], component: Component) -> I:
|
||||
return cls()
|
||||
@ -92,7 +108,9 @@ class Item(Generic[V]):
|
||||
return False
|
||||
|
||||
def is_persistent(self) -> bool:
|
||||
return self._provided_custom_id
|
||||
if self.is_dispatchable():
|
||||
return self._provided_custom_id
|
||||
return True
|
||||
|
||||
def __repr__(self) -> str:
|
||||
attrs = ' '.join(f'{key}={getattr(self, key)!r}' for key in self.__item_repr_attributes__)
|
||||
@ -104,6 +122,10 @@ class Item(Generic[V]):
|
||||
|
||||
@row.setter
|
||||
def row(self, value: Optional[int]) -> None:
|
||||
if self._is_v2():
|
||||
# row is ignored on v2 components
|
||||
return
|
||||
|
||||
if value is None:
|
||||
self._row = None
|
||||
elif 5 > value >= 0:
|
||||
@ -117,9 +139,45 @@ class Item(Generic[V]):
|
||||
|
||||
@property
|
||||
def view(self) -> Optional[V]:
|
||||
"""Optional[:class:`View`]: The underlying view for this item."""
|
||||
"""Optional[Union[:class:`View`, :class:`LayoutView`]]: The underlying view for this item."""
|
||||
return self._view
|
||||
|
||||
@property
|
||||
def id(self) -> Optional[int]:
|
||||
"""Optional[:class:`int`]: The ID of this component."""
|
||||
return self._id
|
||||
|
||||
@id.setter
|
||||
def id(self, value: Optional[int]) -> None:
|
||||
self._id = value
|
||||
|
||||
@property
|
||||
def parent(self) -> Optional[Item[V]]:
|
||||
"""Optional[:class:`Item`]: This item's parent. Only components that can have children
|
||||
can be parents. Any item that has :class:`View` as a view will have this set to `None`
|
||||
since only :class:`LayoutView` component v2 items can contain "container" like items.
|
||||
|
||||
.. versionadded:: 2.6
|
||||
"""
|
||||
return self._parent
|
||||
|
||||
async def _run_checks(self, interaction: Interaction[ClientT]) -> bool:
|
||||
can_run = await self.interaction_check(interaction)
|
||||
|
||||
if can_run and self._parent:
|
||||
can_run = await self._parent._run_checks(interaction)
|
||||
|
||||
return can_run
|
||||
|
||||
def _update_view(self, view) -> None:
|
||||
self._view = view
|
||||
|
||||
def copy(self) -> Self:
|
||||
return copy.deepcopy(self)
|
||||
|
||||
def _has_children(self) -> bool:
|
||||
return False
|
||||
|
||||
async def callback(self, interaction: Interaction[ClientT]) -> Any:
|
||||
"""|coro|
|
||||
|
||||
|
Reference in New Issue
Block a user