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
Member

@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 linting/tooling and dependencies; streamlined ESLint/TypeScript config and stricter tsconfig checks.
  • Style / UI

    • Minor UI/layout consistency fixes across avatars, emojis, banners, replies, discussions, markdown previews and message components.
    • Adjusted children rendering in several components to improve markup consistency.
  • Tests

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

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 21, 2026

Note

Reviews paused

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

Use the following commands to manage reviews:

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

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

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/rewrote ESLint config (parser, extends, plugins, rules, overrides, react detect); enabled noUnusedLocals/noUnusedParameters in tsconfig; updated ESLint/TS-related devDependencies.
Preview typing change
app/containers/markdown/components/Preview.tsx
Changed IMarkdownPreview.style from TextStyle[] to StyleProp<TextStyle> and updated rendering to accept arrays or single style objects.
Children as Nested JSX
app/containers/ActionSheet/ActionSheet.tsx, app/containers/Avatar/AvatarContainer.tsx, app/containers/Avatar/AvatarWithEdit.tsx
Stop passing children via children 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 (style={[x]}) with direct style objects (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 retained.
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) without functional 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 simplified concise-arrow callbacks; 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 and simplified assertions/queries.
Mock & Minor Logic Tweaks
__mocks__/react-native-mmkv.js
Minor callback param syntax changes and added console.error in a catch inside 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 preserving 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 app/sagas/*, other small files
Stylistic refactors (explicit reducer return), rename unused regex/callback params to _, minor formatting and syntactic refinements across many files.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

🚥 Pre-merge checks | ✅ 2 | ❌ 3

❌ Failed checks (2 warnings, 1 inconclusive)

Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning Changes include style array simplifications and parameter renames (_unused convention) that extend beyond the linked issue's explicit objectives of lint/prettier alignment. Clarify whether parameter renaming patterns and style array refactoring are intended scope, or defer these changes to align with the original issue focus on lint configuration and formatting.
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 PR title 'chore: Code style enforcement (1/n)' is vague and generic, using non-descriptive terms that don't convey specific information about the actual changes made. Consider a more descriptive title that specifies the key changes, such as 'chore: Update ESLint and Prettier configuration to align with web project standards' or similar.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Linked Issues check ✅ Passed The PR addresses multiple objectives from NATIVE-49 including ESLint/Prettier reorganization, import resolution fixes, and TypeScript configuration updates, demonstrating progress toward established goals.

✏️ 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.

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 force-pushed the chore/stylistic-changes-1 branch from 669dd57 to 05072a6 Compare March 9, 2026 23:56
@tassoevan tassoevan requested a deployment to approve_e2e_testing March 9, 2026 23:56 — with GitHub Actions Waiting
@tassoevan tassoevan requested a deployment to experimental_ios_build March 10, 2026 00:00 — with GitHub Actions Waiting
@tassoevan tassoevan requested a deployment to official_ios_build March 10, 2026 00:00 — with GitHub Actions Waiting
@tassoevan tassoevan requested a deployment to official_android_build March 10, 2026 00:00 — with GitHub Actions Waiting
@tassoevan tassoevan requested a deployment to experimental_android_build March 10, 2026 00:00 — with GitHub Actions Waiting
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

🧹 Nitpick comments (4)
app/views/RoomView/Banner.tsx (1)

33-34: Drop the lint suppression and pass the style object directly.

MarkdownPreview now accepts StyleProp<TextStyle>, so this single-element array and the eslint disable are no longer needed. style={styles.bannerText} keeps the same behavior and stays aligned with the style cleanup in this PR.

♻️ Proposed cleanup
-						{/* eslint-disable-next-line react-native/no-single-element-style-arrays */}
-						<MarkdownPreview msg={text} style={[styles.bannerText]} />
+						<MarkdownPreview msg={text} style={styles.bannerText} />
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/views/RoomView/Banner.tsx` around lines 33 - 34, The code uses an
unnecessary single-element style array and an eslint-disable comment for
MarkdownPreview; remove the array and the eslint-disable and pass the style
object directly. In RoomView/Banner.tsx update the JSX where <MarkdownPreview
msg={text} style={[styles.bannerText]} /> is rendered to use
style={styles.bannerText} instead, and delete the preceding
eslint-disable-next-line react-native/no-single-element-style-arrays comment so
the component receives a StyleProp<TextStyle> as intended.
app/containers/markdown/components/Preview.tsx (1)

13-13: Let React Native flatten style directly.

The Array.isArray branch is extra work here. <Text style={[..., style]}> already handles objects, registered styles, nested arrays, and falsy values, so passing style through directly is simpler and avoids maintaining bespoke StyleProp normalization.

♻️ Proposed simplification
 interface IMarkdownPreview {
 	msg?: string;
 	numberOfLines?: number;
 	testID?: string;
 	style?: StyleProp<TextStyle>;
 }
 
-const MarkdownPreview = ({ msg, numberOfLines = 1, style = [], testID }: IMarkdownPreview) => {
+const MarkdownPreview = ({ msg, numberOfLines = 1, style, testID }: IMarkdownPreview) => {
 	const { theme } = useTheme();
 	const formattedText = usePreviewFormatText(msg ?? '');
@@
 		<Text
 			accessibilityLabel={m}
-			style={[
-				styles.text,
-				{ color: themes[theme].fontDefault, lineHeight: undefined },
-				...(Array.isArray(style) ? style : [style])
-			]}
+			style={[styles.text, { color: themes[theme].fontDefault, lineHeight: undefined }, style]}
 			numberOfLines={numberOfLines}
 			testID={testID || `markdown-preview-${m}`}>

Also applies to: 16-16, 27-30

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

In `@app/containers/markdown/components/Preview.tsx` at line 13, The Preview
component currently manually normalizes the style prop with Array.isArray;
remove that custom normalization and pass the style prop directly into the
Text/React Native elements (e.g., replace constructs that build style with [...,
style] to use style as-is), keeping the prop type as style?:
StyleProp<TextStyle>; and apply the same simplification to the other occurrences
noted (lines referenced around the Preview render and the blocks at 16 and
27-30) so React Native handles flattening of objects, registered styles, nested
arrays, and falsy values natively.
.eslintrc.js (2)

77-82: Same redundancy: prettier after plugin:prettier/recommended.

The TypeScript override has the same redundant 'prettier' entry.

🧹 Proposed fix
 			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 77 - 82, Remove the redundant 'prettier' entry
that appears after 'plugin:prettier/recommended' in the extends array of
.eslintrc.js and also remove the duplicate 'prettier' in the TypeScript
override's extends; update the extends lists so each only includes
'plugin:prettier/recommended' (remove the plain 'prettier') to eliminate
duplication.

19-25: Redundant prettier in extends array.

plugin:prettier/recommended already includes eslint-config-prettier (the prettier config), so listing 'prettier' separately on line 24 is redundant.

🧹 Proposed fix
 	extends: [
 		'@rocket.chat/eslint-config',
 		'plugin:react/recommended',
 		'plugin:react-hooks/recommended',
-		'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, Remove the redundant 'prettier' entry
from the extends array in .eslintrc.js because 'plugin:prettier/recommended'
already includes the eslint-config-prettier config; update the extends array
(the list containing '@rocket.chat/eslint-config', 'plugin:react/recommended',
'plugin:react-hooks/recommended', 'plugin:prettier/recommended', 'prettier') by
deleting the 'prettier' item so only 'plugin:prettier/recommended' remains.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@tsconfig.json`:
- Around line 38-39: The tsconfig enables "noUnusedLocals" and
"noUnusedParameters" but because "checkJs" is disabled, these checks don't apply
to .js files (e.g., app/sagas/state.js and app/sagas/createChannel.js), leaving
JS files uncovered while TS/TSX files are enforced; fix by choosing one
approach: either enable "checkJs" in tsconfig so TypeScript will enforce
unused-variable rules in .js files (update tsconfig to set "checkJs": true) or
enable the ESLint rule "no-unused-vars" for the JavaScript files (adjust ESLint
config to turn on "no-unused-vars" for the app/ directory or add an override for
app/sagas/*), and make sure to remove the global disable that currently
nullifies ESLint's no-unused-vars.

---

Nitpick comments:
In @.eslintrc.js:
- Around line 77-82: Remove the redundant 'prettier' entry that appears after
'plugin:prettier/recommended' in the extends array of .eslintrc.js and also
remove the duplicate 'prettier' in the TypeScript override's extends; update the
extends lists so each only includes 'plugin:prettier/recommended' (remove the
plain 'prettier') to eliminate duplication.
- Around line 19-25: Remove the redundant 'prettier' entry from the extends
array in .eslintrc.js because 'plugin:prettier/recommended' already includes the
eslint-config-prettier config; update the extends array (the list containing
'@rocket.chat/eslint-config', 'plugin:react/recommended',
'plugin:react-hooks/recommended', 'plugin:prettier/recommended', 'prettier') by
deleting the 'prettier' item so only 'plugin:prettier/recommended' remains.

In `@app/containers/markdown/components/Preview.tsx`:
- Line 13: The Preview component currently manually normalizes the style prop
with Array.isArray; remove that custom normalization and pass the style prop
directly into the Text/React Native elements (e.g., replace constructs that
build style with [..., style] to use style as-is), keeping the prop type as
style?: StyleProp<TextStyle>; and apply the same simplification to the other
occurrences noted (lines referenced around the Preview render and the blocks at
16 and 27-30) so React Native handles flattening of objects, registered styles,
nested arrays, and falsy values natively.

In `@app/views/RoomView/Banner.tsx`:
- Around line 33-34: The code uses an unnecessary single-element style array and
an eslint-disable comment for MarkdownPreview; remove the array and the
eslint-disable and pass the style object directly. In RoomView/Banner.tsx update
the JSX where <MarkdownPreview msg={text} style={[styles.bannerText]} /> is
rendered to use style={styles.bannerText} instead, and delete the preceding
eslint-disable-next-line react-native/no-single-element-style-arrays comment so
the component receives a StyleProp<TextStyle> as intended.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 38e48f26-b5f9-4bf1-aac0-b90b8498aee1

📥 Commits

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

⛔ 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 (40)
  • .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/Preview.tsx
  • 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 as they are similar to previous changes (20)
  • app/views/SelectServerView.tsx
  • app/views/DiscussionsView/Item.tsx
  • app/sagas/deepLinking.js
  • app/lib/encryption/encryption.ts
  • app/containers/ActionSheet/ActionSheet.tsx
  • app/lib/database/utils.test.ts
  • app/sagas/createDiscussion.js
  • app/lib/helpers/formatText.ts
  • app/sagas/rooms.js
  • app/lib/methods/serializeAsciiUrl.test.ts
  • app/containers/MessageComposer/components/Quotes/Quote.tsx
  • app/views/CreateChannelView/RoomSettings/SwitchItemEncrypted.test.tsx
  • app/views/DiscussionsView/DiscussionDetails.tsx
  • app/sagas/login.js
  • mocks/react-native-mmkv.js
  • app/views/ThreadMessagesView/Item.tsx
  • app/containers/UnreadBadge/getUnreadStyle.test.js
  • app/containers/markdown/components/emoji/Emoji.tsx
  • app/containers/Avatar/AvatarContainer.tsx
  • scripts/build-icon-set.js
📜 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 (3)
📚 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
📚 Learning: 2026-03-05T14:28:17.265Z
Learnt from: Rohit3523
Repo: RocketChat/Rocket.Chat.ReactNative PR: 6997
File: .maestro/tests/room/message-markdown-click.yaml:28-39
Timestamp: 2026-03-05T14:28:17.265Z
Learning: In the Rocket.Chat React Native repository's Maestro test files (.maestro/tests/), regex selectors for partial/contains text matching should use the `'.*keyword.*'` pattern (both leading and trailing `.*`). The pattern `'.*keyword*.'` is incorrect — it parses as zero-or-more of the last character of the keyword followed by one required character, and will fail to match elements where the keyword appears at the end of the element's text. This applies to all Maestro YAML selector fields (text, id) in the codebase.

Applied to files:

  • app/containers/MessageComposer/helpers/getMentionRegexp.test.js
📚 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/containers/List/ListRadio.tsx
🔇 Additional comments (12)
app/containers/List/ListRadio.tsx (1)

13-13: Nice lint-safe cleanup.

Aliasing value to _ makes the intent explicit and keeps the public prop shape unchanged. The existing iOS-friendly selected/unselected accessibility label is also preserved.

Based on learnings, in the Rocket.Chat React Native codebase radio components on iOS should expose selection state in the accessibility label.

app/ee/omnichannel/lib/index.ts (1)

56-56: Looks good.

Dropping the unused binding keeps the module-level initialization intact while removing dead state. The constructor side effects still run when this module is loaded.

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

70-77: LGTM!

The underscore prefix on _data correctly signals that the parameter is intentionally unused. This is a standard convention that satisfies no-unused-vars lint rules while preserving the required function signature for getItemLayout.

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

68-68: LGTM!

The underscore prefix convention correctly signals that _event is intentionally unused while preserving the required parameter position to access ctx. This aligns with the PR's objective of fixing unused-variable rule inconsistencies.

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

141-141: Unused executor arg rename is safe.

This keeps the cancellation path unchanged while making the intentionally unused parameter explicit.

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

36-36: Regex callback rename looks good.

Only the unused capture parameter changed, so the replacement logic remains intact.

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

47-48: Private helper rename is behavior-preserving.

The calculation still depends only on validLen and placeHoldersLen; this just makes the unused argument explicit.

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

503-503: Unused rid rename is fine here.

The parameter was already unused in this method, so the underscore prefix improves intent without changing behavior.

.eslintrc.js (3)

101-107: Good: Underscore prefix pattern for unused parameters.

argsIgnorePattern: '^_' aligns with the PR objective to resolve unused-variable rule inconsistencies and follows a common convention for intentionally unused parameters.


14-16: Good: React version auto-detection.

Setting version: 'detect' avoids hardcoding the React version and prevents the "React version not specified" warning.


60-62: The rules set-state-in-effect, immutability, and refs are all supported in eslint-plugin-react-hooks v7.0.1.

package.json (1)

183-190: All flagged ESLint plugin versions exist on npm and are valid. No installation issues will occur.

			> Likely an incorrect or invalid review comment.

Comment on lines +38 to +39
"noUnusedLocals": true, /* Report errors on unused locals. */
"noUnusedParameters": true, /* Report errors on unused parameters. */
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 | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== tsconfig relevant flags =="
sed -n '1,120p' tsconfig.json | rg -n '"allowJs"|"checkJs"|"noUnusedLocals"|"noUnusedParameters"'

echo
echo "== eslint configs mentioning unused-var rules =="
fd -HI '(^|/)(eslint\.config\.(js|cjs|mjs)|\.eslintrc(\.(js|cjs|json|yaml|yml))?)$' -E node_modules -x sh -c '
  echo "--- {} ---"
  sed -n "1,260p" "{}" | rg -n "no-unused-vars|@typescript-eslint/no-unused-vars|overrides|files"
'

echo
echo "== representative JS files in this PR context =="
printf "%s\n" app/sagas/state.js app/sagas/createChannel.js

Repository: RocketChat/Rocket.Chat.ReactNative

Length of output: 912


🏁 Script executed:

sed -n '135,180p' .eslintrc.js

Repository: RocketChat/Rocket.Chat.ReactNative

Length of output: 188


JS files have no unused-var enforcement.

With checkJs disabled, TypeScript's noUnusedLocals and noUnusedParameters (lines 38–39) only apply to TS/TSX files. JavaScript files like app/sagas/state.js and app/sagas/createChannel.js rely on ESLint, which has no-unused-vars globally disabled. This creates inconsistent enforcement: TS/TSX files enforce unused variables, but JS files do not. If this PR aims to address unused-variable handling uniformly, consider either enabling checkJs for TypeScript checks on .js files or activating no-unused-vars in ESLint for JavaScript files in the app/ directory.

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

In `@tsconfig.json` around lines 38 - 39, The tsconfig enables "noUnusedLocals"
and "noUnusedParameters" but because "checkJs" is disabled, these checks don't
apply to .js files (e.g., app/sagas/state.js and app/sagas/createChannel.js),
leaving JS files uncovered while TS/TSX files are enforced; fix by choosing one
approach: either enable "checkJs" in tsconfig so TypeScript will enforce
unused-variable rules in .js files (update tsconfig to set "checkJs": true) or
enable the ESLint rule "no-unused-vars" for the JavaScript files (adjust ESLint
config to turn on "no-unused-vars" for the app/ directory or add an override for
app/sagas/*), and make sure to remove the global disable that currently
nullifies ESLint's no-unused-vars.

Comment on lines +77 to +78
{/* eslint-disable-next-line react-native/no-single-element-style-arrays */}
{username ? <MarkdownPreview msg={makeThreadName(item)} numberOfLines={2} style={styles.markdown} /> : null}
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
{/* eslint-disable-next-line react-native/no-single-element-style-arrays */}
{username ? <MarkdownPreview msg={makeThreadName(item)} numberOfLines={2} style={styles.markdown} /> : null}
{/* eslint-disable-next-line react-native/no-single-element-style-arrays */}
{username ? <MarkdownPreview msg={makeThreadName(item)} numberOfLines={2} style={[styles.markdown]} /> : null}

Copy link
Member Author

Choose a reason for hiding this comment

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

I think I've changed MarkdownPreview to handle it:

const MarkdownPreview = ({ msg, numberOfLines = 1, style = [], testID }: IMarkdownPreview) => {
	const { theme } = useTheme();
	const formattedText = usePreviewFormatText(msg ?? '');

	if (!msg) {
		return null;
	}
	const m = formattedText;
	return (
		<Text
			accessibilityLabel={m}
			style={[
				styles.text,
				{ color: themes[theme].fontDefault, lineHeight: undefined },
				...(Array.isArray(style) ? style : [style]) // HERE!!!
			]}
			numberOfLines={numberOfLines}
			testID={testID || `markdown-preview-${m}`}>
			{m}
		</Text>
	);
};

Copy link
Member

@diegolmello diegolmello Mar 11, 2026

Choose a reason for hiding this comment

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

Got it, but shouldn't you remove {/* eslint-disable-next-line react-native/no-single-element-style-arrays */} then?
You could also apply this fix to the other places you added the inline lint.

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