Skip to content

chore: enable edge to edge on android#7157

Open
Rohit3523 wants to merge 68 commits into
developfrom
edge-to-edge
Open

chore: enable edge to edge on android#7157
Rohit3523 wants to merge 68 commits into
developfrom
edge-to-edge

Conversation

@Rohit3523

@Rohit3523 Rohit3523 commented Apr 15, 2026

Copy link
Copy Markdown
Member

Proposed changes

Replace expo-navigation-bar with @zoontek/react-native-navigation-bar and add safe area bottom insets across 30+ views to enable proper edge-to-edge display on Android. This prevents content from being hidden behind the system navigation bar on devices with gesture navigation.

Key changes:

  • Replaced expo-navigation-bar with @zoontek/react-native-navigation-bar for better edge-to-edge support
  • Added paddingBottom: bottom (via useSafeAreaInsets / withSafeAreaInsets) to FlatLists, ScrollViews, and content containers across the app
  • Cleaned up hardcoded paddingBottom: 100 in NewServerView in favor of FormContainers built-in safe area handling
  • Switched JitsiMeetView from RNs built-in SafeAreaView to react-native-safe-area-contexts
  • Fixed RoomView footer sections to respect bottom safe area

Issue(s)

https://rocketchat.atlassian.net/browse/CORE-1967

How to test or reproduce

  1. Build and run on Android 12+ with gesture navigation enabled
  2. Verify these screens show content above the system navigation bar:
    • MessagesView / ThreadMessagesView / SearchMessagesView
    • RoomView (preview mode, read-only, blocked room footers)
    • RoomActionsView / RoomInfoEditView / RoomMembersView
    • DiscussionsView / TeamChannelsView / PickerView
    • NewMessageView / SelectedUsersView
    • SettingsView / LanguageView / StatusView / ProfileView
    • E2EEncryptionSecurityView / E2ESaveYourPasswordView
    • SelectServerView / SelectListView
    • ShareListView
  3. Verify the "Jump to last message" FAB in rooms respects bottom safe area
  4. Verify the "Add Server" screen (both first-run and from rooms list header) shows correctly without extra header spacing

Screenshots

Screen Android 12 Android 13 Android 14 Android 15 Android 16 Android 17 iOS
Login
Register
Rooms List
Select Server
Room View Default
Room Keyboard
Room Emoji Keyboard
Emoji Picker Bottom
Thread Messages
Search Messages
Room Members
New Message View
Directory
Discussions
Read Only Room
Status View
Language
Default Browser
Auto Translate
Room Action Sheet
Action Sheet Delete
Media Download Images
Members Filter
Profile
Reaction Picker
Reaction Picker Bottom

Summary by CodeRabbit

  • New Features
    • Enabled edge-to-edge display support on Android for a more immersive layout.
  • Bug Fixes
    • Improved bottom safe-area spacing across lists, screens, and the message composer to reduce content being obscured by gesture areas/system bars.
    • Refined action sheet bottom spacing and updated related detent calculations/behavior.
    • Standardized emoji keyboard and bottom inset behavior across platforms.
    • Updated Android navigation bar theming for better visual consistency.
  • Tests
    • Updated action sheet detent unit expectations.
  • Chores
    • Adjusted Android CI Gradle configuration and theme settings.

@coderabbitai

coderabbitai Bot commented Apr 15, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

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

Enables Android edge-to-edge display support, removes bottomInset from action sheet detent handling, and updates multiple containers and views to use safe-area bottom insets for layout padding.

Changes

Edge-to-Edge Android Configuration

Layer / File(s) Summary
Gradle, resources, and navigation bar API
android/gradle.properties, android/app/src/main/res/values/styles.xml, app/lib/methods/helpers/theme.ts
Sets edgeToEdgeEnabled=true, adds android:enforceNavigationBarContrast=false to AppTheme and BootTheme, and switches the Android navigation bar helper to setBarStyle(...).
CI build wiring
.github/actions/build-android/action.yml, .github/workflows/e2e-build-android.yml
Adds edgeToEdgeEnabled=true during Android build setup and in the E2E workflow, and sets persist-credentials: false on checkout in the workflow.

Action Sheet Refactoring

Layer / File(s) Summary
useActionSheetDetents contract and calculations
app/containers/ActionSheet/useActionSheetDetents.ts
Removes bottomInset from the hook type, inputs, detent calculations, and memo dependencies.
ActionSheet component behavior
app/containers/ActionSheet/ActionSheet.tsx
Drops platform/version-specific bottom inset logic, stops passing bottomInset into the hook, and simplifies content panning control.
BottomSheetContent padding
app/containers/ActionSheet/BottomSheetContent.tsx
Applies the bottom safe-area inset directly to the bottom sheet list padding.

Safe-Area Inset Consolidation

Layer / File(s) Summary
Container and sheet layout
app/containers/EmojiPicker/EmojiCategory.tsx, app/containers/FormContainer.tsx, app/views/DirectoryView/index.tsx
Updates bottom-sheet breathing room, scroll sizing, and list padding; DirectoryView also removes the explicit action-sheet panning override.
Scroll and list padding updates
app/views/AddExistingChannelView/index.tsx, app/views/CannedResponsesListView/index.tsx, app/views/DiscussionsView/index.tsx, app/views/NewMessageView/index.tsx, app/views/ProfileView/index.tsx, app/views/RoomInfoEditView/index.tsx, app/views/RoomMembersView/index.tsx, app/views/RoomsListView/index.tsx, app/views/SettingsView/index.tsx, app/views/StatusView/index.tsx
Reads the bottom safe-area inset in each view and applies it to the scroll or list content container padding.
Wrapped views, footer layout, and SafeAreaView import
app/views/ReadReceiptView/index.tsx, app/views/MessagesView/index.tsx, app/views/SelectListView.tsx, app/views/SearchMessagesView/index.tsx, app/views/TeamChannelsView.tsx, app/views/ThreadMessagesView/index.tsx, app/views/RoomActionsView/index.tsx, app/views/RoomView/index.tsx, app/views/JitsiMeetView/index.tsx
Wraps several views with safe-area HOCs, extends props with insets, hoists statics, updates the JitsiMeetView SafeAreaView import, and applies insets.bottom to list, scroll, and footer containers.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Suggested reviewers

  • diegolmello
  • OtavioStasiak
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

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.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main change: enabling Android edge-to-edge layout support.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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

Warning

Review ran into problems

🔥 Problems

Errors were encountered while retrieving linked issues.

Errors (14)
  • CORE-1967: Request failed with status code 401
  • API-31: Request failed with status code 401
  • ANDROID-12: Request failed with status code 401
  • API-33: Request failed with status code 401
  • ANDROID-13: Request failed with status code 401
  • API-34: Request failed with status code 401
  • ANDROID-14: Request failed with status code 401
  • API-35: Request failed with status code 401
  • ANDROID-15: Request failed with status code 401
  • API-36: Request failed with status code 401
  • ANDROID-16: Request failed with status code 401
  • API-37: Request failed with status code 401
  • ANDROID-17: Request failed with status code 401
  • IPHONE-16: Request failed with status code 401

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.

@Rohit3523 Rohit3523 had a problem deploying to official_android_build April 28, 2026 19:29 — with GitHub Actions Error
@Rohit3523 Rohit3523 had a problem deploying to experimental_android_build April 28, 2026 19:29 — with GitHub Actions Error
@Rohit3523 Rohit3523 had a problem deploying to experimental_ios_build April 28, 2026 19:29 — with GitHub Actions Error
@Rohit3523

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Apr 28, 2026

Copy link
Copy Markdown
Contributor
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@Rohit3523 Rohit3523 had a problem deploying to experimental_ios_build April 28, 2026 20:04 — with GitHub Actions Error
@Rohit3523 Rohit3523 had a problem deploying to experimental_android_build April 28, 2026 20:04 — with GitHub Actions Error
@Rohit3523 Rohit3523 had a problem deploying to official_android_build April 28, 2026 20:04 — with GitHub Actions Error

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Caution

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

⚠️ Outside diff range comments (1)
app/containers/ActionSheet/useActionSheetDetents.ts (1)

48-87: ⚠️ Potential issue | 🟠 Major

Add fontScale to the useMemo dependency array.

CANCEL_HEIGHT depends on fontScale from useWindowDimensions(), but the memo doesn't include fontScale in its dependencies. When the user changes text size (accessibility setting), fontScale updates but the memo won't recompute, leaving detent calculations stale.

