Skip to content

chore: migrate react-native-platform-touchable to RectButton#6997

Open
Rohit3523 wants to merge 63 commits intodevelopfrom
remove-platform-touchable
Open

chore: migrate react-native-platform-touchable to RectButton#6997
Rohit3523 wants to merge 63 commits intodevelopfrom
remove-platform-touchable

Conversation

@Rohit3523
Copy link
Contributor

@Rohit3523 Rohit3523 commented Feb 19, 2026

Proposed changes

This PR migrates react-native-platform-touchable to RectButton because react-native-platform-touchable is not maintained anymore and is deprecated, developer suggest to use react-native-gesture-handler instead.
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

  • 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

Summary by CodeRabbit

  • Refactor

    • Standardized touch/press handling across the app: replaced legacy touchables with a unified Touch component, adjusted enabled/disabled semantics and removed ripple touch feedback.
    • Exposed a disabled prop on the touch component to control interactivity.
  • Tests

    • Updated disabled-button test to assert disabled state instead of firing press events; other test flows adjusted.
  • Chores

    • Removed obsolete touch dependency.
  • Localization

    • Added "Clear input" translation (en, pt-BR).

@Rohit3523 Rohit3523 temporarily deployed to approve_e2e_testing February 19, 2026 21:50 — with GitHub Actions Inactive
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 19, 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

Replaced many usages of deprecated react-native-platform-touchable with a local Touch wrapper or Pressable; removed Touchable.Ripple/background props and the react-native-platform-touchable dependency; added disabled?: boolean to ITouchProps; updated Button to extend PressableProps; added i18n key Clear_input.

Changes

Cohort / File(s) Summary
Touch Component Replacements
app/containers/Avatar/Avatar.tsx, app/containers/CallHeader.tsx, app/containers/InAppNotification/IncomingCallNotification/index.tsx, app/containers/InAppNotification/NotifierComponent.tsx, app/containers/TextInput/FormTextInput.tsx, app/containers/ThreadDetails.tsx, app/containers/UIKit/DatePicker.tsx, app/containers/UIKit/MultiSelect/Chips.tsx, app/containers/UIKit/MultiSelect/Input.tsx, app/containers/UIKit/MultiSelect/Items.tsx, app/containers/UIKit/Overflow.tsx, app/containers/UIKit/VideoConferenceBlock/components/VideoConferenceEnded.tsx, app/containers/UIKit/VideoConferenceBlock/components/VideoConferenceOutgoing.tsx, app/containers/message/Message.tsx, app/containers/message/Touchable.tsx, app/views/CannedResponsesListView/CannedResponseItem.tsx, app/views/ChangePasscodeView.tsx, app/views/DiscussionsView/Item.tsx, app/views/ScreenLockedView.tsx, app/views/ThreadMessagesView/Item.tsx, app/containers/message/User.tsx
Swapped Touchable / TouchableOpacity for local Touch (updated imports and JSX). Adjusted some uses from disabledenabled inversion where Touch expects enabled. Removed previously exposed Touchable static members in message/Touchable.tsx.
Ripple Background / Theming Removal
app/containers/message/Broadcast.tsx, app/containers/message/CallButton.tsx, app/containers/message/Components/Attachments/CollapsibleQuote/index.tsx, app/containers/message/Components/Attachments/Image/Button.tsx, app/containers/message/Components/Attachments/Reply.tsx, app/containers/message/Components/Attachments/Video.tsx, app/containers/message/Discussion.tsx, app/containers/message/Reactions.tsx, app/containers/message/Urls.tsx
Removed background / Touchable.Ripple(...) usage and some theme-based ripple color usage; preserved handlers, layout and other props.
Button Migration & Tests
app/containers/Button/index.tsx, app/containers/Button/Button.test.tsx
Replaced platform Touchable with Pressable (react-native-gesture-handler). Updated IButtonProps to extend PressableProps. Tests updated to reset mocks and assert disabled state via rendered prop.
Touch API Change
app/containers/Touch.tsx
Added disabled?: boolean to ITouchProps; forwarded as enabled={!disabled} to the underlying RectButton (inverted behavior).
i18n Additions
app/i18n/locales/en.json, app/i18n/locales/pt-BR.json
Added translation key Clear_input ("Clear input" / "Limpar entrada").
Dependency Removal
package.json
Removed react-native-platform-touchable and its @types devDependency.
Maestro / Tests Adjustments
.maestro/helpers/send-message.yaml, .maestro/tests/assorted/profile.yaml, .maestro/tests/room/share-message.yaml, .maestro/tests/e2ee/flows/create-e2ee-room.yaml, .maestro/tests/e2ee/utils/change-e2ee-key.yaml, .maestro/tests/room/room.yaml, .maestro/tests/teams/team.yaml
Replaced some hideKeyboard steps with swipes/scrolls or removed them; one selector switched to id-based wait; one profile test removed an assertion for disabled state.
Misc / Minor Adjustments
app/containers/InAppNotification/NotifierComponent.tsx, app/containers/UIKit/Overflow.tsx, app/containers/message/Touchable.tsx, app/containers/message/Touchable.tsx
Adjusted Popover anchor prop usage, touch ref types, removed Touchable static members, and minor JSX/prop reorganization accompanying component swaps.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Suggested labels

