@stream-io/video-react-native-sdk 1.29.4-beta.0 → 1.30.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 (276) hide show
  1. package/CHANGELOG.md +3162 -0
  2. package/android/src/main/AndroidManifest.xml +1 -8
  3. package/android/src/main/AndroidManifestNew.xml +0 -11
  4. package/android/src/main/java/com/streamvideo/reactnative/StreamVideoReactNativeModule.kt +5 -42
  5. package/android/src/main/java/com/streamvideo/reactnative/audio/utils/WebRtcAudioUtils.kt +6 -70
  6. package/android/src/main/java/com/streamvideo/reactnative/callmanager/StreamInCallManagerModule.kt +4 -6
  7. package/android/src/main/java/com/streamvideo/reactnative/util/CallAliveServiceChecker.kt +95 -0
  8. package/dist/commonjs/components/Call/CallContent/CallContent.js +13 -7
  9. package/dist/commonjs/components/Call/CallContent/CallContent.js.map +1 -1
  10. package/dist/commonjs/components/Call/CallContent/RTCViewPipIOS.js +50 -14
  11. package/dist/commonjs/components/Call/CallContent/RTCViewPipIOS.js.map +1 -1
  12. package/dist/commonjs/components/Call/CallContent/RTCViewPipNative.js +27 -0
  13. package/dist/commonjs/components/Call/CallContent/RTCViewPipNative.js.map +1 -1
  14. package/dist/commonjs/components/Call/CallLayout/CallParticipantsGrid.js +19 -10
  15. package/dist/commonjs/components/Call/CallLayout/CallParticipantsGrid.js.map +1 -1
  16. package/dist/commonjs/components/Call/CallLayout/CallParticipantsSpotlight.js +12 -9
  17. package/dist/commonjs/components/Call/CallLayout/CallParticipantsSpotlight.js.map +1 -1
  18. package/dist/commonjs/components/Call/CallParticipantsList/CallParticipantsList.js +19 -4
  19. package/dist/commonjs/components/Call/CallParticipantsList/CallParticipantsList.js.map +1 -1
  20. package/dist/commonjs/hooks/push/index.js +2 -0
  21. package/dist/commonjs/hooks/push/index.js.map +1 -1
  22. package/dist/commonjs/hooks/push/useIosCallkeepWithCallingStateEffect.js +160 -0
  23. package/dist/commonjs/hooks/push/useIosCallkeepWithCallingStateEffect.js.map +1 -0
  24. package/dist/commonjs/hooks/push/useIosVoipPushEventsSetupEffect.js +31 -18
  25. package/dist/commonjs/hooks/push/useIosVoipPushEventsSetupEffect.js.map +1 -1
  26. package/dist/commonjs/hooks/push/useProcessPushCallEffect.js +67 -0
  27. package/dist/commonjs/hooks/push/useProcessPushCallEffect.js.map +1 -0
  28. package/dist/commonjs/hooks/useAndroidKeepCallAliveEffect.js +97 -64
  29. package/dist/commonjs/hooks/useAndroidKeepCallAliveEffect.js.map +1 -1
  30. package/dist/commonjs/index.js +0 -1
  31. package/dist/commonjs/index.js.map +1 -1
  32. package/dist/commonjs/modules/call-manager/CallManager.js +0 -26
  33. package/dist/commonjs/modules/call-manager/CallManager.js.map +1 -1
  34. package/dist/commonjs/providers/StreamCall/index.js +6 -6
  35. package/dist/commonjs/providers/StreamCall/index.js.map +1 -1
  36. package/dist/commonjs/utils/StreamVideoRN/index.js +21 -33
  37. package/dist/commonjs/utils/StreamVideoRN/index.js.map +1 -1
  38. package/dist/commonjs/utils/hooks/index.js +0 -11
  39. package/dist/commonjs/utils/hooks/index.js.map +1 -1
  40. package/dist/commonjs/utils/internal/registerSDKGlobals.js +3 -52
  41. package/dist/commonjs/utils/internal/registerSDKGlobals.js.map +1 -1
  42. package/dist/commonjs/utils/push/android.js +202 -151
  43. package/dist/commonjs/utils/push/android.js.map +1 -1
  44. package/dist/commonjs/utils/push/internal/ios.js +34 -17
  45. package/dist/commonjs/utils/push/internal/ios.js.map +1 -1
  46. package/dist/commonjs/utils/push/internal/rxSubjects.js +45 -1
  47. package/dist/commonjs/utils/push/internal/rxSubjects.js.map +1 -1
  48. package/dist/commonjs/utils/push/internal/utils.js +20 -32
  49. package/dist/commonjs/utils/push/internal/utils.js.map +1 -1
  50. package/dist/commonjs/utils/push/ios.js.map +1 -1
  51. package/dist/commonjs/utils/push/libs/callkeep.js +17 -0
  52. package/dist/commonjs/utils/push/libs/callkeep.js.map +1 -0
  53. package/dist/commonjs/utils/push/libs/index.js +19 -8
  54. package/dist/commonjs/utils/push/libs/index.js.map +1 -1
  55. package/dist/commonjs/utils/push/libs/notifee/index.js +19 -0
  56. package/dist/commonjs/utils/push/libs/notifee/index.js.map +1 -1
  57. package/dist/commonjs/utils/push/libs/voipPushNotification.js +17 -0
  58. package/dist/commonjs/utils/push/libs/voipPushNotification.js.map +1 -0
  59. package/dist/commonjs/utils/push/setupIosCallKeepEvents.js +205 -0
  60. package/dist/commonjs/utils/push/setupIosCallKeepEvents.js.map +1 -0
  61. package/dist/commonjs/utils/push/setupIosVoipPushEvents.js +6 -7
  62. package/dist/commonjs/utils/push/setupIosVoipPushEvents.js.map +1 -1
  63. package/dist/commonjs/version.js +1 -1
  64. package/dist/commonjs/version.js.map +1 -1
  65. package/dist/module/components/Call/CallContent/CallContent.js +10 -4
  66. package/dist/module/components/Call/CallContent/CallContent.js.map +1 -1
  67. package/dist/module/components/Call/CallContent/RTCViewPipIOS.js +52 -16
  68. package/dist/module/components/Call/CallContent/RTCViewPipIOS.js.map +1 -1
  69. package/dist/module/components/Call/CallContent/RTCViewPipNative.js +27 -0
  70. package/dist/module/components/Call/CallContent/RTCViewPipNative.js.map +1 -1
  71. package/dist/module/components/Call/CallLayout/CallParticipantsGrid.js +19 -10
  72. package/dist/module/components/Call/CallLayout/CallParticipantsGrid.js.map +1 -1
  73. package/dist/module/components/Call/CallLayout/CallParticipantsSpotlight.js +15 -12
  74. package/dist/module/components/Call/CallLayout/CallParticipantsSpotlight.js.map +1 -1
  75. package/dist/module/components/Call/CallParticipantsList/CallParticipantsList.js +20 -5
  76. package/dist/module/components/Call/CallParticipantsList/CallParticipantsList.js.map +1 -1
  77. package/dist/module/hooks/push/index.js +2 -0
  78. package/dist/module/hooks/push/index.js.map +1 -1
  79. package/dist/module/hooks/push/useIosCallkeepWithCallingStateEffect.js +153 -0
  80. package/dist/module/hooks/push/useIosCallkeepWithCallingStateEffect.js.map +1 -0
  81. package/dist/module/hooks/push/useIosVoipPushEventsSetupEffect.js +31 -18
  82. package/dist/module/hooks/push/useIosVoipPushEventsSetupEffect.js.map +1 -1
  83. package/dist/module/hooks/push/useProcessPushCallEffect.js +60 -0
  84. package/dist/module/hooks/push/useProcessPushCallEffect.js.map +1 -0
  85. package/dist/module/hooks/useAndroidKeepCallAliveEffect.js +99 -66
  86. package/dist/module/hooks/useAndroidKeepCallAliveEffect.js.map +1 -1
  87. package/dist/module/index.js +0 -1
  88. package/dist/module/index.js.map +1 -1
  89. package/dist/module/modules/call-manager/CallManager.js +0 -26
  90. package/dist/module/modules/call-manager/CallManager.js.map +1 -1
  91. package/dist/module/providers/StreamCall/index.js +6 -6
  92. package/dist/module/providers/StreamCall/index.js.map +1 -1
  93. package/dist/module/utils/StreamVideoRN/index.js +21 -33
  94. package/dist/module/utils/StreamVideoRN/index.js.map +1 -1
  95. package/dist/module/utils/hooks/index.js +0 -1
  96. package/dist/module/utils/hooks/index.js.map +1 -1
  97. package/dist/module/utils/internal/registerSDKGlobals.js +3 -52
  98. package/dist/module/utils/internal/registerSDKGlobals.js.map +1 -1
  99. package/dist/module/utils/push/android.js +204 -153
  100. package/dist/module/utils/push/android.js.map +1 -1
  101. package/dist/module/utils/push/internal/ios.js +34 -17
  102. package/dist/module/utils/push/internal/ios.js.map +1 -1
  103. package/dist/module/utils/push/internal/rxSubjects.js +44 -0
  104. package/dist/module/utils/push/internal/rxSubjects.js.map +1 -1
  105. package/dist/module/utils/push/internal/utils.js +19 -29
  106. package/dist/module/utils/push/internal/utils.js.map +1 -1
  107. package/dist/module/utils/push/ios.js.map +1 -1
  108. package/dist/module/utils/push/libs/callkeep.js +11 -0
  109. package/dist/module/utils/push/libs/callkeep.js.map +1 -0
  110. package/dist/module/utils/push/libs/index.js +2 -1
  111. package/dist/module/utils/push/libs/index.js.map +1 -1
  112. package/dist/module/utils/push/libs/notifee/index.js +18 -0
  113. package/dist/module/utils/push/libs/notifee/index.js.map +1 -1
  114. package/dist/module/utils/push/libs/voipPushNotification.js +11 -0
  115. package/dist/module/utils/push/libs/voipPushNotification.js.map +1 -0
  116. package/dist/module/utils/push/setupIosCallKeepEvents.js +199 -0
  117. package/dist/module/utils/push/setupIosCallKeepEvents.js.map +1 -0
  118. package/dist/module/utils/push/setupIosVoipPushEvents.js +6 -7
  119. package/dist/module/utils/push/setupIosVoipPushEvents.js.map +1 -1
  120. package/dist/module/version.js +1 -1
  121. package/dist/module/version.js.map +1 -1
  122. package/dist/typescript/components/Call/CallContent/CallContent.d.ts.map +1 -1
  123. package/dist/typescript/components/Call/CallContent/RTCViewPipIOS.d.ts.map +1 -1
  124. package/dist/typescript/components/Call/CallContent/RTCViewPipNative.d.ts +18 -0
  125. package/dist/typescript/components/Call/CallContent/RTCViewPipNative.d.ts.map +1 -1
  126. package/dist/typescript/components/Call/CallLayout/CallParticipantsGrid.d.ts.map +1 -1
  127. package/dist/typescript/components/Call/CallLayout/CallParticipantsSpotlight.d.ts.map +1 -1
  128. package/dist/typescript/components/Call/CallParticipantsList/CallParticipantsList.d.ts.map +1 -1
  129. package/dist/typescript/hooks/push/index.d.ts.map +1 -1
  130. package/dist/typescript/hooks/push/useIosCallkeepWithCallingStateEffect.d.ts +5 -0
  131. package/dist/typescript/hooks/push/useIosCallkeepWithCallingStateEffect.d.ts.map +1 -0
  132. package/dist/typescript/hooks/push/useIosVoipPushEventsSetupEffect.d.ts.map +1 -1
  133. package/dist/typescript/hooks/push/useProcessPushCallEffect.d.ts +8 -0
  134. package/dist/typescript/hooks/push/useProcessPushCallEffect.d.ts.map +1 -0
  135. package/dist/typescript/hooks/useAndroidKeepCallAliveEffect.d.ts.map +1 -1
  136. package/dist/typescript/index.d.ts +0 -1
  137. package/dist/typescript/index.d.ts.map +1 -1
  138. package/dist/typescript/modules/call-manager/CallManager.d.ts +0 -5
  139. package/dist/typescript/modules/call-manager/CallManager.d.ts.map +1 -1
  140. package/dist/typescript/utils/StreamVideoRN/index.d.ts +2 -20
  141. package/dist/typescript/utils/StreamVideoRN/index.d.ts.map +1 -1
  142. package/dist/typescript/utils/StreamVideoRN/types.d.ts +29 -54
  143. package/dist/typescript/utils/StreamVideoRN/types.d.ts.map +1 -1
  144. package/dist/typescript/utils/hooks/index.d.ts +0 -1
  145. package/dist/typescript/utils/hooks/index.d.ts.map +1 -1
  146. package/dist/typescript/utils/internal/registerSDKGlobals.d.ts.map +1 -1
  147. package/dist/typescript/utils/push/android.d.ts +2 -1
  148. package/dist/typescript/utils/push/android.d.ts.map +1 -1
  149. package/dist/typescript/utils/push/internal/ios.d.ts.map +1 -1
  150. package/dist/typescript/utils/push/internal/rxSubjects.d.ts +33 -0
  151. package/dist/typescript/utils/push/internal/rxSubjects.d.ts.map +1 -1
  152. package/dist/typescript/utils/push/internal/utils.d.ts +1 -8
  153. package/dist/typescript/utils/push/internal/utils.d.ts.map +1 -1
  154. package/dist/typescript/utils/push/ios.d.ts +2 -1
  155. package/dist/typescript/utils/push/ios.d.ts.map +1 -1
  156. package/dist/typescript/utils/push/libs/callkeep.d.ts +3 -0
  157. package/dist/typescript/utils/push/libs/callkeep.d.ts.map +1 -0
  158. package/dist/typescript/utils/push/libs/index.d.ts +2 -1
  159. package/dist/typescript/utils/push/libs/index.d.ts.map +1 -1
  160. package/dist/typescript/utils/push/libs/notifee/index.d.ts +1 -0
  161. package/dist/typescript/utils/push/libs/notifee/index.d.ts.map +1 -1
  162. package/dist/typescript/utils/push/libs/voipPushNotification.d.ts +3 -0
  163. package/dist/typescript/utils/push/libs/voipPushNotification.d.ts.map +1 -0
  164. package/dist/typescript/utils/push/setupIosCallKeepEvents.d.ts +6 -0
  165. package/dist/typescript/utils/push/setupIosCallKeepEvents.d.ts.map +1 -0
  166. package/dist/typescript/utils/push/setupIosVoipPushEvents.d.ts.map +1 -1
  167. package/dist/typescript/version.d.ts +1 -1
  168. package/dist/typescript/version.d.ts.map +1 -1
  169. package/expo-config-plugin/dist/withAndroidManifest.js +33 -1
  170. package/expo-config-plugin/dist/withAndroidPermissions.js +7 -2
  171. package/expo-config-plugin/dist/withAppDelegate.js +197 -19
  172. package/expo-config-plugin/dist/withMainActivity.js +1 -1
  173. package/expo-config-plugin/dist/withiOSInfoPlist.js +3 -2
  174. package/ios/PictureInPicture/PictureInPictureAvatarView.swift +273 -0
  175. package/ios/PictureInPicture/PictureInPictureConnectionQualityIndicator.swift +162 -0
  176. package/ios/PictureInPicture/PictureInPictureContent.swift +173 -0
  177. package/ios/PictureInPicture/PictureInPictureContentState.swift +123 -0
  178. package/ios/PictureInPicture/PictureInPictureDelegateProxy.swift +89 -0
  179. package/ios/PictureInPicture/PictureInPictureEnforcedStopAdapter.swift +166 -0
  180. package/ios/PictureInPicture/PictureInPictureLogger.swift +16 -0
  181. package/ios/PictureInPicture/PictureInPictureParticipantOverlayView.swift +217 -0
  182. package/ios/PictureInPicture/PictureInPictureReconnectionView.swift +193 -0
  183. package/ios/PictureInPicture/StreamAVPictureInPictureVideoCallViewController.swift +125 -7
  184. package/ios/PictureInPicture/StreamPictureInPictureController.swift +237 -63
  185. package/ios/PictureInPicture/StreamPictureInPictureControllerProtocol.swift +30 -0
  186. package/ios/PictureInPicture/StreamPictureInPictureVideoRenderer.swift +384 -12
  187. package/ios/RTCViewPip.swift +187 -21
  188. package/ios/RTCViewPipManager.mm +9 -0
  189. package/ios/RTCViewPipManager.swift +3 -3
  190. package/ios/StreamInCallManager.m +0 -2
  191. package/ios/StreamInCallManager.swift +7 -19
  192. package/ios/StreamVideoReactNative.h +4 -7
  193. package/ios/StreamVideoReactNative.m +82 -189
  194. package/package.json +19 -14
  195. package/src/components/Call/CallContent/CallContent.tsx +16 -8
  196. package/src/components/Call/CallContent/RTCViewPipIOS.tsx +81 -15
  197. package/src/components/Call/CallContent/RTCViewPipNative.tsx +36 -0
  198. package/src/components/Call/CallLayout/CallParticipantsGrid.tsx +28 -14
  199. package/src/components/Call/CallLayout/CallParticipantsSpotlight.tsx +19 -10
  200. package/src/components/Call/CallParticipantsList/CallParticipantsList.tsx +20 -5
  201. package/src/hooks/push/index.ts +2 -0
  202. package/src/hooks/push/useIosCallkeepWithCallingStateEffect.ts +235 -0
  203. package/src/hooks/push/useIosVoipPushEventsSetupEffect.ts +34 -21
  204. package/src/hooks/push/useProcessPushCallEffect.ts +108 -0
  205. package/src/hooks/useAndroidKeepCallAliveEffect.ts +120 -94
  206. package/src/index.ts +0 -1
  207. package/src/modules/call-manager/CallManager.ts +0 -36
  208. package/src/modules/call-manager/native-module.d.ts +0 -7
  209. package/src/providers/StreamCall/index.tsx +6 -6
  210. package/src/utils/StreamVideoRN/index.ts +30 -40
  211. package/src/utils/StreamVideoRN/types.ts +29 -56
  212. package/src/utils/hooks/index.ts +0 -1
  213. package/src/utils/internal/registerSDKGlobals.ts +4 -47
  214. package/src/utils/push/android.ts +309 -227
  215. package/src/utils/push/internal/ios.ts +44 -28
  216. package/src/utils/push/internal/rxSubjects.ts +61 -0
  217. package/src/utils/push/internal/utils.ts +26 -45
  218. package/src/utils/push/ios.ts +6 -1
  219. package/src/utils/push/libs/callkeep.ts +16 -0
  220. package/src/utils/push/libs/index.ts +2 -1
  221. package/src/utils/push/libs/notifee/index.ts +27 -0
  222. package/src/utils/push/libs/voipPushNotification.ts +17 -0
  223. package/src/utils/push/setupIosCallKeepEvents.ts +252 -0
  224. package/src/utils/push/setupIosVoipPushEvents.ts +7 -11
  225. package/src/version.ts +1 -1
  226. package/android/src/main/java/com/streamvideo/reactnative/keepalive/KeepAliveNotification.kt +0 -83
  227. package/android/src/main/java/com/streamvideo/reactnative/keepalive/StreamCallKeepAliveHeadlessService.kt +0 -149
  228. package/dist/commonjs/hooks/push/useCallingExpWithCallingStateEffect.js +0 -121
  229. package/dist/commonjs/hooks/push/useCallingExpWithCallingStateEffect.js.map +0 -1
  230. package/dist/commonjs/utils/hooks/useDebouncedValue.js +0 -24
  231. package/dist/commonjs/utils/hooks/useDebouncedValue.js.map +0 -1
  232. package/dist/commonjs/utils/internal/callingx/audioSessionPromise.js +0 -58
  233. package/dist/commonjs/utils/internal/callingx/audioSessionPromise.js.map +0 -1
  234. package/dist/commonjs/utils/internal/callingx/callingx.js +0 -109
  235. package/dist/commonjs/utils/internal/callingx/callingx.js.map +0 -1
  236. package/dist/commonjs/utils/keepCallAliveHeadlessTask.js +0 -48
  237. package/dist/commonjs/utils/keepCallAliveHeadlessTask.js.map +0 -1
  238. package/dist/commonjs/utils/push/libs/callingx.js +0 -75
  239. package/dist/commonjs/utils/push/libs/callingx.js.map +0 -1
  240. package/dist/commonjs/utils/push/setupCallingExpEvents.js +0 -108
  241. package/dist/commonjs/utils/push/setupCallingExpEvents.js.map +0 -1
  242. package/dist/module/hooks/push/useCallingExpWithCallingStateEffect.js +0 -114
  243. package/dist/module/hooks/push/useCallingExpWithCallingStateEffect.js.map +0 -1
  244. package/dist/module/utils/hooks/useDebouncedValue.js +0 -19
  245. package/dist/module/utils/hooks/useDebouncedValue.js.map +0 -1
  246. package/dist/module/utils/internal/callingx/audioSessionPromise.js +0 -51
  247. package/dist/module/utils/internal/callingx/audioSessionPromise.js.map +0 -1
  248. package/dist/module/utils/internal/callingx/callingx.js +0 -100
  249. package/dist/module/utils/internal/callingx/callingx.js.map +0 -1
  250. package/dist/module/utils/keepCallAliveHeadlessTask.js +0 -42
  251. package/dist/module/utils/keepCallAliveHeadlessTask.js.map +0 -1
  252. package/dist/module/utils/push/libs/callingx.js +0 -67
  253. package/dist/module/utils/push/libs/callingx.js.map +0 -1
  254. package/dist/module/utils/push/setupCallingExpEvents.js +0 -102
  255. package/dist/module/utils/push/setupCallingExpEvents.js.map +0 -1
  256. package/dist/typescript/hooks/push/useCallingExpWithCallingStateEffect.d.ts +0 -5
  257. package/dist/typescript/hooks/push/useCallingExpWithCallingStateEffect.d.ts.map +0 -1
  258. package/dist/typescript/utils/hooks/useDebouncedValue.d.ts +0 -8
  259. package/dist/typescript/utils/hooks/useDebouncedValue.d.ts.map +0 -1
  260. package/dist/typescript/utils/internal/callingx/audioSessionPromise.d.ts +0 -16
  261. package/dist/typescript/utils/internal/callingx/audioSessionPromise.d.ts.map +0 -1
  262. package/dist/typescript/utils/internal/callingx/callingx.d.ts +0 -14
  263. package/dist/typescript/utils/internal/callingx/callingx.d.ts.map +0 -1
  264. package/dist/typescript/utils/keepCallAliveHeadlessTask.d.ts +0 -10
  265. package/dist/typescript/utils/keepCallAliveHeadlessTask.d.ts.map +0 -1
  266. package/dist/typescript/utils/push/libs/callingx.d.ts +0 -9
  267. package/dist/typescript/utils/push/libs/callingx.d.ts.map +0 -1
  268. package/dist/typescript/utils/push/setupCallingExpEvents.d.ts +0 -8
  269. package/dist/typescript/utils/push/setupCallingExpEvents.d.ts.map +0 -1
  270. package/src/hooks/push/useCallingExpWithCallingStateEffect.ts +0 -147
  271. package/src/utils/hooks/useDebouncedValue.ts +0 -21
  272. package/src/utils/internal/callingx/audioSessionPromise.ts +0 -53
  273. package/src/utils/internal/callingx/callingx.ts +0 -146
  274. package/src/utils/keepCallAliveHeadlessTask.ts +0 -54
  275. package/src/utils/push/libs/callingx.ts +0 -90
  276. package/src/utils/push/setupCallingExpEvents.ts +0 -130