Fix
-	}, [contentHeight, hasCancel, headerHeight, itemHeight, optionsLength, snaps, windowHeight]);
+	}, [contentHeight, fontScale, hasCancel, headerHeight, itemHeight, optionsLength, snaps, windowHeight]);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/containers/ActionSheet/useActionSheetDetents.ts` around lines 48 - 87,
The memo currently computes CANCEL_HEIGHT from fontScale (via
useWindowDimensions()) but does not include fontScale in the useMemo dependency
array, so detents won't update when fontScale changes; update the dependency
array for the useMemo that returns { detents, maxHeight, scrollEnabled } to
include fontScale (alongside contentHeight, hasCancel, headerHeight, itemHeight,
optionsLength, snaps, windowHeight) so that CANCEL_HEIGHT and all derived
calculations (maxSnap, measuredHeight, etc.) are recomputed when fontScale
changes.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@app/containers/ActionSheet/useActionSheetDetents.ts`:
- Around line 48-87: The memo currently computes CANCEL_HEIGHT from fontScale
(via useWindowDimensions()) but does not include fontScale in the useMemo
dependency array, so detents won't update when fontScale changes; update the
dependency array for the useMemo that returns { detents, maxHeight,
scrollEnabled } to include fontScale (alongside contentHeight, hasCancel,
headerHeight, itemHeight, optionsLength, snaps, windowHeight) so that
CANCEL_HEIGHT and all derived calculations (maxSnap, measuredHeight, etc.) are
recomputed when fontScale changes.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 924d26f6-ed5c-4379-aa92-9aaff1894492

📥 Commits

Reviewing files that changed from the base of the PR and between 2c4dd8d and c6a2b16.

📒 Files selected for processing (8)
  • android/gradle.properties
  • app/containers/ActionSheet/ActionSheet.tsx
  • app/containers/ActionSheet/BottomSheetContent.tsx
  • app/containers/ActionSheet/useActionSheetDetents.test.tsx
  • app/containers/ActionSheet/useActionSheetDetents.ts
  • app/containers/MessageComposer/hooks/useEmojiKeyboard.tsx
  • app/views/DirectoryView/index.tsx
  • app/views/JitsiMeetView/index.tsx
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: ESLint and Test / run-eslint-and-test
  • GitHub Check: format
🧰 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/views/JitsiMeetView/index.tsx
  • app/views/DirectoryView/index.tsx
  • app/containers/ActionSheet/BottomSheetContent.tsx
  • app/containers/MessageComposer/hooks/useEmojiKeyboard.tsx
  • app/containers/ActionSheet/useActionSheetDetents.ts
  • app/containers/ActionSheet/ActionSheet.tsx
  • app/containers/ActionSheet/useActionSheetDetents.test.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

