Skip to content

chore: develop into feat.voip-lib-new (RN 81 + Expo 54 + reanimated 4 + true-sheet + iOS 26) - #7114

Merged
diegolmello merged 75 commits into
feat.voip-lib-newfrom
merge/develop-into-voip-lib-new
Apr 9, 2026
Merged

chore: develop into feat.voip-lib-new (RN 81 + Expo 54 + reanimated 4 + true-sheet + iOS 26)#7114
diegolmello merged 75 commits into
feat.voip-lib-newfrom
merge/develop-into-voip-lib-new

Conversation

@diegolmello

@diegolmello diegolmello commented Apr 8, 2026

Copy link
Copy Markdown
Member

Summary

Merges origin/develop into feat.voip-lib-new (VoIP lib branch). 71 commits, executed slice-by-slice with per-gate verification.

What was merged

  • RN 0.79 → 0.81 + Expo 53 → 54 (cherry-picked, then develop bulk merge)
  • Reanimated 3 → 4 (VoIP animation screens migrated off @discord/bottom-sheetreact-native-true-sheet)
  • iOS 26 deployment target bump
  • All origin/develop commits through 2637261cd (feat.voip-lib-new tip)
    https://rocketchat.atlassian.net/browse/VMUX-73

Adapt commits (merge-specific fixes)

  • VoipModule.mm: codegen header renamed <RocketChatSpecs/RocketChatSpecs.h><SSLPinning/SSLPinning.h> (RN 0.81 umbrella name)
  • VoipModule.kt / VoipTurboPackage.kt: NativeVoipSpec import package chat.rocket.reactnativechat.rocket.reactnative.networking
  • patches/react-native-config-reader+4.1.1.patch: new patch — ios/**/*ios/*.{h,m} (fixes xcodebuild exit 65 from extra .xcodeproj file in glob)
  • app/containers/message/Touch.tsx: restored from develop (was incorrectly deleted; merged Message.tsx uses ./Touch import)
  • Podfile.lock regenerated (clean reinstall post-merge)
  • 9 snapshot suites regenerated (#E4E7EA → #C1C7D0 color token churn)

Gates passed

Gate Result
23 conflict resolutions, ESLint clean, snapshots regen'd PASS
NotificationIntentHandler subagent review PASS
pod install (132 deps, all VoIP pods present) PASS
iOS builds on simulator (xcodebuild, iPhone 16e) PASS
Android Kotlin compiles (compileExperimentalDebugKotlin) PASS
Zero [Reanimated] warnings in 60s Metro exercise PASS

Skipped gates

  • Slice 12 (wake-from-killed VoIP push — physical device) — deferred
  • Slice 13 (P0 smoke matrix — physical device) — deferred

Test plan

  • yarn install — patches apply clean
  • yarn pod-install — 132 pods, no errors
  • iOS simulator build succeeds
  • Android compileExperimentalDebugKotlin succeeds
  • VoIP call flow (physical device): outbound + inbound + wake-from-killed

Rohit3523 and others added 30 commits January 16, 2026 13:04
* fix: formatting base64 images wrong

* chore: add base64 avatar storybook case

* chore: improve unit tests of getAvatarUrl

* chore: format code and fix lint issues [skip ci]

* fix: unit test

* cleanup

---------

Co-authored-by: OtavioStasiak <OtavioStasiak@users.noreply.github.com>
* fix: hide elements instead of conditional render

* chore: update snapshot test

* fix: remove useMemo

* chore: add case on storybook

* fix: snapshot test

* chore: format code and fix lint issues [skip ci]

---------

Co-authored-by: OtavioStasiak <OtavioStasiak@users.noreply.github.com>
* fix: collapsible attachment with text duplicating the content

* fix: ktex breaking the app

* fix: snapshot test

* chore: format code and fix lint issues [skip ci]

* cleanup

* cleanup

* cleanup

* chore: format code and fix lint issues [skip ci]

---------

Co-authored-by: OtavioStasiak <OtavioStasiak@users.noreply.github.com>
Co-authored-by: Rohit Bansal <40559587+Rohit3523@users.noreply.github.com>
* fix: collapsible attachment with text duplicating the content

* fix: nested attachment does not render

* chore: storybook nested reply

* fix: update snapshot test

* chore: format code and fix lint issues [skip ci]

* code improvements

* fix: forward message between channels not rendering image

* update snapshot test

* fix: collapsible attachment with text duplicating the content

* fix: snapshot test

---------

Co-authored-by: OtavioStasiak <OtavioStasiak@users.noreply.github.com>
* chore: type of getAvatarSuggestion

* chore: add getAvatarSuggestion endpoint and backward compatibility

* chore: format code and fix lint issues [skip ci]

---------

Co-authored-by: OtavioStasiak <OtavioStasiak@users.noreply.github.com>
* fix: collapsible attachment with text duplicating the content

* chore: format code and fix lint issues [skip ci]

* fix: unit test

* code improvements

* chore: format code and fix lint issues

* fix: collapsible attachment with text duplicating the content

* fix: snapshot test

* chore: format code and fix lint issues

* fix: forwarding a message twice does not render the attachment (#6960)

* fix: collapsible attachment with text duplicating the content

* fix: nested attachment does not render

* chore: storybook nested reply

* fix: update snapshot test

* chore: format code and fix lint issues [skip ci]

* code improvements

* fix: forward message between channels not rendering image

* update snapshot test

* fix: collapsible attachment with text duplicating the content

* fix: snapshot test

---------

Co-authored-by: OtavioStasiak <OtavioStasiak@users.noreply.github.com>

* fix: remove getAvatarSuggestion deprecated method (#6948)

* chore: type of getAvatarSuggestion

* chore: add getAvatarSuggestion endpoint and backward compatibility

* chore: format code and fix lint issues [skip ci]

---------

Co-authored-by: OtavioStasiak <OtavioStasiak@users.noreply.github.com>

* fix: snapshot test

* fix: snapshot test

---------

Co-authored-by: OtavioStasiak <OtavioStasiak@users.noreply.github.com>
OtavioStasiak and others added 11 commits April 8, 2026 14:13
…#6970)

Follow-up to the true-sheet cherry-pick: the VoIP branch carried
bottom-sheet usage that the migration did not cover, and the theirs-first
resolution on jest.setup.js dropped VoIP-only mocks.

- jest.setup.js: restore react-native-incall-manager + expo-haptics object
  mocks that VoIP tests depend on (Haptics.ImpactFeedbackStyle.Light)
- NewMediaCall stories (Container, FilterHeader, NewMediaCall): drop
  BottomSheet wrapper decorators; replace with a plain View (storybook
  visual-only, no runtime impact)
- FilterHeader.tsx, Dialpad.tsx: drop removed `bottomSheet` FormTextInput
  prop (no longer exists post-true-sheet migration)
- Regenerate affected snapshots (FilterHeader, ServerItem, TextInput,
  Markdown, Dialpad) per-file — non-VoIP screens see style churn from
  true-sheet render tree; Dialpad/FilterHeader regen due to the prop
  removals above
Reanimated 4's new worklets runtime and the migration from
useAnimatedGestureHandler to the Gesture.Pan() API in Seek.tsx change
the render tree of nested message components that embed the audio
player. 98 snapshots updated, 5 obsolete removed. Non-VoIP,
upstream-driven churn.
Follow-up to the RN 81 / Expo 54 cherry-pick:

Snapshot regeneration (per-file, not blanket) — 200 snapshots updated
and 8 obsolete removed across 26 suites. All failures were render-tree
churn from RN 81 + Expo 54 + gesture-handler/reanimated bumps, none
were functional regressions:
  - VoIP: CallView/index, Dialpad, CallerInfo, FilterHeader, PeerItem,
    PeerList, SelectedPeer, MediaCallHeader, Message
  - Non-VoIP: Avatar, Button, DirectoryItem, List, LoginServices,
    RoomItem, ServerItem, TextInput, UiKitMessage, UiKitModal,
    CannedResponseItem, DiscussionsView/Item, ThreadMessagesView/Item,
    LoadMore, NewMessageView/Item, ServersHistoryItem, RoomInfoButtons

TypeScript tightening fixes (RN 81 / react-navigation ^7):
  - ForwardMessageView: drop dead `?? true` after `!!x` coalescing
  - RoomView: @ts-ignore generic `keyof ModalStackParamList` vs literal
    screen name (pre-existing VoIP pattern)

jest.setup.js: eslint --fix on arrow-body-style (new mocks added by
develop in the cherry-pick did not match repo style).

yarn.lock: updated by `yarn install` to register VoIP-only deps
(callkeep, incall-manager, media-signaling, platform-touchable,
prompt-android, slowlog, webrtc, zustand) on top of develop's lock.
**BASE_TIP:** 58e91f1

# Merge develop → feat.voip-lib-new (v6)

Executed from `.worktrees/merge-develop` on branch `merge/develop-into-voip-lib-new`.

## Slice 1 — Branch hygiene + worktree + preflight

- **Started:** 2026-04-08
- Archived prior aborted branch: `archive/merge-develop-v5-aborted-2026-04-08` → `ea118b952`
- Reset `merge/develop-into-voip-lib-new` to `58e91f1b7` (origin/feat.voip-lib-new)
- Created worktree at `.worktrees/merge-develop`
- `git fsck --no-dangling`: clean
- `df -h`: 23Gi free (user explicitly waived >100 GB precheck — "Don't worry about git or storage")
- Extracted `MERGE_NOTES.md.v5-baseline` from `archive/merge-develop-v5-aborted-2026-04-08:MERGE_NOTES.md`
- Primary checkout at `/Users/diegomello/Development/Work/Rocket.Chat.ReactNative` untouched

## Slice 2 — Initial baseline `yarn install`

- `yarn install` exit 0
- `node_modules/` populated
- `patch-package` applied all 15 patches cleanly (zero "Hunk failed"):
  `@discord/bottom-sheet@4.6.1`, `@rocket.chat/message-parser@0.31.31`, `@rocket.chat/sdk@1.3.3-mobile`,
  `@types/ejson@2.2.2`, `expo-file-system@18.1.7`, `expo-image@2.3.2`, `react-native@0.79.4`,
  `react-native-callkeep@4.3.16`, `react-native-easy-toast@2.3.0`, `react-native-mmkv@3.3.3`,
  `react-native-modal@13.0.1`, `react-native-notifier@1.6.1`, `react-native-picker-select@9.0.1`,
  `react-native-webview@13.15.0`, `remove-markdown@0.3.0`

## Slice 3 — Cherry-pick 2a: iOS 26 deployment target (#6974)

- `git cherry-pick -x 09ec94d` → commit `79a987603` (clean, no conflicts)
  - Auto-merged `.github/actions/upload-ios/action.yml` and `ios/RocketChatRN/Info.plist`
  - 6 files changed, 10 insertions, 8 deletions
- Podfile: no VoIP pod entries to preserve (VoIP libs autolink via package.json; Podfile has no explicit `callkeep`/`media-signaling` refs, pre- or post-cherry-pick)
- Gates:
  - `yarn install` exit 0 (cached, 0.8s)
  - `yarn lint` exit 0 (184 warnings, 0 errors)
  - `yarn test` exit 0 (127 suites, 1022 tests, 317 snapshots, 18.2s)
  - `grep -rE "^<<<<<<< "` → 0
- Commit count `git log feat.voip-lib-new..HEAD --oneline | wc -l` == 1
- No `pod install` (deferred Phase 4)
- **Adapt:** created `.worktrees/.eslintrc.js` barrier (`module.exports = { root: true }`) to stop ESLint cascading from the worktree into the primary checkout's config (worktree is nested inside primary). Not tracked, not part of any commit.

## Slice 4 — Cherry-pick 2b: react-native-true-sheet (#6970)

- `git cherry-pick -x ec27a7c` → commit `4eba633eb`
- Conflicts resolved (`git checkout --theirs` on all 3):
  - `app/containers/ActionSheet/ActionSheet.tsx` → theirs (develop's TrueSheet usage)
  - `app/containers/TextInput/FormTextInput.tsx` → theirs (dropped `BottomSheetTextInput` import)
  - `jest.setup.js` → theirs (dropped bottom-sheet mock, gained TrueSheet mock)
- **Fallout from `--theirs` on `jest.setup.js`**: wiped VoIP-only mocks (`react-native-incall-manager`, `expo-haptics` object form). Restored via adapt commit below.
- `git grep '@discord/bottom-sheet'` in `app/views/CallView/**` → 0 hits
- Other VoIP-side `@discord/bottom-sheet` imports found in NewMediaCall stories + `bottomSheet` prop usages on `FormTextInput` in Dialpad.tsx + FilterHeader.tsx → migrated via adapt commit
- Gates:
  - `yarn install` exit 0 (patch-package: 15/15 applied, `@lodev09/react-native-true-sheet@3.7.3` replaces `@discord/bottom-sheet`)
  - `yarn lint` exit 0 (181 warnings, 0 errors)
  - `yarn test` exit 0 (128 suites, 1027 tests, 317 snapshots)
  - `grep -rE "^<<<<<<< "` → 0
- Snapshot regeneration (per-file, not blanket):
  - `FilterHeader.test.tsx.snap` (VoIP; justification: BottomSheet decorator removed → shallower render tree)
  - `Dialpad.test.tsx.snap` (VoIP; justification: `bottomSheet` prop removed from Dialpad.tsx + upstream RN TextInput `textAlign: "auto"` default)
  - `TextInput.test.tsx.snap`, `ServerItem.test.tsx.snap`, `Markdown.test.tsx.snap` (non-VoIP; justification: true-sheet render tree style churn from upstream components)
- **Adapt commit `021f3d664`**: `adapt: migrate VoIP screens off @discord/bottom-sheet (post true-sheet #6970)`
- Commit count: `git log feat.voip-lib-new..HEAD --oneline | wc -l` == 3 (2 cherry-picks + 1 adapt)

## Slice 5 — Cherry-pick 2c: reanimated v4 (#6720)

- `git cherry-pick -x 75d866b` → commit `d8a2c8f06`
- Conflicts (4):
  - `package.json`: manual union — kept VoIP's `react-native-prompt-android: 1.1.0`, took develop's `react-native-reanimated: ^4.1.3` and `react-native-worklets: ^0.6.1`; other VoIP-exclusive deps (`react-native-platform-touchable`, `react-native-slowlog`, `react-native-webrtc`) were already on non-conflicted context lines and preserved automatically
  - `app/containers/AudioPlayer/Seek.tsx` → theirs (develop migrated from `useAnimatedGestureHandler` to `Gesture.Pan()` API; VoIP did not touch this file)
  - `app/containers/message/__snapshots__/Message.test.tsx.snap` → theirs, then regenerated post-install (see adapt below)
  - `yarn.lock`: **attempted regeneration from scratch failed** — patch-package bombed on `@rocket.chat/message-parser` (0.31.31 → 0.31.35) and `react-native-webview` (13.15.0 → 13.16.1) because yarn floated to newer compatible versions with an empty lock. Recovered by `git checkout 75d866b -- yarn.lock` (develop's reanimated-PR lock), then `yarn install` to reconcile VoIP-only entries. All 15 patches applied cleanly afterwards. **Recipe for future cherry-picks: prefer `git checkout <sha> -- yarn.lock` over `rm yarn.lock && yarn install`.**
- `babel.config.js` → byte-identical to `git show origin/develop:babel.config.js` (not conflicted; auto-merged)
- Gates:
  - `yarn install` exit 0 (all 15 patches applied)
  - `yarn lint` exit 0 (176 warnings, 0 errors)
  - `yarn test` exit 0 (128 suites, 1027 tests, 317 snapshots)
  - `grep -rE "^<<<<<<< "` → 0
- Snapshot regeneration (per-file, not blanket):
  - `Message.test.tsx.snap` (non-VoIP; 98 updated, 5 obsolete removed; justification: reanimated 4 worklets runtime + Seek.tsx gesture API migration alter the render tree of message components that embed the audio player)
- **Adapt commit `95fbb9669`**: `adapt: regenerate Message.test.tsx.snap for reanimated 4 (#6720)`
- Commit count: `git log feat.voip-lib-new..HEAD --oneline | wc -l` == 5 (3 cherry-picks + 2 adapts)

## Slice 6 — Cherry-pick 2d: RN 81 + Expo 54 (#6875)

- `git cherry-pick -x 91b2234` → commit `d8b48adba`
- Highest-risk single slice. Recipes applied per v6 plan.
- Conflicts:
  - **modify/delete (VoIP deleted, develop modified)** — resolved with `git rm`:
    - `app/containers/InAppNotification/__snapshots__/NotifierComponent.test.tsx.snap`
    - `app/containers/message/Touch.tsx`
  - **content (`--theirs`, develop's version)**: 16 snapshot files + `ios/Podfile.lock` + `ios/RocketChatRN.xcodeproj/project.pbxproj`
  - **content (`--ours`, VoIP's version)**:
    - `app/containers/Button/index.tsx` (VoIP migrated from `RectButton` → `Touchable`)
    - `app/containers/UIKit/Overflow.tsx` (VoIP uses `Touchable` + `touchable[blockId]` ref pattern; develop's version imports a `Touch` helper that VoIP removed)
  - **`package.json`**: took theirs then spliced 12 VoIP-exclusive deps back alphabetically:
    - dependencies: `@rocket.chat/media-signaling`, `react-native-callkeep`, `react-native-incall-manager`, `react-native-platform-touchable`, `react-native-prompt-android`, `react-native-slowlog`, `react-native-webrtc`, `zustand`
    - devDependencies: `@types/react-native-platform-touchable`, `eslint-plugin-jsx-a11y`, `lint-staged`
    - Dropped VoIP-side `prop-types` (unused in app/)
  - **`yarn.lock`**: `git checkout 91b2234 -- yarn.lock` then `yarn install` to reconcile VoIP entries (recipe from slice 5)
- patch-package post-install: 14/14 applied (down from 15 — `expo-image+2.3.2.patch` correctly died on expo-image 3.0.x bump)
- Native config: `ios/Podfile.lock`, `ios/RocketChatRN.xcodeproj/project.pbxproj`, `android/` files — all took develop's RN 81 / AGP / Kotlin / Gradle bumps (auto-merged or `--theirs`)
- Package.json AC checks:
  - `react-native` == `0.81.5` ✓
  - `expo` == `^54.0.0` ✓
  - `@rocket.chat/media-signaling` == `file:./packages/rocket.chat-media-signaling-0.1.3.tgz` ✓
  - `react-native-callkeep` == `4.3.16` ✓
- Patches AC checks:
  - `patches/react-native-callkeep+4.3.16.patch` ✓ exists
  - `patches/expo-image+2.3.2.patch` ✓ absent
  - `patches/react-native+0.79.4.patch` ✓ absent
  - `patches/react-native+0.81.5.patch` ✓ exists
- Gates:
  - `yarn install` exit 0
  - `npx patch-package` (via postinstall): 14/14 applied, zero "Hunk failed"
  - `yarn lint` exit 0 (176 warnings, 0 errors after adapt fixes)
  - `yarn test` exit 0 (128 suites, 1027 tests, 317 snapshots after regen)
  - `grep -rE "^<<<<<<< "` → 0
- **Adapt commit `4dbc1185b`**: `adapt: RN 81 + Expo 54 render-tree churn and type tightening (#6875)` — 200 snapshots updated + 8 obsolete removed across 26 suites; 2 TS tightening fixes (`ForwardMessageView` dead `?? true`, `RoomView` @ts-ignore for screen name generic); `jest.setup.js` eslint --fix; `yarn.lock` reconciled for VoIP-only deps.
- Commit count: `git log feat.voip-lib-new..HEAD --oneline | wc -l` == 7 (4 cherry-picks + 3 adapts)

## SHA mapping table (cherry-picks 2a–2d)

| # | Source (origin/develop) | Applied (merge branch) | PR | Purpose |
|---|---|---|---|---|
| 2a | `09ec94dac` | `79a987603` | #6974 | iOS 26 deployment target |
| 2b | `ec27a7c4c` | `4eba633eb` | #6970 | Migrate to react-native-true-sheet |
| 2c | `75d866b88` | `d8a2c8f06` | #6720 | Upgrade reanimated to v4 |
| 2d | `91b223410` | `d8b48adba` | #6875 | Upgrade to RN 81 + Expo 54 |

## Slice 7 — Bulk merge + per-file recipes + Kotlin compile gate

- **Started:** 2026-04-08
- `git merge origin/develop --no-ff --no-commit` → 23 conflicts
- Merge base: `58e91f1b7` (feat.voip-lib-new tip = `4dbc1185b` after slice 6)
- **NOT YET COMMITTED** — Slice 8 (`NotificationIntentHandler.kt` sanity pause) must run first.

### Per-file resolutions

| File | Strategy | Notes |
|---|---|---|
| `package.json` | manual union — take theirs, splice VoIP-only deps | Re-added `react-native-platform-touchable`, `react-native-slowlog`, `@types/react-native-platform-touchable`, `react-native-incall-manager`, `react-native-prompt-android`, `react-native-webrtc`, `@rocket.chat/media-signaling` (already present), `zustand` (already present). devDeps: `eslint-plugin-jsx-a11y`, `lint-staged`. |
| `yarn.lock` | `git checkout MERGE_HEAD -- yarn.lock` + `yarn install` reconcile | Recipe from slice 5/6. Develop lock became base; yarn install added VoIP-only entries. 14/14 patches applied clean. Develop bumped patch targets: `@rocket.chat/message-parser+0.31.32`, `expo-file-system+19.0.21`, `react-native-webview+13.16.1`. |
| `jest.setup.js` | manual — take theirs style on 3 formatting conflicts, preserve VoIP mocks | Conflicts were pure prettier body-style (arrow concise vs braced + parens). VoIP mocks `react-native-incall-manager` + `expo-haptics` (object form with `ImpactFeedbackStyle`) preserved from slice 4 adapt. |
| `android/app/src/main/java/chat/rocket/reactnative/MainApplication.kt` | union — keep both imports + both `add()` calls | VoIP's `VoipTurboPackage` + develop's `InvertedScrollPackage`. Class body auto-merged cleanly (only the import block needed manual resolution). |
| `android/app/build.gradle` | union — keep both deps | `testImplementation 'junit:junit:4.13.2'` (VoIP) + `implementation 'androidx.lifecycle:lifecycle-process:2.8.7'` (develop). |
| `app/sagas/login.js` | manual — base ours (VoIP), layer develop's new logic | Kept VoIP's `disconnect` import (develop's unused `connect` import dropped). Added develop's `setUserPresenceAway` restApi import, `checkBackgroundAndSetAway` function, and `yield fork(checkBackgroundAndSetAway)` call. VoIP's `startVoipFork`, `getUserPresence(user.id)`, and removal of `fetchEnterpriseModulesFork` preserved. |
| `app/containers/message/Touch.tsx` | re-deleted (`git rm -f`) | VoIP intentionally removed this file; merge re-added it from develop. Re-deleted since VoIP code no longer references it (0 importers). |
| `app/containers/InAppNotification/NotifierComponent.{test.tsx,stories.tsx}` + snapshot | re-deleted (`git rm -f`) | VoIP removed the component; merge re-added test/stories from develop. Test file has no component to target. |
| `app/containers/CustomIcon/selection.json`, `ios/custom.ttf`, `android/app/src/main/assets/fonts/custom.ttf` | `--theirs` | VoIP didn't touch icon font assets (empty log); take develop's bump. |
| 15 non-VoIP snapshots (Avatar, DirectoryItem, List, LoginServices, RoomItem, ServerItem, TextInput, UIKitMessage, UIKitModal, Message, DiscussionsView/Item, ServersHistoryItem, LoadMore, ThreadMessagesView/Item) | `--theirs` then regenerate per-file | All 15 failures were pure theme color diffs (`#E4E7EA` → `#C1C7D0`). No logic changes. |
| 9 regenerated snaps after install (Avatar, List, InAppNotification/NotifierComponent, CallView/index, DiscussionsView/Item, ThreadMessagesView/Item, RoomItem, UIKit/UiKitMessage, LoadMore) | `yarn jest -u <explicit paths>` | 15 snapshots updated across 9 suites. CallView/index is VoIP-touched — its snapshot matches VoIP's current component output. No blanket `-u`. |

### Post-merge eslint --fix

`yarn eslint . --fix` cleared 7 autofixable prettier errors (`(error)` → `error` arrow-paren rule) across index.js + sagas/login.js + sagas/deepLinking.js. 0 errors, 172 warnings remain (same warning surface as post-slice-6).

### Gates

- `grep -rE "^<<<<<<< " -- android/app/src/main app android ios` → 0 ✓
- `yarn install` exit 0; 14/14 patches applied clean
- `yarn lint` exit 0 (0 errors, 172 warnings)
- `yarn test` exit 0 (129 suites, 1056 tests, 331 snapshots)
- **`cd android && ./gradlew compileDebugKotlin` BUILD SUCCESSFUL** in 1m 29s (340 tasks; only warnings were from `react-native-screens` upstream, none from VoIP code) ✓
- `grep VoipTurboPackage android/app/src/main/java/chat/rocket/reactnative/MainApplication.kt` → 2 ✓
- `grep media-signaling android/app/build.gradle` → 0 (VoIP's baseline build.gradle also had 0; media-signaling is autolinked from package.json `file:./packages/rocket.chat-media-signaling-0.1.3.tgz`, not declared in build.gradle). **Plan AC line is informational only for this repo.**
- `packages/rocket.chat-media-signaling-0.1.3.tgz` present ✓ (not a conflict)
- `NotificationIntentHandler.kt` auto-merged cleanly (no conflict markers); `grep VoipNotification` == 2. Slice 8 code-reviewer sanity pause still required.

## Slice 8 — NotificationIntentHandler.kt sanity pause

- **Started:** 2026-04-08
- The file auto-merged cleanly during Slice 7's `git merge origin/develop --no-ff` (no conflict markers).
- Sanity-pause review performed via the `oh-my-claudecode:code-reviewer` subagent on the resolved file, with explicit instruction to verify the three VoIP invariants (VoipPayload parsing, MediaCallEvents emissions, no VoIP branch dropped).

### Resolved diff vs HEAD (VoIP baseline)

```diff
@@ -98,6 +98,20 @@ class NotificationIntentHandler {
             }

             try {
+                val notId = extras.getString("notId")
+
+                // Clear the notification messages from the static map to prevent stacking
+                if (!notId.isNullOrEmpty()) {
+                    try {
+                        val notIdInt = notId.toIntOrNull()
+                        if (notIdInt != null) {
+                            CustomPushNotification.clearMessages(notIdInt)
+                        }
+                    } catch (e: Exception) {
+                        Log.e(TAG, "Error clearing notification messages for ID $notId: ${e.message}", e)
+                    }
+                }
+
                 // Extract all notification data from Intent extras
                 // Only include serializable types to avoid JSON serialization errors
                 val notificationData = mutableMapOf<String, Any?>()
```

### NotificationIntentHandler.kt review

**Verdict: PASS**

**Invariant 1 — VoIP early-return intact (line 25-27)**
```kotlin
if (VoipNotification.handleMainActivityVoipIntent(context, intent)) {
    return
}
```
First statement in `handleIntent()`. If the intent is a VoIP payload, it is parsed into `VoipPayload`, handled, and control returns immediately. VoipPayload parsing path preserved.

**Invariant 2 — `clearMessages` block positioned on non-VoIP path only**
The new block (lines 101-113) lives inside `handleNotificationIntent()` (private method, line 91), which is only reached via line 35 — AFTER both the VoIP early-return (line 25) and the videoconf early-return (line 30). A VoIP intent cannot reach `CustomPushNotification.clearMessages()`. The block additionally sits inside the `ejson`-guard (line 96), so it only runs for real push notifications with payload data.

**Invariant 3 — `caller` key rename preserved (line 53, 69-72)**
VoIP branch's `callerName` → `caller` rename survived the merge in the videoconf handler. No regression to the old key.

**MediaCallEvents code paths** — `MediaCallEvents` is not referenced in this file directly; emissions happen inside `VoipNotification.handleMainActivityVoipIntent()`, called unchanged at line 25. No VoIP branch was dropped.

**No VoIP branch dropped** — three-branch dispatch structure (VoIP → VideoConf → Regular Notification) fully intact at lines 25-35.

**Merge semantics summary** — The `origin/develop` addition (`notId`/`clearMessages` cleanup) was semantically independent from VoIP's additions (early-return + `caller` key rename). Auto-merge placed the develop-side change inside `handleNotificationIntent()` — the correct non-VoIP, non-videoconf code path — and left both VoIP modifications untouched. All three invariants hold. Slice 8 merge is safe to keep.

### Invariants verified manually after subagent review

- [x] VoIP push payloads still parsed into `VoipPayload` (via `VoipNotification.handleMainActivityVoipIntent` at line 25)
- [x] `MediaCallEvents` emissions still fire on same paths (indirectly via `VoipNotification`, unchanged call site)
- [x] No VoIP-specific branch dropped (three-branch dispatch intact)
- VoipModule.mm: update import from <RocketChatSpecs/RocketChatSpecs.h>
  to <SSLPinning/SSLPinning.h> — RN 0.81 codegen bundles custom specs
  under the SSLPinning umbrella header (old name from prior RN version)
- app/containers/message/Touch.tsx: restore from origin/develop (was
  incorrectly deleted in Slice 7 as a VoIP-intentional deletion; the
  merged Message.tsx uses develop's ./Touch import, not the old
  react-native-platform-touchable path)
RN 0.81 codegen places NativeVoipSpec in package
chat.rocket.reactnative.networking (not chat.rocket.reactnative).
Update import in VoipModule.kt and VoipTurboPackage.kt.
- patches/react-native-config-reader+4.1.1.patch: hand-authored patch
  (patch-package CLI broken on yarn 1.22) — changes ios/**/* glob to
  ios/*.{h,m} in RNConfigReader.podspec to fix xcodebuild exit 65
- ios/Podfile.lock: RNConfigReader checksum updated to reflect patched podspec
- ios/RocketChatRN.xcodeproj/project.pbxproj: Xcode first-build
  auto-updates: Expo configure-project input/output paths, RNCAsyncStorage
  resources bundle in copy phase, quoted $TARGET_BUILD_DIR in Bugsnag script
@coderabbitai

coderabbitai Bot commented Apr 8, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Too many files!

This PR contains 254 files, which is 104 over the limit of 150.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: bd2a8e7c-fcb7-4b19-9cd8-59a9488b499e

📥 Commits

Reviewing files that changed from the base of the PR and between e05a7aa and e45d8d8.

⛔ Files ignored due to path filters (40)
  • android/app/src/main/assets/fonts/custom.ttf is excluded by !**/*.ttf
  • android/gradle/wrapper/gradle-wrapper.jar is excluded by !**/*.jar
  • 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/Chip/__snapshots__/Chip.test.tsx.snap is excluded by !**/*.snap
  • app/containers/DirectoryItem/__snapshots__/DirectoryItem.test.tsx.snap is excluded by !**/*.snap
  • app/containers/Header/components/HeaderButton/__snapshots__/HeaderButtons.test.tsx.snap is excluded by !**/*.snap
  • app/containers/List/__snapshots__/List.test.tsx.snap is excluded by !**/*.snap
  • app/containers/LoginServices/__snapshots__/LoginServices.test.tsx.snap is excluded by !**/*.snap
  • app/containers/MediaCallHeader/__snapshots__/MediaCallHeader.test.tsx.snap is excluded by !**/*.snap
  • app/containers/MessageComposer/__snapshots__/MessageComposer.test.tsx.snap is excluded by !**/*.snap
  • app/containers/NewMediaCall/__snapshots__/FilterHeader.test.tsx.snap is excluded by !**/*.snap
  • app/containers/NewMediaCall/__snapshots__/PeerItem.test.tsx.snap is excluded by !**/*.snap
  • app/containers/NewMediaCall/__snapshots__/PeerList.test.tsx.snap is excluded by !**/*.snap
  • app/containers/NewMediaCall/__snapshots__/SelectedPeer.test.tsx.snap is excluded by !**/*.snap
  • app/containers/ReactionsList/__snapshots__/ReactionsList.test.tsx.snap is excluded by !**/*.snap
  • app/containers/RoomHeader/__snapshots__/RoomHeader.test.tsx.snap is excluded by !**/*.snap
  • app/containers/RoomItem/__snapshots__/RoomItem.test.tsx.snap is excluded by !**/*.snap
  • app/containers/SearchBox/__snapshots__/SearchBox.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/markdown/__snapshots__/Markdown.test.tsx.snap is excluded by !**/*.snap
  • app/containers/message/__snapshots__/Message.test.tsx.snap is excluded by !**/*.snap
  • app/views/CallView/__snapshots__/index.test.tsx.snap is excluded by !**/*.snap
  • app/views/CallView/components/Dialpad/__snapshots__/Dialpad.test.tsx.snap is excluded by !**/*.snap
  • app/views/CallView/components/__snapshots__/CallActionButton.test.tsx.snap is excluded by !**/*.snap
  • app/views/CallView/components/__snapshots__/CallerInfo.test.tsx.snap is excluded by !**/*.snap
  • app/views/CannedResponsesListView/__snapshots__/CannedResponseItem.test.tsx.snap is excluded by !**/*.snap
  • app/views/CreateChannelView/RoomSettings/__snapshots__/SwitchItem.test.tsx.snap is excluded by !**/*.snap
  • app/views/DiscussionsView/__snapshots__/Item.test.tsx.snap is excluded by !**/*.snap
  • app/views/NewMessageView/__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/RoomInfoView/components/__snapshots__/RoomInfoButtons.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
  • ios/Podfile.lock is excluded by !**/*.lock
  • ios/custom.ttf is excluded by !**/*.ttf
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (254)
  • .eslintignore
  • .eslintrc.js
  • .github/actions/build-ios/action.yml
  • .github/actions/upload-android/action.yml
  • .github/actions/upload-ios/action.yml
  • .github/scripts/prepare-changelog.js
  • .github/workflows/build-develop.yml
  • .github/workflows/build-ios.yml
  • .github/workflows/build-official-android.yml
  • .github/workflows/build-official-ios.yml
  • .github/workflows/e2e-build-ios.yml
  • .github/workflows/generate-changelog.yml
  • .github/workflows/maestro-android.yml
  • .github/workflows/maestro-ios.yml
  • .maestro/helpers/create-account.yaml
  • .maestro/helpers/login-with-deeplink.yaml
  • .maestro/helpers/search-room.yaml
  • .maestro/helpers/send-message.yaml
  • .maestro/scripts/data-setup.js
  • .maestro/tests/accessibilityAndAppearance/ToastsAndDialogs.yml
  • .maestro/tests/assorted/broadcast.yaml
  • .maestro/tests/assorted/change-avatar.yaml
  • .maestro/tests/assorted/join-from-directory.yaml
  • .maestro/tests/assorted/profile.yaml
  • .maestro/tests/e2ee/flows/create-e2ee-room.yaml
  • .maestro/tests/e2ee/utils/change-e2ee-key.yaml
  • .maestro/tests/onboarding/change-password.yaml
  • .maestro/tests/onboarding/login/invalid-credentials.yaml
  • .maestro/tests/onboarding/login/login.yaml
  • .maestro/tests/onboarding/register/create-account.yaml
  • .maestro/tests/room/create-room.yaml
  • .maestro/tests/room/ignoreuser.yaml
  • .maestro/tests/room/jump-to-message.yaml
  • .maestro/tests/room/message-markdown-click.yaml
  • .maestro/tests/room/room-actions.yaml
  • .maestro/tests/room/room-info.yaml
  • .maestro/tests/room/room.yaml
  • .maestro/tests/room/search-member.yaml
  • .maestro/tests/room/share-message.yaml
  • .maestro/tests/teams/team.yaml
  • .maestro/tests/teams/utils/close-action-sheet.yaml
  • .maestro/tests/teams/utils/create-channel.yaml
  • .maestro/tests/teams/utils/open-action-sheet.yaml
  • AGENTS.md
  • CLAUDE.md
  • MERGE_NOTES.md
  • UBIQUITOUS_LANGUAGE.md
  • __mocks__/react-native-mmkv.js
  • android/app/build.gradle
  • android/app/src/debug/AndroidManifest.xml
  • android/app/src/main/AndroidManifest.xml
  • android/app/src/main/java/chat/rocket/reactnative/MainApplication.kt
  • android/app/src/main/java/chat/rocket/reactnative/networking/SSLPinningTurboModule.java
  • android/app/src/main/java/chat/rocket/reactnative/notification/CustomPushNotification.java
  • android/app/src/main/java/chat/rocket/reactnative/notification/NotificationIntentHandler.kt
  • android/app/src/main/java/chat/rocket/reactnative/scroll/InvertedScrollContentView.java
  • android/app/src/main/java/chat/rocket/reactnative/scroll/InvertedScrollContentViewManager.java
  • android/app/src/main/java/chat/rocket/reactnative/scroll/InvertedScrollPackage.java
  • android/app/src/main/java/chat/rocket/reactnative/scroll/InvertedScrollView.java
  • android/app/src/main/java/chat/rocket/reactnative/scroll/InvertedScrollViewManager.java
  • android/app/src/main/java/chat/rocket/reactnative/voip/VoipModule.kt
  • android/app/src/main/java/chat/rocket/reactnative/voip/VoipTurboPackage.kt
  • android/build.gradle
  • android/fastlane/Fastfile
  • android/gradle.properties
  • android/gradle/wrapper/gradle-wrapper.properties
  • android/gradlew
  • android/gradlew.bat
  • app/actions/room.ts
  • app/containers/ActionSheet/ActionSheet.tsx
  • app/containers/ActionSheet/ActionSheetContentWithInputAndSubmit/index.tsx
  • app/containers/ActionSheet/BottomSheetContent.tsx
  • app/containers/ActionSheet/Handle.tsx
  • app/containers/ActionSheet/Provider.tsx
  • app/containers/ActionSheet/styles.ts
  • app/containers/ActionSheet/useActionSheetDetents.test.tsx
  • app/containers/ActionSheet/useActionSheetDetents.ts
  • app/containers/AudioPlayer/Seek.tsx
  • app/containers/Avatar/Avatar.stories.tsx
  • app/containers/Avatar/Avatar.tsx
  • app/containers/Avatar/AvatarContainer.tsx
  • app/containers/Avatar/AvatarWithEdit.tsx
  • app/containers/Button/Button.test.tsx
  • app/containers/Button/index.tsx
  • app/containers/CallHeader.tsx
  • app/containers/Chip/index.tsx
  • app/containers/CustomIcon/selection.json
  • app/containers/EmojiPicker/EmojiCategory.tsx
  • app/containers/EmojiPicker/EmojiSearch.tsx
  • app/containers/EmojiPicker/PressableEmoji.tsx
  • app/containers/EmojiPicker/index.tsx
  • app/containers/EmojiPicker/interfaces.ts
  • app/containers/Header/components/HeaderButton/HeaderButtonContainer.tsx
  • app/containers/InAppNotification/IncomingCallNotification/index.tsx
  • app/containers/InAppNotification/NotifierComponent.tsx
  • app/containers/List/ListContainer.tsx
  • app/containers/List/ListItem.tsx
  • app/containers/List/ListRadio.tsx
  • app/containers/MessageActions/index.tsx
  • app/containers/MessageComposer/components/Autocomplete/Autocomplete.tsx
  • app/containers/MessageComposer/components/Buttons/ActionsButton.tsx
  • app/containers/MessageComposer/components/ComposerInput.tsx
  • app/containers/MessageComposer/components/Quotes/Quote.tsx
  • app/containers/MessageComposer/components/RecordAudio/RecordAudio.tsx
  • app/containers/MessageComposer/components/RecordAudio/ReviewButton.tsx
  • app/containers/MessageComposer/helpers/getMentionRegexp.test.js
  • app/containers/MessageComposer/hooks/useEmojiKeyboard.tsx
  • app/containers/NewMediaCall/Container.stories.tsx
  • app/containers/NewMediaCall/FilterHeader.stories.tsx
  • app/containers/NewMediaCall/NewMediaCall.stories.tsx
  • app/containers/RoomHeader/RoomHeader.tsx
  • app/containers/RoomHeader/index.tsx
  • app/containers/RoomItem/Actions.tsx
  • app/containers/RoomItem/Touchable.tsx
  • app/containers/RoomItem/interfaces.ts
  • app/containers/ServerItem/SwipeableDeleteItem/Actions.tsx
  • app/containers/ServerItem/SwipeableDeleteItem/Touchable.tsx
  • app/containers/SupportedVersions/styles.ts
  • app/containers/TextInput/FormTextInput.tsx
  • app/containers/ThreadDetails.tsx
  • app/containers/Touch.tsx
  • app/containers/TwoFactor/index.tsx
  • app/containers/TwoFactor/styles.ts
  • app/containers/UIKit/DatePicker.tsx
  • app/containers/UIKit/MessageBlock.tsx
  • app/containers/UIKit/MultiSelect/Chips.tsx
  • app/containers/UIKit/MultiSelect/Input.tsx
  • app/containers/UIKit/MultiSelect/Items.tsx
  • app/containers/UIKit/MultiSelect/MultiSelectContent.tsx
  • app/containers/UIKit/MultiSelect/styles.ts
  • app/containers/UIKit/Overflow.tsx
  • app/containers/UIKit/UiKitModal.stories.tsx
  • app/containers/UIKit/VideoConferenceBlock/components/VideoConferenceEnded.tsx
  • app/containers/UIKit/VideoConferenceBlock/components/VideoConferenceOutgoing.tsx
  • app/containers/UnreadBadge/getUnreadStyle.test.js
  • app/containers/markdown/components/Katex.tsx
  • app/containers/markdown/components/Preview.tsx
  • app/containers/markdown/components/Timestamp.tsx
  • app/containers/markdown/components/emoji/Emoji.tsx
  • app/containers/markdown/components/inline/Link.tsx
  • app/containers/message/Broadcast.tsx
  • app/containers/message/CallButton.tsx
  • app/containers/message/Components/Attachments/Attachments.tsx
  • app/containers/message/Components/Attachments/CollapsibleQuote/index.tsx
  • app/containers/message/Components/Attachments/Image/Button.tsx
  • app/containers/message/Components/Attachments/Image/Image.tsx
  • app/containers/message/Components/Attachments/Quote.tsx
  • app/containers/message/Components/Attachments/Reply.tsx
  • app/containers/message/Components/Attachments/Video.tsx
  • app/containers/message/Discussion.tsx
  • app/containers/message/Message.stories.tsx
  • app/containers/message/Message.tsx
  • app/containers/message/Reactions.tsx
  • app/containers/message/Time.tsx
  • app/containers/message/Touch.tsx
  • app/containers/message/Touchable.tsx
  • app/containers/message/Urls.tsx
  • app/containers/message/User.tsx
  • app/definitions/rest/v1/omnichannel.ts
  • app/definitions/rest/v1/users.ts
  • app/ee/omnichannel/lib/index.ts
  • app/ee/omnichannel/views/QueueListView.tsx
  • app/i18n/locales/en.json
  • app/i18n/locales/hi-IN.json
  • app/i18n/locales/pt-BR.json
  • app/i18n/locales/ta-IN.json
  • app/i18n/locales/te-IN.json
  • app/lib/database/utils.test.ts
  • app/lib/encryption/encryption.ts
  • app/lib/encryption/helpers/base64-js/index.ts
  • app/lib/encryption/room.ts
  • app/lib/helpers/formatText.ts
  • app/lib/hooks/useShortnameToUnicode/index.tsx
  • app/lib/hooks/useVideoConf/StartACallActionSheet.tsx
  • app/lib/hooks/useVideoConf/index.tsx
  • app/lib/methods/handleMediaDownload.ts
  • app/lib/methods/helpers/fileDownload.ts
  • app/lib/methods/helpers/fileUpload/Upload.android.ts
  • app/lib/methods/helpers/getAvatarUrl.test.ts
  • app/lib/methods/helpers/getAvatarUrl.ts
  • app/lib/methods/helpers/openLink.ts
  • app/lib/methods/helpers/sslPinning.ts
  • app/lib/methods/loadMessagesForRoom.ts
  • app/lib/methods/search.ts
  • app/lib/methods/sendFileMessage/utils.ts
  • app/lib/methods/serializeAsciiUrl.test.ts
  • app/lib/services/restApi.ts
  • app/sagas/createChannel.js
  • app/sagas/createDiscussion.js
  • app/sagas/deepLinking.js
  • app/sagas/login.js
  • app/sagas/room.js
  • app/sagas/rooms.js
  • app/sagas/state.js
  • app/stacks/MasterDetailStack/index.tsx
  • app/views/AttachmentView.tsx
  • app/views/CannedResponsesListView/CannedResponseItem.tsx
  • app/views/ChangePasscodeView.tsx
  • app/views/CreateChannelView/RoomSettings/SwitchItemEncrypted.test.tsx
  • app/views/CreateDiscussionView/index.tsx
  • app/views/DefaultBrowserView/index.tsx
  • app/views/DirectoryView/Options.tsx
  • app/views/DirectoryView/index.tsx
  • app/views/DiscussionsView/DiscussionDetails.tsx
  • app/views/DiscussionsView/Item.tsx
  • app/views/ForwardMessageView/index.tsx
  • app/views/JitsiMeetView/JitsiAuthModal.tsx
  • app/views/ModalBlockView.tsx
  • app/views/ProfileView/components/ConfirmEmailChangeActionSheetContent/index.tsx
  • app/views/ProfileView/components/DeleteAccountActionSheetContent/index.tsx
  • app/views/ReportUserView/index.tsx
  • app/views/RoomInfoEditView/index.tsx
  • app/views/RoomMembersView/index.tsx
  • app/views/RoomView/Banner.tsx
  • app/views/RoomView/JoinCode.tsx
  • app/views/RoomView/LeftButtons.tsx
  • app/views/RoomView/List/components/InvertedScrollView.tsx
  • app/views/RoomView/List/components/List.tsx
  • app/views/RoomView/ReactionPicker.tsx
  • app/views/RoomView/index.tsx
  • app/views/RoomsListView/components/Header.tsx
  • app/views/RoomsListView/components/ServersList.tsx
  • app/views/ScreenLockedView.tsx
  • app/views/SecurityPrivacyView.tsx
  • app/views/SelectServerView.tsx
  • app/views/ShareListView/index.tsx
  • app/views/ShareView/Thumbs.tsx
  • app/views/TeamChannelsView.tsx
  • app/views/ThreadMessagesView/Item.tsx
  • app/views/UserNotificationPreferencesView/index.tsx
  • app/views/UserPreferencesView/index.tsx
  • babel.config.js
  • index.js
  • ios/Libraries/VoipModule.mm
  • ios/NotificationService/Info.plist
  • ios/RocketChatRN.xcodeproj/project.pbxproj
  • ios/RocketChatRN/Info.plist
  • ios/ShareRocketChatRN/Info.plist
  • ios/fastlane/Fastfile
  • jest.config.js
  • jest.setup.js
  • metro.config.js
  • package.json
  • patches/@discord+bottom-sheet+4.6.1.patch
  • patches/@lodev09+react-native-true-sheet+3.7.3.patch
  • patches/@rocket.chat+message-parser+0.31.32.patch
  • patches/expo-file-system+19.0.21.patch
  • patches/expo-image+2.3.2.patch
  • patches/react-native+0.81.5.patch
  • patches/react-native-config-reader+4.1.1.patch
  • patches/react-native-webview+13.16.1.patch
  • scripts/build-icon-set.js
  • scripts/create-avd.sh
  • tsconfig.json

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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.

