Skip to content

chore: improve spotlight search#7406

Open
OtavioStasiak wants to merge 12 commits into
developfrom
chore.improve-spotilight-search
Open

chore: improve spotlight search#7406
OtavioStasiak wants to merge 12 commits into
developfrom
chore.improve-spotilight-search

Conversation

@OtavioStasiak

@OtavioStasiak OtavioStasiak commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

Proposed changes

Split search() into searchLocal (fast, DB-only) and searchRemote (spotlight merge over the local data).
Search surfaces now paint local results instantly and re-render once the backend responds, instead of blocking the UI on the network round-trip. Updated RoomsListView spotlight, message composer @/# autocomplete, New Message, and Selected Users, each with a request-id guard so a slower older search can't overwrite a newer one. Added unit tests for the local/remote/merge logic. No change to the existing local-vs-web result parity (deferred as follow-up).

Issue(s)

https://rocketchat.atlassian.net/browse/NATIVE-1105

How to test or reproduce

  1. Open the app with an account that has several rooms/DMs and is connected to a server.
  2. Open spotlight search in the Rooms List and type a query (e.g. a partial username/room name).
    Confirm local matches appear instantly, then remote (spotlight) results fill in.
  3. In a room, type @ and # in the message box — confirm local mentions show immediately, then remote
    results merge in without duplicates.
  4. Repeat in New Message and Select Users search inputs.
  5. Type quickly / change the query mid-search and confirm results don't flicker back to an older search's results.
  6. Run the unit tests: TZ=UTC pnpm test --testPathPattern='app/lib/methods/search.test.ts'.

Screenshots

Before After
before_spotlight after_spotlight

Types of changes

  • Bugfix (non-breaking change which fixes an issue)
  • Improvement (non-breaking change which improves a current function)
  • New feature (non-breaking change which adds functionality)
  • Documentation update (if none of the other choices apply)

Checklist

  • I have read the CONTRIBUTING doc
  • I have signed the CLA
  • Lint and unit tests pass locally with my changes
  • I have added tests that prove my fix is effective or that my feature works (if applicable)
  • I have added necessary documentation (if applicable)
  • Any dependent changes have been merged and published in downstream modules

Further comments

Summary by CodeRabbit

Summary by CodeRabbit

  • Performance Improvements

    • Improved search responsiveness with a local-first flow that shows suggestions immediately, then enriches with remote results.
  • Bug Fixes

    • Prevented older in-flight searches from overwriting newer results.
    • Refined message composer and autocomplete to apply remote updates safely, including “all/here” suggestions when permitted.
  • UI Updates

    • Added/adjusted loading indicators during the remote search phase in message composer, new message view, rooms list search, and selected users.
  • Tests

    • Added unit tests covering local vs remote search, merging, filtering, and deduplication.
    • Updated composer tests to target the updated remote search behavior.

@coderabbitai

coderabbitai Bot commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

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

The search flow is split into searchLocal and searchRemote, and consumers now run local results first, then remote augmentation with stale-response guards. Autocomplete, message composition tests, and room/user search views are updated to use the new two-phase behavior and loading state.

Changes

Two-phase search refactor with stale-guard

Layer / File(s) Summary
searchLocal and searchRemote exports
app/lib/methods/search.ts
Removes the 7-item cap from localSearchSubscription. Adds ISearchParams, searchLocal, and searchRemote; searchRemote starts from localData, derives usernames from local results, and merges Spotlight results.
Test suite for searchLocal, searchRemote, and search
app/lib/methods/search.test.ts
Adds coverage for local query routing, remote Spotlight augmentation, deduplication, exclusion rules, gating, rejection fallback, immutability, and merged search output.
useAutocomplete two-phase search and mention suggestions
app/containers/MessageComposer/hooks/useAutocomplete.ts
Switches autocomplete to searchLocal then searchRemote, adds parseUserRoom, and adds ignore guards plus cleanup for pending async work.
Two-phase search with stale-guard in views and hooks
app/views/NewMessageView/index.tsx, app/views/SelectedUsersView/index.tsx, app/views/RoomsListView/hooks/useSearch.ts
Adds searchId stale-guards, local-first updates, remote follow-up searches, and loading/error state handling in the search consumers.
RoomsListView empty state and loading indicator
app/views/RoomsListView/index.tsx
Adjusts the empty-state branch and adds a footer loading indicator for search results.
MessageComposer test mocks for new search exports
app/containers/MessageComposer/MessageComposer.test.tsx
Replaces the old search mock usage with separate searchLocal and searchRemote mocks in autocomplete tests.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~28 minutes

