diff --git a/submodules/ChatListUI/Sources/ChatContextMenus.swift b/submodules/ChatListUI/Sources/ChatContextMenus.swift index b20d77d6f0..b710deca99 100644 --- a/submodules/ChatListUI/Sources/ChatContextMenus.swift +++ b/submodules/ChatListUI/Sources/ChatContextMenus.swift @@ -149,10 +149,13 @@ func chatContextMenuItems(context: AccountContext, peerId: PeerId, promoInfo: Ch }) }))) items.append(.separator) + case .popularApps: + break } } if case .search(.recentApps) = source { + } else if case .search(.popularApps) = source { } else { let isSavedMessages = peerId == context.account.peerId diff --git a/submodules/ChatListUI/Sources/ChatListSearchContainerNode.swift b/submodules/ChatListUI/Sources/ChatListSearchContainerNode.swift index 910d42bf28..5538521545 100644 --- a/submodules/ChatListUI/Sources/ChatListSearchContainerNode.swift +++ b/submodules/ChatListUI/Sources/ChatListSearchContainerNode.swift @@ -330,6 +330,10 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo } } + self.paneContainerNode.requesDismissInput = { + parentController()?.view.endEditing(true) + } + self.filterContainerNode.filterPressed = { [weak self] filter in guard let strongSelf = self else { return diff --git a/submodules/ChatListUI/Sources/ChatListSearchListPaneNode.swift b/submodules/ChatListUI/Sources/ChatListSearchListPaneNode.swift index 55aca75b28..57c0091630 100644 --- a/submodules/ChatListUI/Sources/ChatListSearchListPaneNode.swift +++ b/submodules/ChatListUI/Sources/ChatListSearchListPaneNode.swift @@ -298,13 +298,17 @@ private enum ChatListRecentEntry: Comparable, Identifiable { } }, deletePeer: deletePeer, - contextAction: (key == .channels) ? nil : peerContextAction.flatMap { peerContextAction in + contextAction: (key == .channels || section == .popularApps) ? nil : peerContextAction.flatMap { peerContextAction in return { node, gesture, location in if let chatPeer = peer.peer.peers[peer.peer.peerId] { let source: ChatListSearchContextActionSource if key == .apps { - source = .recentApps + if case .popularApps = section { + source = .popularApps + } else { + source = .recentApps + } } else { source = .recentSearch } @@ -1081,6 +1085,7 @@ public enum ChatListSearchContextActionSource { case recentPeers case recentSearch case recentApps + case popularApps case search(EngineMessage.Id?) } diff --git a/submodules/ChatListUI/Sources/ChatListSearchPaneContainerNode.swift b/submodules/ChatListUI/Sources/ChatListSearchPaneContainerNode.swift index ccf0563396..28bc9b2f8b 100644 --- a/submodules/ChatListUI/Sources/ChatListSearchPaneContainerNode.swift +++ b/submodules/ChatListUI/Sources/ChatListSearchPaneContainerNode.swift @@ -192,6 +192,7 @@ final class ChatListSearchPaneContainerNode: ASDisplayNode, ASGestureRecognizerD var currentPaneUpdated: ((ChatListSearchPaneKey?, CGFloat, ContainedViewLayoutTransition) -> Void)? var requestExpandTabs: (() -> Bool)? + var requesDismissInput: (() -> Void)? private var currentAvailablePanes: [ChatListSearchPaneKey]? @@ -227,12 +228,20 @@ final class ChatListSearchPaneContainerNode: ASDisplayNode, ASGestureRecognizerD if let (size, sideInset, bottomInset, visibleHeight, presentationData, availablePanes) = self.currentParams { self.update(size: size, sideInset: sideInset, bottomInset: bottomInset, visibleHeight: visibleHeight, presentationData: presentationData, availablePanes: availablePanes, transition: .animated(duration: 0.4, curve: .spring)) } + + if case .apps = key { + self.requesDismissInput?() + } } else if self.pendingSwitchToPaneKey != key { self.pendingSwitchToPaneKey = key if let (size, sideInset, bottomInset, visibleHeight, presentationData, availablePanes) = self.currentParams { self.update(size: size, sideInset: sideInset, bottomInset: bottomInset, visibleHeight: visibleHeight, presentationData: presentationData, availablePanes: availablePanes, transition: .animated(duration: 0.4, curve: .spring)) } + + if case .apps = key { + self.requesDismissInput?() + } } } @@ -322,6 +331,10 @@ final class ChatListSearchPaneContainerNode: ASDisplayNode, ASGestureRecognizerD let switchToKey = availablePanes[updatedIndex] if switchToKey != self.currentPaneKey && self.currentPanes[switchToKey] != nil{ self.currentPaneKey = switchToKey + + if case .apps = switchToKey { + self.requesDismissInput?() + } } } self.transitionFraction = 0.0 diff --git a/submodules/SparseItemGrid/Sources/SparseItemGrid.swift b/submodules/SparseItemGrid/Sources/SparseItemGrid.swift index de00d411bd..58dd462609 100644 --- a/submodules/SparseItemGrid/Sources/SparseItemGrid.swift +++ b/submodules/SparseItemGrid/Sources/SparseItemGrid.swift @@ -462,7 +462,7 @@ public final class SparseItemGrid: ASDisplayNode { self.itemSpacing = 1.0 let itemsPerRow: CGFloat - if containerLayout.fixedItemAspect != nil && itemCount <= 2 { + if containerLayout.fixedItemAspect != nil && itemCount <= 2 && containerLayout.adjustForSmallCount { itemsPerRow = 2.0 centerItems = itemCount == 1 } else { @@ -1607,6 +1607,7 @@ public final class SparseItemGrid: ASDisplayNode { var lockScrollingAtTop: Bool var fixedItemHeight: CGFloat? var fixedItemAspect: CGFloat? + var adjustForSmallCount: Bool } private var tapRecognizer: UITapGestureRecognizer? @@ -1932,7 +1933,7 @@ public final class SparseItemGrid: ASDisplayNode { } } - public func update(size: CGSize, insets: UIEdgeInsets, useSideInsets: Bool, scrollIndicatorInsets: UIEdgeInsets, lockScrollingAtTop: Bool, fixedItemHeight: CGFloat?, fixedItemAspect: CGFloat?, items: Items, theme: PresentationTheme, synchronous: SparseItemGrid.Synchronous, transition: ComponentTransition = .immediate) { + public func update(size: CGSize, insets: UIEdgeInsets, useSideInsets: Bool, scrollIndicatorInsets: UIEdgeInsets, lockScrollingAtTop: Bool, fixedItemHeight: CGFloat?, fixedItemAspect: CGFloat?, adjustForSmallCount: Bool = true, items: Items, theme: PresentationTheme, synchronous: SparseItemGrid.Synchronous, transition: ComponentTransition = .immediate) { self.theme = theme var headerInset: CGFloat = 0.0 @@ -1973,7 +1974,7 @@ public final class SparseItemGrid: ASDisplayNode { var insets = insets insets.top += headerInset - let containerLayout = ContainerLayout(size: size, insets: insets, useSideInsets: useSideInsets, scrollIndicatorInsets: scrollIndicatorInsets, lockScrollingAtTop: lockScrollingAtTop, fixedItemHeight: fixedItemHeight, fixedItemAspect: fixedItemAspect) + let containerLayout = ContainerLayout(size: size, insets: insets, useSideInsets: useSideInsets, scrollIndicatorInsets: scrollIndicatorInsets, lockScrollingAtTop: lockScrollingAtTop, fixedItemHeight: fixedItemHeight, fixedItemAspect: fixedItemAspect, adjustForSmallCount: adjustForSmallCount) self.containerLayout = containerLayout self.items = items self.scrollingArea.isHidden = lockScrollingAtTop diff --git a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/ListItems/PeerInfoScreenLabeledValueItem.swift b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/ListItems/PeerInfoScreenLabeledValueItem.swift index 01056e97dc..344ef5873f 100644 --- a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/ListItems/PeerInfoScreenLabeledValueItem.swift +++ b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/ListItems/PeerInfoScreenLabeledValueItem.swift @@ -77,7 +77,7 @@ final class PeerInfoScreenLabeledValueItem: PeerInfoScreenItem { let iconAction: (() -> Void)? let button: Button? let contextAction: ((ASDisplayNode, ContextGesture?, CGPoint?) -> Void)? - let requestLayout: () -> Void + let requestLayout: (Bool) -> Void init( id: AnyHashable, @@ -95,7 +95,7 @@ final class PeerInfoScreenLabeledValueItem: PeerInfoScreenItem { iconAction: (() -> Void)? = nil, button: Button? = nil, contextAction: ((ASDisplayNode, ContextGesture?, CGPoint?) -> Void)? = nil, - requestLayout: @escaping () -> Void + requestLayout: @escaping (Bool) -> Void ) { self.id = id self.context = context @@ -336,7 +336,7 @@ private final class PeerInfoScreenLabeledValueItemNode: PeerInfoScreenItemNode { @objc private func expandPressed() { self.isExpanded = true - self.item?.requestLayout() + self.item?.requestLayout(true) } @objc private func iconPressed() { diff --git a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoScreen.swift b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoScreen.swift index 5f768653d3..c63e6a276f 100644 --- a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoScreen.swift +++ b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoScreen.swift @@ -1273,8 +1273,8 @@ private func infoItems(data: PeerInfoScreenData?, context: AccountContext, prese interaction.openPhone(phone, node, nil, progress) }, longTapAction: nil, contextAction: { node, gesture, _ in interaction.openPhone(phone, node, gesture, nil) - }, requestLayout: { - interaction.requestLayout(false) + }, requestLayout: { animated in + interaction.requestLayout(animated) })) } if let mainUsername = user.addressName { @@ -1304,8 +1304,8 @@ private func infoItems(data: PeerInfoScreenData?, context: AccountContext, prese interaction.openQrCode() }, contextAction: { node, gesture, _ in interaction.openUsernameContextMenu(node, gesture) - }, requestLayout: { - interaction.requestLayout(false) + }, requestLayout: { animated in + interaction.requestLayout(animated) } ) ) @@ -1332,7 +1332,7 @@ private func infoItems(data: PeerInfoScreenData?, context: AccountContext, prese items[currentPeerInfoSection]!.append(PeerInfoScreenLabeledValueItem(id: 400, context: context, label: hasBirthdayToday ? presentationData.strings.UserInfo_BirthdayToday : presentationData.strings.UserInfo_Birthday, text: stringForCompactBirthday(birthday, strings: presentationData.strings, showAge: true), textColor: .primary, leftIcon: hasBirthdayToday ? .birthday : nil, icon: hasBirthdayToday ? .premiumGift : nil, action: birthdayAction, longTapAction: nil, iconAction: { interaction.openPremiumGift() - }, contextAction: birthdayContextAction, requestLayout: { + }, contextAction: birthdayContextAction, requestLayout: { _ in })) } @@ -1347,12 +1347,12 @@ private func infoItems(data: PeerInfoScreenData?, context: AccountContext, prese } if user.isFake { - items[currentPeerInfoSection]!.append(PeerInfoScreenLabeledValueItem(id: 0, label: "", text: user.botInfo != nil ? presentationData.strings.UserInfo_FakeBotWarning : presentationData.strings.UserInfo_FakeUserWarning, textColor: .primary, textBehavior: .multiLine(maxLines: 100, enabledEntities: user.botInfo != nil ? enabledPrivateBioEntities : []), action: nil, requestLayout: { - interaction.requestLayout(false) + items[currentPeerInfoSection]!.append(PeerInfoScreenLabeledValueItem(id: 0, label: "", text: user.botInfo != nil ? presentationData.strings.UserInfo_FakeBotWarning : presentationData.strings.UserInfo_FakeUserWarning, textColor: .primary, textBehavior: .multiLine(maxLines: 100, enabledEntities: user.botInfo != nil ? enabledPrivateBioEntities : []), action: nil, requestLayout: { animated in + interaction.requestLayout(animated) })) } else if user.isScam { - items[currentPeerInfoSection]!.append(PeerInfoScreenLabeledValueItem(id: 0, label: user.botInfo == nil ? presentationData.strings.Profile_About : presentationData.strings.Profile_BotInfo, text: user.botInfo != nil ? presentationData.strings.UserInfo_ScamBotWarning : presentationData.strings.UserInfo_ScamUserWarning, textColor: .primary, textBehavior: .multiLine(maxLines: 100, enabledEntities: user.botInfo != nil ? enabledPrivateBioEntities : []), action: nil, requestLayout: { - interaction.requestLayout(false) + items[currentPeerInfoSection]!.append(PeerInfoScreenLabeledValueItem(id: 0, label: user.botInfo == nil ? presentationData.strings.Profile_About : presentationData.strings.Profile_BotInfo, text: user.botInfo != nil ? presentationData.strings.UserInfo_ScamBotWarning : presentationData.strings.UserInfo_ScamUserWarning, textColor: .primary, textBehavior: .multiLine(maxLines: 100, enabledEntities: user.botInfo != nil ? enabledPrivateBioEntities : []), action: nil, requestLayout: { animated in + interaction.requestLayout(animated) })) } else if hasAbout || hasWebApp { var actionButton: PeerInfoScreenLabeledValueItem.Button? @@ -1385,8 +1385,8 @@ private func infoItems(data: PeerInfoScreenData?, context: AccountContext, prese items[currentPeerInfoSection]!.append(PeerInfoScreenLabeledValueItem(id: 0, label: label, text: cachedData.about ?? "", textColor: .primary, textBehavior: .multiLine(maxLines: 100, enabledEntities: user.isPremium ? enabledPublicBioEntities : enabledPrivateBioEntities), action: isMyProfile ? { node, _ in bioContextAction(node, nil, nil) - } : nil, linkItemAction: bioLinkAction, button: actionButton, contextAction: bioContextAction, requestLayout: { - interaction.requestLayout(false) + } : nil, linkItemAction: bioLinkAction, button: actionButton, contextAction: bioContextAction, requestLayout: { animated in + interaction.requestLayout(animated) })) if let botInfo = user.botInfo, botInfo.flags.contains(.canEdit) { @@ -1579,8 +1579,8 @@ private func infoItems(data: PeerInfoScreenData?, context: AccountContext, prese } }, iconAction: { interaction.openQrCode() - }, requestLayout: { - interaction.requestLayout(false) + }, requestLayout: { animated in + interaction.requestLayout(animated) } ) ) @@ -1636,8 +1636,8 @@ private func infoItems(data: PeerInfoScreenData?, context: AccountContext, prese } }, iconAction: { interaction.openQrCode() - }, requestLayout: { - interaction.requestLayout(false) + }, requestLayout: { animated in + interaction.requestLayout(animated) } ) ) @@ -1669,8 +1669,8 @@ private func infoItems(data: PeerInfoScreenData?, context: AccountContext, prese } items[currentPeerInfoSection]!.append(PeerInfoScreenLabeledValueItem(id: ItemAbout, label: presentationData.strings.Channel_Info_Description, text: aboutText, textColor: .primary, textBehavior: .multiLine(maxLines: 100, enabledEntities: enabledEntities), action: isMyProfile ? { node, _ in bioContextAction(node, nil, nil) - } : nil, linkItemAction: bioLinkAction, contextAction: bioContextAction, requestLayout: { - interaction.requestLayout(true) + } : nil, linkItemAction: bioLinkAction, contextAction: bioContextAction, requestLayout: { animated in + interaction.requestLayout(animated) })) } @@ -1755,8 +1755,8 @@ private func infoItems(data: PeerInfoScreenData?, context: AccountContext, prese if let aboutText = aboutText { items[currentPeerInfoSection]!.append(PeerInfoScreenLabeledValueItem(id: 0, label: presentationData.strings.Channel_Info_Description, text: aboutText, textColor: .primary, textBehavior: .multiLine(maxLines: 100, enabledEntities: enabledPrivateBioEntities), action: isMyProfile ? { node, _ in bioContextAction(node, nil, nil) - } : nil, linkItemAction: bioLinkAction, contextAction: bioContextAction, requestLayout: { - interaction.requestLayout(true) + } : nil, linkItemAction: bioLinkAction, contextAction: bioContextAction, requestLayout: { animated in + interaction.requestLayout(animated) })) } } @@ -10916,19 +10916,21 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro }))) } - items.append(.action(ContextMenuActionItem(text: "Reorder", icon: { theme in - return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/ReorderItems"), color: theme.contextMenu.primaryColor) - }, action: { [weak pane] _, a in - if ignoreNextActions { - return - } - ignoreNextActions = true - a(.default) - - if let pane { - pane.beginReordering() - } - }))) + if pane.canReorder() { + items.append(.action(ContextMenuActionItem(text: "Reorder", icon: { theme in + return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/ReorderItems"), color: theme.contextMenu.primaryColor) + }, action: { [weak pane] _, a in + if ignoreNextActions { + return + } + ignoreNextActions = true + a(.default) + + if let pane { + pane.beginReordering() + } + }))) + } items.append(.action(ContextMenuActionItem(text: "Select", icon: { theme in return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Select"), color: theme.contextMenu.primaryColor) diff --git a/submodules/TelegramUI/Components/PeerInfo/PeerInfoVisualMediaPaneNode/Sources/PeerInfoStoryPaneNode.swift b/submodules/TelegramUI/Components/PeerInfo/PeerInfoVisualMediaPaneNode/Sources/PeerInfoStoryPaneNode.swift index 2c0cbe7c40..791dae59df 100644 --- a/submodules/TelegramUI/Components/PeerInfo/PeerInfoVisualMediaPaneNode/Sources/PeerInfoStoryPaneNode.swift +++ b/submodules/TelegramUI/Components/PeerInfo/PeerInfoVisualMediaPaneNode/Sources/PeerInfoStoryPaneNode.swift @@ -2495,7 +2495,7 @@ public final class PeerInfoStoryPaneNode: ASDisplayNode, PeerInfoPaneNode, ASScr } self.parentController?.present(UndoOverlayController(presentationData: presentationData, content: .universal(animation: isPinned ? "anim_toastunpin" : "anim_toastpin", scale: 0.06, colors: [:], title: toastTitle, text: toastText, customUndoText: nil, timeout: 5), elevatedLayout: false, animateInAsReplacement: false, action: { _ in return false }), in: .current) }))) - if isPinned { + if isPinned && self.canReorder() { //TODO:localize items.append(.action(ContextMenuActionItem(text: "Reorder", icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/ReorderItems"), color: theme.contextMenu.primaryColor) }, action: { [weak self] c, _ in c?.dismiss(completion: { @@ -2560,7 +2560,7 @@ public final class PeerInfoStoryPaneNode: ASDisplayNode, PeerInfoPaneNode, ASScr }))) } - if canManage, case .botPreview = self.scope { + if canManage, case .botPreview = self.scope, self.canReorder() { //TODO:localize items.append(.action(ContextMenuActionItem(text: "Reorder", icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/ReorderItems"), color: theme.contextMenu.primaryColor) }, action: { [weak self] c, _ in c?.dismiss(completion: { @@ -2571,17 +2571,6 @@ public final class PeerInfoStoryPaneNode: ASDisplayNode, PeerInfoPaneNode, ASScr self.beginReordering() }) }))) - - //TODO:localize - items.append(.action(ContextMenuActionItem(text: "Edit Preview", icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Edit"), color: theme.contextMenu.primaryColor) }, action: { [weak self] c, _ in - c?.dismiss(completion: { - guard let self else { - return - } - - let _ = self - }) - }))) } if !item.isForwardingDisabled, case .everyone = item.privacy?.base { @@ -2791,8 +2780,32 @@ public final class PeerInfoStoryPaneNode: ASDisplayNode, PeerInfoPaneNode, ASScr } } botPreviewLanguages.sort(by: { $0.name < $1.name }) + + var hadLocalItems = false + if let currentListState = self.currentListState { + for item in currentListState.items { + if item.storyItem.isPending { + hadLocalItems = true + } + } + } + self.currentListState = state + var hasLocalItems = false + if let currentListState = self.currentListState { + for item in currentListState.items { + if item.storyItem.isPending { + hasLocalItems = true + } + } + } + + var synchronous = synchronous + if hasLocalItems != hadLocalItems { + synchronous = true + } + self.updateItemsFromState(state: state, firstTime: firstTime, reloadAtTop: reloadAtTop, synchronous: synchronous, animated: false) if self.currentBotPreviewLanguages != botPreviewLanguages || reloadAtTop { @@ -4113,9 +4126,14 @@ public final class PeerInfoStoryPaneNode: ASDisplayNode, PeerInfoPaneNode, ASScr fixedItemHeight = nil let fixedItemAspect: CGFloat? = 0.81 + + var adjustForSmallCount = true + if case .botPreview = self.scope { + adjustForSmallCount = false + } - self.itemGrid.pinchEnabled = items.count > 2 - self.itemGrid.update(size: size, insets: UIEdgeInsets(top: gridTopInset, left: sideInset, bottom: bottomInset, right: sideInset), useSideInsets: !isList, scrollIndicatorInsets: UIEdgeInsets(top: 0.0, left: sideInset, bottom: bottomInset, right: sideInset), lockScrollingAtTop: isScrollingLockedAtTop, fixedItemHeight: fixedItemHeight, fixedItemAspect: fixedItemAspect, items: items, theme: self.itemGridBinding.chatPresentationData.theme.theme, synchronous: wasFirstTime ? .full : .none, transition: animateGridItems ? .spring(duration: 0.35) : .immediate) + self.itemGrid.pinchEnabled = items.count > 2 && !self.isReordering + self.itemGrid.update(size: size, insets: UIEdgeInsets(top: gridTopInset, left: sideInset, bottom: bottomInset, right: sideInset), useSideInsets: !isList, scrollIndicatorInsets: UIEdgeInsets(top: 0.0, left: sideInset, bottom: bottomInset, right: sideInset), lockScrollingAtTop: isScrollingLockedAtTop, fixedItemHeight: fixedItemHeight, fixedItemAspect: fixedItemAspect, adjustForSmallCount: adjustForSmallCount, items: items, theme: self.itemGridBinding.chatPresentationData.theme.theme, synchronous: wasFirstTime ? .full : .none, transition: animateGridItems ? .spring(duration: 0.35) : .immediate) } if case .botPreview = self.scope, self.canManageStories { @@ -4212,6 +4230,13 @@ public final class PeerInfoStoryPaneNode: ASDisplayNode, PeerInfoPaneNode, ASScr return items.count < self.maxBotPreviewCount } + public func canReorder() -> Bool { + guard let items = self.items else { + return false + } + return items.count > 1 + } + private func presentAddBotPreviewLanguage() { self.parentController?.push(LanguageSelectionScreen(context: self.context, selectLocalization: { [weak self] info in guard let self else { diff --git a/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryItemSetContainerComponent.swift b/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryItemSetContainerComponent.swift index e027cd2c7f..a1f5b25732 100644 --- a/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryItemSetContainerComponent.swift +++ b/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryItemSetContainerComponent.swift @@ -6616,17 +6616,6 @@ public final class StoryItemSetContainerComponent: Component { component.reorder() }))) - items.append(.action(ContextMenuActionItem(text: "Edit Preview", icon: { theme in - return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Edit"), color: theme.contextMenu.primaryColor) - }, action: { [weak self] _, a in - a(.default) - - guard let self, let component = self.component else { - return - } - - let _ = component - }))) items.append(.action(ContextMenuActionItem(text: "Delete", textColor: .destructive, icon: { theme in return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Edit"), color: theme.contextMenu.destructiveColor) }, action: { [weak self] _, a in