Просмотр исходного кода

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 недель назад: 3
Родитель
Сommit
610f7979d7
1 измененных файлов с 27 добавлено и 2 удалено
  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 {
1564 1564
         }
1565 1565
         DispatchQueue.main.async { [weak self] in
1566 1566
             guard let self else { return }
1567
+            let scroll: () -> Void = {
1568
+                if isUser {
1569
+                    self.scrollChatToBottom()
1570
+                } else {
1571
+                    self.scrollChatToShowTopOfView(host)
1572
+                }
1573
+            }
1567 1574
             if self.prefersReducedMotion {
1568 1575
                 self.updateChatBubbleWidths()
1569
-                self.scrollChatToBottom()
1576
+                scroll()
1570 1577
                 return
1571 1578
             }
1572 1579
             NSAnimationContext.runAnimationGroup { ctx in
@@ -1575,7 +1582,7 @@ final class DashboardView: NSView, NSTextFieldDelegate {
1575 1582
                 host.animator().alphaValue = 1
1576 1583
             }
1577 1584
             self.updateChatBubbleWidths()
1578
-            self.scrollChatToBottom()
1585
+            scroll()
1579 1586
         }
1580 1587
     }
1581 1588
 
@@ -1746,6 +1753,24 @@ final class DashboardView: NSView, NSTextFieldDelegate {
1746 1753
         chatScrollView.reflectScrolledClipView(chatScrollView.contentView)
1747 1754
     }
1748 1755
 
1756
+    /// 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.
1757
+    private func scrollChatToShowTopOfView(_ view: NSView) {
1758
+        chatDocumentView.layoutSubtreeIfNeeded()
1759
+        view.layoutSubtreeIfNeeded()
1760
+        let doc = chatDocumentView
1761
+        let visibleHeight = chatScrollView.contentView.bounds.height
1762
+        let docHeight = doc.bounds.height
1763
+        guard docHeight > 0, visibleHeight > 0 else {
1764
+            scrollChatToBottom()
1765
+            return
1766
+        }
1767
+        let rectInDoc = view.convert(view.bounds, to: doc)
1768
+        let maxY = max(0, docHeight - visibleHeight)
1769
+        let targetY = min(max(0, rectInDoc.minY), maxY)
1770
+        chatScrollView.contentView.scroll(to: NSPoint(x: 0, y: targetY))
1771
+        chatScrollView.reflectScrolledClipView(chatScrollView.contentView)
1772
+    }
1773
+
1749 1774
     private func addInlineChatThinkingRow() {
1750 1775
         removeInlineChatThinkingRow()
1751 1776
         let host = NSView()