Suggested reviewers

  • diegolmello
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title is concise and accurately reflects the main change: improving Spotlight search behavior.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

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

Warning

Review ran into problems

🔥 Problems

Errors were encountered while retrieving linked issues.

Errors (1)
  • NATIVE-1105: Request failed with status code 401

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.

@OtavioStasiak OtavioStasiak temporarily deployed to approve_e2e_testing June 17, 2026 21:00 — with GitHub Actions Inactive
@OtavioStasiak OtavioStasiak marked this pull request as ready for review June 17, 2026 21:18
@OtavioStasiak

Copy link
Copy Markdown
Contributor Author

@CodeRabbit review

@coderabbitai

coderabbitai Bot commented Jun 17, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
app/views/RoomsListView/hooks/useSearch.ts (1)

94-96: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Invalidate in-flight requests when stopping search.

stopSearch clears state, but it does not advance searchId. A previously started request can still pass isStale() and dispatch new results after stop.

Suggested patch
 	const stopSearch = useCallback(() => {
+		searchId.current += 1;
 		dispatch({ type: 'STOP_SEARCH' });
 	}, []);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/views/RoomsListView/hooks/useSearch.ts` around lines 94 - 96, The
stopSearch function dispatches STOP_SEARCH but does not advance the searchId,
allowing previously started in-flight requests to still pass isStale() checks
and update state after the search is stopped. Modify the dispatch action in
stopSearch to increment the searchId along with clearing the search state,
ensuring that any pending requests from before the stop will be considered stale
and their results will be ignored.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@app/containers/MessageComposer/hooks/useAutocomplete.ts`:
- Around line 116-135: The stale-guard mechanism using searchId and isStale() is
only applied to the @ and # autocomplete types, but the useAutocomplete hook
handles multiple types including ':', '/', '/preview', and '!'. When users
switch quickly between different autocomplete types, older requests can still
pass the isStale() check and overwrite newer autocomplete state. Move the
searchId increment and isStale() check outside the type-specific conditional so
it applies to all autocomplete types, and ensure every async operation branch
(for each type) includes isStale() checks after all awaited calls to prevent
stale results from overwriting current state.

In `@app/views/RoomsListView/hooks/useSearch.ts`:
- Around line 71-87: The search function in useSearch.ts dispatches
SET_SEARCHING but lacks error handling for the async operations searchLocal and
searchRemote. If either of these rejects, the state remains stuck in a searching
state because the final dispatch is never reached. Wrap the entire async
operation block (from searchLocal through searchRemote and dispatch calls) in a
try/catch block, and in the catch block dispatch an appropriate failure or reset
action to ensure the searching state is set back to false when errors occur,
following the coding guidelines for explicit async error handling.

---

Outside diff comments:
In `@app/views/RoomsListView/hooks/useSearch.ts`:
- Around line 94-96: The stopSearch function dispatches STOP_SEARCH but does not
advance the searchId, allowing previously started in-flight requests to still
pass isStale() checks and update state after the search is stopped. Modify the
dispatch action in stopSearch to increment the searchId along with clearing the
search state, ensuring that any pending requests from before the stop will be
considered stale and their results will be ignored.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 2c670c49-0fdf-41c3-9fbc-14fb4338e608

📥 Commits

Reviewing files that changed from the base of the PR and between 83b18a2 and c7be4c0.

📒 Files selected for processing (7)
  • app/containers/MessageComposer/MessageComposer.test.tsx
  • app/containers/MessageComposer/hooks/useAutocomplete.ts
  • app/lib/methods/search.test.ts
  • app/lib/methods/search.ts
  • app/views/NewMessageView/index.tsx
  • app/views/RoomsListView/hooks/useSearch.ts
  • app/views/SelectedUsersView/index.tsx
📜 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). (15)
  • GitHub Check: E2E Run Android (7) / Android Tests
  • GitHub Check: E2E Run Android (12) / Android Tests
  • GitHub Check: E2E Run Android (8) / Android Tests
  • GitHub Check: E2E Run Android (1) / Android Tests
  • GitHub Check: E2E Run Android (2) / Android Tests
  • GitHub Check: E2E Run Android (10) / Android Tests
  • GitHub Check: E2E Run Android (11) / Android Tests
  • GitHub Check: E2E Run Android (9) / Android Tests
  • GitHub Check: E2E Run Android (3) / Android Tests
  • GitHub Check: E2E Run Android (13) / Android Tests
  • GitHub Check: E2E Run Android (6) / Android Tests
  • GitHub Check: E2E Run Android (5) / Android Tests
  • GitHub Check: E2E Run Android (14) / Android Tests
  • GitHub Check: E2E Run Android (4) / Android Tests
  • GitHub Check: E2E Build iOS / ios-build
🧰 Additional context used
📓 Path-based instructions (6)
**/*.{js,ts,jsx,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{js,ts,jsx,tsx}: Use descriptive names for functions, variables, and classes that clearly convey their purpose
Write comments that explain the 'why' behind code decisions, not the 'what'
Keep functions small and focused on a single responsibility
Use const by default, let when reassignment is needed, and avoid var
Prefer async/await over .then() chains for handling asynchronous operations
Use explicit error handling with try/catch blocks for async operations
Avoid deeply nested code; refactor complex logic into helper functions

Files:

  • app/views/NewMessageView/index.tsx
  • app/containers/MessageComposer/MessageComposer.test.tsx
  • app/views/SelectedUsersView/index.tsx
  • app/lib/methods/search.test.ts
  • app/containers/MessageComposer/hooks/useAutocomplete.ts
  • app/lib/methods/search.ts
  • app/views/RoomsListView/hooks/useSearch.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx}: Use TypeScript for type safety; add explicit type annotations to function parameters and return types
Prefer interfaces over type aliases for defining object shapes in TypeScript
Use enums for sets of related constants rather than magic strings or numbers

Use TypeScript with strict mode enabled

Files:

  • app/views/NewMessageView/index.tsx
  • app/containers/MessageComposer/MessageComposer.test.tsx
  • app/views/SelectedUsersView/index.tsx
  • app/lib/methods/search.test.ts
  • app/containers/MessageComposer/hooks/useAutocomplete.ts
  • app/lib/methods/search.ts
  • app/views/RoomsListView/hooks/useSearch.ts
**/*.{js,jsx,ts,tsx,json}

📄 CodeRabbit inference engine (CLAUDE.md)

Use Prettier formatting with tabs, single quotes, 130 character line width, no trailing commas, and avoid arrow function parentheses

Files:

  • app/views/NewMessageView/index.tsx
  • app/containers/MessageComposer/MessageComposer.test.tsx
  • app/views/SelectedUsersView/index.tsx
  • app/lib/methods/search.test.ts
  • app/containers/MessageComposer/hooks/useAutocomplete.ts
  • app/lib/methods/search.ts
  • app/views/RoomsListView/hooks/useSearch.ts
**/*.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Enforce ESLint rules from @rocket.chat/eslint-config with React, React Native, TypeScript, and Jest plugins

Files:

  • app/views/NewMessageView/index.tsx
  • app/containers/MessageComposer/MessageComposer.test.tsx
  • app/views/SelectedUsersView/index.tsx
  • app/lib/methods/search.test.ts
  • app/containers/MessageComposer/hooks/useAutocomplete.ts
  • app/lib/methods/search.ts
  • app/views/RoomsListView/hooks/useSearch.ts
app/views/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Place screen components in 'app/views/' directory

Files:

  • app/views/NewMessageView/index.tsx
  • app/views/SelectedUsersView/index.tsx
  • app/views/RoomsListView/hooks/useSearch.ts
app/containers/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Place reusable UI components in 'app/containers/' directory

Files:

  • app/containers/MessageComposer/MessageComposer.test.tsx
  • app/containers/MessageComposer/hooks/useAutocomplete.ts
🧠 Learnings (1)
📚 Learning: 2026-04-30T17:07:51.020Z
Learnt from: diegolmello
Repo: RocketChat/Rocket.Chat.ReactNative PR: 7274
File: app/lib/services/voip/MediaCallEvents.ts:0-0
Timestamp: 2026-04-30T17:07:51.020Z
Learning: In this Rocket.Chat React Native codebase, the ESLint rule `no-void: error` is enforced. When you see a promise returned from an async call that is not awaited (a “floating promise”), do not silence it with the `void somePromise()` pattern. Instead, handle the promise explicitly by attaching `.catch(...)` (or otherwise awaiting/handling the error) so unhandled-rejection risks are addressed in a way that satisfies the existing ESLint configuration.

Applied to files:

  • app/views/NewMessageView/index.tsx
  • app/containers/MessageComposer/MessageComposer.test.tsx
  • app/views/SelectedUsersView/index.tsx
  • app/lib/methods/search.test.ts
  • app/containers/MessageComposer/hooks/useAutocomplete.ts
  • app/lib/methods/search.ts
  • app/views/RoomsListView/hooks/useSearch.ts
🔇 Additional comments (11)
app/lib/methods/search.ts (3)

100-121: LGTM!


123-193: LGTM!


195-205: LGTM!

app/lib/methods/search.test.ts (5)

1-48: LGTM!


50-77: LGTM!


79-212: LGTM!


214-260: LGTM!


262-287: LGTM!

app/views/NewMessageView/index.tsx (1)

3-3: LGTM!

Also applies to: 18-18, 31-33, 71-84

app/views/SelectedUsersView/index.tsx (1)

3-3: LGTM!

Also applies to: 25-26, 39-40, 122-135

app/containers/MessageComposer/MessageComposer.test.tsx (1)

18-18: LGTM!

Also applies to: 28-30, 462-463, 547-548

Comment thread app/containers/MessageComposer/hooks/useAutocomplete.ts
Comment thread app/views/RoomsListView/hooks/useSearch.ts

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
app/containers/MessageComposer/hooks/useAutocomplete.ts (1)

234-238: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Guard stale failures in the catch path before mutating state.

Older async requests that fail after cleanup still execute this catch and clear current autocomplete state. That reintroduces stale overwrite behavior through the error path.

Suggested fix
 			} catch (e) {
+				if (ignore) return;
 				log(e);
 				setItems([]);
 				updateAutocompleteVisible(false);
 			}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/containers/MessageComposer/hooks/useAutocomplete.ts` around lines 234 -
238, The catch block in the autocomplete error handling path unconditionally
mutates state with setItems([]) and updateAutocompleteVisible(false), allowing
stale async request failures to overwrite current state after cleanup. Add a
guard condition in the catch block (before calling setItems and
updateAutocompleteVisible) to check if the async request is still valid and not
stale, such as checking an abort signal or cleanup flag. This ensures that only
failures from the current active request will update the autocomplete state,
preventing stale errors from reintroducing old state.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@app/containers/MessageComposer/hooks/useAutocomplete.ts`:
- Around line 234-238: The catch block in the autocomplete error handling path
unconditionally mutates state with setItems([]) and
updateAutocompleteVisible(false), allowing stale async request failures to
overwrite current state after cleanup. Add a guard condition in the catch block
(before calling setItems and updateAutocompleteVisible) to check if the async
request is still valid and not stale, such as checking an abort signal or
cleanup flag. This ensures that only failures from the current active request
will update the autocomplete state, preventing stale errors from reintroducing
old state.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 33c39c43-6d6b-43f3-82b2-5c9fbdff24d7

📥 Commits

Reviewing files that changed from the base of the PR and between c7be4c0 and 2b3e3f4.

📒 Files selected for processing (2)
  • app/containers/MessageComposer/hooks/useAutocomplete.ts
  • app/views/RoomsListView/hooks/useSearch.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • app/views/RoomsListView/hooks/useSearch.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: ESLint and Test / run-eslint-and-test
  • GitHub Check: format
🧰 Additional context used
📓 Path-based instructions (5)
**/*.{js,ts,jsx,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{js,ts,jsx,tsx}: Use descriptive names for functions, variables, and classes that clearly convey their purpose
Write comments that explain the 'why' behind code decisions, not the 'what'
Keep functions small and focused on a single responsibility
Use const by default, let when reassignment is needed, and avoid var
Prefer async/await over .then() chains for handling asynchronous operations
Use explicit error handling with try/catch blocks for async operations
Avoid deeply nested code; refactor complex logic into helper functions

Files:

  • app/containers/MessageComposer/hooks/useAutocomplete.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx}: Use TypeScript for type safety; add explicit type annotations to function parameters and return types
