@stream-io/video-react-native-sdk 1.10.12 → 1.10.14

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 (75) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/dist/commonjs/components/Call/CallContent/RTCViewPipIOS.js +7 -17
  3. package/dist/commonjs/components/Call/CallContent/RTCViewPipIOS.js.map +1 -1
  4. package/dist/commonjs/components/Call/CallContent/RTCViewPipNative.js +34 -0
  5. package/dist/commonjs/components/Call/CallContent/RTCViewPipNative.js.map +1 -0
  6. package/dist/commonjs/hooks/push/index.js +0 -2
  7. package/dist/commonjs/hooks/push/index.js.map +1 -1
  8. package/dist/commonjs/hooks/push/useIosCallkeepWithCallingStateEffect.js +20 -23
  9. package/dist/commonjs/hooks/push/useIosCallkeepWithCallingStateEffect.js.map +1 -1
  10. package/dist/commonjs/hooks/push/useIosVoipPushEventsSetupEffect.js +6 -103
  11. package/dist/commonjs/hooks/push/useIosVoipPushEventsSetupEffect.js.map +1 -1
  12. package/dist/commonjs/utils/StreamVideoRN/index.js +4 -0
  13. package/dist/commonjs/utils/StreamVideoRN/index.js.map +1 -1
  14. package/dist/commonjs/utils/push/ios.js +95 -1
  15. package/dist/commonjs/utils/push/ios.js.map +1 -1
  16. package/dist/commonjs/utils/push/setupIosCallKeepEvents.js +150 -0
  17. package/dist/commonjs/utils/push/setupIosCallKeepEvents.js.map +1 -0
  18. package/dist/commonjs/utils/push/setupIosVoipPushEvents.js +27 -0
  19. package/dist/commonjs/utils/push/setupIosVoipPushEvents.js.map +1 -0
  20. package/dist/commonjs/version.js +1 -1
  21. package/dist/module/components/Call/CallContent/RTCViewPipIOS.js +9 -19
  22. package/dist/module/components/Call/CallContent/RTCViewPipIOS.js.map +1 -1
  23. package/dist/module/components/Call/CallContent/RTCViewPipNative.js +26 -0
  24. package/dist/module/components/Call/CallContent/RTCViewPipNative.js.map +1 -0
  25. package/dist/module/hooks/push/index.js +0 -2
  26. package/dist/module/hooks/push/index.js.map +1 -1
  27. package/dist/module/hooks/push/useIosCallkeepWithCallingStateEffect.js +21 -24
  28. package/dist/module/hooks/push/useIosCallkeepWithCallingStateEffect.js.map +1 -1
  29. package/dist/module/hooks/push/useIosVoipPushEventsSetupEffect.js +10 -108
  30. package/dist/module/hooks/push/useIosVoipPushEventsSetupEffect.js.map +1 -1
  31. package/dist/module/utils/StreamVideoRN/index.js +4 -0
  32. package/dist/module/utils/StreamVideoRN/index.js.map +1 -1
  33. package/dist/module/utils/push/ios.js +97 -4
  34. package/dist/module/utils/push/ios.js.map +1 -1
  35. package/dist/module/utils/push/setupIosCallKeepEvents.js +145 -0
  36. package/dist/module/utils/push/setupIosCallKeepEvents.js.map +1 -0
  37. package/dist/module/utils/push/setupIosVoipPushEvents.js +21 -0
  38. package/dist/module/utils/push/setupIosVoipPushEvents.js.map +1 -0
  39. package/dist/module/version.js +1 -1
  40. package/dist/typescript/components/Call/CallContent/RTCViewPipIOS.d.ts.map +1 -1
  41. package/dist/typescript/components/Call/CallContent/RTCViewPipNative.d.ts +8 -0
  42. package/dist/typescript/components/Call/CallContent/RTCViewPipNative.d.ts.map +1 -0
  43. package/dist/typescript/hooks/push/index.d.ts.map +1 -1
  44. package/dist/typescript/hooks/push/useIosCallkeepWithCallingStateEffect.d.ts.map +1 -1
  45. package/dist/typescript/hooks/push/useIosVoipPushEventsSetupEffect.d.ts.map +1 -1
  46. package/dist/typescript/utils/StreamVideoRN/index.d.ts.map +1 -1
  47. package/dist/typescript/utils/push/ios.d.ts +1 -0
  48. package/dist/typescript/utils/push/ios.d.ts.map +1 -1
  49. package/dist/typescript/utils/push/setupIosCallKeepEvents.d.ts +6 -0
  50. package/dist/typescript/utils/push/setupIosCallKeepEvents.d.ts.map +1 -0
  51. package/dist/typescript/utils/push/setupIosVoipPushEvents.d.ts +3 -0
  52. package/dist/typescript/utils/push/setupIosVoipPushEvents.d.ts.map +1 -0
  53. package/dist/typescript/version.d.ts +1 -1
  54. package/ios/PictureInPicture/StreamPictureInPictureController.swift +7 -0
  55. package/ios/RTCViewPip.swift +52 -25
  56. package/ios/RTCViewPipManager.swift +5 -5
  57. package/ios/StreamVideoReactNative.m +72 -22
  58. package/package.json +3 -3
  59. package/src/components/Call/CallContent/RTCViewPipIOS.tsx +15 -38
  60. package/src/components/Call/CallContent/RTCViewPipNative.tsx +51 -0
  61. package/src/hooks/push/index.ts +0 -2
  62. package/src/hooks/push/useIosCallkeepWithCallingStateEffect.ts +37 -31
  63. package/src/hooks/push/useIosVoipPushEventsSetupEffect.ts +10 -145
  64. package/src/utils/StreamVideoRN/index.ts +5 -0
  65. package/src/utils/push/ios.ts +135 -3
  66. package/src/utils/push/setupIosCallKeepEvents.ts +187 -0
  67. package/src/utils/push/setupIosVoipPushEvents.ts +29 -0
  68. package/src/version.ts +1 -1
  69. package/dist/commonjs/hooks/push/useIosCallKeepEventsSetupEffect.js +0 -109
  70. package/dist/commonjs/hooks/push/useIosCallKeepEventsSetupEffect.js.map +0 -1
  71. package/dist/module/hooks/push/useIosCallKeepEventsSetupEffect.js +0 -103
  72. package/dist/module/hooks/push/useIosCallKeepEventsSetupEffect.js.map +0 -1
  73. package/dist/typescript/hooks/push/useIosCallKeepEventsSetupEffect.d.ts +0 -5
  74. package/dist/typescript/hooks/push/useIosCallKeepEventsSetupEffect.d.ts.map +0 -1
  75. package/src/hooks/push/useIosCallKeepEventsSetupEffect.ts +0 -132
@@ -0,0 +1,8 @@
1
+ import React from 'react';
2
+ export declare function onNativeCallClosed(reactTag: number): void;
3
+ /** Wrapper for the native view
4
+ * meant to stay private and not exposed */
5
+ export declare const RTCViewPipNative: React.MemoExoticComponent<React.ForwardRefExoticComponent<{
6
+ streamURL?: string;
7
+ } & React.RefAttributes<React.Ref<any>>>>;
8
+ //# sourceMappingURL=RTCViewPipNative.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RTCViewPipNative.d.ts","sourceRoot":"","sources":["../../../../../src/components/Call/CallContent/RTCViewPipNative.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,OAAO,CAAC;AAkB1B,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,QAQlD;AAED;2CAC2C;AAC3C,eAAO,MAAM,gBAAgB;gBAIX,MAAM;yCAevB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/hooks/push/index.ts"],"names":[],"mappings":"AAOA;;;GAGG;AACH,eAAO,MAAM,qBAAqB,YAOjC,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/hooks/push/index.ts"],"names":[],"mappings":"AAMA;;;GAGG;AACH,eAAO,MAAM,qBAAqB,YAMjC,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"useIosCallkeepWithCallingStateEffect.d.ts","sourceRoot":"","sources":["../../../../src/hooks/push/useIosCallkeepWithCallingStateEffect.ts"],"names":[],"mappings":"AAuCA;;GAEG;AACH,eAAO,MAAM,oCAAoC,YAyJhD,CAAC"}
1
+ {"version":3,"file":"useIosCallkeepWithCallingStateEffect.d.ts","sourceRoot":"","sources":["../../../../src/hooks/push/useIosCallkeepWithCallingStateEffect.ts"],"names":[],"mappings":"AA6CA;;GAEG;AACH,eAAO,MAAM,oCAAoC,YAyJhD,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"useIosVoipPushEventsSetupEffect.d.ts","sourceRoot":"","sources":["../../../../src/hooks/push/useIosVoipPushEventsSetupEffect.ts"],"names":[],"mappings":"AAmDA;;;GAGG;AACH,eAAO,MAAM,+BAA+B,YAuI3C,CAAC"}
1
+ {"version":3,"file":"useIosVoipPushEventsSetupEffect.d.ts","sourceRoot":"","sources":["../../../../src/hooks/push/useIosVoipPushEventsSetupEffect.ts"],"names":[],"mappings":"AAuCA;;;GAGG;AACH,eAAO,MAAM,+BAA+B,YAiI3C,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/utils/StreamVideoRN/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAEjD,OAAiC,EAC/B,KAAK,2BAA2B,EACjC,MAAM,sCAAsC,CAAC;AAoB9C,qBAAa,aAAa;IACxB,OAAO,CAAC,MAAM,CAAC,MAAM,CAA+B;IAEpD;;;;OAIG;IACH,MAAM,CAAC,YAAY,CAAC,YAAY,EAAE,OAAO,CAAC,IAAI,CAAC,iBAAiB,EAAE,MAAM,CAAC,CAAC;IAO1E,MAAM,CAAC,gCAAgC,CACrC,aAAa,EAAE,OAAO,CACpB,WAAW,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,qBAAqB,CAAC,CACzE;IAWH;;;;;;;;;;;;;;OAcG;IACH,MAAM,CAAC,aAAa,CAAC,UAAU,EAAE,WAAW,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC;IAmBvE,MAAM,CAAC,SAAS;IAIhB;;;OAGG;IACH,MAAM,CAAC,YAAY;IASnB,MAAM,CAAC,wBAAwB;IAI/B;;;;OAIG;IACH,MAAM,CAAC,gCAAgC,CACrC,QAAQ,EAAE,2BAA2B;CAYxC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/utils/StreamVideoRN/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAEjD,OAAiC,EAC/B,KAAK,2BAA2B,EACjC,MAAM,sCAAsC,CAAC;AAsB9C,qBAAa,aAAa;IACxB,OAAO,CAAC,MAAM,CAAC,MAAM,CAA+B;IAEpD;;;;OAIG;IACH,MAAM,CAAC,YAAY,CAAC,YAAY,EAAE,OAAO,CAAC,IAAI,CAAC,iBAAiB,EAAE,MAAM,CAAC,CAAC;IAO1E,MAAM,CAAC,gCAAgC,CACrC,aAAa,EAAE,OAAO,CACpB,WAAW,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,qBAAqB,CAAC,CACzE;IAWH;;;;;;;;;;;;;;OAcG;IACH,MAAM,CAAC,aAAa,CAAC,UAAU,EAAE,WAAW,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC;IAsBvE,MAAM,CAAC,SAAS;IAIhB;;;OAGG;IACH,MAAM,CAAC,YAAY;IASnB,MAAM,CAAC,wBAAwB;IAI/B;;;;OAIG;IACH,MAAM,CAAC,gCAAgC,CACrC,QAAQ,EAAE,2BAA2B;CAYxC"}
@@ -11,5 +11,6 @@ export declare const oniOSNotifeeEvent: ({ event, }: {
11
11
  export declare function onPushNotificationiOSStreamVideoEvent(notification: PushNotificationiOSType): void;
12
12
  /** Send token to stream */
13
13
  export declare function initIosNonVoipToken(client: StreamVideoClient, pushConfig: PushConfig, setUnsubscribeListener: (unsubscribe: () => void) => void): Promise<void>;
14
+ export declare const onVoipNotificationReceived: (notification: any) => Promise<void>;
14
15
  export {};
15
16
  //# sourceMappingURL=ios.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ios.d.ts","sourceRoot":"","sources":["../../../../src/utils/push/ios.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAEhE,OAAO,EACL,KAAK,gBAAgB,EAIrB,KAAK,uBAAuB,EAC7B,MAAM,QAAQ,CAAC;AAChB,OAAO,EAAE,iBAAiB,EAAa,MAAM,yBAAyB,CAAC;AAEvE,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAInD,KAAK,UAAU,GAAG,WAAW,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC,CAAC;AAqBzD,eAAO,MAAM,0BAA0B,UAAW,gBAAgB,SAoBjE,CAAC;AAEF,eAAO,MAAM,iBAAiB,eAE3B;IACD,KAAK,EAAE,KAAK,CAAC;IACb,YAAY,EAAE,OAAO,CAAC;CACvB,SAmBA,CAAC;AAEF,wBAAgB,qCAAqC,CACnD,YAAY,EAAE,uBAAuB,QAiCtC;AAED,2BAA2B;AAC3B,wBAAsB,mBAAmB,CACvC,MAAM,EAAE,iBAAiB,EACzB,UAAU,EAAE,UAAU,EACtB,sBAAsB,EAAE,CAAC,WAAW,EAAE,MAAM,IAAI,KAAK,IAAI,iBAoF1D"}
1
+ {"version":3,"file":"ios.d.ts","sourceRoot":"","sources":["../../../../src/utils/push/ios.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAMhE,OAAO,EACL,KAAK,gBAAgB,EAMrB,KAAK,uBAAuB,EAC7B,MAAM,QAAQ,CAAC;AAChB,OAAO,EAAW,iBAAiB,EAAa,MAAM,yBAAyB,CAAC;AAEhF,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAQnD,KAAK,UAAU,GAAG,WAAW,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC,CAAC;AAqBzD,eAAO,MAAM,0BAA0B,UAAW,gBAAgB,SAoBjE,CAAC;AAEF,eAAO,MAAM,iBAAiB,eAE3B;IACD,KAAK,EAAE,KAAK,CAAC;IACb,YAAY,EAAE,OAAO,CAAC;CACvB,SAmBA,CAAC;AAEF,wBAAgB,qCAAqC,CACnD,YAAY,EAAE,uBAAuB,QAiCtC;AAED,2BAA2B;AAC3B,wBAAsB,mBAAmB,CACvC,MAAM,EAAE,iBAAiB,EACzB,UAAU,EAAE,UAAU,EACtB,sBAAsB,EAAE,CAAC,WAAW,EAAE,MAAM,IAAI,KAAK,IAAI,iBAoF1D;AAED,eAAO,MAAM,0BAA0B,iBAAwB,GAAG,kBAwHjE,CAAC"}
@@ -0,0 +1,6 @@
1
+ import type { StreamVideoConfig } from '../StreamVideoRN/types';
2
+ /**
3
+ * This hook is used to listen to callkeep events and do the necessary actions
4
+ */
5
+ export declare function setupIosCallKeepEvents(pushConfig: NonNullable<StreamVideoConfig['push']>): void;
6
+ //# sourceMappingURL=setupIosCallKeepEvents.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"setupIosCallKeepEvents.d.ts","sourceRoot":"","sources":["../../../../src/utils/push/setupIosCallKeepEvents.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAchE;;GAEG;AACH,wBAAgB,sBAAsB,CACpC,UAAU,EAAE,WAAW,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC,QAgHnD"}
@@ -0,0 +1,3 @@
1
+ import { StreamVideoConfig } from '../StreamVideoRN/types';
2
+ export declare function setupIosVoipPushEvents(pushConfig: NonNullable<StreamVideoConfig['push']>): void;
3
+ //# sourceMappingURL=setupIosVoipPushEvents.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"setupIosVoipPushEvents.d.ts","sourceRoot":"","sources":["../../../../src/utils/push/setupIosVoipPushEvents.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAE3D,wBAAgB,sBAAsB,CACpC,UAAU,EAAE,WAAW,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC,QAmBnD"}
@@ -1,2 +1,2 @@
1
- export declare const version = "1.10.12";
1
+ export declare const version = "1.10.14";
2
2
  //# sourceMappingURL=version.d.ts.map
@@ -104,6 +104,7 @@ import Foundation
104
104
  _ pictureInPictureController: AVPictureInPictureController,
105
105
  failedToStartPictureInPictureWithError error: Error
106
106
  ) {
107
+ NSLog("PiP - failedToStartPictureInPictureWithError:\(error)")
107
108
  }
108
109
 
109
110
  public func pictureInPictureControllerWillStopPictureInPicture(
@@ -184,4 +185,10 @@ import Foundation
184
185
  private func didUpdatePictureInPictureActiveState(_ isActive: Bool) {
185
186
  trackStateAdapter.isEnabled = isActive
186
187
  }
188
+
189
+ func stopPictureInPicture() {
190
+ if (pictureInPictureController?.isPictureInPictureActive ?? false) {
191
+ pictureInPictureController?.stopPictureInPicture()
192
+ }
193
+ }
187
194
  }
@@ -10,52 +10,76 @@ import Foundation
10
10
  @objc(RTCViewPip)
11
11
  class RTCViewPip: UIView {
12
12
 
13
- private lazy var pictureInPictureController = StreamPictureInPictureController()
13
+ private var pictureInPictureController = StreamPictureInPictureController()
14
14
  private var webRtcModule: WebRTCModule?
15
15
 
16
16
  override init(frame: CGRect) {
17
17
  super.init(frame: frame)
18
- setupView()
18
+ setupNotificationObserver()
19
+ self.pictureInPictureController?.sourceView = self
19
20
  }
20
21
 
21
22
  required init?(coder aDecoder: NSCoder) {
22
23
  super.init(coder: aDecoder)
23
- setupView()
24
+ setupNotificationObserver()
24
25
  }
25
26
 
26
- private func setupView() {
27
- let videoView = UIView()
28
- self.addSubview(videoView)
29
- pictureInPictureController?.sourceView = videoView
30
- videoView.backgroundColor = UIColor.clear // make it transparent
27
+ private func setupNotificationObserver() {
28
+ NotificationCenter.default.addObserver(
29
+ self,
30
+ selector: #selector(appBecameActive),
31
+ name: UIApplication.didBecomeActiveNotification,
32
+ object: nil
33
+ )
34
+ }
35
+
36
+ deinit {
37
+ NotificationCenter.default.removeObserver(self)
31
38
  }
32
39
 
33
40
  func setWebRtcModule(_ module: WebRTCModule) {
34
41
  webRtcModule = module
35
42
  }
36
43
 
37
- @objc func setStreamURL(_ streamReactTag: NSString) {
38
- let tag = String(streamReactTag)
39
- webRtcModule?.workerQueue.async {
40
- let stream = self.webRtcModule?.stream(forReactTag: tag)
41
- let videoTracks = stream?.videoTracks ?? []
42
- let videoTrack = videoTracks.first
43
- if videoTrack == nil {
44
- NSLog("PiP - No video stream for react tag: -\(tag)")
45
- } else {
46
- DispatchQueue.main.async {
47
- self.pictureInPictureController?.track = videoTrack
48
- }
44
+ @objc public var streamURL: NSString? = nil {
45
+ didSet {
46
+ // https://github.com/react-native-webrtc/react-native-webrtc/blob/8dfc9c394b4bf627c0214255466ebd3b160ca563/ios/RCTWebRTC/RTCVideoViewManager.m#L405-L418
47
+ guard let streamURLString = streamURL as String? else {
48
+ NSLog("PiP - No streamURL set")
49
+ return
50
+ }
51
+
52
+ guard let stream = self.webRtcModule?.stream(forReactTag: streamURLString) else {
53
+ NSLog("PiP - No stream for streamURL: -\(streamURLString)")
54
+ return
55
+ }
56
+
57
+ guard let videoTrack = stream.videoTracks.first else {
58
+ NSLog("PiP - No video track for streamURL: -\(streamURLString)")
59
+ return
60
+ }
61
+ if (self.pictureInPictureController?.track == videoTrack) {
62
+ NSLog("PiP - Skipping video track for streamURL: -\(streamURLString)")
63
+ return
64
+ }
65
+
66
+ DispatchQueue.main.async {
67
+ NSLog("PiP - Setting video track for streamURL: -\(streamURLString)")
68
+ self.pictureInPictureController?.track = videoTrack
49
69
  }
50
70
  }
51
71
  }
52
72
 
73
+ @objc func appBecameActive() {
74
+ self.pictureInPictureController?.stopPictureInPicture()
75
+ }
76
+
77
+
53
78
  @objc
54
79
  func onCallClosed() {
55
- DispatchQueue.main.async {
56
- self.pictureInPictureController?.cleanup()
57
- self.pictureInPictureController = nil
58
- }
80
+ NSLog("PiP - pictureInPictureController cleanup called")
81
+ self.pictureInPictureController?.cleanup()
82
+ self.pictureInPictureController = nil
59
83
  }
60
84
 
61
85
  override func didMoveToWindow() {
@@ -64,7 +88,10 @@ class RTCViewPip: UIView {
64
88
  if (!isVisible) {
65
89
  // view is detached so we cleanup the pip controller
66
90
  // taken from: https://github.com/software-mansion/react-native-screens/blob/main/Example/ios/ScreensExample/RNSSampleLifecycleAwareView.m
67
- onCallClosed()
91
+ DispatchQueue.main.async {
92
+ NSLog("PiP - onCallClosed called due to view detaching")
93
+ self.onCallClosed()
94
+ }
68
95
  }
69
96
  }
70
97
  }
@@ -22,13 +22,13 @@ class RTCViewPipManager: RCTViewManager {
22
22
 
23
23
  @objc func onCallClosed(_ reactTag: NSNumber) {
24
24
  self.bridge!.uiManager.addUIBlock { (_: RCTUIManager?, viewRegistry: [NSNumber: UIView]?) in
25
- guard let view = viewRegistry?[reactTag] as? RTCViewPip else {
26
- if RCT_DEBUG == 1 {
27
- print("Invalid view returned from registry, expecting RTCViewPip")
28
- }
25
+ guard let pipView = viewRegistry?[reactTag] as? RTCViewPip else {
26
+ NSLog("PiP - onCallClosed cant be called, Invalid view returned from registry, expecting RTCViewPip")
29
27
  return
30
28
  }
31
- view.onCallClosed()
29
+ DispatchQueue.main.async {
30
+ pipView.onCallClosed()
31
+ }
32
32
  }
33
33
  }
34
34
  }
@@ -7,7 +7,10 @@
7
7
  // Do not change these consts, it is what is used react-native-webrtc
8
8
  NSNotificationName const kBroadcastStartedNotification = @"iOS_BroadcastStarted";
9
9
  NSNotificationName const kBroadcastStoppedNotification = @"iOS_BroadcastStopped";
10
- NSMutableDictionary *dictionary;
10
+
11
+ static NSMutableDictionary *_incomingCallUUIDsByCallID = nil;
12
+ static NSMutableDictionary *_incomingCallCidsByUUID = nil;
13
+ static dispatch_queue_t _dictionaryQueue = nil;
11
14
 
12
15
  void broadcastNotificationCallback(CFNotificationCenterRef center,
13
16
  void *observer,
@@ -17,7 +20,6 @@ void broadcastNotificationCallback(CFNotificationCenterRef center,
17
20
  StreamVideoReactNative *this = (__bridge StreamVideoReactNative*)observer;
18
21
  NSString *eventName = (__bridge NSString*)name;
19
22
  [this screenShareEventReceived: eventName];
20
-
21
23
  }
22
24
 
23
25
  @implementation StreamVideoReactNative
@@ -38,16 +40,22 @@ RCT_EXPORT_MODULE();
38
40
  // options.videoEncoderFactory = simulcastVideoEncoderFactory;
39
41
  }
40
42
 
43
+ +(void)initializeSharedDictionaries {
44
+ static dispatch_once_t onceToken;
45
+ dispatch_once(&onceToken, ^{
46
+ _dictionaryQueue = dispatch_queue_create("com.stream.video.dictionary", DISPATCH_QUEUE_SERIAL);
47
+ _incomingCallUUIDsByCallID = [NSMutableDictionary dictionary];
48
+ _incomingCallCidsByUUID = [NSMutableDictionary dictionary];
49
+ });
50
+ }
51
+
41
52
  -(instancetype)init {
42
- self = [super init];
43
- if (self) {
53
+ if ((self = [super init])) {
44
54
  _notificationCenter = CFNotificationCenterGetDarwinNotifyCenter();
45
- [self setupObserver];
46
- }
47
- if (self) {
48
55
  [UIDevice currentDevice].batteryMonitoringEnabled = YES;
56
+ [self setupObserver];
57
+ [StreamVideoReactNative initializeSharedDictionaries];
49
58
  }
50
-
51
59
  return self;
52
60
  }
53
61
 
@@ -153,26 +161,68 @@ RCT_EXPORT_METHOD(currentThermalState:(RCTPromiseResolveBlock)resolve rejecter:(
153
161
  }
154
162
 
155
163
  +(void)registerIncomingCall:(NSString *)cid uuid:(NSString *)uuid {
156
- if (dictionary == nil) {
157
- dictionary = [NSMutableDictionary dictionary];
158
- }
159
- dictionary[cid] = uuid;
164
+ [StreamVideoReactNative initializeSharedDictionaries];
165
+ dispatch_sync(_dictionaryQueue, ^{
166
+
167
+ #ifdef DEBUG
168
+ NSLog(@"registerIncomingCall cid:%@ -> uuid:%@",cid,uuid);
169
+ #endif
170
+ NSString *lowercaseUUID = [uuid lowercaseString];
171
+ _incomingCallUUIDsByCallID[cid] = lowercaseUUID;
172
+ _incomingCallCidsByUUID[lowercaseUUID] = cid;
173
+ });
160
174
  }
161
175
 
162
176
  RCT_EXPORT_METHOD(getIncomingCallUUid:(NSString *)cid
163
177
  resolver:(RCTPromiseResolveBlock)resolve
164
178
  rejecter:(RCTPromiseRejectBlock)reject)
165
179
  {
166
- if (dictionary == nil) {
167
- reject(@"access_failure", @"no incoming call dictionary found", nil);
168
- }
169
- NSString *uuid = dictionary[cid];
170
- if (uuid) {
171
- resolve(uuid);
172
- } else {
173
- reject(@"access_failure", @"requested incoming call found", nil);
174
- }
175
-
180
+ dispatch_sync(_dictionaryQueue, ^{
181
+ NSString *uuid = _incomingCallUUIDsByCallID[cid];
182
+ if (uuid) {
183
+ resolve(uuid);
184
+ } else {
185
+ NSString *errorString = [NSString stringWithFormat:@"requested incoming call not found for cid: %@", cid];
186
+ reject(@"access_failure", errorString, nil);
187
+ }
188
+ });
189
+ }
190
+
191
+ RCT_EXPORT_METHOD(getIncomingCallCid:(NSString *)uuid
192
+ resolver:(RCTPromiseResolveBlock)resolve
193
+ rejecter:(RCTPromiseRejectBlock)reject)
194
+ {
195
+ dispatch_sync(_dictionaryQueue, ^{
196
+ NSString *lowercaseUUID = [uuid lowercaseString];
197
+ NSString *foundCid = _incomingCallCidsByUUID[lowercaseUUID];
198
+
199
+ if (foundCid) {
200
+ resolve(foundCid);
201
+ } else {
202
+ NSString *errorString = [NSString stringWithFormat:@"requested incoming call not found for uuid: %@", uuid];
203
+ reject(@"access_failure", errorString, nil);
204
+ }
205
+ });
206
+ }
207
+
208
+ RCT_EXPORT_METHOD(removeIncomingCall:(NSString *)cid
209
+ resolver:(RCTPromiseResolveBlock)resolve
210
+ rejecter:(RCTPromiseRejectBlock)reject)
211
+ {
212
+ dispatch_sync(_dictionaryQueue, ^{
213
+ NSString *uuid = _incomingCallUUIDsByCallID[cid];
214
+ if (uuid) {
215
+ #ifdef DEBUG
216
+ NSLog(@"removeIncomingCall cid:%@ -> uuid:%@",cid,uuid);
217
+ #endif
218
+
219
+ [_incomingCallUUIDsByCallID removeObjectForKey:cid];
220
+ [_incomingCallCidsByUUID removeObjectForKey:uuid];
221
+ resolve(@YES);
222
+ } else {
223
+ resolve(@NO);
224
+ }
225
+ });
176
226
  }
177
227
 
178
228
  -(NSArray<NSString *> *)supportedEvents {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stream-io/video-react-native-sdk",
3
- "version": "1.10.12",
3
+ "version": "1.10.14",
4
4
  "packageManager": "yarn@3.2.4",
5
5
  "description": "Stream Video SDK for React Native",
6
6
  "author": "https://getstream.io",
@@ -46,8 +46,8 @@
46
46
  "!**/.*"
47
47
  ],
48
48
  "dependencies": {
49
- "@stream-io/video-client": "1.18.3",
50
- "@stream-io/video-react-bindings": "1.5.5",
49
+ "@stream-io/video-client": "1.18.4",
50
+ "@stream-io/video-react-bindings": "1.5.6",
51
51
  "intl-pluralrules": "2.0.1",
52
52
  "lodash.merge": "^4.6.2",
53
53
  "react-native-url-polyfill": "1.3.0",
@@ -1,45 +1,17 @@
1
1
  import {
2
2
  CallingState,
3
+ getLogger,
3
4
  hasScreenShare,
4
5
  speakerLayoutSortPreset,
5
6
  } from '@stream-io/video-client';
6
7
  import { useCall, useCallStateHooks } from '@stream-io/video-react-bindings';
7
8
  import type { MediaStream } from '@stream-io/react-native-webrtc';
8
9
  import React, { useEffect, useMemo } from 'react';
9
- import {
10
- findNodeHandle,
11
- type HostComponent,
12
- Platform,
13
- requireNativeComponent,
14
- UIManager,
15
- } from 'react-native';
10
+ import { findNodeHandle } from 'react-native';
11
+ import { RTCViewPipNative, onNativeCallClosed } from './RTCViewPipNative';
16
12
  import { useDebouncedValue } from '../../../utils/hooks/useDebouncedValue';
17
13
  import { shouldDisableIOSLocalVideoOnBackgroundRef } from '../../../utils/internal/shouldDisableIOSLocalVideoOnBackground';
18
14
 
19
- const COMPONENT_NAME = 'RTCViewPip';
20
-
21
- type RTCViewPipNativeProps = {
22
- streamURL?: string;
23
- };
24
-
25
- const RTCViewPipNative: HostComponent<RTCViewPipNativeProps> =
26
- requireNativeComponent(COMPONENT_NAME);
27
-
28
- /** Wrapper for the native view
29
- * meant to stay private and not exposed */
30
- const RTCViewPip = React.memo(
31
- React.forwardRef<
32
- React.Ref<any>,
33
- {
34
- streamURL?: string;
35
- }
36
- >((props, ref) => {
37
- if (Platform.OS !== 'ios') return null;
38
- // @ts-ignore
39
- return <RTCViewPipNative streamURL={props.streamURL} ref={ref} />;
40
- })
41
- );
42
-
43
15
  type Props = {
44
16
  includeLocalParticipantVideo?: boolean;
45
17
  };
@@ -80,20 +52,25 @@ const RTCViewPipIOS = React.memo(({ includeLocalParticipantVideo }: Props) => {
80
52
  callClosedInvokedOnce = true;
81
53
  const node = findNodeHandle(nativeRef.current);
82
54
  if (node !== null) {
83
- UIManager.dispatchViewManagerCommand(
84
- node,
85
- // @ts-ignore
86
- UIManager.getViewManagerConfig(COMPONENT_NAME).Commands.onCallClosed,
87
- []
88
- );
55
+ onNativeCallClosed(node);
89
56
  }
90
57
  shouldDisableIOSLocalVideoOnBackgroundRef.current = true;
91
58
  };
92
59
  const unsubFunc = call?.on('call.ended', () => {
60
+ getLogger(['RTCViewPipIOS'])(
61
+ 'debug',
62
+ `onCallClosed due to call.ended event`
63
+ );
64
+ unsubFunc?.();
93
65
  onCallClosed();
94
66
  });
95
67
  const subscription = call?.state.callingState$.subscribe((state) => {
96
68
  if (state === CallingState.LEFT || state === CallingState.IDLE) {
69
+ getLogger(['RTCViewPipIOS'])(
70
+ 'debug',
71
+ `onCallClosed due to callingState: ${state}`
72
+ );
73
+ subscription?.unsubscribe();
97
74
  onCallClosed();
98
75
  }
99
76
  });
@@ -120,7 +97,7 @@ const RTCViewPipIOS = React.memo(({ includeLocalParticipantVideo }: Props) => {
120
97
  return videoStreamToRender?.toURL();
121
98
  }, [participantInSpotlight]);
122
99
 
123
- return <RTCViewPip streamURL={streamURL} ref={nativeRef} />;
100
+ return <RTCViewPipNative streamURL={streamURL} ref={nativeRef} />;
124
101
  });
125
102
 
126
103
  export default RTCViewPipIOS;
@@ -0,0 +1,51 @@
1
+ import { getLogger } from '@stream-io/video-client';
2
+ import React from 'react';
3
+ import {
4
+ type HostComponent,
5
+ Platform,
6
+ requireNativeComponent,
7
+ UIManager,
8
+ StyleSheet,
9
+ } from 'react-native';
10
+
11
+ const COMPONENT_NAME = 'RTCViewPip';
12
+
13
+ type RTCViewPipNativeProps = {
14
+ streamURL?: string;
15
+ };
16
+
17
+ const NativeComponent: HostComponent<RTCViewPipNativeProps> =
18
+ requireNativeComponent(COMPONENT_NAME);
19
+
20
+ export function onNativeCallClosed(reactTag: number) {
21
+ getLogger(['RTCViewPipNative'])('debug', 'onNativeCallClosed');
22
+ UIManager.dispatchViewManagerCommand(
23
+ reactTag,
24
+ // @ts-ignore
25
+ UIManager.getViewManagerConfig(COMPONENT_NAME).Commands.onCallClosed,
26
+ []
27
+ );
28
+ }
29
+
30
+ /** Wrapper for the native view
31
+ * meant to stay private and not exposed */
32
+ export const RTCViewPipNative = React.memo(
33
+ React.forwardRef<
34
+ React.Ref<any>,
35
+ {
36
+ streamURL?: string;
37
+ }
38
+ >((props, ref) => {
39
+ if (Platform.OS !== 'ios') return null;
40
+
41
+ return (
42
+ <NativeComponent
43
+ style={StyleSheet.absoluteFill}
44
+ pointerEvents={'none'}
45
+ streamURL={props.streamURL}
46
+ // @ts-ignore
47
+ ref={ref}
48
+ />
49
+ );
50
+ })
51
+ );
@@ -1,4 +1,3 @@
1
- import { useIosCallKeepEventsSetupEffect } from './useIosCallKeepEventsSetupEffect';
2
1
  import { useIosVoipPushEventsSetupEffect } from './useIosVoipPushEventsSetupEffect';
3
2
  import { useProcessPushCallEffect } from './useProcessPushCallEffect';
4
3
  import { useInitAndroidTokenAndRest } from './useInitAndroidTokenAndRest';
@@ -11,7 +10,6 @@ import { useProcessPushNonRingingCallEffect } from './useProcessPushNonRingingCa
11
10
  */
12
11
  export const usePushRegisterEffect = () => {
13
12
  useIosInitRemoteNotifications();
14
- useIosCallKeepEventsSetupEffect();
15
13
  useIosVoipPushEventsSetupEffect();
16
14
  useProcessPushNonRingingCallEffect();
17
15
  useProcessPushCallEffect();