@@ -1,9 +1,10 @@
1
- import { Platform } from 'react-native';
1
+ import { AppState, NativeModules, Platform } from 'react-native';
2
+ import { getCallKeepLib, getVoipPushNotificationLib } from '../libs';
3
+ import { voipPushNotificationCallCId$ } from './rxSubjects';
2
4
  import { pushUnsubscriptionCallbacks } from './constants';
3
- import { canListenToWS, shouldCallBeClosed } from './utils';
5
+ import { canAddPushWSSubscriptionsRef, shouldCallBeEnded } from './utils';
4
6
  import { StreamVideoConfig } from '../../StreamVideoRN/types';
5
7
  import { videoLoggerSystem } from '@stream-io/video-client';
6
- import { getCallingxLib } from '../libs/callingx';
7
8
 
8
9
  export const onVoipNotificationReceived = async (
9
10
  notification: any,
@@ -31,57 +32,71 @@ export const onVoipNotificationReceived = async (
31
32
  "version": "v2"
32
33
  }
33
34
  } */
34
- const logger = videoLoggerSystem.getLogger(
35
- 'callingx - onVoipNotificationReceived',
36
- );
37
-
38
35
  const sender = notification?.stream?.sender;
39
36
  const type = notification?.stream?.type;
40
37
  // do not process any other notifications other than stream.video or ringing
