mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-04 01:20:12 +00:00
Bump the RustSDK to v1.0.53: adopt latest record based timeline item APIs (#3356)
This commit is contained in:
@@ -10,9 +10,9 @@ import Foundation
|
||||
enum RoomTimelineItemFixtures {
|
||||
/// The default timeline items used in Xcode previews etc.
|
||||
static var `default`: [RoomTimelineItemProtocol] = [
|
||||
SeparatorRoomTimelineItem(id: .init(timelineID: "Yesterday"), text: "Yesterday"),
|
||||
TextRoomTimelineItem(id: .init(timelineID: ".RoomTimelineItemFixtures.default.0",
|
||||
eventID: "RoomTimelineItemFixtures.default.0"),
|
||||
SeparatorRoomTimelineItem(id: .init(uniqueID: "Yesterday"), text: "Yesterday"),
|
||||
TextRoomTimelineItem(id: .init(uniqueID: ".RoomTimelineItemFixtures.default.0",
|
||||
eventOrTransactionID: .eventId(eventId: "RoomTimelineItemFixtures.default.0")),
|
||||
timestamp: "10:10 AM",
|
||||
isOutgoing: false,
|
||||
isEditable: false,
|
||||
@@ -21,8 +21,8 @@ enum RoomTimelineItemFixtures {
|
||||
sender: .init(id: "", displayName: "Jacob"),
|
||||
content: .init(body: "That looks so good!"),
|
||||
properties: RoomTimelineItemProperties(isEdited: true)),
|
||||
TextRoomTimelineItem(id: .init(timelineID: "RoomTimelineItemFixtures.default.1",
|
||||
eventID: "RoomTimelineItemFixtures.default.1"),
|
||||
TextRoomTimelineItem(id: .init(uniqueID: "RoomTimelineItemFixtures.default.1",
|
||||
eventOrTransactionID: .eventId(eventId: "RoomTimelineItemFixtures.default.1")),
|
||||
timestamp: "10:11 AM",
|
||||
isOutgoing: false,
|
||||
isEditable: false,
|
||||
@@ -33,8 +33,8 @@ enum RoomTimelineItemFixtures {
|
||||
properties: RoomTimelineItemProperties(reactions: [
|
||||
AggregatedReaction(accountOwnerID: "me", key: "🙌", senders: [ReactionSender(id: "me", timestamp: Date())])
|
||||
])),
|
||||
TextRoomTimelineItem(id: .init(timelineID: "RoomTimelineItemFixtures.default.2",
|
||||
eventID: "RoomTimelineItemFixtures.default.2"),
|
||||
TextRoomTimelineItem(id: .init(uniqueID: "RoomTimelineItemFixtures.default.2",
|
||||
eventOrTransactionID: .eventId(eventId: "RoomTimelineItemFixtures.default.2")),
|
||||
timestamp: "10:11 AM",
|
||||
isOutgoing: false,
|
||||
isEditable: false,
|
||||
@@ -52,9 +52,9 @@ enum RoomTimelineItemFixtures {
|
||||
ReactionSender(id: "jacob", timestamp: Date())
|
||||
])
|
||||
])),
|
||||
SeparatorRoomTimelineItem(id: .init(timelineID: "Today"), text: "Today"),
|
||||
TextRoomTimelineItem(id: .init(timelineID: "RoomTimelineItemFixtures.default.3",
|
||||
eventID: "RoomTimelineItemFixtures.default.3"),
|
||||
SeparatorRoomTimelineItem(id: .init(uniqueID: "Today"), text: "Today"),
|
||||
TextRoomTimelineItem(id: .init(uniqueID: "RoomTimelineItemFixtures.default.3",
|
||||
eventOrTransactionID: .eventId(eventId: "RoomTimelineItemFixtures.default.3")),
|
||||
timestamp: "5 PM",
|
||||
isOutgoing: false,
|
||||
isEditable: false,
|
||||
@@ -63,8 +63,8 @@ enum RoomTimelineItemFixtures {
|
||||
sender: .init(id: "", displayName: "Helena"),
|
||||
content: .init(body: "Wow, cool. Ok, lets go the usual place tomorrow?! Is that too soon? Here’s the menu, let me know what you want it’s on me!"),
|
||||
properties: RoomTimelineItemProperties(orderedReadReceipts: [ReadReceipt(userID: "alice", formattedTimestamp: nil)])),
|
||||
TextRoomTimelineItem(id: .init(timelineID: "RoomTimelineItemFixtures.default.4",
|
||||
eventID: "RoomTimelineItemFixtures.default.4"),
|
||||
TextRoomTimelineItem(id: .init(uniqueID: "RoomTimelineItemFixtures.default.4",
|
||||
eventOrTransactionID: .eventId(eventId: "RoomTimelineItemFixtures.default.4")),
|
||||
timestamp: "5 PM",
|
||||
isOutgoing: true,
|
||||
isEditable: true,
|
||||
@@ -72,8 +72,8 @@ enum RoomTimelineItemFixtures {
|
||||
isThreaded: false,
|
||||
sender: .init(id: "", displayName: "Bob"),
|
||||
content: .init(body: "And John's speech was amazing!")),
|
||||
TextRoomTimelineItem(id: .init(timelineID: "RoomTimelineItemFixtures.default.5",
|
||||
eventID: "RoomTimelineItemFixtures.default.5"),
|
||||
TextRoomTimelineItem(id: .init(uniqueID: "RoomTimelineItemFixtures.default.5",
|
||||
eventOrTransactionID: .eventId(eventId: "RoomTimelineItemFixtures.default.5")),
|
||||
timestamp: "5 PM",
|
||||
isOutgoing: true,
|
||||
isEditable: true,
|
||||
@@ -86,8 +86,8 @@ enum RoomTimelineItemFixtures {
|
||||
ReadReceipt(userID: "bob", formattedTimestamp: nil),
|
||||
ReadReceipt(userID: "charlie", formattedTimestamp: nil),
|
||||
ReadReceipt(userID: "dan", formattedTimestamp: nil)])),
|
||||
TextRoomTimelineItem(id: .init(timelineID: "RoomTimelineItemFixtures.default.6",
|
||||
eventID: "RoomTimelineItemFixtures.default.6"),
|
||||
TextRoomTimelineItem(id: .init(uniqueID: "RoomTimelineItemFixtures.default.6",
|
||||
eventOrTransactionID: .eventId(eventId: "RoomTimelineItemFixtures.default.6")),
|
||||
timestamp: "5 PM",
|
||||
isOutgoing: false,
|
||||
isEditable: false,
|
||||
@@ -242,7 +242,7 @@ enum RoomTimelineItemFixtures {
|
||||
|
||||
static var permalinkChunk: [RoomTimelineItemProtocol] {
|
||||
(1...20).map { index in
|
||||
TextRoomTimelineItem(id: .init(timelineID: "\(index)", eventID: "$\(index)"),
|
||||
TextRoomTimelineItem(id: .init(uniqueID: "\(index)", eventOrTransactionID: .eventId(eventId: "$\(index)")),
|
||||
text: "Message ID \(index)",
|
||||
senderDisplayName: index > 10 ? "Alice" : "Bob")
|
||||
}
|
||||
|
||||
@@ -184,38 +184,11 @@ class RoomTimelineProvider: RoomTimelineProviderProtocol {
|
||||
}
|
||||
}
|
||||
|
||||
private extension TimelineItem {
|
||||
var debugIdentifier: DebugIdentifier {
|
||||
if let virtualTimelineItem = asVirtual() {
|
||||
return .virtual(timelineID: String(uniqueId()), dscription: virtualTimelineItem.description)
|
||||
} else if let eventTimelineItem = asEvent() {
|
||||
return .event(timelineID: String(uniqueId()),
|
||||
eventID: eventTimelineItem.eventId(),
|
||||
transactionID: eventTimelineItem.transactionId())
|
||||
}
|
||||
|
||||
return .unknown(timelineID: String(uniqueId()))
|
||||
}
|
||||
}
|
||||
|
||||
private extension TimelineItemProxy {
|
||||
var debugIdentifier: DebugIdentifier {
|
||||
switch self {
|
||||
case .event(let eventTimelineItem):
|
||||
return .event(timelineID: eventTimelineItem.id.timelineID,
|
||||
eventID: eventTimelineItem.id.eventID,
|
||||
transactionID: eventTimelineItem.id.transactionID)
|
||||
case .virtual(let virtualTimelineItem, let timelineID):
|
||||
return .virtual(timelineID: timelineID, dscription: virtualTimelineItem.description)
|
||||
case .unknown(let item):
|
||||
return .unknown(timelineID: String(item.uniqueId()))
|
||||
}
|
||||
}
|
||||
|
||||
var isMembershipChange: Bool {
|
||||
switch self {
|
||||
case .event(let eventTimelineItemProxy):
|
||||
switch eventTimelineItemProxy.content.kind() {
|
||||
switch eventTimelineItemProxy.content {
|
||||
case .roomMembership:
|
||||
true
|
||||
default:
|
||||
@@ -238,12 +211,6 @@ private extension VirtualTimelineItem {
|
||||
}
|
||||
}
|
||||
|
||||
enum DebugIdentifier {
|
||||
case event(timelineID: String, eventID: String?, transactionID: String?)
|
||||
case virtual(timelineID: String, dscription: String)
|
||||
case unknown(timelineID: String)
|
||||
}
|
||||
|
||||
private final class RoomTimelineListener: TimelineListener {
|
||||
private let onUpdateClosure: ([TimelineDiff]) -> Void
|
||||
|
||||
|
||||
@@ -186,7 +186,7 @@ class RoomTimelineController: RoomTimelineControllerProtocol {
|
||||
MXLog.info("Editing timeline item: \(timelineItemID)")
|
||||
|
||||
let editMode: EditMode
|
||||
if !timelineItemID.timelineID.isEmpty,
|
||||
if !timelineItemID.uniqueID.isEmpty,
|
||||
let timelineItem = liveTimelineProvider.itemProxies.firstEventTimelineItemUsingStableID(timelineItemID) {
|
||||
editMode = .byEvent(timelineItem)
|
||||
} else if let eventID = timelineItemID.eventID {
|
||||
@@ -392,15 +392,15 @@ class RoomTimelineController: RoomTimelineControllerProtocol {
|
||||
}
|
||||
|
||||
return timelineItem
|
||||
case .virtual(let virtualItem, let timelineID):
|
||||
case .virtual(let virtualItem, let uniqueID):
|
||||
switch virtualItem {
|
||||
case .dayDivider(let timestamp):
|
||||
let date = Date(timeIntervalSince1970: TimeInterval(timestamp / 1000))
|
||||
let dateString = date.formatted(date: .complete, time: .omitted)
|
||||
|
||||
return SeparatorRoomTimelineItem(id: .init(timelineID: dateString), text: dateString)
|
||||
return SeparatorRoomTimelineItem(id: .init(uniqueID: dateString), text: dateString)
|
||||
case .readMarker:
|
||||
return ReadMarkerRoomTimelineItem(id: .init(timelineID: timelineID))
|
||||
return ReadMarkerRoomTimelineItem(id: .init(uniqueID: uniqueID))
|
||||
}
|
||||
case .unknown:
|
||||
return nil
|
||||
@@ -409,7 +409,7 @@ class RoomTimelineController: RoomTimelineControllerProtocol {
|
||||
|
||||
private func isItemCollapsible(_ item: TimelineItemProxy) -> Bool {
|
||||
if case let .event(eventItem) = item {
|
||||
switch eventItem.content.kind() {
|
||||
switch eventItem.content {
|
||||
case .profileChange, .roomMembership, .state:
|
||||
return true
|
||||
default:
|
||||
|
||||
+7
-7
@@ -9,43 +9,43 @@ import MatrixRustSDK
|
||||
|
||||
// MARK: Redact message content from logs
|
||||
|
||||
extension EmoteMessageContent: CustomStringConvertible {
|
||||
extension EmoteMessageContent: @retroactive CustomStringConvertible {
|
||||
public var description: String {
|
||||
String(describing: Self.self)
|
||||
}
|
||||
}
|
||||
|
||||
extension FileMessageContent: CustomStringConvertible {
|
||||
extension FileMessageContent: @retroactive CustomStringConvertible {
|
||||
public var description: String {
|
||||
String(describing: Self.self)
|
||||
}
|
||||
}
|
||||
|
||||
extension ImageMessageContent: CustomStringConvertible {
|
||||
extension ImageMessageContent: @retroactive CustomStringConvertible {
|
||||
public var description: String {
|
||||
String(describing: Self.self)
|
||||
}
|
||||
}
|
||||
|
||||
extension NoticeMessageContent: CustomStringConvertible {
|
||||
extension NoticeMessageContent: @retroactive CustomStringConvertible {
|
||||
public var description: String {
|
||||
String(describing: Self.self)
|
||||
}
|
||||
}
|
||||
|
||||
extension TextMessageContent: CustomStringConvertible {
|
||||
extension TextMessageContent: @retroactive CustomStringConvertible {
|
||||
public var description: String {
|
||||
String(describing: Self.self)
|
||||
}
|
||||
}
|
||||
|
||||
extension VideoMessageContent: CustomStringConvertible {
|
||||
extension VideoMessageContent: @retroactive CustomStringConvertible {
|
||||
public var description: String {
|
||||
String(describing: Self.self)
|
||||
}
|
||||
}
|
||||
|
||||
extension AudioMessageContent: CustomStringConvertible {
|
||||
extension AudioMessageContent: @retroactive CustomStringConvertible {
|
||||
public var description: String {
|
||||
String(describing: Self.self)
|
||||
}
|
||||
|
||||
@@ -11,35 +11,48 @@ import MatrixRustSDK
|
||||
struct TimelineItemIdentifier: Hashable {
|
||||
/// Stable id across state changes of the timeline item, it uniquely identifies an item in a timeline.
|
||||
/// It's value is consistent only per timeline instance, it should **not** be used to identify an item across timeline instances.
|
||||
let timelineID: String
|
||||
|
||||
/// Uniquely identifies the timeline item from the server side.
|
||||
/// Only available for EventTimelineItem and only when the item is returned by the server.
|
||||
var eventID: String?
|
||||
|
||||
/// Uniquely identifies the local echo of the timeline item.
|
||||
/// Only available for sent EventTimelineItem that have not been returned by the server yet.
|
||||
var transactionID: String?
|
||||
let uniqueID: String
|
||||
|
||||
/// Contains the 2 possible identifiers of an event, either it has a remote event id or a local transaction id, never both or none.
|
||||
var eventOrTransactionID: EventOrTransactionId?
|
||||
|
||||
var eventID: String? {
|
||||
switch eventOrTransactionID {
|
||||
case .eventId(let eventId):
|
||||
return eventId
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
var transactionID: String? {
|
||||
switch eventOrTransactionID {
|
||||
case .transactionId(let transactionId):
|
||||
return transactionId
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension TimelineItemIdentifier {
|
||||
/// Use only for mocks/tests
|
||||
static var random: Self {
|
||||
.init(timelineID: UUID().uuidString, eventID: UUID().uuidString)
|
||||
.init(uniqueID: UUID().uuidString, eventOrTransactionID: .eventId(eventId: UUID().uuidString))
|
||||
}
|
||||
}
|
||||
|
||||
/// A light wrapper around timeline items returned from Rust.
|
||||
enum TimelineItemProxy {
|
||||
case event(EventTimelineItemProxy)
|
||||
case virtual(MatrixRustSDK.VirtualTimelineItem, timelineID: String)
|
||||
case virtual(MatrixRustSDK.VirtualTimelineItem, uniqueID: String)
|
||||
case unknown(MatrixRustSDK.TimelineItem)
|
||||
|
||||
init(item: MatrixRustSDK.TimelineItem) {
|
||||
if let eventItem = item.asEvent() {
|
||||
self = .event(EventTimelineItemProxy(item: eventItem, id: String(item.uniqueId())))
|
||||
self = .event(EventTimelineItemProxy(item: eventItem, uniqueID: String(item.uniqueId())))
|
||||
} else if let virtualItem = item.asVirtual() {
|
||||
self = .virtual(virtualItem, timelineID: String(item.uniqueId()))
|
||||
self = .virtual(virtualItem, uniqueID: String(item.uniqueId()))
|
||||
} else {
|
||||
self = .unknown(item)
|
||||
}
|
||||
@@ -92,13 +105,14 @@ class EventTimelineItemProxy {
|
||||
let item: MatrixRustSDK.EventTimelineItem
|
||||
let id: TimelineItemIdentifier
|
||||
|
||||
init(item: MatrixRustSDK.EventTimelineItem, id: String) {
|
||||
init(item: MatrixRustSDK.EventTimelineItem, uniqueID: String) {
|
||||
self.item = item
|
||||
self.id = TimelineItemIdentifier(timelineID: id, eventID: item.eventId(), transactionID: item.transactionId())
|
||||
|
||||
id = TimelineItemIdentifier(uniqueID: uniqueID, eventOrTransactionID: item.eventOrTransactionId)
|
||||
}
|
||||
|
||||
lazy var deliveryStatus: TimelineItemDeliveryStatus? = {
|
||||
guard let localSendState = item.localSendState() else {
|
||||
guard let localSendState = item.localSendState else {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -118,43 +132,43 @@ class EventTimelineItemProxy {
|
||||
}
|
||||
}()
|
||||
|
||||
lazy var canBeRepliedTo = item.canBeRepliedTo()
|
||||
lazy var canBeRepliedTo = item.canBeRepliedTo
|
||||
|
||||
lazy var content = item.content()
|
||||
lazy var content = item.content
|
||||
|
||||
lazy var isOwn = item.isOwn()
|
||||
lazy var isOwn = item.isOwn
|
||||
|
||||
lazy var isEditable = item.isEditable()
|
||||
lazy var isEditable = item.isEditable
|
||||
|
||||
lazy var sender: TimelineItemSender = {
|
||||
let profile = item.senderProfile()
|
||||
let profile = item.senderProfile
|
||||
|
||||
switch profile {
|
||||
case let .ready(displayName, isDisplayNameAmbiguous, avatarUrl):
|
||||
return .init(id: item.sender(),
|
||||
return .init(id: item.sender,
|
||||
displayName: displayName,
|
||||
isDisplayNameAmbiguous: isDisplayNameAmbiguous,
|
||||
avatarURL: avatarUrl.flatMap(URL.init(string:)))
|
||||
default:
|
||||
return .init(id: item.sender(),
|
||||
return .init(id: item.sender,
|
||||
displayName: nil,
|
||||
isDisplayNameAmbiguous: false,
|
||||
avatarURL: nil)
|
||||
}
|
||||
}()
|
||||
|
||||
lazy var reactions = item.reactions()
|
||||
lazy var reactions = item.reactions
|
||||
|
||||
lazy var timestamp = Date(timeIntervalSince1970: TimeInterval(item.timestamp() / 1000))
|
||||
lazy var timestamp = Date(timeIntervalSince1970: TimeInterval(item.timestamp / 1000))
|
||||
|
||||
lazy var debugInfo: TimelineItemDebugInfo = {
|
||||
let debugInfo = item.debugInfo()
|
||||
let debugInfo = item.debugInfoProvider.get()
|
||||
return TimelineItemDebugInfo(model: debugInfo.model, originalJSON: debugInfo.originalJson, latestEditJSON: debugInfo.latestEditJson)
|
||||
}()
|
||||
|
||||
lazy var shieldState = item.getShield(strict: false)
|
||||
lazy var shieldState = item.shieldsProvider.getShields(strict: false)
|
||||
|
||||
lazy var readReceipts = item.readReceipts()
|
||||
lazy var readReceipts = item.readReceipts
|
||||
}
|
||||
|
||||
struct TimelineItemDebugInfo: Identifiable, CustomStringConvertible {
|
||||
|
||||
+1
-1
@@ -22,6 +22,6 @@ struct PaginationIndicatorRoomTimelineItem: DecorationTimelineItemProtocol, Equa
|
||||
}
|
||||
|
||||
init(position: Position) {
|
||||
id = TimelineItemIdentifier(timelineID: position.id)
|
||||
id = TimelineItemIdentifier(uniqueID: position.id)
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -8,6 +8,6 @@
|
||||
import Foundation
|
||||
|
||||
struct TimelineStartRoomTimelineItem: DecorationTimelineItemProtocol, Equatable {
|
||||
let id = TimelineItemIdentifier(timelineID: UUID().uuidString)
|
||||
let id = TimelineItemIdentifier(uniqueID: UUID().uuidString)
|
||||
let name: String?
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol {
|
||||
func buildTimelineItem(for eventItemProxy: EventTimelineItemProxy, isDM: Bool) -> RoomTimelineItemProtocol? {
|
||||
let isOutgoing = eventItemProxy.isOwn
|
||||
|
||||
switch eventItemProxy.content.kind() {
|
||||
switch eventItemProxy.content {
|
||||
case .unableToDecrypt(let encryptedMessage):
|
||||
return buildEncryptedTimelineItem(eventItemProxy, encryptedMessage, isOutgoing)
|
||||
case .redactedMessage:
|
||||
@@ -43,8 +43,8 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol {
|
||||
return buildUnsupportedTimelineItem(eventItemProxy, eventType, error, isOutgoing)
|
||||
case .failedToParseState(let eventType, _, let error):
|
||||
return buildUnsupportedTimelineItem(eventItemProxy, eventType, error, isOutgoing)
|
||||
case .message:
|
||||
return buildMessageTimelineItem(eventItemProxy, isOutgoing)
|
||||
case .message(let messageContent):
|
||||
return buildMessageTimelineItem(eventItemProxy, messageContent, isOutgoing)
|
||||
case .state(_, let content):
|
||||
if isDM, content == .roomCreate {
|
||||
return nil
|
||||
@@ -72,34 +72,29 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol {
|
||||
}
|
||||
|
||||
// MARK: - Message Events
|
||||
|
||||
private func buildMessageTimelineItem(_ eventItemProxy: EventTimelineItemProxy, _ isOutgoing: Bool) -> RoomTimelineItemProtocol? {
|
||||
guard let messageTimelineItem = eventItemProxy.content.asMessage() else {
|
||||
fatalError("Invalid message timeline item: \(eventItemProxy)")
|
||||
}
|
||||
|
||||
let isThreaded = messageTimelineItem.isThreaded()
|
||||
switch messageTimelineItem.msgtype() {
|
||||
case .text(content: let content):
|
||||
return buildTextTimelineItem(for: eventItemProxy, messageTimelineItem, content, isOutgoing, isThreaded)
|
||||
case .image(content: let content):
|
||||
return buildImageTimelineItem(for: eventItemProxy, messageTimelineItem, content, isOutgoing, isThreaded)
|
||||
case .video(let content):
|
||||
return buildVideoTimelineItem(for: eventItemProxy, messageTimelineItem, content, isOutgoing, isThreaded)
|
||||
case .file(let content):
|
||||
return buildFileTimelineItem(for: eventItemProxy, messageTimelineItem, content, isOutgoing, isThreaded)
|
||||
case .notice(content: let content):
|
||||
return buildNoticeTimelineItem(for: eventItemProxy, messageTimelineItem, content, isOutgoing, isThreaded)
|
||||
case .emote(content: let content):
|
||||
return buildEmoteTimelineItem(for: eventItemProxy, messageTimelineItem, content, isOutgoing, isThreaded)
|
||||
case .audio(let content):
|
||||
if content.voice != nil {
|
||||
return buildVoiceTimelineItem(for: eventItemProxy, messageTimelineItem, content, isOutgoing, isThreaded)
|
||||
|
||||
private func buildMessageTimelineItem(_ eventItemProxy: EventTimelineItemProxy, _ messageContent: MessageContent, _ isOutgoing: Bool) -> RoomTimelineItemProtocol? {
|
||||
switch messageContent.msgType {
|
||||
case .text(content: let textMessageContent):
|
||||
return buildTextTimelineItem(for: eventItemProxy, messageContent, textMessageContent, isOutgoing)
|
||||
case .image(content: let imageMessageContent):
|
||||
return buildImageTimelineItem(for: eventItemProxy, messageContent, imageMessageContent, isOutgoing)
|
||||
case .video(let videoMessageContent):
|
||||
return buildVideoTimelineItem(for: eventItemProxy, messageContent, videoMessageContent, isOutgoing)
|
||||
case .file(let fileMessageContent):
|
||||
return buildFileTimelineItem(for: eventItemProxy, messageContent, fileMessageContent, isOutgoing)
|
||||
case .notice(content: let noticeMessageContent):
|
||||
return buildNoticeTimelineItem(for: eventItemProxy, messageContent, noticeMessageContent, isOutgoing)
|
||||
case .emote(content: let emoteMessageContent):
|
||||
return buildEmoteTimelineItem(for: eventItemProxy, messageContent, emoteMessageContent, isOutgoing)
|
||||
case .audio(let audioMessageContent):
|
||||
if audioMessageContent.voice != nil {
|
||||
return buildVoiceTimelineItem(for: eventItemProxy, messageContent, audioMessageContent, isOutgoing)
|
||||
} else {
|
||||
return buildAudioTimelineItem(for: eventItemProxy, messageTimelineItem, content, isOutgoing, isThreaded)
|
||||
return buildAudioTimelineItem(for: eventItemProxy, messageContent, audioMessageContent, isOutgoing)
|
||||
}
|
||||
case .location(let content):
|
||||
return buildLocationTimelineItem(for: eventItemProxy, messageTimelineItem, content, isOutgoing, isThreaded)
|
||||
case .location(let locationMessageContent):
|
||||
return buildLocationTimelineItem(for: eventItemProxy, messageContent, locationMessageContent, isOutgoing)
|
||||
case .other:
|
||||
return nil
|
||||
}
|
||||
@@ -196,20 +191,19 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol {
|
||||
}
|
||||
|
||||
private func buildTextTimelineItem(for eventItemProxy: EventTimelineItemProxy,
|
||||
_ messageTimelineItem: Message,
|
||||
_ messageContent: TextMessageContent,
|
||||
_ isOutgoing: Bool,
|
||||
_ isThreaded: Bool) -> RoomTimelineItemProtocol {
|
||||
_ messageContent: MessageContent,
|
||||
_ textMessageContent: TextMessageContent,
|
||||
_ isOutgoing: Bool) -> RoomTimelineItemProtocol {
|
||||
TextRoomTimelineItem(id: eventItemProxy.id,
|
||||
timestamp: eventItemProxy.timestamp.formatted(date: .omitted, time: .shortened),
|
||||
isOutgoing: isOutgoing,
|
||||
isEditable: eventItemProxy.isEditable,
|
||||
canBeRepliedTo: eventItemProxy.canBeRepliedTo,
|
||||
isThreaded: isThreaded,
|
||||
isThreaded: messageContent.threadRoot != nil,
|
||||
sender: eventItemProxy.sender,
|
||||
content: buildTextTimelineItemContent(messageContent),
|
||||
replyDetails: buildReplyToDetailsFromDetailsIfAvailable(details: messageTimelineItem.inReplyTo()),
|
||||
properties: RoomTimelineItemProperties(isEdited: messageTimelineItem.isEdited(),
|
||||
content: buildTextTimelineItemContent(textMessageContent),
|
||||
replyDetails: buildReplyToDetailsFromDetailsIfAvailable(details: messageContent.inReplyTo),
|
||||
properties: RoomTimelineItemProperties(isEdited: messageContent.isEdited,
|
||||
reactions: aggregateReactions(eventItemProxy.reactions),
|
||||
deliveryStatus: eventItemProxy.deliveryStatus,
|
||||
orderedReadReceipts: orderReadReceipts(eventItemProxy.readReceipts),
|
||||
@@ -217,20 +211,19 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol {
|
||||
}
|
||||
|
||||
private func buildImageTimelineItem(for eventItemProxy: EventTimelineItemProxy,
|
||||
_ messageTimelineItem: Message,
|
||||
_ messageContent: ImageMessageContent,
|
||||
_ isOutgoing: Bool,
|
||||
_ isThreaded: Bool) -> RoomTimelineItemProtocol {
|
||||
_ messageContent: MessageContent,
|
||||
_ imageMessageContent: ImageMessageContent,
|
||||
_ isOutgoing: Bool) -> RoomTimelineItemProtocol {
|
||||
ImageRoomTimelineItem(id: eventItemProxy.id,
|
||||
timestamp: eventItemProxy.timestamp.formatted(date: .omitted, time: .shortened),
|
||||
isOutgoing: isOutgoing,
|
||||
isEditable: eventItemProxy.isEditable,
|
||||
canBeRepliedTo: eventItemProxy.canBeRepliedTo,
|
||||
isThreaded: isThreaded,
|
||||
isThreaded: messageContent.threadRoot != nil,
|
||||
sender: eventItemProxy.sender,
|
||||
content: buildImageTimelineItemContent(messageContent),
|
||||
replyDetails: buildReplyToDetailsFromDetailsIfAvailable(details: messageTimelineItem.inReplyTo()),
|
||||
properties: RoomTimelineItemProperties(isEdited: messageTimelineItem.isEdited(),
|
||||
content: buildImageTimelineItemContent(imageMessageContent),
|
||||
replyDetails: buildReplyToDetailsFromDetailsIfAvailable(details: messageContent.inReplyTo),
|
||||
properties: RoomTimelineItemProperties(isEdited: messageContent.isEdited,
|
||||
reactions: aggregateReactions(eventItemProxy.reactions),
|
||||
deliveryStatus: eventItemProxy.deliveryStatus,
|
||||
orderedReadReceipts: orderReadReceipts(eventItemProxy.readReceipts),
|
||||
@@ -238,20 +231,19 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol {
|
||||
}
|
||||
|
||||
private func buildVideoTimelineItem(for eventItemProxy: EventTimelineItemProxy,
|
||||
_ messageTimelineItem: Message,
|
||||
_ messageContent: VideoMessageContent,
|
||||
_ isOutgoing: Bool,
|
||||
_ isThreaded: Bool) -> RoomTimelineItemProtocol {
|
||||
_ messageContent: MessageContent,
|
||||
_ videoMessageContent: VideoMessageContent,
|
||||
_ isOutgoing: Bool) -> RoomTimelineItemProtocol {
|
||||
VideoRoomTimelineItem(id: eventItemProxy.id,
|
||||
timestamp: eventItemProxy.timestamp.formatted(date: .omitted, time: .shortened),
|
||||
isOutgoing: isOutgoing,
|
||||
isEditable: eventItemProxy.isEditable,
|
||||
canBeRepliedTo: eventItemProxy.canBeRepliedTo,
|
||||
isThreaded: isThreaded,
|
||||
isThreaded: messageContent.threadRoot != nil,
|
||||
sender: eventItemProxy.sender,
|
||||
content: buildVideoTimelineItemContent(messageContent),
|
||||
replyDetails: buildReplyToDetailsFromDetailsIfAvailable(details: messageTimelineItem.inReplyTo()),
|
||||
properties: RoomTimelineItemProperties(isEdited: messageTimelineItem.isEdited(),
|
||||
content: buildVideoTimelineItemContent(videoMessageContent),
|
||||
replyDetails: buildReplyToDetailsFromDetailsIfAvailable(details: messageContent.inReplyTo),
|
||||
properties: RoomTimelineItemProperties(isEdited: messageContent.isEdited,
|
||||
reactions: aggregateReactions(eventItemProxy.reactions),
|
||||
deliveryStatus: eventItemProxy.deliveryStatus,
|
||||
orderedReadReceipts: orderReadReceipts(eventItemProxy.readReceipts),
|
||||
@@ -259,20 +251,19 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol {
|
||||
}
|
||||
|
||||
private func buildAudioTimelineItem(for eventItemProxy: EventTimelineItemProxy,
|
||||
_ messageTimelineItem: Message,
|
||||
_ messageContent: AudioMessageContent,
|
||||
_ isOutgoing: Bool,
|
||||
_ isThreaded: Bool) -> RoomTimelineItemProtocol {
|
||||
_ messageContent: MessageContent,
|
||||
_ audioMessageContent: AudioMessageContent,
|
||||
_ isOutgoing: Bool) -> RoomTimelineItemProtocol {
|
||||
AudioRoomTimelineItem(id: eventItemProxy.id,
|
||||
timestamp: eventItemProxy.timestamp.formatted(date: .omitted, time: .shortened),
|
||||
isOutgoing: isOutgoing,
|
||||
isEditable: eventItemProxy.isEditable,
|
||||
canBeRepliedTo: eventItemProxy.canBeRepliedTo,
|
||||
isThreaded: isThreaded,
|
||||
isThreaded: messageContent.threadRoot != nil,
|
||||
sender: eventItemProxy.sender,
|
||||
content: buildAudioTimelineItemContent(messageContent),
|
||||
replyDetails: buildReplyToDetailsFromDetailsIfAvailable(details: messageTimelineItem.inReplyTo()),
|
||||
properties: RoomTimelineItemProperties(isEdited: messageTimelineItem.isEdited(),
|
||||
content: buildAudioTimelineItemContent(audioMessageContent),
|
||||
replyDetails: buildReplyToDetailsFromDetailsIfAvailable(details: messageContent.inReplyTo),
|
||||
properties: RoomTimelineItemProperties(isEdited: messageContent.isEdited,
|
||||
reactions: aggregateReactions(eventItemProxy.reactions),
|
||||
deliveryStatus: eventItemProxy.deliveryStatus,
|
||||
orderedReadReceipts: orderReadReceipts(eventItemProxy.readReceipts),
|
||||
@@ -280,20 +271,19 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol {
|
||||
}
|
||||
|
||||
private func buildVoiceTimelineItem(for eventItemProxy: EventTimelineItemProxy,
|
||||
_ messageTimelineItem: Message,
|
||||
_ messageContent: AudioMessageContent,
|
||||
_ isOutgoing: Bool,
|
||||
_ isThreaded: Bool) -> RoomTimelineItemProtocol {
|
||||
_ messageContent: MessageContent,
|
||||
_ audioMessageContent: AudioMessageContent,
|
||||
_ isOutgoing: Bool) -> RoomTimelineItemProtocol {
|
||||
VoiceMessageRoomTimelineItem(id: eventItemProxy.id,
|
||||
timestamp: eventItemProxy.timestamp.formatted(date: .omitted, time: .shortened),
|
||||
isOutgoing: isOutgoing,
|
||||
isEditable: eventItemProxy.isEditable,
|
||||
canBeRepliedTo: eventItemProxy.canBeRepliedTo,
|
||||
isThreaded: isThreaded,
|
||||
isThreaded: messageContent.threadRoot != nil,
|
||||
sender: eventItemProxy.sender,
|
||||
content: buildAudioTimelineItemContent(messageContent),
|
||||
replyDetails: buildReplyToDetailsFromDetailsIfAvailable(details: messageTimelineItem.inReplyTo()),
|
||||
properties: RoomTimelineItemProperties(isEdited: messageTimelineItem.isEdited(),
|
||||
content: buildAudioTimelineItemContent(audioMessageContent),
|
||||
replyDetails: buildReplyToDetailsFromDetailsIfAvailable(details: messageContent.inReplyTo),
|
||||
properties: RoomTimelineItemProperties(isEdited: messageContent.isEdited,
|
||||
reactions: aggregateReactions(eventItemProxy.reactions),
|
||||
deliveryStatus: eventItemProxy.deliveryStatus,
|
||||
orderedReadReceipts: orderReadReceipts(eventItemProxy.readReceipts),
|
||||
@@ -301,20 +291,19 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol {
|
||||
}
|
||||
|
||||
private func buildFileTimelineItem(for eventItemProxy: EventTimelineItemProxy,
|
||||
_ messageTimelineItem: Message,
|
||||
_ messageContent: FileMessageContent,
|
||||
_ isOutgoing: Bool,
|
||||
_ isThreaded: Bool) -> RoomTimelineItemProtocol {
|
||||
_ messageContent: MessageContent,
|
||||
_ fileMessageContent: FileMessageContent,
|
||||
_ isOutgoing: Bool) -> RoomTimelineItemProtocol {
|
||||
FileRoomTimelineItem(id: eventItemProxy.id,
|
||||
timestamp: eventItemProxy.timestamp.formatted(date: .omitted, time: .shortened),
|
||||
isOutgoing: isOutgoing,
|
||||
isEditable: eventItemProxy.isEditable,
|
||||
canBeRepliedTo: eventItemProxy.canBeRepliedTo,
|
||||
isThreaded: isThreaded,
|
||||
isThreaded: messageContent.threadRoot != nil,
|
||||
sender: eventItemProxy.sender,
|
||||
content: buildFileTimelineItemContent(messageContent),
|
||||
replyDetails: buildReplyToDetailsFromDetailsIfAvailable(details: messageTimelineItem.inReplyTo()),
|
||||
properties: RoomTimelineItemProperties(isEdited: messageTimelineItem.isEdited(),
|
||||
content: buildFileTimelineItemContent(fileMessageContent),
|
||||
replyDetails: buildReplyToDetailsFromDetailsIfAvailable(details: messageContent.inReplyTo),
|
||||
properties: RoomTimelineItemProperties(isEdited: messageContent.isEdited,
|
||||
reactions: aggregateReactions(eventItemProxy.reactions),
|
||||
deliveryStatus: eventItemProxy.deliveryStatus,
|
||||
orderedReadReceipts: orderReadReceipts(eventItemProxy.readReceipts),
|
||||
@@ -322,20 +311,19 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol {
|
||||
}
|
||||
|
||||
private func buildNoticeTimelineItem(for eventItemProxy: EventTimelineItemProxy,
|
||||
_ messageTimelineItem: Message,
|
||||
_ messageContent: NoticeMessageContent,
|
||||
_ isOutgoing: Bool,
|
||||
_ isThreaded: Bool) -> RoomTimelineItemProtocol {
|
||||
_ messageContent: MessageContent,
|
||||
_ noticeMessageContent: NoticeMessageContent,
|
||||
_ isOutgoing: Bool) -> RoomTimelineItemProtocol {
|
||||
NoticeRoomTimelineItem(id: eventItemProxy.id,
|
||||
timestamp: eventItemProxy.timestamp.formatted(date: .omitted, time: .shortened),
|
||||
isOutgoing: isOutgoing,
|
||||
isEditable: eventItemProxy.isEditable,
|
||||
canBeRepliedTo: eventItemProxy.canBeRepliedTo,
|
||||
isThreaded: isThreaded,
|
||||
isThreaded: messageContent.threadRoot != nil,
|
||||
sender: eventItemProxy.sender,
|
||||
content: buildNoticeTimelineItemContent(messageContent),
|
||||
replyDetails: buildReplyToDetailsFromDetailsIfAvailable(details: messageTimelineItem.inReplyTo()),
|
||||
properties: RoomTimelineItemProperties(isEdited: messageTimelineItem.isEdited(),
|
||||
content: buildNoticeTimelineItemContent(noticeMessageContent),
|
||||
replyDetails: buildReplyToDetailsFromDetailsIfAvailable(details: messageContent.inReplyTo),
|
||||
properties: RoomTimelineItemProperties(isEdited: messageContent.isEdited,
|
||||
reactions: aggregateReactions(eventItemProxy.reactions),
|
||||
deliveryStatus: eventItemProxy.deliveryStatus,
|
||||
orderedReadReceipts: orderReadReceipts(eventItemProxy.readReceipts),
|
||||
@@ -343,20 +331,19 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol {
|
||||
}
|
||||
|
||||
private func buildEmoteTimelineItem(for eventItemProxy: EventTimelineItemProxy,
|
||||
_ messageTimelineItem: Message,
|
||||
_ messageContent: EmoteMessageContent,
|
||||
_ isOutgoing: Bool,
|
||||
_ isThreaded: Bool) -> RoomTimelineItemProtocol {
|
||||
_ messageContent: MessageContent,
|
||||
_ emoteMessageContent: EmoteMessageContent,
|
||||
_ isOutgoing: Bool) -> RoomTimelineItemProtocol {
|
||||
EmoteRoomTimelineItem(id: eventItemProxy.id,
|
||||
timestamp: eventItemProxy.timestamp.formatted(date: .omitted, time: .shortened),
|
||||
isOutgoing: isOutgoing,
|
||||
isEditable: eventItemProxy.isEditable,
|
||||
canBeRepliedTo: eventItemProxy.canBeRepliedTo,
|
||||
isThreaded: isThreaded,
|
||||
isThreaded: messageContent.threadRoot != nil,
|
||||
sender: eventItemProxy.sender,
|
||||
content: buildEmoteTimelineItemContent(senderDisplayName: eventItemProxy.sender.displayName, senderID: eventItemProxy.sender.id, messageContent: messageContent),
|
||||
replyDetails: buildReplyToDetailsFromDetailsIfAvailable(details: messageTimelineItem.inReplyTo()),
|
||||
properties: RoomTimelineItemProperties(isEdited: messageTimelineItem.isEdited(),
|
||||
content: buildEmoteTimelineItemContent(senderDisplayName: eventItemProxy.sender.displayName, senderID: eventItemProxy.sender.id, messageContent: emoteMessageContent),
|
||||
replyDetails: buildReplyToDetailsFromDetailsIfAvailable(details: messageContent.inReplyTo),
|
||||
properties: RoomTimelineItemProperties(isEdited: messageContent.isEdited,
|
||||
reactions: aggregateReactions(eventItemProxy.reactions),
|
||||
deliveryStatus: eventItemProxy.deliveryStatus,
|
||||
orderedReadReceipts: orderReadReceipts(eventItemProxy.readReceipts),
|
||||
@@ -364,20 +351,19 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol {
|
||||
}
|
||||
|
||||
private func buildLocationTimelineItem(for eventItemProxy: EventTimelineItemProxy,
|
||||
_ messageTimelineItem: Message,
|
||||
_ messageContent: LocationContent,
|
||||
_ isOutgoing: Bool,
|
||||
_ isThreaded: Bool) -> RoomTimelineItemProtocol {
|
||||
_ messageContent: MessageContent,
|
||||
_ locationMessageContent: LocationContent,
|
||||
_ isOutgoing: Bool) -> RoomTimelineItemProtocol {
|
||||
LocationRoomTimelineItem(id: eventItemProxy.id,
|
||||
timestamp: eventItemProxy.timestamp.formatted(date: .omitted, time: .shortened),
|
||||
isOutgoing: isOutgoing,
|
||||
isEditable: eventItemProxy.isEditable,
|
||||
canBeRepliedTo: eventItemProxy.canBeRepliedTo,
|
||||
isThreaded: isThreaded,
|
||||
isThreaded: messageContent.threadRoot != nil,
|
||||
sender: eventItemProxy.sender,
|
||||
content: buildLocationTimelineItemContent(messageContent),
|
||||
replyDetails: buildReplyToDetailsFromDetailsIfAvailable(details: messageTimelineItem.inReplyTo()),
|
||||
properties: RoomTimelineItemProperties(isEdited: messageTimelineItem.isEdited(),
|
||||
content: buildLocationTimelineItemContent(locationMessageContent),
|
||||
replyDetails: buildReplyToDetailsFromDetailsIfAvailable(details: messageContent.inReplyTo),
|
||||
properties: RoomTimelineItemProperties(isEdited: messageContent.isEdited,
|
||||
reactions: aggregateReactions(eventItemProxy.reactions),
|
||||
deliveryStatus: eventItemProxy.deliveryStatus,
|
||||
orderedReadReceipts: orderReadReceipts(eventItemProxy.readReceipts),
|
||||
@@ -652,12 +638,12 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol {
|
||||
// MARK: - Reply details
|
||||
|
||||
func buildReply(details: InReplyToDetails) -> TimelineItemReply {
|
||||
let isThreaded = details.event.isThreaded
|
||||
switch details.event {
|
||||
let isThreaded = details.event().isThreaded
|
||||
switch details.event() {
|
||||
case .unavailable:
|
||||
return .init(details: .notLoaded(eventID: details.eventId), isThreaded: isThreaded)
|
||||
return .init(details: .notLoaded(eventID: details.eventId()), isThreaded: isThreaded)
|
||||
case .pending:
|
||||
return .init(details: .loading(eventID: details.eventId), isThreaded: isThreaded)
|
||||
return .init(details: .loading(eventID: details.eventId()), isThreaded: isThreaded)
|
||||
case let .ready(timelineItem, senderID, senderProfile):
|
||||
let sender: TimelineItemSender
|
||||
switch senderProfile {
|
||||
@@ -675,9 +661,9 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol {
|
||||
|
||||
let replyContent: TimelineEventContent
|
||||
|
||||
switch timelineItem.kind() {
|
||||
case .message:
|
||||
return .init(details: timelineItemReplyDetails(sender: sender, eventID: details.eventId, messageType: timelineItem.asMessage()?.msgtype()), isThreaded: isThreaded)
|
||||
switch timelineItem {
|
||||
case .message(let messageContent):
|
||||
return .init(details: timelineItemReplyDetails(sender: sender, eventID: details.eventId(), messageType: messageContent.msgType), isThreaded: isThreaded)
|
||||
case .poll(let question, _, _, _, _, _, _):
|
||||
replyContent = .poll(question: question)
|
||||
case .sticker(let body, _, _):
|
||||
@@ -688,9 +674,9 @@ struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol {
|
||||
replyContent = .message(.text(.init(body: L10n.commonUnsupportedEvent)))
|
||||
}
|
||||
|
||||
return .init(details: .loaded(sender: sender, eventID: details.eventId, eventContent: replyContent), isThreaded: isThreaded)
|
||||
return .init(details: .loaded(sender: sender, eventID: details.eventId(), eventContent: replyContent), isThreaded: isThreaded)
|
||||
case let .error(message):
|
||||
return .init(details: .error(eventID: details.eventId, message: message), isThreaded: isThreaded)
|
||||
return .init(details: .error(eventID: details.eventId(), message: message), isThreaded: isThreaded)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -751,7 +737,11 @@ private extension RepliedToEventDetails {
|
||||
var isThreaded: Bool {
|
||||
switch self {
|
||||
case .ready(let content, _, _):
|
||||
return content.asMessage()?.isThreaded() ?? false
|
||||
guard case let .message(content) = content else {
|
||||
return false
|
||||
}
|
||||
|
||||
return content.threadRoot != nil
|
||||
default:
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -8,23 +8,14 @@
|
||||
import Foundation
|
||||
|
||||
final class RoomTimelineItemViewState: Identifiable, Equatable, ObservableObject {
|
||||
static func == (lhs: RoomTimelineItemViewState, rhs: RoomTimelineItemViewState) -> Bool {
|
||||
lhs.type == rhs.type && lhs.groupStyle == rhs.groupStyle
|
||||
}
|
||||
|
||||
@Published var type: RoomTimelineItemType
|
||||
@Published var groupStyle: TimelineGroupStyle
|
||||
|
||||
/// Contains all the identification info of the item, `timelineID`, `eventID` and `transactionID`
|
||||
/// Contains all the identification info of the item, `uniqueID`, `eventID` and `transactionID`
|
||||
var identifier: TimelineItemIdentifier {
|
||||
type.id
|
||||
}
|
||||
|
||||
/// The `timelineID` of the item, used for the timeline view level identification, do not use for any business logic use `identifier` instead
|
||||
var id: String {
|
||||
identifier.timelineID
|
||||
}
|
||||
|
||||
init(type: RoomTimelineItemType, groupStyle: TimelineGroupStyle) {
|
||||
self.type = type
|
||||
self.groupStyle = groupStyle
|
||||
@@ -33,6 +24,19 @@ final class RoomTimelineItemViewState: Identifiable, Equatable, ObservableObject
|
||||
convenience init(item: RoomTimelineItemProtocol, groupStyle: TimelineGroupStyle) {
|
||||
self.init(type: .init(item: item), groupStyle: groupStyle)
|
||||
}
|
||||
|
||||
// MARK: - Equatable
|
||||
|
||||
static func == (lhs: RoomTimelineItemViewState, rhs: RoomTimelineItemViewState) -> Bool {
|
||||
lhs.type == rhs.type && lhs.groupStyle == rhs.groupStyle
|
||||
}
|
||||
|
||||
// MARK: Identifiable
|
||||
|
||||
/// The `timelineID` of the item, used for the timeline view level identification, do not use for any business logic use `identifier` instead
|
||||
var id: String {
|
||||
identifier.uniqueID
|
||||
}
|
||||
}
|
||||
|
||||
enum RoomTimelineItemType: Equatable {
|
||||
|
||||
@@ -72,7 +72,17 @@ final class TimelineProxy: TimelineProxyProtocol {
|
||||
}
|
||||
|
||||
func messageEventContent(for timelineItemID: TimelineItemIdentifier) async -> RoomMessageEventContentWithoutRelation? {
|
||||
await timelineProvider.itemProxies.firstEventTimelineItemUsingStableID(timelineItemID)?.content().asMessage()?.content()
|
||||
guard let content = await timelineProvider.itemProxies.firstEventTimelineItemUsingStableID(timelineItemID)?.content,
|
||||
case let .message(messageContent) = content else {
|
||||
return nil
|
||||
}
|
||||
|
||||
do {
|
||||
return try contentWithoutRelationFromMessage(message: messageContent)
|
||||
} catch {
|
||||
MXLog.error("Failed retrieving message event content for timelineItemID=\(timelineItemID)")
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func paginateBackwards(requestSize: UInt16) async -> Result<Void, TimelineProxyError> {
|
||||
@@ -156,15 +166,15 @@ final class TimelineProxy: TimelineProxyProtocol {
|
||||
|
||||
func edit(_ timelineItem: EventTimelineItem, newContent: RoomMessageEventContentWithoutRelation) async -> Result<Void, TimelineProxyError> {
|
||||
do {
|
||||
guard try await timeline.edit(item: timelineItem, newContent: .roomMessage(content: newContent)) == true else {
|
||||
guard try await timeline.edit(eventOrTransactionId: timelineItem.eventOrTransactionId, newContent: .roomMessage(content: newContent)) == true else {
|
||||
return .failure(.failedEditing)
|
||||
}
|
||||
|
||||
MXLog.info("Finished editing timeline item: \(timelineItem.eventId() ?? timelineItem.transactionId() ?? "unknown")")
|
||||
MXLog.info("Finished editing timeline item: \(timelineItem.eventOrTransactionId)")
|
||||
|
||||
return .success(())
|
||||
} catch {
|
||||
MXLog.error("Failed editing timeline item: \(timelineItem.eventId() ?? timelineItem.transactionId() ?? "unknown") with error: \(error)")
|
||||
MXLog.error("Failed editing timeline item: \(timelineItem.eventOrTransactionId) with error: \(error)")
|
||||
return .failure(.sdkError(error))
|
||||
}
|
||||
}
|
||||
@@ -172,18 +182,13 @@ final class TimelineProxy: TimelineProxyProtocol {
|
||||
func redact(_ timelineItemID: TimelineItemIdentifier, reason: String?) async -> Result<Void, TimelineProxyError> {
|
||||
MXLog.info("Redacting timeline item: \(timelineItemID)")
|
||||
|
||||
guard let eventTimelineItem = await timelineProvider.itemProxies.firstEventTimelineItemUsingStableID(timelineItemID) else {
|
||||
guard let eventOrTransactionID = await timelineProvider.itemProxies.firstEventTimelineItemUsingStableID(timelineItemID)?.eventOrTransactionId else {
|
||||
MXLog.error("Unknown timeline item: \(timelineItemID)")
|
||||
return .failure(.failedRedacting)
|
||||
}
|
||||
|
||||
do {
|
||||
let success = try await timeline.redactEvent(item: eventTimelineItem, reason: reason)
|
||||
|
||||
guard success else {
|
||||
MXLog.error("Failed redacting timeline item: \(timelineItemID)")
|
||||
return .failure(.failedRedacting)
|
||||
}
|
||||
try await timeline.redactEvent(eventOrTransactionId: eventOrTransactionID, reason: reason)
|
||||
|
||||
MXLog.info("Redacted timeline item: \(timelineItemID)")
|
||||
|
||||
@@ -425,7 +430,7 @@ final class TimelineProxy: TimelineProxyProtocol {
|
||||
MXLog.info("Toggling reaction for event: \(itemID)")
|
||||
|
||||
do {
|
||||
try await timeline.toggleReaction(uniqueId: itemID.timelineID, key: reaction)
|
||||
try await timeline.toggleReaction(uniqueId: itemID.uniqueID, key: reaction)
|
||||
MXLog.info("Finished toggling reaction for event: \(itemID)")
|
||||
return .success(())
|
||||
} catch {
|
||||
@@ -460,7 +465,7 @@ final class TimelineProxy: TimelineProxyProtocol {
|
||||
do {
|
||||
let originalEvent = try await timeline.getEventTimelineItemByEventId(eventId: eventID)
|
||||
|
||||
guard try await timeline.edit(item: originalEvent,
|
||||
guard try await timeline.edit(eventOrTransactionId: originalEvent.eventOrTransactionId,
|
||||
newContent: .pollStart(pollData: .init(question: question,
|
||||
answers: answers,
|
||||
maxSelections: 1,
|
||||
@@ -482,7 +487,7 @@ final class TimelineProxy: TimelineProxyProtocol {
|
||||
|
||||
return await Task.dispatch(on: .global()) {
|
||||
do {
|
||||
try self.timeline.endPoll(pollStartId: pollStartID, text: text)
|
||||
try self.timeline.endPoll(pollStartEventId: pollStartID, text: text)
|
||||
|
||||
MXLog.info("Finished ending poll with eventID: \(pollStartID)")
|
||||
|
||||
@@ -498,7 +503,7 @@ final class TimelineProxy: TimelineProxyProtocol {
|
||||
MXLog.info("Sending response for poll with eventID: \(pollStartID)")
|
||||
|
||||
do {
|
||||
try await timeline.sendPollResponse(pollStartId: pollStartID, answers: answers)
|
||||
try await timeline.sendPollResponse(pollStartEventId: pollStartID, answers: answers)
|
||||
|
||||
MXLog.info("Finished sending response for poll with eventID: \(pollStartID)")
|
||||
|
||||
@@ -618,7 +623,7 @@ extension Array where Element == TimelineItemProxy {
|
||||
func firstEventTimelineItemUsingStableID(_ id: TimelineItemIdentifier) -> EventTimelineItem? {
|
||||
for item in self {
|
||||
if case let .event(eventTimelineItem) = item {
|
||||
if eventTimelineItem.id.timelineID == id.timelineID {
|
||||
if eventTimelineItem.id.uniqueID == id.uniqueID {
|
||||
return eventTimelineItem.item
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user