From cf5584e02ff15a1e9317c6977394cd01dacbc5a8 Mon Sep 17 00:00:00 2001 From: Isaac <> Date: Tue, 2 Dec 2025 17:20:43 +0800 Subject: [PATCH] Collapse sibling options --- .../AdminUserActionsPeerComponent.swift | 1 + .../Sources/ContentContainer.swift | 20 +++++++++++++++++-- .../Sources/ListActionItemComponent.swift | 20 ++++++++++++++++++- .../ListComposePollOptionComponent.swift | 1 + .../ListItemSliderSelectorComponent.swift | 1 + .../ListMultilineTextFieldItemComponent.swift | 1 + .../Sources/ListSectionComponent.swift | 12 +++++++++++ .../Sources/ListTextFieldItemComponent.swift | 1 + .../Sources/HashtagListItemComponent.swift | 1 + ...aticBusinessMessageListItemComponent.swift | 1 + .../BusinessLinkListItemComponent.swift | 1 + .../Sources/ChatIntroItemComponent.swift | 1 + .../Sources/MapPreviewComponent.swift | 1 + .../ChatbotSearchResultItemComponent.swift | 1 + .../Sources/PeerListItemComponent.swift | 1 + 15 files changed, 61 insertions(+), 3 deletions(-) diff --git a/submodules/TelegramUI/Components/AdminUserActionsSheet/Sources/AdminUserActionsPeerComponent.swift b/submodules/TelegramUI/Components/AdminUserActionsSheet/Sources/AdminUserActionsPeerComponent.swift index 69bab1e9b0..dc1f55617c 100644 --- a/submodules/TelegramUI/Components/AdminUserActionsSheet/Sources/AdminUserActionsPeerComponent.swift +++ b/submodules/TelegramUI/Components/AdminUserActionsSheet/Sources/AdminUserActionsPeerComponent.swift @@ -108,6 +108,7 @@ final class AdminUserActionsPeerComponent: Component { private weak var state: EmptyComponentState? public var customUpdateIsHighlighted: ((Bool) -> Void)? + public var enumerateSiblings: (((UIView) -> Void) -> Void)? public var separatorInset: CGFloat = 0.0 override init(frame: CGRect) { diff --git a/submodules/TelegramUI/Components/ListActionItemComponent/Sources/ContentContainer.swift b/submodules/TelegramUI/Components/ListActionItemComponent/Sources/ContentContainer.swift index aa6362378b..2fd83b0272 100644 --- a/submodules/TelegramUI/Components/ListActionItemComponent/Sources/ContentContainer.swift +++ b/submodules/TelegramUI/Components/ListActionItemComponent/Sources/ContentContainer.swift @@ -100,18 +100,23 @@ private final class ContextOptionComponent: Component { } final class ContentContainer: UIScrollView, UIScrollViewDelegate { + private let closeOtherContextOptions: () -> Void + private var itemViews: [AnyHashable: ComponentView] = [:] private var ignoreScrollingEvents: Bool = false private var draggingBeganInClosedState: Bool = false + private var didProcessScrollingCycle: Bool = false private var contextOptions: [ListActionItemComponent.ContextOption] = [] private var optionsWidth: CGFloat = 0.0 private var revealedStateTapRecognizer: UITapGestureRecognizer? - override init(frame: CGRect) { - super.init(frame: frame) + init(closeOtherContextOptions: @escaping () -> Void) { + self.closeOtherContextOptions = closeOtherContextOptions + + super.init(frame: CGRect()) let revealedStateTapRecognizer = UITapGestureRecognizer(target: self, action: #selector(self.onTapGesture(_:))) self.revealedStateTapRecognizer = revealedStateTapRecognizer @@ -155,9 +160,16 @@ final class ContentContainer: UIScrollView, UIScrollViewDelegate { func scrollViewDidScroll(_ scrollView: UIScrollView) { self.revealedStateTapRecognizer?.isEnabled = self.contentOffset.x > 0.0 + if self.contentOffset.x > 0.0 { + if !self.didProcessScrollingCycle { + self.didProcessScrollingCycle = true + self.closeOtherContextOptions() + } + } } func scrollViewWillBeginDragging(_ scrollView: UIScrollView) { + self.didProcessScrollingCycle = false self.draggingBeganInClosedState = self.contentOffset.x == 0.0 } @@ -200,6 +212,10 @@ final class ContentContainer: UIScrollView, UIScrollViewDelegate { return result } + func closeContextOptions() { + self.setContentOffset(CGPoint(x: 0.0, y: 0.0), animated: true) + } + func update(size: CGSize, contextOptions: [ListActionItemComponent.ContextOption], transition: ComponentTransition) { self.contextOptions = contextOptions diff --git a/submodules/TelegramUI/Components/ListActionItemComponent/Sources/ListActionItemComponent.swift b/submodules/TelegramUI/Components/ListActionItemComponent/Sources/ListActionItemComponent.swift index e578f095b1..435802b919 100644 --- a/submodules/TelegramUI/Components/ListActionItemComponent/Sources/ListActionItemComponent.swift +++ b/submodules/TelegramUI/Components/ListActionItemComponent/Sources/ListActionItemComponent.swift @@ -348,10 +348,14 @@ public final class ListActionItemComponent: Component { } public var customUpdateIsHighlighted: ((Bool) -> Void)? + public var enumerateSiblings: (((UIView) -> Void) -> Void)? public var separatorInset: CGFloat = 0.0 public override init(frame: CGRect) { - self.container = ContentContainer(frame: CGRect()) + var closeOtherContextOptions: (() -> Void)? + self.container = ContentContainer(closeOtherContextOptions: { + closeOtherContextOptions?() + }) self.button = HighlightTrackingButton() super.init(frame: CGRect()) @@ -375,6 +379,20 @@ public final class ListActionItemComponent: Component { customUpdateIsHighlighted(isHighlighted) } } + + closeOtherContextOptions = { [weak self] in + guard let self else { + return + } + self.enumerateSiblings?({ sibling in + if self === sibling { + return + } + if let view = sibling as? View { + view.container.closeContextOptions() + } + }) + } } required public init?(coder: NSCoder) { diff --git a/submodules/TelegramUI/Components/ListComposePollOptionComponent/Sources/ListComposePollOptionComponent.swift b/submodules/TelegramUI/Components/ListComposePollOptionComponent/Sources/ListComposePollOptionComponent.swift index f0784bd4a2..0744f141da 100644 --- a/submodules/TelegramUI/Components/ListComposePollOptionComponent/Sources/ListComposePollOptionComponent.swift +++ b/submodules/TelegramUI/Components/ListComposePollOptionComponent/Sources/ListComposePollOptionComponent.swift @@ -425,6 +425,7 @@ public final class ListComposePollOptionComponent: Component { } public var customUpdateIsHighlighted: ((Bool) -> Void)? + public var enumerateSiblings: (((UIView) -> Void) -> Void)? public private(set) var separatorInset: CGFloat = 0.0 public override init(frame: CGRect) { diff --git a/submodules/TelegramUI/Components/ListItemSliderSelectorComponent/Sources/ListItemSliderSelectorComponent.swift b/submodules/TelegramUI/Components/ListItemSliderSelectorComponent/Sources/ListItemSliderSelectorComponent.swift index 31cd8ad9a1..a7ec0fe0da 100644 --- a/submodules/TelegramUI/Components/ListItemSliderSelectorComponent/Sources/ListItemSliderSelectorComponent.swift +++ b/submodules/TelegramUI/Components/ListItemSliderSelectorComponent/Sources/ListItemSliderSelectorComponent.swift @@ -130,6 +130,7 @@ public final class ListItemSliderSelectorComponent: Component { private weak var state: EmptyComponentState? public var customUpdateIsHighlighted: ((Bool) -> Void)? + public var enumerateSiblings: (((UIView) -> Void) -> Void)? public private(set) var separatorInset: CGFloat = 0.0 override public init(frame: CGRect) { diff --git a/submodules/TelegramUI/Components/ListMultilineTextFieldItemComponent/Sources/ListMultilineTextFieldItemComponent.swift b/submodules/TelegramUI/Components/ListMultilineTextFieldItemComponent/Sources/ListMultilineTextFieldItemComponent.swift index 60dc69c6bd..171a610f85 100644 --- a/submodules/TelegramUI/Components/ListMultilineTextFieldItemComponent/Sources/ListMultilineTextFieldItemComponent.swift +++ b/submodules/TelegramUI/Components/ListMultilineTextFieldItemComponent/Sources/ListMultilineTextFieldItemComponent.swift @@ -202,6 +202,7 @@ public final class ListMultilineTextFieldItemComponent: Component { } public var customUpdateIsHighlighted: ((Bool) -> Void)? + public var enumerateSiblings: (((UIView) -> Void) -> Void)? public private(set) var separatorInset: CGFloat = 0.0 public override init(frame: CGRect) { diff --git a/submodules/TelegramUI/Components/ListSectionComponent/Sources/ListSectionComponent.swift b/submodules/TelegramUI/Components/ListSectionComponent/Sources/ListSectionComponent.swift index 10ad6baf5d..9b6d022b7e 100644 --- a/submodules/TelegramUI/Components/ListSectionComponent/Sources/ListSectionComponent.swift +++ b/submodules/TelegramUI/Components/ListSectionComponent/Sources/ListSectionComponent.swift @@ -7,6 +7,7 @@ import DynamicCornerRadiusView public protocol ListSectionComponentChildView: AnyObject { var customUpdateIsHighlighted: ((Bool) -> Void)? { get set } + var enumerateSiblings: (((UIView) -> Void) -> Void)? { get set } var separatorInset: CGFloat { get } } @@ -190,6 +191,16 @@ public final class ListSectionContentView: UIView { } self.updateHighlightedItem(itemId: isHighlighted ? itemId : nil) } + itemComponentView.enumerateSiblings = { [weak self, weak itemComponentView] f in + guard let self, let itemComponentView else { + return + } + for (_, itemView) in self.itemViews { + if let otherItemView = itemView.contents.view, otherItemView !== itemComponentView { + f(otherItemView) + } + } + } } } var separatorInset: CGFloat = 0.0 @@ -619,6 +630,7 @@ public final class ListSubSectionComponent: Component { private var component: ListSubSectionComponent? public var customUpdateIsHighlighted: ((Bool) -> Void)? + public var enumerateSiblings: (((UIView) -> Void) -> Void)? public var separatorInset: CGFloat = 0.0 public override init(frame: CGRect) { diff --git a/submodules/TelegramUI/Components/ListTextFieldItemComponent/Sources/ListTextFieldItemComponent.swift b/submodules/TelegramUI/Components/ListTextFieldItemComponent/Sources/ListTextFieldItemComponent.swift index ae8554b1e3..dbe60f2178 100644 --- a/submodules/TelegramUI/Components/ListTextFieldItemComponent/Sources/ListTextFieldItemComponent.swift +++ b/submodules/TelegramUI/Components/ListTextFieldItemComponent/Sources/ListTextFieldItemComponent.swift @@ -127,6 +127,7 @@ public final class ListTextFieldItemComponent: Component { } public var customUpdateIsHighlighted: ((Bool) -> Void)? + public var enumerateSiblings: (((UIView) -> Void) -> Void)? public private(set) var separatorInset: CGFloat = 0.0 public override init(frame: CGRect) { diff --git a/submodules/TelegramUI/Components/MessageInputPanelComponent/Sources/HashtagListItemComponent.swift b/submodules/TelegramUI/Components/MessageInputPanelComponent/Sources/HashtagListItemComponent.swift index e51ab6cfea..13cfb235cb 100644 --- a/submodules/TelegramUI/Components/MessageInputPanelComponent/Sources/HashtagListItemComponent.swift +++ b/submodules/TelegramUI/Components/MessageInputPanelComponent/Sources/HashtagListItemComponent.swift @@ -196,6 +196,7 @@ public final class HashtagListItemComponent: Component { private var isExtractedToContextMenu: Bool = false public var customUpdateIsHighlighted: ((Bool) -> Void)? + public var enumerateSiblings: (((UIView) -> Void) -> Void)? public private(set) var separatorInset: CGFloat = 0.0 override init(frame: CGRect) { diff --git a/submodules/TelegramUI/Components/Settings/AutomaticBusinessMessageSetupScreen/Sources/AutomaticBusinessMessageListItemComponent.swift b/submodules/TelegramUI/Components/Settings/AutomaticBusinessMessageSetupScreen/Sources/AutomaticBusinessMessageListItemComponent.swift index c293113855..74bcf76ef4 100644 --- a/submodules/TelegramUI/Components/Settings/AutomaticBusinessMessageSetupScreen/Sources/AutomaticBusinessMessageListItemComponent.swift +++ b/submodules/TelegramUI/Components/Settings/AutomaticBusinessMessageSetupScreen/Sources/AutomaticBusinessMessageListItemComponent.swift @@ -72,6 +72,7 @@ final class GreetingMessageListItemComponent: Component { private var itemNode: ListViewItemNode? var customUpdateIsHighlighted: ((Bool) -> Void)? + var enumerateSiblings: (((UIView) -> Void) -> Void)? private(set) var separatorInset: CGFloat = 0.0 override init(frame: CGRect) { diff --git a/submodules/TelegramUI/Components/Settings/AutomaticBusinessMessageSetupScreen/Sources/BusinessLinkListItemComponent.swift b/submodules/TelegramUI/Components/Settings/AutomaticBusinessMessageSetupScreen/Sources/BusinessLinkListItemComponent.swift index 16d7b4488f..e1f7fd4b1f 100644 --- a/submodules/TelegramUI/Components/Settings/AutomaticBusinessMessageSetupScreen/Sources/BusinessLinkListItemComponent.swift +++ b/submodules/TelegramUI/Components/Settings/AutomaticBusinessMessageSetupScreen/Sources/BusinessLinkListItemComponent.swift @@ -73,6 +73,7 @@ final class BusinessLinkListItemComponent: Component { private weak var componentState: EmptyComponentState? var customUpdateIsHighlighted: ((Bool) -> Void)? + var enumerateSiblings: (((UIView) -> Void) -> Void)? private(set) var separatorInset: CGFloat = 0.0 private var isExtractedToContextMenu: Bool = false diff --git a/submodules/TelegramUI/Components/Settings/BusinessIntroSetupScreen/Sources/ChatIntroItemComponent.swift b/submodules/TelegramUI/Components/Settings/BusinessIntroSetupScreen/Sources/ChatIntroItemComponent.swift index a6811b04db..1bd282be5d 100644 --- a/submodules/TelegramUI/Components/Settings/BusinessIntroSetupScreen/Sources/ChatIntroItemComponent.swift +++ b/submodules/TelegramUI/Components/Settings/BusinessIntroSetupScreen/Sources/ChatIntroItemComponent.swift @@ -67,6 +67,7 @@ final class ChatIntroItemComponent: Component { private var emptyNode: ChatEmptyNode? var customUpdateIsHighlighted: ((Bool) -> Void)? + var enumerateSiblings: (((UIView) -> Void) -> Void)? private(set) var separatorInset: CGFloat = 0.0 override init(frame: CGRect) { diff --git a/submodules/TelegramUI/Components/Settings/BusinessLocationSetupScreen/Sources/MapPreviewComponent.swift b/submodules/TelegramUI/Components/Settings/BusinessLocationSetupScreen/Sources/MapPreviewComponent.swift index b48375c117..35f16ff3bd 100644 --- a/submodules/TelegramUI/Components/Settings/BusinessLocationSetupScreen/Sources/MapPreviewComponent.swift +++ b/submodules/TelegramUI/Components/Settings/BusinessLocationSetupScreen/Sources/MapPreviewComponent.swift @@ -56,6 +56,7 @@ final class MapPreviewComponent: Component { private let pinForegroundView: UIImageView var customUpdateIsHighlighted: ((Bool) -> Void)? + var enumerateSiblings: (((UIView) -> Void) -> Void)? private(set) var separatorInset: CGFloat = 0.0 override init(frame: CGRect) { diff --git a/submodules/TelegramUI/Components/Settings/ChatbotSetupScreen/Sources/ChatbotSearchResultItemComponent.swift b/submodules/TelegramUI/Components/Settings/ChatbotSetupScreen/Sources/ChatbotSearchResultItemComponent.swift index 3423eb4caf..bbe37bf01b 100644 --- a/submodules/TelegramUI/Components/Settings/ChatbotSetupScreen/Sources/ChatbotSearchResultItemComponent.swift +++ b/submodules/TelegramUI/Components/Settings/ChatbotSetupScreen/Sources/ChatbotSearchResultItemComponent.swift @@ -74,6 +74,7 @@ final class ChatbotSearchResultItemComponent: Component { private weak var state: EmptyComponentState? var customUpdateIsHighlighted: ((Bool) -> Void)? + var enumerateSiblings: (((UIView) -> Void) -> Void)? private(set) var separatorInset: CGFloat = 0.0 override init(frame: CGRect) { diff --git a/submodules/TelegramUI/Components/Stories/PeerListItemComponent/Sources/PeerListItemComponent.swift b/submodules/TelegramUI/Components/Stories/PeerListItemComponent/Sources/PeerListItemComponent.swift index 6567c1d2a5..3e4d303edd 100644 --- a/submodules/TelegramUI/Components/Stories/PeerListItemComponent/Sources/PeerListItemComponent.swift +++ b/submodules/TelegramUI/Components/Stories/PeerListItemComponent/Sources/PeerListItemComponent.swift @@ -464,6 +464,7 @@ public final class PeerListItemComponent: Component { private var isExtractedToContextMenu: Bool = false public var customUpdateIsHighlighted: ((Bool) -> Void)? + public var enumerateSiblings: (((UIView) -> Void) -> Void)? public private(set) var separatorInset: CGFloat = 0.0 override init(frame: CGRect) {