@stream-io/video-react-native-sdk 1.36.2 → 1.37.1-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/android/src/main/java/com/streamvideo/reactnative/StreamVideoReactNativeModule.kt +81 -0
  3. package/android/src/main/java/com/streamvideo/reactnative/recorder/AudioPipeline.kt +436 -0
  4. package/android/src/main/java/com/streamvideo/reactnative/recorder/EncoderConstants.kt +17 -0
  5. package/android/src/main/java/com/streamvideo/reactnative/recorder/PipelineHost.kt +36 -0
  6. package/android/src/main/java/com/streamvideo/reactnative/recorder/RecorderPlaybackSamplesSink.kt +60 -0
  7. package/android/src/main/java/com/streamvideo/reactnative/recorder/RecorderVideoSink.kt +31 -0
  8. package/android/src/main/java/com/streamvideo/reactnative/recorder/TracksRecorderManager.kt +329 -0
  9. package/android/src/main/java/com/streamvideo/reactnative/recorder/VideoPipeline.kt +472 -0
  10. package/dist/commonjs/hooks/index.js +11 -0
  11. package/dist/commonjs/hooks/index.js.map +1 -1
  12. package/dist/commonjs/hooks/useLoopbackRecording.js +243 -0
  13. package/dist/commonjs/hooks/useLoopbackRecording.js.map +1 -0
  14. package/dist/commonjs/utils/internal/callingx/callingx.js +18 -38
  15. package/dist/commonjs/utils/internal/callingx/callingx.js.map +1 -1
  16. package/dist/commonjs/utils/push/internal/ios.js +4 -3
  17. package/dist/commonjs/utils/push/internal/ios.js.map +1 -1
  18. package/dist/commonjs/version.js +1 -1
  19. package/dist/commonjs/version.js.map +1 -1
  20. package/dist/module/hooks/index.js +1 -0
  21. package/dist/module/hooks/index.js.map +1 -1
  22. package/dist/module/hooks/useLoopbackRecording.js +238 -0
  23. package/dist/module/hooks/useLoopbackRecording.js.map +1 -0
  24. package/dist/module/utils/internal/callingx/callingx.js +19 -39
  25. package/dist/module/utils/internal/callingx/callingx.js.map +1 -1
  26. package/dist/module/utils/push/internal/ios.js +4 -3
  27. package/dist/module/utils/push/internal/ios.js.map +1 -1
  28. package/dist/module/version.js +1 -1
  29. package/dist/module/version.js.map +1 -1
  30. package/dist/typescript/hooks/index.d.ts +1 -0
  31. package/dist/typescript/hooks/index.d.ts.map +1 -1
  32. package/dist/typescript/hooks/useLoopbackRecording.d.ts +85 -0
  33. package/dist/typescript/hooks/useLoopbackRecording.d.ts.map +1 -0
  34. package/dist/typescript/utils/internal/callingx/callingx.d.ts.map +1 -1
  35. package/dist/typescript/utils/push/internal/ios.d.ts.map +1 -1
  36. package/dist/typescript/version.d.ts +1 -1
  37. package/dist/typescript/version.d.ts.map +1 -1
  38. package/expo-config-plugin/dist/withAppDelegate.js +14 -177
  39. package/ios/RTCViewPip.swift +6 -6
  40. package/ios/RTCViewPipManager.swift +47 -10
  41. package/ios/StreamInCallManager.swift +2 -6
  42. package/ios/StreamVideoReactNative-Bridging-Header.h +2 -0
  43. package/ios/StreamVideoReactNative.h +5 -18
  44. package/ios/StreamVideoReactNative.m +83 -296
  45. package/ios/TracksRecorder/AudioPipeline.swift +270 -0
  46. package/ios/TracksRecorder/PipelineHost.swift +56 -0
  47. package/ios/TracksRecorder/RecorderAudioRenderTap.swift +154 -0
  48. package/ios/TracksRecorder/RecorderVideoSink.swift +137 -0
  49. package/ios/TracksRecorder/TracksRecorderManager.swift +327 -0
  50. package/ios/TracksRecorder/VideoPipeline.swift +297 -0
  51. package/package.json +8 -8
  52. package/src/hooks/index.ts +1 -0
  53. package/src/hooks/useLoopbackRecording.ts +438 -0
  54. package/src/utils/internal/callingx/callingx.ts +19 -44
  55. package/src/utils/push/internal/ios.ts +4 -3
  56. package/src/version.ts +1 -1
