diff --git a/NucleicRemote/NucleicRemote/Models/HostConnection.swift b/NucleicRemote/NucleicRemote/Models/HostConnection.swift index 2d20037..0dba1bd 100644 --- a/NucleicRemote/NucleicRemote/Models/HostConnection.swift +++ b/NucleicRemote/NucleicRemote/Models/HostConnection.swift @@ -476,12 +476,17 @@ final class HostConnection { callbacks.didUpdate() case .snapshot(let snapshot): guard snapshot.summary.sessionID == openSessionID else { break } - seenSeq = Set(snapshot.recentEvents.map(\.seq)) + // A snapshot may be a fresh open (tail window) or a warm-resubscribe delta; either way + // union its seqs into the dedup set and advance the cursor. RemoteStore merges the events + // into the transcript rather than replacing, so an existing transcript isn't truncated. + seenSeq.formUnion(snapshot.recentEvents.map(\.seq)) + if let maxSeq = snapshot.recentEvents.map(\.seq).max() { openMaxSeq = max(openMaxSeq ?? 0, maxSeq) } callbacks.openSnapshot(snapshot) case .events(let batch): guard batch.sessionID == openSessionID else { break } let fresh = batch.events.filter { !seenSeq.contains($0.seq) } for e in fresh { seenSeq.insert(e.seq) } + if let maxSeq = batch.events.map(\.seq).max() { openMaxSeq = max(openMaxSeq ?? 0, maxSeq) } if !fresh.isEmpty { callbacks.openEvents(EventBatch(sessionID: batch.sessionID, events: fresh)) } case .approvalRequested(let req): let title = sessions.first { $0.sessionID == req.sessionID }?.title ?? "Approval"