mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-03 16:10:20 +00:00
Refactor theTimelineItemIdentifier handling; stop relying on optional EventOrTransactionIds and be explicit when setting composer modes from the draft service.
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(uniqueID: "Yesterday"), text: "Yesterday"),
|
||||
TextRoomTimelineItem(id: .init(uniqueID: ".RoomTimelineItemFixtures.default.0",
|
||||
eventOrTransactionID: .eventId(eventId: "RoomTimelineItemFixtures.default.0")),
|
||||
SeparatorRoomTimelineItem(id: .virtual(uniqueID: "Yesterday"), text: "Yesterday"),
|
||||
TextRoomTimelineItem(id: .event(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(uniqueID: "RoomTimelineItemFixtures.default.1",
|
||||
eventOrTransactionID: .eventId(eventId: "RoomTimelineItemFixtures.default.1")),
|
||||
TextRoomTimelineItem(id: .event(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(uniqueID: "RoomTimelineItemFixtures.default.2",
|
||||
eventOrTransactionID: .eventId(eventId: "RoomTimelineItemFixtures.default.2")),
|
||||
TextRoomTimelineItem(id: .event(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(uniqueID: "Today"), text: "Today"),
|
||||
TextRoomTimelineItem(id: .init(uniqueID: "RoomTimelineItemFixtures.default.3",
|
||||
eventOrTransactionID: .eventId(eventId: "RoomTimelineItemFixtures.default.3")),
|
||||
SeparatorRoomTimelineItem(id: .virtual(uniqueID: "Today"), text: "Today"),
|
||||
TextRoomTimelineItem(id: .event(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(uniqueID: "RoomTimelineItemFixtures.default.4",
|
||||
eventOrTransactionID: .eventId(eventId: "RoomTimelineItemFixtures.default.4")),
|
||||
TextRoomTimelineItem(id: .event(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(uniqueID: "RoomTimelineItemFixtures.default.5",
|
||||
eventOrTransactionID: .eventId(eventId: "RoomTimelineItemFixtures.default.5")),
|
||||
TextRoomTimelineItem(id: .event(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(uniqueID: "RoomTimelineItemFixtures.default.6",
|
||||
eventOrTransactionID: .eventId(eventId: "RoomTimelineItemFixtures.default.6")),
|
||||
TextRoomTimelineItem(id: .event(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(uniqueID: "\(index)", eventOrTransactionID: .eventId(eventId: "$\(index)")),
|
||||
TextRoomTimelineItem(id: .event(uniqueID: "\(index)", eventOrTransactionID: .eventId(eventId: "$\(index)")),
|
||||
text: "Message ID \(index)",
|
||||
senderDisplayName: index > 10 ? "Alice" : "Bob")
|
||||
}
|
||||
@@ -250,7 +250,7 @@ enum RoomTimelineItemFixtures {
|
||||
|
||||
static var mediaChunk: [RoomTimelineItemProtocol] {
|
||||
[
|
||||
VideoRoomTimelineItem(id: .random,
|
||||
VideoRoomTimelineItem(id: .randomEvent,
|
||||
timestamp: "10:47 am",
|
||||
isOutgoing: false,
|
||||
isEditable: false,
|
||||
@@ -265,7 +265,7 @@ enum RoomTimelineItemFixtures {
|
||||
height: 1080,
|
||||
aspectRatio: 1.78,
|
||||
blurhash: "KtI~70X5V?yss9oyrYs:t6")),
|
||||
ImageRoomTimelineItem(id: .random,
|
||||
ImageRoomTimelineItem(id: .randomEvent,
|
||||
timestamp: "10:47 am",
|
||||
isOutgoing: false,
|
||||
isEditable: false,
|
||||
@@ -285,7 +285,7 @@ enum RoomTimelineItemFixtures {
|
||||
|
||||
private extension TextRoomTimelineItem {
|
||||
init(id: TimelineItemIdentifier? = nil, text: String, senderDisplayName: String) {
|
||||
self.init(id: id ?? .random,
|
||||
self.init(id: id ?? .randomEvent,
|
||||
timestamp: "10:47 am",
|
||||
isOutgoing: senderDisplayName == "Alice",
|
||||
isEditable: false,
|
||||
|
||||
+3
-2
@@ -81,12 +81,13 @@ class MockRoomTimelineController: RoomTimelineControllerProtocol {
|
||||
|
||||
func sendMessage(_ message: String,
|
||||
html: String?,
|
||||
inReplyTo itemID: TimelineItemIdentifier?,
|
||||
inReplyToEventID: String?,
|
||||
intentionalMentions: IntentionalMentions) async { }
|
||||
|
||||
func toggleReaction(_ reaction: String, to itemID: TimelineItemIdentifier) async { }
|
||||
|
||||
func edit(_ timelineItemID: TimelineItemIdentifier,
|
||||
func edit(_ eventOrTransactionID: EventOrTransactionId,
|
||||
useTimeline: Bool,
|
||||
message: String,
|
||||
html: String?,
|
||||
intentionalMentions: IntentionalMentions) async { }
|
||||
|
||||
+16
-36
@@ -143,22 +143,13 @@ class RoomTimelineController: RoomTimelineControllerProtocol {
|
||||
|
||||
func sendMessage(_ message: String,
|
||||
html: String?,
|
||||
inReplyTo itemID: TimelineItemIdentifier?,
|
||||
inReplyToEventID: String?,
|
||||
intentionalMentions: IntentionalMentions) async {
|
||||
var inReplyTo: String?
|
||||
if itemID == nil {
|
||||
MXLog.info("Send message in \(roomID)")
|
||||
} else if let eventID = itemID?.eventID {
|
||||
inReplyTo = eventID
|
||||
MXLog.info("Send reply in \(roomID)")
|
||||
} else {
|
||||
MXLog.error("Send reply in \(roomID) failed: missing event ID")
|
||||
return
|
||||
}
|
||||
MXLog.info("Send message in \(roomID)")
|
||||
|
||||
switch await activeTimeline.sendMessage(message,
|
||||
html: html,
|
||||
inReplyTo: inReplyTo,
|
||||
inReplyToEventID: inReplyToEventID,
|
||||
intentionalMentions: intentionalMentions) {
|
||||
case .success:
|
||||
MXLog.info("Finished sending message")
|
||||
@@ -178,37 +169,31 @@ class RoomTimelineController: RoomTimelineControllerProtocol {
|
||||
}
|
||||
}
|
||||
|
||||
func edit(_ timelineItemID: TimelineItemIdentifier,
|
||||
func edit(_ eventOrTransactionID: EventOrTransactionId,
|
||||
useTimeline: Bool,
|
||||
message: String,
|
||||
html: String?,
|
||||
intentionalMentions: IntentionalMentions) async {
|
||||
MXLog.info("Edit message in \(roomID)")
|
||||
MXLog.info("Editing timeline item: \(timelineItemID)")
|
||||
|
||||
let editMode: EditMode
|
||||
if !timelineItemID.uniqueID.isEmpty,
|
||||
let timelineItem = liveTimelineProvider.itemProxies.firstEventTimelineItemUsingStableID(timelineItemID) {
|
||||
editMode = .byEvent(timelineItem)
|
||||
} else if let eventID = timelineItemID.eventID {
|
||||
editMode = .byID(eventID)
|
||||
} else {
|
||||
MXLog.error("Unknown timeline item: \(timelineItemID)")
|
||||
return
|
||||
}
|
||||
MXLog.info("Editing timeline item: \(eventOrTransactionID)")
|
||||
|
||||
let messageContent = activeTimeline.buildMessageContentFor(message,
|
||||
html: html,
|
||||
intentionalMentions: intentionalMentions.toRustMentions())
|
||||
|
||||
switch editMode {
|
||||
case let .byEvent(item):
|
||||
switch await activeTimeline.edit(item, newContent: messageContent) {
|
||||
if useTimeline {
|
||||
switch await activeTimeline.edit(eventOrTransactionID, newContent: messageContent) {
|
||||
case .success:
|
||||
MXLog.info("Finished editing message by event")
|
||||
case let .failure(error):
|
||||
MXLog.error("Failed editing message by event with error: \(error)")
|
||||
}
|
||||
case let .byID(eventID):
|
||||
} else {
|
||||
guard case let .eventId(eventID) = eventOrTransactionID else {
|
||||
MXLog.error("Failed editing message, missing eventID.")
|
||||
return
|
||||
}
|
||||
|
||||
switch await roomProxy.edit(eventID: eventID, newContent: messageContent) {
|
||||
case .success:
|
||||
MXLog.info("Finished editing message by event ID")
|
||||
@@ -398,9 +383,9 @@ class RoomTimelineController: RoomTimelineControllerProtocol {
|
||||
let date = Date(timeIntervalSince1970: TimeInterval(timestamp / 1000))
|
||||
let dateString = date.formatted(date: .complete, time: .omitted)
|
||||
|
||||
return SeparatorRoomTimelineItem(id: .init(uniqueID: dateString), text: dateString)
|
||||
return SeparatorRoomTimelineItem(id: .virtual(uniqueID: uniqueID), text: dateString)
|
||||
case .readMarker:
|
||||
return ReadMarkerRoomTimelineItem(id: .init(uniqueID: uniqueID))
|
||||
return ReadMarkerRoomTimelineItem(id: .virtual(uniqueID: uniqueID))
|
||||
}
|
||||
case .unknown:
|
||||
return nil
|
||||
@@ -453,8 +438,3 @@ class RoomTimelineController: RoomTimelineControllerProtocol {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
private enum EditMode {
|
||||
case byEvent(EventTimelineItem)
|
||||
case byID(String)
|
||||
}
|
||||
|
||||
+3
-13
@@ -48,10 +48,11 @@ protocol RoomTimelineControllerProtocol {
|
||||
|
||||
func sendMessage(_ message: String,
|
||||
html: String?,
|
||||
inReplyTo itemID: TimelineItemIdentifier?,
|
||||
inReplyToEventID: String?,
|
||||
intentionalMentions: IntentionalMentions) async
|
||||
|
||||
func edit(_ timelineItemID: TimelineItemIdentifier,
|
||||
func edit(_ eventOrTransactionID: EventOrTransactionId,
|
||||
useTimeline: Bool,
|
||||
message: String,
|
||||
html: String?,
|
||||
intentionalMentions: IntentionalMentions) async
|
||||
@@ -72,14 +73,3 @@ protocol RoomTimelineControllerProtocol {
|
||||
|
||||
func eventTimestamp(for itemID: TimelineItemIdentifier) -> Date?
|
||||
}
|
||||
|
||||
extension RoomTimelineControllerProtocol {
|
||||
func sendMessage(_ message: String,
|
||||
html: String?,
|
||||
intentionalMentions: IntentionalMentions) async {
|
||||
await sendMessage(message,
|
||||
html: html,
|
||||
inReplyTo: nil,
|
||||
intentionalMentions: intentionalMentions)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
//
|
||||
// Copyright 2024 New Vector Ltd.
|
||||
//
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
// Please see LICENSE in the repository root for full details.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import MatrixRustSDK
|
||||
|
||||
/// A timeline item identifier
|
||||
/// - uniqueID: Stable id across state changes of the timeline item, it uniquely identifies an item in a timeline.
|
||||
/// Its value is consistent only per timeline instance, it should **not** be used to identify an item across timeline instances.
|
||||
/// - eventOrTransactionID: Contains the 2 possible identifiers of an event, either it has a remote event id or
|
||||
/// a local transaction id, never both or none.
|
||||
enum TimelineItemIdentifier: Hashable {
|
||||
case event(uniqueID: String, eventOrTransactionID: EventOrTransactionId)
|
||||
case virtual(uniqueID: String)
|
||||
|
||||
var uniqueID: String {
|
||||
switch self {
|
||||
case .event(let uniqueID, _):
|
||||
return uniqueID
|
||||
case .virtual(let uniqueID):
|
||||
return uniqueID
|
||||
}
|
||||
}
|
||||
|
||||
var eventID: String? {
|
||||
guard case let .event(_, eventOrTransactionID) = self else {
|
||||
return nil
|
||||
}
|
||||
|
||||
switch eventOrTransactionID {
|
||||
case .eventId(let eventID):
|
||||
return eventID
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
var transactionID: String? {
|
||||
guard case let .event(_, eventOrTransactionID) = self else {
|
||||
return nil
|
||||
}
|
||||
|
||||
switch eventOrTransactionID {
|
||||
case .transactionId(let transactionID):
|
||||
return transactionID
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Mocks
|
||||
|
||||
extension TimelineItemIdentifier {
|
||||
static var randomEvent: Self {
|
||||
.event(uniqueID: UUID().uuidString, eventOrTransactionID: .eventId(eventId: UUID().uuidString))
|
||||
}
|
||||
|
||||
static var randomVirtual: Self {
|
||||
.virtual(uniqueID: UUID().uuidString)
|
||||
}
|
||||
}
|
||||
@@ -8,40 +8,6 @@
|
||||
import Foundation
|
||||
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 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(uniqueID: UUID().uuidString, eventOrTransactionID: .eventId(eventId: UUID().uuidString))
|
||||
}
|
||||
}
|
||||
|
||||
/// A light wrapper around timeline items returned from Rust.
|
||||
enum TimelineItemProxy {
|
||||
case event(EventTimelineItemProxy)
|
||||
@@ -108,7 +74,7 @@ class EventTimelineItemProxy {
|
||||
init(item: MatrixRustSDK.EventTimelineItem, uniqueID: String) {
|
||||
self.item = item
|
||||
|
||||
id = TimelineItemIdentifier(uniqueID: uniqueID, eventOrTransactionID: item.eventOrTransactionId)
|
||||
id = .event(uniqueID: uniqueID, eventOrTransactionID: item.eventOrTransactionId)
|
||||
}
|
||||
|
||||
lazy var deliveryStatus: TimelineItemDeliveryStatus? = {
|
||||
|
||||
+1
-1
@@ -97,7 +97,7 @@ struct VoiceMessageRoomPlaybackView_Previews: PreviewProvider, TestablePreview {
|
||||
294, 131, 19, 2, 3, 3, 1, 2, 0, 0,
|
||||
0, 0, 0, 0, 0, 3])
|
||||
|
||||
static var playerState = AudioPlayerState(id: .timelineItemIdentifier(.random),
|
||||
static var playerState = AudioPlayerState(id: .timelineItemIdentifier(.randomEvent),
|
||||
title: L10n.commonVoiceMessage,
|
||||
duration: 10.0,
|
||||
waveform: waveform,
|
||||
|
||||
+1
-1
@@ -55,7 +55,7 @@ struct VoiceMessageRoomTimelineView: View {
|
||||
|
||||
struct VoiceMessageRoomTimelineView_Previews: PreviewProvider, TestablePreview {
|
||||
static let viewModel = TimelineViewModel.mock
|
||||
static let timelineItemIdentifier = TimelineItemIdentifier.random
|
||||
static let timelineItemIdentifier = TimelineItemIdentifier.randomEvent
|
||||
static let voiceRoomTimelineItem = VoiceMessageRoomTimelineItem(id: timelineItemIdentifier,
|
||||
timestamp: "Now",
|
||||
isOutgoing: false,
|
||||
|
||||
+1
-1
@@ -22,6 +22,6 @@ struct PaginationIndicatorRoomTimelineItem: DecorationTimelineItemProtocol, Equa
|
||||
}
|
||||
|
||||
init(position: Position) {
|
||||
id = TimelineItemIdentifier(uniqueID: position.id)
|
||||
id = .virtual(uniqueID: position.id)
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -8,6 +8,6 @@
|
||||
import Foundation
|
||||
|
||||
struct TimelineStartRoomTimelineItem: DecorationTimelineItemProtocol, Equatable {
|
||||
let id = TimelineItemIdentifier(uniqueID: UUID().uuidString)
|
||||
let id: TimelineItemIdentifier = .virtual(uniqueID: UUID().uuidString)
|
||||
let name: String?
|
||||
}
|
||||
|
||||
@@ -164,17 +164,17 @@ final class TimelineProxy: TimelineProxyProtocol {
|
||||
}
|
||||
}
|
||||
|
||||
func edit(_ timelineItem: EventTimelineItem, newContent: RoomMessageEventContentWithoutRelation) async -> Result<Void, TimelineProxyError> {
|
||||
func edit(_ eventOrTransactionID: EventOrTransactionId, newContent: RoomMessageEventContentWithoutRelation) async -> Result<Void, TimelineProxyError> {
|
||||
do {
|
||||
guard try await timeline.edit(eventOrTransactionId: timelineItem.eventOrTransactionId, newContent: .roomMessage(content: newContent)) == true else {
|
||||
guard try await timeline.edit(eventOrTransactionId: eventOrTransactionID, newContent: .roomMessage(content: newContent)) == true else {
|
||||
return .failure(.failedEditing)
|
||||
}
|
||||
|
||||
MXLog.info("Finished editing timeline item: \(timelineItem.eventOrTransactionId)")
|
||||
MXLog.info("Finished editing timeline item: \(eventOrTransactionID)")
|
||||
|
||||
return .success(())
|
||||
} catch {
|
||||
MXLog.error("Failed editing timeline item: \(timelineItem.eventOrTransactionId) with error: \(error)")
|
||||
MXLog.error("Failed editing timeline item: \(eventOrTransactionID) with error: \(error)")
|
||||
return .failure(.sdkError(error))
|
||||
}
|
||||
}
|
||||
@@ -366,10 +366,10 @@ final class TimelineProxy: TimelineProxyProtocol {
|
||||
|
||||
func sendMessage(_ message: String,
|
||||
html: String?,
|
||||
inReplyTo eventID: String? = nil,
|
||||
inReplyToEventID: String? = nil,
|
||||
intentionalMentions: IntentionalMentions) async -> Result<Void, TimelineProxyError> {
|
||||
if let eventID {
|
||||
MXLog.info("Sending reply to eventID: \(eventID)")
|
||||
if let inReplyToEventID {
|
||||
MXLog.info("Sending reply to eventID: \(inReplyToEventID)")
|
||||
} else {
|
||||
MXLog.info("Sending message")
|
||||
}
|
||||
@@ -379,16 +379,16 @@ final class TimelineProxy: TimelineProxyProtocol {
|
||||
intentionalMentions: intentionalMentions.toRustMentions())
|
||||
|
||||
do {
|
||||
if let eventID {
|
||||
try await timeline.sendReply(msg: messageContent, eventId: eventID)
|
||||
MXLog.info("Finished sending reply to eventID: \(eventID)")
|
||||
if let inReplyToEventID {
|
||||
try await timeline.sendReply(msg: messageContent, eventId: inReplyToEventID)
|
||||
MXLog.info("Finished sending reply to eventID: \(inReplyToEventID)")
|
||||
} else {
|
||||
_ = try await timeline.send(msg: messageContent)
|
||||
MXLog.info("Finished sending message")
|
||||
}
|
||||
} catch {
|
||||
if let eventID {
|
||||
MXLog.error("Failed sending reply to eventID: \(eventID) with error: \(error)")
|
||||
if let inReplyToEventID {
|
||||
MXLog.error("Failed sending reply to eventID: \(inReplyToEventID) with error: \(error)")
|
||||
} else {
|
||||
MXLog.error("Failed sending message with error: \(error)")
|
||||
}
|
||||
@@ -631,4 +631,16 @@ extension Array where Element == TimelineItemProxy {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func firstEventTimelineItemUsingEventOrTransactionID(_ eventOrTransactionID: EventOrTransactionId) -> EventTimelineItem? {
|
||||
for item in self {
|
||||
if case let .event(eventTimelineItem) = item,
|
||||
case let .event(_, identifier) = eventTimelineItem.id,
|
||||
identifier == eventOrTransactionID {
|
||||
return eventTimelineItem.item
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,7 +38,8 @@ protocol TimelineProxyProtocol {
|
||||
func paginateBackwards(requestSize: UInt16) async -> Result<Void, TimelineProxyError>
|
||||
func paginateForwards(requestSize: UInt16) async -> Result<Void, TimelineProxyError>
|
||||
|
||||
func edit(_ timelineItem: EventTimelineItem, newContent: RoomMessageEventContentWithoutRelation) async -> Result<Void, TimelineProxyError>
|
||||
func edit(_ eventOrTransactionID: EventOrTransactionId,
|
||||
newContent: RoomMessageEventContentWithoutRelation) async -> Result<Void, TimelineProxyError>
|
||||
|
||||
func redact(_ timelineItemID: TimelineItemIdentifier,
|
||||
reason: String?) async -> Result<Void, TimelineProxyError>
|
||||
@@ -89,12 +90,11 @@ protocol TimelineProxyProtocol {
|
||||
|
||||
func sendMessage(_ message: String,
|
||||
html: String?,
|
||||
inReplyTo eventID: String?,
|
||||
inReplyToEventID: String?,
|
||||
intentionalMentions: IntentionalMentions) async -> Result<Void, TimelineProxyError>
|
||||
|
||||
func toggleReaction(_ reaction: String, to itemID: TimelineItemIdentifier) async -> Result<Void, TimelineProxyError>
|
||||
|
||||
// Polls
|
||||
func createPoll(question: String, answers: [String], pollKind: Poll.Kind) async -> Result<Void, TimelineProxyError>
|
||||
|
||||
func editPoll(original eventID: String,
|
||||
@@ -112,14 +112,3 @@ protocol TimelineProxyProtocol {
|
||||
html: String?,
|
||||
intentionalMentions: Mentions) -> RoomMessageEventContentWithoutRelation
|
||||
}
|
||||
|
||||
extension TimelineProxyProtocol {
|
||||
func sendMessage(_ message: String,
|
||||
html: String?,
|
||||
intentionalMentions: IntentionalMentions) async -> Result<Void, TimelineProxyError> {
|
||||
await sendMessage(message,
|
||||
html: html,
|
||||
inReplyTo: nil,
|
||||
intentionalMentions: intentionalMentions)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user