Parcourir la source

Fix chat auto-scroll to show assistant response from start

Keep user messages pinned to the bottom, but align new assistant replies to the top of the visible chat area so long responses open at their beginning instead of the end.

Co-authored-by: Cursor <cursoragent@cursor.com>
AhtashamShahzad1 il y a 2 mois
Parent
commit
610f7979d7
1 fichiers modifiés avec 27 ajouts et 2 suppressions
  1. 27 2
      App for Indeed/Views/DashboardView.swift

+ 27 - 2
App for Indeed/Views/DashboardView.swift

@@ -1564,9 +1564,16 @@ final class DashboardView: NSView, NSTextFieldDelegate {
         }
         }
         DispatchQueue.main.async { [weak self] in
         DispatchQueue.main.async { [weak self] in
             guard let self else { return }
             guard let self else { return }
+            let scroll: () -> Void = {
+                if isUser {
+                    self.scrollChatToBottom()
+                } else {
+                    self.scrollChatToShowTopOfView(host)
+                }
+            }
             if self.prefersReducedMotion {
             if self.prefersReducedMotion {
                 self.updateChatBubbleWidths()
                 self.updateChatBubbleWidths()
-                self.scrollChatToBottom()
+                scroll()
                 return
                 return
             }
             }
             NSAnimationContext.runAnimationGroup { ctx in
             NSAnimationContext.runAnimationGroup { ctx in
@@ -1575,7 +1582,7 @@ final class DashboardView: NSView, NSTextFieldDelegate {
                 host.animator().alphaValue = 1
                 host.animator().alphaValue = 1
             }
             }
             self.updateChatBubbleWidths()
             self.updateChatBubbleWidths()
-            self.scrollChatToBottom()
+            scroll()
         }
         }
     }
     }
 
 
@@ -1746,6 +1753,24 @@ final class DashboardView: NSView, NSTextFieldDelegate {
         chatScrollView.reflectScrolledClipView(chatScrollView.contentView)
         chatScrollView.reflectScrolledClipView(chatScrollView.contentView)
     }
     }
 
 
+    /// Scrolls so the top of `view` sits at the top of the chat clip (flipped document coords). Long assistant replies stay readable from the first line instead of jumping to the end.
+    private func scrollChatToShowTopOfView(_ view: NSView) {
+        chatDocumentView.layoutSubtreeIfNeeded()
+        view.layoutSubtreeIfNeeded()
+        let doc = chatDocumentView
+        let visibleHeight = chatScrollView.contentView.bounds.height
+        let docHeight = doc.bounds.height
+        guard docHeight > 0, visibleHeight > 0 else {
+            scrollChatToBottom()
+            return
+        }
+        let rectInDoc = view.convert(view.bounds, to: doc)
+        let maxY = max(0, docHeight - visibleHeight)
+        let targetY = min(max(0, rectInDoc.minY), maxY)
+        chatScrollView.contentView.scroll(to: NSPoint(x: 0, y: targetY))
+        chatScrollView.reflectScrolledClipView(chatScrollView.contentView)
+    }
+
     private func addInlineChatThinkingRow() {
     private func addInlineChatThinkingRow() {
         removeInlineChatThinkingRow()
         removeInlineChatThinkingRow()
         let host = NSView()
         let host = NSView()