Prefer interfaces over type aliases for defining object shapes in TypeScript
Use enums for sets of related constants rather than magic strings or numbers

Use TypeScript with strict mode enabled

Files:

  • app/containers/MessageComposer/hooks/useAutocomplete.ts
**/*.{js,jsx,ts,tsx,json}

📄 CodeRabbit inference engine (CLAUDE.md)

Use Prettier formatting with tabs, single quotes, 130 character line width, no trailing commas, and avoid arrow function parentheses

Files:

  • app/containers/MessageComposer/hooks/useAutocomplete.ts
**/*.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Enforce ESLint rules from @rocket.chat/eslint-config with React, React Native, TypeScript, and Jest plugins

Files:

  • app/containers/MessageComposer/hooks/useAutocomplete.ts
app/containers/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Place reusable UI components in 'app/containers/' directory

Files:

  • app/containers/MessageComposer/hooks/useAutocomplete.ts
🧠 Learnings (1)
📚 Learning: 2026-04-30T17:07:51.020Z
Learnt from: diegolmello
Repo: RocketChat/Rocket.Chat.ReactNative PR: 7274
File: app/lib/services/voip/MediaCallEvents.ts:0-0
Timestamp: 2026-04-30T17:07:51.020Z
Learning: In this Rocket.Chat React Native codebase, the ESLint rule `no-void: error` is enforced. When you see a promise returned from an async call that is not awaited (a “floating promise”), do not silence it with the `void somePromise()` pattern. Instead, handle the promise explicitly by attaching `.catch(...)` (or otherwise awaiting/handling the error) so unhandled-rejection risks are addressed in a way that satisfies the existing ESLint configuration.

Applied to files:

  • app/containers/MessageComposer/hooks/useAutocomplete.ts

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
app/lib/methods/search.ts (1)

146-150: ⚡ Quick win

Bound the usernames exclusion list before calling spotlight.

At Line 146, remote search now always runs when searchText exists. Combined with uncapped local results, usernames can become very large and hurt latency on busy workspaces. Dedupe + cap the list before sending it upstream.

💡 Suggested change
-	const usernames =
-		rid && filterUsers
-			? (localData as IUserMessage[]).map(sub => sub.username as string)
-			: (localData as ISearchLocal[]).map(sub => sub.name);
+	const usernamesSource =
+		rid && filterUsers
+			? (localData as IUserMessage[]).map(sub => sub.username)
+			: (localData as ISearchLocal[]).map(sub => sub.name);
+	const usernames = Array.from(new Set(usernamesSource.filter((value): value is string => Boolean(value)))).slice(0, 200);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/lib/methods/search.ts` around lines 146 - 150, The usernames list passed
to the spotlight function call can grow unbounded and degrade performance on
busy workspaces. Before passing usernames to the spotlight function in the
Promise.race block, deduplicate the list to remove any duplicate entries and cap
it to a reasonable maximum size (consider using a Set for deduplication and then
slicing or limiting the array to a fixed upper bound). Apply these
transformations to the usernames variable before it is used in the spotlight
function call with searchText and the filter options.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@app/lib/methods/search.ts`:
- Around line 146-150: The usernames list passed to the spotlight function call
can grow unbounded and degrade performance on busy workspaces. Before passing
usernames to the spotlight function in the Promise.race block, deduplicate the
list to remove any duplicate entries and cap it to a reasonable maximum size
(consider using a Set for deduplication and then slicing or limiting the array
to a fixed upper bound). Apply these transformations to the usernames variable
before it is used in the spotlight function call with searchText and the filter
options.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: a9645699-5ffa-432b-96b4-9b53a9317977

