From a6449020b69772ac6cd735dd1dd6ffdfc03e3fcf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20D=E2=80=99Aquino?= Date: Mon, 14 Oct 2024 17:24:04 -0700 Subject: [PATCH] Fix sensitive chat bubble on iOS 18 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit fixes an issue with the chat bubble view where it would unexpectedly trigger the reaction emoji keyboard when scrolling or swiping, which became specially sensitive on iOS 18. The fix consists of 2 parts: - Changing the long press gesture logic to better adhere to Apple's API specs - Modify the SwipeActions library to allow the gesture priority to be configurable, and demote the swiping gesture to have normal priority (it was found that having a high-priority drag gesture prevents long-presses from being activated) Closes: https://github.com/damus-io/damus/issues/2577 Changelog-Fixed: Fix sensitive long-press gesture on event chat bubble in iOS 18 Signed-off-by: Daniel D’Aquino --- damus.xcodeproj/project.pbxproj | 6 ++-- .../xcshareddata/swiftpm/Package.resolved | 7 ++--- damus/Views/Chat/ChatEventView.swift | 28 ++++++------------- 3 files changed, 15 insertions(+), 26 deletions(-) diff --git a/damus.xcodeproj/project.pbxproj b/damus.xcodeproj/project.pbxproj index 260c145b..7e3f76a5 100644 --- a/damus.xcodeproj/project.pbxproj +++ b/damus.xcodeproj/project.pbxproj @@ -5564,10 +5564,10 @@ }; D78DB8572C1CE9CA00F0AB12 /* XCRemoteSwiftPackageReference "SwipeActions" */ = { isa = XCRemoteSwiftPackageReference; - repositoryURL = "https://github.com/aheze/SwipeActions"; + repositoryURL = "https://github.com/damus-io/SwipeActions.git"; requirement = { - kind = exactVersion; - version = 1.1.0; + kind = revision; + revision = 33d99756c3112e1a07c1732e3cddc5ad5bd0c5f4; }; }; D7A343EC2AD0D77C00CED48B /* XCRemoteSwiftPackageReference "swift-snapshot-testing" */ = { diff --git a/damus.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/damus.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index f2ca14fd..7cdc452f 100644 --- a/damus.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/damus.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -1,5 +1,5 @@ { - "originHash" : "babaf4d5748afecf49bbb702530d8e9576460692f478b0a50ee43195dd4440e2", + "originHash" : "1b14e62192b3fa4b04a57cb4601d175b325dc16cb5f22c4c8eb975a675328637", "pins" : [ { "identity" : "emojikit", @@ -92,10 +92,9 @@ { "identity" : "swipeactions", "kind" : "remoteSourceControl", - "location" : "https://github.com/aheze/SwipeActions", + "location" : "https://github.com/damus-io/SwipeActions.git", "state" : { - "revision" : "41e6f6dce02d8cfa164f8c5461a41340850ca3ab", - "version" : "1.1.0" + "revision" : "33d99756c3112e1a07c1732e3cddc5ad5bd0c5f4" } } ], diff --git a/damus/Views/Chat/ChatEventView.swift b/damus/Views/Chat/ChatEventView.swift index 751d9b64..5884b409 100644 --- a/damus/Views/Chat/ChatEventView.swift +++ b/damus/Views/Chat/ChatEventView.swift @@ -27,8 +27,6 @@ struct ChatEventView: View { // MARK: long-press reaction control objects /// Whether the user is actively pressing the view @State var is_pressing = false - /// The dispatched work item scheduled by a timer to bounce the event bubble and show the emoji selector - @State var long_press_bounce_work_item: DispatchWorkItem? @State var popover_state: PopoverState = .closed { didSet { let generator = UIImpactFeedbackGenerator(style: popover_state.some_sheet_open() ? .heavy : .light) @@ -39,6 +37,7 @@ struct ChatEventView: View { @State private var isOnTopHalfOfScreen: Bool = false @ObservedObject var bar: ActionBarModel + @Environment(\.swipeViewGroupSelection) var swipeViewGroupSelection enum PopoverState: String { case closed @@ -206,28 +205,18 @@ struct ChatEventView: View { .scaleEffect(self.popover_state.some_sheet_open() ? 1.08 : is_pressing ? 1.02 : 1) .shadow(color: (is_pressing || self.popover_state.some_sheet_open()) ? .black.opacity(0.1) : .black.opacity(0.3), radius: (is_pressing || self.popover_state.some_sheet_open()) ? 8 : 0, y: (is_pressing || self.popover_state.some_sheet_open()) ? 15 : 0) .onLongPressGesture(minimumDuration: 0.5, maximumDistance: 10, perform: { - long_press_bounce_work_item?.cancel() + withAnimation(.bouncy(duration: 0.2, extraBounce: 0.35)) { + let should_show_zap_sheet = !damus_state.settings.nozaps && damus_state.settings.onlyzaps_mode + popover_state = should_show_zap_sheet ? .open_zap_sheet : .open_emoji_selector + } }, onPressingChanged: { is_pressing in withAnimation(is_pressing ? .easeIn(duration: 0.5) : .easeOut(duration: 0.1)) { self.is_pressing = is_pressing - if popover_state != .closed { - return - } - if self.is_pressing { - let item = DispatchWorkItem { - // Ensure the action is performed only if the condition is still valid - if self.is_pressing { - withAnimation(.bouncy(duration: 0.2, extraBounce: 0.35)) { - let should_show_zap_sheet = !damus_state.settings.nozaps && damus_state.settings.onlyzaps_mode - popover_state = should_show_zap_sheet ? .open_zap_sheet : .open_emoji_selector - } - } - } - long_press_bounce_work_item = item - DispatchQueue.main.asyncAfter(deadline: .now() + 0.5, execute: item) - } } }) + .onChange(of: swipeViewGroupSelection.wrappedValue) { newValue in + self.is_pressing = false + } .background( GeometryReader { geometry in EmptyView() @@ -310,6 +299,7 @@ struct ChatEventView: View { .swipeSpacing(-20) .swipeActionsStyle(.mask) .swipeMinimumDistance(20) + .swipeDragGesturePriority(.normal) } }