Skip to content

chore: Code style enforcement (1/n)#7001

Open
tassoevan wants to merge 12 commits intodevelopfrom
chore/stylistic-changes-1
Open

chore: Code style enforcement (1/n)#7001
tassoevan wants to merge 12 commits intodevelopfrom
chore/stylistic-changes-1

Conversation

@tassoevan
Copy link
Contributor

@tassoevan tassoevan commented Feb 21, 2026

Proposed changes

It reviews lint rules to aim consistency.

Issue(s)

Task: NATIVE-49

How to test or reproduce

Screenshots

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

This is one in a sequence of incoming suggested changes.

Summary by CodeRabbit

  • Chores

    • Updated ESLint/tooling and dependencies; streamlined lint config and TypeScript-aware overrides.
    • Enabled stricter TypeScript checks in tsconfig.
  • Style / UI

    • Minor styling and rendering consistency fixes across avatars, emojis, banners, replies, discussions and markdown previews.
  • Tests

    • Enabled Android ASCII URL test and consolidated several tests into parameterized cases.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 21, 2026

Walkthrough

Removes .eslintrc.js from ignores and rewrites ESLint config and related devDeps; enables stricter TS checks; applies widespread small edits: unwrap/suppress single-element style arrays, convert children props to nested JSX, mark unused params with _, simplify single-param arrow syntax, test consolidations, mock tweaks, and a Preview style prop typing change.

Changes

Cohort / File(s) Summary
ESLint & TypeScript Config
.eslintignore, .eslintrc.js, tsconfig.json, package.json
Removed .eslintrc.js from ignore; replaced ESLint config (parser, plugins, extends, rules, overrides, react detect); enabled noUnusedLocals/noUnusedParameters; updated ESLint-related dependencies and versions.
Preview typing change
app/containers/markdown/components/Preview.tsx
Changed IMarkdownPreview.style from TextStyle[] to StyleProp<TextStyle] and adjusted rendering to accept arrays or single styles.
Children as Nested JSX
app/containers/ActionSheet/ActionSheet.tsx, app/containers/Avatar/AvatarContainer.tsx, app/containers/Avatar/AvatarWithEdit.tsx
Stop passing children via prop; render children between opening/closing tags instead.
Single-Element Style Arrays — Replace
app/containers/Avatar/Avatar.stories.tsx, app/containers/markdown/components/emoji/Emoji.tsx, app/containers/message/Components/Attachments/Reply.tsx, app/views/DiscussionsView/DiscussionDetails.tsx
Replaced single-element style arrays with direct style objects (e.g., style={[x]}style={x}).
ESLint Suppressions for Style Arrays
app/containers/MessageComposer/components/Quotes/Quote.tsx, app/views/DiscussionsView/Item.tsx, app/views/RoomView/Banner.tsx, app/views/ThreadMessagesView/Item.tsx
Added // eslint-disable-next-line react-native/no-single-element-style-arrays where single-element style arrays are kept.
Rename Unused Parameters (underscore prefix)
app/containers/AudioPlayer/Seek.tsx, app/ee/omnichannel/views/QueueListView.tsx, app/lib/encryption/encryption.ts, app/lib/encryption/helpers/base64-js/index.ts, app/lib/encryption/room.ts, app/lib/helpers/formatText.ts, app/lib/hooks/useShortnameToUnicode/index.tsx, app/lib/methods/search.ts, app/views/SelectServerView.tsx
Renamed unused parameters to start with _ (e.g., messageId_messageId) with no behavior changes.
Arrow Parameter Formatting (paren removal)
__mocks__/react-native-mmkv.js, app/sagas/createChannel.js,app/sagas/createDiscussion.js,app/sagas/deepLinking.js,app/sagas/login.js,app/sagas/rooms.js,app/sagas/state.js
Removed parentheses around single arrow parameters and similar concise-arrow formatting; no semantic changes.
Tests & Test Refactors
app/lib/database/utils.test.ts, app/lib/methods/serializeAsciiUrl.test.ts, app/containers/MessageComposer/helpers/getMentionRegexp.test.js, app/containers/UnreadBadge/getUnreadStyle.test.js, app/views/CreateChannelView/RoomSettings/SwitchItemEncrypted.test.tsx
Consolidated tests with test.each, enabled previously commented Android test, normalized quoting, simplified query/assert patterns.
Mock & Small Logic Tweaks
__mocks__/react-native-mmkv.js
Minor callback param syntax changes and added console.error in a catch within notifyListeners.
Remove/Ignore Unused Instances
app/ee/omnichannel/lib/index.ts
Replaced stored instance (const omn = new Omnichannel()) with anonymous new Omnichannel() to avoid retaining a reference while keeping constructor side effects.
Prop Forwarding / Minor Component Changes
app/containers/List/ListRadio.tsx, app/containers/MessageComposer/components/Quotes/Quote.tsx
Stopped forwarding value prop by renaming to _ in destructure; added lint directive in Quote.
Small Refactors / Formatting
scripts/build-icon-set.js, various small files across repo
Stylistic refactors (explicit reducer return), rename unused regex/callback params to _, minor formatting edits across many files.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

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.
Title check ❓ Inconclusive The title 'chore: Code style enforcement (1/n)' is vague and generic, using non-descriptive language that doesn't convey the specific nature of the changes made. Use a more specific title that describes the primary change, such as 'chore: Update ESLint config and refactor callback parameters' or 'chore: Modernize ESLint rules and enforce consistent code style'.
✅ Passed checks (1 passed)
Check name Status Explanation
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.


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

❤️ Share

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

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

Caution

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

⚠️ Outside diff range comments (1)
app/lib/methods/serializeAsciiUrl.test.ts (1)

8-8: ⚠️ Potential issue | 🟠 Major

jest.mock inside describe does not produce per-suite platform isolation

jest.mock calls are hoisted by babel-jest to the top of the file regardless of where they appear in the source. When two factories are registered for the same module (react-native), Jest uses the last one for the entire file — meaning the iOS describe block also runs under the Android mock ({ Platform: { OS: 'android' } }). The iOS tests therefore do not actually test iOS behaviour.

A reliable approach is to use jest.isolateModules inside each test so the module registry is reset before each mock is applied:

♻️ Proposed fix using `jest.isolateModules`
-describe('Serialize ASCII url on ios', () => {
-	jest.mock('react-native', () => ({ Platform: { OS: 'ios' } }));
-	test('ASCII url', () => {
-		const result = serializeAsciiUrl(ASCIIUrl);
-		expect(result).toBe(ASCIIUrlSerialized);
-	});
-	test('Non ASCII url', () => {
-		const result = serializeAsciiUrl(NonASCIIUrl);
-		expect(result).toBe(NonASCIIUrl);
-	});
-});
-
-describe('Serialize ASCII url on android', () => {
-	jest.mock('react-native', () => ({ Platform: { OS: 'android' } }));
-	// By default android converts ASCII addresses
-	test('ASCII url', () => {
-		const result = serializeAsciiUrl(ASCIIUrl);
-		expect(result).toBe(ASCIIUrlSerialized);
-	});
-	test('Non ASCII url', () => {
-		const result = serializeAsciiUrl(NonASCIIUrl);
-		expect(result).toBe(NonASCIIUrl);
-	});
-});
+describe.each([
+	['ios', ASCIIUrlSerialized],
+	['android', ASCIIUrlSerialized], // android converts ASCII addresses natively
+])('Serialize ASCII url on %s', (os, expectedASCII) => {
+	let serializeAsciiUrlFn: typeof import('./serializeAsciiUrl').serializeAsciiUrl;
+
+	beforeEach(() => {
+		jest.resetModules();
+		jest.mock('react-native', () => ({ Platform: { OS: os } }));
+		// eslint-disable-next-line `@typescript-eslint/no-require-imports`
+		serializeAsciiUrlFn = require('./serializeAsciiUrl').serializeAsciiUrl;
+	});
+
+	test('ASCII url', () => {
+		expect(serializeAsciiUrlFn(ASCIIUrl)).toBe(expectedASCII);
+	});
+	test('Non ASCII url', () => {
+		expect(serializeAsciiUrlFn(NonASCIIUrl)).toBe(NonASCIIUrl);
+	});
+});

