chore: migrate react-native-platform-touchable to RectButton#6997
chore: migrate react-native-platform-touchable to RectButton#6997
Conversation
|
Note Reviews pausedIt 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 Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
WalkthroughReplaced many usages of deprecated react-native-platform-touchable with a local Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Suggested labels
🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (3 passed)
✏️ 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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 4
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
app/containers/InAppNotification/IncomingCallNotification/index.tsx (2)
99-120:⚠️ Potential issue | 🟡 Minor
declineandacceptbuttons are missingaccessibilityLabel.The dismiss button (line 93) correctly has
accessibilityLabel={i18n.t('A11y_incoming_call_dismiss')}, but the decline and acceptTouchelements have no accessibility label. Screen reader users will hear "button" with no description for these critical call-action controls.♿ Proposed fix
<Touch hitSlop={BUTTON_HIT_SLOP} onPress={() => { setAudio(!audio); hideNotification(); dispatch(cancelCall({ callId })); }} + accessibilityLabel={i18n.t('decline')} style={styles.cancelButton}> <Text style={styles.buttonText}>{i18n.t('decline')}</Text> </Touch> ... <Touch hitSlop={BUTTON_HIT_SLOP} onPress={() => { setAudio(!audio); hideNotification(); dispatch(acceptCall({ callId })); }} + accessibilityLabel={i18n.t('accept')} style={styles.acceptButton}> <Text style={styles.buttonText}>{i18n.t('accept')}</Text> </Touch>🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@app/containers/InAppNotification/IncomingCallNotification/index.tsx` around lines 99 - 120, The decline and accept Touch buttons in the IncomingCallNotification component are missing accessibilityLabel props; update the two Touch elements (the one that dispatches cancelCall({ callId }) and the one that dispatches acceptCall({ callId })) to include accessibilityLabel using the i18n keys (e.g. i18n.t('A11y_incoming_call_decline') and i18n.t('A11y_incoming_call_accept')) so screen readers announce the actions, keeping existing handlers (setAudio, hideNotification, dispatch) and styles (styles.cancelButton, styles.acceptButton) unchanged.
87-121:⚠️ Potential issue | 🟠 MajorFix
hitSlophandling inTouchcomponent to support cross-platform touch area expansion.The
Touchcomponent currently passeshitSlopdirectly toRectButton(line 81 ofapp/containers/Touch.tsx), which uses gesture-handler's hitSlop implementation. For proper cross-platform touch area expansion on these call-action buttons,hitSlopshould be forwarded to the innerViewinstead, which respects React Native's native hitSlop behavior.The issue affects the three buttons in this file (dismiss, decline, accept), all of which rely on
hitSlop={BUTTON_HIT_SLOP}for adequate tappability.Modify
Touch.tsxto extract and forwardhitSlopto the innerViewcomponent rather than passing it through toRectButton.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@app/containers/InAppNotification/IncomingCallNotification/index.tsx` around lines 87 - 121, The Touch component currently forwards hitSlop to gesture-handler's RectButton which prevents native RN hit area expansion; update Touch.tsx to destructure hitSlop from props, do NOT pass hitSlop into RectButton, and instead pass that hitSlop value to the inner View (or wrapper) so the native hitSlop is applied; keep RectButton for press handling but ensure other props (onPress, style, children) are forwarded unchanged so uses like the dismiss/decline/accept buttons (which pass BUTTON_HIT_SLOP) get the correct cross-platform touch expansion.
🧹 Nitpick comments (2)
app/containers/InAppNotification/NotifierComponent.tsx (1)
125-127: Optional: AddaccessibilityLabelto the close button.The icon-only
Touchfor the close action has noaccessibilityLabel, making it inaccessible to screen readers. This is a pre-existing gap, not introduced by this PR, but worth addressing while touching this component.♿ Suggested improvement
-<Touch onPress={hideNotification} hitSlop={BUTTON_HIT_SLOP}> +<Touch onPress={hideNotification} hitSlop={BUTTON_HIT_SLOP} accessibilityLabel={I18n.t('Close')}>🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@app/containers/InAppNotification/NotifierComponent.tsx` around lines 125 - 127, The close icon Touch lacks an accessibilityLabel, making it invisible to screen readers; update the Touch around CustomIcon (the Touch component wrapping CustomIcon with props hitSlop={BUTTON_HIT_SLOP} and onPress={hideNotification}) to include a descriptive accessibilityLabel (e.g., "Close notification") and optionally accessibilityRole="button" and an accessibilityHint, so screen readers can announce the control while leaving CustomIcon and styles.close unchanged.app/containers/message/Message.tsx (1)
240-248: Disabled→enabled inversion is correct; minor redundancy in the expression.The De Morgan transformation is logically sound. One observation: the early return at Line 229 (
if (props.hasError || props.isInfo)) ensuresprops.isInfois alwaysfalseby the timeTouchis rendered, making!(props.isInfo && !props.isThreadReply)unconditionallytrue. The term is harmless but could be simplified to!props.archived && !props.isTemp && props.type !== 'jitsi_call_started'for clarity.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@app/containers/message/Message.tsx` around lines 240 - 248, The enabled expression on the Touch component contains a redundant term: because earlier code returns when props.isInfo is true (see the guard with props.hasError || props.isInfo), the sub-expression !(props.isInfo && !props.isThreadReply) is always true; simplify the enabled prop in the Touch element by removing that redundant check and use a clearer expression like !props.archived && !props.isTemp && props.type !== 'jitsi_call_started' so the logic remains the same but is easier to read.
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (12)
app/containers/Avatar/__snapshots__/Avatar.test.tsx.snapis excluded by!**/*.snapapp/containers/Button/__snapshots__/Button.test.tsx.snapis excluded by!**/*.snapapp/containers/LoginServices/__snapshots__/LoginServices.test.tsx.snapis excluded by!**/*.snapapp/containers/TextInput/__snapshots__/TextInput.test.tsx.snapis excluded by!**/*.snapapp/containers/UIKit/__snapshots__/UiKitMessage.test.tsx.snapis excluded by!**/*.snapapp/containers/UIKit/__snapshots__/UiKitModal.test.tsx.snapis excluded by!**/*.snapapp/containers/message/__snapshots__/Message.test.tsx.snapis excluded by!**/*.snapapp/views/CannedResponsesListView/__snapshots__/CannedResponseItem.test.tsx.snapis excluded by!**/*.snapapp/views/DiscussionsView/__snapshots__/Item.test.tsx.snapis excluded by!**/*.snapapp/views/RoomView/LoadMore/__snapshots__/LoadMore.test.tsx.snapis excluded by!**/*.snapapp/views/ThreadMessagesView/__snapshots__/Item.test.tsx.snapis excluded by!**/*.snapyarn.lockis excluded by!**/yarn.lock,!**/*.lock
📒 Files selected for processing (32)
app/containers/Avatar/Avatar.tsxapp/containers/Button/Button.test.tsxapp/containers/Button/index.tsxapp/containers/CallHeader.tsxapp/containers/InAppNotification/IncomingCallNotification/index.tsxapp/containers/InAppNotification/NotifierComponent.tsxapp/containers/TextInput/FormTextInput.tsxapp/containers/ThreadDetails.tsxapp/containers/UIKit/DatePicker.tsxapp/containers/UIKit/MultiSelect/Chips.tsxapp/containers/UIKit/MultiSelect/Input.tsxapp/containers/UIKit/MultiSelect/Items.tsxapp/containers/UIKit/Overflow.tsxapp/containers/UIKit/VideoConferenceBlock/components/VideoConferenceEnded.tsxapp/containers/UIKit/VideoConferenceBlock/components/VideoConferenceOutgoing.tsxapp/containers/message/Broadcast.tsxapp/containers/message/CallButton.tsxapp/containers/message/Components/Attachments/CollapsibleQuote/index.tsxapp/containers/message/Components/Attachments/Image/Button.tsxapp/containers/message/Components/Attachments/Reply.tsxapp/containers/message/Components/Attachments/Video.tsxapp/containers/message/Discussion.tsxapp/containers/message/Message.tsxapp/containers/message/Reactions.tsxapp/containers/message/Touchable.tsxapp/containers/message/Urls.tsxapp/views/CannedResponsesListView/CannedResponseItem.tsxapp/views/ChangePasscodeView.tsxapp/views/DiscussionsView/Item.tsxapp/views/ScreenLockedView.tsxapp/views/ThreadMessagesView/Item.tsxpackage.json
💤 Files with no reviewable changes (7)
- app/containers/message/CallButton.tsx
- package.json
- app/containers/message/Components/Attachments/CollapsibleQuote/index.tsx
- app/containers/message/Components/Attachments/Reply.tsx
- app/containers/message/Reactions.tsx
- app/containers/message/Broadcast.tsx
- app/containers/message/Discussion.tsx
🧰 Additional context used
🧠 Learnings (3)
📓 Common learnings
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.
Learnt from: Rohit3523
Repo: RocketChat/Rocket.Chat.ReactNative PR: 6930
File: package.json:101-101
Timestamp: 2026-02-05T13:55:06.688Z
Learning: The RocketChat/Rocket.Chat.ReactNative repository uses a fork of react-native-image-crop-picker (RocketChat/react-native-image-crop-picker) with custom Android edge-to-edge fixes, not the upstream ivpusic/react-native-image-crop-picker package. Dependencies should reference commit pins from the RocketChat fork.
📚 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/InAppNotification/IncomingCallNotification/index.tsxapp/containers/UIKit/MultiSelect/Chips.tsxapp/containers/UIKit/MultiSelect/Items.tsxapp/containers/message/Touchable.tsxapp/containers/CallHeader.tsxapp/containers/UIKit/MultiSelect/Input.tsxapp/containers/UIKit/DatePicker.tsx
📚 Learning: 2026-02-05T13:55:06.688Z
Learnt from: Rohit3523
Repo: RocketChat/Rocket.Chat.ReactNative PR: 6930
File: package.json:101-101
Timestamp: 2026-02-05T13:55:06.688Z
Learning: The RocketChat/Rocket.Chat.ReactNative repository uses a fork of react-native-image-crop-picker (RocketChat/react-native-image-crop-picker) with custom Android edge-to-edge fixes, not the upstream ivpusic/react-native-image-crop-picker package. Dependencies should reference commit pins from the RocketChat fork.
Applied to files:
app/containers/Avatar/Avatar.tsx
🧬 Code graph analysis (9)
app/views/ScreenLockedView.tsx (1)
app/containers/RoomItem/RoomItem.stories.tsx (1)
Touch(57-57)
app/views/ThreadMessagesView/Item.tsx (1)
app/containers/RoomItem/RoomItem.stories.tsx (1)
Touch(57-57)
app/containers/UIKit/VideoConferenceBlock/components/VideoConferenceOutgoing.tsx (2)
app/containers/UIKit/VideoConferenceBlock/components/VideoConferenceBaseContainer.tsx (1)
VideoConferenceBaseContainer(14-60)app/lib/methods/videoConf.ts (1)
videoConfJoin(29-48)
app/views/CannedResponsesListView/CannedResponseItem.tsx (2)
app/containers/RoomItem/RoomItem.stories.tsx (1)
Touch(57-57)app/lib/constants/colors.ts (1)
themes(304-304)
app/containers/UIKit/MultiSelect/Items.tsx (1)
app/containers/RoomItem/RoomItem.stories.tsx (1)
Touch(57-57)
app/containers/Button/Button.test.tsx (1)
app/containers/UIKit/index.tsx (1)
button(77-90)
app/containers/CallHeader.tsx (2)
app/containers/RoomItem/RoomItem.stories.tsx (1)
Touch(57-57)app/containers/CustomIcon/index.tsx (1)
CustomIcon(47-47)
app/containers/Avatar/Avatar.tsx (1)
app/containers/UIKit/index.tsx (2)
image(124-126)image(185-187)
app/containers/UIKit/VideoConferenceBlock/components/VideoConferenceEnded.tsx (1)
app/containers/RoomItem/RoomItem.stories.tsx (1)
Touch(57-57)
🔇 Additional comments (21)
app/containers/UIKit/VideoConferenceBlock/components/VideoConferenceOutgoing.tsx (1)
9-18: LGTM — clean one-to-one migration.The swap from
Touchable(react-native-platform-touchable) to the localTouchwrapper preserves both thestyleandonPressprops without any behavioural regression. The relative import path../../../Touchcorrectly resolves toapp/containers/Touchfrom this file's location.app/containers/UIKit/MultiSelect/Chips.tsx (2)
26-43: Migration looks correct — LGTM.The component swap is clean:
onPress,style, andtestIDsemantics are preserved, and removing theRipplebackground prop aligns with the rest of the PR. No logic or public API changes.
10-10: Touch component properly forwardsstyleandtestIDprops.The
Touchcomponent accepts and correctly handles bothstyleandtestID:
testIDis captured via...props(line 38) and spread toRectButton(line 81), ensuring test selectors work correctly.styleis intelligently parsed:backgroundColoris extracted and applied toRectButtonfor proper ripple animation, while remaining view styles are applied to the innerView. For the Chips component, thebackgroundColor: colors.surfaceHoveroverride is correctly extracted and applied toRectButton.The migration is sound with no prop forwarding issues.
app/views/CannedResponsesListView/CannedResponseItem.tsx (1)
4-60: LGTM — clean drop-in swap.
Touchreceives the sameonPressandstyleprops as the oldTouchable. No logic, accessibility, or styling concerns.app/containers/ThreadDetails.tsx (1)
4-94: LGTM — straightforward swap preservingaccessibilityLabelandonPress.app/containers/message/Components/Attachments/Video.tsx (1)
16-16: LGTM — intentionally retains the localTouchable, not the deprecated package.
app/containers/message/Touchableis a separate message-specific component, notreact-native-platform-touchable. The marked change on line 105 removes only thebackground/ripple styling prop, which is correct and consistent with the PR's broader goal.app/views/ScreenLockedView.tsx (1)
12-80: LGTM — clean swap with no behavioral changes.app/views/ChangePasscodeView.tsx (1)
12-76: LGTM — clean swap with no behavioral changes.app/containers/UIKit/MultiSelect/Input.tsx (1)
24-37: No action needed. Theenabledprop is properly handled.
ITouchProps extends RectButtonProps, which includes theenabledprop from react-native-gesture-handler. Sinceenabledis not explicitly destructured in the component signature, it flows into the...propsspread, which is then forwarded directly toRectButton. The disabled state will work as intended.Likely an incorrect or invalid review comment.
app/containers/Avatar/Avatar.tsx (1)
100-103: No action needed — accessibility props are properly forwarded.The
Touchcomponent explicitly declaresaccessibleandaccessibilityLabelin its props interface and passes them to the innerViewcomponent (lines 83–88 of Touch.tsx), which is the correct pattern for this architecture. Accessibility attributes onRectButtonare not needed; they belong on theViewcontainer.app/containers/UIKit/DatePicker.tsx (1)
16-16: LGTM — clean migration with appropriate background fix.Applying
backgroundColor: themes[theme].surfaceRoomon theTouchwrapper is a reasonable substitute for the old Ripple background to ensure no visual artifacts from RectButton's press overlay on the form surface.Also applies to: 65-65, 85-85
app/containers/CallHeader.tsx (1)
52-70:disabled→enabled={!calling}inversion is correct.
enabled={!calling}onTouch(RectButton) is semantically equivalent to the olddisabled={calling}. The visual disabled states are already handled viahandleColors(cam/mic), so interaction blocking viaenabledis the right coupling here.app/views/ThreadMessagesView/Item.tsx (1)
12-12: LGTM — straightforward component swap.Also applies to: 77-97
app/views/DiscussionsView/Item.tsx (1)
12-12: LGTM — straightforward component swap.Also applies to: 66-82
app/containers/UIKit/VideoConferenceBlock/components/VideoConferenceEnded.tsx (1)
12-12: LGTM — clean swap; text children provide accessible label.Also applies to: 35-39
app/containers/message/Urls.tsx (1)
9-9: The migration is complete and consistent—no action needed.The
message/Touchable.tsxcomponent has been properly migrated to useTouchfrom../Touch, which wrapsRectButtonfromreact-native-gesture-handler. There are no remaining references toreact-native-platform-touchablein the codebase, and the removal ofbackground={Touchable.Ripple(...)}on line 180 is correct since that static method no longer exists. The localTouchablewrapper pattern is intentional and addsMessageContexthandling that justifies keeping it separate from the standardTouchcomponent.app/containers/UIKit/MultiSelect/Items.tsx (1)
29-29: This review comment is incorrect.MultiSelect does not use React Native's
Modalcomponent. Instead, it uses ActionSheet (lines 79 of index.tsx), which renders content via BottomSheet from@discord/bottom-sheet(ActionSheet.tsx, line 153). Items is therefore rendered inside a BottomSheetView (MultiSelectContent.tsx, line 83), not a Modal.The RectButton-in-Modal issue documented on line 29 (RNGH
#139,#500,#996) only affects React Native's<Modal>component. Custom BottomSheet implementations work fine with gesture handlers. Additionally,GestureHandlerRootViewis already wrapping the entire app at the root level (app/index.tsx), ensuring gesture handlers function correctly throughout the application.No fix is needed.
Likely an incorrect or invalid review comment.
app/containers/Button/Button.test.tsx (1)
35-37:beforeEachreset is good practice — approved.app/containers/Button/index.tsx (1)
3-3: LGTM —disabledandPressablePropsextension are correct per RNGH API.RNGH's
Pressableexposesdisabledas "Whether the press behavior is disabled", sodisabled={isDisabled}at Line 92 is the correct prop. ExtendingPressablePropsis clean and the re-declaredonPress: () => voidis valid TypeScript (fewer-parameter functions are assignable to wider callback types).Also applies to: 9-20
app/containers/message/Touchable.tsx (1)
6-16: Removal ofRCTouchable.RippleandRCTouchable.SelectableBackgroundBorderlessis safe—no remaining call sites detected.The static members have been removed and all previous references have been cleaned up. No code in the repository references these removed properties.
app/containers/UIKit/Overflow.tsx (1)
29-33: TheIOptioninterface still includesthemeas a property (inherited fromPropsOption), so passingtheme={theme}to<Option>at line 38 is not a TypeScript error.The actual situation is:
IOptionextendsPropsOption, which includestheme: TSupportedThemesthemeis correctly being passed to<Option>at line 38- However, the
Optioncomponent's destructuring (line 29) does not extracttheme, so the prop is accepted but unusedIf the theme is genuinely unused, it could be removed from the destructuring annotation and the prop pass for clarity, but this is not a type mismatch.
Likely an incorrect or invalid review comment.
🤖 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/containers/Button/Button.test.tsx`:
- Around line 64-70: The test currently asserts button.props.enabled but the
Button component passes disabled={isDisabled} to RNGH's Pressable; update the
test in Button.test.tsx (the 'disabled button is in disabled state' case that
renders <TestButton disabled={true} /> and queries via
findByTestId(testProps.testID)) to assert button.props.disabled is true (instead
of checking enabled), so the test reads the actual prop used by the Pressable.
In `@app/containers/message/Components/Attachments/Image/Button.tsx`:
- Line 16: The Touchable/Touch chain is passing a `disabled` prop that
RectButton expects as `enabled`; update the mapping so disabled works: in
Touch.tsx (where RectButton is rendered) set RectButton's enabled prop to
{!props.disabled} (or compute const enabled = !disabled and pass enabled) and do
not pass an unsupported `disabled` prop through to RectButton; alternatively,
perform the conversion in Touchable.tsx by mapping disabled -> enabled before
forwarding props to Touch, ensuring the component names Touchable, Touch (and
the RectButton usage) are the places you change.
In `@app/containers/TextInput/FormTextInput.tsx`:
- Around line 200-208: The clear-input Touch within FormTextInput is missing an
accessibilityLabel which leaves a screen-reader user with an unlabeled
interactive element; update the Touch (the element rendered when showClearInput
is true) to include accessibilityLabel={i18n.t('Clear_input')} (or the matching
translated string) and ensure the corresponding i18n key 'Clear_input' is added
to your localization files; reference the Touch that uses onClearInput and
testID='clear-text-input' to locate where to add the label.
In `@app/containers/UIKit/Overflow.tsx`:
- Line 44: The module-level touchable dictionary is typed as RefObject but the
ref callback in the Overflow component stores raw component instances
(touchable[blockId] = ref), causing a type mismatch and possibly invalid value
for Popover's from prop; fix it by moving per-instance ref storage into the
component via React.useRef (or a Map of refs created with useRef for multiple
instances) so touchable values are actual RefObjects (with .current) referenced
by blockId, update the ref callback to assign to ref.current (or set the Map's
useRef().current) and pass that RefObject to Popover.from (symbols: touchable,
blockId, Overflow component, Popover, from).
---
Outside diff comments:
In `@app/containers/InAppNotification/IncomingCallNotification/index.tsx`:
- Around line 99-120: The decline and accept Touch buttons in the
IncomingCallNotification component are missing accessibilityLabel props; update
the two Touch elements (the one that dispatches cancelCall({ callId }) and the
one that dispatches acceptCall({ callId })) to include accessibilityLabel using
the i18n keys (e.g. i18n.t('A11y_incoming_call_decline') and
i18n.t('A11y_incoming_call_accept')) so screen readers announce the actions,
keeping existing handlers (setAudio, hideNotification, dispatch) and styles
(styles.cancelButton, styles.acceptButton) unchanged.
- Around line 87-121: The Touch component currently forwards hitSlop to
gesture-handler's RectButton which prevents native RN hit area expansion; update
Touch.tsx to destructure hitSlop from props, do NOT pass hitSlop into
RectButton, and instead pass that hitSlop value to the inner View (or wrapper)
so the native hitSlop is applied; keep RectButton for press handling but ensure
other props (onPress, style, children) are forwarded unchanged so uses like the
dismiss/decline/accept buttons (which pass BUTTON_HIT_SLOP) get the correct
cross-platform touch expansion.
---
Nitpick comments:
In `@app/containers/InAppNotification/NotifierComponent.tsx`:
- Around line 125-127: The close icon Touch lacks an accessibilityLabel, making
it invisible to screen readers; update the Touch around CustomIcon (the Touch
component wrapping CustomIcon with props hitSlop={BUTTON_HIT_SLOP} and
onPress={hideNotification}) to include a descriptive accessibilityLabel (e.g.,
"Close notification") and optionally accessibilityRole="button" and an
accessibilityHint, so screen readers can announce the control while leaving
CustomIcon and styles.close unchanged.
In `@app/containers/message/Message.tsx`:
- Around line 240-248: The enabled expression on the Touch component contains a
redundant term: because earlier code returns when props.isInfo is true (see the
guard with props.hasError || props.isInfo), the sub-expression !(props.isInfo &&
!props.isThreadReply) is always true; simplify the enabled prop in the Touch
element by removing that redundant check and use a clearer expression like
!props.archived && !props.isTemp && props.type !== 'jitsi_call_started' so the
logic remains the same but is easier to read.
There was a problem hiding this comment.
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/containers/Touch.tsx (1)
85-94:⚠️ Potential issue | 🟡 MinorMissing
accessibilityStatefor the disabled stateThe inner
Viewforwards all other a11y props but omitsaccessibilityState. Whendisabled={true}, touch is blocked onRectButtonbut screen readers still treat the element as interactive, becauseaccessibilityState={{ disabled }}is never set.♿ Proposed fix
<View accessible={accessible} accessibilityRole={props.accessibilityRole} accessibilityLabel={accessibilityLabel} accessibilityHint={accessibilityHint} accessibilityActions={accessibilityActions} onAccessibilityAction={onAccessibilityAction} + accessibilityState={{ disabled }} style={viewStyle}>🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@app/containers/Touch.tsx` around lines 85 - 94, The inner View is missing accessibilityState so screen readers don't know when the button is disabled; update the View in Touch.tsx to pass accessibilityState that includes the disabled flag (e.g. accessibilityState={{ ...(props.accessibilityState || {}), disabled }}) so existing accessibilityState is preserved while ensuring disabled is communicated; locate the View render (the block with accessible, accessibilityRole, accessibilityLabel, accessibilityHint, accessibilityActions, onAccessibilityAction, style={viewStyle}) and add the accessibilityState prop as described.
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (14)
app/containers/Avatar/__snapshots__/Avatar.test.tsx.snapis excluded by!**/*.snapapp/containers/DirectoryItem/__snapshots__/DirectoryItem.test.tsx.snapis excluded by!**/*.snapapp/containers/LoginServices/__snapshots__/LoginServices.test.tsx.snapis excluded by!**/*.snapapp/containers/RoomItem/__snapshots__/RoomItem.test.tsx.snapis excluded by!**/*.snapapp/containers/ServerItem/__snapshots__/ServerItem.test.tsx.snapis excluded by!**/*.snapapp/containers/TextInput/__snapshots__/TextInput.test.tsx.snapis excluded by!**/*.snapapp/containers/UIKit/__snapshots__/UiKitMessage.test.tsx.snapis excluded by!**/*.snapapp/containers/UIKit/__snapshots__/UiKitModal.test.tsx.snapis excluded by!**/*.snapapp/containers/message/__snapshots__/Message.test.tsx.snapis excluded by!**/*.snapapp/views/CannedResponsesListView/__snapshots__/CannedResponseItem.test.tsx.snapis excluded by!**/*.snapapp/views/DiscussionsView/__snapshots__/Item.test.tsx.snapis excluded by!**/*.snapapp/views/NewServerView/components/ServersHistoryItem/__snapshots__/ServersHistoryItem.test.tsx.snapis excluded by!**/*.snapapp/views/RoomView/LoadMore/__snapshots__/LoadMore.test.tsx.snapis excluded by!**/*.snapapp/views/ThreadMessagesView/__snapshots__/Item.test.tsx.snapis excluded by!**/*.snap
📒 Files selected for processing (4)
app/containers/TextInput/FormTextInput.tsxapp/containers/Touch.tsxapp/i18n/locales/en.jsonapp/i18n/locales/pt-BR.json
🚧 Files skipped from review as they are similar to previous changes (1)
- app/containers/TextInput/FormTextInput.tsx
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
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.
Learnt from: Rohit3523
Repo: RocketChat/Rocket.Chat.ReactNative PR: 6930
File: package.json:101-101
Timestamp: 2026-02-05T13:55:06.688Z
Learning: The RocketChat/Rocket.Chat.ReactNative repository uses a fork of react-native-image-crop-picker (RocketChat/react-native-image-crop-picker) with custom Android edge-to-edge fixes, not the upstream ivpusic/react-native-image-crop-picker package. Dependencies should reference commit pins from the RocketChat fork.
⏰ 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 comments (2)
app/i18n/locales/en.json (1)
160-160: LGTM —Clear_inputkey correctly placed and the value is clear.app/i18n/locales/pt-BR.json (1)
158-158: LGTM —Clear_inputtranslation is accurate and correctly ordered.
🤖 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/containers/Touch.tsx`:
- Around line 82-84: The component currently spreads {...props} after setting
enabled={!disabled}, allowing an incoming enabled in RectButtonProps to override
the disabled prop; fix by either moving enabled={!disabled} to after the
{...props} spread so it wins, or better, destructure enabled out of the props
(e.g., const { enabled, ...rest } = props) and spread rest so callers' enabled
is discarded—update the Touch component where enabled, disabled and {...props}
are used (the RectButton/RectButtonProps usage) accordingly.
---
Outside diff comments:
In `@app/containers/Touch.tsx`:
- Around line 85-94: The inner View is missing accessibilityState so screen
readers don't know when the button is disabled; update the View in Touch.tsx to
pass accessibilityState that includes the disabled flag (e.g.
accessibilityState={{ ...(props.accessibilityState || {}), disabled }}) so
existing accessibilityState is preserved while ensuring disabled is
communicated; locate the View render (the block with accessible,
accessibilityRole, accessibilityLabel, accessibilityHint, accessibilityActions,
onAccessibilityAction, style={viewStyle}) and add the accessibilityState prop as
described.
|
|
||
| const keyExtractor = (item: IItemData) => item.value?.name || item.text?.text; | ||
|
|
||
| // RectButton doesn't work on modal (Android) |
Proposed changes
This PR migrates
react-native-platform-touchableto RectButton becausereact-native-platform-touchableis not maintained anymore and is deprecated, developer suggest to usereact-native-gesture-handlerinstead.We already have a component which uses RectButton from gesture-handler which provides same functionality.
have to add more info
https://docs.swmansion.com/react-native-gesture-handler/docs/fundamentals/installation/#android
Issue(s)
https://rocketchat.atlassian.net/browse/CORE-1858
How to test or reproduce
Screenshots
Types of changes
Checklist
Further comments
Summary by CodeRabbit
Refactor
Tests
Chores
Localization