Skip to content

refactor: derive isMasterDetail per-component and remove Dimensions provider#7422

Open
diegolmello wants to merge 4 commits into
developfrom
native-886-remove-dimensions-provider
Open

refactor: derive isMasterDetail per-component and remove Dimensions provider#7422
diegolmello wants to merge 4 commits into
developfrom
native-886-remove-dimensions-provider

Conversation

@diegolmello

@diegolmello diegolmello commented Jun 19, 2026

Copy link
Copy Markdown
Member

Proposed changes

The app tracked the master-detail layout flag through a root pipeline: Dimensions.addEventListener in app/index.tsx recomputed isMasterDetail on every window change, wrote it to state.app.isMasterDetail, and fed width/height/scale/fontScale into a DimensionsContext consumed app-wide. Every dimension change triggered a Redux dispatch plus a context update that re-rendered unrelated subtrees.

This removes that pipeline and derives the flag where it's used:

  • New useMasterDetail() hook computes isTablet && width > MIN_WIDTH_MASTER_DETAIL_LAYOUT from useWindowDimensions().
  • Function-component readers call the hook directly.
  • Class components receive the flag via a withMasterDetail HOC in their connect chain (and the three views that needed raw dimensions move to a hook-backed withDimensions).
  • Non-React callers (sagas) read a synchronous getIsMasterDetail() snapshot from Dimensions.get('window'), since hooks can't run there.
  • Deleted state.app.isMasterDetail (field, action, reducer case), the root Dimensions listener, and app/dimensions.tsx.

The flag now reacts to window resize directly instead of a debounced Redux round-trip, and dimension changes no longer fan out through a global context.

Issue(s)

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

How to test or reproduce

  • Tablet (or split view): rotate / resize across the 700px master-detail threshold and confirm the layout switches between MasterDetailStack and InsideStack as before.
  • Phone: confirm single-stack layout is unchanged.
  • Exercise screens that branch on master-detail (RoomView, RoomActionsView, RoomsListView, ProfileView, directory/new-message flows) and confirm navigation targets the correct pane.

Types of changes

  • Improvement (non-breaking change which improves a current function)

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)

Further comments

IBaseScreen.isMasterDetail is kept — it's the prop the HOC injects into class screens, distinct from the removed Redux field.

Summary by CodeRabbit

  • Refactor
    • Improved master/detail layout detection by switching from a stored setting to a live, device-width–based evaluation.
    • Applied the same master/detail behavior consistently across headers, views, message flows, and navigation targets.
    • Updated app initialization to remove reliance on the previous window-dimensions state/context, keeping layout decisions responsive to size changes.
  • Bug Fixes
    • Prevented stale master/detail state by eliminating Redux-driven master/detail updates.
  • Tests
    • Updated reducer/view mocks and removed coverage tied to the old master/detail action.

useMasterDetail derives the master-detail flag per-component from
useWindowDimensions, replacing the Redux state.app.isMasterDetail field.
withMasterDetail/withDimensions bridge the hooks into class components,
injecting the values as props and stripping them from the public prop type.

Claude-Session: https://claude.ai/code/session_01G1Y1nFCGsaMDy5XaYYmGhX
Remove the root Dimensions.addEventListener -> setState pipeline in
app/index.tsx and the DimensionsContext it fed, along with the Redux
state.app.isMasterDetail field, its action, and reducer case. Every reader
now derives the flag locally: function components call useMasterDetail();
class components receive it via the withMasterDetail HOC in their connect
chain. The three views that consumed dimension props move to the
hook-backed withDimensions. Delete app/dimensions.tsx; its only remaining
consumer (List stories) drives fontScale through ResponsiveLayoutContext.

The flag now tracks window resize directly instead of a debounced Redux
round-trip, so split-view changes on tablets apply without a store update.

Claude-Session: https://claude.ai/code/session_01G1Y1nFCGsaMDy5XaYYmGhX
@coderabbitai

coderabbitai Bot commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: e688697d-e28d-4e25-ad33-56e765183f4c

📥 Commits

Reviewing files that changed from the base of the PR and between 687c68b and 9868072.

📒 Files selected for processing (6)
  • app/lib/hooks/useMasterDetail.tsx
  • app/sagas/createChannel.js
  • app/sagas/deepLinking.js
  • app/sagas/login.js
  • app/sagas/messages.js
  • app/sagas/room.js
📜 Recent review details
🧰 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/sagas/deepLinking.js
  • app/sagas/messages.js
  • app/sagas/createChannel.js
  • app/sagas/login.js
  • app/lib/hooks/useMasterDetail.tsx
  • app/sagas/room.js