Also applies to: 19-25

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

In `@app/lib/methods/serializeAsciiUrl.test.ts` at line 8, The jest.mock calls for
'react-native' are hoisted and cause cross-suite leakage; update the tests in
serializeAsciiUrl.test.ts to remove per-describe jest.mock usage and instead
wrap each test (or beforeEach) in jest.isolateModules so you can call
jest.mock('react-native', () => ({ Platform: { OS: 'ios' } })) or the Android
variant inside the isolate callback and then require the module under test (the
serializeAsciiUrl import) inside that isolateModules block; ensure each test
requires the module after mocking so Platform.OS is correctly isolated for tests
referencing serializeAsciiUrl.
🧹 Nitpick comments (7)
app/containers/MessageComposer/components/Quotes/Quote.tsx (1)

52-53: Same optional root-cause fix applies as in DiscussionsView/Item.tsx.

If MarkdownPreview's style prop accepts StyleProp<TextStyle>, style={styles.message} removes the need for the suppress comment.

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

In `@app/containers/MessageComposer/components/Quotes/Quote.tsx` around lines 52 -
53, The inline eslint suppression exists because style is passed as a
single-element array; update the JSX in Quote.tsx to pass the style directly
(use style={styles.message} instead of style={[styles.message]}) and remove the
eslint-disable-next-line comment; if TypeScript complains about prop typing,
adjust MarkdownPreview's prop type to accept StyleProp<TextStyle> (or cast the
value to that type) so the direct style prop is valid—look for the
MarkdownPreview prop definition and styles.message to make the change, similar
to the fix applied in DiscussionsView/Item.tsx.
app/ee/omnichannel/lib/index.ts (1)

56-56: Consider const _omnichannel = new Omnichannel() for consistency with the PR's underscore convention.

The anonymous instantiation is functionally safe (the EventEmitter holds references to the bound methods, preventing GC of the instance), but it departs from the underscore-prefix pattern applied everywhere else in this PR (_data, _b64, _messageId, _rid). Using _omnichannel makes the "instantiate for side-effects" intent explicit and keeps the codebase idiom consistent.

♻️ Suggested change
-new Omnichannel();
+const _omnichannel = new Omnichannel();
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/ee/omnichannel/lib/index.ts` at line 56, The code instantiates
Omnichannel anonymously which breaks the PR's underscore-prefix convention;
change the anonymous call to a named const (e.g., _omnichannel) so the instance
is assigned and follows the pattern used for other module-level side-effect
instances; locate the new Omnichannel() invocation in the module (symbol:
Omnichannel) and replace it with a const declaration named _omnichannel assigned
to the new Omnichannel() instance.
app/containers/List/ListRadio.tsx (1)

13-13: Prefer _value over bare _ for the discarded prop.

Using _ drops all context about which prop is intentionally ignored. _value satisfies both TypeScript noUnusedParameters and ESLint no-unused-vars (underscore prefix convention) while keeping the original name readable.

♻️ Proposed rename
-const ListRadio = ({ value: _, isSelected, ...rest }: IListRadio) => {
+const ListRadio = ({ value: _value, isSelected, ...rest }: IListRadio) => {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/containers/List/ListRadio.tsx` at line 13, In ListRadio change the
discarded prop name from "_" to "_value" so the parameter list becomes ({ value:
_value, isSelected, ...rest }: IListRadio) — update the ListRadio function
signature to use _value instead of _ to satisfy TypeScript/ESLint unused-var
conventions while preserving the original prop name context.
app/lib/encryption/room.ts (1)

503-503: _rid parameter is structurally dead — consider removing it.

file: TSendFileMessageFileInfo already includes rid, so the first parameter has never been needed. The rename to _rid satisfies the linter but leaves every caller supplying a redundant argument.

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

In `@app/lib/encryption/room.ts` at line 503, The function encryptFile currently
accepts a redundant first parameter named _rid even though file:
TSendFileMessageFileInfo already contains rid; remove the unused _rid parameter
from encryptFile's signature and update the implementation to use file.rid
wherever needed (refer to encryptFile and TSendFileMessageFileInfo), then update
all callers to stop passing the extra rid argument so they call
encryptFile(file) and adjust any related type references (e.g.,
TEncryptFileResult) as needed to match the new signature.
.eslintrc.js (3)

19-25: 'prettier' in extends is redundant when 'plugin:prettier/recommended' is already present.

plugin:prettier/recommended includes eslint-config-prettier (which is what 'prettier' resolves to). The same duplication appears in the TypeScript override at lines 81–82.

♻️ Suggested cleanup
 	extends: [
 		'@rocket.chat/eslint-config',
 		'plugin:react/recommended',
 		'plugin:react-hooks/recommended',
-		'plugin:prettier/recommended',
-		'prettier'
+		'plugin:prettier/recommended'
 	],

And in the TS override:

 			extends: [
 				'plugin:`@typescript-eslint/recommended`',
 				'plugin:`@typescript-eslint/eslint-recommended`',
 				'@rocket.chat/eslint-config',
-				'plugin:prettier/recommended',
-				'prettier'
+				'plugin:prettier/recommended'
 			],
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.eslintrc.js around lines 19 - 25, The extends array currently includes both
"plugin:prettier/recommended" and the redundant "prettier"; remove the duplicate
"prettier" entry from the top-level extends list and also remove the duplicate
"prettier" entry from the TypeScript override extends to avoid redundant
inclusion (locate the extends arrays where "plugin:prettier/recommended" and
"prettier" appear and delete only the plain "prettier" entries).

96-100: Several turned-off rules are deprecated in @typescript-eslint v7.

@typescript-eslint/indent, @typescript-eslint/no-extra-parens, @typescript-eslint/no-var-requires, and no-spaced-func are all deprecated (formatting rules were removed in v6+, no-var-requires replaced by no-require-imports). Turning them off is harmless but adds dead configuration. Consider removing them in a follow-up cleanup pass.

Also applies to: 108-108, 112-112

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

In @.eslintrc.js around lines 96 - 100, The .eslintrc.js currently disables
several deprecated `@typescript-eslint` rules; remove the dead configuration
entries for '@typescript-eslint/indent', '@typescript-eslint/no-extra-parens',
'no-spaced-func', and '@typescript-eslint/no-var-requires' (and any duplicate
occurrences of those exact rule keys elsewhere in the file) so the config no
longer contains deprecated/removed rule names; keep other valid rules like
'@typescript-eslint/no-dupe-class-members' and
'@typescript-eslint/no-empty-function' unchanged.

45-47: import/no-cycle can be expensive on large codebases.

This rule performs deep dependency graph traversal. In a React Native monorepo of this size, it can noticeably slow down lint runs. Consider setting maxDepth to bound the cost, or running it only in CI rather than in editor integrations.

♻️ Option to bound cycle detection depth
-		'import/no-cycle': 'error',
+		'import/no-cycle': ['error', { maxDepth: 5 }],
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.eslintrc.js around lines 45 - 47, The 'import/no-cycle' rule in
.eslintrc.js is expensive on large monorepos; update its configuration (the
'import/no-cycle' entry) to limit traversal by adding a maxDepth option (e.g.,
set maxDepth to a small integer like 3–5) or move/override the rule so it's only
enforced in CI/editor-independent runs (e.g., enable it in an ESLint CI override
or disable it for editor integrations), ensuring you reference the
'import/no-cycle' rule name when making the change.
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ae5e663 and fd66233.

⛔ Files ignored due to path filters (5)
  • app/containers/Avatar/__snapshots__/Avatar.test.tsx.snap is excluded by !**/*.snap
  • app/containers/markdown/__snapshots__/Markdown.test.tsx.snap is excluded by !**/*.snap
  • app/containers/message/__snapshots__/Message.test.tsx.snap is excluded by !**/*.snap
  • app/views/DiscussionsView/__snapshots__/Item.test.tsx.snap is excluded by !**/*.snap
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (39)
  • .eslintignore
  • .eslintrc.js
  • __mocks__/react-native-mmkv.js
  • app/containers/ActionSheet/ActionSheet.tsx
  • app/containers/AudioPlayer/Seek.tsx
  • app/containers/Avatar/Avatar.stories.tsx
  • app/containers/Avatar/AvatarContainer.tsx
  • app/containers/Avatar/AvatarWithEdit.tsx
  • app/containers/List/ListRadio.tsx
  • app/containers/MessageComposer/components/Quotes/Quote.tsx
  • app/containers/MessageComposer/helpers/getMentionRegexp.test.js
  • app/containers/UnreadBadge/getUnreadStyle.test.js
  • app/containers/markdown/components/emoji/Emoji.tsx
  • app/containers/message/Components/Attachments/Reply.tsx
  • app/ee/omnichannel/lib/index.ts
  • app/ee/omnichannel/views/QueueListView.tsx
  • app/lib/database/utils.test.ts
  • app/lib/encryption/encryption.ts
  • app/lib/encryption/helpers/base64-js/index.ts
  • app/lib/encryption/room.ts
  • app/lib/helpers/formatText.ts
  • app/lib/hooks/useShortnameToUnicode/index.tsx
  • app/lib/methods/search.ts
  • app/lib/methods/serializeAsciiUrl.test.ts
  • app/sagas/createChannel.js
  • app/sagas/createDiscussion.js
  • app/sagas/deepLinking.js
  • app/sagas/login.js
  • app/sagas/rooms.js
  • app/sagas/state.js
  • app/views/CreateChannelView/RoomSettings/SwitchItemEncrypted.test.tsx
  • app/views/DiscussionsView/DiscussionDetails.tsx
  • app/views/DiscussionsView/Item.tsx
  • app/views/RoomView/Banner.tsx
  • app/views/SelectServerView.tsx
  • app/views/ThreadMessagesView/Item.tsx
  • package.json
  • scripts/build-icon-set.js
  • tsconfig.json
💤 Files with no reviewable changes (1)
  • .eslintignore
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2026-02-05T13:55:00.974Z
Learnt from: Rohit3523
Repo: RocketChat/Rocket.Chat.ReactNative PR: 6930
File: package.json:101-101
Timestamp: 2026-02-05T13:55:00.974Z
Learning: In this repository, the dependency on react-native-image-crop-picker should reference the RocketChat fork (RocketChat/react-native-image-crop-picker) with explicit commit pins, not the upstream ivpusic/react-native-image-crop-picker. Update package.json dependencies (and any lockfile) to point to the fork URL and a specific commit, ensuring edge-to-edge Android fixes are included. This pattern should apply to all package.json files in the repo that declare this dependency.

Applied to files:

  • package.json
🧬 Code graph analysis (6)
app/sagas/state.js (1)
app/lib/notifications/index.ts (1)
  • checkPendingNotification (100-135)
app/lib/encryption/encryption.ts (1)
app/lib/encryption/definitions.ts (1)
  • TDecryptFile (18-23)
app/views/SelectServerView.tsx (1)
app/containers/ServerItem/index.tsx (1)
  • ROW_HEIGHT (12-12)
app/sagas/createDiscussion.js (2)
app/sagas/createChannel.js (1)
  • subCollection (62-62)
app/sagas/rooms.js (1)
  • subCollection (52-52)
app/lib/encryption/room.ts (2)
app/definitions/IUpload.ts (1)
  • TSendFileMessageFileInfo (26-29)
app/lib/encryption/definitions.ts (1)
  • TEncryptFileResult (10-14)
app/containers/Avatar/AvatarWithEdit.tsx (1)
app/containers/message/MessageAvatar.tsx (1)
  • AvatarContainer (13-17)
⏰ 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 comments (35)
app/lib/helpers/formatText.ts (1)

5-5: LGTM!

Renaming match_match correctly signals the parameter is intentionally unused, consistent with the lint rule being enforced across the PR. No behavioral change.

app/lib/database/utils.test.ts (1)

13-21: LGTM — clean consolidation into test.each.

The array-of-arrays format, %s title interpolation, _ prefix for the unused label parameter, and length-based '_'.repeat(disallowedChars.length) expectation (which correctly handles _ being both a disallowed char and the replacement character) are all correct.

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

22-25: LGTM — placeholder replaced with the correct constant

Changing the expected value from the stale 'filename.png' placeholder to ASCIIUrlSerialized correctly reflects the behaviour described in the comment above (Android serializes ASCII URLs to their Punycode form).

app/sagas/createDiscussion.js (1)

26-29: LGTM — parentheses removal is stylistically clean.

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

141-142: LGTM — _resolve rename correctly signals the unused parameter.

The executor only assigns reject to debounce; resolve was and remains uncalled. The cancellation pattern is sound.

app/sagas/login.js (1)

61-64: LGTM — consistent single-parameter arrow function style across WatermelonDB callbacks.

app/lib/hooks/useShortnameToUnicode/index.tsx (1)

36-48: LGTM — _m1 rename correctly reflects that capture group 1 is unused.

entire (position 0) already covers the full match; _m1 (position 1) would be its duplicate, so the underscore prefix is appropriate.

app/sagas/state.js (1)

31-33: LGTM.

app/containers/message/Components/Attachments/Reply.tsx (1)

264-271: LGTM — removing the single-element array from the outer View is correct.

The outer View (container) only needs styles.backdrop; the inner View (lines 266–269) correctly retains the two-element array for dynamic opacity/color. The treatment is consistent with React Native's StyleProp<ViewStyle>.

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

80-81: The current implementation with the eslint-disable comment is correct and necessary.

The style prop in MarkdownPreview is explicitly typed as TextStyle[] (see app/containers/markdown/components/Preview.tsx line 13), so the array wrapper style={[styles.markdown]} is required by the component's type signature. The component spreads this array into a larger style array (line 30), confirming the array type is intentional. The eslint-disable comment correctly suppresses a false-positive lint warning in this case—removing the array would violate the component's type contract.

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

70-77: LGTM.

Renaming data_data correctly communicates that the first parameter is intentionally unused, satisfying the newly enabled noUnusedParameters rule without any behavioral change.

app/sagas/createChannel.js (1)

64-67: LGTM.

Removing the parentheses around the single s parameter is idiomatic and semantically identical.

app/sagas/deepLinking.js (1)

49-56: LGTM.

Removing the parentheses around the single resolve parameter is a no-op style change consistent with the rest of the PR.

app/sagas/rooms.js (1)

21-23: LGTM.

All six single-parameter arrow functions consistently drop their optional parentheses. No behavioral change in any case.

Also applies to: 78-82, 83-101, 102-109, 111-115, 117-127

app/containers/UnreadBadge/getUnreadStyle.test.js (1)

5-5: LGTM.

Removing parentheses around the single theme parameter is a consistent style-only change.

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

91-92: The ESLint disable comment is appropriate and necessary here.

MarkdownPreview's style prop is explicitly typed as TextStyle[] (an array), not as a scalar or StyleProp<TextStyle>. The component spreads the style into an array: style={[styles.text, { color: ... }, ...style]}. Therefore, style={[styles.markdown]} is the correct way to pass a value, and the ESLint suppress comment is the right approach—no refactoring needed.

app/views/SelectServerView.tsx (1)

18-18: LGTM — correct underscore-prefix convention for the unused data parameter.

tsconfig.json (1)

38-39: Good strictness uplift — enabling noUnusedLocals and noUnusedParameters.

These flags are the root driver for all the _-prefixed parameter renames throughout the rest of this PR, so the codebase is already consistent with them.

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

45-45: LGTM — removing the single-item style array wrapper is functionally equivalent in React Native.

scripts/build-icon-set.js (1)

4-4: LGTM — explicit block body is functionally equivalent and more readable.

app/lib/encryption/helpers/base64-js/index.ts (1)

47-48: LGTM — _b64 is correctly marked unused; the function body only needs validLen and placeHoldersLen.

app/containers/markdown/components/emoji/Emoji.tsx (1)

72-72: LGTM — removing the single-element style array is functionally equivalent.

app/lib/encryption/encryption.ts (1)

599-609: LGTM — _messageId correctly signals the unused first parameter; implementation aligns with the TDecryptFile contract.

app/containers/Avatar/AvatarContainer.tsx (1)

74-76: LGTM — idiomatic JSX children pattern.

Switching from children={children} prop syntax to nested JSX is a style improvement with no behavioral difference.

app/containers/MessageComposer/helpers/getMentionRegexp.test.js (1)

32-32: LGTM — quote normalization with no behavioral change.

app/containers/AudioPlayer/Seek.tsx (1)

68-71: LGTM — unused parameter correctly prefixed.

app/containers/Avatar/AvatarWithEdit.tsx (1)

67-69: LGTM — consistent with the children-as-JSX pattern adopted in AvatarContainer.tsx.

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

67-67: LGTM — unnecessary single-element array wrapper correctly removed.

React Native's StyleProp accepts a registered style number directly; the array wrapper was redundant.

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

171-173: LGTM — same idiomatic JSX children pattern applied consistently.

package.json (2)

177-178: Version range change from ^ to ~ for TypeScript ESLint packages.

Switching from ^7.4.0 to ~7.18.0 tightens the allowed range to patch-only updates, which is a sensible choice for linting tooling stability. 7.18.0 is the latest 7.x release, so this effectively pins at the final minor.


184-192: Both eslint-plugin-react-hooks v7.0.1 and eslint-plugin-react-native v5.x are compatible with ESLint 8.57.0.

eslint-plugin-react-hooks 7.0.1 declares ESLint peer dependency ^8.0.0-0 || ^9.0.0, confirming ESLint 8 support. eslint-plugin-react-native 5.x is also compatible with ESLint 8 using the classic .eslintrc* format. The three rules referenced (react-hooks/set-state-in-effect, react-hooks/immutability, react-hooks/refs) are already in use at lines 60–62 with no apparent issues. The ESLint 9 flat config migration is irrelevant for the current ESLint 8 setup.

Likely an incorrect or invalid review comment.

__mocks__/react-native-mmkv.js (1)

87-87: Stylistic-only changes — LGTM.

All changes remove redundant parentheses around single arrow function parameters, consistent with the Prettier/lint enforcement goals of this PR.

Also applies to: 105-105, 113-113, 129-129, 137-137, 153-153, 161-161, 180-180, 189-189

.eslintrc.js (3)

101-107: Good: strict unused-vars enforcement with underscore escape hatch.

Configuring args: 'all' with argsIgnorePattern: '^_' is a solid pattern — it catches genuinely unused parameters while allowing intentional placeholders. This aligns well with the tsconfig.json changes enabling noUnusedParameters.


14-16: Good structural improvements: auto-detecting React version and scoping environments.

Auto-detecting the React version (line 15) eliminates the common "React version not specified" warning. The test-file override (line 131–133) and React Native env scoping (lines 134–139) properly isolate concerns.

Also applies to: 131-139


60-62: No action needed. All three rule names (react-hooks/set-state-in-effect, react-hooks/immutability, react-hooks/refs) are valid and confirmed to exist in eslint-plugin-react-hooks v7.0.0 as part of the React Compiler rules set enabled by default.

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@app/views/CreateChannelView/RoomSettings/SwitchItemEncrypted.test.tsx`:
- Around line 59-61: The test is sending an object instead of a boolean to the
Switch handler and asserting on the returned object rather than the call
argument; update the fireEvent call that targets
screen.getByTestId(testEncrypted.testSwitchID) to pass a plain boolean (true) —
i.e. fireEvent(component, 'valueChange', true) — and replace the tautological
expect(onPressMock).toHaveReturnedWith(...) with
expect(onPressMock).toHaveBeenCalledWith(true) so the test verifies the callback
was invoked with a boolean as the Switch would in real usage (references:
testEncrypted, testSwitchID, fireEvent, onPressMock).

---

Outside diff comments:
In `@app/lib/methods/serializeAsciiUrl.test.ts`:
- Line 8: The jest.mock calls for 'react-native' are hoisted and cause
cross-suite leakage; update the tests in serializeAsciiUrl.test.ts to remove
per-describe jest.mock usage and instead wrap each test (or beforeEach) in
jest.isolateModules so you can call jest.mock('react-native', () => ({ Platform:
{ OS: 'ios' } })) or the Android variant inside the isolate callback and then
require the module under test (the serializeAsciiUrl import) inside that
isolateModules block; ensure each test requires the module after mocking so
Platform.OS is correctly isolated for tests referencing serializeAsciiUrl.

---

Duplicate comments:
In `@app/views/RoomView/Banner.tsx`:
- Around line 33-34: The Banner component is passing style as an array wrapper
to <MarkdownPreview> which triggered an eslint suppression; remove the array
wrapper so the prop is passed as style={styles.bannerText} (and delete the
eslint-disable-next-line comment) and, if necessary, update MarkdownPreview's
prop type to accept StyleProp<TextStyle> so this direct style object is valid;
locate the usage in Banner.tsx (MarkdownPreview msg={text}
style={[styles.bannerText]}) and change accordingly.

---

Nitpick comments:
In @.eslintrc.js:
- Around line 19-25: The extends array currently includes both
"plugin:prettier/recommended" and the redundant "prettier"; remove the duplicate
"prettier" entry from the top-level extends list and also remove the duplicate
"prettier" entry from the TypeScript override extends to avoid redundant
inclusion (locate the extends arrays where "plugin:prettier/recommended" and
"prettier" appear and delete only the plain "prettier" entries).
- Around line 96-100: The .eslintrc.js currently disables several deprecated
`@typescript-eslint` rules; remove the dead configuration entries for
'@typescript-eslint/indent', '@typescript-eslint/no-extra-parens',
'no-spaced-func', and '@typescript-eslint/no-var-requires' (and any duplicate
occurrences of those exact rule keys elsewhere in the file) so the config no
longer contains deprecated/removed rule names; keep other valid rules like
'@typescript-eslint/no-dupe-class-members' and
'@typescript-eslint/no-empty-function' unchanged.
- Around line 45-47: The 'import/no-cycle' rule in .eslintrc.js is expensive on
large monorepos; update its configuration (the 'import/no-cycle' entry) to limit
traversal by adding a maxDepth option (e.g., set maxDepth to a small integer
like 3–5) or move/override the rule so it's only enforced in
CI/editor-independent runs (e.g., enable it in an ESLint CI override or disable
it for editor integrations), ensuring you reference the 'import/no-cycle' rule
name when making the change.

In `@app/containers/List/ListRadio.tsx`:
- Line 13: In ListRadio change the discarded prop name from "_" to "_value" so
the parameter list becomes ({ value: _value, isSelected, ...rest }: IListRadio)
— update the ListRadio function signature to use _value instead of _ to satisfy
TypeScript/ESLint unused-var conventions while preserving the original prop name
context.

In `@app/containers/MessageComposer/components/Quotes/Quote.tsx`:
- Around line 52-53: The inline eslint suppression exists because style is
passed as a single-element array; update the JSX in Quote.tsx to pass the style
directly (use style={styles.message} instead of style={[styles.message]}) and
remove the eslint-disable-next-line comment; if TypeScript complains about prop
typing, adjust MarkdownPreview's prop type to accept StyleProp<TextStyle> (or
cast the value to that type) so the direct style prop is valid—look for the
MarkdownPreview prop definition and styles.message to make the change, similar
to the fix applied in DiscussionsView/Item.tsx.

In `@app/ee/omnichannel/lib/index.ts`:
- Line 56: The code instantiates Omnichannel anonymously which breaks the PR's
underscore-prefix convention; change the anonymous call to a named const (e.g.,
_omnichannel) so the instance is assigned and follows the pattern used for other
module-level side-effect instances; locate the new Omnichannel() invocation in
the module (symbol: Omnichannel) and replace it with a const declaration named
_omnichannel assigned to the new Omnichannel() instance.

In `@app/lib/encryption/room.ts`:
- Line 503: The function encryptFile currently accepts a redundant first
parameter named _rid even though file: TSendFileMessageFileInfo already contains
rid; remove the unused _rid parameter from encryptFile's signature and update
the implementation to use file.rid wherever needed (refer to encryptFile and
TSendFileMessageFileInfo), then update all callers to stop passing the extra rid
argument so they call encryptFile(file) and adjust any related type references
(e.g., TEncryptFileResult) as needed to match the new signature.

Comment on lines +59 to +61
const component = screen.getByTestId(testEncrypted.testSwitchID);
fireEvent(component, 'valueChange', { value: true });
expect(onPressMock).toHaveReturnedWith({ value: !testEncrypted.encrypted });
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

fd -e tsx -e ts SwitchItemEncrypted --exclude '*.test.*'

Repository: RocketChat/Rocket.Chat.ReactNative

Length of output: 142


🏁 Script executed:

cat -n app/views/CreateChannelView/RoomSettings/SwitchItemEncrypted.tsx

Repository: RocketChat/Rocket.Chat.ReactNative

Length of output: 1207


🏁 Script executed:

fd -e tsx -e ts SwitchItem --exclude '*.test.*' -path '*/RoomSettings/*'

Repository: RocketChat/Rocket.Chat.ReactNative

Length of output: 246


🏁 Script executed:

fd SwitchItem --exclude '*.test.*' -path '*/RoomSettings/*'

Repository: RocketChat/Rocket.Chat.ReactNative

Length of output: 246


🏁 Script executed:

fd SwitchItem --exclude '*.test.*'

Repository: RocketChat/Rocket.Chat.ReactNative

Length of output: 386


🏁 Script executed:

cat -n app/views/CreateChannelView/RoomSettings/SwitchItem.tsx

Repository: RocketChat/Rocket.Chat.ReactNative

Length of output: 2049


🏁 Script executed:

cat -n app/views/CreateChannelView/RoomSettings/SwitchItemEncrypted.test.tsx

Repository: RocketChat/Rocket.Chat.ReactNative

Length of output: 3282


getByTestId upgrade is correct, but fireEvent event data format and the assertion need fixing.

Two issues:

  1. fireEvent data format: fireEvent passes its extra arguments directly to the event handler. React Native's Switch component calls onValueChange(boolean) with a plain boolean in real usage, but the test sends fireEvent(component, 'valueChange', { value: true }), which dispatches an object instead. The mock (typed as (value: boolean) => value) receives and returns this object, violating its type contract. The event should be fireEvent(component, 'valueChange', true) (a boolean).

  2. Tautological assertion: Since testEncrypted.encrypted = false, the assertion { value: !testEncrypted.encrypted } evaluates to { value: true } — the exact object sent to fireEvent. Because the mock returns its argument unchanged, toHaveReturnedWith({ value: true }) merely confirms data passes through unmodified; it validates nothing about component behavior. Use toHaveBeenCalledWith(true) instead, which is both clearer and semantically correct for callback testing.

🛠️ Proposed fix
		const component = screen.getByTestId(testEncrypted.testSwitchID);
-		fireEvent(component, 'valueChange', { value: true });
-		expect(onPressMock).toHaveReturnedWith({ value: !testEncrypted.encrypted });
+		fireEvent(component, 'valueChange', true);
+		expect(onPressMock).toHaveBeenCalledWith(true);
📝 Committable suggestion

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

Suggested change
const component = screen.getByTestId(testEncrypted.testSwitchID);
fireEvent(component, 'valueChange', { value: true });
expect(onPressMock).toHaveReturnedWith({ value: !testEncrypted.encrypted });
const component = screen.getByTestId(testEncrypted.testSwitchID);
fireEvent(component, 'valueChange', true);
expect(onPressMock).toHaveBeenCalledWith(true);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/views/CreateChannelView/RoomSettings/SwitchItemEncrypted.test.tsx` around
lines 59 - 61, The test is sending an object instead of a boolean to the Switch
handler and asserting on the returned object rather than the call argument;
update the fireEvent call that targets
screen.getByTestId(testEncrypted.testSwitchID) to pass a plain boolean (true) —
i.e. fireEvent(component, 'valueChange', true) — and replace the tautological
expect(onPressMock).toHaveReturnedWith(...) with
expect(onPressMock).toHaveBeenCalledWith(true) so the test verifies the callback
was invoked with a boolean as the Switch would in real usage (references:
testEncrypted, testSwitchID, fireEvent, onPressMock).

@tassoevan tassoevan force-pushed the chore/stylistic-changes-1 branch from fd66233 to 800e82b Compare February 25, 2026 14:24
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
app/lib/encryption/encryption.ts (1)

599-599: LGTM — unused messageId parameter correctly prefixed.

_messageId is never used in the body; decryption depends only on path, encryption, and originalChecksum. The value is still correctly threaded through addFileToDecryptFileQueueprocessFileQueuedecryptFile, so the queue contract is unaffected.

For completeness, the messageId label in the TDecryptFile type alias (app/lib/encryption/definitions.ts:17) could be updated to _messageId to stay consistent with the implementation convention, though TypeScript does not enforce name parity between a type alias and its implementing assignment.

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

In `@app/lib/encryption/encryption.ts` at line 599, The TDecryptFile type alias's
first parameter name should be renamed from messageId to _messageId in
app/lib/encryption/definitions.ts to match the implementation's unused parameter
naming; update the parameter label in the type alias (TDecryptFile) to
_messageId so it aligns with decryptFile's signature and maintainers'
convention—no behavioural changes needed, and calls through
addFileToDecryptFileQueue and processFileQueue remain unaffected.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@app/lib/encryption/encryption.ts`:
- Line 599: The TDecryptFile type alias's first parameter name should be renamed
from messageId to _messageId in app/lib/encryption/definitions.ts to match the
implementation's unused parameter naming; update the parameter label in the type
alias (TDecryptFile) to _messageId so it aligns with decryptFile's signature and
maintainers' convention—no behavioural changes needed, and calls through
addFileToDecryptFileQueue and processFileQueue remain unaffected.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between fd66233 and 800e82b.

⛔ Files ignored due to path filters (5)
  • app/containers/Avatar/__snapshots__/Avatar.test.tsx.snap is excluded by !**/*.snap
  • app/containers/markdown/__snapshots__/Markdown.test.tsx.snap is excluded by !**/*.snap
  • app/containers/message/__snapshots__/Message.test.tsx.snap is excluded by !**/*.snap
  • app/views/DiscussionsView/__snapshots__/Item.test.tsx.snap is excluded by !**/*.snap
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (39)
  • .eslintignore
  • .eslintrc.js
  • __mocks__/react-native-mmkv.js
  • app/containers/ActionSheet/ActionSheet.tsx
  • app/containers/AudioPlayer/Seek.tsx
  • app/containers/Avatar/Avatar.stories.tsx
  • app/containers/Avatar/AvatarContainer.tsx
  • app/containers/Avatar/AvatarWithEdit.tsx
  • app/containers/List/ListRadio.tsx
  • app/containers/MessageComposer/components/Quotes/Quote.tsx
  • app/containers/MessageComposer/helpers/getMentionRegexp.test.js
  • app/containers/UnreadBadge/getUnreadStyle.test.js
  • app/containers/markdown/components/emoji/Emoji.tsx
  • app/containers/message/Components/Attachments/Reply.tsx
  • app/ee/omnichannel/lib/index.ts
  • app/ee/omnichannel/views/QueueListView.tsx
  • app/lib/database/utils.test.ts
  • app/lib/encryption/encryption.ts
  • app/lib/encryption/helpers/base64-js/index.ts
  • app/lib/encryption/room.ts
  • app/lib/helpers/formatText.ts
  • app/lib/hooks/useShortnameToUnicode/index.tsx
  • app/lib/methods/search.ts
  • app/lib/methods/serializeAsciiUrl.test.ts
  • app/sagas/createChannel.js
  • app/sagas/createDiscussion.js
  • app/sagas/deepLinking.js
  • app/sagas/login.js
  • app/sagas/rooms.js
  • app/sagas/state.js
  • app/views/CreateChannelView/RoomSettings/SwitchItemEncrypted.test.tsx
  • app/views/DiscussionsView/DiscussionDetails.tsx
  • app/views/DiscussionsView/Item.tsx
  • app/views/RoomView/Banner.tsx
  • app/views/SelectServerView.tsx
  • app/views/ThreadMessagesView/Item.tsx
  • package.json
  • scripts/build-icon-set.js
  • tsconfig.json
💤 Files with no reviewable changes (1)
  • .eslintignore
✅ Files skipped from review due to trivial changes (3)
  • app/lib/methods/search.ts
  • app/sagas/rooms.js
  • app/views/SelectServerView.tsx
🚧 Files skipped from review as they are similar to previous changes (26)
  • app/sagas/deepLinking.js
  • app/lib/methods/serializeAsciiUrl.test.ts
  • app/views/DiscussionsView/Item.tsx
  • app/sagas/login.js
  • app/containers/UnreadBadge/getUnreadStyle.test.js
  • app/sagas/createChannel.js
  • app/views/RoomView/Banner.tsx
  • tsconfig.json
  • mocks/react-native-mmkv.js
  • app/lib/database/utils.test.ts
  • app/containers/MessageComposer/components/Quotes/Quote.tsx
  • app/ee/omnichannel/lib/index.ts
  • app/sagas/state.js
  • app/lib/encryption/helpers/base64-js/index.ts
  • app/containers/List/ListRadio.tsx
  • app/containers/message/Components/Attachments/Reply.tsx
  • app/views/DiscussionsView/DiscussionDetails.tsx
  • app/views/CreateChannelView/RoomSettings/SwitchItemEncrypted.test.tsx
  • app/containers/Avatar/AvatarWithEdit.tsx
  • app/containers/AudioPlayer/Seek.tsx
  • app/sagas/createDiscussion.js
  • app/containers/ActionSheet/ActionSheet.tsx
  • app/containers/MessageComposer/helpers/getMentionRegexp.test.js
  • app/containers/markdown/components/emoji/Emoji.tsx
  • app/views/ThreadMessagesView/Item.tsx
  • app/lib/helpers/formatText.ts
📜 Review details
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2026-02-05T13:55:00.974Z
Learnt from: Rohit3523
Repo: RocketChat/Rocket.Chat.ReactNative PR: 6930
File: package.json:101-101
Timestamp: 2026-02-05T13:55:00.974Z
Learning: In this repository, the dependency on react-native-image-crop-picker should reference the RocketChat fork (RocketChat/react-native-image-crop-picker) with explicit commit pins, not the upstream ivpusic/react-native-image-crop-picker. Update package.json dependencies (and any lockfile) to point to the fork URL and a specific commit, ensuring edge-to-edge Android fixes are included. This pattern should apply to all package.json files in the repo that declare this dependency.

Applied to files:

  • package.json
🧬 Code graph analysis (2)
app/lib/encryption/encryption.ts (1)
app/lib/encryption/definitions.ts (1)
  • TDecryptFile (18-23)
app/lib/encryption/room.ts (2)
app/definitions/IUpload.ts (1)
  • TSendFileMessageFileInfo (26-29)
app/lib/encryption/definitions.ts (1)
  • TEncryptFileResult (10-14)
🔇 Additional comments (8)
app/ee/omnichannel/views/QueueListView.tsx (1)

70-70: Nice cleanup: intentional unused parameter is explicit.

The _data rename keeps the FlatList callback signature while making non-usage clear for linting/readability.

app/lib/hooks/useShortnameToUnicode/index.tsx (1)

36-36: Good lint-safe rename for unused capture group.

Renaming to _m1 clearly marks it as intentionally unused while keeping the m2/m3 capture positions unchanged.

app/containers/Avatar/AvatarContainer.tsx (1)

74-76: LGTM — idiomatic JSX child composition.

Converting from children={children} prop to nested JSX content is semantically equivalent in React and is the conventional pattern. No functional or type-safety regression.

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

67-67: LGTM — single-element style array correctly unwrapped.

React Native's style prop accepts a plain style object directly; removing the redundant single-element array wrapper is valid and marginally more efficient (avoids an ephemeral array allocation on every render).

app/lib/encryption/room.ts (1)

503-503: LGTM — unused rid parameter correctly prefixed.

_rid is never referenced inside the method body; this.roomId is the source of truth for the room ID within EncryptionRoom. The rename accurately signals intent.

scripts/build-icon-set.js (1)

4-4: Reducer refactor preserves behavior.

The block-bodied reducer still returns the same sorted object output while improving readability.

.eslintrc.js (1)

19-33: ESLint config refactor is clean and well-scoped.

The updated base rules plus targeted TypeScript, Jest, and React Native overrides are organized clearly and align with the stated lint-consistency objective.

Also applies to: 45-73, 74-139

package.json (1)

177-178: No action needed. The @typescript-eslint versions are compatible with the repository's TypeScript version.

The npm peer dependency metadata shows no TypeScript version constraint for @typescript-eslint 7.18.0, indicating compatibility with TypeScript 5.9.3. The concern about parser/lint breakage is unfounded.

Likely an incorrect or invalid review comment.

@tassoevan tassoevan force-pushed the chore/stylistic-changes-1 branch from 800e82b to dd86d07 Compare February 25, 2026 16:45
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

♻️ Duplicate comments (1)
app/views/CreateChannelView/RoomSettings/SwitchItemEncrypted.test.tsx (1)

60-61: fireEvent payload and assertion are still incorrect.

Both issues flagged in the prior review are unaddressed:

  1. fireEvent(component, 'valueChange', { value: true }) — passes an object to a handler typed as (value: boolean) => value; the argument should be the plain boolean true.
  2. toHaveReturnedWith({ value: !testEncrypted.encrypted }) — since the mock returns its argument and the argument is { value: true }, this assertion is tautological and tests nothing meaningful. Use toHaveBeenCalledWith(true) instead.
🛠️ Proposed fix
-		fireEvent(component, 'valueChange', { value: true });
-		expect(onPressMock).toHaveReturnedWith({ value: !testEncrypted.encrypted });
+		fireEvent(component, 'valueChange', true);
+		expect(onPressMock).toHaveBeenCalledWith(true);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/views/CreateChannelView/RoomSettings/SwitchItemEncrypted.test.tsx` around
lines 60 - 61, The test fires the wrong payload and asserts the wrong behavior:
change the fireEvent call in SwitchItemEncrypted.test to pass a plain boolean
(true) to the handler (i.e., fireEvent(component, 'valueChange', true)) and
replace the tautological toHaveReturnedWith check with a meaningful call
assertion: assert that the mock onPress handler was called with true (i.e.,
toHaveBeenCalledWith(true)); refer to the test's fireEvent invocation and the
onPressMock / testEncrypted.encrypted references to locate the lines to change.
🧹 Nitpick comments (1)
.eslintrc.js (1)

19-25: Redundant 'prettier' entry in extends.

plugin:prettier/recommended (line 23) already incorporates eslint-config-prettier as its first extend, so the trailing 'prettier' on line 24 has no effect and can be removed. The same duplication exists inside the TypeScript override (line 82).

🧹 Proposed cleanup
  extends: [
    '@rocket.chat/eslint-config',
    'plugin:react/recommended',
    'plugin:react-hooks/recommended',
    'plugin:prettier/recommended',
-   'prettier'
  ],
  extends: [
    'plugin:`@typescript-eslint/recommended`',
    'plugin:`@typescript-eslint/eslint-recommended`',
    '@rocket.chat/eslint-config',
    'plugin:prettier/recommended',
-   'prettier'
  ],
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.eslintrc.js around lines 19 - 25, Remove the redundant 'prettier' entry
from the top-level extends array and the TypeScript override extends: both
already include 'plugin:prettier/recommended' which internally applies
eslint-config-prettier, so delete the duplicated 'prettier' string from the
extends arrays (look for the top-level extends and the TypeScript override where
'plugin:prettier/recommended' and 'prettier' are listed).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@app/views/CreateChannelView/RoomSettings/SwitchItemEncrypted.test.tsx`:
- Around line 60-61: The test fires the wrong payload and asserts the wrong
behavior: change the fireEvent call in SwitchItemEncrypted.test to pass a plain
boolean (true) to the handler (i.e., fireEvent(component, 'valueChange', true))
and replace the tautological toHaveReturnedWith check with a meaningful call
assertion: assert that the mock onPress handler was called with true (i.e.,
toHaveBeenCalledWith(true)); refer to the test's fireEvent invocation and the
onPressMock / testEncrypted.encrypted references to locate the lines to change.

---

Nitpick comments:
In @.eslintrc.js:
- Around line 19-25: Remove the redundant 'prettier' entry from the top-level
extends array and the TypeScript override extends: both already include
'plugin:prettier/recommended' which internally applies eslint-config-prettier,
so delete the duplicated 'prettier' string from the extends arrays (look for the
top-level extends and the TypeScript override where
'plugin:prettier/recommended' and 'prettier' are listed).

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 800e82b and dd86d07.

⛔ Files ignored due to path filters (5)
  • app/containers/Avatar/__snapshots__/Avatar.test.tsx.snap is excluded by !**/*.snap
  • app/containers/markdown/__snapshots__/Markdown.test.tsx.snap is excluded by !**/*.snap
  • app/containers/message/__snapshots__/Message.test.tsx.snap is excluded by !**/*.snap
  • app/views/DiscussionsView/__snapshots__/Item.test.tsx.snap is excluded by !**/*.snap
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (39)
  • .eslintignore
  • .eslintrc.js
  • __mocks__/react-native-mmkv.js
  • app/containers/ActionSheet/ActionSheet.tsx
  • app/containers/AudioPlayer/Seek.tsx
  • app/containers/Avatar/Avatar.stories.tsx
  • app/containers/Avatar/AvatarContainer.tsx
  • app/containers/Avatar/AvatarWithEdit.tsx
  • app/containers/List/ListRadio.tsx
  • app/containers/MessageComposer/components/Quotes/Quote.tsx
  • app/containers/MessageComposer/helpers/getMentionRegexp.test.js
  • app/containers/UnreadBadge/getUnreadStyle.test.js
  • app/containers/markdown/components/emoji/Emoji.tsx
  • app/containers/message/Components/Attachments/Reply.tsx
  • app/ee/omnichannel/lib/index.ts
  • app/ee/omnichannel/views/QueueListView.tsx
  • app/lib/database/utils.test.ts
  • app/lib/encryption/encryption.ts
  • app/lib/encryption/helpers/base64-js/index.ts
  • app/lib/encryption/room.ts
  • app/lib/helpers/formatText.ts
  • app/lib/hooks/useShortnameToUnicode/index.tsx
  • app/lib/methods/search.ts
  • app/lib/methods/serializeAsciiUrl.test.ts
  • app/sagas/createChannel.js
  • app/sagas/createDiscussion.js
  • app/sagas/deepLinking.js
  • app/sagas/login.js
  • app/sagas/rooms.js
  • app/sagas/state.js
  • app/views/CreateChannelView/RoomSettings/SwitchItemEncrypted.test.tsx
  • app/views/DiscussionsView/DiscussionDetails.tsx
  • app/views/DiscussionsView/Item.tsx
  • app/views/RoomView/Banner.tsx
  • app/views/SelectServerView.tsx
  • app/views/ThreadMessagesView/Item.tsx
  • package.json
  • scripts/build-icon-set.js
  • tsconfig.json
💤 Files with no reviewable changes (1)
  • .eslintignore
✅ Files skipped from review due to trivial changes (1)
  • app/sagas/createChannel.js
🚧 Files skipped from review as they are similar to previous changes (23)
  • app/sagas/state.js
  • app/views/RoomView/Banner.tsx
  • app/containers/UnreadBadge/getUnreadStyle.test.js
  • tsconfig.json
  • app/containers/MessageComposer/components/Quotes/Quote.tsx
  • app/sagas/deepLinking.js
  • app/containers/List/ListRadio.tsx
  • app/containers/Avatar/Avatar.stories.tsx
  • app/lib/methods/serializeAsciiUrl.test.ts
  • app/ee/omnichannel/lib/index.ts
  • app/sagas/createDiscussion.js
  • app/views/ThreadMessagesView/Item.tsx
  • app/containers/markdown/components/emoji/Emoji.tsx
  • app/containers/AudioPlayer/Seek.tsx
  • app/containers/Avatar/AvatarWithEdit.tsx
  • app/lib/encryption/encryption.ts
  • app/lib/helpers/formatText.ts
  • app/lib/database/utils.test.ts
  • app/sagas/login.js
  • app/views/DiscussionsView/Item.tsx
  • app/views/SelectServerView.tsx
  • scripts/build-icon-set.js
  • package.json
📜 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
🧠 Learnings (1)
📚 Learning: 2025-12-17T15:56:22.578Z
Learnt from: OtavioStasiak
Repo: RocketChat/Rocket.Chat.ReactNative PR: 6499
File: app/containers/ServerItem/index.tsx:34-36
Timestamp: 2025-12-17T15:56:22.578Z
Learning: In the Rocket.Chat React Native codebase, for radio button components on iOS, include the selection state ("Selected"/"Unselected") in the accessibilityLabel instead of using accessibilityState={{ checked: hasCheck }}, because iOS VoiceOver has known issues with accessibilityRole="radio" + accessibilityState that prevent correct state announcement.

Applied to files:

  • app/views/CreateChannelView/RoomSettings/SwitchItemEncrypted.test.tsx
🧬 Code graph analysis (3)
app/lib/methods/search.ts (2)
app/lib/encryption/helpers/deferred.ts (1)
  • reject (36-38)
app/lib/methods/helpers/debounce.ts (1)
  • debounce (3-25)
app/lib/encryption/room.ts (2)
app/definitions/IUpload.ts (1)
  • TSendFileMessageFileInfo (26-29)
app/lib/encryption/definitions.ts (1)
  • TEncryptFileResult (10-14)
app/ee/omnichannel/views/QueueListView.tsx (1)
app/definitions/IRoom.ts (1)
  • IOmnichannelRoom (107-143)
🔇 Additional comments (16)
app/ee/omnichannel/views/QueueListView.tsx (1)

70-70: LGTM!

Renaming the unused data parameter to _data is the correct convention to satisfy the @typescript-eslint/no-unused-vars rule for intentionally-unused parameters. The function body and behavior are unchanged.

__mocks__/react-native-mmkv.js (1)

87-87: Stylistic changes look good.

All modifications are consistent parentheses removal from single-parameter arrow functions, aligning with the Prettier/ESLint style enforcement described in the PR objectives. No behavioral changes.

Also applies to: 105-105, 113-113, 129-137, 153-161, 180-189

app/lib/encryption/helpers/base64-js/index.ts (1)

47-47: Intentional unused parameter is clearly expressed.

Line 47 is a clean, low-risk lint-alignment change; behavior remains unchanged.

app/lib/encryption/room.ts (1)

503-503: Good lint-oriented rename for an intentionally unused argument.

Line 503 keeps the API shape while making unused intent explicit; this looks correct.

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

141-141: LGTM — correct lint-driven rename.

Renaming resolve_resolve accurately signals that the resolve callback is intentionally unused; only reject is captured and assigned to debounce for the cancellation race. No behavioral change.

app/views/CreateChannelView/RoomSettings/SwitchItemEncrypted.test.tsx (1)

59-59: getByTestId is the right query for this test.

Switching from queryByTestId to getByTestId is correct here — the component is expected to be present, and getByTestId will surface a meaningful assertion failure (vs. a null-reference error later) if the element is missing.

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

171-173: LGTM!

Converting from children={data?.children} prop to nested JSX children is idiomatic React and functionally equivalent; data?.children being undefined on the initial empty-state still renders nothing correctly.

app/containers/Avatar/AvatarContainer.tsx (1)

74-76: The Avatar component's props interface (IAvatar) already explicitly includes children?: React.ReactElement | null; at the interface definition level. The component properly destructures and renders this prop, so the refactor is fully type-safe with no TypeScript errors.

app/containers/message/Components/Attachments/Reply.tsx (1)

264-264: LGTM — correct unwrap of single-element style array.

Aligns with the newly enforced react-native/no-single-element-style-arrays rule; no runtime behaviour change.

app/lib/hooks/useShortnameToUnicode/index.tsx (1)

36-48: LGTM — _m1 prefix correctly marks the unused capture group.

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

45-45: LGTM — single-element style array correctly unwrapped.

app/sagas/rooms.js (1)

21-21: LGTM — cosmetic-only removal of redundant parentheses around single arrow-function parameters throughout the file.

app/containers/MessageComposer/helpers/getMentionRegexp.test.js (1)

32-32: LGTM — quote style change to avoid backslash escaping; string value unchanged.

.eslintrc.js (3)

66-67: LGTM — react-native/no-single-element-style-arrays and react-native/no-unused-styles at error level are well-motivated.

These two new rules directly drive the mechanical fixes across Reply.tsx, DiscussionDetails.tsx, and the other style-array unwraps in this PR.


60-62: No action needed — all three React Compiler rules are properly supported.

The installed eslint-plugin-react-hooks v7.0.1 fully supports set-state-in-effect, immutability, and refs rules. These rules are properly defined in the plugin bundle with complete metadata and will function as configured in .eslintrc.js lines 60-62.

Likely an incorrect or invalid review comment.


101-107: The ESLint rule configuration with args: 'all' and argsIgnorePattern: '^_' has been properly implemented throughout the codebase. The example cited in the review—the _m1 parameter in useShortnameToUnicode—is correctly prefixed with an underscore on line 41. No remaining violations of this rule were found across the TypeScript files in the app directory. All unused callback parameters already follow the required pattern.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
app/views/DiscussionsView/Item.tsx (1)

80-81: The ESLint disable comment appears unnecessary.

Since styles.markdown is passed directly as a single style object (not wrapped in an array), the react-native/no-single-element-style-arrays rule shouldn't trigger. With the StyleProp<TextStyle> typing change in Preview.tsx, the lint suppression can be removed.

🧹 Suggested cleanup
-					{/* eslint-disable-next-line react-native/no-single-element-style-arrays */}
-					{username ? <MarkdownPreview msg={makeThreadName(item)} numberOfLines={2} style={styles.markdown} /> : null}
+					{username ? <MarkdownPreview msg={makeThreadName(item)} numberOfLines={2} style={styles.markdown} /> : null}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/views/DiscussionsView/Item.tsx` around lines 80 - 81, Remove the
unnecessary ESLint suppression: delete the comment "// eslint-disable-next-line
react-native/no-single-element-style-arrays" before the JSX that renders
MarkdownPreview since styles.markdown is passed as a single style object and the
StyleProp<TextStyle> change in Preview.tsx already prevents the rule from
triggering; update the line that renders MarkdownPreview (the JSX using
MarkdownPreview, makeThreadName(item), and styles.markdown) to have no
eslint-disable comment.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@app/views/DiscussionsView/Item.tsx`:
- Around line 80-81: Remove the unnecessary ESLint suppression: delete the
comment "// eslint-disable-next-line
react-native/no-single-element-style-arrays" before the JSX that renders
MarkdownPreview since styles.markdown is passed as a single style object and the
StyleProp<TextStyle> change in Preview.tsx already prevents the rule from
triggering; update the line that renders MarkdownPreview (the JSX using
MarkdownPreview, makeThreadName(item), and styles.markdown) to have no
eslint-disable comment.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between dd86d07 and 669dd57.

📒 Files selected for processing (2)
  • app/containers/markdown/components/Preview.tsx
  • app/views/DiscussionsView/Item.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). (1)
  • GitHub Check: ESLint and Test / run-eslint-and-test
🧰 Additional context used
🧬 Code graph analysis (2)
app/views/DiscussionsView/Item.tsx (2)
app/lib/methods/helpers/room.ts (1)
  • makeThreadName (69-70)
app/sagas/deepLinking.js (1)
  • item (71-76)
app/containers/markdown/components/Preview.tsx (1)
app/lib/constants/colors.ts (1)
  • themes (304-304)
🔇 Additional comments (1)
app/containers/markdown/components/Preview.tsx (1)

2-31: LGTM!

Good improvement to use StyleProp<TextStyle> — the idiomatic React Native type for style props. The conditional spread logic correctly handles both single style objects and arrays, and the default empty array maintains backward compatibility.

@tassoevan tassoevan requested a deployment to official_android_build February 26, 2026 17:14 — with GitHub Actions Waiting
@tassoevan tassoevan requested a deployment to experimental_ios_build February 26, 2026 17:14 — with GitHub Actions Waiting
@tassoevan tassoevan requested a deployment to experimental_android_build February 26, 2026 17:14 — with GitHub Actions Waiting
@tassoevan tassoevan requested a review from diegolmello March 2, 2026 19:02
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