**/*.{ts,tsx}: Use TypeScript with strict mode enabled and baseUrl set to app/ for module imports
Support iOS 13.4+ and Android 6.0+ as minimum target platforms

Files:

  • app/views/JitsiMeetView/index.tsx
  • app/views/DirectoryView/index.tsx
  • app/containers/ActionSheet/BottomSheetContent.tsx
  • app/containers/MessageComposer/hooks/useEmojiKeyboard.tsx
  • app/containers/ActionSheet/useActionSheetDetents.ts
  • app/containers/ActionSheet/ActionSheet.tsx
  • app/containers/ActionSheet/useActionSheetDetents.test.tsx
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx,js,jsx}: Use tabs for indentation with single quotes, 130 character line width, no trailing commas, and avoid arrow function parentheses when possible
Use ESLint with @rocket.chat/eslint-config base including React, React Native, TypeScript, and Jest plugins

Files:

  • app/views/JitsiMeetView/index.tsx
  • app/views/DirectoryView/index.tsx
  • app/containers/ActionSheet/BottomSheetContent.tsx
  • app/containers/MessageComposer/hooks/useEmojiKeyboard.tsx
  • app/containers/ActionSheet/useActionSheetDetents.ts
  • app/containers/ActionSheet/ActionSheet.tsx
  • app/containers/ActionSheet/useActionSheetDetents.test.tsx
app/views/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Create view components (screens) in app/views/ directory

Files:

  • app/views/JitsiMeetView/index.tsx
  • app/views/DirectoryView/index.tsx
app/containers/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Create reusable UI components in app/containers/ directory

Files:

  • app/containers/ActionSheet/BottomSheetContent.tsx
  • app/containers/MessageComposer/hooks/useEmojiKeyboard.tsx
  • app/containers/ActionSheet/useActionSheetDetents.ts
  • app/containers/ActionSheet/ActionSheet.tsx
  • app/containers/ActionSheet/useActionSheetDetents.test.tsx
🧠 Learnings (9)
📓 Common learnings
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: 2026-04-22T22:57:58.545Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat.ReactNative PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-04-22T22:57:58.545Z
Learning: Applies to {app/sagas/videoConf.ts,app/lib/methods/videoConf.ts} : Implement video conferencing in app/sagas/videoConf.ts and app/lib/methods/videoConf.ts using Redux actions, reducers, and sagas for server-managed Jitsi integration

Applied to files:

  • app/views/JitsiMeetView/index.tsx
📚 Learning: 2026-04-22T22:57:58.545Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat.ReactNative PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-04-22T22:57:58.545Z
Learning: Applies to app/AppContainer.tsx : Use AppContainer.tsx as the root navigation container that switches between authentication states

Applied to files:

  • app/views/JitsiMeetView/index.tsx
📚 Learning: 2026-04-22T22:57:58.545Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat.ReactNative PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-04-22T22:57:58.545Z
Learning: Applies to app/index.tsx : Set up Redux provider, theme, navigation, and notifications in app/index.tsx

Applied to files:

  • app/views/JitsiMeetView/index.tsx
  • app/containers/MessageComposer/hooks/useEmojiKeyboard.tsx
  • app/containers/ActionSheet/ActionSheet.tsx
📚 Learning: 2026-04-22T22:57:58.545Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat.ReactNative PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-04-22T22:57:58.545Z
Learning: Use React 19 with React Native 0.79 and Expo 53

Applied to files:

  • app/views/JitsiMeetView/index.tsx
  • app/containers/MessageComposer/hooks/useEmojiKeyboard.tsx
📚 Learning: 2026-04-04T21:34:30.268Z
Learnt from: Rohit3523
Repo: RocketChat/Rocket.Chat.ReactNative PR: 6808
File: app/containers/MessageComposer/components/ComposerInput.tsx:337-341
Timestamp: 2026-04-04T21:34:30.268Z
Learning: In Rocket.Chat React Native, the markdown composer's autocomplete insertion (ComposerInput.tsx onAutocompleteItemSelected) does NOT need to add a space between an underscore italic delimiter `_` and a `@` or `#` mention sigil. The web platform (using the same rocket.chat/message-parser) does not add such a space either, so parity with web is the correct behavior. The previous learning about "space between `_` and mention sigil" applies only to test/story file content strings, not to the composer's runtime autocomplete behavior.

Applied to files:

  • app/containers/MessageComposer/hooks/useEmojiKeyboard.tsx
📚 Learning: 2026-04-22T22:57:58.545Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat.ReactNative PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-04-22T22:57:58.545Z
Learning: Applies to **/*.{ts,tsx} : Support iOS 13.4+ and Android 6.0+ as minimum target platforms

Applied to files:

  • app/containers/MessageComposer/hooks/useEmojiKeyboard.tsx
  • app/containers/ActionSheet/ActionSheet.tsx
📚 Learning: 2026-04-22T22:57:58.545Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat.ReactNative PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-04-22T22:57:58.545Z
Learning: Applies to app/theme.tsx : Define theming context in app/theme.tsx

Applied to files:

  • app/containers/MessageComposer/hooks/useEmojiKeyboard.tsx
📚 Learning: 2026-04-22T22:57:58.545Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat.ReactNative PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-04-22T22:57:58.545Z
Learning: Applies to app/lib/hooks/useResponsiveLayout/**/*.{ts,tsx} : Implement responsive layouts using useResponsiveLayout hook to switch between master-detail on tablets and single stack on phones

Applied to files:

  • app/containers/ActionSheet/ActionSheet.tsx
🔇 Additional comments (7)
app/views/JitsiMeetView/index.tsx (1)

5-7: Import update looks good.

No concerns in this changed segment; this is a clean import adjustment.

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

38-43: Looks good.

Using the safe-area bottom inset as the only bottom padding source matches the edge-to-edge refactor and keeps spacing tied to the device inset.

app/containers/MessageComposer/hooks/useEmojiKeyboard.tsx (1)

79-98: Looks good.

The new bottom-based notch handling keeps keyboard spacing consistent across platforms and lines up with the safe-area driven refactor.

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

41-71: Looks good.

The updated expectations now match the hook's no-bottomInset formula.

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

4-9: Looks good.

The new disableContentPanning wiring and iOS-only contentMinHeight behavior align with the updated detent and inset flow.

Also applies to: 79-92

app/views/DirectoryView/index.tsx (1)

172-185: Looks good.

Removing the explicit enableContentPanningGesture override keeps this screen aligned with the new ActionSheet default behavior.

android/gradle.properties (1)

48-51: Verify the host activity before enabling this flag.

edgeToEdgeEnabled only takes effect with ReactActivity; if the Android entry point uses a custom activity, this property will be ignored and the edge-to-edge change won't ship.

}}
ItemSeparatorComponent={List.Separator}
contentContainerStyle={{ backgroundColor: colors.surfaceRoom }}
contentContainerStyle={{ backgroundColor: colors.surfaceRoom, paddingBottom: bottom }}

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

To prevent last item from hiding behind nav bar

Comment thread app/views/E2EEncryptionSecurityView/index.tsx Outdated
import { type RouteProp, useNavigation, useRoute } from '@react-navigation/native';
import { activateKeepAwake, deactivateKeepAwake } from 'expo-keep-awake';
import { useCallback, useEffect, useState, type ReactElement } from 'react';
import { ActivityIndicator, Linking, SafeAreaView, StyleSheet, View } from 'react-native';

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

SafeAreaView from react-native is deprecated

const { submit } = useConnectServer({ workspaceUrl, certificate, previousServer });
const phoneMarginTop = previousServer ? 32 : 84;
const marginTop = isTablet ? 0 : phoneMarginTop;
const formContainerStyle = previousServer ? { paddingBottom: 100 } : {};

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I have verified and there is no UI difference

Comment thread app/views/ReadReceiptView/index.tsx Outdated
export default connect(mapStateToProps)(withTheme(ReadReceiptView));
const ReadReceiptViewWithInsets = withSafeAreaInsets(ReadReceiptView);
hoistNonReactStatics(ReadReceiptViewWithInsets, ReadReceiptView);
export default connect(mapStateToProps)(withTheme(ReadReceiptViewWithInsets));

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Added hoistNonReactStatics because withSafeAreaInsets was removing the static navigation options, causing the header title to disappear.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

You're having to repeat yourself on other places like RoomActionsView. I'd patch withSafeAreaInsets in the lib instead. It should be simple to add hoistNonReactStatics there.

Comment thread app/views/RoomActionsView/index.tsx Outdated
export default connect(mapStateToProps)(withTheme(withActionSheet(withDimensions(withMasterDetail(RoomActionsView)))));
const RoomActionsViewWithInsets = withSafeAreaInsets(RoomActionsView);
hoistNonReactStatics(RoomActionsViewWithInsets, RoomActionsView);
export default connect(mapStateToProps)(withTheme(withActionSheet(withDimensions(withMasterDetail(RoomActionsViewWithInsets)))));

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Added hoistNonReactStatics because withSafeAreaInsets was removing the static navigation options, causing the header title to disappear.

