Skip to content

Commit 9df170e

Browse files
committed
fix intermittent glitches when sending messages.
When UITableView inserts a new row at precisely the same time as us hiding the Send Receipts on a bubble (due to moving them to the new row), there's a race which can cause UITableView to miscalculate y-offsets due to the height of the bubble suddenly changing. To break the race, we hide the SR shortly after the row is inserted. Fixes the problem shown in #4127 (comment)
1 parent 550f59f commit 9df170e

File tree

1 file changed

+23
-1
lines changed

1 file changed

+23
-1
lines changed

ElementX/Sources/Screens/Timeline/View/Supplementary/TimelineItemStatusView.swift

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,35 @@ struct TimelineItemStatusView: View {
1212
let timelineItem: EventBasedTimelineItemProtocol
1313
let adjustedDeliveryStatus: TimelineItemDeliveryStatus?
1414
@EnvironmentObject private var context: TimelineViewModel.Context
15+
@State private var isSendReceiptVisible: Bool
1516

1617
private var isLastOutgoingMessage: Bool {
1718
timelineItem.isOutgoing && context.viewState.timelineState.uniqueIDs.last == timelineItem.id.uniqueID
1819
}
1920

21+
init(timelineItem: EventBasedTimelineItemProtocol, adjustedDeliveryStatus: TimelineItemDeliveryStatus?, context: TimelineViewModel.Context, isSendReceiptVisible: Bool = false) {
22+
self.timelineItem = timelineItem
23+
self.adjustedDeliveryStatus = adjustedDeliveryStatus
24+
// Ugly - we can't call isLastOutgoingMessage here as the real `context` hasn't loaded yet
25+
// so instead we manually pass in context to init() and duplicate isLastOutgoingMessage here.
26+
self.isSendReceiptVisible = timelineItem.isOutgoing && context.viewState.timelineState.uniqueIDs.last == timelineItem.id.uniqueID
27+
}
28+
2029
var body: some View {
2130
mainContent
31+
.onChange(of: context.viewState.timelineState.uniqueIDs.last) { _, _ in
32+
if isLastOutgoingMessage {
33+
isSendReceiptVisible = true
34+
} else if isSendReceiptVisible {
35+
// we were the last msg in the timeline, but not any more
36+
// so remove the SR after a short delay to avoid racing with the new msg animation
37+
DispatchQueue.main.asyncAfter(deadline: .now() + 0.01) {
38+
withAnimation {
39+
isSendReceiptVisible = false
40+
}
41+
}
42+
}
43+
}
2244
}
2345

2446
@ViewBuilder
@@ -39,7 +61,7 @@ struct TimelineItemStatusView: View {
3961
case .sending:
4062
TimelineDeliveryStatusView(deliveryStatus: .sending)
4163
case .sent, .none:
42-
if isLastOutgoingMessage {
64+
if isSendReceiptVisible {
4365
// We only display the sent icon for the latest outgoing message
4466
TimelineDeliveryStatusView(deliveryStatus: .sent)
4567
}

0 commit comments

Comments
 (0)