type: chore, community

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Out of Scope Changes check ❓ Inconclusive Some unrelated test helper and E2E test changes (hideKeyboard removal, swipe/scroll actions) appear tangential to the core migration objective. Clarify whether test flow changes (keyboard dismissal behavior) are necessary side effects of the migration or separate improvements to be decoupled.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the primary change: migrating from react-native-platform-touchable to RectButton (via custom Touch component).
Linked Issues check ✅ Passed The PR successfully replaces react-native-platform-touchable usage with RectButton across all files, resolves gesture conflicts with TrueSheet, and removes the deprecated dependency.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


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

❤️ Share

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

@OtavioStasiak OtavioStasiak had a problem deploying to experimental_android_build February 20, 2026 16:55 — with GitHub Actions Error
@Rohit3523 Rohit3523 marked this pull request as ready for review February 20, 2026 18:06
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: 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

decline and accept buttons are missing accessibilityLabel.

The dismiss button (line 93) correctly has accessibilityLabel={i18n.t('A11y_incoming_call_dismiss')}, but the decline and accept Touch elements 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 | 🟠 Major

Fix hitSlop handling in Touch component to support cross-platform touch area expansion.

The Touch component currently passes hitSlop directly to RectButton (line 81 of app/containers/Touch.tsx), which uses gesture-handler's hitSlop implementation. For proper cross-platform touch area expansion on these call-action buttons, hitSlop should be forwarded to the inner View instead, 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.tsx to extract and forward hitSlop to the inner View component rather than passing it through to RectButton.

🤖 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: Add accessibilityLabel to the close button.

The icon-only Touch for the close action has no accessibilityLabel, 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)) ensures props.isInfo is always false by the time Touch is rendered, making !(props.isInfo && !props.isThreadReply) unconditionally true. 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

📥 Commits

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