export default StyleSheet.create({
scrollContentContainer: {
paddingTop: 16
},

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

For some reason, the room action view lost the top padding, so added padding top to get the old UI

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

"For some reason" always gets me 🤔 or 🙈

Comment thread app/views/SearchMessagesView/index.tsx Outdated
export default connect(mapStateToProps)(withTheme(withMasterDetail(SearchMessagesView)));
const SearchMessagesViewWithInsets = withSafeAreaInsets(SearchMessagesView);
hoistNonReactStatics(SearchMessagesViewWithInsets, SearchMessagesView);
export default connect(mapStateToProps)(withTheme(withMasterDetail(SearchMessagesViewWithInsets)));

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Added hoistNonReactStatics because withSafeAreaInsets was removing the static navigation options, causing the header title to disappear.

@Rohit3523

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jun 24, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 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/views/MessagesView/index.tsx`:
- Line 392: The `withSafeAreaInsets` HOC is dropping static properties like
`navigationOptions` because the wrapped `MessagesView` class is hidden behind
`React.forwardRef`. Update the export chain around `MessagesView` so the final
connected component preserves statics by using `hoistNonReactStatics` after
composing `withSafeAreaInsets`, `withMasterDetail`, `withActionSheet`,
`withTheme`, and `connect(mapStateToProps)`. Make sure the hoisted component
keeps `MessagesView`’s static keys available to react-navigation.
🪄 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: b9d9cb28-6da5-42ae-96e4-fc0291275f1c

📥 Commits

Reviewing files that changed from the base of the PR and between 34ad7f7 and 311a2d7.

📒 Files selected for processing (20)
  • android/app/src/main/res/values/styles.xml
  • app/lib/methods/helpers/theme.ts
  • app/views/AddExistingChannelView/index.tsx
  • app/views/CannedResponsesListView/index.tsx
  • app/views/DirectoryView/index.tsx
  • app/views/DiscussionsView/index.tsx
  • app/views/MessagesView/index.tsx
  • app/views/NewMessageView/index.tsx
  • app/views/ProfileView/index.tsx
  • app/views/RoomActionsView/index.tsx
  • app/views/RoomActionsView/styles.ts
  • app/views/RoomMembersView/index.tsx
  • app/views/RoomView/index.tsx
  • app/views/RoomsListView/index.tsx
  • app/views/SearchMessagesView/index.tsx
  • app/views/SelectListView.tsx
  • app/views/SettingsView/index.tsx
  • app/views/StatusView/index.tsx
  • app/views/TeamChannelsView.tsx
  • app/views/ThreadMessagesView/index.tsx
✅ Files skipped from review due to trivial changes (3)
  • app/views/RoomActionsView/styles.ts
  • app/views/DiscussionsView/index.tsx
  • android/app/src/main/res/values/styles.xml
🚧 Files skipped from review as they are similar to previous changes (2)
  • app/views/SearchMessagesView/index.tsx
  • app/views/RoomActionsView/index.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/views/AddExistingChannelView/index.tsx
  • app/views/StatusView/index.tsx
  • app/views/SettingsView/index.tsx
  • app/views/CannedResponsesListView/index.tsx
  • app/views/NewMessageView/index.tsx
  • app/lib/methods/helpers/theme.ts
  • app/views/RoomView/index.tsx
  • app/views/ThreadMessagesView/index.tsx
  • app/views/RoomsListView/index.tsx
  • app/views/MessagesView/index.tsx
  • app/views/SelectListView.tsx
  • app/views/ProfileView/index.tsx
  • app/views/TeamChannelsView.tsx
  • app/views/DirectoryView/index.tsx
  • app/views/RoomMembersView/index.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

Use TypeScript with strict mode enabled

Files:

  • app/views/AddExistingChannelView/index.tsx
  • app/views/StatusView/index.tsx
  • app/views/SettingsView/index.tsx
  • app/views/CannedResponsesListView/index.tsx
  • app/views/NewMessageView/index.tsx
  • app/lib/methods/helpers/theme.ts
  • app/views/RoomView/index.tsx
  • app/views/ThreadMessagesView/index.tsx
  • app/views/RoomsListView/index.tsx
  • app/views/MessagesView/index.tsx
  • app/views/SelectListView.tsx
  • app/views/ProfileView/index.tsx
  • app/views/TeamChannelsView.tsx
  • app/views/DirectoryView/index.tsx
  • app/views/RoomMembersView/index.tsx
**/*.{js,jsx,ts,tsx,json}

📄 CodeRabbit inference engine (CLAUDE.md)

Use Prettier formatting with tabs, single quotes, 130 character line width, no trailing commas, and avoid arrow function parentheses

Files:

  • app/views/AddExistingChannelView/index.tsx
  • app/views/StatusView/index.tsx
  • app/views/SettingsView/index.tsx
  • app/views/CannedResponsesListView/index.tsx
  • app/views/NewMessageView/index.tsx
  • app/lib/methods/helpers/theme.ts
  • app/views/RoomView/index.tsx
  • app/views/ThreadMessagesView/index.tsx
  • app/views/RoomsListView/index.tsx
  • app/views/MessagesView/index.tsx
  • app/views/SelectListView.tsx
  • app/views/ProfileView/index.tsx
  • app/views/TeamChannelsView.tsx
  • app/views/DirectoryView/index.tsx
  • app/views/RoomMembersView/index.tsx
**/*.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Enforce ESLint rules from @rocket.chat/eslint-config with React, React Native, TypeScript, and Jest plugins

Files:

  • app/views/AddExistingChannelView/index.tsx
  • app/views/StatusView/index.tsx
  • app/views/SettingsView/index.tsx
  • app/views/CannedResponsesListView/index.tsx
  • app/views/NewMessageView/index.tsx
  • app/lib/methods/helpers/theme.ts
  • app/views/RoomView/index.tsx
  • app/views/ThreadMessagesView/index.tsx
  • app/views/RoomsListView/index.tsx
  • app/views/MessagesView/index.tsx
  • app/views/SelectListView.tsx
  • app/views/ProfileView/index.tsx
  • app/views/TeamChannelsView.tsx
  • app/views/DirectoryView/index.tsx
  • app/views/RoomMembersView/index.tsx
app/views/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Place screen components in 'app/views/' directory

Files:

  • app/views/AddExistingChannelView/index.tsx
  • app/views/StatusView/index.tsx
  • app/views/SettingsView/index.tsx
  • app/views/CannedResponsesListView/index.tsx
  • app/views/NewMessageView/index.tsx
  • app/views/RoomView/index.tsx
  • app/views/ThreadMessagesView/index.tsx
  • app/views/RoomsListView/index.tsx
  • app/views/MessagesView/index.tsx
  • app/views/SelectListView.tsx
  • app/views/ProfileView/index.tsx
  • app/views/TeamChannelsView.tsx
  • app/views/DirectoryView/index.tsx
  • app/views/RoomMembersView/index.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/views/AddExistingChannelView/index.tsx
  • app/views/StatusView/index.tsx
  • app/views/SettingsView/index.tsx
  • app/views/CannedResponsesListView/index.tsx
  • app/views/NewMessageView/index.tsx
  • app/lib/methods/helpers/theme.ts
  • app/views/RoomView/index.tsx
  • app/views/ThreadMessagesView/index.tsx
  • app/views/RoomsListView/index.tsx
  • app/views/MessagesView/index.tsx
  • app/views/SelectListView.tsx
  • app/views/ProfileView/index.tsx
  • app/views/TeamChannelsView.tsx
  • app/views/DirectoryView/index.tsx
  • app/views/RoomMembersView/index.tsx
🔇 Additional comments (16)
app/views/DirectoryView/index.tsx (1)

28-28: LGTM!

Also applies to: 40-40, 43-50, 56-72, 203-203

app/views/AddExistingChannelView/index.tsx (1)

24-24: LGTM!

Also applies to: 42-42, 44-54, 180-180

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

28-28: LGTM!

Also applies to: 70-71, 276-276

app/views/NewMessageView/index.tsx (1)

21-21: LGTM!

Also applies to: 37-37, 39-47, 110-110

app/views/ProfileView/index.tsx (1)

37-37: LGTM!

Also applies to: 62-62, 85-85, 285-285, 297-300

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

47-47: LGTM!

Also applies to: 70-70, 496-496, 515-515, 538-541

app/views/RoomView/index.tsx (1)

44-45: LGTM!

Also applies to: 1529-1531, 1537-1537, 1552-1552, 1567-1587, 1597-1597, 1759-1761

app/views/RoomMembersView/index.tsx (1)

83-92: LGTM!

Also applies to: 439-439

app/views/RoomsListView/index.tsx (1)

45-48: LGTM!

Also applies to: 138-138

app/views/StatusView/index.tsx (1)

112-112: LGTM!

Also applies to: 142-142, 249-249

app/views/MessagesView/index.tsx (1)

59-59: LGTM!

Also applies to: 363-363, 377-377

app/views/SelectListView.tsx (1)

42-42: LGTM!

Also applies to: 195-195, 204-204, 212-212

app/views/TeamChannelsView.tsx (1)

98-98: LGTM!

Also applies to: 548-576, 604-606

app/views/SettingsView/index.tsx (1)

141-141: 🩺 Stability & Availability

List.Container supports contentContainerStyle.

The List.Container implementation maps directly to a ScrollView that spreads all received props ({...props}) onto the native component. This ensures that passing contentContainerStyle={{ paddingBottom: bottom }} correctly applies the padding to the underlying scrollable content without being overwritten.

app/lib/methods/helpers/theme.ts (2)

3-3: LGTM!

Also applies to: 53-54


56-59: 🩺 Stability & Availability

Remove suggestion to use .catch() for synchronous method.

NavigationBar.setBarStyle from @zoontek/react-native-navigation-bar is a synchronous function that returns void, not a Promise. Therefore, the existing try/catch block is correct for handling potential synchronous errors, and no asynchronous error handling (like .catch()) is required.

			> Likely an incorrect or invalid review comment.

Comment thread app/views/MessagesView/index.tsx
@github-actions

Copy link
Copy Markdown

@github-actions

Copy link
Copy Markdown

iOS Build Available

Rocket.Chat 4.74.0.109207

@diegolmello diegolmello left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Almost there!
Nice job with the screenshots.

Just to be sure: we should test on landscape and on tablets.

Comment thread .github/workflows/e2e-build-android.yml Outdated
- name: Checkout Repository
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
with:
persist-credentials: false

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

looks unrelated to the pr. what does it do?

Comment thread app/containers/FormContainer.tsx
Comment thread app/views/E2EEncryptionSecurityView/index.tsx Outdated
Comment thread app/views/JitsiMeetView/index.tsx Outdated
Comment thread app/views/ReadReceiptView/index.tsx Outdated
export default connect(mapStateToProps)(withTheme(ReadReceiptView));
const ReadReceiptViewWithInsets = withSafeAreaInsets(ReadReceiptView);
hoistNonReactStatics(ReadReceiptViewWithInsets, ReadReceiptView);
export default connect(mapStateToProps)(withTheme(ReadReceiptViewWithInsets));

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

You're having to repeat yourself on other places like RoomActionsView. I'd patch withSafeAreaInsets in the lib instead. It should be simple to add hoistNonReactStatics there.

Comment thread app/views/RoomActionsView/index.tsx Outdated
export default StyleSheet.create({
scrollContentContainer: {
paddingTop: 16
},

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

"For some reason" always gets me 🤔 or 🙈

Comment thread app/views/SettingsView/index.tsx Outdated
Comment thread package.json

@diegolmello diegolmello left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Code review — Edge-to-edge Android (#7157)

Consolidated from two independent review passes. Inline comments below.

Correctness (worth fixing before merge):

  1. JitsiMeetView — SafeAreaView from react-native-safe-area-context with no edges insets the WebView on all four sides on Android.
  2. SettingsView (+ a ListContainer merge fix) — contentContainerStyle override drops the default paddingVertical: 16.
  3. FormContainer — { paddingBottom: bottom } overrides the base paddingBottom: 24 across all form screens.
  4. useEmojiKeyboard — Android loses its Platform gating → composer spacer + double-counted notch.
  5. useActionSheetDetents — dropped HANDLE_HEIGHT can clip the last row of custom-content sheets.
  6. EmojiCategory — inset double-counted against the parent's marginBottom.
  7. E2EEncryptionSecurityView — padding on the wrong element (outer frame, not scroll content).
  8. BottomSheetContent — Android lost the Cancel-row bottom padding.

Confirm intent / device-check: ActionSheet content-panning, NavBottomFAB offset, NewServerView cert-picker clearance.

Inset-dependent — only bites where insets.bottom is 0 (hardware buttons, landscape, tablet master-detail): RoomActionsView, and the LanguageView / AutoTranslate / DefaultBrowser / SelectServer / SelectList FlatLists.

Minor: RoomActionsView insets should use the EdgeInsets type.

Note: CI sets edgeToEdgeEnabled=true both in android/gradle.properties and by echoing it in the two build workflows — two sources of truth, so a future toggle in gradle.properties won't take effect in CI.

Verified-correct, no action: the added hoistNonReactStatics calls, the zoontek setBarStyle API, the RoomView footer change (paddingBottom is additive to the existing marginBottom), and FormContainer's flexGrow change.

Comment thread app/views/JitsiMeetView/index.tsx Outdated
Comment thread app/views/SettingsView/index.tsx
Comment thread app/containers/FormContainer.tsx Outdated
Comment thread app/containers/MessageComposer/hooks/useEmojiKeyboard.tsx
Comment thread app/containers/ActionSheet/useActionSheetDetents.ts

return (
<View style={styles.container}>
<View style={[styles.container, { bottom: EDGE_DISTANCE + bottom }]}>

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

bottom: EDGE_DISTANCE + bottom — this FAB is absolutely positioned inside the message List view, whose bottom edge is the top of the composer (RoomView's SafeAreaView uses edges={['right','left']}, so the list doesn't extend into the nav-bar area; the composer is a sibling below it). Adding the nav-bar inset bottom here looks like it offsets the FAB ~bottompx too high, leaving a gap above the composer on nav-bar devices. Please confirm the FAB still sits just above the composer.

Comment thread app/views/RoomActionsView/index.tsx Outdated
Comment thread app/views/RoomActionsView/index.tsx Outdated
Comment thread app/views/LanguageView/index.tsx Outdated
Comment thread app/views/NewServerView/index.tsx
@github-actions

Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants