mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-05 20:09:04 +00:00
Low effort fix for timeline date separator glitches
This commit is contained in:
committed by
Stefan Ceriu
parent
faefb00626
commit
0d27ed1bbd
@@ -44,8 +44,8 @@ struct CollapsibleRoomTimelineView: View {
|
|||||||
|
|
||||||
struct CollapsibleRoomTimelineView_Previews: PreviewProvider {
|
struct CollapsibleRoomTimelineView_Previews: PreviewProvider {
|
||||||
static var previews: some View {
|
static var previews: some View {
|
||||||
let item = CollapsibleTimelineItem(items: [SeparatorRoomTimelineItem(text: "This is a separator"),
|
let item = CollapsibleTimelineItem(items: [SeparatorRoomTimelineItem(id: "First separator", text: "This is a separator"),
|
||||||
SeparatorRoomTimelineItem(text: "This is another separator")])
|
SeparatorRoomTimelineItem(id: "Second separator", text: "This is another separator")])
|
||||||
CollapsibleRoomTimelineView(timelineItem: item)
|
CollapsibleRoomTimelineView(timelineItem: item)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ struct ReadMarkerRoomTimelineView_Previews: PreviewProvider {
|
|||||||
static let item = ReadMarkerRoomTimelineItem()
|
static let item = ReadMarkerRoomTimelineItem()
|
||||||
static var previews: some View {
|
static var previews: some View {
|
||||||
VStack(alignment: .leading, spacing: 0) {
|
VStack(alignment: .leading, spacing: 0) {
|
||||||
RoomTimelineViewProvider.separator(.init(text: "Today"), .single)
|
RoomTimelineViewProvider.separator(.init(id: "Separator", text: "Today"), .single)
|
||||||
RoomTimelineViewProvider.text(.init(id: "",
|
RoomTimelineViewProvider.text(.init(id: "",
|
||||||
timestamp: "",
|
timestamp: "",
|
||||||
isOutgoing: true,
|
isOutgoing: true,
|
||||||
@@ -51,7 +51,7 @@ struct ReadMarkerRoomTimelineView_Previews: PreviewProvider {
|
|||||||
|
|
||||||
ReadMarkerRoomTimelineView(timelineItem: item)
|
ReadMarkerRoomTimelineView(timelineItem: item)
|
||||||
|
|
||||||
RoomTimelineViewProvider.separator(.init(text: "Today"), .single)
|
RoomTimelineViewProvider.separator(.init(id: "Separator", text: "Today"), .single)
|
||||||
RoomTimelineViewProvider.text(.init(id: "",
|
RoomTimelineViewProvider.text(.init(id: "",
|
||||||
timestamp: "",
|
timestamp: "",
|
||||||
isOutgoing: false,
|
isOutgoing: false,
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ struct SeparatorRoomTimelineView: View {
|
|||||||
|
|
||||||
struct SeparatorRoomTimelineView_Previews: PreviewProvider {
|
struct SeparatorRoomTimelineView_Previews: PreviewProvider {
|
||||||
static var previews: some View {
|
static var previews: some View {
|
||||||
let item = SeparatorRoomTimelineItem(text: "This is a separator")
|
let item = SeparatorRoomTimelineItem(id: "Separator", text: "This is a separator")
|
||||||
SeparatorRoomTimelineView(timelineItem: item)
|
SeparatorRoomTimelineView(timelineItem: item)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ import Foundation
|
|||||||
enum RoomTimelineItemFixtures {
|
enum RoomTimelineItemFixtures {
|
||||||
/// The default timeline items used in Xcode previews etc.
|
/// The default timeline items used in Xcode previews etc.
|
||||||
static var `default`: [RoomTimelineItemProtocol] = [
|
static var `default`: [RoomTimelineItemProtocol] = [
|
||||||
SeparatorRoomTimelineItem(text: "Yesterday"),
|
SeparatorRoomTimelineItem(id: "Yesterday", text: "Yesterday"),
|
||||||
TextRoomTimelineItem(id: UUID().uuidString,
|
TextRoomTimelineItem(id: UUID().uuidString,
|
||||||
timestamp: "10:10 AM",
|
timestamp: "10:10 AM",
|
||||||
isOutgoing: false,
|
isOutgoing: false,
|
||||||
@@ -46,7 +46,7 @@ enum RoomTimelineItemFixtures {
|
|||||||
AggregatedReaction(key: "🙏", count: 1, isHighlighted: false),
|
AggregatedReaction(key: "🙏", count: 1, isHighlighted: false),
|
||||||
AggregatedReaction(key: "🙌", count: 2, isHighlighted: true)
|
AggregatedReaction(key: "🙌", count: 2, isHighlighted: true)
|
||||||
])),
|
])),
|
||||||
SeparatorRoomTimelineItem(text: "Today"),
|
SeparatorRoomTimelineItem(id: "Today", text: "Today"),
|
||||||
TextRoomTimelineItem(id: UUID().uuidString,
|
TextRoomTimelineItem(id: UUID().uuidString,
|
||||||
timestamp: "5 PM",
|
timestamp: "5 PM",
|
||||||
isOutgoing: false,
|
isOutgoing: false,
|
||||||
|
|||||||
@@ -231,8 +231,13 @@ class RoomTimelineController: RoomTimelineControllerProtocol {
|
|||||||
for (index, collapsibleChunk) in collapsibleChunks.enumerated() {
|
for (index, collapsibleChunk) in collapsibleChunks.enumerated() {
|
||||||
let isLastItem = index == collapsibleChunks.indices.last
|
let isLastItem = index == collapsibleChunks.indices.last
|
||||||
|
|
||||||
|
// Try building a stable identifier for items that don't have one
|
||||||
|
// We need to avoid duplicates otherwise the diffable datasource will crash
|
||||||
|
let reversedIndex = collapsibleChunks.count - index
|
||||||
|
|
||||||
let items = collapsibleChunk.compactMap { itemProxy in
|
let items = collapsibleChunk.compactMap { itemProxy in
|
||||||
let timelineItem = buildTimelineItem(for: itemProxy)
|
|
||||||
|
let timelineItem = buildTimelineItem(for: itemProxy, chunkIndex: reversedIndex)
|
||||||
|
|
||||||
if timelineItem is PaginationIndicatorRoomTimelineItem {
|
if timelineItem is PaginationIndicatorRoomTimelineItem {
|
||||||
isBackPaginating = true
|
isBackPaginating = true
|
||||||
@@ -267,17 +272,19 @@ class RoomTimelineController: RoomTimelineControllerProtocol {
|
|||||||
callbacks.send(.isBackPaginating(isBackPaginating))
|
callbacks.send(.isBackPaginating(isBackPaginating))
|
||||||
}
|
}
|
||||||
|
|
||||||
private func buildTimelineItem(for itemProxy: TimelineItemProxy) -> RoomTimelineItemProtocol? {
|
private func buildTimelineItem(for itemProxy: TimelineItemProxy, chunkIndex: Int) -> RoomTimelineItemProtocol? {
|
||||||
switch itemProxy {
|
switch itemProxy {
|
||||||
case .event(let eventTimelineItem):
|
case .event(let eventTimelineItem):
|
||||||
return timelineItemFactory.buildTimelineItem(for: eventTimelineItem)
|
return timelineItemFactory.buildTimelineItem(for: eventTimelineItem)
|
||||||
case .virtual(let virtualItem):
|
case .virtual(let virtualItem):
|
||||||
switch virtualItem {
|
switch virtualItem {
|
||||||
case .dayDivider(let timestamp):
|
case .dayDivider(let timestamp):
|
||||||
// These components will be replaced by a timestamp in upcoming releases
|
|
||||||
let date = Date(timeIntervalSince1970: TimeInterval(timestamp / 1000))
|
let date = Date(timeIntervalSince1970: TimeInterval(timestamp / 1000))
|
||||||
let dateString = date.formatted(date: .complete, time: .omitted)
|
let dateString = date.formatted(date: .complete, time: .omitted)
|
||||||
return SeparatorRoomTimelineItem(text: dateString)
|
|
||||||
|
// Separators without stable identifiers cause UI glitches
|
||||||
|
let identifier = "\(chunkIndex)-\(dateString)"
|
||||||
|
return SeparatorRoomTimelineItem(id: identifier, text: dateString)
|
||||||
case .readMarker:
|
case .readMarker:
|
||||||
return ReadMarkerRoomTimelineItem()
|
return ReadMarkerRoomTimelineItem()
|
||||||
case .loadingIndicator:
|
case .loadingIndicator:
|
||||||
|
|||||||
+1
-2
@@ -17,7 +17,6 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
struct SeparatorRoomTimelineItem: DecorationTimelineItemProtocol, Identifiable, Hashable {
|
struct SeparatorRoomTimelineItem: DecorationTimelineItemProtocol, Identifiable, Hashable {
|
||||||
#warning("This should really be a stable identifier, ideally coming from the SDK, but unfortunately we receive duplicates for it at the moment, crashing our timeline data source")
|
let id: String
|
||||||
let id: String = UUID().uuidString
|
|
||||||
let text: String
|
let text: String
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user