diff --git a/Mactrix/Models/LiveTimeline.swift b/Mactrix/Models/LiveTimeline.swift index 17c1b28..c45ab8b 100644 --- a/Mactrix/Models/LiveTimeline.swift +++ b/Mactrix/Models/LiveTimeline.swift @@ -23,6 +23,7 @@ public final class LiveTimeline { public var sendReplyTo: MatrixRustSDK.EventTimelineItem? public private(set) var timelineItems: [TimelineItem] = [] + public private(set) var loadedReplyDetails: [String: InReplyToDetails] = [:] // public private(set) var timelineGroups: TimelineGroups = .init() public private(set) var paginating: RoomPaginationStatus = .idle(hitTimelineStart: false) @@ -174,6 +175,32 @@ extension LiveTimeline { timelineItems = values } } + + loadPendingReplyDetails() + } + + private func loadPendingReplyDetails() { + guard let sdkTimeline = timeline else { return } + for item in timelineItems { + guard let event = item.asEvent() else { continue } + guard case let .msgLike(content: msgLike) = event.content else { continue } + guard let inReplyTo = msgLike.inReplyTo else { continue } + let eventId = inReplyTo.eventId() + switch inReplyTo.event() { + case .ready, .error: continue + case .pending, .unavailable: break + } + guard loadedReplyDetails[eventId] == nil else { continue } + Task { [weak self] in + guard let self else { return } + do { + let details = try await sdkTimeline.loadReplyDetails(eventIdStr: eventId) + self.loadedReplyDetails[eventId] = details + } catch { + Logger.liveTimeline.error("loadPendingReplyDetails: failed \(eventId): \(error)") + } + } + } } } diff --git a/Mactrix/Views/ChatView/ChatMessageView.swift b/Mactrix/Views/ChatView/ChatMessageView.swift index 5937e2d..879b790 100644 --- a/Mactrix/Views/ChatView/ChatMessageView.swift +++ b/Mactrix/Views/ChatView/ChatMessageView.swift @@ -132,8 +132,10 @@ struct ChatMessageView: View, UI.MessageEventActions { UI.MessageEventBodyView(event: event, focused: isEventFocused, reactions: msg.reactions, actions: self, ownUserID: ownUserId, imageLoader: appState.matrixClient, roomMembers: timeline?.room.members ?? []) { VStack(alignment: .leading, spacing: 10) { if let replyTo = msg.inReplyTo { - EmbeddedMessageView(embeddedEvent: replyTo.event()) { - timeline?.focusEvent(id: .eventId(eventId: replyTo.eventId())) + let eventId = replyTo.eventId() + let embeddedEvent = timeline?.loadedReplyDetails[eventId]?.event() ?? replyTo.event() + EmbeddedMessageView(embeddedEvent: embeddedEvent) { + timeline?.focusEvent(id: .eventId(eventId: eventId)) } .padding(.bottom, 10) } diff --git a/Mactrix/Views/ChatView/EmbeddedMessageView.swift b/Mactrix/Views/ChatView/EmbeddedMessageView.swift index 025bb01..7aa8b48 100644 --- a/Mactrix/Views/ChatView/EmbeddedMessageView.swift +++ b/Mactrix/Views/ChatView/EmbeddedMessageView.swift @@ -15,8 +15,15 @@ struct EmbeddedMessageView: View { action: action ) .redacted(reason: .placeholder) - case let .ready(content, sender, _, _, _): - UI.MessageReplyView(username: sender, message: content.description, action: action) + case let .ready(content, sender, senderProfile, _, _): + UI.MessageReplyView( + username: { + if case let .ready(name, _, _) = senderProfile, let name { return name } + return sender + }(), + message: content.description, + action: action + ) case let .error(message): Text("error: \(message)") }