diff --git a/Signal/src/ViewControllers/Context Menus/ContextMenuInteraction.swift b/Signal/src/ViewControllers/Context Menus/ContextMenuInteraction.swift index a6996917b1..22ea2bd762 100644 --- a/Signal/src/ViewControllers/Context Menus/ContextMenuInteraction.swift +++ b/Signal/src/ViewControllers/Context Menus/ContextMenuInteraction.swift @@ -48,7 +48,7 @@ public class ContextMenuInteraction: NSObject, UIInteraction { private var longPressGestureRecognizer: UIGestureRecognizer = { let recognizer = UILongPressGestureRecognizer(target: self, action: #selector(longPressRecognized(sender:))) - recognizer.minimumPressDuration = 0.1 + recognizer.minimumPressDuration = 0.2 return recognizer }() @@ -278,6 +278,10 @@ public class ChatHistoryContextMenuInteraction: ContextMenuInteraction { } public func initiatingGestureRecognizerDidEnd() { + cancelPresentationGesture() + } + + public func cancelPresentationGesture() { gestureEligibleForMenuPresentation = false if contextMenuController == nil, let configuarion = self.configuration { diff --git a/Signal/src/ViewControllers/ConversationView/ConversationCollectionView.h b/Signal/src/ViewControllers/ConversationView/ConversationCollectionView.h index 410e0d5ed6..b78f2fe99b 100644 --- a/Signal/src/ViewControllers/ConversationView/ConversationCollectionView.h +++ b/Signal/src/ViewControllers/ConversationView/ConversationCollectionView.h @@ -9,6 +9,7 @@ NS_ASSUME_NONNULL_BEGIN - (void)collectionViewWillChangeSizeFrom:(CGSize)oldSize to:(CGSize)newSize; - (void)collectionViewDidChangeSizeFrom:(CGSize)oldSize to:(CGSize)newSize; - (void)collectionViewWillAnimate; +- (BOOL)collectionViewShouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer; @end diff --git a/Signal/src/ViewControllers/ConversationView/ConversationCollectionView.m b/Signal/src/ViewControllers/ConversationView/ConversationCollectionView.m index 5e5613e86d..37d7fdf72e 100644 --- a/Signal/src/ViewControllers/ConversationView/ConversationCollectionView.m +++ b/Signal/src/ViewControllers/ConversationView/ConversationCollectionView.m @@ -112,6 +112,13 @@ NS_ASSUME_NONNULL_BEGIN [super scrollRectToVisible:rect animated:animated]; } +- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer + shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer +{ + return + [self.layoutDelegate collectionViewShouldRecognizeSimultaneouslyWithGestureRecognizer:otherGestureRecognizer]; +} + @end NS_ASSUME_NONNULL_END diff --git a/Signal/src/ViewControllers/ConversationView/ConversationViewController+Delegates.swift b/Signal/src/ViewControllers/ConversationView/ConversationViewController+Delegates.swift index 41d6928e4b..37ffb89237 100644 --- a/Signal/src/ViewControllers/ConversationView/ConversationViewController+Delegates.swift +++ b/Signal/src/ViewControllers/ConversationView/ConversationViewController+Delegates.swift @@ -444,6 +444,10 @@ extension ConversationViewController: ConversationCollectionViewDelegate { scrollingAnimationDidStart() } + public func collectionViewShouldRecognizeSimultaneously(with otherGestureRecognizer: UIGestureRecognizer) -> Bool { + return otherGestureRecognizer == collectionViewContextMenuGestureRecognizer + } + public func scrollingAnimationDidStart() { AssertIsOnMainThread() diff --git a/Signal/src/ViewControllers/ConversationView/ConversationViewController+GestureRecognizers.swift b/Signal/src/ViewControllers/ConversationView/ConversationViewController+GestureRecognizers.swift index 9efcdedbc1..24c36b5c5e 100644 --- a/Signal/src/ViewControllers/ConversationView/ConversationViewController+GestureRecognizers.swift +++ b/Signal/src/ViewControllers/ConversationView/ConversationViewController+GestureRecognizers.swift @@ -16,7 +16,7 @@ extension ConversationViewController: UIGestureRecognizerDelegate { if FeatureFlags.contextMenus { collectionViewContextMenuGestureRecognizer.addTarget(self, action: #selector(handleLongPressGesture)) - collectionViewContextMenuGestureRecognizer.minimumPressDuration = 0.1 + collectionViewContextMenuGestureRecognizer.minimumPressDuration = 0.2 collectionViewContextMenuGestureRecognizer.delegate = self collectionView.addGestureRecognizer(collectionViewContextMenuGestureRecognizer) } @@ -71,7 +71,13 @@ extension ConversationViewController: UIGestureRecognizerDelegate { } public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool { - // Support standard long press recognizing for body text cases, and context menu long press recognizing for everything else + + // Allow the context menu gesture recognizer to recognize simultaneously with scroll + if gestureRecognizer == collectionViewContextMenuGestureRecognizer && otherGestureRecognizer == collectionView.panGestureRecognizer { + return true + } + + // Support standard long press recognizing for body text cases, and context menu long press recognizing for everything else let currentIsLongPressOrTap = (gestureRecognizer == collectionViewLongPressGestureRecognizer || gestureRecognizer == collectionViewContextMenuGestureRecognizer || gestureRecognizer == collectionViewTapGestureRecognizer) let otherIsLongPressOrTap = (otherGestureRecognizer == collectionViewLongPressGestureRecognizer || otherGestureRecognizer == collectionViewContextMenuGestureRecognizer || otherGestureRecognizer == collectionViewTapGestureRecognizer) return currentIsLongPressOrTap && otherIsLongPressOrTap diff --git a/Signal/src/ViewControllers/ConversationView/ConversationViewController+MessageActions.swift b/Signal/src/ViewControllers/ConversationView/ConversationViewController+MessageActions.swift index 401420a2ef..ab8f5a642f 100644 --- a/Signal/src/ViewControllers/ConversationView/ConversationViewController+MessageActions.swift +++ b/Signal/src/ViewControllers/ConversationView/ConversationViewController+MessageActions.swift @@ -286,6 +286,9 @@ extension ConversationViewController: ContextMenuInteractionDelegate { } public func contextMenuInteraction(_ interaction: ContextMenuInteraction, willDisplayMenuForConfiguration: ContextMenuConfiguration) { + // Reset scroll view pan gesture recognizer, so CV does not scroll behind context menu post presentation on user swipe + collectionView.panGestureRecognizer.isEnabled = false + collectionView.panGestureRecognizer.isEnabled = true dismissKeyBoard() } diff --git a/Signal/src/ViewControllers/ConversationView/ConversationViewController+UIScrollView.swift b/Signal/src/ViewControllers/ConversationView/ConversationViewController+UIScrollView.swift index cd91df0cd1..79f72cb376 100644 --- a/Signal/src/ViewControllers/ConversationView/ConversationViewController+UIScrollView.swift +++ b/Signal/src/ViewControllers/ConversationView/ConversationViewController+UIScrollView.swift @@ -150,6 +150,8 @@ extension ConversationViewController: UIScrollViewDelegate { scheduleScrollUpdateTimer() updateScrollingContent() + + updateContextMenuInteractionIfNeeded() } private func scheduleScrollUpdateTimer() { @@ -173,6 +175,12 @@ extension ConversationViewController: UIScrollViewDelegate { RunLoop.main.add(scrollUpdateTimer, forMode: .common) } + private func updateContextMenuInteractionIfNeeded() { + if let contextMenuInteraction = collectionViewActiveContextMenuInteraction { + contextMenuInteraction.cancelPresentationGesture() + } + } + @objc private func scrollUpdateTimerDidFire() { AssertIsOnMainThread()