@@ -1,11 +1,7 @@
1
1
  "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
2
  Object.defineProperty(exports, "__esModule", { value: true });
6
3
  const config_plugins_1 = require("@expo/config-plugins");
7
4
  const codeMod_1 = require("@expo/config-plugins/build/ios/codeMod");
8
- const addNewLinesToAppDelegateObjc_1 = __importDefault(require("./common/addNewLinesToAppDelegateObjc"));
9
5
  const addToSwiftBridgingHeaderFile_1 = require("./common/addToSwiftBridgingHeaderFile");
10
6
  const withAppDelegate = (configuration, props) => {
11
7
  return (0, config_plugins_1.withAppDelegate)(configuration, (config) => {
@@ -22,13 +18,9 @@ const withAppDelegate = (configuration, props) => {
22
18
  }
23
19
  config.modResults.contents = addDidFinishLaunchingWithOptionsObjc(config.modResults.contents, props.iOSEnableMultitaskingCameraAccess, props.addNoiseCancellation);
24
20
  if (props?.ringing) {
25
- config.modResults.contents = (0, codeMod_1.addObjcImports)(config.modResults.contents, ['<PushKit/PushKit.h>', '"StreamVideoReactNative.h"']);
21
+ config.modResults.contents = (0, codeMod_1.addObjcImports)(config.modResults.contents, ['"StreamVideoReactNative.h"']);
26
22
  config.modResults.contents =
27
23
  addDidFinishLaunchingWithOptionsRingingObjc(config.modResults.contents);
28
- config.modResults.contents = addDidUpdatePushCredentialsObjc(config.modResults.contents);
29
- config.modResults.contents = addDidReceiveIncomingPushCallbackObjc(config.modResults.contents);
30
- config.modResults.contents =
31
- addDidReceiveIncomingVoIPPushMetadataCallbackObjc(config.modResults.contents);
32
24
  }
33
25
  return config;
34
26
  }
@@ -38,26 +30,6 @@ const withAppDelegate = (configuration, props) => {
38
30
  }
39
31
  else {
40
32
  try {
41
- if (props?.ringing) {
42
- // make it public class AppDelegate: ExpoAppDelegate, PKPushRegistryDelegate {
43
- const regex = /(class\s+AppDelegate[^{]*)(\s*\{)/;
44
- config.modResults.contents = config.modResults.contents.replace(regex, (match, declarationPart, openBrace) => {
45
- // Check if PKPushRegistryDelegate is already in the declaration part
46
- if (declarationPart.includes('PKPushRegistryDelegate')) {
47
- return match; // Already present, no change needed
48
- }
49
- const trimmedDecl = declarationPart.trimRight();
50
- // If the declaration already has a colon (superclass or other protocols)
51
- if (trimmedDecl.includes(':')) {
52
- return `${trimmedDecl}, PKPushRegistryDelegate${openBrace}`;
53
- }
54
- else {
55
- // No colon, so AppDelegate is the first thing to be listed after :
56
- // This means the class declaration was like "class AppDelegate {"
57
- return `${trimmedDecl}: PKPushRegistryDelegate${openBrace}`;
58
- }
59
- });
60
- }
61
33
  config.modResults.contents = (0, codeMod_1.addSwiftImports)(config.modResults.contents, ['WebRTC']);
62
34
  (0, addToSwiftBridgingHeaderFile_1.addToSwiftBridgingHeaderFile)(config.modRequest.projectRoot, (headerFileContents) => {
63
35
  headerFileContents = (0, codeMod_1.addObjcImports)(headerFileContents, [
@@ -72,13 +44,9 @@ const withAppDelegate = (configuration, props) => {
72
44
  }
73
45
  config.modResults.contents = addDidFinishLaunchingWithOptionsSwift(config.modResults.contents, props.iOSEnableMultitaskingCameraAccess, props.addNoiseCancellation);
74
46
  if (props?.ringing) {
75
- config.modResults.contents = (0, codeMod_1.addSwiftImports)(config.modResults.contents, ['PushKit', 'stream_video_react_native']);
47
+ config.modResults.contents = (0, codeMod_1.addSwiftImports)(config.modResults.contents, ['stream_video_react_native']);
76
48
  config.modResults.contents =
77
49
  addDidFinishLaunchingWithOptionsRingingSwift(config.modResults.contents);
78
- config.modResults.contents = addDidUpdatePushCredentialsSwift(config.modResults.contents);
79
- config.modResults.contents = addDidReceiveIncomingPushCallbackSwift(config.modResults.contents);
80
- config.modResults.contents =
81
- addDidReceiveIncomingVoIPPushMetadataCallbackSwift(config.modResults.contents);
82
50
  }
83
51
  return config;
84
52
  }
@@ -125,157 +93,26 @@ function addDidFinishLaunchingWithOptionsObjc(contents, iOSEnableMultitaskingCam
125
93
  }
126
94
  function addDidFinishLaunchingWithOptionsRingingSwift(contents) {
127
95
  const functionSelector = 'application(_:didFinishLaunchingWithOptions:)';
128
- // call the setup of voip push notification
129
96
  const voipSetupMethod = 'StreamVideoReactNative.voipRegistration()';
130
- if (!contents.includes(voipSetupMethod)) {
131
- contents = (0, codeMod_1.insertContentsInsideSwiftFunctionBlock)(contents, functionSelector, ' ' /* indentation */ + voipSetupMethod, { position: 'head' });
97
+ if (contents.includes(voipSetupMethod)) {
98
+ return contents;
132
99
  }
133
- return contents;
100
+ const updated = (0, codeMod_1.insertContentsInsideSwiftFunctionBlock)(contents, functionSelector, ' ' + voipSetupMethod, { position: 'head' });
101
+ if (!updated.includes(voipSetupMethod)) {
102
+ throw new Error(`Could not find ${functionSelector} in AppDelegate to inject ${voipSetupMethod}`);
103
+ }
104
+ return updated;
134
105
  }
135
106
  function addDidFinishLaunchingWithOptionsRingingObjc(contents) {
136
107
  const functionSelector = 'application:didFinishLaunchingWithOptions:';
137
- // call the setup of voip push notification
138
108
  const voipSetupMethod = '[StreamVideoReactNative voipRegistration];';
139
- if (!contents.includes(voipSetupMethod)) {
140
- contents = (0, codeMod_1.insertContentsInsideObjcFunctionBlock)(contents, functionSelector, voipSetupMethod, { position: 'head' });
141
- }
142
- return contents;
143
- }
144
- function addDidUpdatePushCredentialsSwift(contents) {
145
- const updatedPushCredentialsMethod = 'StreamVideoReactNative.didUpdate(credentials, forType: type.rawValue)';
146
- if (!contents.includes(updatedPushCredentialsMethod)) {
147
- const functionSelector = 'pushRegistry(_:didUpdate:for:)';
148
- const codeblock = (0, codeMod_1.findSwiftFunctionCodeBlock)(contents, functionSelector);
149
- if (!codeblock) {
150
- return (0, codeMod_1.insertContentsInsideSwiftClassBlock)(contents, 'class AppDelegate', `
151
- public func pushRegistry(
152
- _ registry: PKPushRegistry,
153
- didUpdate credentials: PKPushCredentials,
154
- for type: PKPushType
155
- ) {
156
- ${updatedPushCredentialsMethod}
157
- }
158
- `, { position: 'tail' });
159
- }
160
- else {
161
- return (0, codeMod_1.insertContentsInsideSwiftFunctionBlock)(contents, functionSelector, updatedPushCredentialsMethod, { position: 'tail' });
162
- }
163
- }
164
- return contents;
165
- }
166
- function addDidUpdatePushCredentialsObjc(contents) {
167
- const updatedPushCredentialsMethod = '[StreamVideoReactNative didUpdatePushCredentials:credentials forType: (NSString *) type];';
168
- if (!contents.includes(updatedPushCredentialsMethod)) {
169
- const functionSelector = 'pushRegistry:didUpdatePushCredentials:forType:';
170
- const codeblock = (0, codeMod_1.findObjcFunctionCodeBlock)(contents, functionSelector);
171
- if (!codeblock) {
172
- return (0, addNewLinesToAppDelegateObjc_1.default)(contents, [
173
- '- (void)pushRegistry:(PKPushRegistry *)registry didUpdatePushCredentials:(PKPushCredentials *)credentials forType:(PKPushType)type {',
174
- ' ' /* indentation */ + updatedPushCredentialsMethod,
175
- '}',
176
- ]);
177
- }
178
- else {
179
- return (0, codeMod_1.insertContentsInsideObjcFunctionBlock)(contents, functionSelector, updatedPushCredentialsMethod, { position: 'tail' });
180
- }
181
- }
182
- return contents;
183
- }
184
- function addDidReceiveIncomingPushCallbackSwift(contents) {
185
- const onIncomingPush = `
186
- StreamVideoReactNative.didReceiveIncomingPush(payload, forType: type.rawValue, completionHandler: completion)`;
187
- if (!contents.includes('StreamVideoReactNative.didReceiveIncomingPush')) {
188
- const functionSelector = 'pushRegistry(_:didReceiveIncomingPushWith:for:completion:)';
189
- const codeblock = (0, codeMod_1.findSwiftFunctionCodeBlock)(contents, functionSelector);
190
- if (!codeblock) {
191
- return (0, codeMod_1.insertContentsInsideSwiftClassBlock)(contents, 'class AppDelegate', `
192
- public func pushRegistry(
193
- _ registry: PKPushRegistry,
194
- didReceiveIncomingPushWith payload: PKPushPayload,
195
- for type: PKPushType,
196
- completion: @escaping () -> Void
197
- ) {
198
- ${onIncomingPush}
199
- }
200
- `, { position: 'tail' });
201
- }
202
- else {
203
- return (0, codeMod_1.insertContentsInsideSwiftFunctionBlock)(contents, functionSelector, onIncomingPush, { position: 'tail' });
204
- }
205
- }
206
- return contents;
207
- }
208
- function addDidReceiveIncomingPushCallbackObjc(contents) {
209
- const onIncomingPush = `
210
- // process the payload and display the incoming call notification
211
- [StreamVideoReactNative didReceiveIncomingPush:payload forType: (NSString *)type completionHandler:completion];
212
- `;
213
- if (!contents.includes('[StreamVideoReactNative didReceiveIncomingPush')) {
214
- const functionSelector = 'pushRegistry:didReceiveIncomingPushWithPayload:forType:withCompletionHandler:';
215
- const codeblock = (0, codeMod_1.findObjcFunctionCodeBlock)(contents, functionSelector);
216
- if (!codeblock) {
217
- return (0, addNewLinesToAppDelegateObjc_1.default)(contents, [
218
- '- (void)pushRegistry:(PKPushRegistry *)registry didReceiveIncomingPushWithPayload:(PKPushPayload *)payload forType:(PKPushType)type withCompletionHandler:(void (^)(void))completion {',
219
- ...onIncomingPush.trim().split('\n'),
220
- '}',
221
- ]);
222
- }
223
- else {
224
- return (0, codeMod_1.insertContentsInsideObjcFunctionBlock)(contents, functionSelector, onIncomingPush, { position: 'tail' });
225
- }
226
- }
227
- return contents;
228
- }
229
- // Injects the iOS 26.4+ VoIP push delegate.
230
- // - AnyObject for metadata: builds on Xcode older than the iOS 26.4 SDK.
231
- // - Swift label `didReceiveIncomingVoIPPushWith` (no "Payload") matches the
232
- // protocol's optional requirement on the iOS 26.4 SDK; combined with
233
- // `private`, the method is excluded from protocol-conformance checking and
234
- // Swift auto-derives the same ObjC selector PushKit dispatches on.
235
- function addDidReceiveIncomingVoIPPushMetadataCallbackSwift(contents) {
236
- // Match the unique signature, not just the function name: the legacy and
237
- // new delegates are both 4-arg `pushRegistry(...)` methods, so
238
- // findSwiftFunctionCodeBlock would confuse them.
239
- const idempotencyMarker = 'didReceiveIncomingVoIPPushWith payload: PKPushPayload';
240
- if (contents.includes(idempotencyMarker)) {
109
+ if (contents.includes(voipSetupMethod)) {
241
110
  return contents;
242
111
  }
243
- return (0, codeMod_1.insertContentsInsideSwiftClassBlock)(contents, 'class AppDelegate', `
244
- private func pushRegistry(
245
- _ registry: PKPushRegistry,
246
- didReceiveIncomingVoIPPushWith payload: PKPushPayload,
247
- metadata: AnyObject,
248
- withCompletionHandler completion: @escaping () -> Void
249
- ) {
250
- StreamVideoReactNative.didReceiveIncomingVoIPPush(
251
- payload,
252
- metadata: metadata,
253
- completionHandler: completion
254
- )
255
- }
256
- `, { position: 'tail' });
257
- }
258
- // ObjC counterpart of the Swift helper. Uses `id` for the metadata so it
259
- // builds on Xcode older than the iOS 26.4 SDK. The new selector is different
260
- // from the legacy one, so findObjcFunctionCodeBlock is safe to use here.
261
- function addDidReceiveIncomingVoIPPushMetadataCallbackObjc(contents) {
262
- const onIncomingPush = `
263
- [StreamVideoReactNative didReceiveIncomingVoIPPush:payload metadata:metadata completionHandler:completion];
264
- `;
265
- if (!contents.includes('[StreamVideoReactNative didReceiveIncomingVoIPPush:payload')) {
266
- const functionSelector = 'pushRegistry:didReceiveIncomingVoIPPushWithPayload:metadata:withCompletionHandler:';
267
- const codeblock = (0, codeMod_1.findObjcFunctionCodeBlock)(contents, functionSelector);
268
- if (!codeblock) {
269
- return (0, addNewLinesToAppDelegateObjc_1.default)(contents, [
270
- '- (void)pushRegistry:(PKPushRegistry *)registry didReceiveIncomingVoIPPushWithPayload:(PKPushPayload *)payload metadata:(id)metadata withCompletionHandler:(void (^)(void))completion {',
271
- ...onIncomingPush.trim().split('\n'),
272
- '}',
273
- ]);
274
- }
275
- else {
276
- return (0, codeMod_1.insertContentsInsideObjcFunctionBlock)(contents, functionSelector, onIncomingPush, { position: 'tail' });
277
- }
112
+ const updated = (0, codeMod_1.insertContentsInsideObjcFunctionBlock)(contents, functionSelector, voipSetupMethod, { position: 'head' });
113
+ if (!updated.includes(voipSetupMethod)) {
114
+ throw new Error(`Could not find ${functionSelector} in AppDelegate to inject ${voipSetupMethod}`);
278
115
  }
279
- return contents;
116
+ return updated;
280
117
  }
281
118
  exports.default = withAppDelegate;
@@ -13,6 +13,8 @@ class RTCViewPip: UIView {
13
13
 
14
14
  private var pictureInPictureController: StreamPictureInPictureController? = StreamPictureInPictureController()
15
15
  private var webRtcModule: WebRTCModule?
16
+ // Back-reference set by RTCViewPipManager
17
+ weak var manager: RTCViewPipManager?
16
18
 
17
19
  @objc var onPiPChange: RCTBubblingEventBlock?
18
20
 
@@ -193,12 +195,10 @@ class RTCViewPip: UIView {
193
195
  self.pictureInPictureController?.onPiPStateChange = { [weak self] isActive in
194
196
  self?.sendPiPChangeEvent(isActive: isActive)
195
197
  }
196
- if let reactTag = self.reactTag, let bridge = self.webRtcModule?.bridge {
197
- if let manager = bridge.module(for: RTCViewPipManager.self) as? RTCViewPipManager,
198
- let size = manager.getCachedSize(for: reactTag) {
199
- PictureInPictureLogger.log("Applying cached size \(size) for reactTag \(reactTag)")
200
- self.setPreferredContentSize(size)
201
- }
198
+ if let reactTag = self.reactTag,
199
+ let size = self.manager?.getCachedSize(for: reactTag) {
200
+ PictureInPictureLogger.log("Applying cached size \(size) for reactTag \(reactTag)")
201
+ self.setPreferredContentSize(size)
202
202
  }
203
203
  }
204
204
  }
@@ -9,25 +9,62 @@ import Foundation
9
9
 
10
10
  @objc(RTCViewPipManager)
11
11
  class RTCViewPipManager: RCTViewManager {
12
-
12
+
13
13
  private var cachedSizes: [NSNumber: CGSize] = [:]
14
-
14
+
15
+ // Swift equivalent of Obj-C `@synthesize moduleRegistry/viewRegistry_DEPRECATED`.
16
+ private weak var injectedModuleRegistry: RCTModuleRegistry?
17
+ @objc override var moduleRegistry: RCTModuleRegistry! {
18
+ get { injectedModuleRegistry }
19
+ set { injectedModuleRegistry = newValue }
20
+ }
21
+ private weak var injectedViewRegistry: RCTViewRegistry?
22
+ @objc override var viewRegistry_DEPRECATED: RCTViewRegistry! {
23
+ get { injectedViewRegistry }
24
+ set { injectedViewRegistry = newValue }
25
+ }
26
+
15
27
  override func view() -> UIView! {
16
28
  let view = RTCViewPip()
17
- view.setWebRtcModule(self.bridge.module(forName: "WebRTCModule") as! WebRTCModule)
29
+ view.manager = self
30
+ view.setWebRtcModule(moduleRegistry.module(forName: "WebRTCModule") as! WebRTCModule)
18
31
  return view
19
32
  }
20
-
33
+
21
34
  override static func requiresMainQueueSetup() -> Bool {
22
35
  return true
23
36
  }
37
+
38
+ // Resolves the `RTCViewPip` backing a registry lookup, across both RN architectures.
39
+ // Legacy interop stores the backing view in `contentView` since RN 0.73,
40
+ // and newer RN versions also expose it via `paperView`.
41
+ // Taken from https://github.com/rnmapbox/maps/blob/ab2a6dc183dff3a88527803c41edab7d29-2df9cb/ios/RNMBX/Utils/RNMBXViewResolver.mm#L110-L126
42
+ private func resolvePipView(_ view: UIView?) -> RTCViewPip? {
43
+ guard let view else { return nil }
44
+
45
+ if let pipView = view as? RTCViewPip {
46
+ return pipView
47
+ }
48
+
49
+ for selectorName in ["paperView", "contentView"] {
50
+ let selector = NSSelectorFromString(selectorName)
51
+
52
+ if view.responds(to: selector),
53
+ let wrappedView = view.perform(selector)?.takeUnretainedValue() as? UIView,
54
+ let pipView = wrappedView as? RTCViewPip {
55
+ return pipView
56
+ }
57
+ }
58
+
59
+ return nil
60
+ }
24
61
 
25
62
  @objc(onCallClosed:)
26
63
  func onCallClosed(_ reactTag: NSNumber) {
27
64
 
28
- bridge.uiManager.addUIBlock({ (uiManager, viewRegistry) in
29
- let view = uiManager?.view(forReactTag: reactTag)
30
- if let pipView = view as? RTCViewPip {
65
+ viewRegistry_DEPRECATED.addUIBlock({ viewRegistry in
66
+ let view = viewRegistry?.view(forReactTag: reactTag)
67
+ if let pipView = self.resolvePipView(view) {
31
68
  DispatchQueue.main.async {
32
69
  pipView.onCallClosed()
33
70
  }
@@ -42,9 +79,9 @@ class RTCViewPipManager: RCTViewManager {
42
79
  func setPreferredContentSize(_ reactTag: NSNumber, width: CGFloat, height: CGFloat) {
43
80
  let size = CGSize(width: width, height: height)
44
81
 
45
- bridge.uiManager.addUIBlock({ (uiManager, viewRegistry) in
46
- let view = uiManager?.view(forReactTag: reactTag)
47
- if let pipView = view as? RTCViewPip {
82
+ viewRegistry_DEPRECATED.addUIBlock({ viewRegistry in
83
+ let view = viewRegistry?.view(forReactTag: reactTag)
84
+ if let pipView = self.resolvePipView(view) {
48
85
  DispatchQueue.main.async {
49
86
  pipView.setPreferredContentSize(size)
50
87
  }
@@ -470,12 +470,8 @@ class StreamInCallManager: RCTEventEmitter {
470
470
 
471
471
  // MARK: - Helper Methods
472
472
  private func getAudioDeviceModule() -> AudioDeviceModule {
473
- guard let bridge = self.bridge else {
474
- fatalError("StreamInCallManager: RCTBridge is not available yet.")
475
- }
476
-
477
- guard let webrtcModule = bridge.module(forName: "WebRTCModule") as? WebRTCModule else {
478
- fatalError("WebRTCModule is required but not registered with the bridge")
473
+ guard let webrtcModule = moduleRegistry?.module(forName: "WebRTCModule") as? WebRTCModule else {
474
+ fatalError("WebRTCModule is required but not registered with the module registry")
479
475
  }
480
476
 
481
477
  return webrtcModule.audioDeviceModule
@@ -11,6 +11,8 @@
11
11
  #import <WebRTC/RTCVideoTrack.h>
12
12
  #import <WebRTC/RTCVideoRenderer.h>
13
13
  #import <WebRTC/RTCVideoFrameBuffer.h>
14
+ #import <WebRTC/RTCAudioTrack.h>
15
+ #import <WebRTC/RTCAudioRenderer.h>
14
16
  #import "WebRTCModule.h"
15
17
  #import "WebRTCModuleOptions.h"
16
18
 
@@ -1,6 +1,5 @@
1
1
  #import <React/RCTEventEmitter.h>
2
2
  #import <React/RCTBridge.h>
3
- #import <PushKit/PushKit.h>
4
3
 
5
4
  @interface StreamVideoReactNative : RCTEventEmitter <RCTBridgeModule>
6
5
 
@@ -10,24 +9,12 @@
10
9
 
11
10
  + (BOOL)hasAnyActiveCall;
12
11
 
13
- + (void)voipRegistration;
14
-
15
- + (void)didUpdatePushCredentials:(PKPushCredentials *)credentials forType:(NSString *)type;
16
-
17
- + (void)didReceiveIncomingPush:(PKPushPayload *)payload forType:(NSString *)type completionHandler: (void (^_Nullable)(void)) completion;
18
-
19
12
  /**
20
- * VoIP push entry point for iOS 26.4+. Call from your AppDelegate's
21
- * `pushRegistry:didReceiveIncomingVoIPPushWithPayload:metadata:withCompletionHandler:`
22
- * delegate. The SDK reads `mustReport` from `metadata` internally and decides
23
- * whether to show CallKit and/or forward the push to JS based on the
24
- * configured options.
25
- *
26
- * `metadata` is typed `id` (not `PKVoIPPushMetadata *`) so the call site
27
- * compiles on Xcode older than the iOS 26.4 SDK.
13
+ * Registers for VoIP push notifications. The SDK owns the `PKPushRegistry` and
14
+ * its delegate internally, so your `AppDelegate` does not need to conform to
15
+ * `PKPushRegistryDelegate` or implement any `pushRegistry(...)` methods. Call
16
+ * once from `application:didFinishLaunchingWithOptions:`.
28
17
  */
29
- + (void)didReceiveIncomingVoIPPush:(PKPushPayload *)payload
30
- metadata:(id _Nullable)metadata
31
- completionHandler:(void (^_Nullable)(void))completion;
18
+ + (void)voipRegistration;
32
19
 
33
20
  @end