Skip to content

Conversation

@yyhhyyyyyy
Copy link
Collaborator

@yyhhyyyyyy yyhhyyyyyy commented Aug 27, 2025

improve auto scroll behavior for fast AI responses

CleanShot.2025-08-27.at.19.49.40.mp4

Summary by CodeRabbit

  • New Features

    • Smooth scrolling when tapping the “scroll to bottom” button for a more polished experience.
    • Auto-scroll to the latest message when a message stream finishes, only if you haven’t scrolled up.
  • Bug Fixes

    • Prevents unintended jumps to the bottom while you’re reading older messages.
    • More reliable scrolling after content resizes to maintain position and readability.
    • Reduces occasional scrolling glitches by ensuring targets exist before scrolling.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Aug 27, 2025

Walkthrough

Implements conditional auto-scroll at stream end in ChatView using nextTick and aboveThreshold; updates MessageList to support smooth/instant scroll via scrollToBottom(smooth = false), adds null guards, and defers certain scrolls with nextTick. The bottom button now triggers smooth scrolling.

Changes

Cohort / File(s) Summary of Changes
Stream end auto-scroll logic
src/renderer/src/components/ChatView.vue
Imported nextTick; after STREAM_EVENTS.END, schedules nextTick to call scrollToBottom(false) only when messageList exists and user is not aboveThreshold.
Message list scrolling behavior
src/renderer/src/components/message/MessageList.vue
Button now calls scrollToBottom(true) for smooth behavior; scrollToBottom signature updated to scrollToBottom(smooth = false) selecting 'smooth' vs 'instant'; added anchor existence guard; deferred certain scrolls via nextTick(() => scrollToBottom()).

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor User
  participant ChatView
  participant MessageList
  participant DOM as ScrollAnchor/DOM

  rect rgba(230,245,255,0.5)
  note over ChatView: Stream completes (STREAM_EVENTS.END)
  ChatView->>ChatView: nextTick(...)
  ChatView->>MessageList: if (!aboveThreshold) scrollToBottom(false)
  MessageList->>DOM: scrollIntoView({ behavior: 'instant' })
  end

  rect rgba(235,255,235,0.5)
  User->>MessageList: Click "Scroll to bottom"
  MessageList->>MessageList: scrollToBottom(true)
  MessageList->>DOM: scrollIntoView({ behavior: 'smooth' })
  end

  rect rgba(255,245,230,0.5)
  note over MessageList: Height change detected
  MessageList->>MessageList: nextTick(() => scrollToBottom())
  MessageList->>DOM: scrollIntoView({ behavior: 'instant' })
  end

  alt Anchor missing
    MessageList-->>MessageList: Guard prevents scroll call
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Poem

A bunny waits where messages flow,
With gentle ticks that ebb and go.
If you’ve not hopped far above, it’ll glide—
Smooth or swift, a tidy ride.
At stream’s soft end, we scroll just so—
Thump-thump! To bottom, down we go. 🐇📜

✨ Finishing Touches
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/scroll-to-bottom-fast-response

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
src/renderer/src/components/message/MessageList.vue (2)

79-79: Avoid creating a new function on each render in the template.

Call the method directly to reduce needless allocations.

-              @click="() => scrollToBottom(true)"
+              @click="scrollToBottom(true)"

333-336: Remove redundant nextTick; scrollToBottom already defers.

You’re wrapping a function that itself wraps in nextTick, causing double deferral.

-        nextTick(() => {
-          scrollToBottom()
-        })
+        scrollToBottom()
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 12b209e and ed93702.

📒 Files selected for processing (2)
  • src/renderer/src/components/ChatView.vue (2 hunks)
  • src/renderer/src/components/message/MessageList.vue (3 hunks)
🧰 Additional context used
📓 Path-based instructions (10)
src/renderer/src/**/*

📄 CodeRabbit inference engine (.cursor/rules/i18n.mdc)

src/renderer/src/**/*: All user-facing strings must use i18n keys (avoid hardcoded user-visible text in code)
Use the 'vue-i18n' framework for all internationalization in the renderer
Ensure all user-visible text in the renderer uses the translation system

Files:

  • src/renderer/src/components/ChatView.vue
  • src/renderer/src/components/message/MessageList.vue
src/renderer/**/*.{vue,ts,js,tsx,jsx}

📄 CodeRabbit inference engine (.cursor/rules/project-structure.mdc)

渲染进程代码放在 src/renderer

Files:

  • src/renderer/src/components/ChatView.vue
  • src/renderer/src/components/message/MessageList.vue
src/renderer/src/**/*.{vue,ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.cursor/rules/vue-best-practices.mdc)

src/renderer/src/**/*.{vue,ts,tsx,js,jsx}: Use the Composition API for better code organization and reusability
Implement proper state management with Pinia
Utilize Vue Router for navigation and route management
Leverage Vue's built-in reactivity system for efficient data handling

Files:

  • src/renderer/src/components/ChatView.vue
  • src/renderer/src/components/message/MessageList.vue
src/renderer/src/**/*.vue

📄 CodeRabbit inference engine (.cursor/rules/vue-best-practices.mdc)

Use scoped styles to prevent CSS conflicts between components

src/renderer/src/**/*.vue: Follow existing component patterns when creating new UI components
Ensure responsive design with Tailwind CSS for new UI components
Add proper error handling and loading states to UI components

Files:

  • src/renderer/src/components/ChatView.vue
  • src/renderer/src/components/message/MessageList.vue