⛔ Files ignored due to path filters (12)
  • app/containers/Avatar/__snapshots__/Avatar.test.tsx.snap is excluded by !**/*.snap
  • app/containers/Button/__snapshots__/Button.test.tsx.snap is excluded by !**/*.snap
  • app/containers/LoginServices/__snapshots__/LoginServices.test.tsx.snap is excluded by !**/*.snap
  • app/containers/TextInput/__snapshots__/TextInput.test.tsx.snap is excluded by !**/*.snap
  • app/containers/UIKit/__snapshots__/UiKitMessage.test.tsx.snap is excluded by !**/*.snap
  • app/containers/UIKit/__snapshots__/UiKitModal.test.tsx.snap is excluded by !**/*.snap
  • app/containers/message/__snapshots__/Message.test.tsx.snap is excluded by !**/*.snap
  • app/views/CannedResponsesListView/__snapshots__/CannedResponseItem.test.tsx.snap is excluded by !**/*.snap
  • app/views/DiscussionsView/__snapshots__/Item.test.tsx.snap is excluded by !**/*.snap
  • app/views/RoomView/LoadMore/__snapshots__/LoadMore.test.tsx.snap is excluded by !**/*.snap
  • app/views/ThreadMessagesView/__snapshots__/Item.test.tsx.snap is excluded by !**/*.snap
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (32)
  • app/containers/Avatar/Avatar.tsx
  • app/containers/Button/Button.test.tsx
  • app/containers/Button/index.tsx
  • app/containers/CallHeader.tsx
  • app/containers/InAppNotification/IncomingCallNotification/index.tsx
  • app/containers/InAppNotification/NotifierComponent.tsx
  • app/containers/TextInput/FormTextInput.tsx
  • app/containers/ThreadDetails.tsx
  • app/containers/UIKit/DatePicker.tsx
  • app/containers/UIKit/MultiSelect/Chips.tsx
  • app/containers/UIKit/MultiSelect/Input.tsx
  • app/containers/UIKit/MultiSelect/Items.tsx
  • app/containers/UIKit/Overflow.tsx
  • app/containers/UIKit/VideoConferenceBlock/components/VideoConferenceEnded.tsx
  • app/containers/UIKit/VideoConferenceBlock/components/VideoConferenceOutgoing.tsx
  • app/containers/message/Broadcast.tsx
  • app/containers/message/CallButton.tsx
  • app/containers/message/Components/Attachments/CollapsibleQuote/index.tsx
  • app/containers/message/Components/Attachments/Image/Button.tsx
  • app/containers/message/Components/Attachments/Reply.tsx
  • app/containers/message/Components/Attachments/Video.tsx
  • app/containers/message/Discussion.tsx
  • app/containers/message/Message.tsx
  • app/containers/message/Reactions.tsx
  • app/containers/message/Touchable.tsx
  • app/containers/message/Urls.tsx
  • app/views/CannedResponsesListView/CannedResponseItem.tsx
  • app/views/ChangePasscodeView.tsx
  • app/views/DiscussionsView/Item.tsx
  • app/views/ScreenLockedView.tsx
  • app/views/ThreadMessagesView/Item.tsx
  • package.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.tsx
  • app/containers/UIKit/MultiSelect/Chips.tsx
  • app/containers/UIKit/MultiSelect/Items.tsx
  • app/containers/message/Touchable.tsx
  • app/containers/CallHeader.tsx
  • app/containers/UIKit/MultiSelect/Input.tsx
  • app/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 local Touch wrapper preserves both the style and onPress props without any behavioural regression. The relative import path ../../../Touch correctly resolves to app/containers/Touch from this file's location.

app/containers/UIKit/MultiSelect/Chips.tsx (2)

26-43: Migration looks correct — LGTM.

The component swap is clean: onPress, style, and testID semantics are preserved, and removing the Ripple background prop aligns with the rest of the PR. No logic or public API changes.


10-10: Touch component properly forwards style and testID props.

The Touch component accepts and correctly handles both style and testID:

  • testID is captured via ...props (line 38) and spread to RectButton (line 81), ensuring test selectors work correctly.
  • style is intelligently parsed: backgroundColor is extracted and applied to RectButton for proper ripple animation, while remaining view styles are applied to the inner View. For the Chips component, the backgroundColor: colors.surfaceHover override is correctly extracted and applied to RectButton.

The migration is sound with no prop forwarding issues.

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

4-60: LGTM — clean drop-in swap.

Touch receives the same onPress and style props as the old Touchable. No logic, accessibility, or styling concerns.

app/containers/ThreadDetails.tsx (1)

4-94: LGTM — straightforward swap preserving accessibilityLabel and onPress.

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

16-16: LGTM — intentionally retains the local Touchable, not the deprecated package.

app/containers/message/Touchable is a separate message-specific component, not react-native-platform-touchable. The marked change on line 105 removes only the background/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. The enabled prop is properly handled.

ITouchProps extends RectButtonProps, which includes the enabled prop from react-native-gesture-handler. Since enabled is not explicitly destructured in the component signature, it flows into the ...props spread, which is then forwarded directly to RectButton. 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 Touch component explicitly declares accessible and accessibilityLabel in its props interface and passes them to the inner View component (lines 83–88 of Touch.tsx), which is the correct pattern for this architecture. Accessibility attributes on RectButton are not needed; they belong on the View container.

app/containers/UIKit/DatePicker.tsx (1)

16-16: LGTM — clean migration with appropriate background fix.

Applying backgroundColor: themes[theme].surfaceRoom on the Touch wrapper 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: disabledenabled={!calling} inversion is correct.

enabled={!calling} on Touch (RectButton) is semantically equivalent to the old disabled={calling}. The visual disabled states are already handled via handleColors(cam/mic), so interaction blocking via enabled is 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.tsx component has been properly migrated to use Touch from ../Touch, which wraps RectButton from react-native-gesture-handler. There are no remaining references to react-native-platform-touchable in the codebase, and the removal of background={Touchable.Ripple(...)} on line 180 is correct since that static method no longer exists. The local Touchable wrapper pattern is intentional and adds MessageContext handling that justifies keeping it separate from the standard Touch component.

app/containers/UIKit/MultiSelect/Items.tsx (1)

29-29: This review comment is incorrect.

MultiSelect does not use React Native's Modal component. 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, GestureHandlerRootView is 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: beforeEach reset is good practice — approved.

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

3-3: LGTM — disabled and PressableProps extension are correct per RNGH API.

RNGH's Pressable exposes disabled as "Whether the press behavior is disabled", so disabled={isDisabled} at Line 92 is the correct prop. Extending PressableProps is clean and the re-declared onPress: () => void is 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 of RCTouchable.Ripple and RCTouchable.SelectableBackgroundBorderless is 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: The IOption interface still includes theme as a property (inherited from PropsOption), so passing theme={theme} to <Option> at line 38 is not a TypeScript error.

The actual situation is:

  • IOption extends PropsOption, which includes theme: TSupportedThemes
  • theme is correctly being passed to <Option> at line 38
  • However, the Option component's destructuring (line 29) does not extract theme, so the prop is accepted but unused

If 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.

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/containers/Touch.tsx (1)

85-94: ⚠️ Potential issue | 🟡 Minor

Missing accessibilityState for the disabled state

The inner View forwards all other a11y props but omits accessibilityState. When disabled={true}, touch is blocked on RectButton but screen readers still treat the element as interactive, because accessibilityState={{ 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

📥 Commits

Reviewing files that changed from the base of the PR and between b8acb3d and 65428e7.

⛔ Files ignored due to path filters (14)
  • app/containers/Avatar/__snapshots__/Avatar.test.tsx.snap is excluded by !**/*.snap
  • app/containers/DirectoryItem/__snapshots__/DirectoryItem.test.tsx.snap is excluded by !**/*.snap
  • app/containers/LoginServices/__snapshots__/LoginServices.test.tsx.snap is excluded by !**/*.snap
  • app/containers/RoomItem/__snapshots__/RoomItem.test.tsx.snap is excluded by !**/*.snap
  • app/containers/ServerItem/__snapshots__/ServerItem.test.tsx.snap is excluded by !**/*.snap
  • app/containers/TextInput/__snapshots__/TextInput.test.tsx.snap is excluded by !**/*.snap
  • app/containers/UIKit/__snapshots__/UiKitMessage.test.tsx.snap is excluded by !**/*.snap
  • app/containers/UIKit/__snapshots__/UiKitModal.test.tsx.snap is excluded by !**/*.snap
  • app/containers/message/__snapshots__/Message.test.tsx.snap is excluded by !**/*.snap
  • app/views/CannedResponsesListView/__snapshots__/CannedResponseItem.test.tsx.snap is excluded by !**/*.snap
  • app/views/DiscussionsView/__snapshots__/Item.test.tsx.snap is excluded by !**/*.snap
  • app/views/NewServerView/components/ServersHistoryItem/__snapshots__/ServersHistoryItem.test.tsx.snap is excluded by !**/*.snap
  • app/views/RoomView/LoadMore/__snapshots__/LoadMore.test.tsx.snap is excluded by !**/*.snap
  • app/views/ThreadMessagesView/__snapshots__/Item.test.tsx.snap is excluded by !**/*.snap
📒 Files selected for processing (4)
  • app/containers/TextInput/FormTextInput.tsx
  • app/containers/Touch.tsx
  • app/i18n/locales/en.json
  • app/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_input key correctly placed and the value is clear.

app/i18n/locales/pt-BR.json (1)

158-158: LGTM — Clear_input translation 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.

@Rohit3523 Rohit3523 had a problem deploying to experimental_android_build March 2, 2026 15:03 — with GitHub Actions Error
@Rohit3523 Rohit3523 had a problem deploying to official_android_build March 2, 2026 15:03 — with GitHub Actions Error
@Rohit3523 Rohit3523 had a problem deploying to experimental_ios_build March 2, 2026 15:03 — with GitHub Actions Error
@Rohit3523 Rohit3523 deployed to approve_e2e_testing March 2, 2026 16:00 — with GitHub Actions Active
@Rohit3523 Rohit3523 had a problem deploying to experimental_android_build March 2, 2026 16:04 — with GitHub Actions Error
@Rohit3523 Rohit3523 had a problem deploying to official_android_build March 2, 2026 16:04 — with GitHub Actions Error
@Rohit3523 Rohit3523 had a problem deploying to experimental_ios_build March 2, 2026 16:04 — with GitHub Actions Error
@Rohit3523 Rohit3523 had a problem deploying to experimental_ios_build March 2, 2026 19:24 — with GitHub Actions Error
@Rohit3523 Rohit3523 had a problem deploying to official_android_build March 2, 2026 19:24 — with GitHub Actions Error
@Rohit3523 Rohit3523 had a problem deploying to experimental_android_build March 2, 2026 19:24 — with GitHub Actions Error
@Rohit3523 Rohit3523 had a problem deploying to official_android_build March 2, 2026 20:42 — with GitHub Actions Error
@Rohit3523 Rohit3523 had a problem deploying to experimental_ios_build March 2, 2026 20:42 — with GitHub Actions Error
@Rohit3523 Rohit3523 had a problem deploying to experimental_android_build March 2, 2026 20:42 — with GitHub Actions Error

const keyExtractor = (item: IItemData) => item.value?.name || item.text?.text;

// RectButton doesn't work on modal (Android)
Copy link
Member

Choose a reason for hiding this comment

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

🤔

@Rohit3523 Rohit3523 had a problem deploying to experimental_android_build March 3, 2026 12:39 — with GitHub Actions Error
@Rohit3523 Rohit3523 had a problem deploying to official_android_build March 3, 2026 12:39 — with GitHub Actions Error
@Rohit3523 Rohit3523 had a problem deploying to experimental_ios_build March 3, 2026 12:39 — with GitHub Actions Error
@Rohit3523 Rohit3523 requested a deployment to approve_e2e_testing March 3, 2026 12:54 — with GitHub Actions Waiting
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.

3 participants