41
38
  if (sender !== 'stream.video' && type !== 'call.ring') {
42
39
  return;
43
40
  }
44
-
45
41
  const call_cid = notification?.stream?.call_cid;
46
42
  if (!call_cid || Platform.OS !== 'ios' || !pushConfig.ios.pushProviderName) {
47
43
  return;
48
44
  }
49
-
50
- const callingx = getCallingxLib();
51
- if (callingx.isCallTracked(call_cid)) {
52
- //same call_cid is already tracked, so we skip the notification
53
- logger.debug(
54
- `the same call_cid ${call_cid} is already tracked, skipping the call.ring notification`,
55
- );
56
- return;
57
- }
58
-
45
+ const logger = videoLoggerSystem.getLogger('setupIosVoipPushEvents');
59
46
  const client = await pushConfig.createStreamVideoClient();
47
+
60
48
  if (!client) {
61
49
  logger.debug(
62
50
  'client not found, not processing call.ring voip push notification',
63
51
  );
64
52
  return;
65
53
  }
66
-
54
+ const shouldRejectCallWhenBusy = client['rejectCallWhenBusy'] ?? false;
55
+ if (shouldRejectCallWhenBusy) {
56
+ // inform the iOS native module that we should reject call when busy
57
+ NativeModules.StreamVideoReactNative.setShouldRejectCallWhenBusy(
58
+ shouldRejectCallWhenBusy,
59
+ );
60
+ }
67
61
  const callFromPush = await client.onRingingCall(call_cid);
