Introduced the RoomTimelineViewProvider with different timeline items/views. Added timeline date separators (currently breaks back pagination)

This commit is contained in:
Stefan Ceriu
2022-03-11 14:47:11 +02:00
parent d413a67329
commit 3d7b3d3d63
17 changed files with 329 additions and 192 deletions
@@ -0,0 +1,14 @@
//
// ImageRoomTimelineItem.swift
// ElementX
//
// Created by Stefan Ceriu on 11/03/2022.
// Copyright © 2022 Element. All rights reserved.
//
import Foundation
struct ImageRoomTimelineItem: Identifiable, Equatable {
let id: String
let text: String
}
@@ -0,0 +1,23 @@
//
// ImageRoomTimelineView.swift
// ElementX
//
// Created by Stefan Ceriu on 11/03/2022.
// Copyright © 2022 Element. All rights reserved.
//
import Foundation
import SwiftUI
struct ImageRoomTimelineView: View {
let timelineItem: ImageRoomTimelineItem
var loadedImage: UIImage?
var body: some View {
if let loadedImage = loadedImage {
Image(uiImage: loadedImage)
} else {
ProgressView()
}
}
}
@@ -1,84 +0,0 @@
//
// TextRoomTimelineItem.swift
// ElementX
//
// Created by Stefan Ceriu on 04.03.2022.
// Copyright © 2022 Element. All rights reserved.
//
import Foundation
import SwiftUI
private var dateFormatter: DateFormatter = {
let dateFormatter = DateFormatter()
dateFormatter.dateStyle = .none
dateFormatter.timeStyle = .short
return dateFormatter
}()
enum RoomTimelineItem: Identifiable, Equatable {
case text(id: String, senderDisplayName: String, text: String, originServerTs: Date, shouldShowSenderDetails: Bool)
case sectionTitle(id: String, text: String)
var id: String {
switch self {
case .text(let id, _, _, _, _):
return id
case .sectionTitle(let id, _):
return id
}
}
}
extension RoomTimelineItem: View {
var body: some View {
switch self {
case .text(let id, let senderDisplayName, let text, let originServerTs, let shouldShowSenderDetails):
VStack(alignment: .leading) {
if shouldShowSenderDetails {
HStack {
Text(senderDisplayName)
.font(.footnote)
.bold()
Spacer()
Text(dateFormatter.string(from: originServerTs))
.font(.footnote)
}
Divider()
Spacer()
}
Text(text)
}
.listRowSeparator(.hidden)
.id(id)
case .sectionTitle(let id, let text):
LabelledDivider(label: text)
.id(id)
}
}
}
struct LabelledDivider: View {
let label: String
let color: Color
init(label: String, color: Color = .gray) {
self.label = label
self.color = color
}
var body: some View {
HStack {
line
Text(label)
.foregroundColor(color)
.fixedSize()
line
}
}
var line: some View {
VStack { Divider().background(color) }
}
}
@@ -0,0 +1,40 @@
//
// TextRoomTimelineItem.swift
// ElementX
//
// Created by Stefan Ceriu on 04.03.2022.
// Copyright © 2022 Element. All rights reserved.
//
import Foundation
import SwiftUI
enum RoomTimelineViewProvider: Identifiable, Equatable {
case text(TextRoomTimelineItem)
case separator(SeparatorRoomTimelineItem)
case image(ImageRoomTimelineItem)
var id: String {
switch self {
case .text(let item):
return item.id
case .separator(let item):
return item.id
case .image(let item):
return item.id
}
}
}
extension RoomTimelineViewProvider: View {
@ViewBuilder var body: some View {
switch self {
case .text(let item):
TextRoomTimelineView(timelineItem: item)
case .separator(let item):
SeparatorRoomTimelineView(timelineItem: item)
case .image(let item):
ImageRoomTimelineView(timelineItem: item)
}
}
}
@@ -0,0 +1,14 @@
//
// SectionSeparatorTimelineItem.swift
// ElementX
//
// Created by Stefan Ceriu on 11/03/2022.
// Copyright © 2022 Element. All rights reserved.
//
import Foundation
struct SeparatorRoomTimelineItem: Identifiable, Equatable {
let id: String
let text: String
}
@@ -0,0 +1,43 @@
//
// SeparatorRoomTimelineView.swift
// ElementX
//
// Created by Stefan Ceriu on 11/03/2022.
// Copyright © 2022 Element. All rights reserved.
//
import Foundation
import SwiftUI
struct SeparatorRoomTimelineView: View {
let timelineItem: SeparatorRoomTimelineItem
var body: some View {
LabelledDivider(label: timelineItem.text)
.id(timelineItem.id)
}
}
struct LabelledDivider: View {
let label: String
let color: Color
init(label: String, color: Color = .gray) {
self.label = label
self.color = color
}
var body: some View {
HStack {
line
Text(label)
.foregroundColor(color)
.fixedSize()
line
}
}
var line: some View {
VStack { Divider().background(color) }
}
}
@@ -0,0 +1,17 @@
//
// TextRoomTimelineItem.swift
// ElementX
//
// Created by Stefan Ceriu on 11/03/2022.
// Copyright © 2022 Element. All rights reserved.
//
import Foundation
struct TextRoomTimelineItem: Identifiable, Equatable {
let id: String
let senderDisplayName: String
let text: String
let timestamp: String
let shouldShowSenderDetails: Bool
}
@@ -0,0 +1,33 @@
//
// TextRoomTimelineView.swift
// ElementX
//
// Created by Stefan Ceriu on 11/03/2022.
// Copyright © 2022 Element. All rights reserved.
//
import Foundation
import SwiftUI
struct TextRoomTimelineView: View {
let timelineItem: TextRoomTimelineItem
var body: some View {
VStack(alignment: .leading) {
if timelineItem.shouldShowSenderDetails {
HStack {
Text(timelineItem.senderDisplayName)
.font(.footnote)
.bold()
Spacer()
Text(timelineItem.timestamp)
.font(.footnote)
}
Divider()
Spacer()
}
Text(timelineItem.text)
}
.id(timelineItem.id)
}
}