feat(a11y): Message actions announcement and back focus#7229
feat(a11y): Message actions announcement and back focus#7229OtavioStasiak wants to merge 31 commits into
Conversation
|
Important Review skippedReview was skipped due to path filters ⛔ Files ignored due to path filters (1)
CodeRabbit blocks several paths by default. You can override this behavior by explicitly including those paths in the path filters. For example, including ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
WalkthroughAdds accessibility focus tracking and restoration for message action sheets: shared last-focused message ref, message accessibility label/action utilities and tests, Touch/Handle ref forwarding, action-sheet header focus on present, and focus restoration on dismiss. ChangesAccessibility Focus Restoration Workflow
Sequence DiagramsequenceDiagram
participant User
participant MessageTouchable
participant lastFocusedRef as lastFocusedMessageRef
participant MessageActions
participant ActionSheet
participant Handle
participant AccessibilityInfo
User->>MessageTouchable: Long press / accessibility action
MessageTouchable->>lastFocusedRef: markAsLastFocused()
MessageTouchable->>MessageActions: open message actions
MessageActions->>ActionSheet: showActionSheet(onClose)
ActionSheet->>ActionSheet: onDidPresent
ActionSheet->>Handle: focusHandle -> findNodeHandle(handleRef)
Handle->>AccessibilityInfo: setAccessibilityFocus(header) (defer 300ms on Android)
User->>ActionSheet: Dismiss
ActionSheet->>lastFocusedRef: get() -> messageRef
ActionSheet->>AccessibilityInfo: setAccessibilityFocus(messageRef) (after animation)
ActionSheet->>lastFocusedRef: clear()
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Suggested labelstype: feature 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. Warning Review ran into problems🔥 ProblemsErrors were encountered while retrieving linked issues. Errors (1)
Tip 💬 Introducing Slack Agent: The best way for teams to turn conversations into code.Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.
Built for teams:
One agent for your entire SDLC. Right inside Slack. 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. Comment |
|
Android Build Available Rocket.Chat Experimental 4.72.0.108617 Internal App Sharing: https://play.google.com/apps/test/RQVpXLytHNc/ahAO29uNR-q4kPySm10tUnMpVhAS_0xW-fB4K8AaSET3MuDoXjn9hXgrmFsio_VEihbYHT191fB6aC8vRNjhGD5Ibp |
|
iOS Build Available Rocket.Chat Experimental 4.72.0.108618 |
There was a problem hiding this comment.
Actionable comments posted: 4
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@app/lib/a11y/useMessageAccessibilityLabel.test.ts`:
- Around line 33-41: The test suite is missing a case for isThreadReply when
tmid is falsy which exposes a bug in useMessageAccessibilityLabel where the
implementation mistakenly references props instead of props.msg (causing
“[object Object]” in the label); add the proposed test case (it('handles
isThreadReply without tmid', ...) asserting the label contains 'replying to' and
'hello world' and not '[object Object]') and fix the implementation in
useMessageAccessibilityLabel by replacing any erroneous uses of props with
props.msg (ensure all message field accesses come from props.msg and handle tmid
undefined correctly so the accessibility label builds from the message text).
In `@app/lib/a11y/useMessageAccessibilityLabel.ts`:
- Line 28: The accessibility label construction in useMessageAccessibilityLabel
sets label to `replying to ${props.tmid ? \`thread message ${props.msg}\` :
props}` which falls back to the entire props object when tmid is falsy; update
the fallback to use props.msg (or a safe string) instead of props so the label
becomes `replying to ${props.tmid ? \`thread message ${props.msg}\` :
props.msg}` (ensure you reference the label assignment in
useMessageAccessibilityLabel and handle missing/undefined props.msg with a
sensible default).
- Around line 33-46: In useMessageAccessibilityLabel, you're duplicating the
"Encrypted_message" string by setting label = i18n.t('Encrypted_message') when
props.isEncrypted and also appending encryptedMessageLabel = props.isEncrypted ?
i18n.t('Encrypted_message') : ''; remove the redundant encryptedMessageLabel
assignment (or its inclusion in the final concatenation) so the encrypted
message text appears only once, keeping the initial label setting when
props.isEncrypted and leaving readReceipt/other suffixes intact.
- Line 37: The code is suppressing a real TypeScript error with // `@ts-ignore`
when calling getInfoMessage from useMessageAccessibilityLabel; instead extract
and pass only the required properties (type, role, msg, author: { username:
string }, and optional comment) from the incoming IMessageTouchable & IMessage
object rather than spreading ...props. Update the call to getInfoMessage to
build a new plain object using props.type, props.role, props.msg, props.comment
(if present) and author: { username: props.author.username } (converting from
IUserMessage), remove the // `@ts-ignore`, and ensure the argument matches the
expected shape so the TS error is resolved.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: fb62eaa2-72bd-4202-b41e-69536d992978
📒 Files selected for processing (29)
app/containers/message/Message.tsxapp/i18n/locales/ar.jsonapp/i18n/locales/bn-IN.jsonapp/i18n/locales/cs.jsonapp/i18n/locales/de.jsonapp/i18n/locales/es.jsonapp/i18n/locales/fi.jsonapp/i18n/locales/fr.jsonapp/i18n/locales/hi-IN.jsonapp/i18n/locales/hu.jsonapp/i18n/locales/it.jsonapp/i18n/locales/ja.jsonapp/i18n/locales/nl.jsonapp/i18n/locales/nn.jsonapp/i18n/locales/no.jsonapp/i18n/locales/pt-BR.jsonapp/i18n/locales/pt-PT.jsonapp/i18n/locales/ru.jsonapp/i18n/locales/sl-SI.jsonapp/i18n/locales/sv.jsonapp/i18n/locales/ta-IN.jsonapp/i18n/locales/te-IN.jsonapp/i18n/locales/tr.jsonapp/i18n/locales/zh-CN.jsonapp/i18n/locales/zh-TW.jsonapp/lib/a11y/useMessageAccessibilityActions.test.tsapp/lib/a11y/useMessageAccessibilityActions.tsapp/lib/a11y/useMessageAccessibilityLabel.test.tsapp/lib/a11y/useMessageAccessibilityLabel.ts
✅ Files skipped from review due to trivial changes (20)
- app/i18n/locales/es.json
- app/lib/a11y/useMessageAccessibilityActions.test.ts
- app/i18n/locales/pt-PT.json
- app/i18n/locales/ar.json
- app/i18n/locales/tr.json
- app/i18n/locales/no.json
- app/i18n/locales/pt-BR.json
- app/i18n/locales/it.json
- app/i18n/locales/sl-SI.json
- app/i18n/locales/ru.json
- app/i18n/locales/ja.json
- app/i18n/locales/bn-IN.json
- app/i18n/locales/fr.json
- app/i18n/locales/nl.json
- app/i18n/locales/ta-IN.json
- app/i18n/locales/zh-CN.json
- app/i18n/locales/nn.json
- app/i18n/locales/te-IN.json
- app/i18n/locales/fi.json
- app/i18n/locales/hu.json
🚧 Files skipped from review as they are similar to previous changes (1)
- app/containers/message/Message.tsx
📜 Review details
🧰 Additional context used
📓 Path-based instructions (5)
**/*.{js,ts,jsx,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{js,ts,jsx,tsx}: Use descriptive names for functions, variables, and classes that clearly convey their purpose
Write comments that explain the 'why' behind code decisions, not the 'what'
Keep functions small and focused on a single responsibility
Use const by default, let when reassignment is needed, and avoid var
Prefer async/await over .then() chains for handling asynchronous operations
Use explicit error handling with try/catch blocks for async operations
Avoid deeply nested code; refactor complex logic into helper functions
Files:
app/lib/a11y/useMessageAccessibilityActions.tsapp/lib/a11y/useMessageAccessibilityLabel.test.tsapp/lib/a11y/useMessageAccessibilityLabel.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{ts,tsx}: Use TypeScript for type safety; add explicit type annotations to function parameters and return types
Prefer interfaces over type aliases for defining object shapes in TypeScript
Use enums for sets of related constants rather than magic strings or numbers
Files:
app/lib/a11y/useMessageAccessibilityActions.tsapp/lib/a11y/useMessageAccessibilityLabel.test.tsapp/lib/a11y/useMessageAccessibilityLabel.ts
**/*.{ts,tsx,js,jsx,json}
📄 CodeRabbit inference engine (CLAUDE.md)
Use Prettier formatting with tabs, single quotes, 130 character width, no trailing commas, avoid arrow parens, and bracket same line
Files:
app/lib/a11y/useMessageAccessibilityActions.tsapp/i18n/locales/cs.jsonapp/i18n/locales/hi-IN.jsonapp/i18n/locales/de.jsonapp/lib/a11y/useMessageAccessibilityLabel.test.tsapp/i18n/locales/zh-TW.jsonapp/i18n/locales/sv.jsonapp/lib/a11y/useMessageAccessibilityLabel.ts
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Use ESLint with
@rocket.chat/eslint-configbase including React, React Native, TypeScript, and Jest plugins
Files:
app/lib/a11y/useMessageAccessibilityActions.tsapp/lib/a11y/useMessageAccessibilityLabel.test.tsapp/lib/a11y/useMessageAccessibilityLabel.ts
app/i18n/**/*.{ts,tsx,json}
📄 CodeRabbit inference engine (CLAUDE.md)
Place i18n configuration and locale files in 'app/i18n/' directory with support for 40+ locales and RTL
Files:
app/i18n/locales/cs.jsonapp/i18n/locales/hi-IN.jsonapp/i18n/locales/de.jsonapp/i18n/locales/zh-TW.jsonapp/i18n/locales/sv.json
🧠 Learnings (1)
📚 Learning: 2026-04-30T17:07:51.020Z
Learnt from: diegolmello
Repo: RocketChat/Rocket.Chat.ReactNative PR: 7274
File: app/lib/services/voip/MediaCallEvents.ts:0-0
Timestamp: 2026-04-30T17:07:51.020Z
Learning: In this Rocket.Chat React Native codebase, the ESLint rule `no-void: error` is enforced. When you see a promise returned from an async call that is not awaited (a “floating promise”), do not silence it with the `void somePromise()` pattern. Instead, handle the promise explicitly by attaching `.catch(...)` (or otherwise awaiting/handling the error) so unhandled-rejection risks are addressed in a way that satisfies the existing ESLint configuration.
Applied to files:
app/lib/a11y/useMessageAccessibilityActions.tsapp/lib/a11y/useMessageAccessibilityLabel.test.tsapp/lib/a11y/useMessageAccessibilityLabel.ts
🔇 Additional comments (6)
app/i18n/locales/cs.json (1)
12-12: LGTM!app/i18n/locales/de.json (1)
12-12: LGTM!app/i18n/locales/hi-IN.json (1)
12-12: LGTM!app/i18n/locales/sv.json (1)
12-12: LGTM!app/i18n/locales/zh-TW.json (1)
8-8: LGTM!app/lib/a11y/useMessageAccessibilityActions.ts (1)
5-12: LGTM!
…ew thread" hint to message accessibility label
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (4)
app/lib/a11y/useMessageAccessibilityLabel.ts (3)
28-28:⚠️ Potential issue | 🔴 Critical | ⚡ Quick winFix object-to-string coercion bug.
When
isThreadReplyis true andtmidis falsy, the fallback usesprops(the entire object) instead ofprops.msg, which will produce[object Object]in the accessibility label.🐛 Proposed fix
if (props.isThreadReply) { - label = `replying to ${props.tmid ? `thread message ${props.msg}` : props}`; + label = `replying to ${props.tmid ? `thread message ${props.msg}` : props.msg}`; }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@app/lib/a11y/useMessageAccessibilityLabel.ts` at line 28, The accessibility label construction in useMessageAccessibilityLabel is coercing the whole props object to string when tmid is falsy; update the label assignment so the fallback uses props.msg (not props) when building the "replying to" string (i.e., change the expression that currently does `props.tmid ? \`thread message ${props.msg}\` : props` to use `: props.msg`), ensuring you reference the label variable and props.tmid/props.msg in the fix.
36-39:⚠️ Potential issue | 🟠 Major | ⚡ Quick winPass only required properties to
getInfoMessageinstead of using@ts-ignore.The
@ts-ignoresuppresses a real type mismatch:getInfoMessageexpects specific properties includingauthor: { username: string }, but spreading...propspasses the entireIMessageTouchable & IMessageobject withauthorasIUserMessage(which has additional fields beyondusername).🔧 Suggested fix
if (props.isInfo) { - // `@ts-ignore` - label = getInfoMessage({ ...props }); + label = getInfoMessage({ + type: props.type, + role: props.role, + msg: props.msg, + author: { username: props.author?.username || '' }, + comment: props.comment + }); }As per coding guidelines: "Use explicit error handling" and "Use TypeScript for type safety; add explicit type annotations to function parameters and return types."
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@app/lib/a11y/useMessageAccessibilityLabel.ts` around lines 36 - 39, The code currently ignores TS errors when calling getInfoMessage by spreading ...props; instead remove the `@ts-ignore` and call getInfoMessage with an explicit object containing only the properties that getInfoMessage expects (for example pass author: { username: props.author.username } and any other required fields rather than the full IMessage/IMessageTouchable), e.g. build a small payload from props when props.isInfo is true and pass that to getInfoMessage; this preserves type safety and avoids passing an IUserMessage with extra fields.
33-53:⚠️ Potential issue | 🟠 Major | ⚡ Quick winRemove duplicate "Encrypted message" in final label.
When
isEncryptedis true,labelis set toi18n.t('Encrypted_message')at line 34, andencryptedMessageLabelis also set to the same string at line 46. Both are concatenated in the return statement at line 53, causing "Encrypted message" to appear twice.♻️ Proposed fix: remove the duplicate assignment
const readOrUnreadLabel = !props.unread && props.unread !== null ? i18n.t('Message_was_read') : i18n.t('Message_was_not_read'); const readReceipt = props.isReadReceiptEnabled && !props.isInfo ? readOrUnreadLabel : ''; - const encryptedMessageLabel = props.isEncrypted ? i18n.t('Encrypted_message') : ''; const translatedLanguage = translationLanguages[props?.autoTranslateLanguage || 'en']; const translated = props.isTranslated ? i18n.t('Message_translated_into_idiom', { idiom: translatedLanguage }) : ''; const isThread = !props.isInfo && !!(props.tmid || props.tcount || props.isThreadReply || props.isThreadSequential); const threadHint = isThread ? `. ${i18n.t('A11y_press_to_view_thread')}` : ''; return props.isTranslated ? `${user} ${hour} ${translated}${threadHint}` - : `${user} ${hour} ${translated} ${label}. ${encryptedMessageLabel} ${readReceipt}${threadHint}`; + : `${user} ${hour} ${translated} ${label}. ${readReceipt}${threadHint}`;🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@app/lib/a11y/useMessageAccessibilityLabel.ts` around lines 33 - 53, The return value duplicates the "Encrypted_message" because label is set to i18n.t('Encrypted_message') when props.isEncrypted and encryptedMessageLabel is also appended; in useMessageAccessibilityLabel remove the redundant assignment by not overriding label for encrypted messages (delete or skip the if (props.isEncrypted) { label = i18n.t('Encrypted_message'); } block) so encryptedMessageLabel remains the single source for that phrase (keep references to label, encryptedMessageLabel, and the final return unchanged).app/lib/a11y/useMessageAccessibilityLabel.test.ts (1)
100-103: 🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick winEnhance test to catch the object-to-string coercion bug.
This test sets
isThreadReply: truewithout atmid(sincebasePropsdoesn't include it), which triggers the critical bug at line 28 of the implementation wherepropsis used instead ofprops.msg. However, the test only checks for the thread hint and doesn't verify the actual label content, so it misses the[object Object]bug.✅ Enhanced test case
it('appends "Press to view thread" hint when message is a thread reply', () => { const { result } = renderHook(() => useMessageAccessibilityLabel({ ...baseProps, isThreadReply: true })); + expect(result.current).toContain('replying to hello world'); + expect(result.current).not.toContain('[object Object]'); expect(result.current).toContain('Press to view thread'); });🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@app/lib/a11y/useMessageAccessibilityLabel.test.ts` around lines 100 - 103, The test for useMessageAccessibilityLabel misses the object-to-string coercion bug because it sets isThreadReply: true without asserting the full label or checking for "[object Object]"; update the test that uses baseProps and isThreadReply to include a realistic msg object (ensure baseProps.msg is present), call useMessageAccessibilityLabel with isThreadReply: true and no tmid, then assert the returned label contains the expected readable text (e.g., the message text and "Press to view thread") and explicitly assert it does NOT contain the substring "[object Object]" so the implementation bug where props is used instead of props.msg is caught; reference useMessageAccessibilityLabel, baseProps, isThreadReply, tmid and props.msg when making the assertion.
🧹 Nitpick comments (1)
app/lib/a11y/useMessageAccessibilityLabel.test.ts (1)
5-18: ⚡ Quick winReplace
anytype with proper interface.Using
anyforbasePropsdefeats TypeScript's type checking. Define an explicit type matchingIMessageTouchable & IMessageor import theParamstype from the implementation.♻️ Suggested fix
+import { type IMessage, type IMessageTouchable } from '../../containers/message/interfaces'; + import { renderHook } from '@testing-library/react-native'; import { useMessageAccessibilityLabel } from './useMessageAccessibilityLabel'; -const baseProps: any = { +const baseProps: IMessageTouchable & IMessage = { msg: 'hello world', author: { username: 'john', name: 'John Doe' },As per coding guidelines: "Use TypeScript for type safety; add explicit type annotations to function parameters and return types."
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@app/lib/a11y/useMessageAccessibilityLabel.test.ts` around lines 5 - 18, The test uses baseProps: any which disables type checking; change baseProps to use the proper interface by importing and applying the correct type (e.g., IMessageTouchable & IMessage or the Params type exported by useMessageAccessibilityLabel) and annotate the constant accordingly; ensure all fields in baseProps match the selected interface (msg, author, ts, isInfo, isThreadReply, isThreadSequential, isEncrypted, isTranslated, isReadReceiptEnabled, useRealName, unread, type) and update any missing/incorrect property names to satisfy the type.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@app/lib/a11y/useMessageAccessibilityLabel.ts`:
- Line 47: The lookup for translatedLanguage using
translationLanguages[props?.autoTranslateLanguage || 'en'] can yield undefined
if props.autoTranslateLanguage is not a key; update the logic in
useMessageAccessibilityLabel so you coalesce missing keys to a safe default
(e.g., 'en' or translationLanguages['en']) before interpolation: check
translationLanguages[props?.autoTranslateLanguage] and fall back to
translationLanguages['en'] (or a hardcoded string) when undefined, then use that
safe translatedLanguage value for the i18n string to avoid "translated into
undefined".
---
Duplicate comments:
In `@app/lib/a11y/useMessageAccessibilityLabel.test.ts`:
- Around line 100-103: The test for useMessageAccessibilityLabel misses the
object-to-string coercion bug because it sets isThreadReply: true without
asserting the full label or checking for "[object Object]"; update the test that
uses baseProps and isThreadReply to include a realistic msg object (ensure
baseProps.msg is present), call useMessageAccessibilityLabel with isThreadReply:
true and no tmid, then assert the returned label contains the expected readable
text (e.g., the message text and "Press to view thread") and explicitly assert
it does NOT contain the substring "[object Object]" so the implementation bug
where props is used instead of props.msg is caught; reference
useMessageAccessibilityLabel, baseProps, isThreadReply, tmid and props.msg when
making the assertion.
In `@app/lib/a11y/useMessageAccessibilityLabel.ts`:
- Line 28: The accessibility label construction in useMessageAccessibilityLabel
is coercing the whole props object to string when tmid is falsy; update the
label assignment so the fallback uses props.msg (not props) when building the
"replying to" string (i.e., change the expression that currently does
`props.tmid ? \`thread message ${props.msg}\` : props` to use `: props.msg`),
ensuring you reference the label variable and props.tmid/props.msg in the fix.
- Around line 36-39: The code currently ignores TS errors when calling
getInfoMessage by spreading ...props; instead remove the `@ts-ignore` and call
getInfoMessage with an explicit object containing only the properties that
getInfoMessage expects (for example pass author: { username:
props.author.username } and any other required fields rather than the full
IMessage/IMessageTouchable), e.g. build a small payload from props when
props.isInfo is true and pass that to getInfoMessage; this preserves type safety
and avoids passing an IUserMessage with extra fields.
- Around line 33-53: The return value duplicates the "Encrypted_message" because
label is set to i18n.t('Encrypted_message') when props.isEncrypted and
encryptedMessageLabel is also appended; in useMessageAccessibilityLabel remove
the redundant assignment by not overriding label for encrypted messages (delete
or skip the if (props.isEncrypted) { label = i18n.t('Encrypted_message'); }
block) so encryptedMessageLabel remains the single source for that phrase (keep
references to label, encryptedMessageLabel, and the final return unchanged).
---
Nitpick comments:
In `@app/lib/a11y/useMessageAccessibilityLabel.test.ts`:
- Around line 5-18: The test uses baseProps: any which disables type checking;
change baseProps to use the proper interface by importing and applying the
correct type (e.g., IMessageTouchable & IMessage or the Params type exported by
useMessageAccessibilityLabel) and annotate the constant accordingly; ensure all
fields in baseProps match the selected interface (msg, author, ts, isInfo,
isThreadReply, isThreadSequential, isEncrypted, isTranslated,
isReadReceiptEnabled, useRealName, unread, type) and update any
missing/incorrect property names to satisfy the type.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: efe12536-326d-4e0d-8d78-8cd19ca5bb62
📒 Files selected for processing (30)
app/containers/MessageActions/index.tsxapp/containers/message/Message.tsxapp/i18n/locales/ar.jsonapp/i18n/locales/bn-IN.jsonapp/i18n/locales/cs.jsonapp/i18n/locales/de.jsonapp/i18n/locales/en.jsonapp/i18n/locales/es.jsonapp/i18n/locales/fi.jsonapp/i18n/locales/fr.jsonapp/i18n/locales/hi-IN.jsonapp/i18n/locales/hu.jsonapp/i18n/locales/it.jsonapp/i18n/locales/ja.jsonapp/i18n/locales/nl.jsonapp/i18n/locales/nn.jsonapp/i18n/locales/no.jsonapp/i18n/locales/pt-BR.jsonapp/i18n/locales/pt-PT.jsonapp/i18n/locales/ru.jsonapp/i18n/locales/sl-SI.jsonapp/i18n/locales/sv.jsonapp/i18n/locales/ta-IN.jsonapp/i18n/locales/te-IN.jsonapp/i18n/locales/tr.jsonapp/i18n/locales/zh-CN.jsonapp/i18n/locales/zh-TW.jsonapp/lib/a11y/useLastFocusedMessageRef.tsapp/lib/a11y/useMessageAccessibilityLabel.test.tsapp/lib/a11y/useMessageAccessibilityLabel.ts
✅ Files skipped from review due to trivial changes (10)
- app/i18n/locales/fi.json
- app/i18n/locales/es.json
- app/i18n/locales/hu.json
- app/i18n/locales/ar.json
- app/i18n/locales/cs.json
- app/i18n/locales/hi-IN.json
- app/i18n/locales/it.json
- app/i18n/locales/de.json
- app/i18n/locales/sl-SI.json
- app/i18n/locales/ta-IN.json
🚧 Files skipped from review as they are similar to previous changes (15)
- app/i18n/locales/nn.json
- app/lib/a11y/useLastFocusedMessageRef.ts
- app/i18n/locales/pt-PT.json
- app/i18n/locales/bn-IN.json
- app/i18n/locales/fr.json
- app/i18n/locales/zh-TW.json
- app/i18n/locales/te-IN.json
- app/i18n/locales/sv.json
- app/i18n/locales/nl.json
- app/i18n/locales/en.json
- app/i18n/locales/pt-BR.json
- app/i18n/locales/ja.json
- app/containers/MessageActions/index.tsx
- app/i18n/locales/ru.json
- app/i18n/locales/no.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). (2)
- GitHub Check: ESLint and Test / run-eslint-and-test
- GitHub Check: format
🧰 Additional context used
📓 Path-based instructions (6)
**/*.{ts,tsx,js,jsx,json}
📄 CodeRabbit inference engine (CLAUDE.md)
Use Prettier formatting with tabs, single quotes, 130 character width, no trailing commas, avoid arrow parens, and bracket same line
Files:
app/i18n/locales/zh-CN.jsonapp/i18n/locales/tr.jsonapp/lib/a11y/useMessageAccessibilityLabel.test.tsapp/lib/a11y/useMessageAccessibilityLabel.tsapp/containers/message/Message.tsx
app/i18n/**/*.{ts,tsx,json}
📄 CodeRabbit inference engine (CLAUDE.md)
Place i18n configuration and locale files in 'app/i18n/' directory with support for 40+ locales and RTL
Files:
app/i18n/locales/zh-CN.jsonapp/i18n/locales/tr.json
**/*.{js,ts,jsx,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{js,ts,jsx,tsx}: Use descriptive names for functions, variables, and classes that clearly convey their purpose
Write comments that explain the 'why' behind code decisions, not the 'what'
Keep functions small and focused on a single responsibility
Use const by default, let when reassignment is needed, and avoid var
Prefer async/await over .then() chains for handling asynchronous operations
Use explicit error handling with try/catch blocks for async operations
Avoid deeply nested code; refactor complex logic into helper functions
Files:
app/lib/a11y/useMessageAccessibilityLabel.test.tsapp/lib/a11y/useMessageAccessibilityLabel.tsapp/containers/message/Message.tsx
**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{ts,tsx}: Use TypeScript for type safety; add explicit type annotations to function parameters and return types
Prefer interfaces over type aliases for defining object shapes in TypeScript
Use enums for sets of related constants rather than magic strings or numbers
Files:
app/lib/a11y/useMessageAccessibilityLabel.test.tsapp/lib/a11y/useMessageAccessibilityLabel.tsapp/containers/message/Message.tsx
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Use ESLint with
@rocket.chat/eslint-configbase including React, React Native, TypeScript, and Jest plugins
Files:
app/lib/a11y/useMessageAccessibilityLabel.test.tsapp/lib/a11y/useMessageAccessibilityLabel.tsapp/containers/message/Message.tsx
app/containers/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Place reusable UI components in 'app/containers/' directory
Files:
app/containers/message/Message.tsx
🧠 Learnings (1)
📚 Learning: 2026-04-30T17:07:51.020Z
Learnt from: diegolmello
Repo: RocketChat/Rocket.Chat.ReactNative PR: 7274
File: app/lib/services/voip/MediaCallEvents.ts:0-0
Timestamp: 2026-04-30T17:07:51.020Z
Learning: In this Rocket.Chat React Native codebase, the ESLint rule `no-void: error` is enforced. When you see a promise returned from an async call that is not awaited (a “floating promise”), do not silence it with the `void somePromise()` pattern. Instead, handle the promise explicitly by attaching `.catch(...)` (or otherwise awaiting/handling the error) so unhandled-rejection risks are addressed in a way that satisfies the existing ESLint configuration.
Applied to files:
app/lib/a11y/useMessageAccessibilityLabel.test.tsapp/lib/a11y/useMessageAccessibilityLabel.tsapp/containers/message/Message.tsx
🔇 Additional comments (4)
app/i18n/locales/tr.json (1)
8-8: LGTM!Also applies to: 12-12
app/i18n/locales/zh-CN.json (1)
8-8: LGTM!Also applies to: 12-12
app/containers/message/Message.tsx (1)
176-218: LGTM!app/lib/a11y/useMessageAccessibilityLabel.ts (1)
57-57: No action needed. The'use memo'directive is a valid React Compiler directive, properly documented at react.dev/reference/react-compiler/directives, and correctly placed at the beginning of the function for compiler optimization. It is not a React 19 feature like'use client'or'use server', but rather a build-time compiler instruction that enables the React Compiler to memoize this function.
Proposed changes
Improve the actionSheet behavior on a11y.
open message actionsis available on a11y actions;Issue(s)
https://rocketchat.atlassian.net/browse/MA-263
How to test or reproduce
Screenshots
Types of changes
Checklist
Further comments
Summary by CodeRabbit
Accessibility Improvements
New Features
Tests