@diegolmello diegolmello changed the title merge: develop into feat.voip-lib-new (RN 81 + Expo 54 + reanimated 4 + true-sheet + iOS 26) chore: develop into feat.voip-lib-new (RN 81 + Expo 54 + reanimated 4 + true-sheet + iOS 26) Apr 8, 2026
…velop-into-voip-lib-new

# Conflicts:
#	app/containers/NewMediaCall/__snapshots__/FilterHeader.test.tsx.snap
#	app/views/CallView/components/Dialpad/Dialpad.tsx
#	app/views/CallView/components/Dialpad/__snapshots__/Dialpad.test.tsx.snap
#	yarn.lock
Fix TypeScript error when passing useAnimatedStyle() return value to
Autocomplete component's style prop.
@diegolmello
diegolmello force-pushed the merge/develop-into-voip-lib-new branch from 0b97054 to e45d8d8 Compare April 9, 2026 16:29
@diegolmello
diegolmello had a problem deploying to approve_e2e_testing April 9, 2026 16:29 — with GitHub Actions Failure
@diegolmello
diegolmello had a problem deploying to experimental_android_build April 9, 2026 16:34 — with GitHub Actions Failure
@diegolmello
diegolmello had a problem deploying to official_android_build April 9, 2026 16:34 — with GitHub Actions Failure
@diegolmello
diegolmello had a problem deploying to experimental_ios_build April 9, 2026 16:34 — with GitHub Actions Failure
@diegolmello
diegolmello merged commit c6089b1 into feat.voip-lib-new Apr 9, 2026
3 of 10 checks passed
@diegolmello
diegolmello deleted the merge/develop-into-voip-lib-new branch April 9, 2026 16:47
diegolmello added a commit that referenced this pull request Apr 22, 2026
…/Decline (#7215)

* merge feat.voip-lib

* feat(voip): enhance call handling with UUID mapping and event listeners

* Base call UI

* feat(voip): integrate Zustand for call state management and enhance CallView UI

* feat(voip): add simulateCall function for mock call handling in UI development

* refactor(CallView): update button handlers and improve UI responsiveness

* Add pause-shape-unfilled icon

* Base CallHeader

* toggleFocus

* collapse buttons

* Header components

* Hide header when no call

* Timer

* Add use memo

* Add voice call item on sidebar

* cleanup

* Temp use @rocket.chat/media-signaling from .tgz

* cleanup

* Check module and permissions to enable voip

* Refactor stop method to use optional chaining for media signal listeners

* voip push first test

* Add VoIP call handling with pending call management

- Implemented VoIP push notification handling in index.js, including storing call info for later processing.
- Added CallKeep event handlers for answering and ending calls from a cold start.
- Introduced a new CallIdUUID module to convert call IDs to deterministic UUIDs for compatibility with CallKit.
- Created a pending call store to manage incoming calls when the app is not fully initialized.
- Updated deep linking actions to include VoIP call handling.
- Enhanced MediaSessionInstance to process pending calls and manage call states effectively.

* Remove pending store and create getInitialEvents on app/index

* Attempt to make iOS calls work from cold state

* lint and format

* Patch callkeep ios

* Temp send iOS voip push token on gcm

* Temp fix require cycle

* chore: format code and fix lint issues [skip ci]

* CallIDUUID module on android and voip push

* Add setCallUUID on useCallStore to persist calls accepted on native Android

* remove callkeep from notification

* Android Incoming Call UI POC

* Refactor VoIP handling: Migrate VoIP-related classes to a new package structure, removing deprecated modules and consolidating functionality. Update imports in MainApplication and NotificationIntentHandler to reflect changes. This cleanup enhances code organization and prepares for future VoIP feature enhancements.

* Remove VoipForegroundService

* cleanup and use caller instead of callerName

* Cleanup and make iOS build again

* Refactor VoIP handling: Remove unused event emissions for call answered and declined, switch from SharedPreferences to in-memory storage for pending VoIP call data, and update method signatures for better clarity. This cleanup enhances performance and prepares for future VoIP feature improvements.

* Refactor VoIP handling: Introduce a new VoipPayload class to encapsulate call data, streamline notification processing, and enhance method signatures across the VoIP module. This update improves code clarity and prepares for future feature enhancements.

* Migrate react-native-voip-push-notifications to VoipModule

* Refactor VoIP module: Update package structure by moving VoipTurboPackage to the main package and removing the obsolete NativeVoipSpec class. Adjust imports in MainApplication and VoipModule to reflect these changes, enhancing code organization and maintainability.

* Unify emitters

* Move CallKeep listeners from MediaSessionInstance to getInitialEvents

* Clear callkeep on endcall

* Unify getInitialEvents logic

* getInitialEvents -> MediaCallEvents

* chore: format code and fix lint issues [skip ci]

* feat(Android): Add full screen incoming call (#6977)

* feat: Update call UI (#6990)

* feat: Handle audio routing, e.g., Bluetooth headset vs. internal speaker switching (#6992)

* fix: empty space when not on call (#6993)

* feat: Dialpad (#7000)

* action: organized translations

* feat: start call (#7024)

* chore: format code and fix lint issues

* feat: Pre flight (#7038)

* action: organized translations

* feat: Receive voip push notifications from backend (#7045)

* feat: Refactor media session handling and improve disconnect logic (#7065)

* feat: Control incoming call from native (#7066)

* feat: Voice message blocks (#7057)

* feat: native accept success event (#7068)

* feat(voip): call waiting, busy detection, and videoconf blocking (#7077)

* action: organized translations

* feat(voip): tap-to-hide call controls with animations (#7078)

* feat(voip): navigate to call DM from message button and header (#7082)

* feat(voip): tablet and landscape layout (#7110)

* chore: develop into feat.voip-lib-new (RN 81 + Expo 54 + reanimated 4 + true-sheet + iOS 26) (#7114)

* chore: format code and fix lint issues

* feat(voip): android landscape layout for IncomingCallActivity (#7116)

* Update agents files

* feat(voip): Support a11y (#7106)

* Fix content cutting on iOS on some edge cases

* pods

* Ignore .worktrees on jest

* chore: Merge develop into feat.voip-lib-new (#7129)

* fix(voip): show CallKit UI when call is active in background (#7128)

* chore: Update media-signaling to 0.2.0 (#7153)

* feat(voip): migrate iOS accept/reject from DDP to REST (#7124)

* Fix icons

* feat(voip): migrate Android accept/reject from DDP to REST (#7127)

* test(voip): integration tests for CallView pipeline (#7161)

* feat(voip): display video conf provider as subtitle (#7160)

* fix(voip): CallView button grid and correct landscape/dialpad layouts (#7164)

* fix(voip): prevent stale MMKV cache on Android first-install accept

MMKVKeyManager.initialize ran in MainApplication.onCreate before the JS
engine started and opened the default MMKV file via the Tencent 1.2 JAR
when it was still empty. Tencent caches instances per-ID in a singleton
registry, so that empty-state view was held for the rest of the process.
JS later wrote credentials through react-native-mmkv (MMKV Core 2.0),
which has its own separate registry. When a VoIP push arrived,
Ejson.getMMKV() got the cached empty Tencent instance and reported
"No userId found in MMKV for server". Closing and reopening the app
cleared the cache, which is why only the very first call after install
failed.

Drop the open/verify block — the encryption key is already cached from
SecureKeystore, so no MMKV handle is needed here. The first Tencent
instance is now created inside Ejson.getMMKV() after JS has written,
so it scans the file fresh.

* fix(voip): prevent duplicate ringtone on Android incoming call (#7158)

* fix(voip): set explicit snaps for NewMediaCall bottom sheet (#7165)

* Update app/lib/services/voip/MediaSessionStore.ts

Co-authored-by: Pierre Lehnen <55164754+pierre-lehnen-rc@users.noreply.github.com>

* fix: make startVoipFork reactive to permissions-changed (#7151)

* fix(android): remove MediaProjectionService from merged manifest (#7190)

* fix(voip): Phone account creation (#7170)

* feat: add Enable Mobile Ringing toggle in user preferences (#7155)

* fix(voip): ship blockers for PushKit, licensing, outbound calls, push tokens (#7167)

* fix(android): Play Store mic discoverability, safer FCM logs, avatar auth via headers (#7171)

* fix(ios): serialize VoipService bridge statics (#7169)

* fix(voip): Android DDP thread safety and VoipPayload bundle parity (#7168)

* chore(voip): dead-code and hygiene sweep (#7174)

* refactor(voip): decouple navigateToCallRoom from Redux and backfill REST/connect tests (#7176)

* test(voip): tighten ringing endCall assertion and add VideoConf VoIP-lock saga coverage (#7177)

* fix(ios): harden VoIP DDP WebSocket client on receive failures and TLS (#7173)

* refactor(voip): MediaCallEvents Redux adapters and resetVoipState (#7178)

* refactor(voip): decouple peer autocomplete from Redux; simplify NewMediaCall (#7175)

* fix(ios): add NS_SWIFT_NAME to Challenge.runChallenge for Swift 6.2 compatibility

Swift 6.2 (Xcode 26.x / macos-26 runner) auto-renames the Objective-C
method runChallenge:didReceiveChallenge:completionHandler: to
run(_:didReceive:completionHandler:) when imported into Swift.

Add NS_SWIFT_NAME to explicitly pin the Swift import name, preventing
the compiler from applying its heuristics. This keeps the existing
Swift call site in DDPClient.swift working without changes.

* fix(ios): cancel old URLSession/webSocketTask before reconnecting in DDPClient.connect (#7197)

* fix(ios): add NSLock to nativeAcceptHandledCallIds and 10s REST timeout to handleNativeAccept (#7198)

* feat(android): create VoipCallService with FOREGROUND_SERVICE_MICROPHONE (#7199)

* fix(android): start VoipCallService on accept, stop on hangup/timeout, install end-call listener (#7200)

* fix(voip): enable DM nav for users with SIP extension (#7203)

* fix(android): handle null VoiceConnection in answerIncomingCall, notify JS (#7201)

* fix(voip): resolve closure capture ordering in handleNativeAccept (#7209)

* fix(android): integrate VoIP modules with SSL-pinned OkHttpClient (#7208)

* fix(push): gate id and voipToken behind server version checks, fix VideoConf caller extra (#7210)

* fix(voip): remove sensitive data from production logs (#7207)

* fix(android): remove isRunning guard + add double-tap guard on Accept/Decline

- VoipCallService: remove if (!isRunning) guard, call startForeground unconditionally
  (idempotent on Android, fixes Android 14+ foreground service requirement)
- IncomingCallActivity: add AtomicBoolean guard on handleAccept/handleDecline
  to prevent double-tap from triggering multiple service starts

---------

Co-authored-by: diegolmello <diegolmello@users.noreply.github.com>
Co-authored-by: Pierre Lehnen <55164754+pierre-lehnen-rc@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants