Skip to content

fix: Thread's jump to message action changes main channel scroll position#39092

Merged
dionisio-bot[bot] merged 14 commits intodevelopfrom
fix/jump-msg-erratic-scroll
Mar 10, 2026
Merged

fix: Thread's jump to message action changes main channel scroll position#39092
dionisio-bot[bot] merged 14 commits intodevelopfrom
fix/jump-msg-erratic-scroll

Conversation

@aleksandernsilva
Copy link
Copy Markdown
Contributor

@aleksandernsilva aleksandernsilva commented Feb 26, 2026

Proposed changes (including videos or screenshots)

This PR fixes an issue causing the main channel to scroll when trying to jump to a message outside the viewport.

To address the issue a few adjustments were made:

  • Searching and jumping thread messages does not affect the main channel message list anymore. (getSurroundingMessages is skipped for messages with tmid).
  • RoomHistoryManager.getSurroundingMessages method allows filtering out thread messages. This prevents the scenario where the limit of messages surrounding the main message is taken up by thread messages and improves scroll by giving the appropriate buffer for the lazy loading.
  • Specifically for thread parent messages (tcount > 0) legacyJumpToMessage now calls getSurroundingMessages with showThreadMessages=false.
  • legacyJumpToMessage now calls RoomHistoryManager.getMore when jumping to thread messages if room history is not loaded. This covers the behavior since useGetMore skips this fetch for rooms being accessed through message jumps.
  • Minor reordering of early returns in the useGetMore to reduce unnecessary calculations.
  • Updated the IMessagesModel interface and its MessagesRaw implementation to add a showThreadMessages parameter to findVisibleByRoomIdAfterTimestamp and findVisibleByRoomIdBeforeTimestamp methods. This allows callers to specify whether to include thread messages in results.
  • Modified server-side methods for loading surrounding messages to explicitly pass showThreadMessages = false when querying for messages before and after a given timestamp, ensuring correct message filtering.

Issue(s)

CORE-1184

Steps to test or reproduce

  1. Open a channel with threads
  2. At the top of the channel, click on “Search”
  3. Search for a message that is part of a thread
  4. Find the message and click on “Jump to message”

Further comments

Note

Due to the async nature of the jump to message and the tendency to generate flaky e2e tests it will be implemented in a separate PR

Note

A sparate refactor PR will be opened to deal with the deprecated meteor method still being used.
https://rocketchat.atlassian.net/browse/CORE-1893

Summary by CodeRabbit

  • New Features

    • User-facing option to include or exclude thread messages when loading surrounding conversation history.
  • Improvements

    • Conditionalized surrounding-message loading to avoid unnecessary fetches when navigating to thread messages.
    • Added connectivity and loading guards to prevent redundant layout reads/restores and preserve scroll position.
  • Tests

    • Added end-to-end tests covering both thread-included and thread-excluded loading modes, limits, and error cases.

@dionisio-bot
Copy link
Copy Markdown
Contributor

dionisio-bot bot commented Feb 26, 2026

Looks like this PR is ready to merge! 🎉
If you have any trouble, please check the PR guidelines

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Feb 26, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Adds an optional showThreadMessages flag propagated from client (RoomHistoryManager/legacyJumpToMessage) through the DDP/server method loadSurroundingMessages into message model queries to allow excluding thread messages; also adds DOM/connectivity guards in a scroll hook to avoid layout reads/restores during navigation.

Changes

Cohort / File(s) Summary
Client — history manager
apps/meteor/app/ui-utils/client/lib/RoomHistoryManager.ts
Added optional showThreadMessages parameter to getSurroundingMessages and pass it into the loadSurroundingMessages call.
Client — jump logic
apps/meteor/client/lib/utils/legacyJumpToMessage.ts
Conditionalized calls to surrounding-message loading: when jumping to a thread message, call getSurroundingMessages(..., false) to avoid loading thread replies into main view.
Client — scroll hook
apps/meteor/client/views/room/body/hooks/useGetMore.ts
Added early-return guards and element connectivity checks before reading layout metrics and before restoring scroll after async loads.
Server — DDP method
apps/meteor/server/methods/loadSurroundingMessages.ts
Added optional showThreadMessages parameter to the Meteor method signature and implementation; forwarded flag to message retrieval calls.
Model typings
packages/model-typings/src/models/IMessagesModel.ts
Extended findVisibleByRoomIdAfterTimestamp / findVisibleByRoomIdBeforeTimestamp signatures to accept optional showThreadMessages.
Models — query logic
packages/models/src/models/Messages.ts
Added showThreadMessages param and applied conditional filter to exclude threaded messages when false.
Tests
apps/meteor/tests/end-to-end/api/methods.ts
Added end-to-end tests for loadSurroundingMessages exercising showThreadMessages true/false cases and adjusted imports.
Release notes
.changeset/bright-dots-march.md
Added changeset describing patch bumps and the fix for main channel scroll when jumping to a thread message.

Sequence Diagram(s)

sequenceDiagram
    participant UI as Client UI
    participant RHM as RoomHistoryManager
    participant DDP as DDP Client
    participant SRV as Server Method
    participant MSG as Messages Model

    UI->>RHM: getSurroundingMessages(message, showThreadMessages)
    RHM->>DDP: callWithErrorHandling('loadSurroundingMessages', message, limit, showThreadMessages)
    DDP->>SRV: loadSurroundingMessages(message, limit, showThreadMessages)
    SRV->>MSG: findVisibleByRoomIdBeforeTimestamp(rid, ts, opts, showThreadMessages)
    SRV->>MSG: findVisibleByRoomIdAfterTimestamp(rid, ts, opts, showThreadMessages)
    MSG-->>SRV: messages (threaded messages filtered when showThreadMessages = false)
    SRV-->>DDP: { messages, moreBefore, moreAfter }
    DDP-->>RHM: result
    RHM-->>UI: deliver surrounding messages
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Linked Issues check ❓ Inconclusive The PR addresses CORE-1184 (prevent main channel scroll changes when jumping to thread messages) through the showThreadMessages parameter and conditional logic. However, CORE-1893 (REST endpoint migration) is explicitly deferred to follow-up PRs and not implemented here. Clarify whether this PR fully addresses CORE-1893 or if it's a partial implementation. The PR notes indicate the REST migration is deferred, so consider linking only CORE-1184 or documenting the phased approach.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main objective: fixing the issue where jumping to a thread message changes the main channel scroll position. It directly relates to the primary change in the changeset.
Out of Scope Changes check ✅ Passed All changes are directly related to preventing thread messages from affecting main channel scroll position. The showThreadMessages parameter, conditional loading in legacyJumpToMessage, and related helper method updates all support the core objective of CORE-1184.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


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.

@aleksandernsilva aleksandernsilva force-pushed the fix/jump-msg-erratic-scroll branch from ef13fd0 to d328c8a Compare February 26, 2026 14:49
@changeset-bot
Copy link
Copy Markdown

changeset-bot bot commented Feb 26, 2026

🦋 Changeset detected

Latest commit: 168a569

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 41 packages
Name Type
@rocket.chat/meteor Patch
@rocket.chat/model-typings Patch
@rocket.chat/models Patch
@rocket.chat/apps Patch
@rocket.chat/account-service Patch
@rocket.chat/authorization-service Patch
@rocket.chat/ddp-streamer Patch
@rocket.chat/omnichannel-transcript Patch
@rocket.chat/presence-service Patch
@rocket.chat/queue-worker Patch
@rocket.chat/omnichannel-services Patch
rocketchat-services Patch
@rocket.chat/core-services Patch
@rocket.chat/cron Patch
@rocket.chat/instance-status Patch
@rocket.chat/omni-core Patch
@rocket.chat/server-fetch Patch
@rocket.chat/ui-client Patch
@rocket.chat/abac Patch
@rocket.chat/federation-matrix Patch
@rocket.chat/media-calls Patch
@rocket.chat/omni-core-ee Patch
@rocket.chat/presence Patch
@rocket.chat/network-broker Patch
@rocket.chat/core-typings Patch
@rocket.chat/rest-typings Patch
@rocket.chat/uikit-playground Patch
@rocket.chat/api-client Patch
@rocket.chat/ddp-client Patch
@rocket.chat/fuselage-ui-kit Patch
@rocket.chat/gazzodown Patch
@rocket.chat/http-router Patch
@rocket.chat/livechat Patch
@rocket.chat/ui-avatar Patch
@rocket.chat/ui-contexts Patch
@rocket.chat/ui-voip Patch
@rocket.chat/web-ui-registration Patch
@rocket.chat/license Patch
@rocket.chat/pdf-worker Patch
@rocket.chat/mock-providers Patch
@rocket.chat/ui-video-conf Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@codecov
Copy link
Copy Markdown

codecov bot commented Feb 26, 2026

Codecov Report

❌ Patch coverage is 79.31034% with 6 lines in your changes missing coverage. Please review.
✅ Project coverage is 70.90%. Comparing base (692a891) to head (168a569).
⚠️ Report is 9 commits behind head on develop.

Additional details and impacted files

Impacted file tree graph

@@             Coverage Diff             @@
##           develop   #39092      +/-   ##
===========================================
+ Coverage    70.87%   70.90%   +0.03%     
===========================================
  Files         3196     3196              
  Lines       113288   113309      +21     
  Branches     20531    20535       +4     
===========================================
+ Hits         80294    80347      +53     
+ Misses       30943    30913      -30     
+ Partials      2051     2049       -2     
Flag Coverage Δ
e2e 60.42% <81.25%> (+0.05%) ⬆️
e2e-api 47.96% <100.00%> (+0.19%) ⬆️
unit 71.60% <57.14%> (+0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@aleksandernsilva aleksandernsilva force-pushed the fix/jump-msg-erratic-scroll branch from d328c8a to 66897a8 Compare February 26, 2026 15:23
@aleksandernsilva
Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Feb 26, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Copy Markdown
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 (1)
apps/meteor/client/lib/utils/legacyJumpToMessage.ts (1)

3-3: Remove commented-out import.

This commented-out import is dead code. As per coding guidelines, avoid code comments in the implementation.

🧹 Proposed fix
-// import { flushSync } from 'react-dom';
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/meteor/client/lib/utils/legacyJumpToMessage.ts` at line 3, Remove the
dead commented-out import line "// import { flushSync } from 'react-dom';" from
apps/meteor/client/lib/utils/legacyJumpToMessage.ts so the file contains no
commented implementation imports; simply delete that commented line to comply
with the coding guidelines and keep the module clean.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/meteor/server/methods/loadSurroundingMessages.ts`:
- Around line 29-31: The loadSurroundingMessages method is missing validation
for the showThreadMessages parameter; add a Meteor check for it (e.g.,
check(showThreadMessages, Boolean)) in the loadSurroundingMessages function
alongside the existing checks for message and limit so the parameter is
validated before use and client input can't pass malformed values.

---

Nitpick comments:
In `@apps/meteor/client/lib/utils/legacyJumpToMessage.ts`:
- Line 3: Remove the dead commented-out import line "// import { flushSync }
from 'react-dom';" from apps/meteor/client/lib/utils/legacyJumpToMessage.ts so
the file contains no commented implementation imports; simply delete that
commented line to comply with the coding guidelines and keep the module clean.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5f6b887 and 66897a8.

📒 Files selected for processing (6)
  • apps/meteor/app/ui-utils/client/lib/RoomHistoryManager.ts
  • apps/meteor/client/lib/utils/legacyJumpToMessage.ts
  • apps/meteor/client/views/room/body/hooks/useGetMore.ts
  • apps/meteor/server/methods/loadSurroundingMessages.ts
  • packages/model-typings/src/models/IMessagesModel.ts
  • packages/models/src/models/Messages.ts
📜 Review details
⏰ 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). (2)
  • GitHub Check: 📦 Build Packages
  • GitHub Check: CodeQL-Build
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx,js}

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

**/*.{ts,tsx,js}: Write concise, technical TypeScript/JavaScript with accurate typing in Playwright tests
Avoid code comments in the implementation

Files:

  • apps/meteor/app/ui-utils/client/lib/RoomHistoryManager.ts
  • apps/meteor/client/lib/utils/legacyJumpToMessage.ts
  • packages/model-typings/src/models/IMessagesModel.ts
  • apps/meteor/client/views/room/body/hooks/useGetMore.ts
  • packages/models/src/models/Messages.ts
  • apps/meteor/server/methods/loadSurroundingMessages.ts
🧠 Learnings (5)
📓 Common learnings
Learnt from: ggazzo
Repo: RocketChat/Rocket.Chat PR: 35995
File: apps/meteor/app/api/server/v1/rooms.ts:1107-1112
Timestamp: 2026-02-23T17:53:18.785Z
Learning: In Rocket.Chat PR reviews, maintain strict scope boundaries—when a PR is focused on a specific endpoint (e.g., rooms.favorite), avoid reviewing or suggesting changes to other endpoints that were incidentally refactored (e.g., rooms.invite) unless explicitly requested by maintainers.
Learnt from: juliajforesti
Repo: RocketChat/Rocket.Chat PR: 38493
File: apps/meteor/tests/e2e/page-objects/fragments/home-content.ts:60-82
Timestamp: 2026-02-24T19:36:55.089Z
Learning: In RocketChat/Rocket.Chat e2e tests (apps/meteor/tests/e2e/page-objects/fragments/home-content.ts), thread message preview listitems do not have aria-roledescription="message", so lastThreadMessagePreview locator cannot be scoped to messageListItems (which filters for aria-roledescription="message"). It should remain scoped to page.getByRole('listitem') or mainMessageList.getByRole('listitem').
📚 Learning: 2025-10-28T16:53:42.761Z
Learnt from: ricardogarim
Repo: RocketChat/Rocket.Chat PR: 37205
File: ee/packages/federation-matrix/src/FederationMatrix.ts:296-301
Timestamp: 2025-10-28T16:53:42.761Z
Learning: In the Rocket.Chat federation-matrix integration (ee/packages/federation-matrix/), the createRoom method from rocket.chat/federation-sdk will support a 4-argument signature (userId, roomName, visibility, displayName) in newer versions. Code using this 4-argument call is forward-compatible with planned library updates and should not be flagged as an error.

Applied to files:

  • apps/meteor/app/ui-utils/client/lib/RoomHistoryManager.ts
  • apps/meteor/client/lib/utils/legacyJumpToMessage.ts
📚 Learning: 2025-11-19T18:20:37.116Z
Learnt from: gabriellsh
Repo: RocketChat/Rocket.Chat PR: 37419
File: apps/meteor/server/services/media-call/service.ts:141-141
Timestamp: 2025-11-19T18:20:37.116Z
Learning: In apps/meteor/server/services/media-call/service.ts, the sendHistoryMessage method should use call.caller.id or call.createdBy?.id as the message author, not call.transferredBy?.id. Even for transferred calls, the message should appear in the DM between the two users who are calling each other, not sent by the person who transferred the call.

Applied to files:

  • apps/meteor/app/ui-utils/client/lib/RoomHistoryManager.ts
📚 Learning: 2026-02-24T19:36:55.089Z
Learnt from: juliajforesti
Repo: RocketChat/Rocket.Chat PR: 38493
File: apps/meteor/tests/e2e/page-objects/fragments/home-content.ts:60-82
Timestamp: 2026-02-24T19:36:55.089Z
Learning: In RocketChat/Rocket.Chat e2e tests (apps/meteor/tests/e2e/page-objects/fragments/home-content.ts), thread message preview listitems do not have aria-roledescription="message", so lastThreadMessagePreview locator cannot be scoped to messageListItems (which filters for aria-roledescription="message"). It should remain scoped to page.getByRole('listitem') or mainMessageList.getByRole('listitem').

Applied to files:

  • apps/meteor/client/lib/utils/legacyJumpToMessage.ts
📚 Learning: 2026-02-10T16:32:42.586Z
Learnt from: tassoevan
Repo: RocketChat/Rocket.Chat PR: 38528
File: apps/meteor/client/startup/roles.ts:14-14
Timestamp: 2026-02-10T16:32:42.586Z
Learning: In Rocket.Chat's Meteor client code, DDP streams use EJSON and Date fields arrive as Date objects; do not manually construct new Date() in stream handlers (for example, in sdk.stream()). Only REST API responses return plain JSON where dates are strings, so implement explicit conversion there if needed. Apply this guidance to all TypeScript files under apps/meteor/client to ensure consistent date handling in DDP streams and REST responses.

Applied to files:

  • apps/meteor/client/lib/utils/legacyJumpToMessage.ts
  • apps/meteor/client/views/room/body/hooks/useGetMore.ts
🧬 Code graph analysis (2)
apps/meteor/client/lib/utils/legacyJumpToMessage.ts (1)
apps/meteor/app/ui-utils/client/lib/RoomHistoryManager.ts (1)
  • RoomHistoryManager (341-341)
apps/meteor/client/views/room/body/hooks/useGetMore.ts (1)
apps/meteor/app/ui-utils/client/lib/RoomHistoryManager.ts (3)
  • RoomHistoryManager (341-341)
  • hasMore (260-263)
  • hasMoreNext (265-268)
🔇 Additional comments (8)
packages/model-typings/src/models/IMessagesModel.ts (1)

179-216: LGTM!

The interface additions for showThreadMessages?: boolean on both findVisibleByRoomIdAfterTimestamp and findVisibleByRoomIdBeforeTimestamp are consistent with existing patterns in the interface (e.g., findVisibleByRoomIdNotContainingTypesAndUsers, findVisibleByRoomIdBeforeTimestampNotContainingTypes).

packages/models/src/models/Messages.ts (2)

892-919: LGTM!

The implementation correctly adds the showThreadMessages filter. The $or condition pattern (tmid: { $exists: false } OR tshow: true) is consistent with other methods in this file (e.g., findVisibleByRoomIdNotContainingTypes at lines 873-882).


931-958: LGTM!

Consistent implementation with findVisibleByRoomIdAfterTimestamp. The thread filtering logic is identical and correctly applied.

apps/meteor/server/methods/loadSurroundingMessages.ts (1)

64-86: LGTM!

The showThreadMessages parameter is correctly propagated to both findVisibleByRoomIdBeforeTimestamp and findVisibleByRoomIdAfterTimestamp calls, maintaining consistent filtering behavior for surrounding messages.

apps/meteor/app/ui-utils/client/lib/RoomHistoryManager.ts (1)

312-312: LGTM!

Passing false for showThreadMessages correctly ensures that when loading surrounding messages for the main channel view, thread-only messages are excluded. This aligns with the PR objective of preventing main channel scroll position changes when jumping to threaded messages.

apps/meteor/client/lib/utils/legacyJumpToMessage.ts (1)

23-31: LGTM!

The conditional logic correctly handles the two cases:

  • Thread parent messages (message.tcount truthy): loads surrounding messages to position the view
  • Thread reply messages (no tcount): loads room history if not already loaded, since the thread panel will handle displaying the specific message

This ensures proper message context is loaded without affecting main channel scroll position.

apps/meteor/client/views/room/body/hooks/useGetMore.ts (2)

28-34: LGTM!

The early guards effectively prevent redundant operations:

  • jumpToRef.current check avoids loading during jump-to-message actions
  • isLoading(rid) check prevents concurrent load requests

Moving these checks before getBoundingClientRect is a good optimization that avoids unnecessary layout calculations.


53-56: LGTM!

Good defensive check. Since getMore is async, the element could become disconnected during the await. Checking isConnected before calling flushSync and restoreScroll prevents operating on stale elements.

@aleksandernsilva aleksandernsilva force-pushed the fix/jump-msg-erratic-scroll branch from 173d035 to 614af86 Compare February 26, 2026 18:14
@aleksandernsilva aleksandernsilva marked this pull request as ready for review February 26, 2026 23:15
@aleksandernsilva aleksandernsilva requested review from a team as code owners February 26, 2026 23:15
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

No issues found across 7 files

Copy link
Copy Markdown
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.

🧹 Nitpick comments (1)
apps/meteor/client/lib/utils/legacyJumpToMessage.ts (1)

26-27: Remove the inline implementation comment at Line 26.

This comment restates obvious control flow and conflicts with the repository rule for TS/JS implementation files.

Proposed cleanup
-		} else if (!RoomHistoryManager.isLoaded(message.rid)) {
-			// Load room history if room is not loaded
+		} else if (!RoomHistoryManager.isLoaded(message.rid)) {
 			await RoomHistoryManager.getMore(message.rid);
 		}

As per coding guidelines "Avoid code comments in the implementation".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/meteor/client/lib/utils/legacyJumpToMessage.ts` around lines 26 - 27,
Remove the redundant inline implementation comment that restates control flow
above the call to RoomHistoryManager.getMore in legacyJumpToMessage.ts; edit the
function containing the call to RoomHistoryManager.getMore(message.rid) to
delete the comment line so only the await
RoomHistoryManager.getMore(message.rid); statement remains, keeping all
surrounding logic and behavior unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@apps/meteor/client/lib/utils/legacyJumpToMessage.ts`:
- Around line 26-27: Remove the redundant inline implementation comment that
restates control flow above the call to RoomHistoryManager.getMore in
legacyJumpToMessage.ts; edit the function containing the call to
RoomHistoryManager.getMore(message.rid) to delete the comment line so only the
await RoomHistoryManager.getMore(message.rid); statement remains, keeping all
surrounding logic and behavior unchanged.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 66897a8 and 24b94d2.

📒 Files selected for processing (7)
  • .changeset/bright-dots-march.md
  • apps/meteor/app/ui-utils/client/lib/RoomHistoryManager.ts
  • apps/meteor/client/lib/utils/legacyJumpToMessage.ts
  • apps/meteor/client/views/room/body/hooks/useGetMore.ts
  • apps/meteor/server/methods/loadSurroundingMessages.ts
  • packages/model-typings/src/models/IMessagesModel.ts
  • packages/models/src/models/Messages.ts
✅ Files skipped from review due to trivial changes (1)
  • .changeset/bright-dots-march.md
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/meteor/client/views/room/body/hooks/useGetMore.ts
📜 Review details
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx,js}

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

**/*.{ts,tsx,js}: Write concise, technical TypeScript/JavaScript with accurate typing in Playwright tests
Avoid code comments in the implementation

