@@ -10,7 +10,6 @@ public struct MessageContainerView<Factory: ViewFactory>: View {
1010 @StateObject var messageViewModel : MessageViewModel
1111 @Environment ( \. channelTranslationLanguage) var translationLanguage
1212 @Environment ( \. highlightedMessageId) var highlightedMessageId
13- @Environment ( \. messageListSwipe) var messageListSwipe
1413
1514 @Injected ( \. fonts) private var fonts
1615 @Injected ( \. colors) private var colors
@@ -33,6 +32,7 @@ public struct MessageContainerView<Factory: ViewFactory>: View {
3332 @State private var computeFrame = false
3433 @State private var offsetX : CGFloat = 0
3534 @State private var offsetYAvatar : CGFloat = 0
35+ @GestureState private var offset : CGSize = . zero
3636
3737 private let replyThreshold : CGFloat = 60
3838 private var paddingValue : CGFloat {
@@ -129,9 +129,6 @@ public struct MessageContainerView<Factory: ViewFactory>: View {
129129 . onChange ( of: computeFrame, perform: { _ in
130130 frame = proxy. frame ( in: . global)
131131 } )
132- . onChange ( of: messageListSwipe, perform: { messageListSwipe in
133- handleMessageListSwipe ( messageListSwipe, geometry: proxy)
134- } )
135132 }
136133 )
137134 . onTapGesture ( count: 2 ) {
@@ -143,6 +140,40 @@ public struct MessageContainerView<Factory: ViewFactory>: View {
143140 handleGestureForMessage ( showsMessageActions: true )
144141 } )
145142 . offset ( x: min ( self . offsetX, maximumHorizontalSwipeDisplacement) )
143+ . simultaneousGesture (
144+ DragGesture (
145+ minimumDistance: minimumSwipeDistance,
146+ coordinateSpace: . local
147+ )
148+ . updating ( $offset) { ( value, gestureState, _) in
149+ guard messageViewModel. isSwipeToQuoteReplyPossible else {
150+ return
151+ }
152+ // Using updating since onEnded is not called if the gesture is canceled.
153+ let diff = CGSize (
154+ width: value. location. x - value. startLocation. x,
155+ height: value. location. y - value. startLocation. y
156+ )
157+
158+ if diff == . zero {
159+ gestureState = . zero
160+ } else {
161+ gestureState = value. translation
162+ }
163+ }
164+ )
165+ . onChange ( of: offset, perform: { _ in
166+ if !channel. config. quotesEnabled {
167+ return
168+ }
169+
170+ if offset == . zero {
171+ // gesture ended or cancelled
172+ setOffsetX ( value: 0 )
173+ } else {
174+ dragChanged ( to: offset. width)
175+ }
176+ } )
146177 . accessibilityElement ( children: . contain)
147178 . accessibilityIdentifier ( " MessageView " )
148179
@@ -320,18 +351,6 @@ public struct MessageContainerView<Factory: ViewFactory>: View {
320351 private var messageListConfig : MessageListConfig {
321352 utils. messageListConfig
322353 }
323-
324- private func handleMessageListSwipe( _ messageListSwipe: MessageListSwipe ? , geometry: GeometryProxy ) {
325- guard messageViewModel. isSwipeToQuoteReplyPossible else { return }
326- guard let messageListSwipe else { return }
327- // The view is moving during the swipe handling, therefore we skip the contains check if it is in progress
328- guard offsetX > 0 || geometry. frame ( in: . global) . contains ( messageListSwipe. startLocation) else { return }
329- if messageListSwipe. horizontalOffset == 0 {
330- setOffsetX ( value: 0 )
331- } else {
332- dragChanged ( to: messageListSwipe. horizontalOffset)
333- }
334- }
335354
336355 private func dragChanged( to value: CGFloat ) {
337356 let horizontalTranslation = value
0 commit comments