📥 Commits

Reviewing files that changed from the base of the PR and between 2b3e3f4 and eeea149.

📒 Files selected for processing (2)
  • app/lib/methods/search.test.ts
  • app/lib/methods/search.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). (1)
  • GitHub Check: ESLint and Test / run-eslint-and-test
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{js,ts,jsx,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{js,ts,jsx,tsx}: Use descriptive names for functions, variables, and classes that clearly convey their purpose
Write comments that explain the 'why' behind code decisions, not the 'what'
Keep functions small and focused on a single responsibility
Use const by default, let when reassignment is needed, and avoid var
Prefer async/await over .then() chains for handling asynchronous operations
Use explicit error handling with try/catch blocks for async operations
Avoid deeply nested code; refactor complex logic into helper functions

Files:

  • app/lib/methods/search.test.ts
  • app/lib/methods/search.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx}: Use TypeScript for type safety; add explicit type annotations to function parameters and return types
Prefer interfaces over type aliases for defining object shapes in TypeScript
Use enums for sets of related constants rather than magic strings or numbers

Use TypeScript with strict mode enabled

Files:

  • app/lib/methods/search.test.ts
  • app/lib/methods/search.ts
**/*.{js,jsx,ts,tsx,json}

📄 CodeRabbit inference engine (CLAUDE.md)

Use Prettier formatting with tabs, single quotes, 130 character line width, no trailing commas, and avoid arrow function parentheses

Files:

  • app/lib/methods/search.test.ts
  • app/lib/methods/search.ts
**/*.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Enforce ESLint rules from @rocket.chat/eslint-config with React, React Native, TypeScript, and Jest plugins

Files:

  • app/lib/methods/search.test.ts
  • app/lib/methods/search.ts
🧠 Learnings (1)
📚 Learning: 2026-04-30T17:07:51.020Z
Learnt from: diegolmello
Repo: RocketChat/Rocket.Chat.ReactNative PR: 7274
File: app/lib/services/voip/MediaCallEvents.ts:0-0
Timestamp: 2026-04-30T17:07:51.020Z
Learning: In this Rocket.Chat React Native codebase, the ESLint rule `no-void: error` is enforced. When you see a promise returned from an async call that is not awaited (a “floating promise”), do not silence it with the `void somePromise()` pattern. Instead, handle the promise explicitly by attaching `.catch(...)` (or otherwise awaiting/handling the error) so unhandled-rejection risks are addressed in a way that satisfies the existing ESLint configuration.

Applied to files:

  • app/lib/methods/search.test.ts
  • app/lib/methods/search.ts
🔇 Additional comments (2)
app/lib/methods/search.ts (1)

56-69: LGTM!

app/lib/methods/search.test.ts (1)

93-100: LGTM!

Also applies to: 253-260

@OtavioStasiak OtavioStasiak changed the title chore: improve spotilight search chore: improve spotlight search Jun 19, 2026

@diegolmello diegolmello left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM. Only missing a before/after video running on open server. Expecting a big change 👀

Comment thread app/views/NewMessageView/index.tsx Outdated
Comment thread app/views/RoomsListView/hooks/useSearch.ts Outdated
Comment thread app/views/RoomsListView/index.tsx Outdated
Comment thread app/views/SelectedUsersView/index.tsx Outdated
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants