mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-03 16:10:20 +00:00
New timeline items (#424)
* Cleanup session verification state machine configuration * Add support for new timeline items: loading indicators, stickers and invalid/unsupported events * Add sticker accessibility label, fix session verification ones * Add support for the new TimelineStart timeline item and new pagination API. Remove identifiers from individual timeline items and only set them in the TimelineTableViewController * Add changelog
This commit is contained in:
committed by
Stefan Ceriu
parent
956e92a9ac
commit
d70a240869
@@ -21,6 +21,7 @@ typealias RoomScreenViewModelType = StateStoreViewModel<RoomScreenViewState, Roo
|
||||
|
||||
class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol {
|
||||
private enum Constants {
|
||||
static let backPaginationEventLimit: UInt = 20
|
||||
static let backPaginationPageSize: UInt = 50
|
||||
static let toastErrorID = "RoomScreenToastError"
|
||||
}
|
||||
@@ -122,7 +123,7 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol
|
||||
// MARK: - Private
|
||||
|
||||
private func paginateBackwards() async {
|
||||
switch await timelineController.paginateBackwards(Constants.backPaginationPageSize) {
|
||||
switch await timelineController.paginateBackwards(requestSize: Constants.backPaginationEventLimit, untilNumberOfItems: Constants.backPaginationPageSize) {
|
||||
case .failure:
|
||||
displayError(.toast(ElementL10n.roomTimelineBackpaginationFailure))
|
||||
default:
|
||||
|
||||
@@ -98,7 +98,7 @@ struct TimelineItemBubbledStylerView<Content: View>: View {
|
||||
|
||||
@ViewBuilder
|
||||
var styledContentOutgoing: some View {
|
||||
let topPadding: CGFloat? = timelineItem.inGroupState == .single || timelineItem.inGroupState == .beginning ? 8 : 0
|
||||
let topPadding: CGFloat? = timelineItem.groupState == .single || timelineItem.groupState == .beginning ? 8 : 0
|
||||
|
||||
if shouldAvoidBubbling {
|
||||
content()
|
||||
|
||||
+2
-2
@@ -16,7 +16,7 @@
|
||||
|
||||
import SwiftUI
|
||||
struct TimelineDeliveryStatusView: View {
|
||||
let deliveryStatus: MessageTimelineItemDeliveryStatus
|
||||
let deliveryStatus: TimelineItemDeliveryStatus
|
||||
|
||||
@State var showDeliveryStatus: Bool
|
||||
|
||||
@@ -29,7 +29,7 @@ struct TimelineDeliveryStatusView: View {
|
||||
}
|
||||
}
|
||||
|
||||
init(deliveryStatus: MessageTimelineItemDeliveryStatus) {
|
||||
init(deliveryStatus: TimelineItemDeliveryStatus) {
|
||||
self.deliveryStatus = deliveryStatus
|
||||
|
||||
switch deliveryStatus {
|
||||
|
||||
@@ -31,7 +31,6 @@ struct EmoteRoomTimelineView: View {
|
||||
}
|
||||
}
|
||||
}
|
||||
.id(timelineItem.id)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,7 +56,7 @@ struct EmoteRoomTimelineView_Previews: PreviewProvider {
|
||||
EmoteRoomTimelineItem(id: UUID().uuidString,
|
||||
text: text,
|
||||
timestamp: timestamp,
|
||||
inGroupState: .single,
|
||||
groupState: .single,
|
||||
isOutgoing: false,
|
||||
isEditable: false,
|
||||
senderId: senderId)
|
||||
|
||||
@@ -26,20 +26,19 @@ struct EncryptedRoomTimelineView: View {
|
||||
Button {
|
||||
showEncryptionInfo = !showEncryptionInfo
|
||||
} label: {
|
||||
HStack(alignment: .top) {
|
||||
Image(systemName: "lock.shield")
|
||||
.foregroundColor(.red)
|
||||
.padding(.top, 1.0)
|
||||
Label {
|
||||
if showEncryptionInfo {
|
||||
FormattedBodyText(text: encryptionDetails)
|
||||
} else {
|
||||
FormattedBodyText(text: timelineItem.text)
|
||||
}
|
||||
} icon: {
|
||||
Image(systemName: "lock.shield")
|
||||
.foregroundColor(.red)
|
||||
}
|
||||
.animation(nil, value: showEncryptionInfo)
|
||||
}
|
||||
}
|
||||
.id(timelineItem.id)
|
||||
}
|
||||
|
||||
private var encryptionDetails: String {
|
||||
@@ -79,7 +78,7 @@ struct EncryptedRoomTimelineView_Previews: PreviewProvider {
|
||||
text: text,
|
||||
encryptionType: .unknown,
|
||||
timestamp: timestamp,
|
||||
inGroupState: .single,
|
||||
groupState: .single,
|
||||
isOutgoing: isOutgoing,
|
||||
isEditable: false,
|
||||
senderId: senderId)
|
||||
|
||||
@@ -30,7 +30,6 @@ struct FileRoomTimelineView: View {
|
||||
.padding(.vertical, 12)
|
||||
.padding(.horizontal, 6)
|
||||
}
|
||||
.id(timelineItem.id)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,7 +44,7 @@ struct FileRoomTimelineView_Previews: PreviewProvider {
|
||||
FileRoomTimelineView(timelineItem: FileRoomTimelineItem(id: UUID().uuidString,
|
||||
text: "document.pdf",
|
||||
timestamp: "Now",
|
||||
inGroupState: .single,
|
||||
groupState: .single,
|
||||
isOutgoing: false,
|
||||
isEditable: false,
|
||||
senderId: "Bob",
|
||||
@@ -55,7 +54,7 @@ struct FileRoomTimelineView_Previews: PreviewProvider {
|
||||
FileRoomTimelineView(timelineItem: FileRoomTimelineItem(id: UUID().uuidString,
|
||||
text: "document.docx",
|
||||
timestamp: "Now",
|
||||
inGroupState: .single,
|
||||
groupState: .single,
|
||||
isOutgoing: false,
|
||||
isEditable: false,
|
||||
senderId: "Bob",
|
||||
@@ -65,7 +64,7 @@ struct FileRoomTimelineView_Previews: PreviewProvider {
|
||||
FileRoomTimelineView(timelineItem: FileRoomTimelineItem(id: UUID().uuidString,
|
||||
text: "document.txt",
|
||||
timestamp: "Now",
|
||||
inGroupState: .single,
|
||||
groupState: .single,
|
||||
isOutgoing: false,
|
||||
isEditable: false,
|
||||
senderId: "Bob",
|
||||
|
||||
@@ -44,7 +44,6 @@ struct ImageRoomTimelineView: View {
|
||||
.aspectRatio(timelineItem.aspectRatio, contentMode: .fit)
|
||||
}
|
||||
}
|
||||
.id(timelineItem.id)
|
||||
.animation(.elementDefault, value: timelineItem.image)
|
||||
}
|
||||
}
|
||||
@@ -60,7 +59,7 @@ struct ImageRoomTimelineView_Previews: PreviewProvider {
|
||||
ImageRoomTimelineView(timelineItem: ImageRoomTimelineItem(id: UUID().uuidString,
|
||||
text: "Some image",
|
||||
timestamp: "Now",
|
||||
inGroupState: .single,
|
||||
groupState: .single,
|
||||
isOutgoing: false,
|
||||
isEditable: false,
|
||||
senderId: "Bob",
|
||||
@@ -70,7 +69,7 @@ struct ImageRoomTimelineView_Previews: PreviewProvider {
|
||||
ImageRoomTimelineView(timelineItem: ImageRoomTimelineItem(id: UUID().uuidString,
|
||||
text: "Some other image",
|
||||
timestamp: "Now",
|
||||
inGroupState: .single,
|
||||
groupState: .single,
|
||||
isOutgoing: false,
|
||||
isEditable: false,
|
||||
senderId: "Bob",
|
||||
@@ -80,7 +79,7 @@ struct ImageRoomTimelineView_Previews: PreviewProvider {
|
||||
ImageRoomTimelineView(timelineItem: ImageRoomTimelineItem(id: UUID().uuidString,
|
||||
text: "Blurhashed image",
|
||||
timestamp: "Now",
|
||||
inGroupState: .single,
|
||||
groupState: .single,
|
||||
isOutgoing: false,
|
||||
isEditable: false,
|
||||
senderId: "Bob",
|
||||
|
||||
@@ -31,7 +31,6 @@ struct NoticeRoomTimelineView: View {
|
||||
}
|
||||
}
|
||||
}
|
||||
.id(timelineItem.id)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,7 +56,7 @@ struct NoticeRoomTimelineView_Previews: PreviewProvider {
|
||||
NoticeRoomTimelineItem(id: UUID().uuidString,
|
||||
text: text,
|
||||
timestamp: timestamp,
|
||||
inGroupState: .single,
|
||||
groupState: .single,
|
||||
isOutgoing: false,
|
||||
isEditable: false,
|
||||
senderId: senderId)
|
||||
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
//
|
||||
// Copyright 2022 New Vector Ltd
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct PaginationIndicatorRoomTimelineView: View {
|
||||
let timelineItem: PaginationIndicatorRoomTimelineItem
|
||||
|
||||
var body: some View {
|
||||
ProgressView()
|
||||
.frame(maxWidth: .infinity)
|
||||
}
|
||||
}
|
||||
|
||||
struct PaginationIndicatorRoomTimelineView_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
let item = PaginationIndicatorRoomTimelineItem()
|
||||
PaginationIndicatorRoomTimelineView(timelineItem: item)
|
||||
}
|
||||
}
|
||||
@@ -24,7 +24,6 @@ struct ReadMarkerRoomTimelineView: View {
|
||||
VStack {
|
||||
Spacer(minLength: 4.0)
|
||||
Divider()
|
||||
.id(timelineItem.id)
|
||||
.frame(maxWidth: .infinity)
|
||||
.overlay(Color.element.accent)
|
||||
}
|
||||
@@ -33,7 +32,7 @@ struct ReadMarkerRoomTimelineView: View {
|
||||
|
||||
struct ReadMarkerRoomTimelineView_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
let item = ReadMarkerRoomTimelineItem(id: UUID().uuidString)
|
||||
let item = ReadMarkerRoomTimelineItem()
|
||||
ReadMarkerRoomTimelineView(timelineItem: item)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,7 +27,6 @@ struct RedactedRoomTimelineView: View {
|
||||
FormattedBodyText(text: timelineItem.text)
|
||||
}
|
||||
}
|
||||
.id(timelineItem.id)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,7 +43,7 @@ struct RedactedRoomTimelineView_Previews: PreviewProvider {
|
||||
RedactedRoomTimelineItem(id: UUID().uuidString,
|
||||
text: text,
|
||||
timestamp: timestamp,
|
||||
inGroupState: .single,
|
||||
groupState: .single,
|
||||
isOutgoing: false,
|
||||
isEditable: false,
|
||||
senderId: senderId)
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import SwiftUI
|
||||
|
||||
struct SeparatorRoomTimelineView: View {
|
||||
@@ -24,7 +23,6 @@ struct SeparatorRoomTimelineView: View {
|
||||
Text(timelineItem.text)
|
||||
.font(.element.footnote)
|
||||
.foregroundColor(.element.secondaryContent)
|
||||
.id(timelineItem.id)
|
||||
.padding(.vertical, 24)
|
||||
.frame(maxWidth: .infinity)
|
||||
}
|
||||
@@ -32,7 +30,7 @@ struct SeparatorRoomTimelineView: View {
|
||||
|
||||
struct SeparatorRoomTimelineView_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
let item = SeparatorRoomTimelineItem(id: UUID().uuidString, text: "This is a separator")
|
||||
let item = SeparatorRoomTimelineItem(text: "This is a separator")
|
||||
SeparatorRoomTimelineView(timelineItem: item)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
//
|
||||
// Copyright 2023 New Vector Ltd
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import SwiftUI
|
||||
|
||||
struct StickerRoomTimelineView: View {
|
||||
let timelineItem: StickerRoomTimelineItem
|
||||
|
||||
var body: some View {
|
||||
TimelineStyler(timelineItem: timelineItem) {
|
||||
if let image = timelineItem.image {
|
||||
Image(uiImage: image)
|
||||
.resizable()
|
||||
.aspectRatio(timelineItem.aspectRatio, contentMode: .fit)
|
||||
} else if let blurhash = timelineItem.blurhash,
|
||||
// Build a small blurhash image so that it's fast
|
||||
let image = UIImage(blurHash: blurhash, size: .init(width: 10.0, height: 10.0)) {
|
||||
Image(uiImage: image)
|
||||
.resizable()
|
||||
.aspectRatio(timelineItem.aspectRatio, contentMode: .fit)
|
||||
} else {
|
||||
ZStack {
|
||||
Rectangle()
|
||||
.foregroundColor(.element.systemGray6)
|
||||
.opacity(0.3)
|
||||
|
||||
ProgressView(ElementL10n.loading)
|
||||
.frame(maxWidth: .infinity)
|
||||
}
|
||||
.aspectRatio(timelineItem.aspectRatio, contentMode: .fit)
|
||||
}
|
||||
}
|
||||
.animation(.elementDefault, value: timelineItem.image)
|
||||
.accessibilityLabel(timelineItem.text)
|
||||
}
|
||||
}
|
||||
|
||||
struct StickerRoomTimelineView_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
body
|
||||
body.timelineStyle(.plain)
|
||||
}
|
||||
|
||||
static var body: some View {
|
||||
VStack(spacing: 20.0) {
|
||||
StickerRoomTimelineView(timelineItem: StickerRoomTimelineItem(id: UUID().uuidString,
|
||||
text: "Some image",
|
||||
timestamp: "Now",
|
||||
groupState: .single,
|
||||
isOutgoing: false,
|
||||
isEditable: false,
|
||||
senderId: "Bob",
|
||||
urlString: nil,
|
||||
image: UIImage(systemName: "photo")))
|
||||
|
||||
StickerRoomTimelineView(timelineItem: StickerRoomTimelineItem(id: UUID().uuidString,
|
||||
text: "Some other image",
|
||||
timestamp: "Now",
|
||||
groupState: .single,
|
||||
isOutgoing: false,
|
||||
isEditable: false,
|
||||
senderId: "Bob",
|
||||
urlString: nil,
|
||||
image: nil))
|
||||
|
||||
StickerRoomTimelineView(timelineItem: StickerRoomTimelineItem(id: UUID().uuidString,
|
||||
text: "Blurhashed image",
|
||||
timestamp: "Now",
|
||||
groupState: .single,
|
||||
isOutgoing: false,
|
||||
isEditable: false,
|
||||
senderId: "Bob",
|
||||
urlString: nil,
|
||||
image: nil,
|
||||
aspectRatio: 0.7,
|
||||
blurhash: "L%KUc%kqS$RP?Ks,WEf8OlrqaekW"))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -28,7 +28,6 @@ struct TextRoomTimelineView: View {
|
||||
FormattedBodyText(text: timelineItem.text)
|
||||
}
|
||||
}
|
||||
.id(timelineItem.id)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,7 +65,7 @@ struct TextRoomTimelineView_Previews: PreviewProvider {
|
||||
TextRoomTimelineItem(id: UUID().uuidString,
|
||||
text: text,
|
||||
timestamp: timestamp,
|
||||
inGroupState: .single,
|
||||
groupState: .single,
|
||||
isOutgoing: isOutgoing,
|
||||
isEditable: isOutgoing,
|
||||
senderId: senderId)
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
//
|
||||
// Copyright 2023 New Vector Ltd
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct TimelineStartRoomTimelineView: View {
|
||||
let timelineItem: TimelineStartRoomTimelineItem
|
||||
|
||||
var body: some View {
|
||||
Text(title)
|
||||
.font(.element.footnote)
|
||||
.foregroundColor(.element.secondaryContent)
|
||||
.padding(.vertical, 24)
|
||||
.frame(maxWidth: .infinity)
|
||||
}
|
||||
|
||||
var title: String {
|
||||
var text = ElementL10n.thisIsTheBeginningOfRoomNoName
|
||||
if let name = timelineItem.name {
|
||||
text = ElementL10n.thisIsTheBeginningOfRoom(name)
|
||||
}
|
||||
return text
|
||||
}
|
||||
}
|
||||
|
||||
struct TimelineStartRoomTimelineView_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
let item = TimelineStartRoomTimelineItem(name: "Alice and Bob")
|
||||
TimelineStartRoomTimelineView(timelineItem: item)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
//
|
||||
// Copyright 2023 New Vector Ltd
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct UnsupportedRoomTimelineView: View {
|
||||
let timelineItem: UnsupportedRoomTimelineItem
|
||||
|
||||
var body: some View {
|
||||
TimelineStyler(timelineItem: timelineItem) {
|
||||
Label {
|
||||
VStack(alignment: .leading) {
|
||||
Text("\(timelineItem.text): \(timelineItem.eventType)")
|
||||
.fixedSize(horizontal: false, vertical: true)
|
||||
.foregroundColor(.element.primaryContent)
|
||||
|
||||
Text(timelineItem.error)
|
||||
.fixedSize(horizontal: false, vertical: true)
|
||||
.font(.element.footnote)
|
||||
.foregroundColor(.element.primaryContent)
|
||||
}
|
||||
} icon: {
|
||||
Image(systemName: "exclamationmark.bubble")
|
||||
.foregroundColor(.red)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct UnsupportedRoomTimelineView_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
body
|
||||
body.timelineStyle(.plain)
|
||||
}
|
||||
|
||||
static var body: some View {
|
||||
VStack(alignment: .leading, spacing: 20.0) {
|
||||
UnsupportedRoomTimelineView(timelineItem: itemWith(text: "Text",
|
||||
timestamp: "Now",
|
||||
isOutgoing: false,
|
||||
senderId: "Bob"))
|
||||
|
||||
UnsupportedRoomTimelineView(timelineItem: itemWith(text: "Some other text",
|
||||
timestamp: "Later",
|
||||
isOutgoing: true,
|
||||
senderId: "Anne"))
|
||||
}
|
||||
}
|
||||
|
||||
private static func itemWith(text: String, timestamp: String, isOutgoing: Bool, senderId: String) -> UnsupportedRoomTimelineItem {
|
||||
UnsupportedRoomTimelineItem(id: UUID().uuidString,
|
||||
text: text,
|
||||
eventType: "Some Event Type",
|
||||
error: "Something went wrong",
|
||||
timestamp: timestamp,
|
||||
groupState: .single,
|
||||
isOutgoing: isOutgoing,
|
||||
isEditable: false,
|
||||
senderId: senderId)
|
||||
}
|
||||
}
|
||||
@@ -40,7 +40,6 @@ struct VideoRoomTimelineView: View {
|
||||
.aspectRatio(timelineItem.aspectRatio, contentMode: .fit)
|
||||
}
|
||||
}
|
||||
.id(timelineItem.id)
|
||||
.animation(.elementDefault, value: timelineItem.image)
|
||||
}
|
||||
|
||||
@@ -70,7 +69,7 @@ struct VideoRoomTimelineView_Previews: PreviewProvider {
|
||||
VideoRoomTimelineView(timelineItem: VideoRoomTimelineItem(id: UUID().uuidString,
|
||||
text: "Some video",
|
||||
timestamp: "Now",
|
||||
inGroupState: .single,
|
||||
groupState: .single,
|
||||
isOutgoing: false,
|
||||
isEditable: false,
|
||||
senderId: "Bob",
|
||||
@@ -82,7 +81,7 @@ struct VideoRoomTimelineView_Previews: PreviewProvider {
|
||||
VideoRoomTimelineView(timelineItem: VideoRoomTimelineItem(id: UUID().uuidString,
|
||||
text: "Some other video",
|
||||
timestamp: "Now",
|
||||
inGroupState: .single,
|
||||
groupState: .single,
|
||||
isOutgoing: false,
|
||||
isEditable: false,
|
||||
senderId: "Bob",
|
||||
@@ -94,7 +93,7 @@ struct VideoRoomTimelineView_Previews: PreviewProvider {
|
||||
VideoRoomTimelineView(timelineItem: VideoRoomTimelineItem(id: UUID().uuidString,
|
||||
text: "Blurhashed video",
|
||||
timestamp: "Now",
|
||||
inGroupState: .single,
|
||||
groupState: .single,
|
||||
isOutgoing: false,
|
||||
isEditable: false,
|
||||
senderId: "Bob",
|
||||
|
||||
@@ -191,32 +191,29 @@ class TimelineTableViewController: UIViewController {
|
||||
|
||||
cell.item = timelineItem
|
||||
cell.contentConfiguration = UIHostingConfiguration {
|
||||
if case .backPaginationIndicator = timelineItem {
|
||||
timelineItem
|
||||
} else {
|
||||
timelineItem
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
.opacity(opacity)
|
||||
.contextMenu {
|
||||
contextMenuBuilder?(timelineItem.id)
|
||||
}
|
||||
.onAppear {
|
||||
coordinator.send(viewAction: .itemAppeared(id: timelineItem.id))
|
||||
}
|
||||
.onDisappear {
|
||||
coordinator.send(viewAction: .itemDisappeared(id: timelineItem.id))
|
||||
}
|
||||
.environment(\.openURL, OpenURLAction { url in
|
||||
coordinator.send(viewAction: .linkClicked(url: url))
|
||||
return .systemAction
|
||||
})
|
||||
.onTapGesture(count: 2) {
|
||||
coordinator.send(viewAction: .displayEmojiPicker(itemId: timelineItem.id))
|
||||
}
|
||||
.onTapGesture {
|
||||
coordinator.send(viewAction: .itemTapped(id: timelineItem.id))
|
||||
}
|
||||
}
|
||||
timelineItem
|
||||
.id(timelineItem.id)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
.opacity(opacity)
|
||||
.contextMenu {
|
||||
contextMenuBuilder?(timelineItem.id)
|
||||
}
|
||||
.onAppear {
|
||||
coordinator.send(viewAction: .itemAppeared(id: timelineItem.id))
|
||||
}
|
||||
.onDisappear {
|
||||
coordinator.send(viewAction: .itemDisappeared(id: timelineItem.id))
|
||||
}
|
||||
.environment(\.openURL, OpenURLAction { url in
|
||||
coordinator.send(viewAction: .linkClicked(url: url))
|
||||
return .systemAction
|
||||
})
|
||||
.onTapGesture(count: 2) {
|
||||
coordinator.send(viewAction: .displayEmojiPicker(itemId: timelineItem.id))
|
||||
}
|
||||
.onTapGesture {
|
||||
coordinator.send(viewAction: .itemTapped(id: timelineItem.id))
|
||||
}
|
||||
}
|
||||
.margins(.all, self.timelineStyle.rowInsets)
|
||||
.minSize(height: 1)
|
||||
@@ -236,8 +233,6 @@ class TimelineTableViewController: UIViewController {
|
||||
let previousLayout = layout()
|
||||
|
||||
var snapshot = NSDiffableDataSourceSnapshot<TimelineSection, RoomTimelineViewProvider>()
|
||||
snapshot.appendSections([.loadingIndicator])
|
||||
snapshot.appendItems([.backPaginationIndicator(isBackPaginating)])
|
||||
snapshot.appendSections([.main])
|
||||
snapshot.appendItems(timelineItems)
|
||||
dataSource.apply(snapshot, animatingDifferences: false)
|
||||
@@ -399,7 +394,6 @@ extension TimelineTableViewController: UITableViewDelegate {
|
||||
extension TimelineTableViewController {
|
||||
/// The sections of the table view used in the diffable data source.
|
||||
enum TimelineSection {
|
||||
case loadingIndicator
|
||||
case main
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user