68
-
62
+ let uuid = '';
63
+ try {
64
+ uuid =
65
+ await NativeModules?.StreamVideoReactNative?.getIncomingCallUUid(
66
+ call_cid,
67
+ );
68
+ } catch (error) {
69
+ logger.error('Error in getting call uuid from native module', error);
70
+ }
71
+ if (!uuid) {
72
+ logger.error(
73
+ `Not processing call.ring push notification, as no uuid found for call_cid: ${call_cid}`,
74
+ );
75
+ return;
76
+ }
77
+ const created_by_id = notification?.stream?.created_by_id;
78
+ const receiver_id = notification?.stream?.receiver_id;
69
79
  function closeCallIfNecessary() {
70
- const { mustEndCall, endCallReason } = shouldCallBeClosed(
80
+ const { mustEndCall, callkeepReason } = shouldCallBeEnded(
71
81
  callFromPush,
72
- notification?.stream,
82
+ created_by_id,
83
+ receiver_id,
73
84
  );
74
85
  if (mustEndCall) {
86
+ const callkeep = getCallKeepLib();
75
87
  logger.debug(
76
- `callingx.endCallWithReason for call_cid: ${call_cid} endCallReason: ${endCallReason}`,
88
+ `callkeep.reportEndCallWithUUID for uuid: ${uuid}, call_cid: ${call_cid}, reason: ${callkeepReason}`,
77
89
  );
78
- callingx.endCallWithReason(call_cid, endCallReason);
90
+ callkeep.reportEndCallWithUUID(uuid, callkeepReason);
91
+ const voipPushNotification = getVoipPushNotificationLib();
92
+ voipPushNotification.onVoipNotificationCompleted(uuid);
79
93
  return true;
80
94
  }
81
95
  return false;
82
96
  }
83
-
84
97
  const closed = closeCallIfNecessary();
98
+ const canListenToWS = () =>
99
+ canAddPushWSSubscriptionsRef.current && AppState.currentState !== 'active';
85
100
  if (!closed && canListenToWS()) {
86
101
  const unsubscribe = callFromPush.on('all', (event) => {
87
102
  const _canListenToWS = canListenToWS();
@@ -106,9 +121,10 @@ export const onVoipNotificationReceived = async (
106
121
  pushUnsubscriptionCallbacks.get(call_cid)?.forEach((cb) => cb());
107
122
  pushUnsubscriptionCallbacks.set(call_cid, [unsubscribe]);
108
123
  }
109
-
110
- // callingx event listeners (setupCallingExpEvents) will handle accept/reject
124
+ // send the info to this subject, it is listened by callkeep events
125
+ // callkeep events will then accept/reject the call
111
126
  logger.debug(
112
- `call_cid:${call_cid} received and processed from call.ring push notification`,
127
+ `call_cid:${call_cid} uuid:${uuid} received and processed from call.ring push notification`,
113
128
  );
129
+ voipPushNotificationCallCId$.next(call_cid);
114
130
  };
@@ -8,3 +8,64 @@ import type { NonRingingPushEvent } from '../../StreamVideoRN/types';
8
8
  export const pushNonRingingCallData$ = new BehaviorSubject<
9
9
  { cid: string; type: NonRingingPushEvent } | undefined
10
10
  >(undefined);
11
+
12
+ /**
13
+ * This rxjs subject is used to store the call cid of the accepted incoming call from push notification
14
+ * Note: it is should be subscribed only when a user has connected to the websocket of Stream
15
+ */
16
+ export const pushAcceptedIncomingCallCId$ = new BehaviorSubject<
17
+ string | undefined
18
+ >(undefined);
19
+
20
+ /**
21
+ * This rxjs subject is used to store the call cid of the tapped incoming call from push notification it is neither accepted nor rejected yet
22
+ * Note: it should be subscribed only when a user has connected to the websocket of Stream
23
+ */
24
+ export const pushTappedIncomingCallCId$ = new BehaviorSubject<
25
+ string | undefined
26
+ >(undefined);
27
+
28
+ /**
29
+ * This rxjs subject is used to store the call cid of the delivered incoming call from push notification it is neither accepted nor rejected yet
30
+ * Used so that the call is navigated to when app is open from being killed
31
+ * Note: it should be subscribed only when a user has connected to the websocket of Stream
32
+ */
33
+ export const pushAndroidBackgroundDeliveredIncomingCallCId$ =
34
+ new BehaviorSubject<string | undefined>(undefined);
35
+
36
+ /**
37
+ * This rxjs subject is used to store the call cid of the accepted incoming call from push notification
38
+ * Note: it should be subscribed only when a user has connected to the websocket of Stream
39
+ */
40
+ export const pushRejectedIncomingCallCId$ = new BehaviorSubject<
41
+ string | undefined
42
+ >(undefined);
43
+
44
+ /**
45
+ * This rxjs subject is used to store the call cid of the incoming call from ios voip pushkit notification
46
+ */
47
+ export const voipPushNotificationCallCId$ = new BehaviorSubject<
48
+ string | undefined
49
+ >(undefined);
50
+
51
+ /** The pair of cid of a call and its corresponding uuid created in the native side */
52
+ type CallkeepMap = {
53
+ uuid: string;
54
+ cid: string;
55
+ };
56
+
57
+ /*
58
+ * This rxjs subject should only used to store the CallkeepMap
59
+ * for the incoming call when on foreground
60
+ * or in other words, when we get didDisplayIncomingCall from callkeep lib
61
+ */
62
+ export const voipCallkeepCallOnForegroundMap$ = new BehaviorSubject<
63
+ CallkeepMap | undefined
64
+ >(undefined);
65
+
66
+ /*
67
+ * This rxjs subject should only used to store the CallkeepMap when it was accepted in the native dialer
68
+ */
69
+ export const voipCallkeepAcceptedCallOnNativeDialerMap$ = new BehaviorSubject<
70
+ CallkeepMap | undefined
71
+ >(undefined);
@@ -10,8 +10,6 @@ import type {
10
10
  } from '../../StreamVideoRN/types';
11
11
  import { onNewCallNotification } from '../../internal/newNotificationCallbacks';
12
12
  import { pushUnsubscriptionCallbacks } from './constants';
13
- import { AppState } from 'react-native';
14
- import type { EndCallReason } from '@stream-io/react-native-callingx';
15
13
 
16
14
  type PushConfig = NonNullable<StreamVideoConfig['push']>;
17
15
 
@@ -26,37 +24,44 @@ export const shouldCallBeEnded = (
26
24
  created_by_id: string | undefined,
27
25
  receiver_id: string | undefined,
28
26
  ) => {
27
+ /* callkeep reasons for ending a call
28
+ FAILED: 1,
29
+ REMOTE_ENDED: 2,
30
+ UNANSWERED: 3,
31
+ ANSWERED_ELSEWHERE: 4,
32
+ DECLINED_ELSEWHERE: 5,
33
+ MISSED: 6
34
+ */
29
35
  const callSession = callFromPush.state.session;
30
36
  const rejected_by = callSession?.rejected_by;
31
37
  const accepted_by = callSession?.accepted_by;
32
38
  let mustEndCall = false;
33
- let endCallReason: EndCallReason = 'unknown';
34
-
39
+ let callkeepReason = 0;
35
40
  if (created_by_id && rejected_by) {
36
41
  if (rejected_by[created_by_id]) {
37
- // call was cancelled by the caller before the receiver could answer
42
+ // call was cancelled by the caller
38
43
  mustEndCall = true;
39
- endCallReason = 'canceled';
44
+ callkeepReason = 2;
40
45
  }
41
46
  } else if (receiver_id && rejected_by) {
42
47
  if (rejected_by[receiver_id]) {
43
48
  // call was rejected by the receiver in some other device
44
49
  mustEndCall = true;
45
- endCallReason = 'rejected';
50
+ callkeepReason = 5;
46
51
  }
47
52
  } else if (receiver_id && accepted_by) {
48
53
  if (accepted_by[receiver_id]) {
49
54
  // call was accepted by the receiver in some other device
50
55
  mustEndCall = true;
51
- endCallReason = 'answeredElsewhere';
56
+ callkeepReason = 4;
52
57
  }
53
58
  }
54
59
  videoLoggerSystem
55
60
  .getLogger('shouldCallBeEnded')
56
61
  .debug(
57
- `callCid: ${callFromPush.cid} mustEndCall: ${mustEndCall} endCallReason: ${endCallReason}`,
62
+ `callCid: ${callFromPush.cid} mustEndCall: ${mustEndCall} callkeepReason: ${callkeepReason}`,
58
63
  );
59
- return { mustEndCall, endCallReason };
64
+ return { mustEndCall, callkeepReason };
60
65
  };
61
66
 
62
67
  /* An action for the notification or callkeep and app does not have JS context setup yet, so we need to do two steps:
@@ -99,10 +104,10 @@ export const processCallFromPush = async (
99
104
  pushConfig: PushConfig,
100
105
  ) => {
101
106
  let callFromPush: Call;
102
- const logger = videoLoggerSystem.getLogger('Callingx - processCallFromPush');
103
107
  try {
104
108
  callFromPush = await client.onRingingCall(call_cid);
105
109
  } catch (e) {
110
+ const logger = videoLoggerSystem.getLogger('processCallFromPush');
106
111
  logger.error('failed to fetch call from push notification', e);
107
112
  return;
108
113
  }
@@ -112,30 +117,24 @@ export const processCallFromPush = async (
112
117
  if (pushConfig.publishOptions) {
113
118
  callFromPush.updatePublishOptions(pushConfig.publishOptions);
114
119
  }
115
- logger.debug(
116
- `joining call from push notification with callCid: ${callFromPush.cid}`,
117
- );
118
- const callingState = callFromPush.state.callingState;
119
- if (
120
- callingState !== CallingState.RINGING &&
121
- callingState !== CallingState.IDLE
122
- ) {
123
- logger.debug(
124
- `skipping join call as it is not in ringing or idle state from push notification. callCid: ${callFromPush.cid}`,
120
+ videoLoggerSystem
121
+ .getLogger('processCallFromPush')
122
+ .debug(
123
+ `joining call from push notification with callCid: ${callFromPush.cid}`,
125
124
  );
126
- return;
127
- }
128
-
129
125
  await callFromPush.join();
130
126
  } else if (action === 'decline') {
131
127
  const canReject =
132
128
  callFromPush.state.callingState === CallingState.RINGING;
133
- logger.debug(
134
- `declining call from push notification with callCid: ${callFromPush.cid} reject: ${canReject}`,
135
- );
129
+ videoLoggerSystem
130
+ .getLogger('processCallFromPush')
131
+ .debug(
132
+ `declining call from push notification with callCid: ${callFromPush.cid} reject: ${canReject}`,
133
+ );
136
134
  await callFromPush.leave({ reject: canReject, reason: 'decline' });
137
135
  }
138
136
  } catch (e) {
137
+ const logger = videoLoggerSystem.getLogger('processCallFromPush');
139
138
  logger.warn(`failed to process ${action} call from push notification`, e);
140
139
  }
141
140
  };
@@ -192,21 +191,3 @@ export const clearPushWSEventSubscriptions = (call_cid: string) => {
192
191
  export const canAddPushWSSubscriptionsRef: CanAddPushWSSubscriptionsRef = {
193
192
  current: true,
194
193
  };
195
-
196
- export const canListenToWS = () =>
197
- canAddPushWSSubscriptionsRef.current && AppState.currentState !== 'active';
198
-
199
- export const shouldCallBeClosed = (
200
- call: Call,
201
- pushData: { [key: string]: string | object },
202
- ) => {
203
- const created_by_id = pushData?.created_by_id as string;
204
- const receiver_id = pushData?.receiver_id as string;
205
-
206
- const { mustEndCall, endCallReason } = shouldCallBeEnded(
207
- call,
208
- created_by_id,
209
- receiver_id,
210
- );
211
- return { mustEndCall, endCallReason };
212
- };
@@ -62,7 +62,12 @@ export const oniOSExpoNotificationEvent = (event: ExpoNotification) => {
62
62
  }
63
63
  };
64
64
 
65
- export const oniOSNotifeeEvent = ({ event }: { event: Event }) => {
65
+ export const oniOSNotifeeEvent = ({
66
+ event,
67
+ }: {
68
+ event: Event;
69
+ isBackground: boolean;
70
+ }) => {
66
71
  if (Platform.OS !== 'ios') return;
67
72
  const pushConfig = StreamVideoRN.getConfig().push;
68
73
  const { type, detail } = event;
@@ -0,0 +1,16 @@
1
+ export type RNCallKeepType = typeof import('react-native-callkeep').default;
2
+
3
+ let callkeep: RNCallKeepType | undefined;
4
+
5
+ try {
6
+ callkeep = require('react-native-callkeep').default;
7
+ } catch {}
8
+
9
+ export function getCallKeepLib() {
10
+ if (!callkeep) {
11
+ throw Error(
12
+ 'react-native-callkeep library is not installed. Please see https://github.com/react-native-webrtc/react-native-callkeep#Installation for installation instructions',
13
+ );
14
+ }
15
+ return callkeep;
16
+ }
@@ -1,8 +1,9 @@
1
1
  export * from './expoNotifications';
2
2
  export * from './firebaseMessaging';
3
3
  export * from './iosPushNotification';
4
+ export * from './voipPushNotification';
5
+ export * from './callkeep';
4
6
  export * from './notifee';
5
- export * from './callingx';
6
7
 
7
8
  /*
8
9
  NOTE: must keep each libs in different files
@@ -1,4 +1,6 @@
1
+ import { PermissionsAndroid } from 'react-native';
1
2
  import { lib, type Type } from './lib';
3
+ import { videoLoggerSystem } from '@stream-io/video-client';
2
4
 
3
5
  export type NotifeeLib = Type;
4
6
 
@@ -34,9 +36,34 @@ export function getNotifeeLibThrowIfNotInstalledForPush() {
34
36
  }
35
37
 
36
38
  export function getNotifeeLibNoThrowForKeepCallAlive() {
39
+ if (!lib) {
40
+ const logger = videoLoggerSystem.getLogger('getNotifeeLibNoThrow');
41
+ logger.info(
42
+ `${'@notifee/react-native library not installed. It is required to keep call alive in the background for Android. '}${INSTALLATION_INSTRUCTION}`,
43
+ );
44
+ }
37
45
  return lib;
38
46
  }
39
47
 
48
+ export async function getKeepCallAliveForegroundServiceTypes() {
49
+ const types: AndroidForegroundServiceType[] = [
50
+ AndroidForegroundServiceType.FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK,
51
+ ];
52
+ const hasCameraPermission = await PermissionsAndroid.check(
53
+ PermissionsAndroid.PERMISSIONS.CAMERA!,
54
+ );
55
+ if (hasCameraPermission) {
56
+ types.push(AndroidForegroundServiceType.FOREGROUND_SERVICE_TYPE_CAMERA);
57
+ }
58
+ const hasMicrophonePermission = await PermissionsAndroid.check(
59
+ PermissionsAndroid.PERMISSIONS.RECORD_AUDIO!,
60
+ );
61
+ if (hasMicrophonePermission) {
62
+ types.push(AndroidForegroundServiceType.FOREGROUND_SERVICE_TYPE_MICROPHONE);
63
+ }
64
+ return types;
65
+ }
66
+
40
67
  export function getIncomingCallForegroundServiceTypes() {
41
68
  const types: AndroidForegroundServiceType[] = [
42
69
  AndroidForegroundServiceType.FOREGROUND_SERVICE_TYPE_SHORT_SERVICE,
@@ -0,0 +1,17 @@
1
+ export type VoipPushNotificationType =
2
+ typeof import('react-native-voip-push-notification').default;
3
+
4
+ let voipPushNotification: VoipPushNotificationType | undefined;
5
+
6
+ try {
7
+ voipPushNotification = require('react-native-voip-push-notification').default;
8
+ } catch {}
9
+
10
+ export function getVoipPushNotificationLib() {
11
+ if (!voipPushNotification) {
12
+ throw Error(
13
+ "react-native-voip-push-notification library is not installed. Please install it using 'yarn add react-native-voip-push-notification' or 'npm i react-native-voip-push-notification --save'",
14
+ );
15
+ }
16
+ return voipPushNotification;
17
+ }
@@ -0,0 +1,252 @@
1
+ import {
2
+ pushAcceptedIncomingCallCId$,
3
+ voipCallkeepAcceptedCallOnNativeDialerMap$,
4
+ voipCallkeepCallOnForegroundMap$,
5
+ voipPushNotificationCallCId$,
6
+ } from './internal/rxSubjects';
7
+ import { RxUtils, videoLoggerSystem } from '@stream-io/video-client';
8
+ import { getCallKeepLib, getVoipPushNotificationLib } from './libs';
9
+ import type { StreamVideoConfig } from '../StreamVideoRN/types';
10
+ import {
11
+ clearPushWSEventSubscriptions,
12
+ processCallFromPushInBackground,
13
+ } from './internal/utils';
14
+ import { AppState, NativeModules, Platform } from 'react-native';
15
+ import { RTCAudioSession } from '@stream-io/react-native-webrtc';
16
+ import { setPushLogoutCallback } from '../internal/pushLogoutCallback';
17
+
18
+ type PushConfig = NonNullable<StreamVideoConfig['push']>;
19
+
20
+ /**
21
+ * This hook is used to listen to callkeep events and do the necessary actions
22
+ */
23
+ export function setupIosCallKeepEvents(
24
+ pushConfig: NonNullable<StreamVideoConfig['push']>,
25
+ ) {
26
+ if (Platform.OS !== 'ios' || !pushConfig.ios.pushProviderName) {
27
+ return;
28
+ }
29
+ if (!pushConfig.android.incomingCallChannel) {
30
+ // TODO: remove this check and find a better way once we have telecom integration for android
31
+ videoLoggerSystem
32
+ .getLogger('setupIosCallKeepEvents')
33
+ .debug(
34
+ 'android incomingCallChannel is not defined, so skipping the setupIosCallKeepEvents',
35
+ );
36
+ return;
37
+ }
38
+ const logger = videoLoggerSystem.getLogger('setupIosCallKeepEvents');
39
+ const callkeep = getCallKeepLib();
40
+
41
+ async function getCallCid(callUUID: string): Promise<string | undefined> {
42
+ try {
43
+ const call_cid =
44
+ await NativeModules.StreamVideoReactNative.getIncomingCallCid(callUUID);
45
+ // in a case that voipPushNotificationCallCId$ is empty (this should not happen as voipPushNotificationCallCId$ is updated in push reception)]
46
+ // update it with this call_cid
47
+ const voipPushNotificationCallCId = RxUtils.getCurrentValue(
48
+ voipPushNotificationCallCId$,
49
+ );
50
+ if (!voipPushNotificationCallCId) {
51
+ logger.debug(
52
+ `voipPushNotificationCallCId$ is empty, updating it with the call_cid: ${call_cid} for callUUID: ${callUUID}`,
53
+ );
54
+ voipPushNotificationCallCId$.next(call_cid);
55
+ }
56
+ return call_cid;
57
+ } catch {
58
+ logger.debug(
59
+ `Error in getting call cid from native module for callUUID: ${callUUID} - probably the call was already processed, so ignoring this callkeep event`,
60
+ );
61
+ }
62
+ return undefined;
63
+ }
64
+
65
+ function answerCall(callUUID: string) {
66
+ getCallCid(callUUID).then((call_cid) => {
67
+ logger.debug(`answerCall event with call_cid: ${call_cid}`);
68
+ iosCallkeepAcceptCall(call_cid, callUUID);
69
+ });
70
+ }
71
+
72
+ function endCall(callUUID: string) {
73
+ getCallCid(callUUID).then((call_cid) => {
74
+ logger.debug(`endCall event with call_cid: ${call_cid}`);
75
+ iosCallkeepRejectCall(call_cid, callUUID, pushConfig!);
76
+ });
77
+ }
78
+
79
+ /**
80
+ * CallKeep / CallKit audio-session events -> WebRTC (iOS)
81
+ *
82
+ * iOS CallKit is the authority that *activates* and *deactivates* the underlying `AVAudioSession`
83
+ * when a call is answered/ended from the system UI (lock screen, Call UI, Bluetooth, etc).
84
+ *
85
+ * WebRTC on iOS wraps `AVAudioSession` with `RTCAudioSession` and its AudioDeviceModule relies on
86
+ * being notified of those lifecycle transitions to correctly start/stop audio I/O and keep its
87
+ * internal activation state consistent (e.g. activation count, playout/recording start).
88
+ *
89
+ * If these callbacks don’t reach WebRTC, answering via the native dialer UI can result in:
90
+ * - no microphone capture / one-way audio
91
+ * - silent playout until the app forces an audio reconfiguration
92
+ * - flaky audio routing (speaker/earpiece/Bluetooth) across subsequent calls
93
+ *
94
+ * We forward CallKeep’s `didActivateAudioSession` / `didDeactivateAudioSession` events to WebRTC’s
95
+ * `RTCAudioSession.audioSessionDidActivate()` / `audioSessionDidDeactivate()` methods.
96
+ */
97
+ function didActivateAudioSession() {
98
+ logger.debug('didActivateAudioSession');
99
+ RTCAudioSession.audioSessionDidActivate();
100
+ }
101
+
102
+ function didDeactivateAudioSession() {
103
+ logger.debug('didDeactivateAudioSession');
104
+ RTCAudioSession.audioSessionDidDeactivate();
105
+ }
106
+
107
+ function didDisplayIncomingCall(callUUID: string, payload: object) {
108
+ const voipPushNotification = getVoipPushNotificationLib();
109
+ // @ts-expect-error - call_cid is not part of RNCallKeepEventPayload
110
+ const call_cid = payload?.call_cid as string | undefined;
111
+ logger.debug(
112
+ `didDisplayIncomingCall event with callUUID: ${callUUID} call_cid: ${call_cid}`,
113
+ );
114
+ if (call_cid) {
115
+ if (AppState.currentState === 'background') {
116
+ processCallFromPushInBackground(
117
+ pushConfig!,
118
+ call_cid,
119
+ 'backgroundDelivered',
120
+ );
121
+ }
122
+ voipCallkeepCallOnForegroundMap$.next({
123
+ uuid: callUUID,
124
+ cid: call_cid,
125
+ });
126
+ }
127
+ voipPushNotification.onVoipNotificationCompleted(callUUID);
128
+ }
129
+
130
+ const { remove: removeAnswerCall } = callkeep.addEventListener(
131
+ 'answerCall',
132
+ ({ callUUID }) => {
133
+ answerCall(callUUID);
134
+ },
135
+ );
136
+ const { remove: removeEndCall } = callkeep.addEventListener(
137
+ 'endCall',
138
+ ({ callUUID }) => {
139
+ endCall(callUUID);
140
+ },
141
+ );
142
+
143
+ const { remove: removeDisplayIncomingCall } = callkeep.addEventListener(
144
+ 'didDisplayIncomingCall',
145
+ ({ callUUID, payload }) => {
146
+ didDisplayIncomingCall(callUUID, payload);
147
+ },
148
+ );
149
+
150
+ const { remove: removeDidActivateAudioSession } = callkeep.addEventListener(
151
+ 'didActivateAudioSession',
152
+ () => {
153
+ didActivateAudioSession();
154
+ },
155
+ );
156
+
157
+ const { remove: removeDidDeactivateAudioSession } = callkeep.addEventListener(
158
+ 'didDeactivateAudioSession',
159
+ () => {
160
+ didDeactivateAudioSession();
161
+ },
162
+ );
163
+
164
+ const { remove: removeDidLoadWithEvents } = callkeep.addEventListener(
165
+ 'didLoadWithEvents',
166
+ (events) => {
167
+ if (!events || !Array.isArray(events) || events.length < 1) {
168
+ return;
169
+ }
170
+
171
+ events.forEach((event) => {
172
+ const { name, data } = event;
173
+ if (name === 'RNCallKeepDidDisplayIncomingCall') {
174
+ didDisplayIncomingCall(data.callUUID, data.payload);
175
+ } else if (name === 'RNCallKeepPerformAnswerCallAction') {
176
+ answerCall(data.callUUID);
177
+ } else if (name === 'RNCallKeepPerformEndCallAction') {
178
+ endCall(data.callUUID);
179
+ } else if (name === 'RNCallKeepDidActivateAudioSession') {
180
+ didActivateAudioSession();
181
+ } else if (name === 'RNCallKeepDidDeactivateAudioSession') {
182
+ didDeactivateAudioSession();
183
+ }
184
+ });
185
+ },
186
+ );
187
+
188
+ setPushLogoutCallback(async () => {
189
+ removeAnswerCall();
190
+ removeEndCall();
191
+ removeDisplayIncomingCall();
192
+ removeDidActivateAudioSession();
193
+ removeDidDeactivateAudioSession();
194
+ removeDidLoadWithEvents();
195
+ });
196
+ }
197
+
198
+ const iosCallkeepAcceptCall = (
199
+ call_cid: string | undefined,
200
+ callUUIDFromCallkeep: string,
201
+ ) => {
202
+ if (!shouldProcessCallFromCallkeep(call_cid, callUUIDFromCallkeep)) {
203
+ return;
204
+ }
205
+ clearPushWSEventSubscriptions(call_cid);
206
+ // to call end callkeep later if ended in app and not through callkeep
207
+ voipCallkeepAcceptedCallOnNativeDialerMap$.next({
208
+ uuid: callUUIDFromCallkeep,
209
+ cid: call_cid,
210
+ });
211
+ // to process the call in the app
212
+ pushAcceptedIncomingCallCId$.next(call_cid);
213
+ // no need to keep these references anymore
214
+ voipCallkeepCallOnForegroundMap$.next(undefined);
215
+ };
216
+
217
+ const iosCallkeepRejectCall = async (
218
+ call_cid: string | undefined,
219
+ callUUIDFromCallkeep: string,
220
+ pushConfig: PushConfig,
221
+ ) => {
222
+ if (!shouldProcessCallFromCallkeep(call_cid, callUUIDFromCallkeep)) {
223
+ return;
224
+ }
225
+ clearPushWSEventSubscriptions(call_cid);
226
+ // remove the references if the call_cid matches
227
+ const voipPushNotificationCallCId = RxUtils.getCurrentValue(
228
+ voipPushNotificationCallCId$,
229
+ );
230
+ if (voipPushNotificationCallCId === call_cid) {
231
+ voipCallkeepAcceptedCallOnNativeDialerMap$.next(undefined);
232
+ voipCallkeepCallOnForegroundMap$.next(undefined);
233
+ voipPushNotificationCallCId$.next(undefined);
234
+ }
235
+
236
+ await processCallFromPushInBackground(pushConfig, call_cid, 'decline');
237
+ await NativeModules.StreamVideoReactNative?.removeIncomingCall(call_cid);
238
+ };
239
+
240
+ /**
241
+ * Helper function to determine if the answer/end call event from callkeep must be processed
242
+ * Just checks if we have a valid call_cid and acts as a type guard for call_cid
243
+ */
244
+ const shouldProcessCallFromCallkeep = (
245
+ call_cid: string | undefined,
246
+ callUUIDFromCallkeep: string,
247
+ ): call_cid is string => {
248
+ if (!call_cid || !callUUIDFromCallkeep) {
249
+ return false;
250
+ }
251
+ return true;
252
+ };