Files:

  • apps/meteor/client/lib/utils/legacyJumpToMessage.ts
  • apps/meteor/app/ui-utils/client/lib/RoomHistoryManager.ts
  • packages/model-typings/src/models/IMessagesModel.ts
  • packages/models/src/models/Messages.ts
  • apps/meteor/server/methods/loadSurroundingMessages.ts
🧠 Learnings (7)
📓 Common learnings
Learnt from: ggazzo
Repo: RocketChat/Rocket.Chat PR: 35995
File: apps/meteor/app/api/server/v1/rooms.ts:1107-1112
Timestamp: 2026-02-23T17:53:18.785Z
Learning: In Rocket.Chat PR reviews, maintain strict scope boundaries—when a PR is focused on a specific endpoint (e.g., rooms.favorite), avoid reviewing or suggesting changes to other endpoints that were incidentally refactored (e.g., rooms.invite) unless explicitly requested by maintainers.
Learnt from: juliajforesti
Repo: RocketChat/Rocket.Chat PR: 38493
File: apps/meteor/tests/e2e/page-objects/fragments/home-content.ts:60-82
Timestamp: 2026-02-24T19:36:55.089Z
Learning: In RocketChat/Rocket.Chat e2e tests (apps/meteor/tests/e2e/page-objects/fragments/home-content.ts), thread message preview listitems do not have aria-roledescription="message", so lastThreadMessagePreview locator cannot be scoped to messageListItems (which filters for aria-roledescription="message"). It should remain scoped to page.getByRole('listitem') or mainMessageList.getByRole('listitem').
📚 Learning: 2026-02-24T19:36:55.089Z
Learnt from: juliajforesti
Repo: RocketChat/Rocket.Chat PR: 38493
File: apps/meteor/tests/e2e/page-objects/fragments/home-content.ts:60-82
Timestamp: 2026-02-24T19:36:55.089Z
Learning: In RocketChat/Rocket.Chat e2e tests (apps/meteor/tests/e2e/page-objects/fragments/home-content.ts), thread message preview listitems do not have aria-roledescription="message", so lastThreadMessagePreview locator cannot be scoped to messageListItems (which filters for aria-roledescription="message"). It should remain scoped to page.getByRole('listitem') or mainMessageList.getByRole('listitem').

Applied to files:

  • apps/meteor/client/lib/utils/legacyJumpToMessage.ts
  • apps/meteor/app/ui-utils/client/lib/RoomHistoryManager.ts
  • apps/meteor/server/methods/loadSurroundingMessages.ts
📚 Learning: 2026-02-10T16:32:42.586Z
Learnt from: tassoevan
Repo: RocketChat/Rocket.Chat PR: 38528
File: apps/meteor/client/startup/roles.ts:14-14
Timestamp: 2026-02-10T16:32:42.586Z
Learning: In Rocket.Chat's Meteor client code, DDP streams use EJSON and Date fields arrive as Date objects; do not manually construct new Date() in stream handlers (for example, in sdk.stream()). Only REST API responses return plain JSON where dates are strings, so implement explicit conversion there if needed. Apply this guidance to all TypeScript files under apps/meteor/client to ensure consistent date handling in DDP streams and REST responses.

Applied to files:

  • apps/meteor/client/lib/utils/legacyJumpToMessage.ts
📚 Learning: 2026-02-26T19:25:44.063Z
Learnt from: gabriellsh
Repo: RocketChat/Rocket.Chat PR: 38778
File: packages/ui-voip/src/providers/useMediaSession.ts:192-192
Timestamp: 2026-02-26T19:25:44.063Z
Learning: In the Rocket.Chat repository, do not reference Biome lint rules in code review feedback. Biome is not used even if biome.json exists; only reference Biome rules if there is explicit, project-wide usage documented. For TypeScript files, review lint implications without Biome guidance unless the project enables Biome rules.

Applied to files:

  • apps/meteor/client/lib/utils/legacyJumpToMessage.ts
  • apps/meteor/app/ui-utils/client/lib/RoomHistoryManager.ts
  • packages/model-typings/src/models/IMessagesModel.ts
  • packages/models/src/models/Messages.ts
  • apps/meteor/server/methods/loadSurroundingMessages.ts
📚 Learning: 2026-02-26T19:25:44.063Z
Learnt from: gabriellsh
Repo: RocketChat/Rocket.Chat PR: 38778
File: packages/ui-voip/src/providers/useMediaSession.ts:192-192
Timestamp: 2026-02-26T19:25:44.063Z
Learning: In this repository (RocketChat/Rocket.Chat), Biome lint rules are not used even if a biome.json exists. When reviewing TypeScript files (e.g., packages/ui-voip/src/providers/useMediaSession.ts), ensure lint suggestions do not reference Biome-specific rules. Rely on general ESLint/TypeScript lint rules and project conventions instead.

Applied to files:

  • apps/meteor/client/lib/utils/legacyJumpToMessage.ts
  • apps/meteor/app/ui-utils/client/lib/RoomHistoryManager.ts
  • packages/model-typings/src/models/IMessagesModel.ts
  • packages/models/src/models/Messages.ts
  • apps/meteor/server/methods/loadSurroundingMessages.ts
📚 Learning: 2025-11-19T18:20:37.116Z
Learnt from: gabriellsh
Repo: RocketChat/Rocket.Chat PR: 37419
File: apps/meteor/server/services/media-call/service.ts:141-141
Timestamp: 2025-11-19T18:20:37.116Z
Learning: In apps/meteor/server/services/media-call/service.ts, the sendHistoryMessage method should use call.caller.id or call.createdBy?.id as the message author, not call.transferredBy?.id. Even for transferred calls, the message should appear in the DM between the two users who are calling each other, not sent by the person who transferred the call.

Applied to files:

  • apps/meteor/app/ui-utils/client/lib/RoomHistoryManager.ts
📚 Learning: 2025-10-28T16:53:42.761Z
Learnt from: ricardogarim
Repo: RocketChat/Rocket.Chat PR: 37205
File: ee/packages/federation-matrix/src/FederationMatrix.ts:296-301
Timestamp: 2025-10-28T16:53:42.761Z
Learning: In the Rocket.Chat federation-matrix integration (ee/packages/federation-matrix/), the createRoom method from rocket.chat/federation-sdk will support a 4-argument signature (userId, roomName, visibility, displayName) in newer versions. Code using this 4-argument call is forward-compatible with planned library updates and should not be flagged as an error.

Applied to files:

  • apps/meteor/app/ui-utils/client/lib/RoomHistoryManager.ts
  • packages/model-typings/src/models/IMessagesModel.ts
🧬 Code graph analysis (2)
apps/meteor/client/lib/utils/legacyJumpToMessage.ts (2)
apps/meteor/app/ui-utils/client/lib/RoomHistoryManager.ts (1)
  • RoomHistoryManager (341-341)
apps/meteor/client/lib/utils/goToRoomById.ts (1)
  • goToRoomById (16-30)
packages/model-typings/src/models/IMessagesModel.ts (1)
packages/ui-contexts/src/index.ts (1)
  • FindOptions (110-110)
🔇 Additional comments (5)
apps/meteor/client/lib/utils/legacyJumpToMessage.ts (1)

34-35: Good use of showThreadMessages = false for surrounding fetches.

This aligns with the bugfix goal by preventing thread replies from influencing main-channel surrounding-message windows during jump flows.

Also applies to: 40-40

apps/meteor/app/ui-utils/client/lib/RoomHistoryManager.ts (1)

298-313: showThreadMessages propagation is implemented cleanly.

The defaulted parameter and pass-through to loadSurroundingMessages preserve existing behavior while enabling caller control.

packages/models/src/models/Messages.ts (1)

892-919: Thread-visibility filtering is correctly integrated into timestamp queries.

Both before/after methods now expose the same opt-in behavior and apply the expected filter when thread messages are hidden.

Also applies to: 931-958

packages/model-typings/src/models/IMessagesModel.ts (1)

179-184: Interface updates are consistent with model implementation.

The optional showThreadMessages argument keeps compatibility while exposing the new behavior through typings.

Also applies to: 211-216

apps/meteor/server/methods/loadSurroundingMessages.ts (1)

17-17: Server-side threading flag handling looks correct end-to-end.

Validation is in place and the showThreadMessages value is consistently forwarded to both surrounding timestamp queries.

Also applies to: 29-33, 65-70, 82-87

@aleksandernsilva aleksandernsilva force-pushed the fix/jump-msg-erratic-scroll branch from 92c796f to 7824f57 Compare March 3, 2026 22:17
Copy link
Copy Markdown
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.

🧹 Nitpick comments (1)
apps/meteor/tests/end-to-end/api/methods.ts (1)

3451-3472: Refactor repeated sleeps in setup into a typed helper.

Lines 3454, 3457, 3461, 3464, 3467, and 3470 repeat the same timing primitive. A local helper reduces duplication and clarifies intent.