src/renderer/**/*.{ts,tsx,vue}

📄 CodeRabbit inference engine (.cursor/rules/vue-shadcn.mdc)

src/renderer/**/*.{ts,tsx,vue}: Use descriptive variable names with auxiliary verbs (e.g., isLoading, hasError).
Use TypeScript for all code; prefer types over interfaces.
Avoid enums; use const objects instead.
Use arrow functions for methods and computed properties.
Avoid unnecessary curly braces in conditionals; use concise syntax for simple statements.

Files:

  • src/renderer/src/components/ChatView.vue
  • src/renderer/src/components/message/MessageList.vue
src/renderer/**/*.{vue,ts}

📄 CodeRabbit inference engine (.cursor/rules/vue-shadcn.mdc)

Implement lazy loading for routes and components.

Files:

  • src/renderer/src/components/ChatView.vue
  • src/renderer/src/components/message/MessageList.vue
src/renderer/**/*.{ts,vue}

📄 CodeRabbit inference engine (.cursor/rules/vue-shadcn.mdc)

src/renderer/**/*.{ts,vue}: Use useFetch and useAsyncData for data fetching.
Implement SEO best practices using Nuxt's useHead and useSeoMeta.

src/renderer/**/*.{ts,vue}: Use Pinia for frontend state management
From renderer to main, call presenters via the usePresenter.ts composable

Files:

  • src/renderer/src/components/ChatView.vue
  • src/renderer/src/components/message/MessageList.vue
src/**/*.{ts,tsx,vue}

📄 CodeRabbit inference engine (CLAUDE.md)

Use English for all logs and comments

Files:

  • src/renderer/src/components/ChatView.vue
  • src/renderer/src/components/message/MessageList.vue
src/renderer/**/*.vue

📄 CodeRabbit inference engine (CLAUDE.md)

src/renderer/**/*.vue: Use Vue 3 Composition API for all components
Use Tailwind CSS with scoped styles for component styling

Files:

  • src/renderer/src/components/ChatView.vue
  • src/renderer/src/components/message/MessageList.vue
src/renderer/src/**

📄 CodeRabbit inference engine (CLAUDE.md)

Organize UI components by feature under src/renderer/src/

Files:

  • src/renderer/src/components/ChatView.vue
  • src/renderer/src/components/message/MessageList.vue
🧠 Learnings (2)
📚 Learning: 2025-07-23T00:45:57.322Z
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: .cursor/rules/vue-shadcn.mdc:0-0
Timestamp: 2025-07-23T00:45:57.322Z
Learning: Applies to src/renderer/**/*.{vue} : Use <script setup> syntax for concise component definitions.

Applied to files:

  • src/renderer/src/components/ChatView.vue
📚 Learning: 2025-07-23T00:45:57.322Z
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: .cursor/rules/vue-shadcn.mdc:0-0
Timestamp: 2025-07-23T00:45:57.322Z
Learning: Applies to src/renderer/**/*.{vue} : Leverage ref, reactive, and computed for reactive state management.

Applied to files:

  • src/renderer/src/components/ChatView.vue
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build-check (x64)
🔇 Additional comments (2)
src/renderer/src/components/message/MessageList.vue (1)

281-289: Use a standards-compliant scroll behavior ('auto' instead of non-standard 'instant').

scrollIntoView only supports 'auto' | 'smooth'. 'instant' may be ignored. Use 'auto' to disable smoothing.

-      scrollAnchor.value.scrollIntoView({
-        behavior: smooth ? 'smooth' : 'instant',
-        block: 'end'
-      })
+      scrollAnchor.value.scrollIntoView({
+        behavior: smooth ? 'smooth' : 'auto',
+        block: 'end'
+      })

Likely an incorrect or invalid review comment.

src/renderer/src/components/ChatView.vue (1)

24-24: LGTM: nextTick import is necessary for the scheduled auto-scroll.

Comment on lines +71 to +75
nextTick(() => {
if (messageList.value && !messageList.value.aboveThreshold) {
scrollToBottom(false)
}
})
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Bug: aboveThreshold is a Ref — need .value to read it.

As written, the condition always treats the ref object as truthy, preventing auto-scroll.

-    nextTick(() => {
-      if (messageList.value && !messageList.value.aboveThreshold) {
-        scrollToBottom(false)
-      }
-    })
+    nextTick(() => {
+      if (messageList.value && !messageList.value.aboveThreshold?.value) {
+        scrollToBottom(false)
+      }
+    })
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
nextTick(() => {
if (messageList.value && !messageList.value.aboveThreshold) {
scrollToBottom(false)
}
})
nextTick(() => {
if (messageList.value && !messageList.value.aboveThreshold?.value) {
scrollToBottom(false)
}
})
🤖 Prompt for AI Agents
In src/renderer/src/components/ChatView.vue around lines 71–75, the code checks
messageList.value.aboveThreshold but aboveThreshold itself is a Ref, so the
current condition always treats the ref object as truthy and prevents
auto-scroll; update the condition to read the inner value (e.g. verify
messageList.value exists and use messageList.value.aboveThreshold.value) and
keep the null/undefined guard (for example: if (messageList.value &&
!messageList.value.aboveThreshold.value) scrollToBottom(false)); ensure you also
defensively check that aboveThreshold exists before accessing .value.

@zerob13 zerob13 merged commit 8c931c4 into dev Aug 27, 2025
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants