Skip to content

Conversation

@BP602
Copy link
Owner

@BP602 BP602 commented Oct 2, 2025

Summary

  • Adds user-configurable scroll placeholder sensitivity control (0-2000, step 50)
  • Optimizes Message component rendering performance with React.memo and memoization
  • Improves scroll performance during high-velocity scrolling

Changes

Settings UI

  • New "Scroll Placeholder Sensitivity" slider in Chatroom settings
  • Range: 0 (disabled) to 2000 (very sensitive)
  • Default: 300 (from DEFAULT_SCROLL_SEEK_VELOCITY)
  • Real-time value display shows current threshold or "Off"

Message Component Performance

  • Wrapped component with React.memo to prevent unnecessary re-renders
  • Converted all event handlers to useCallback for stable references
  • Memoized expensive calculations:
    • userStyle lookup from cosmetics store
    • isSupportEvent type checking
    • shouldHighlightMessage logic
  • Moved badge calculations to parent (MessagesHandler) for better prop stability
  • Reorganized imports and simplified conditional expressions

Constants

  • Added DEFAULT_SCROLL_SEEK_VELOCITY = 300 constant

Test Plan

  • Verify scroll placeholder sensitivity slider appears in Settings > Chatrooms
  • Test slider range (0-2000) with correct step increments (50)
  • Confirm setting value to 0 disables placeholders
  • Test various sensitivity values during fast scrolling
  • Verify Message component renders correctly with optimizations
  • Check that message interactions (copy, reply, pin, delete) still work
  • Verify badges (KickTalk, Donator) display correctly
  • Test context menus and emote right-click functionality
  • Confirm highlight/mention detection still works

Summary by CodeRabbit

  • New Features

    • Added “Scroll Placeholder Sensitivity” setting with slider control to tune scroll-seek behavior.
    • Enhanced message list with scroll-seek placeholders for smoother, more responsive scrolling during fast scrolls.
    • Introduced per-user badge rendering, including donor badges, in message items.
  • Refactor

    • Optimized message rendering with memoization and streamlined handlers to reduce unnecessary re-renders and improve UI responsiveness.
    • Adjusted scrolling configuration for smoother follow behavior and improved viewport handling.

…essage component

- Add configurable scroll placeholder sensitivity slider in settings (0-2000, default 300)
- Allow users to disable placeholders entirely by setting sensitivity to 0
- Optimize Message component with React.memo to prevent unnecessary re-renders
- Convert event handlers to useCallback for stable references
- Memoize userStyle, isSupportEvent, and shouldHighlightMessage calculations
- Move badge calculations (kickTalkBadges, donatorBadges) to MessagesHandler for better performance
- Reorganize imports and simplify conditional expressions
- Add DEFAULT_SCROLL_SEEK_VELOCITY constant
@coderabbitai
Copy link

coderabbitai bot commented Oct 2, 2025

Walkthrough

Adds a configurable scroll-seek velocity setting and placeholder UI, wires scroll-seek configuration into Virtuoso with a placeholder component, introduces per-user badge maps passed to messages, and refactors Message to a memoized component with prop updates and optimized handlers. Adds DEFAULT_SCROLL_SEEK_VELOCITY constant used by settings and message list behavior.

Changes

Cohort / File(s) Summary
Scroll Seek Settings
src/renderer/src/components/Dialogs/Settings/Sections/General.jsx, utils/constants.js
Adds DEFAULT_SCROLL_SEEK_VELOCITY (700). Introduces “Scroll Placeholder Sensitivity” slider (0–2000) controlling chatrooms.scrollSeekVelocityThreshold with clamping, defaulting to the constant, and active state when deviating from default.
Message Component Refactor
src/renderer/src/components/Messages/Message.jsx
Renames component to MessageComponent and exports memo(MessageComponent, areEqual). Replaces existingKickTalkBadges with kickTalkBadges; adds donatorBadges; removes donators. Memoizes styling, handlers, and highlight logic; adds right-click emote handling and support-event rendering updates.
Messages List Scroll-Seek & Badges
src/renderer/src/components/Messages/MessagesHandler.jsx
Adds ScrollSeekPlaceholder component. Implements scrollSeekConfiguration with velocity threshold and caps; integrates with Virtuoso (smooth follow, adjusted overscan/viewport). Introduces per-user kickTalkBadgeMap and donatorBadgeMap; passes derived badges to each message.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor User
  participant Settings as Settings (General.jsx)
  participant Store as SettingsData
  participant Handler as MessagesHandler.jsx
  participant List as Virtuoso
  participant UI as ScrollSeekPlaceholder
  participant Msg as MessageComponent

  User->>Settings: Adjust "Scroll Placeholder Sensitivity" slider
  Settings->>Store: onChange(chatrooms.scrollSeekVelocityThreshold)
  Note right of Store: Defaults to DEFAULT_SCROLL_SEEK_VELOCITY if unset

  Store-->>Handler: read scrollSeekVelocityThreshold
  Handler->>List: set scrollSeekConfiguration (enter/exit, velocity cap)
  User->>List: Fast scroll
  List->>UI: Render placeholder during seek
  List->>Msg: Render full message when seek ends
Loading
sequenceDiagram
  autonumber
  participant Handler as MessagesHandler.jsx
  participant Maps as Badge Maps
  participant Msg as MessageComponent

  Handler->>Maps: Build kickTalkBadgeMap, donatorBadgeMap
  Handler->>Msg: itemContent(..., { kickTalkBadges, donatorBadges })
  Msg->>Msg: Memoized render (areEqual comparator)
  Note right of Msg: Uses memoized styling, highlight checks, handlers
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Poem

I tuned the winds of scroll and speed,
A placeholder sails where lists proceed.
Badges gleam on names that pass,
Memoed whispers through the glass.
Constants set, the sliders sing—
Hop, hop—smooth streams in spring. 🐇✨

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title clearly summarizes the primary change by indicating both the chat scroll performance optimizations and the introduction of a configurable placeholder sensitivity setting, which aligns precisely with the feature additions and refactorings described in the pull request.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.
✨ Finishing touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/chat-scroll-performance

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

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@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

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e76d55e and c712c1a.

📒 Files selected for processing (4)
  • src/renderer/src/components/Dialogs/Settings/Sections/General.jsx (3 hunks)
  • src/renderer/src/components/Messages/Message.jsx (8 hunks)
  • src/renderer/src/components/Messages/MessagesHandler.jsx (4 hunks)
  • utils/constants.js (1 hunks)
🧰 Additional context used
📓 Path-based instructions (6)
**

📄 CodeRabbit inference engine (AGENTS.md)

**: Use electron-vite + React conventions instead of raw Electron patterns
When unsure, consult electron-vite/Electron/Vite docs (Context7) to confirm patterns
Omit empty sections in release notes

Files:

  • utils/constants.js
  • src/renderer/src/components/Dialogs/Settings/Sections/General.jsx
  • src/renderer/src/components/Messages/MessagesHandler.jsx
  • src/renderer/src/components/Messages/Message.jsx
!dist/**

📄 CodeRabbit inference engine (AGENTS.md)

Do not commit built installers/artifacts in dist/

Files:

  • utils/constants.js
  • src/renderer/src/components/Dialogs/Settings/Sections/General.jsx
  • src/renderer/src/components/Messages/MessagesHandler.jsx
  • src/renderer/src/components/Messages/Message.jsx
src/renderer/src/**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

src/renderer/src/**/*.{ts,tsx,js,jsx}: Do not use direct Node APIs in the renderer
Use ipcRenderer.invoke('channel', payload) for request/response from renderer
Use import.meta.env.RENDERER_VITE_* for renderer-scoped config
Avoid bare KT_* env vars in the renderer; use RENDERER_VITE_KT_* instead

Files:

  • src/renderer/src/components/Dialogs/Settings/Sections/General.jsx
  • src/renderer/src/components/Messages/MessagesHandler.jsx
  • src/renderer/src/components/Messages/Message.jsx
src/{renderer/src,preload}/**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

Resolve static assets via Vite URLs (new URL('./asset', import.meta.url))

Files:

  • src/renderer/src/components/Dialogs/Settings/Sections/General.jsx
  • src/renderer/src/components/Messages/MessagesHandler.jsx
  • src/renderer/src/components/Messages/Message.jsx
src/{main,renderer/src}/**/*.{ts,tsx,js,jsx,mts,mjs,cjs}

📄 CodeRabbit inference engine (AGENTS.md)

For fire-and-forget events, use ipcRenderer.send and ipcMain.on with namespaced channels like 'app:settings:get'

Files:

  • src/renderer/src/components/Dialogs/Settings/Sections/General.jsx
  • src/renderer/src/components/Messages/MessagesHandler.jsx
  • src/renderer/src/components/Messages/Message.jsx
src/{main,preload,renderer/src}/**/*.{ts,tsx,js,jsx,mts,mjs,cjs}

📄 CodeRabbit inference engine (AGENTS.md)

Use shared non-secret variables via import.meta.env.VITE_*

Files:

  • src/renderer/src/components/Dialogs/Settings/Sections/General.jsx
  • src/renderer/src/components/Messages/MessagesHandler.jsx
  • src/renderer/src/components/Messages/Message.jsx
🧬 Code graph analysis (3)
src/renderer/src/components/Dialogs/Settings/Sections/General.jsx (3)
utils/constants.js (2)
  • DEFAULT_SCROLL_SEEK_VELOCITY (10-10)
  • DEFAULT_SCROLL_SEEK_VELOCITY (10-10)
src/renderer/src/components/Shared/Tooltip.jsx (3)
  • Tooltip (9-9)
  • TooltipTrigger (11-11)
  • TooltipContent (13-17)
src/renderer/src/components/Shared/Slider.jsx (2)
  • Slider (9-69)
  • value (10-10)
src/renderer/src/components/Messages/MessagesHandler.jsx (5)
src/renderer/src/components/Chat/index.jsx (3)
  • donators (21-21)
  • subscriberBadges (30-30)
  • allStvEmotes (31-31)
src/renderer/src/providers/ChatProvider.jsx (1)
  • settings (4235-4235)
src/preload/index.js (1)
  • settings (219-219)
src/renderer/src/providers/SettingsProvider.jsx (1)
  • settings (8-8)
utils/constants.js (2)
  • DEFAULT_SCROLL_SEEK_VELOCITY (10-10)
  • DEFAULT_SCROLL_SEEK_VELOCITY (10-10)
src/renderer/src/components/Messages/Message.jsx (1)
utils/regex.js (1)
  • createMentionRegex (10-29)
⏰ 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: test-builds (windows-latest)

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting

Comment on lines +27 to +34
const MessageComponent = ({
message,
userChatroomInfo,
chatroomId,
subscriberBadges,
allStvEmotes,
existingKickTalkBadges,
kickTalkBadges,
donatorBadges,

Choose a reason for hiding this comment

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

P1 Badge Update Message callers for new per-user badge props

The Message component now destructures kickTalkBadges and donatorBadges as already‑filtered badge arrays for the rendered user. MessagesHandler was updated to pass those per-user arrays, but other Message callers (e.g. the user dialog and reply thread components) still pass the entire userKickTalkBadges dataset. Since the component no longer filters internally, those dialogs will render every known KickTalk badge (with undefined type/title values) for each message. This regresses badge display in those views; they need to compute the per-user badge array before passing it, or Message should retain the filtering logic.

Useful? React with 👍 / 👎.

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.

1 participant