From 1f4a8b785787149b12498569103f3941e43882d5 Mon Sep 17 00:00:00 2001 From: Andrew Blakeslee Moore Date: Mon, 6 Jul 2026 19:41:50 -0700 Subject: [PATCH] Transcript Incremental Projection Nucleic-Session: 0FFD007B-0696-4517-9429-129C7B0FD5AC Co-authored-by: Nucleic --- .../NucleicRemote/Views/SessionDetailView.swift | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/NucleicRemote/NucleicRemote/Views/SessionDetailView.swift b/NucleicRemote/NucleicRemote/Views/SessionDetailView.swift index 0a866ab..26b57fb 100644 --- a/NucleicRemote/NucleicRemote/Views/SessionDetailView.swift +++ b/NucleicRemote/NucleicRemote/Views/SessionDetailView.swift @@ -617,6 +617,16 @@ struct TranscriptList: View { scrollPhase == .interacting || scrollPhase == .decelerating } + /// True from an explicit jump (chevron / send) until the scroll actually reaches the bottom. + /// While set, the unfollow branch is suppressed entirely: phase changes and geometry + /// emissions are delivered on separate callbacks with no ordering guarantee, so a stopping + /// fling could emit one last far-from-bottom reading whose *recorded* phase was still + /// user-driven (`.decelerating`) — landing after the tap's "follow again" and disengaging it, + /// which left the chevron up until a second tap. The latch outlives any stale emission and + /// clears on arrival at the bottom, or the moment the user genuinely grabs the transcript + /// again (`.interacting`), so a mid-jump scroll-away still works. + @State private var jumpingToBottom = false + var body: some View { ScrollViewReader { proxy in ScrollView {