Add a swap method for dynamic item's dispatching

This commit is contained in:
DA344 2025-08-21 00:52:31 +02:00 committed by GitHub
parent b2aab86ba1
commit 0309aac335
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 26 additions and 3 deletions

View File

@ -67,6 +67,7 @@ if TYPE_CHECKING:
from ..components import SelectOption from ..components import SelectOption
from ..interactions import Interaction from ..interactions import Interaction
from .container import Container from .container import Container
from .dynamic import DynamicItem
SelectCallbackDecorator = Callable[[ItemCallbackType['S', BaseSelectT]], BaseSelectT] SelectCallbackDecorator = Callable[[ItemCallbackType['S', BaseSelectT]], BaseSelectT]
@ -194,6 +195,10 @@ class ActionRow(Item[V]):
# it should error anyways. # it should error anyways.
return True return True
def _swap_item(self, base: Item, new: DynamicItem, custom_id: str) -> None:
child_index = self._children.index(base)
self._children[child_index] = new # type: ignore
@property @property
def width(self): def width(self):
return 5 return 5

View File

@ -50,6 +50,7 @@ if TYPE_CHECKING:
from ..components import Container as ContainerComponent from ..components import Container as ContainerComponent
from ..interactions import Interaction from ..interactions import Interaction
from .dynamic import DynamicItem
S = TypeVar('S', bound='Container', covariant=True) S = TypeVar('S', bound='Container', covariant=True)
V = TypeVar('V', bound='LayoutView', covariant=True) V = TypeVar('V', bound='LayoutView', covariant=True)
@ -198,6 +199,10 @@ class Container(Item[V]):
def _has_children(self): def _has_children(self):
return True return True
def _swap_item(self, base: Item, new: DynamicItem, custom_id: str) -> None:
child_index = self._children.index(base)
self._children[child_index] = new # type: ignore
@property @property
def children(self) -> List[Item[V]]: def children(self) -> List[Item[V]]:
"""List[:class:`Item`]: The children of this container.""" """List[:class:`Item`]: The children of this container."""

View File

@ -44,6 +44,7 @@ if TYPE_CHECKING:
from ..components import Component from ..components import Component
from .action_row import ActionRow from .action_row import ActionRow
from .container import Container from .container import Container
from .dynamic import DynamicItem
I = TypeVar('I', bound='Item[Any]') I = TypeVar('I', bound='Item[Any]')
V = TypeVar('V', bound='BaseView', covariant=True) V = TypeVar('V', bound='BaseView', covariant=True)
@ -118,6 +119,9 @@ class Item(Generic[V]):
return self._provided_custom_id return self._provided_custom_id
return True return True
def _swap_item(self, base: Item, new: DynamicItem, custom_id: str) -> None:
raise ValueError
def __repr__(self) -> str: def __repr__(self) -> str:
attrs = ' '.join(f'{key}={getattr(self, key)!r}' for key in self.__item_repr_attributes__) attrs = ' '.join(f'{key}={getattr(self, key)!r}' for key in self.__item_repr_attributes__)
return f'<{self.__class__.__name__} {attrs}>' return f'<{self.__class__.__name__} {attrs}>'

View File

@ -35,6 +35,7 @@ if TYPE_CHECKING:
from typing_extensions import Self from typing_extensions import Self
from .view import LayoutView from .view import LayoutView
from .dynamic import DynamicItem
from ..components import SectionComponent from ..components import SectionComponent
V = TypeVar('V', bound='LayoutView', covariant=True) V = TypeVar('V', bound='LayoutView', covariant=True)
@ -117,6 +118,10 @@ class Section(Item[V]):
def _is_v2(self) -> bool: def _is_v2(self) -> bool:
return True return True
def _swap_item(self, base: Item, new: DynamicItem, custom_id: str) -> None:
if self.accessory.is_dispatchable() and getattr(self.accessory, 'custom_id', None) == custom_id:
self.accessory = new # type: ignore
def walk_children(self) -> Generator[Item[V], None, None]: def walk_children(self) -> Generator[Item[V], None, None]:
"""An iterator that recursively walks through all the children of this section """An iterator that recursively walks through all the children of this section
and its children, if applicable. This includes the `accessory`. and its children, if applicable. This includes the `accessory`.

View File

@ -300,6 +300,12 @@ class BaseView:
if self.__timeout: if self.__timeout:
self.__timeout_expiry = time.monotonic() + self.__timeout self.__timeout_expiry = time.monotonic() + self.__timeout
def _swap_item(self, base: Item, new: DynamicItem, custom_id: str) -> None:
# if an error is raised it is catched by the try/except block that calls
# this function
child_index = self._children.index(base)
self._children[child_index] = new # type: ignore
@property @property
def timeout(self) -> Optional[float]: def timeout(self) -> Optional[float]:
"""Optional[:class:`float`]: The timeout in seconds from last interaction with the UI before no longer accepting input. """Optional[:class:`float`]: The timeout in seconds from last interaction with the UI before no longer accepting input.
@ -954,11 +960,9 @@ class ViewStore:
parent = base_item._parent or view parent = base_item._parent or view
try: try:
child_index = parent._children.index(base_item) # type: ignore parent._swap_item(base_item, item, custom_id)
except ValueError: except ValueError:
return return
else:
parent._children[child_index] = item # type: ignore
item._view = view item._view = view
item._rendered_row = base_item._rendered_row item._rendered_row = base_item._rendered_row