**/*.{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/sagas/deepLinking.js
  • app/sagas/messages.js
  • app/sagas/createChannel.js
  • app/sagas/login.js
  • app/lib/hooks/useMasterDetail.tsx
  • app/sagas/room.js
**/*.{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/sagas/deepLinking.js
  • app/sagas/messages.js
  • app/sagas/createChannel.js
  • app/sagas/login.js
  • app/lib/hooks/useMasterDetail.tsx
  • app/sagas/room.js
**/*.{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/hooks/useMasterDetail.tsx
🧠 Learnings (2)
📚 Learning: 2026-05-07T13:19:52.152Z
Learnt from: diegolmello
Repo: RocketChat/Rocket.Chat.ReactNative PR: 7304
File: app/sagas/deepLinking.js:237-243
Timestamp: 2026-05-07T13:19:52.152Z
Learning: In this codebase’s Redux-Saga usage, remember that `yield put(action)` dispatches through the Redux store synchronously, and any saga(s) that synchronously react via action listeners (and synchronous `put` chains) will run to completion before the calling saga resumes at its next `yield`. As a result, within a single saga there is no scheduler interleaving between a `yield select(...)` and a subsequent `yield take(...)` at the next `yield` point, so a check-then-take pattern like `const state = yield select(...); if (state !== TARGET) { yield take(a => a.type === TARGET); }` is safe from TOCTOU races under the synchronous `put`/take model described above.

Applied to files:

  • app/sagas/deepLinking.js
  • app/sagas/messages.js
  • app/sagas/createChannel.js
  • app/sagas/login.js
  • app/sagas/room.js
📚 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/hooks/useMasterDetail.tsx
🔇 Additional comments (6)
app/lib/hooks/useMasterDetail.tsx (1)

2-18: LGTM!

app/sagas/createChannel.js (1)

11-11: LGTM!

Also applies to: 85-85

app/sagas/deepLinking.js (1)

21-21: LGTM!

Also applies to: 70-70, 270-270

app/sagas/login.js (1)

27-27: LGTM!

Also applies to: 58-58

app/sagas/messages.js (1)

1-1: LGTM!

Also applies to: 8-8, 19-19

app/sagas/room.js (1)

2-2: LGTM!

Also applies to: 14-14, 70-70, 149-149


Walkthrough

Introduces useMasterDetail hook and withMasterDetail/withDimensions HOCs in app/lib/hooks/. Removes isMasterDetail from the Redux IApp state, ISetMasterDetail action, and SET_MASTER_DETAIL action type. Removes DimensionsContext from the app root. Migrates all ~50 consumers across views, containers, and sagas to the new hook or HOC pattern.

Changes

isMasterDetail Redux-to-hook migration

Layer / File(s) Summary
New useMasterDetail and withDimensions hooks/HOCs
app/lib/hooks/useMasterDetail.tsx, app/lib/hooks/withDimensions.tsx
useMasterDetail computes a boolean from isTablet and window width vs MIN_WIDTH_MASTER_DETAIL_LAYOUT. getIsMasterDetail provides a non-hook variant for sagas. withMasterDetail HOC injects that value and hoists statics. withDimensions HOC injects useWindowDimensions fields and hoists statics.
Remove isMasterDetail from Redux actions and reducer
app/actions/actionsTypes.ts, app/actions/app.ts, app/reducers/app.ts, app/reducers/app.test.ts, app/views/ProfileView/index.test.tsx
Removes SET_MASTER_DETAIL action type, ISetMasterDetail interface, setMasterDetail action creator, isMasterDetail field from IApp and initialState, the corresponding reducer case, and unit tests.
Remove DimensionsContext from app root
app/index.tsx, app/containers/List/List.stories.tsx
Root's IState loses dimension fields; constructor drops Dimensions reads and tablet setup; render() removes the DimensionsContext.Provider wrapper. List.stories.tsx switches FontStory from DimensionsContext.Provider to ResponsiveLayoutContext.Provider.
Functional components migrated to useMasterDetail hook
app/AppContainer.tsx, app/containers/..., app/ee/omnichannel/..., app/views/... (40+ files)
All functional component consumers replace useAppSelector(state => state.app.isMasterDetail) with a direct useMasterDetail() call.
Class components and connected views migrated to withMasterDetail HOC
app/containers/InAppNotification/NotifierComponent.tsx, app/containers/MessageActions/index.tsx, app/views/MessagesView/index.tsx, app/views/RoomView/..., app/views/RoomActionsView/index.tsx, app/views/SearchMessagesView/index.tsx, app/views/SelectListView.tsx, app/views/TeamChannelsView.tsx, app/views/ThreadMessagesView/index.tsx
mapStateToProps no longer provides isMasterDetail; components are wrapped with withMasterDetail in their default export HOC chain. withDimensions import paths updated in RoomActionsView, RoomView, and TeamChannelsView.
Sagas migrated to use getIsMasterDetail helper
app/sagas/createChannel.js, app/sagas/deepLinking.js, app/sagas/login.js, app/sagas/messages.js, app/sagas/room.js
Sagas replace yield select(state => state.app.isMasterDetail) with synchronous getIsMasterDetail() calls; redux-saga's select effect import removed where no longer used.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Suggested reviewers

  • OtavioStasiak
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 25.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title clearly and concisely summarizes the main refactoring: shifting from a global Redux/context-based isMasterDetail tracking to per-component derivation and removing the Dimensions provider.
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.

✏️ 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-886: 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 and usage tips.

connect(..., { forwardRef: true }) wraps forwardRef screens (MessageActions,
JoinCode) whose parents hold a ref and call imperative methods. The HOC sat
between connect and the component as a plain function component, swallowing
the ref. Make both HOCs forwardRef so the ref reaches the wrapped component.

Claude-Session: https://claude.ai/code/session_01G1Y1nFCGsaMDy5XaYYmGhX
…ield

Sagas can't call the useMasterDetail hook, and the Redux state.app.isMasterDetail
field no longer exists. Add getIsMasterDetail(), a synchronous snapshot from
Dimensions.get('window'), and use it in the createChannel, deepLinking, login,
room, and messages sagas so master-detail navigation keeps working.

Claude-Session: https://claude.ai/code/session_01G1Y1nFCGsaMDy5XaYYmGhX
@diegolmello diegolmello requested a deployment to approve_e2e_testing June 19, 2026 21:40 — with GitHub Actions Waiting
@diegolmello

Copy link
Copy Markdown
Member Author

Review summary

Reviewed the full diff (≈50 readers migrated, 2 HOCs added, root pipeline + app/dimensions.tsx removed). tsc --noEmit clean, ESLint clean (only pre-existing React-hooks/complexity warnings, none introduced here), TZ=UTC pnpm test 1615/1615 green.

Two correctness issues were found and fixed while reviewing:

1. Refs were swallowed by the new HOCs. withMasterDetail/withDimensions started as plain function components, so a parent's ref never reached the wrapped component. RoomView holds refs to MessageActions and JoinCode and calls imperative methods on them, so those refs would have been null. Fixed by making both HOCs use forwardRef and pass the ref through (and hoistNonReactStatics to preserve navigationOptions).

2. Five sagas still read the removed Redux field. createChannel, deepLinking, login, room, and messages read state.app.isMasterDetail, which now returns undefined — master-detail navigation (goRoom/navigateToRoom/popToTop) would silently get a falsy value. Sagas can't call the hook, so they now read a synchronous getIsMasterDetail() snapshot from Dimensions.get('window'). This is behaviorally equivalent to (slightly fresher than) the old debounced Redux value.

Nit

No dedicated unit test for useMasterDetail/the HOCs. Behavior is covered indirectly by existing view and reducer tests; a focused test would lock the threshold formula down but isn't blocking.

Otherwise the migration is consistent and the refactor preserves behavior. LGTM.

@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/AddExistingChannelView/index.tsx (1)

47-52: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Header options do not react to master-detail toggles.

isMasterDetail now changes with window width, but useLayoutEffect only depends on selected.length. Crossing the tablet threshold will not refresh headerLeft until selection changes.

Suggested fix
-	useLayoutEffect(() => {
-		setHeader();
-	}, [selected.length]);
+	useLayoutEffect(() => {
+		setHeader();
+	}, [selected.length, isMasterDetail, navigation]);
🤖 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/AddExistingChannelView/index.tsx` around lines 47 - 52, The
useLayoutEffect hook that calls setHeader() only includes selected.length in its
dependency array, but the effect also depends on isMasterDetail which changes
when the window crosses the tablet threshold. Add isMasterDetail to the
dependency array of the useLayoutEffect hook so that setHeader() is properly
invoked whenever either selected.length or isMasterDetail changes, ensuring
header options update correctly during master-detail mode toggles.
🧹 Nitpick comments (2)
app/views/UserNotificationPreferencesView/index.tsx (1)

33-35: Select the primitive id directly to avoid unnecessary rerenders.

The current selector wraps the result in an object literal, creating a new reference on every store update. Since useAppSelector uses reference equality, this triggers rerenders even when the userId value hasn't changed. Select the primitive directly instead:

Suggested change
-	const { userId } = useAppSelector(state => ({
-		userId: getUserSelector(state).id
-	}));
+	const userId = useAppSelector(state => getUserSelector(state).id);
🤖 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/UserNotificationPreferencesView/index.tsx` around lines 33 - 35,
The useAppSelector call in the UserNotificationPreferencesView is wrapping the
userId value in an object literal, which creates a new reference on every store
update even when the userId itself hasn't changed, triggering unnecessary
rerenders. Instead of selecting an object and destructuring it, modify the
selector to return the primitive id value directly by removing the object
wrapper and calling getUserSelector(state).id directly as the return value of
the useAppSelector callback, then assign it directly to userId without
destructuring.
app/views/SelectListView.tsx (1)

211-213: ⚡ Quick win

Avoid a no-op mapStateToProps subscription.

connect(() => ({})) subscribes this component to store updates without consuming state. Prefer connect(null) or remove connect entirely if no dispatch props are needed.

Proposed change
-const mapStateToProps = () => ({});
-
-export default connect(mapStateToProps)(withTheme(withMasterDetail(SelectListView)));
+export default withTheme(withMasterDetail(SelectListView));
🤖 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/SelectListView.tsx` around lines 211 - 213, The mapStateToProps
function in SelectListView is a no-op that returns an empty object and creates
an unnecessary Redux subscription. Replace the mapStateToProps function call in
the connect() invocation with null instead, by changing connect(mapStateToProps)
to connect(null), or remove the connect wrapper entirely if no dispatch props
are required. This eliminates the unnecessary store subscription and simplifies
the component definition.
🤖 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/views/AccessibilityAndAppearanceView/index.tsx`:
- Line 25: The useLayoutEffect hook that sets up headerLeft needs to be updated
to respond to changes in the isMasterDetail value. Add isMasterDetail to the
dependency array of the useLayoutEffect hook (the one that configures the
navigation header options) so that the effect re-runs whenever the master-detail
mode changes due to resize, rotation, or other layout changes. This ensures that
headerLeft and other header options remain synchronized with the current
master-detail state.

In `@app/views/RoomsListView/components/TabletHeader.tsx`:
- Around line 8-13: In the TabletHeader component, replace the `any` type
parameters in the useNavigation and useRoute hooks with proper TypeScript types.
Import NativeStackNavigationProp and RouteProp from
`@react-navigation/native-stack` and MasterDetailInsideStackParamList from the
navigation types, then apply these types to the respective hooks. Additionally,
add an explicit return type annotation of ReactElement | null to the
TabletHeader function declaration to ensure proper type safety.

---

Outside diff comments:
In `@app/views/AddExistingChannelView/index.tsx`:
- Around line 47-52: The useLayoutEffect hook that calls setHeader() only
includes selected.length in its dependency array, but the effect also depends on
isMasterDetail which changes when the window crosses the tablet threshold. Add
isMasterDetail to the dependency array of the useLayoutEffect hook so that
setHeader() is properly invoked whenever either selected.length or
isMasterDetail changes, ensuring header options update correctly during
master-detail mode toggles.

---

Nitpick comments:
In `@app/views/SelectListView.tsx`:
- Around line 211-213: The mapStateToProps function in SelectListView is a no-op
that returns an empty object and creates an unnecessary Redux subscription.
Replace the mapStateToProps function call in the connect() invocation with null
instead, by changing connect(mapStateToProps) to connect(null), or remove the
connect wrapper entirely if no dispatch props are required. This eliminates the
unnecessary store subscription and simplifies the component definition.

In `@app/views/UserNotificationPreferencesView/index.tsx`:
- Around line 33-35: The useAppSelector call in the
UserNotificationPreferencesView is wrapping the userId value in an object
literal, which creates a new reference on every store update even when the
userId itself hasn't changed, triggering unnecessary rerenders. Instead of
selecting an object and destructuring it, modify the selector to return the
primitive id value directly by removing the object wrapper and calling
getUserSelector(state).id directly as the return value of the useAppSelector
callback, then assign it directly to userId without destructuring.
🪄 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: d1f6a55b-f099-4c25-9b69-77775209d6bd

📥 Commits

Reviewing files that changed from the base of the PR and between 6bbf88a and 687c68b.

📒 Files selected for processing (62)
  • app/AppContainer.tsx
  • app/actions/actionsTypes.ts
  • app/actions/app.ts
  • app/containers/Header/index.tsx
  • app/containers/InAppNotification/IncomingCallNotification/index.tsx
  • app/containers/InAppNotification/NotifierComponent.tsx
  • app/containers/List/List.stories.tsx
  • app/containers/MediaCallHeader/components/Content.tsx
  • app/containers/MessageActions/index.tsx
  • app/containers/MessageComposer/components/Buttons/ActionsButton.tsx
  • app/containers/MessageComposer/components/ComposerInput.tsx
  • app/containers/RoomHeader/RoomHeader.tsx
  • app/containers/TwoFactor/index.tsx
  • app/containers/markdown/components/mentions/Hashtag.tsx
  • app/dimensions.tsx
  • app/ee/omnichannel/containers/OmnichannelHeader/index.tsx
  • app/ee/omnichannel/views/QueueListView.tsx
  • app/index.tsx
  • app/lib/hooks/useMasterDetail.tsx
  • app/lib/hooks/withDimensions.tsx
  • app/reducers/app.test.ts
  • app/reducers/app.ts
  • app/views/AccessibilityAndAppearanceView/index.tsx
  • app/views/AddChannelTeamView.tsx
  • app/views/AddExistingChannelView/index.tsx
  • app/views/AdminPanelView/index.tsx
  • app/views/CallView/components/CallButtons.tsx
  • app/views/CannedResponseDetail.tsx
  • app/views/CannedResponsesListView/index.tsx
  • app/views/CloseLivechatView.tsx
  • app/views/CreateDiscussionView/index.tsx
  • app/views/DirectoryView/index.tsx
  • app/views/DiscussionsView/index.tsx
  • app/views/MessagesView/index.tsx
  • app/views/NewMessageView/index.tsx
  • app/views/NotificationPreferencesView/index.tsx
  • app/views/ProfileView/index.test.tsx
  • app/views/ProfileView/index.tsx
  • app/views/ReportUserView/index.tsx
  • app/views/RoomActionsView/index.tsx
  • app/views/RoomInfoView/index.tsx
  • app/views/RoomMembersView/index.tsx
  • app/views/RoomView/JoinCode.tsx
  • app/views/RoomView/RightButtons.tsx
  • app/views/RoomView/components/EncryptedRoom.tsx
  • app/views/RoomView/index.tsx
  • app/views/RoomsListView/components/ListHeader.tsx
  • app/views/RoomsListView/components/ServersList.tsx
  • app/views/RoomsListView/components/TabletHeader.tsx
  • app/views/RoomsListView/hooks/useHeader.tsx
  • app/views/RoomsListView/index.tsx
  • app/views/SearchMessagesView/index.tsx
  • app/views/SelectListView.tsx
  • app/views/SettingsView/index.tsx
  • app/views/SidebarView/components/Admin.tsx
  • app/views/SidebarView/components/Profile.tsx
  • app/views/SidebarView/components/Stacks.tsx
  • app/views/SidebarView/components/SupportedVersionsWarnItem.tsx
  • app/views/StatusView/index.tsx
  • app/views/TeamChannelsView.tsx
  • app/views/ThreadMessagesView/index.tsx
  • app/views/UserNotificationPreferencesView/index.tsx
💤 Files with no reviewable changes (3)
  • app/dimensions.tsx
  • app/reducers/app.ts
  • app/actions/actionsTypes.ts
📜 Review details
🧰 Additional context used
📓 Path-based instructions (9)
**/*.{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/MediaCallHeader/components/Content.tsx
  • app/containers/Header/index.tsx
  • app/ee/omnichannel/containers/OmnichannelHeader/index.tsx
  • app/views/RoomsListView/components/TabletHeader.tsx
  • app/views/SidebarView/components/SupportedVersionsWarnItem.tsx
  • app/views/SelectListView.tsx
  • app/views/RoomsListView/components/ListHeader.tsx
  • app/views/NotificationPreferencesView/index.tsx
  • app/views/AddChannelTeamView.tsx
  • app/views/ProfileView/index.test.tsx
  • app/views/NewMessageView/index.tsx
  • app/lib/hooks/withDimensions.tsx
  • app/containers/InAppNotification/IncomingCallNotification/index.tsx
  • app/views/RoomsListView/components/ServersList.tsx
  • app/containers/MessageComposer/components/Buttons/ActionsButton.tsx
  • app/views/AccessibilityAndAppearanceView/index.tsx
  • app/ee/omnichannel/views/QueueListView.tsx
  • app/views/ReportUserView/index.tsx
  • app/containers/MessageComposer/components/ComposerInput.tsx
  • app/views/SidebarView/components/Profile.tsx
  • app/views/SettingsView/index.tsx
  • app/containers/TwoFactor/index.tsx
  • app/views/CloseLivechatView.tsx
  • app/views/CallView/components/CallButtons.tsx
  • app/views/StatusView/index.tsx
  • app/views/AdminPanelView/index.tsx
  • app/views/SearchMessagesView/index.tsx
  • app/containers/List/List.stories.tsx
  • app/views/RoomsListView/index.tsx
  • app/views/ProfileView/index.tsx
  • app/views/CannedResponsesListView/index.tsx
  • app/views/RoomView/JoinCode.tsx
  • app/lib/hooks/useMasterDetail.tsx
  • app/views/SidebarView/components/Admin.tsx
  • app/views/SidebarView/components/Stacks.tsx
  • app/AppContainer.tsx
  • app/views/RoomView/components/EncryptedRoom.tsx
  • app/reducers/app.test.ts
  • app/views/MessagesView/index.tsx
  • app/containers/markdown/components/mentions/Hashtag.tsx
  • app/containers/RoomHeader/RoomHeader.tsx
  • app/views/RoomMembersView/index.tsx
  • app/views/DiscussionsView/index.tsx
  • app/views/AddExistingChannelView/index.tsx
  • app/views/CannedResponseDetail.tsx
  • app/views/CreateDiscussionView/index.tsx
  • app/views/UserNotificationPreferencesView/index.tsx
  • app/views/RoomsListView/hooks/useHeader.tsx
  • app/containers/InAppNotification/NotifierComponent.tsx
  • app/views/RoomInfoView/index.tsx
  • app/views/RoomView/RightButtons.tsx
  • app/views/TeamChannelsView.tsx
  • app/views/DirectoryView/index.tsx
  • app/containers/MessageActions/index.tsx
  • app/views/RoomActionsView/index.tsx
  • app/views/RoomView/index.tsx
  • app/actions/app.ts
  • app/views/ThreadMessagesView/index.tsx
  • app/index.tsx
**/*.{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/MediaCallHeader/components/Content.tsx
  • app/containers/Header/index.tsx
  • app/ee/omnichannel/containers/OmnichannelHeader/index.tsx
  • app/views/RoomsListView/components/TabletHeader.tsx
  • app/views/SidebarView/components/SupportedVersionsWarnItem.tsx
  • app/views/SelectListView.tsx
  • app/views/RoomsListView/components/ListHeader.tsx
  • app/views/NotificationPreferencesView/index.tsx
  • app/views/AddChannelTeamView.tsx
  • app/views/ProfileView/index.test.tsx
  • app/views/NewMessageView/index.tsx
  • app/lib/hooks/withDimensions.tsx
  • app/containers/InAppNotification/IncomingCallNotification/index.tsx
  • app/views/RoomsListView/components/ServersList.tsx
  • app/containers/MessageComposer/components/Buttons/ActionsButton.tsx
  • app/views/AccessibilityAndAppearanceView/index.tsx
  • app/ee/omnichannel/views/QueueListView.tsx
  • app/views/ReportUserView/index.tsx
  • app/containers/MessageComposer/components/ComposerInput.tsx
  • app/views/SidebarView/components/Profile.tsx
  • app/views/SettingsView/index.tsx
  • app/containers/TwoFactor/index.tsx
  • app/views/CloseLivechatView.tsx
  • app/views/CallView/components/CallButtons.tsx
  • app/views/StatusView/index.tsx
  • app/views/AdminPanelView/index.tsx
  • app/views/SearchMessagesView/index.tsx
  • app/containers/List/List.stories.tsx
  • app/views/RoomsListView/index.tsx
  • app/views/ProfileView/index.tsx
  • app/views/CannedResponsesListView/index.tsx
  • app/views/RoomView/JoinCode.tsx
  • app/lib/hooks/useMasterDetail.tsx
  • app/views/SidebarView/components/Admin.tsx
  • app/views/SidebarView/components/Stacks.tsx
  • app/AppContainer.tsx
  • app/views/RoomView/components/EncryptedRoom.tsx
  • app/reducers/app.test.ts
  • app/views/MessagesView/index.tsx
  • app/containers/markdown/components/mentions/Hashtag.tsx
  • app/containers/RoomHeader/RoomHeader.tsx
  • app/views/RoomMembersView/index.tsx
  • app/views/DiscussionsView/index.tsx
  • app/views/AddExistingChannelView/index.tsx
  • app/views/CannedResponseDetail.tsx
  • app/views/CreateDiscussionView/index.tsx
  • app/views/UserNotificationPreferencesView/index.tsx
  • app/views/RoomsListView/hooks/useHeader.tsx
  • app/containers/InAppNotification/NotifierComponent.tsx
  • app/views/RoomInfoView/index.tsx
  • app/views/RoomView/RightButtons.tsx
  • app/views/TeamChannelsView.tsx
  • app/views/DirectoryView/index.tsx
  • app/containers/MessageActions/index.tsx
  • app/views/RoomActionsView/index.tsx
  • app/views/RoomView/index.tsx
  • app/actions/app.ts
  • app/views/ThreadMessagesView/index.tsx
  • app/index.tsx
**/*.{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/MediaCallHeader/components/Content.tsx
  • app/containers/Header/index.tsx
  • app/ee/omnichannel/containers/OmnichannelHeader/index.tsx
  • app/views/RoomsListView/components/TabletHeader.tsx
  • app/views/SidebarView/components/SupportedVersionsWarnItem.tsx
  • app/views/SelectListView.tsx
  • app/views/RoomsListView/components/ListHeader.tsx
  • app/views/NotificationPreferencesView/index.tsx
  • app/views/AddChannelTeamView.tsx
  • app/views/ProfileView/index.test.tsx
  • app/views/NewMessageView/index.tsx
  • app/lib/hooks/withDimensions.tsx
  • app/containers/InAppNotification/IncomingCallNotification/index.tsx
  • app/views/RoomsListView/components/ServersList.tsx
  • app/containers/MessageComposer/components/Buttons/ActionsButton.tsx
  • app/views/AccessibilityAndAppearanceView/index.tsx
  • app/ee/omnichannel/views/QueueListView.tsx
  • app/views/ReportUserView/index.tsx
  • app/containers/MessageComposer/components/ComposerInput.tsx
  • app/views/SidebarView/components/Profile.tsx
  • app/views/SettingsView/index.tsx
  • app/containers/TwoFactor/index.tsx
  • app/views/CloseLivechatView.tsx
  • app/views/CallView/components/CallButtons.tsx
  • app/views/StatusView/index.tsx
  • app/views/AdminPanelView/index.tsx
  • app/views/SearchMessagesView/index.tsx
  • app/containers/List/List.stories.tsx
  • app/views/RoomsListView/index.tsx
  • app/views/ProfileView/index.tsx
  • app/views/CannedResponsesListView/index.tsx
  • app/views/RoomView/JoinCode.tsx
  • app/lib/hooks/useMasterDetail.tsx
  • app/views/SidebarView/components/Admin.tsx
  • app/views/SidebarView/components/Stacks.tsx
  • app/AppContainer.tsx
  • app/views/RoomView/components/EncryptedRoom.tsx
  • app/reducers/app.test.ts
  • app/views/MessagesView/index.tsx
  • app/containers/markdown/components/mentions/Hashtag.tsx
  • app/containers/RoomHeader/RoomHeader.tsx
  • app/views/RoomMembersView/index.tsx
  • app/views/DiscussionsView/index.tsx
  • app/views/AddExistingChannelView/index.tsx
  • app/views/CannedResponseDetail.tsx
  • app/views/CreateDiscussionView/index.tsx
  • app/views/UserNotificationPreferencesView/index.tsx
  • app/views/RoomsListView/hooks/useHeader.tsx
  • app/containers/InAppNotification/NotifierComponent.tsx
  • app/views/RoomInfoView/index.tsx
  • app/views/RoomView/RightButtons.tsx
  • app/views/TeamChannelsView.tsx
  • app/views/DirectoryView/index.tsx
  • app/containers/MessageActions/index.tsx
  • app/views/RoomActionsView/index.tsx
  • app/views/RoomView/index.tsx
  • app/actions/app.ts
  • app/views/ThreadMessagesView/index.tsx
  • app/index.tsx
**/*.{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/MediaCallHeader/components/Content.tsx
  • app/containers/Header/index.tsx
  • app/ee/omnichannel/containers/OmnichannelHeader/index.tsx
  • app/views/RoomsListView/components/TabletHeader.tsx
  • app/views/SidebarView/components/SupportedVersionsWarnItem.tsx
  • app/views/SelectListView.tsx
  • app/views/RoomsListView/components/ListHeader.tsx
  • app/views/NotificationPreferencesView/index.tsx
  • app/views/AddChannelTeamView.tsx
  • app/views/ProfileView/index.test.tsx
  • app/views/NewMessageView/index.tsx
  • app/lib/hooks/withDimensions.tsx
  • app/containers/InAppNotification/IncomingCallNotification/index.tsx
  • app/views/RoomsListView/components/ServersList.tsx
  • app/containers/MessageComposer/components/Buttons/ActionsButton.tsx
  • app/views/AccessibilityAndAppearanceView/index.tsx
  • app/ee/omnichannel/views/QueueListView.tsx
  • app/views/ReportUserView/index.tsx
  • app/containers/MessageComposer/components/ComposerInput.tsx
  • app/views/SidebarView/components/Profile.tsx
  • app/views/SettingsView/index.tsx
  • app/containers/TwoFactor/index.tsx
  • app/views/CloseLivechatView.tsx
  • app/views/CallView/components/CallButtons.tsx
  • app/views/StatusView/index.tsx
  • app/views/AdminPanelView/index.tsx
  • app/views/SearchMessagesView/index.tsx
  • app/containers/List/List.stories.tsx
  • app/views/RoomsListView/index.tsx
  • app/views/ProfileView/index.tsx
  • app/views/CannedResponsesListView/index.tsx
  • app/views/RoomView/JoinCode.tsx
  • app/lib/hooks/useMasterDetail.tsx
  • app/views/SidebarView/components/Admin.tsx
  • app/views/SidebarView/components/Stacks.tsx
  • app/AppContainer.tsx
  • app/views/RoomView/components/EncryptedRoom.tsx
  • app/reducers/app.test.ts
  • app/views/MessagesView/index.tsx
  • app/containers/markdown/components/mentions/Hashtag.tsx
  • app/containers/RoomHeader/RoomHeader.tsx
  • app/views/RoomMembersView/index.tsx
  • app/views/DiscussionsView/index.tsx
  • app/views/AddExistingChannelView/index.tsx
  • app/views/CannedResponseDetail.tsx
  • app/views/CreateDiscussionView/index.tsx
  • app/views/UserNotificationPreferencesView/index.tsx
  • app/views/RoomsListView/hooks/useHeader.tsx
  • app/containers/InAppNotification/NotifierComponent.tsx
  • app/views/RoomInfoView/index.tsx
  • app/views/RoomView/RightButtons.tsx
  • app/views/TeamChannelsView.tsx
  • app/views/DirectoryView/index.tsx
  • app/containers/MessageActions/index.tsx
  • app/views/RoomActionsView/index.tsx
  • app/views/RoomView/index.tsx
  • app/actions/app.ts
  • app/views/ThreadMessagesView/index.tsx
  • app/index.tsx
app/containers/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

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

Files:

  • app/containers/MediaCallHeader/components/Content.tsx
  • app/containers/Header/index.tsx
  • app/containers/InAppNotification/IncomingCallNotification/index.tsx
  • app/containers/MessageComposer/components/Buttons/ActionsButton.tsx
  • app/containers/MessageComposer/components/ComposerInput.tsx
  • app/containers/TwoFactor/index.tsx
  • app/containers/List/List.stories.tsx
  • app/containers/markdown/components/mentions/Hashtag.tsx
  • app/containers/RoomHeader/RoomHeader.tsx
  • app/containers/InAppNotification/NotifierComponent.tsx
  • app/containers/MessageActions/index.tsx
app/ee/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Place enterprise features (Omnichannel/livechat) in 'app/ee/' directory

Files:

  • app/ee/omnichannel/containers/OmnichannelHeader/index.tsx
  • app/ee/omnichannel/views/QueueListView.tsx
app/views/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Place screen components in 'app/views/' directory

Files:

  • app/views/RoomsListView/components/TabletHeader.tsx
  • app/views/SidebarView/components/SupportedVersionsWarnItem.tsx
  • app/views/SelectListView.tsx
  • app/views/RoomsListView/components/ListHeader.tsx
  • app/views/NotificationPreferencesView/index.tsx
  • app/views/AddChannelTeamView.tsx
  • app/views/ProfileView/index.test.tsx
  • app/views/NewMessageView/index.tsx
  • app/views/RoomsListView/components/ServersList.tsx
  • app/views/AccessibilityAndAppearanceView/index.tsx
  • app/views/ReportUserView/index.tsx
  • app/views/SidebarView/components/Profile.tsx
  • app/views/SettingsView/index.tsx
  • app/views/CloseLivechatView.tsx
  • app/views/CallView/components/CallButtons.tsx
  • app/views/StatusView/index.tsx
  • app/views/AdminPanelView/index.tsx
  • app/views/SearchMessagesView/index.tsx
  • app/views/RoomsListView/index.tsx
  • app/views/ProfileView/index.tsx
  • app/views/CannedResponsesListView/index.tsx
  • app/views/RoomView/JoinCode.tsx
  • app/views/SidebarView/components/Admin.tsx
  • app/views/SidebarView/components/Stacks.tsx
  • app/views/RoomView/components/EncryptedRoom.tsx
  • app/views/MessagesView/index.tsx
  • app/views/RoomMembersView/index.tsx
  • app/views/DiscussionsView/index.tsx
  • app/views/AddExistingChannelView/index.tsx
  • app/views/CannedResponseDetail.tsx
  • app/views/CreateDiscussionView/index.tsx
  • app/views/UserNotificationPreferencesView/index.tsx
  • app/views/RoomsListView/hooks/useHeader.tsx
  • app/views/RoomInfoView/index.tsx
  • app/views/RoomView/RightButtons.tsx
  • app/views/TeamChannelsView.tsx
  • app/views/DirectoryView/index.tsx
  • app/views/RoomActionsView/index.tsx
  • app/views/RoomView/index.tsx
  • app/views/ThreadMessagesView/index.tsx
app/reducers/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Place reducers in 'app/reducers/' directory

Files:

  • app/reducers/app.test.ts
app/actions/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Place action creators in 'app/actions/' directory

Files:

  • app/actions/app.ts
🧠 Learnings (2)
📚 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/MediaCallHeader/components/Content.tsx
  • app/containers/Header/index.tsx
  • app/ee/omnichannel/containers/OmnichannelHeader/index.tsx
  • app/views/RoomsListView/components/TabletHeader.tsx
  • app/views/SidebarView/components/SupportedVersionsWarnItem.tsx
  • app/views/SelectListView.tsx
  • app/views/RoomsListView/components/ListHeader.tsx
  • app/views/NotificationPreferencesView/index.tsx
  • app/views/AddChannelTeamView.tsx
  • app/views/ProfileView/index.test.tsx
  • app/views/NewMessageView/index.tsx
  • app/lib/hooks/withDimensions.tsx
  • app/containers/InAppNotification/IncomingCallNotification/index.tsx
  • app/views/RoomsListView/components/ServersList.tsx
  • app/containers/MessageComposer/components/Buttons/ActionsButton.tsx
  • app/views/AccessibilityAndAppearanceView/index.tsx
  • app/ee/omnichannel/views/QueueListView.tsx
  • app/views/ReportUserView/index.tsx
  • app/containers/MessageComposer/components/ComposerInput.tsx
  • app/views/SidebarView/components/Profile.tsx
  • app/views/SettingsView/index.tsx
  • app/containers/TwoFactor/index.tsx
  • app/views/CloseLivechatView.tsx
  • app/views/CallView/components/CallButtons.tsx
  • app/views/StatusView/index.tsx
  • app/views/AdminPanelView/index.tsx
  • app/views/SearchMessagesView/index.tsx
  • app/containers/List/List.stories.tsx
  • app/views/RoomsListView/index.tsx
  • app/views/ProfileView/index.tsx
  • app/views/CannedResponsesListView/index.tsx
  • app/views/RoomView/JoinCode.tsx
  • app/lib/hooks/useMasterDetail.tsx
  • app/views/SidebarView/components/Admin.tsx
  • app/views/SidebarView/components/Stacks.tsx
  • app/AppContainer.tsx
  • app/views/RoomView/components/EncryptedRoom.tsx
  • app/reducers/app.test.ts
  • app/views/MessagesView/index.tsx
  • app/containers/markdown/components/mentions/Hashtag.tsx
  • app/containers/RoomHeader/RoomHeader.tsx
  • app/views/RoomMembersView/index.tsx
  • app/views/DiscussionsView/index.tsx
  • app/views/AddExistingChannelView/index.tsx
  • app/views/CannedResponseDetail.tsx
  • app/views/CreateDiscussionView/index.tsx
  • app/views/UserNotificationPreferencesView/index.tsx
  • app/views/RoomsListView/hooks/useHeader.tsx
  • app/containers/InAppNotification/NotifierComponent.tsx
  • app/views/RoomInfoView/index.tsx
  • app/views/RoomView/RightButtons.tsx
  • app/views/TeamChannelsView.tsx
  • app/views/DirectoryView/index.tsx
  • app/containers/MessageActions/index.tsx
  • app/views/RoomActionsView/index.tsx
  • app/views/RoomView/index.tsx
  • app/actions/app.ts
  • app/views/ThreadMessagesView/index.tsx
  • app/index.tsx
📚 Learning: 2026-03-15T13:55:42.038Z
Learnt from: Rohit3523
Repo: RocketChat/Rocket.Chat.ReactNative PR: 6911
File: app/containers/markdown/Markdown.stories.tsx:104-104
Timestamp: 2026-03-15T13:55:42.038Z
Learning: In Rocket.Chat React Native, the markdown parser requires a space between the underscore wrapping italic text and a mention sigil (_ mention _ instead of _mention_). Ensure stories and tests that include italic-wrapped mentions follow this form to guarantee proper parsing. Specifically, for files like app/containers/markdown/Markdown.stories.tsx, and any test/content strings that exercise italic-mentions, use the pattern _ mention _ (with spaces) to prevent the mention from being treated as plain text. Validate any test strings or story content accordingly.

Applied to files:

  • app/containers/List/List.stories.tsx
🔇 Additional comments (55)
app/lib/hooks/useMasterDetail.tsx (1)

9-12: LGTM!

Also applies to: 14-25

app/lib/hooks/withDimensions.tsx (1)

11-22: LGTM!

app/actions/app.ts (1)

20-20: LGTM!

app/reducers/app.test.ts (1)

1-1: LGTM!

app/views/ProfileView/index.test.tsx (1)

64-64: LGTM!

app/index.tsx (1)

2-2: LGTM!

Also applies to: 11-11, 88-88, 182-182, 194-207

app/containers/List/List.stories.tsx (1)

7-7: LGTM!

Also applies to: 245-247

app/containers/InAppNotification/NotifierComponent.tsx (1)

12-15: LGTM!

Also applies to: 134-136

app/containers/MessageActions/index.tsx (1)

39-39: LGTM!

Also applies to: 631-631

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

39-39: LGTM!

Also applies to: 386-389

app/views/RoomView/RightButtons.tsx (1)

33-33: LGTM!

Also applies to: 574-574

app/views/RoomView/components/EncryptedRoom.tsx (1)

10-10: LGTM!

Also applies to: 26-26

app/views/SidebarView/components/SupportedVersionsWarnItem.tsx (1)

7-7: LGTM!

Also applies to: 17-17

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

18-18: LGTM!

Also applies to: 110-110

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

13-13: LGTM!

Also applies to: 36-37

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

27-28: LGTM!

Also applies to: 1333-1333

app/views/RoomView/JoinCode.tsx (1)

14-14: LGTM!

Also applies to: 132-134

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

13-20: LGTM!

app/views/CallView/components/CallButtons.tsx (1)

5-5: LGTM!

Also applies to: 30-30

app/views/CannedResponseDetail.tsx (1)

16-16: LGTM!

Also applies to: 90-90

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

27-27: LGTM!

Also applies to: 69-69

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

44-45: LGTM!

Also applies to: 1723-1725

app/AppContainer.tsx (1)

8-8: LGTM!

Also applies to: 37-39, 93-93

app/containers/MediaCallHeader/components/Content.tsx (1)

3-3: LGTM!

Also applies to: 23-23

app/views/AddChannelTeamView.tsx (1)

13-13: LGTM!

Also applies to: 50-50

app/views/RoomsListView/components/ServersList.tsx (1)

18-18: LGTM!

Also applies to: 39-39

app/views/SidebarView/components/Profile.tsx (1)

13-13: LGTM!

Also applies to: 15-20

app/views/SidebarView/components/Stacks.tsx (1)

4-5: LGTM!

Also applies to: 7-12

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

44-44: LGTM!

Also applies to: 360-360

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

13-13: LGTM!

Also applies to: 94-98

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

36-36: LGTM!

Also applies to: 83-83

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

19-19: LGTM!

Also applies to: 44-44

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

16-16: LGTM!

Also applies to: 77-77

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

19-19: LGTM!

Also applies to: 81-91

app/views/TeamChannelsView.tsx (1)

20-21: LGTM!

Also applies to: 600-600

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

46-46: LGTM!

Also applies to: 536-537, 539-539

app/views/CloseLivechatView.tsx (1)

15-15: LGTM!

Also applies to: 48-52

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

27-27: LGTM!

Also applies to: 65-65

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

27-27: LGTM!

Also applies to: 41-49

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

22-22: LGTM!

Also applies to: 41-41

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

20-20: LGTM!

Also applies to: 37-45

app/containers/Header/index.tsx (1)

8-8: LGTM!

Also applies to: 19-19

app/containers/InAppNotification/IncomingCallNotification/index.tsx (1)

10-10: LGTM!

Also applies to: 42-42

app/containers/MessageComposer/components/Buttons/ActionsButton.tsx (1)

9-9: LGTM!

Also applies to: 27-27

app/containers/MessageComposer/components/ComposerInput.tsx (1)

40-40: LGTM!

Also applies to: 61-61

app/containers/RoomHeader/RoomHeader.tsx (1)

14-14: LGTM!

Also applies to: 172-172

app/containers/TwoFactor/index.tsx (1)

21-21: LGTM!

Also applies to: 70-70

app/containers/markdown/components/mentions/Hashtag.tsx (1)

8-8: LGTM!

Also applies to: 29-29

app/ee/omnichannel/containers/OmnichannelHeader/index.tsx (1)

16-16: LGTM!

Also applies to: 26-26

app/ee/omnichannel/views/QueueListView.tsx (1)

22-22: LGTM!

Also applies to: 57-57

app/views/RoomsListView/components/ListHeader.tsx (1)

9-9: LGTM!

Also applies to: 22-22

app/views/RoomsListView/hooks/useHeader.tsx (1)

7-7: LGTM!

Also applies to: 23-23

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

16-16: LGTM!

Also applies to: 45-45

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

21-21: LGTM!

Also applies to: 43-43

app/views/SidebarView/components/Admin.tsx (1)

4-12: LGTM!

const AccessibilityAndAppearanceView = () => {
const navigation = useNavigation<NativeStackNavigationProp<AccessibilityStackParamList>>();
const isMasterDetail = useAppSelector(state => state.app.isMasterDetail as boolean);
const isMasterDetail = useMasterDetail();

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.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Update header options when master-detail mode changes.

Line 25 introduces a dynamic isMasterDetail, but useLayoutEffect still runs only once. On resize/rotation across the breakpoint, headerLeft can stay stale.

Suggested fix
-	useLayoutEffect(() => {
+	useLayoutEffect(() => {
 		navigation.setOptions({
 			title: I18n.t('Accessibility_and_Appearance'),
 			headerLeft: isMasterDetail
 				? undefined
 				: () => <HeaderButton.Drawer navigation={navigation} testID='accessibility-view-drawer' />
 		});
-	}, []);
+	}, [navigation, isMasterDetail]);
🤖 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/AccessibilityAndAppearanceView/index.tsx` at line 25, The
useLayoutEffect hook that sets up headerLeft needs to be updated to respond to
changes in the isMasterDetail value. Add isMasterDetail to the dependency array
of the useLayoutEffect hook (the one that configures the navigation header
options) so that the effect re-runs whenever the master-detail mode changes due
to resize, rotation, or other layout changes. This ensures that headerLeft and
other header options remain synchronized with the current master-detail state.

Comment on lines 8 to +13
const TabletHeader = () => {
'use memo';

const navigation = useNavigation<any>();
const route = useRoute<any>();
const isMasterDetail = useAppSelector(state => state.app.isMasterDetail);
const isMasterDetail = useMasterDetail();

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.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Find existing typed navigation/route patterns to reuse in this view flow
rg -n --type=tsx "useNavigation<|useRoute<|NativeStackNavigationProp|RouteProp" app/views/RoomsListView app/views app/containers | sed -n '1,200p'

Repository: RocketChat/Rocket.Chat.ReactNative

Length of output: 106


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Read the file in question
echo "=== TabletHeader.tsx content ==="
cat -n app/views/RoomsListView/components/TabletHeader.tsx | head -30

# Search for navigation type patterns using correct syntax
echo -e "\n=== Navigation/Route type patterns in codebase ==="
rg -n "useNavigation<|useRoute<|NativeStackNavigationProp|RouteProp" -g "*.ts" -g "*.tsx" app/views/ | head -50

# Check specifically in RoomsListView for patterns
echo -e "\n=== RoomsListView navigation patterns ==="
rg -n "useNavigation|useRoute" -g "*.ts" -g "*.tsx" app/views/RoomsListView/ -A 2

Repository: RocketChat/Rocket.Chat.ReactNative

Length of output: 9221


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Search for navigation param list definitions
echo "=== ParamList definitions ==="
rg -n "ParamList|StackParamList" -g "*.ts" -g "*.tsx" --max-count=50 | grep -i "rooms\|master" | head -30

# Check Header component to see what it expects
echo -e "\n=== Header component type requirements ==="
cat -n app/containers/Header/index.tsx | head -50

# Look for InsideStack or navigation type definitions
echo -e "\n=== Navigation type files ==="
fd -e ts -e tsx "navigation" app/ | head -20
</script

Repository: RocketChat/Rocket.Chat.ReactNative

Length of output: 3599


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Read Header component to see type requirements
echo "=== Header component interface ==="
head -100 app/containers/Header/index.tsx

# Read MasterDetailStack types
echo -e "\n=== MasterDetailStack types ==="
cat -n app/stacks/MasterDetailStack/types.ts | head -250

# Check parent RoomsListView to understand navigation context
echo -e "\n=== RoomsListView navigation setup ==="
head -60 app/views/RoomsListView/index.tsx

Repository: RocketChat/Rocket.Chat.ReactNative

Length of output: 12418


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Check how NativeStackHeaderProps is used in Header and what generics it has
echo "=== NativeStackHeaderProps import and usage ==="
rg -n "NativeStackHeaderProps" -g "*.ts" -g "*.tsx" -A 3 | head -40

# Check React types for return type
echo -e "\n=== React types usage in similar components ==="
rg -n "React\.ReactElement|React\.FC|ReactElement" app/views/RoomsListView -g "*.ts" -g "*.tsx" | head -20

Repository: RocketChat/Rocket.Chat.ReactNative

Length of output: 1198


Replace any with proper navigation/route types in TabletHeader

The useNavigation<any>() and useRoute<any>() calls bypass TypeScript strict mode checks. Based on the navigation structure and how other components in the codebase are typed, use NativeStackNavigationProp and RouteProp from @react-navigation/native-stack with MasterDetailInsideStackParamList from the navigation types. Also add an explicit return type (ReactElement | null) to the component.

🤖 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/components/TabletHeader.tsx` around lines 8 - 13, In
the TabletHeader component, replace the `any` type parameters in the
useNavigation and useRoute hooks with proper TypeScript types. Import
NativeStackNavigationProp and RouteProp from `@react-navigation/native-stack` and
MasterDetailInsideStackParamList from the navigation types, then apply these
types to the respective hooks. Additionally, add an explicit return type
annotation of ReactElement | null to the TabletHeader function declaration to
ensure proper type safety.

Source: Coding guidelines

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.

1 participant