diff --git a/NucleicRemote/NucleicRemote/Models/RemoteStore.swift b/NucleicRemote/NucleicRemote/Models/RemoteStore.swift index 97e1d0e..f5016b2 100644 --- a/NucleicRemote/NucleicRemote/Models/RemoteStore.swift +++ b/NucleicRemote/NucleicRemote/Models/RemoteStore.swift @@ -560,6 +560,20 @@ final class RemoteStore: ObservableObject { } } + /// Merge transcript events by `seq` (monotonic, globally unique within a session), keeping the + /// union sorted. Lets a reconnect's snapshot fold its events into the transcript already on + /// screen without duplicating what's shown or dropping history outside the host's tail window. + /// A fresh open merges into `[]`, so it's just the tail — the same result as a plain replace. + private static func mergedEvents(_ existing: [AgentEvent], _ incoming: [AgentEvent]) -> [AgentEvent] { + guard !existing.isEmpty else { return incoming } + guard !incoming.isEmpty else { return existing } + var bySeq: [UInt64: AgentEvent] = [:] + bySeq.reserveCapacity(existing.count + incoming.count) + for e in existing { bySeq[e.seq] = e } + for e in incoming { bySeq[e.seq] = e } + return bySeq.values.sorted { $0.seq < $1.seq } + } + /// The flat sessions list: every connected Mac's sessions, deduped by id (ids are globally /// unique). Views handle sorting/grouping. private func aggregatedSessions() -> [WireSessionSummary] {