Skip to content

Commit f87de2d

Browse files
Preventing jump when new messages are received
1 parent 2f449d6 commit f87de2d

File tree

1 file changed

+56
-11
lines changed

1 file changed

+56
-11
lines changed

Sources/StreamChatSwiftUI/ChatChannel/MessageList/MessageListView.swift

Lines changed: 56 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@ public struct MessageListView<Factory: ViewFactory>: View, KeyboardReadable {
3131
@State private var keyboardShown = false
3232
@State private var pendingKeyboardUpdate: Bool?
3333

34+
private var messageRenderingUtil = MessageRenderingUtil.shared
35+
private var skipRenderingMessageIds = [String]()
36+
3437
private var dateFormatter: DateFormatter {
3538
utils.dateFormatter
3639
}
@@ -75,6 +78,19 @@ public struct MessageListView<Factory: ViewFactory>: View, KeyboardReadable {
7578
_scrolledId = scrolledId
7679
_showScrollToLatestButton = showScrollToLatestButton
7780
_quotedMessage = quotedMessage
81+
if !messageRenderingUtil.hasPreviousMessageSet
82+
|| self.showScrollToLatestButton == false
83+
|| self.scrolledId != nil
84+
|| messages.first?.isSentByCurrentUser == true {
85+
messageRenderingUtil.update(previousTopMessage: messages.first)
86+
}
87+
skipRenderingMessageIds = messageRenderingUtil.messagesToSkipRendering(newMessages: messages)
88+
if !skipRenderingMessageIds.isEmpty {
89+
self.messages = LazyCachedMapCollection(
90+
source: messages.filter { !skipRenderingMessageIds.contains($0.id) },
91+
map: { $0 }
92+
)
93+
}
7894
}
7995

8096
public var body: some View {
@@ -151,10 +167,6 @@ public struct MessageListView<Factory: ViewFactory>: View, KeyboardReadable {
151167
.flippedUpsideDown()
152168
.frame(minWidth: self.width, minHeight: height)
153169
.onChange(of: scrolledId) { scrolledId in
154-
if !self.scrolledIdAvailableInMessages {
155-
self.scrolledId = nil
156-
return
157-
}
158170
if let scrolledId = scrolledId {
159171
if scrolledId == messages.first?.messageId {
160172
self.scrolledId = nil
@@ -199,13 +211,8 @@ public struct MessageListView<Factory: ViewFactory>: View, KeyboardReadable {
199211
}
200212
})
201213
.modifier(HideKeyboardOnTapGesture(shouldAdd: keyboardShown))
202-
}
203-
204-
private var scrolledIdAvailableInMessages: Bool {
205-
if let scrolledId = scrolledId {
206-
return messages.map(\.messageId).contains(scrolledId)
207-
} else {
208-
return false
214+
.onDisappear {
215+
messageRenderingUtil.update(previousTopMessage: nil)
209216
}
210217
}
211218

@@ -340,3 +347,41 @@ struct TypingIndicatorBottomView: View {
340347
}
341348
}
342349
}
350+
351+
private class MessageRenderingUtil {
352+
353+
private var previousTopMessage: ChatMessage?
354+
355+
static let shared = MessageRenderingUtil()
356+
357+
var hasPreviousMessageSet: Bool {
358+
previousTopMessage != nil
359+
}
360+
361+
func update(previousTopMessage: ChatMessage?) {
362+
self.previousTopMessage = previousTopMessage
363+
}
364+
365+
func messagesToSkipRendering(newMessages: LazyCachedMapCollection<ChatMessage>) -> [String] {
366+
let newTopMessage = newMessages.first
367+
if newTopMessage?.id == previousTopMessage?.id {
368+
return []
369+
}
370+
371+
if newTopMessage?.cid != previousTopMessage?.cid {
372+
previousTopMessage = newTopMessage
373+
return []
374+
}
375+
376+
var skipRendering = [String]()
377+
for message in newMessages {
378+
if previousTopMessage?.id == message.id {
379+
break
380+
} else {
381+
skipRendering.append(message.id)
382+
}
383+
}
384+
385+
return skipRendering
386+
}
387+
}

0 commit comments

Comments
 (0)