diff --git a/discord/ui/action_row.py b/discord/ui/action_row.py index c7f7a2b7b9a3..07c8948284e4 100644 --- a/discord/ui/action_row.py +++ b/discord/ui/action_row.py @@ -274,6 +274,47 @@ def add_item(self, item: Item[Any]) -> Self: return self + def insert_item_at(self, position: int, item: Item[Any]) -> Self: + """Insert an item to this action row. + + This function returns the class instance to allow for fluent-style + chaining. + + Parameters + ---------- + position: int + The position at which to add the item. `0` to insert at the beginning. + item: :class:`Item` + The item to add to the action row. + + Raises + ------ + TypeError + An :class:`Item` was not passed. + ValueError + Maximum number of children has been exceeded (5) + or (40) for the entire view. + """ + + if (self._weight + item.width) > 5: + raise ValueError('maximum number of children exceeded') + + if len(self._children) >= 5: + raise ValueError('maximum number of children exceeded') + + if not isinstance(item, Item): + raise TypeError(f'expected Item not {item.__class__.__name__}') + + if self._view: + self._view._add_count(1) + + item._update_view(self.view) + item._parent = self + self._weight += 1 + self._children.insert(position, item) + + return self + def remove_item(self, item: Item[Any]) -> Self: """Removes an item from the action row. diff --git a/discord/ui/container.py b/discord/ui/container.py index 3025e17f80b7..fa6dae8c6cbd 100644 --- a/discord/ui/container.py +++ b/discord/ui/container.py @@ -322,6 +322,37 @@ def add_item(self, item: Item[Any]) -> Self: item._parent = self return self + def insert_item_at(self, position: int, item: Item[Any]) -> Self: + """Insert an item to this container. + + This function returns the class instance to allow for fluent-style + chaining. + + Parameters + ---------- + position: int + The position at which to add the item. `0` to insert at the beginning. + item: :class:`Item` + The item to append. + + Raises + ------ + TypeError + An :class:`Item` was not passed. + ValueError + Maximum number of children has been exceeded (40) for the entire view. + """ + if not isinstance(item, Item): + raise TypeError(f'expected Item not {item.__class__.__name__}') + + if self._view: + self._view._add_count(item._total_count) + + self._children.insert(position, item) + item._update_view(self.view) + item._parent = self + return self + def remove_item(self, item: Item[Any]) -> Self: """Removes an item from this container. diff --git a/discord/ui/modal.py b/discord/ui/modal.py index db8bf524138a..ab3fbdfb773e 100644 --- a/discord/ui/modal.py +++ b/discord/ui/modal.py @@ -271,3 +271,8 @@ def add_item(self, item: Item[Any]) -> Self: if len(self._children) >= 5: raise ValueError('maximum number of children exceeded (5)') return super().add_item(item) + + def insert_item_at(self, position: int, item: Item[Any]) -> Self: + if len(self._children) >= 5: + raise ValueError('maximum number of children exceeded (5)') + return super().insert_item_at(position, item) diff --git a/discord/ui/view.py b/discord/ui/view.py index 252a21dbb981..d323568af9b7 100644 --- a/discord/ui/view.py +++ b/discord/ui/view.py @@ -405,6 +405,37 @@ def from_message(cls, message: Message, /, *, timeout: Optional[float] = 180.0) return view + def insert_item_at(self, position: int, item: Item[Any]) -> Self: + """Insert an item to the view. + + This function returns the class instance to allow for fluent-style + chaining. + + Parameters + ----------- + position: int + The position at which to add the item. `0` to insert at the beginning. + item: :class:`Item` + The item to add to the view. + + Raises + -------- + TypeError + An :class:`Item` was not passed. + ValueError + Maximum number of children has been exceeded, the + row the item is trying to be added to is full or the item + you tried to add is not allowed in this View. + """ + + if not isinstance(item, Item): + raise TypeError(f'expected Item not {item.__class__.__name__}') + + item._update_view(self) + self._add_count(item._total_count) + self._children.insert(position, item) + return self + def add_item(self, item: Item[Any]) -> Self: """Adds an item to the view. @@ -733,6 +764,23 @@ def key(item: Item) -> int: return components + def insert_item_at(self, position: int, item: Item[Any]) -> Self: + if len(self._children) >= 25: + raise ValueError('maximum number of children exceeded') + + if item._is_v2(): + raise ValueError('v2 items cannot be added to this view') + + super().insert_item_at(position, item) + try: + self.__weights.add_item(item) + except ValueError as e: + # if the item has no space left then remove it from _children + self._children.remove(item) + raise e + + return self + def add_item(self, item: Item[Any]) -> Self: if len(self._children) >= 25: raise ValueError('maximum number of children exceeded') @@ -837,6 +885,12 @@ def add_item(self, item: Item[Any]) -> Self: super().add_item(item) return self + def insert_item_at(self, position: int, item: Item[Any]) -> Self: + if self._total_children >= 40: + raise ValueError('maximum number of children exceeded (40)') + super().insert_item_at(position, item) + return self + def content_length(self) -> int: """:class:`int`: Returns the total length of all text content in the view's items.