♻️ Proposed refactor
 describe('[`@loadSurroundingMessages`]', () => {
 	let rid: IRoom['_id'];
 	let middleMessage: IMessage;
 	let channelName: string;
+	const waitForMessageOrdering = (): Promise<void> => new Promise((resolve) => setTimeout(resolve, 50));

 	before('create room', (done) => {
 		channelName = `methods-test-channel-${Date.now()}`;
@@
 	before('send messages', async () => {
 		await sendMessage({ message: { rid, msg: 'Message 1' } });

-		await new Promise((resolve) => setTimeout(resolve, 50));
+		await waitForMessageOrdering();
 		await sendMessage({ message: { rid, msg: 'Message 2' } });

-		await new Promise((resolve) => setTimeout(resolve, 50));
+		await waitForMessageOrdering();
 		const msg3 = await sendMessage({ message: { rid, msg: 'Message 3' } });
 		middleMessage = msg3.body.message;

-		await new Promise((resolve) => setTimeout(resolve, 50));
+		await waitForMessageOrdering();
 		const threadMsg = await sendMessage({ message: { rid, msg: 'Message 4 (Thread)' } });

-		await new Promise((resolve) => setTimeout(resolve, 50));
+		await waitForMessageOrdering();
 		await sendMessage({ message: { rid, msg: 'Message 4.1 (Reply)', tmid: threadMsg.body.message._id } });

-		await new Promise((resolve) => setTimeout(resolve, 50));
+		await waitForMessageOrdering();
 		await sendMessage({ message: { rid, msg: 'Message 4.2 (Reply)', tmid: threadMsg.body.message._id } });

-		await new Promise((resolve) => setTimeout(resolve, 50));
+		await waitForMessageOrdering();
 		await sendMessage({ message: { rid, msg: 'Message 5' } });
 	});
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/meteor/tests/end-to-end/api/methods.ts` around lines 3451 - 3472, The
test repeats the same "await new Promise(resolve => setTimeout(resolve, 50))"
timing primitive multiple times inside the before('send messages') setup; define
a small typed helper like wait(ms: number): Promise<void> at the top of the test
file (or within the describe scope) and replace each repeated new
Promise/setTimeout call with await wait(50) to remove duplication and clarify
intent around sendMessage, middleMessage and threadMsg setup.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@apps/meteor/tests/end-to-end/api/methods.ts`:
- Around line 3451-3472: The test repeats the same "await new Promise(resolve =>
setTimeout(resolve, 50))" timing primitive multiple times inside the
before('send messages') setup; define a small typed helper like wait(ms:
number): Promise<void> at the top of the test file (or within the describe
scope) and replace each repeated new Promise/setTimeout call with await wait(50)
to remove duplication and clarify intent around sendMessage, middleMessage and
threadMsg setup.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 92c796f and 7824f57.

📒 Files selected for processing (1)
  • apps/meteor/tests/end-to-end/api/methods.ts
📜 Review details
⏰ 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). (3)
  • GitHub Check: 📦 Build Packages
  • GitHub Check: CodeQL-Build
  • GitHub Check: CodeQL-Build
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx,js}

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

**/*.{ts,tsx,js}: Write concise, technical TypeScript/JavaScript with accurate typing in Playwright tests
Avoid code comments in the implementation

Files:

  • apps/meteor/tests/end-to-end/api/methods.ts
🧠 Learnings (14)
📓 Common learnings
Learnt from: ggazzo
Repo: RocketChat/Rocket.Chat PR: 35995
File: apps/meteor/app/api/server/v1/rooms.ts:1107-1112
Timestamp: 2026-02-23T17:53:18.785Z
Learning: In Rocket.Chat PR reviews, maintain strict scope boundaries—when a PR is focused on a specific endpoint (e.g., rooms.favorite), avoid reviewing or suggesting changes to other endpoints that were incidentally refactored (e.g., rooms.invite) unless explicitly requested by maintainers.
Learnt from: juliajforesti
Repo: RocketChat/Rocket.Chat PR: 38493
File: apps/meteor/tests/e2e/page-objects/fragments/home-content.ts:60-82
Timestamp: 2026-02-24T19:36:55.089Z
Learning: In RocketChat/Rocket.Chat e2e tests (apps/meteor/tests/e2e/page-objects/fragments/home-content.ts), thread message preview listitems do not have aria-roledescription="message", so lastThreadMessagePreview locator cannot be scoped to messageListItems (which filters for aria-roledescription="message"). It should remain scoped to page.getByRole('listitem') or mainMessageList.getByRole('listitem').
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Ensure tests run reliably in parallel without shared state conflicts

Applied to files:

  • apps/meteor/tests/end-to-end/api/methods.ts
📚 Learning: 2026-03-02T16:31:30.612Z
Learnt from: KevLehman
Repo: RocketChat/Rocket.Chat PR: 39250
File: apps/meteor/tests/end-to-end/api/livechat/07-queue.ts:1084-1094
Timestamp: 2026-03-02T16:31:30.612Z
Learning: In E2E API tests at apps/meteor/tests/end-to-end/api/livechat/, using sleep(1000) after updateSetting() or updateEESetting() calls in test setup hooks is acceptable and intentional to allow omnichannel settings to propagate their side effects.

Applied to files:

  • apps/meteor/tests/end-to-end/api/methods.ts
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : All test files must be created in `apps/meteor/tests/e2e/` directory

Applied to files:

  • apps/meteor/tests/end-to-end/api/methods.ts
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Group related tests in the same file

Applied to files:

  • apps/meteor/tests/end-to-end/api/methods.ts
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Utilize Playwright fixtures (`test`, `page`, `expect`) for consistency in test files

Applied to files:

  • apps/meteor/tests/end-to-end/api/methods.ts
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/page-objects/**/*.ts : Utilize existing page objects pattern from `apps/meteor/tests/e2e/page-objects/`

Applied to files:

  • apps/meteor/tests/end-to-end/api/methods.ts
📚 Learning: 2026-02-24T19:36:55.089Z
Learnt from: juliajforesti
Repo: RocketChat/Rocket.Chat PR: 38493
File: apps/meteor/tests/e2e/page-objects/fragments/home-content.ts:60-82
Timestamp: 2026-02-24T19:36:55.089Z
Learning: In RocketChat/Rocket.Chat e2e tests (apps/meteor/tests/e2e/page-objects/fragments/home-content.ts), thread message preview listitems do not have aria-roledescription="message", so lastThreadMessagePreview locator cannot be scoped to messageListItems (which filters for aria-roledescription="message"). It should remain scoped to page.getByRole('listitem') or mainMessageList.getByRole('listitem').

Applied to files:

  • apps/meteor/tests/end-to-end/api/methods.ts
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Use `test.step()` for complex test scenarios to improve organization in Playwright tests

Applied to files:

  • apps/meteor/tests/end-to-end/api/methods.ts
📚 Learning: 2025-12-10T21:00:54.909Z
Learnt from: KevLehman
Repo: RocketChat/Rocket.Chat PR: 37091
File: ee/packages/abac/jest.config.ts:4-7
Timestamp: 2025-12-10T21:00:54.909Z
Learning: Rocket.Chat monorepo: Jest testMatch pattern '<rootDir>/src/**/*.spec.(ts|js|mjs)' is valid in this repo and used across multiple packages (e.g., packages/tools, ee/packages/omnichannel-services). Do not flag it as invalid in future reviews.

Applied to files:

  • apps/meteor/tests/end-to-end/api/methods.ts
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Maintain test isolation between test cases in Playwright tests

Applied to files:

  • apps/meteor/tests/end-to-end/api/methods.ts
📚 Learning: 2026-02-24T19:16:35.307Z
Learnt from: sampaiodiego
Repo: RocketChat/Rocket.Chat PR: 39003
File: apps/meteor/client/lib/chats/flows/sendMessage.ts:39-45
Timestamp: 2026-02-24T19:16:35.307Z
Learning: In apps/meteor/client/lib/chats/flows/sendMessage.ts, when sdk.call('sendMessage', ...) throws an error, the message is intentionally left with temp: true (not deleted or cleaned up) to support a future retry UI feature. This allows users to retry sending failed messages rather than losing them.

Applied to files:

  • apps/meteor/tests/end-to-end/api/methods.ts
📚 Learning: 2026-02-26T19:25:44.063Z
Learnt from: gabriellsh
Repo: RocketChat/Rocket.Chat PR: 38778
File: packages/ui-voip/src/providers/useMediaSession.ts:192-192
Timestamp: 2026-02-26T19:25:44.063Z
Learning: In the Rocket.Chat repository, do not reference Biome lint rules in code review feedback. Biome is not used even if biome.json exists; only reference Biome rules if there is explicit, project-wide usage documented. For TypeScript files, review lint implications without Biome guidance unless the project enables Biome rules.

Applied to files:

  • apps/meteor/tests/end-to-end/api/methods.ts
📚 Learning: 2026-02-26T19:25:44.063Z
Learnt from: gabriellsh
Repo: RocketChat/Rocket.Chat PR: 38778
File: packages/ui-voip/src/providers/useMediaSession.ts:192-192
Timestamp: 2026-02-26T19:25:44.063Z
Learning: In this repository (RocketChat/Rocket.Chat), Biome lint rules are not used even if a biome.json exists. When reviewing TypeScript files (e.g., packages/ui-voip/src/providers/useMediaSession.ts), ensure lint suggestions do not reference Biome-specific rules. Rely on general ESLint/TypeScript lint rules and project conventions instead.

Applied to files:

  • apps/meteor/tests/end-to-end/api/methods.ts
🧬 Code graph analysis (1)
apps/meteor/tests/end-to-end/api/methods.ts (2)
apps/meteor/tests/data/rooms.helper.ts (1)
  • deleteRoom (98-99)
packages/ddp-client/src/legacy/RocketchatSDKLegacy.ts (1)
  • methodCall (186-188)
🪛 Biome (2.4.4)
apps/meteor/tests/end-to-end/api/methods.ts

[error] 3451-3472: Duplicate before hook found.

(lint/suspicious/noDuplicateTestHooks)

🔇 Additional comments (1)
apps/meteor/tests/end-to-end/api/methods.ts (1)

3428-3675: Good coverage for loadSurroundingMessages thread filtering behavior.

This suite validates the key branches (auth, param validation, default windowing, limit handling, and showThreadMessages toggles) and directly supports the regression target.

KevLehman
KevLehman previously approved these changes Mar 4, 2026
Copy link
Copy Markdown
Member

@KevLehman KevLehman left a comment

Choose a reason for hiding this comment

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

BE seems fine

@aleksandernsilva aleksandernsilva force-pushed the fix/jump-msg-erratic-scroll branch from 53b4f43 to 168a569 Compare March 9, 2026 18:35
@tassoevan tassoevan added this to the 8.3.0 milestone Mar 10, 2026
@tassoevan tassoevan added the stat: QA assured Means it has been tested and approved by a company insider label Mar 10, 2026
@dionisio-bot dionisio-bot bot added the stat: ready to merge PR tested and approved waiting for merge label Mar 10, 2026
@dionisio-bot dionisio-bot bot added this pull request to the merge queue Mar 10, 2026
Merged via the queue into develop with commit e206889 Mar 10, 2026
44 checks passed
@dionisio-bot dionisio-bot bot deleted the fix/jump-msg-erratic-scroll branch March 10, 2026 19:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

stat: QA assured Means it has been tested and approved by a company insider stat: ready to merge PR tested and approved waiting for merge type: bug

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants