@@ -28,6 +28,7 @@ public struct MessageContainerView<Factory: ViewFactory>: View {
28
28
@State private var frame : CGRect = . zero
29
29
@State private var computeFrame = false
30
30
@State private var offsetX : CGFloat = 0
31
+ @State private var offsetYAvatar : CGFloat = 0
31
32
@GestureState private var offset : CGSize = . zero
32
33
33
34
private let replyThreshold : CGFloat = 60
@@ -70,14 +71,16 @@ public struct MessageContainerView<Factory: ViewFactory>: View {
70
71
for: utils. messageCachingUtils. authorInfo ( from: message)
71
72
)
72
73
. opacity ( showsAllInfo ? 1 : 0 )
74
+ . offset ( y: bottomReactionsShown ? offsetYAvatar : 0 )
75
+ . animation ( nil )
73
76
}
74
77
}
75
78
76
79
VStack ( alignment: message. isRightAligned ? . trailing : . leading) {
77
80
if isMessagePinned {
78
81
MessagePinDetailsView (
79
82
message: message,
80
- reactionsShown: reactionsShown
83
+ reactionsShown: topReactionsShown
81
84
)
82
85
}
83
86
@@ -90,7 +93,7 @@ public struct MessageContainerView<Factory: ViewFactory>: View {
90
93
)
91
94
. overlay (
92
95
ZStack {
93
- reactionsShown ?
96
+ topReactionsShown ?
94
97
factory. makeMessageReactionView (
95
98
message: message,
96
99
onTapGesture: {
@@ -172,6 +175,29 @@ public struct MessageContainerView<Factory: ViewFactory>: View {
172
175
. accessibilityElement ( children: . contain)
173
176
. accessibility ( identifier: " MessageRepliesView " )
174
177
}
178
+
179
+ if bottomReactionsShown {
180
+ factory. makeBottomReactionsView ( message: message, showsAllInfo: showsAllInfo) {
181
+ handleGestureForMessage (
182
+ showsMessageActions: false ,
183
+ showsBottomContainer: false
184
+ )
185
+ } onLongPress: {
186
+ handleGestureForMessage ( showsMessageActions: false )
187
+ }
188
+ . background (
189
+ GeometryReader { proxy in
190
+ let frame = proxy. frame ( in: . local)
191
+ let height = frame. height
192
+ Color . clear. preference ( key: HeightPreferenceKey . self, value: height)
193
+ }
194
+ )
195
+ . onPreferenceChange ( HeightPreferenceKey . self) { value in
196
+ if value != 0 {
197
+ self . offsetYAvatar = - ( value ?? 0 )
198
+ }
199
+ }
200
+ }
175
201
176
202
if showsAllInfo && !message. isDeleted {
177
203
if message. isSentByCurrentUser && channel. config. readEventsEnabled {
@@ -210,7 +236,7 @@ public struct MessageContainerView<Factory: ViewFactory>: View {
210
236
}
211
237
. padding (
212
238
. top,
213
- reactionsShown && !isMessagePinned ? messageListConfig. messageDisplayOptions. reactionsTopPadding ( message) : 0
239
+ topReactionsShown && !isMessagePinned ? messageListConfig. messageDisplayOptions. reactionsTopPadding ( message) : 0
214
240
)
215
241
. padding ( . horizontal, messageListConfig. messagePaddings. horizontal)
216
242
. padding ( . bottom, showsAllInfo || isMessagePinned ? paddingValue : 2 )
@@ -247,6 +273,20 @@ public struct MessageContainerView<Factory: ViewFactory>: View {
247
273
messageListConfig. messageDisplayOptions. spacerWidth ( width ?? 0 )
248
274
}
249
275
276
+ private var topReactionsShown : Bool {
277
+ if messageListConfig. messageDisplayOptions. reactionsPlacement == . bottom {
278
+ return false
279
+ }
280
+ return reactionsShown
281
+ }
282
+
283
+ private var bottomReactionsShown : Bool {
284
+ if messageListConfig. messageDisplayOptions. reactionsPlacement == . top {
285
+ return false
286
+ }
287
+ return reactionsShown
288
+ }
289
+
250
290
private var reactionsShown : Bool {
251
291
!message. reactionScores. isEmpty
252
292
&& !message. isDeleted
@@ -289,7 +329,10 @@ public struct MessageContainerView<Factory: ViewFactory>: View {
289
329
}
290
330
}
291
331
292
- private func handleGestureForMessage( showsMessageActions: Bool ) {
332
+ private func handleGestureForMessage(
333
+ showsMessageActions: Bool ,
334
+ showsBottomContainer: Bool = true
335
+ ) {
293
336
computeFrame = true
294
337
DispatchQueue . main. asyncAfter ( deadline: . now( ) + 0.1 ) {
295
338
computeFrame = false
@@ -300,7 +343,8 @@ public struct MessageContainerView<Factory: ViewFactory>: View {
300
343
frame: frame,
301
344
contentWidth: contentWidth,
302
345
isFirst: showsAllInfo,
303
- showsMessageActions: showsMessageActions
346
+ showsMessageActions: showsMessageActions,
347
+ showsBottomContainer: showsBottomContainer
304
348
)
305
349
)
306
350
}
@@ -331,6 +375,7 @@ public struct MessageDisplayInfo {
331
375
public let contentWidth : CGFloat
332
376
public let isFirst : Bool
333
377
public var showsMessageActions : Bool = true
378
+ public var showsBottomContainer : Bool = true
334
379
public var keyboardWasShown : Bool = false
335
380
336
381
public init (
@@ -339,6 +384,7 @@ public struct MessageDisplayInfo {
339
384
contentWidth: CGFloat ,
340
385
isFirst: Bool ,
341
386
showsMessageActions: Bool = true ,
387
+ showsBottomContainer: Bool = true ,
342
388
keyboardWasShown: Bool = false
343
389
) {
344
390
self . message = message
@@ -347,5 +393,6 @@ public struct MessageDisplayInfo {
347
393
self . isFirst = isFirst
348
394
self . showsMessageActions = showsMessageActions
349
395
self . keyboardWasShown = keyboardWasShown
396
+ self . showsBottomContainer = showsBottomContainer
350
397
}
351
398
}
0 commit comments