• Mohamed Aziz Mejri's avatar
    Fixing scrolling behavior in the chat panel (#2040) · d91f9953
    Mohamed Aziz Mejri 提交于
    closes #2038 #2055 
    
    
    
    
    
    
    
    
    <!-- This is an auto-generated description by cubic. -->
    ---
    ## Summary by cubic
    Fixes chat panel scrolling (issue #2038). Auto-scroll only runs while
    streaming and when you’re near the bottom, and a “scroll to bottom”
    button appears when you scroll away.
    
    - **Bug Fixes**
    - Use Virtuoso scrollerRef and a conditional followOutput to control
    auto-scroll based on streaming state and distance from bottom.
    - Track distance and user scrolling to show/hide the button; clean up
    listeners on unmount.
    - Add overflow-y-auto to the messages list and a test-mode fallback that
    uses the container’s scroll events.
    
    <sup>Written for commit 2307453c7f1ad721d6eca9cfc5a9a24224f5da26.
    Summary will update on new commits.</sup>
    
    <!-- End of auto-generated description by cubic. -->
    
    
    
    
    
    
    
    
    
    <!-- greptile_comment -->
    
    <h3>Greptile Summary</h3>
    
    
    Replaced custom scroll tracking logic with Virtuoso's native scroll
    state management to fix the issue where users couldn't scroll up during
    streaming.
    
    **Key Changes:**
    - Removed manual scroll event listeners, timeout refs, and distance
    calculations from `ChatPanel.tsx`
    - Delegated scroll state to Virtuoso's `atBottomStateChange` callback
    which detects when user is within 150px of bottom
    - Converted `followOutput` from always `"smooth"` to a function that
    returns `"smooth"` only when `isStreaming && isAtBottom`, otherwise
    returns `false` to prevent forced scrolling
    - This allows users to scroll up and read earlier messages while the AI
    generates a response, restoring the behavior that existed before PR
    #1993
    
    <h3>Confidence Score: 5/5</h3>
    
    
    - This PR is safe to merge with minimal risk
    - The changes are well-architected and leverage Virtuoso's built-in
    functionality instead of reinventing scroll tracking logic. The fix
    directly addresses the reported issue by making `followOutput`
    conditional on user position, which is the correct approach for this
    library.
    - No files require special attention
    
    <h3>Important Files Changed</h3>
    
    
    
    
    | Filename | Overview |
    |----------|----------|
    | src/components/ChatPanel.tsx | Refactored scroll handling to delegate
    to Virtuoso's native `atBottomStateChange`, removed custom scroll
    tracking logic and manual scroll event listeners |
    | src/components/chat/MessagesList.tsx | Added `atBottomStateChange` and
    conditional `followOutput` to Virtuoso, allowing users to scroll up
    while streaming without forced auto-scroll |
    
    </details>
    
    
    
    <h3>Sequence Diagram</h3>
    
    ```mermaid
    sequenceDiagram
        participant User
        participant ChatPanel
        participant MessagesList
        participant Virtuoso
        
        Note over User,Virtuoso: Streaming Scenario
        User->>MessagesList: Scrolls to read earlier messages
        Virtuoso->>Virtuoso: Detects scroll position > 150px from bottom
        Virtuoso->>MessagesList: atBottomStateChange(false)
        MessagesList->>ChatPanel: onScrollStateChange(false)
        ChatPanel->>ChatPanel: setShowScrollButton(true)
        
        Note over Virtuoso: New message chunk arrives
        Virtuoso->>Virtuoso: followOutput((isAtBottom) => isAtBottom && isStreaming ? "smooth" : false)
        Virtuoso->>Virtuoso: Returns false (user scrolled away)
        Virtuoso->>Virtuoso: Does NOT auto-scroll
        
        Note over User,Virtuoso: User Returns to Bottom
        User->>ChatPanel: Clicks scroll-to-bottom button
        ChatPanel->>MessagesList: scrollToBottom("smooth")
        MessagesList->>Virtuoso: scrollIntoView on messagesEndRef
        Virtuoso->>Virtuoso: Scrolls to bottom
        Virtuoso->>MessagesList: atBottomStateChange(true)
        MessagesList->>ChatPanel: onScrollStateChange(true)
        ChatPanel->>ChatPanel: setShowScrollButton(false)
        
        Note over Virtuoso: Subsequent message chunks
        Virtuoso->>Virtuoso: followOutput returns "smooth" (isAtBottom = true)
        Virtuoso->>Virtuoso: Auto-scrolls smoothly
    ```
    
    <!-- greptile_other_comments_section -->
    
    <!-- /greptile_comment -->
    
    
    <!-- CURSOR_SUMMARY -->
    ---
    
    > [!NOTE]
    > Improves chat scrolling reliability across production (Virtuoso) and
    test modes.
    > 
    > - Integrates `MessagesList` with Virtuoso `scrollerRef` and
    conditional `followOutput` (auto-scroll only when `isStreaming` and
    within ~280px of bottom), with proper listener cleanup
    > - Centralizes scroll tracking in `ChatPanel` using
    `distanceFromBottomRef` and a timeout to debounce user scrolling;
    toggles a "scroll to bottom" button when scrolled away
    > - Adds test-mode behavior: non-virtualized rendering, container scroll
    listeners, and manual auto-scroll near bottom
    > - Ensures smooth scroll-to-bottom after streaming completes; applies
    `overflow-y-auto` and passes new props (`onScrollerRef`,
    `distanceFromBottomRef`, `isUserScrolling`) between components
    > 
    > <sup>Written by [Cursor
    Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
    2307453c7f1ad721d6eca9cfc5a9a24224f5da26. This will update automatically
    on new commits. Configure
    [here](https://cursor.com/dashboard?tab=bugbot).</sup>
    <!-- /CURSOR_SUMMARY -->
    d91f9953
名称
最后提交
最后更新
..
AgentConsentBanner.tsx 正在载入提交数据...
AttachmentsList.tsx 正在载入提交数据...
ChatActivity.tsx 正在载入提交数据...
ChatError.tsx 正在载入提交数据...
ChatErrorBox.tsx 正在载入提交数据...
ChatHeader.tsx 正在载入提交数据...
ChatInput.tsx 正在载入提交数据...
ChatMessage.tsx 正在载入提交数据...
CodeHighlight.tsx 正在载入提交数据...
ContextLimitBanner.tsx 正在载入提交数据...
DeleteChatDialog.tsx 正在载入提交数据...
DragDropOverlay.tsx 正在载入提交数据...
DyadAddDependency.tsx 正在载入提交数据...
DyadAddIntegration.tsx 正在载入提交数据...
DyadCodeSearch.tsx 正在载入提交数据...
DyadCodeSearchResult.tsx 正在载入提交数据...
DyadCodebaseContext.tsx 正在载入提交数据...
DyadDatabaseSchema.tsx 正在载入提交数据...
DyadDelete.tsx 正在载入提交数据...
DyadEdit.tsx 正在载入提交数据...
DyadExecuteSql.tsx 正在载入提交数据...
DyadListFiles.tsx 正在载入提交数据...
DyadMarkdownParser.tsx 正在载入提交数据...
DyadMcpToolCall.tsx 正在载入提交数据...
DyadMcpToolResult.tsx 正在载入提交数据...
DyadOutput.tsx 正在载入提交数据...
DyadProblemSummary.tsx 正在载入提交数据...
DyadRead.tsx 正在载入提交数据...
DyadRename.tsx 正在载入提交数据...
DyadSearchReplace.tsx 正在载入提交数据...
DyadThink.tsx 正在载入提交数据...
DyadTokenSavings.tsx 正在载入提交数据...
DyadWebCrawl.tsx 正在载入提交数据...
DyadWebSearch.tsx 正在载入提交数据...
DyadWebSearchResult.tsx 正在载入提交数据...
DyadWrite.tsx 正在载入提交数据...
FileAttachmentDropdown.tsx 正在载入提交数据...
FixAllErrorsButton.tsx 正在载入提交数据...
HomeChatInput.tsx 正在载入提交数据...
LexicalChatInput.tsx 正在载入提交数据...
MessagesList.tsx 正在载入提交数据...
PromoMessage.tsx 正在载入提交数据...
RenameChatDialog.tsx 正在载入提交数据...
SelectedComponentDisplay.tsx 正在载入提交数据...
SummarizeInNewChatButton.tsx 正在载入提交数据...
TokenBar.tsx 正在载入提交数据...
VersionPane.tsx 正在载入提交数据...
monaco.ts 正在载入提交数据...
stateTypes.ts 正在载入提交数据...
types.d.ts 正在载入提交数据...