@stream-io/video-react-native-sdk 1.30.5 → 1.31.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.
- package/CHANGELOG.md +11 -0
- package/android/src/main/AndroidManifest.xml +8 -1
- package/android/src/main/AndroidManifestNew.xml +11 -0
- package/android/src/main/java/com/streamvideo/reactnative/StreamVideoReactNativeModule.kt +127 -5
- package/android/src/main/java/com/streamvideo/reactnative/audio/utils/WebRtcAudioUtils.kt +70 -6
- package/android/src/main/java/com/streamvideo/reactnative/callmanager/StreamInCallManagerModule.kt +6 -4
- package/android/src/main/java/com/streamvideo/reactnative/keepalive/KeepAliveNotification.kt +83 -0
- package/android/src/main/java/com/streamvideo/reactnative/keepalive/StreamCallKeepAliveHeadlessService.kt +149 -0
- package/android/src/main/java/com/streamvideo/reactnative/screenshare/ScreenAudioCapture.kt +111 -0
- package/dist/commonjs/components/Call/CallControls/ScreenShareToggleButton.js +3 -2
- package/dist/commonjs/components/Call/CallControls/ScreenShareToggleButton.js.map +1 -1
- package/dist/commonjs/hooks/index.js +11 -0
- package/dist/commonjs/hooks/index.js.map +1 -1
- package/dist/commonjs/hooks/push/index.js +0 -2
- package/dist/commonjs/hooks/push/index.js.map +1 -1
- package/dist/commonjs/hooks/push/useCallingExpWithCallingStateEffect.js +144 -0
- package/dist/commonjs/hooks/push/useCallingExpWithCallingStateEffect.js.map +1 -0
- package/dist/commonjs/hooks/push/useIosVoipPushEventsSetupEffect.js +18 -31
- package/dist/commonjs/hooks/push/useIosVoipPushEventsSetupEffect.js.map +1 -1
- package/dist/commonjs/hooks/useAndroidKeepCallAliveEffect.js +64 -97
- package/dist/commonjs/hooks/useAndroidKeepCallAliveEffect.js.map +1 -1
- package/dist/commonjs/hooks/useScreenShareAudioMixing.js +126 -0
- package/dist/commonjs/hooks/useScreenShareAudioMixing.js.map +1 -0
- package/dist/commonjs/hooks/useScreenShareButton.js +57 -3
- package/dist/commonjs/hooks/useScreenShareButton.js.map +1 -1
- package/dist/commonjs/index.js +1 -0
- package/dist/commonjs/index.js.map +1 -1
- package/dist/commonjs/modules/ScreenShareAudioManager.js +54 -0
- package/dist/commonjs/modules/ScreenShareAudioManager.js.map +1 -0
- package/dist/commonjs/modules/call-manager/CallManager.js +26 -0
- package/dist/commonjs/modules/call-manager/CallManager.js.map +1 -1
- package/dist/commonjs/providers/StreamCall/index.js +16 -6
- package/dist/commonjs/providers/StreamCall/index.js.map +1 -1
- package/dist/commonjs/utils/StreamVideoRN/index.js +35 -21
- package/dist/commonjs/utils/StreamVideoRN/index.js.map +1 -1
- package/dist/commonjs/utils/internal/callingx/audioSessionPromise.js +68 -0
- package/dist/commonjs/utils/internal/callingx/audioSessionPromise.js.map +1 -0
- package/dist/commonjs/utils/internal/callingx/callingx.js +150 -0
- package/dist/commonjs/utils/internal/callingx/callingx.js.map +1 -0
- package/dist/commonjs/utils/internal/registerSDKGlobals.js +53 -3
- package/dist/commonjs/utils/internal/registerSDKGlobals.js.map +1 -1
- package/dist/commonjs/utils/keepCallAliveHeadlessTask.js +48 -0
- package/dist/commonjs/utils/keepCallAliveHeadlessTask.js.map +1 -0
- package/dist/commonjs/utils/push/android.js +135 -202
- package/dist/commonjs/utils/push/android.js.map +1 -1
- package/dist/commonjs/utils/push/internal/ios.js +17 -34
- package/dist/commonjs/utils/push/internal/ios.js.map +1 -1
- package/dist/commonjs/utils/push/internal/rxSubjects.js +1 -45
- package/dist/commonjs/utils/push/internal/rxSubjects.js.map +1 -1
- package/dist/commonjs/utils/push/internal/utils.js +71 -53
- package/dist/commonjs/utils/push/internal/utils.js.map +1 -1
- package/dist/commonjs/utils/push/ios.js.map +1 -1
- package/dist/commonjs/utils/push/libs/callingx.js +75 -0
- package/dist/commonjs/utils/push/libs/callingx.js.map +1 -0
- package/dist/commonjs/utils/push/libs/index.js +8 -19
- package/dist/commonjs/utils/push/libs/index.js.map +1 -1
- package/dist/commonjs/utils/push/libs/notifee/index.js +0 -19
- package/dist/commonjs/utils/push/libs/notifee/index.js.map +1 -1
- package/dist/commonjs/utils/push/setupCallingExpEvents.js +105 -0
- package/dist/commonjs/utils/push/setupCallingExpEvents.js.map +1 -0
- package/dist/commonjs/utils/push/setupIosVoipPushEvents.js +7 -6
- package/dist/commonjs/utils/push/setupIosVoipPushEvents.js.map +1 -1
- package/dist/commonjs/version.js +1 -1
- package/dist/commonjs/version.js.map +1 -1
- package/dist/module/components/Call/CallControls/ScreenShareToggleButton.js +3 -2
- package/dist/module/components/Call/CallControls/ScreenShareToggleButton.js.map +1 -1
- package/dist/module/hooks/index.js +1 -0
- package/dist/module/hooks/index.js.map +1 -1
- package/dist/module/hooks/push/index.js +0 -2
- package/dist/module/hooks/push/index.js.map +1 -1
- package/dist/module/hooks/push/useCallingExpWithCallingStateEffect.js +137 -0
- package/dist/module/hooks/push/useCallingExpWithCallingStateEffect.js.map +1 -0
- package/dist/module/hooks/push/useIosVoipPushEventsSetupEffect.js +18 -31
- package/dist/module/hooks/push/useIosVoipPushEventsSetupEffect.js.map +1 -1
- package/dist/module/hooks/useAndroidKeepCallAliveEffect.js +66 -99
- package/dist/module/hooks/useAndroidKeepCallAliveEffect.js.map +1 -1
- package/dist/module/hooks/useScreenShareAudioMixing.js +119 -0
- package/dist/module/hooks/useScreenShareAudioMixing.js.map +1 -0
- package/dist/module/hooks/useScreenShareButton.js +57 -3
- package/dist/module/hooks/useScreenShareButton.js.map +1 -1
- package/dist/module/index.js +1 -0
- package/dist/module/index.js.map +1 -1
- package/dist/module/modules/ScreenShareAudioManager.js +47 -0
- package/dist/module/modules/ScreenShareAudioManager.js.map +1 -0
- package/dist/module/modules/call-manager/CallManager.js +26 -0
- package/dist/module/modules/call-manager/CallManager.js.map +1 -1
- package/dist/module/providers/StreamCall/index.js +16 -6
- package/dist/module/providers/StreamCall/index.js.map +1 -1
- package/dist/module/utils/StreamVideoRN/index.js +35 -21
- package/dist/module/utils/StreamVideoRN/index.js.map +1 -1
- package/dist/module/utils/internal/callingx/audioSessionPromise.js +61 -0
- package/dist/module/utils/internal/callingx/audioSessionPromise.js.map +1 -0
- package/dist/module/utils/internal/callingx/callingx.js +140 -0
- package/dist/module/utils/internal/callingx/callingx.js.map +1 -0
- package/dist/module/utils/internal/registerSDKGlobals.js +53 -3
- package/dist/module/utils/internal/registerSDKGlobals.js.map +1 -1
- package/dist/module/utils/keepCallAliveHeadlessTask.js +42 -0
- package/dist/module/utils/keepCallAliveHeadlessTask.js.map +1 -0
- package/dist/module/utils/push/android.js +137 -204
- package/dist/module/utils/push/android.js.map +1 -1
- package/dist/module/utils/push/internal/ios.js +17 -34
- package/dist/module/utils/push/internal/ios.js.map +1 -1
- package/dist/module/utils/push/internal/rxSubjects.js +0 -44
- package/dist/module/utils/push/internal/rxSubjects.js.map +1 -1
- package/dist/module/utils/push/internal/utils.js +67 -50
- package/dist/module/utils/push/internal/utils.js.map +1 -1
- package/dist/module/utils/push/ios.js.map +1 -1
- package/dist/module/utils/push/libs/callingx.js +67 -0
- package/dist/module/utils/push/libs/callingx.js.map +1 -0
- package/dist/module/utils/push/libs/index.js +1 -2
- package/dist/module/utils/push/libs/index.js.map +1 -1
- package/dist/module/utils/push/libs/notifee/index.js +0 -18
- package/dist/module/utils/push/libs/notifee/index.js.map +1 -1
- package/dist/module/utils/push/setupCallingExpEvents.js +99 -0
- package/dist/module/utils/push/setupCallingExpEvents.js.map +1 -0
- package/dist/module/utils/push/setupIosVoipPushEvents.js +7 -6
- package/dist/module/utils/push/setupIosVoipPushEvents.js.map +1 -1
- package/dist/module/version.js +1 -1
- package/dist/module/version.js.map +1 -1
- package/dist/typescript/components/Call/CallControls/ScreenShareToggleButton.d.ts +6 -1
- package/dist/typescript/components/Call/CallControls/ScreenShareToggleButton.d.ts.map +1 -1
- package/dist/typescript/hooks/index.d.ts +1 -0
- package/dist/typescript/hooks/index.d.ts.map +1 -1
- package/dist/typescript/hooks/push/index.d.ts.map +1 -1
- package/dist/typescript/hooks/push/useCallingExpWithCallingStateEffect.d.ts +5 -0
- package/dist/typescript/hooks/push/useCallingExpWithCallingStateEffect.d.ts.map +1 -0
- package/dist/typescript/hooks/push/useIosVoipPushEventsSetupEffect.d.ts.map +1 -1
- package/dist/typescript/hooks/useAndroidKeepCallAliveEffect.d.ts.map +1 -1
- package/dist/typescript/hooks/useScreenShareAudioMixing.d.ts +14 -0
- package/dist/typescript/hooks/useScreenShareAudioMixing.d.ts.map +1 -0
- package/dist/typescript/hooks/useScreenShareButton.d.ts +39 -2
- package/dist/typescript/hooks/useScreenShareButton.d.ts.map +1 -1
- package/dist/typescript/index.d.ts +1 -0
- package/dist/typescript/index.d.ts.map +1 -1
- package/dist/typescript/modules/ScreenShareAudioManager.d.ts +28 -0
- package/dist/typescript/modules/ScreenShareAudioManager.d.ts.map +1 -0
- package/dist/typescript/modules/call-manager/CallManager.d.ts +5 -0
- package/dist/typescript/modules/call-manager/CallManager.d.ts.map +1 -1
- package/dist/typescript/providers/StreamCall/index.d.ts.map +1 -1
- package/dist/typescript/utils/StreamVideoRN/index.d.ts +22 -2
- package/dist/typescript/utils/StreamVideoRN/index.d.ts.map +1 -1
- package/dist/typescript/utils/StreamVideoRN/types.d.ts +59 -25
- package/dist/typescript/utils/StreamVideoRN/types.d.ts.map +1 -1
- package/dist/typescript/utils/internal/callingx/audioSessionPromise.d.ts +16 -0
- package/dist/typescript/utils/internal/callingx/audioSessionPromise.d.ts.map +1 -0
- package/dist/typescript/utils/internal/callingx/callingx.d.ts +18 -0
- package/dist/typescript/utils/internal/callingx/callingx.d.ts.map +1 -0
- package/dist/typescript/utils/internal/registerSDKGlobals.d.ts.map +1 -1
- package/dist/typescript/utils/keepCallAliveHeadlessTask.d.ts +10 -0
- package/dist/typescript/utils/keepCallAliveHeadlessTask.d.ts.map +1 -0
- package/dist/typescript/utils/push/android.d.ts +1 -2
- package/dist/typescript/utils/push/android.d.ts.map +1 -1
- package/dist/typescript/utils/push/internal/ios.d.ts.map +1 -1
- package/dist/typescript/utils/push/internal/rxSubjects.d.ts +0 -33
- package/dist/typescript/utils/push/internal/rxSubjects.d.ts.map +1 -1
- package/dist/typescript/utils/push/internal/utils.d.ts +14 -8
- package/dist/typescript/utils/push/internal/utils.d.ts.map +1 -1
- package/dist/typescript/utils/push/ios.d.ts +1 -2
- package/dist/typescript/utils/push/ios.d.ts.map +1 -1
- package/dist/typescript/utils/push/libs/callingx.d.ts +9 -0
- package/dist/typescript/utils/push/libs/callingx.d.ts.map +1 -0
- package/dist/typescript/utils/push/libs/firebaseMessaging/index.d.ts +16 -2
- package/dist/typescript/utils/push/libs/firebaseMessaging/index.d.ts.map +1 -1
- package/dist/typescript/utils/push/libs/index.d.ts +1 -2
- package/dist/typescript/utils/push/libs/index.d.ts.map +1 -1
- package/dist/typescript/utils/push/libs/notifee/index.d.ts +0 -1
- package/dist/typescript/utils/push/libs/notifee/index.d.ts.map +1 -1
- package/dist/typescript/utils/push/setupCallingExpEvents.d.ts +8 -0
- package/dist/typescript/utils/push/setupCallingExpEvents.d.ts.map +1 -0
- package/dist/typescript/utils/push/setupIosVoipPushEvents.d.ts.map +1 -1
- package/dist/typescript/version.d.ts +1 -1
- package/dist/typescript/version.d.ts.map +1 -1
- package/expo-config-plugin/dist/withAndroidManifest.js +1 -33
- package/expo-config-plugin/dist/withAndroidPermissions.js +2 -7
- package/expo-config-plugin/dist/withAppDelegate.js +19 -197
- package/expo-config-plugin/dist/withMainActivity.js +1 -1
- package/expo-config-plugin/dist/withiOSInfoPlist.js +2 -3
- package/ios/StreamInCallManager.m +2 -0
- package/ios/StreamInCallManager.swift +19 -7
- package/ios/StreamVideoReactNative.h +7 -4
- package/ios/StreamVideoReactNative.m +282 -86
- package/package.json +13 -18
- package/src/components/Call/CallControls/ScreenShareToggleButton.tsx +11 -1
- package/src/hooks/index.ts +1 -0
- package/src/hooks/push/index.ts +0 -2
- package/src/hooks/push/useCallingExpWithCallingStateEffect.ts +189 -0
- package/src/hooks/push/useIosVoipPushEventsSetupEffect.ts +21 -34
- package/src/hooks/useAndroidKeepCallAliveEffect.ts +94 -120
- package/src/hooks/useScreenShareAudioMixing.ts +130 -0
- package/src/hooks/useScreenShareButton.ts +87 -2
- package/src/index.ts +1 -0
- package/src/modules/ScreenShareAudioManager.ts +49 -0
- package/src/modules/call-manager/CallManager.ts +36 -0
- package/src/modules/call-manager/native-module.d.ts +7 -0
- package/src/providers/StreamCall/index.tsx +17 -6
- package/src/utils/StreamVideoRN/index.ts +42 -30
- package/src/utils/StreamVideoRN/types.ts +61 -25
- package/src/utils/internal/callingx/audioSessionPromise.ts +65 -0
- package/src/utils/internal/callingx/callingx.ts +194 -0
- package/src/utils/internal/registerSDKGlobals.ts +52 -4
- package/src/utils/keepCallAliveHeadlessTask.ts +54 -0
- package/src/utils/push/android.ts +198 -311
- package/src/utils/push/internal/ios.ts +28 -44
- package/src/utils/push/internal/rxSubjects.ts +0 -61
- package/src/utils/push/internal/utils.ts +108 -64
- package/src/utils/push/ios.ts +1 -6
- package/src/utils/push/libs/callingx.ts +89 -0
- package/src/utils/push/libs/index.ts +1 -2
- package/src/utils/push/libs/notifee/index.ts +0 -27
- package/src/utils/push/setupCallingExpEvents.ts +135 -0
- package/src/utils/push/setupIosVoipPushEvents.ts +11 -7
- package/src/version.ts +1 -1
- package/android/src/main/java/com/streamvideo/reactnative/util/CallAliveServiceChecker.kt +0 -95
- package/dist/commonjs/hooks/push/useIosCallkeepWithCallingStateEffect.js +0 -160
- package/dist/commonjs/hooks/push/useIosCallkeepWithCallingStateEffect.js.map +0 -1
- package/dist/commonjs/hooks/push/useProcessPushCallEffect.js +0 -67
- package/dist/commonjs/hooks/push/useProcessPushCallEffect.js.map +0 -1
- package/dist/commonjs/utils/push/libs/callkeep.js +0 -17
- package/dist/commonjs/utils/push/libs/callkeep.js.map +0 -1
- package/dist/commonjs/utils/push/libs/voipPushNotification.js +0 -17
- package/dist/commonjs/utils/push/libs/voipPushNotification.js.map +0 -1
- package/dist/commonjs/utils/push/setupIosCallKeepEvents.js +0 -205
- package/dist/commonjs/utils/push/setupIosCallKeepEvents.js.map +0 -1
- package/dist/module/hooks/push/useIosCallkeepWithCallingStateEffect.js +0 -153
- package/dist/module/hooks/push/useIosCallkeepWithCallingStateEffect.js.map +0 -1
- package/dist/module/hooks/push/useProcessPushCallEffect.js +0 -60
- package/dist/module/hooks/push/useProcessPushCallEffect.js.map +0 -1
- package/dist/module/utils/push/libs/callkeep.js +0 -11
- package/dist/module/utils/push/libs/callkeep.js.map +0 -1
- package/dist/module/utils/push/libs/voipPushNotification.js +0 -11
- package/dist/module/utils/push/libs/voipPushNotification.js.map +0 -1
- package/dist/module/utils/push/setupIosCallKeepEvents.js +0 -199
- package/dist/module/utils/push/setupIosCallKeepEvents.js.map +0 -1
- package/dist/typescript/hooks/push/useIosCallkeepWithCallingStateEffect.d.ts +0 -5
- package/dist/typescript/hooks/push/useIosCallkeepWithCallingStateEffect.d.ts.map +0 -1
- package/dist/typescript/hooks/push/useProcessPushCallEffect.d.ts +0 -8
- package/dist/typescript/hooks/push/useProcessPushCallEffect.d.ts.map +0 -1
- package/dist/typescript/utils/push/libs/callkeep.d.ts +0 -3
- package/dist/typescript/utils/push/libs/callkeep.d.ts.map +0 -1
- package/dist/typescript/utils/push/libs/voipPushNotification.d.ts +0 -3
- package/dist/typescript/utils/push/libs/voipPushNotification.d.ts.map +0 -1
- package/dist/typescript/utils/push/setupIosCallKeepEvents.d.ts +0 -6
- package/dist/typescript/utils/push/setupIosCallKeepEvents.d.ts.map +0 -1
- package/src/hooks/push/useIosCallkeepWithCallingStateEffect.ts +0 -235
- package/src/hooks/push/useProcessPushCallEffect.ts +0 -108
- package/src/utils/push/libs/callkeep.ts +0 -16
- package/src/utils/push/libs/voipPushNotification.ts +0 -17
- package/src/utils/push/setupIosCallKeepEvents.ts +0 -252
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { useCallback, useEffect, useRef, useState } from 'react';
|
|
2
|
+
import { hasScreenShare, videoLoggerSystem } from '@stream-io/video-client';
|
|
3
|
+
import { useCall, useCallStateHooks } from '@stream-io/video-react-bindings';
|
|
4
|
+
import { screenShareAudioMixingManager } from '../modules/ScreenShareAudioManager';
|
|
5
|
+
import { NoiseCancellationWrapper } from '../providers/NoiseCancellation/lib';
|
|
6
|
+
|
|
7
|
+
const logger = videoLoggerSystem.getLogger('useScreenShareAudioMixing');
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Tries to disable noise cancellation so screen audio passes through
|
|
11
|
+
* unfiltered. Returns true if NC was disabled (and should be re-enabled later).
|
|
12
|
+
*/
|
|
13
|
+
async function disableNoiseCancellation(): Promise<boolean> {
|
|
14
|
+
try {
|
|
15
|
+
const nc = NoiseCancellationWrapper.getInstance();
|
|
16
|
+
const wasEnabled = await nc.isEnabled();
|
|
17
|
+
if (wasEnabled) {
|
|
18
|
+
await nc.disable();
|
|
19
|
+
logger.info('Noise cancellation disabled for screen share audio');
|
|
20
|
+
}
|
|
21
|
+
return wasEnabled;
|
|
22
|
+
} catch {
|
|
23
|
+
// NC module not installed or not configured — nothing to do
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Re-enables noise cancellation if it was previously disabled.
|
|
30
|
+
*/
|
|
31
|
+
async function restoreNoiseCancellation() {
|
|
32
|
+
try {
|
|
33
|
+
const nc = NoiseCancellationWrapper.getInstance();
|
|
34
|
+
await nc.enable();
|
|
35
|
+
logger.info('Noise cancellation re-enabled after screen share audio');
|
|
36
|
+
} catch {
|
|
37
|
+
// NC module not installed — nothing to do
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Hook that manages the lifecycle of screen share audio mixing.
|
|
43
|
+
*
|
|
44
|
+
* When screen share is active and audio mixing is enabled
|
|
45
|
+
* (via `call.screenShare.enableScreenShareAudio()`), this hook
|
|
46
|
+
* calls the native module to mix captured screen/app audio
|
|
47
|
+
* into the microphone audio track.
|
|
48
|
+
*
|
|
49
|
+
* Noise cancellation is temporarily disabled while screen audio mixing
|
|
50
|
+
* is active so that all captured sounds (music, game audio, etc.)
|
|
51
|
+
* pass through without being filtered.
|
|
52
|
+
*/
|
|
53
|
+
export const useScreenShareAudioMixing = () => {
|
|
54
|
+
const call = useCall();
|
|
55
|
+
const { useLocalParticipant } = useCallStateHooks();
|
|
56
|
+
const localParticipant = useLocalParticipant();
|
|
57
|
+
const isScreenSharing =
|
|
58
|
+
localParticipant != null && hasScreenShare(localParticipant);
|
|
59
|
+
|
|
60
|
+
const [audioEnabled, setAudioEnabled] = useState(
|
|
61
|
+
() => call?.screenShare.state.audioEnabled ?? false,
|
|
62
|
+
);
|
|
63
|
+
|
|
64
|
+
const isMixingActiveRef = useRef(false);
|
|
65
|
+
const ncWasEnabledRef = useRef(false);
|
|
66
|
+
|
|
67
|
+
useEffect(() => {
|
|
68
|
+
if (!call) return;
|
|
69
|
+
const sub = call.screenShare.state.audioEnabled$.subscribe(setAudioEnabled);
|
|
70
|
+
return () => sub.unsubscribe();
|
|
71
|
+
}, [call]);
|
|
72
|
+
|
|
73
|
+
const startMixing = useCallback(async () => {
|
|
74
|
+
if (isMixingActiveRef.current) return;
|
|
75
|
+
try {
|
|
76
|
+
// Disable NC before starting mixing so screen audio is not filtered
|
|
77
|
+
ncWasEnabledRef.current = await disableNoiseCancellation();
|
|
78
|
+
|
|
79
|
+
logger.info('Starting screen share audio mixing');
|
|
80
|
+
await screenShareAudioMixingManager.startScreenShareAudioMixing();
|
|
81
|
+
isMixingActiveRef.current = true;
|
|
82
|
+
} catch (error) {
|
|
83
|
+
logger.warn('Failed to start screen share audio mixing', error);
|
|
84
|
+
if (ncWasEnabledRef.current) {
|
|
85
|
+
restoreNoiseCancellation().catch(() => {});
|
|
86
|
+
ncWasEnabledRef.current = false;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}, []);
|
|
90
|
+
|
|
91
|
+
const stopMixing = useCallback(async () => {
|
|
92
|
+
if (!isMixingActiveRef.current) return;
|
|
93
|
+
try {
|
|
94
|
+
logger.info('Stopping screen share audio mixing');
|
|
95
|
+
await screenShareAudioMixingManager.stopScreenShareAudioMixing();
|
|
96
|
+
isMixingActiveRef.current = false;
|
|
97
|
+
|
|
98
|
+
if (ncWasEnabledRef.current) {
|
|
99
|
+
await restoreNoiseCancellation();
|
|
100
|
+
ncWasEnabledRef.current = false;
|
|
101
|
+
}
|
|
102
|
+
} catch (error) {
|
|
103
|
+
logger.warn('Failed to stop screen share audio mixing', error);
|
|
104
|
+
}
|
|
105
|
+
}, []);
|
|
106
|
+
|
|
107
|
+
// Start/stop audio mixing based on screen share status and audio preference
|
|
108
|
+
useEffect(() => {
|
|
109
|
+
if (isScreenSharing && audioEnabled) {
|
|
110
|
+
startMixing();
|
|
111
|
+
} else {
|
|
112
|
+
stopMixing();
|
|
113
|
+
}
|
|
114
|
+
}, [isScreenSharing, audioEnabled, startMixing, stopMixing]);
|
|
115
|
+
|
|
116
|
+
useEffect(() => {
|
|
117
|
+
return () => {
|
|
118
|
+
if (isMixingActiveRef.current) {
|
|
119
|
+
screenShareAudioMixingManager
|
|
120
|
+
.stopScreenShareAudioMixing()
|
|
121
|
+
.catch(() => {});
|
|
122
|
+
isMixingActiveRef.current = false;
|
|
123
|
+
if (ncWasEnabledRef.current) {
|
|
124
|
+
restoreNoiseCancellation().catch(() => {});
|
|
125
|
+
ncWasEnabledRef.current = false;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
};
|
|
129
|
+
}, []);
|
|
130
|
+
};
|
|
@@ -8,6 +8,42 @@ import React, { useEffect, useRef } from 'react';
|
|
|
8
8
|
import { findNodeHandle, NativeModules, Platform } from 'react-native';
|
|
9
9
|
import { usePrevious } from '../utils/hooks';
|
|
10
10
|
import { useIsIosScreenshareBroadcastStarted } from './useIsIosScreenshareBroadcastStarted';
|
|
11
|
+
import { screenShareAudioMixingManager } from '../modules/ScreenShareAudioManager';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* The type of screen sharing to use on iOS.
|
|
15
|
+
*
|
|
16
|
+
* - `'broadcast'` — Uses a Broadcast Upload Extension (RPSystemBroadcastPickerView).
|
|
17
|
+
* Captures the entire device screen, works across all apps. Requires an extension target.
|
|
18
|
+
* - `'inApp'` — Uses RPScreenRecorder.startCapture to capture the current app's screen.
|
|
19
|
+
* Only captures the current app. Supports `.audioApp` sample buffers for audio mixing.
|
|
20
|
+
*
|
|
21
|
+
* On Android, this option is ignored — the system screen capture dialog is always used.
|
|
22
|
+
*/
|
|
23
|
+
export type ScreenShareType = 'broadcast' | 'inApp';
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Options for screen share behavior.
|
|
27
|
+
*/
|
|
28
|
+
export type ScreenShareOptions = {
|
|
29
|
+
/**
|
|
30
|
+
* The type of screen sharing on iOS. Default: `'broadcast'`.
|
|
31
|
+
* On Android this is ignored.
|
|
32
|
+
*/
|
|
33
|
+
type?: ScreenShareType;
|
|
34
|
+
/**
|
|
35
|
+
* Whether to capture and mix system/app audio into the microphone audio track.
|
|
36
|
+
* When `true`, remote participants will hear media audio from the shared screen
|
|
37
|
+
* (e.g., YouTube video audio) mixed with the user's microphone.
|
|
38
|
+
*
|
|
39
|
+
* - iOS in-app: Audio captured from RPScreenRecorder `.audioApp` buffers.
|
|
40
|
+
* - iOS broadcast: Audio mixing is **not** currently supported.
|
|
41
|
+
* - Android: Audio captured via AudioPlaybackCaptureConfiguration (API 29+).
|
|
42
|
+
*
|
|
43
|
+
* Default: `false`.
|
|
44
|
+
*/
|
|
45
|
+
includeAudio?: boolean;
|
|
46
|
+
};
|
|
11
47
|
|
|
12
48
|
// ios >= 14.0 or android - platform restrictions
|
|
13
49
|
const CanDeviceScreenShare =
|
|
@@ -18,7 +54,7 @@ const CanDeviceScreenShare =
|
|
|
18
54
|
export const useScreenShareButton = (
|
|
19
55
|
/**
|
|
20
56
|
* Ref of the ScreenCapturePickerView component.
|
|
21
|
-
*
|
|
57
|
+
* Required for iOS broadcast screen sharing. Can be `null` for in-app mode.
|
|
22
58
|
*/
|
|
23
59
|
screenCapturePickerViewiOSRef: React.MutableRefObject<any>,
|
|
24
60
|
/**
|
|
@@ -36,6 +72,10 @@ export const useScreenShareButton = (
|
|
|
36
72
|
*
|
|
37
73
|
*/
|
|
38
74
|
onMissingScreenShareStreamPermission?: () => void,
|
|
75
|
+
/**
|
|
76
|
+
* Options for screen share behavior (type, includeAudio).
|
|
77
|
+
*/
|
|
78
|
+
screenShareOptions?: ScreenShareOptions,
|
|
39
79
|
) => {
|
|
40
80
|
const call = useCall();
|
|
41
81
|
const { useLocalParticipant, useCallSettings, useOwnCapabilities } =
|
|
@@ -47,6 +87,9 @@ export const useScreenShareButton = (
|
|
|
47
87
|
);
|
|
48
88
|
const isScreenSharingEnabledInCall = callSettings?.screensharing.enabled;
|
|
49
89
|
|
|
90
|
+
const screenShareType = screenShareOptions?.type ?? 'broadcast';
|
|
91
|
+
const includeAudio = screenShareOptions?.includeAudio ?? false;
|
|
92
|
+
|
|
50
93
|
const onScreenShareStartedHandlerRef = useRef(onScreenShareStartedHandler);
|
|
51
94
|
onScreenShareStartedHandlerRef.current = onScreenShareStartedHandler;
|
|
52
95
|
const onScreenShareStoppedHandlerRef = useRef(onScreenShareStoppedHandler);
|
|
@@ -62,15 +105,22 @@ export const useScreenShareButton = (
|
|
|
62
105
|
localParticipant && hasScreenShare(localParticipant);
|
|
63
106
|
|
|
64
107
|
// listens to iOS screen share broadcast started event from the system
|
|
108
|
+
// (only relevant for broadcast mode)
|
|
65
109
|
useEffect(() => {
|
|
66
110
|
if (Platform.OS !== 'ios') {
|
|
67
111
|
return;
|
|
68
112
|
}
|
|
113
|
+
if (screenShareType !== 'broadcast') {
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
69
116
|
if (
|
|
70
117
|
iosScreenShareStartedFromSystem &&
|
|
71
118
|
!prevIosScreenShareStartedFromSystem
|
|
72
119
|
) {
|
|
73
120
|
onScreenShareStartedHandlerRef.current?.();
|
|
121
|
+
if (includeAudio) {
|
|
122
|
+
call?.screenShare.enableScreenShareAudio();
|
|
123
|
+
}
|
|
74
124
|
call?.screenShare.enable();
|
|
75
125
|
} else if (
|
|
76
126
|
!iosScreenShareStartedFromSystem &&
|
|
@@ -81,6 +131,8 @@ export const useScreenShareButton = (
|
|
|
81
131
|
}
|
|
82
132
|
}, [
|
|
83
133
|
call,
|
|
134
|
+
includeAudio,
|
|
135
|
+
screenShareType,
|
|
84
136
|
iosScreenShareStartedFromSystem,
|
|
85
137
|
prevIosScreenShareStartedFromSystem,
|
|
86
138
|
]);
|
|
@@ -92,14 +144,43 @@ export const useScreenShareButton = (
|
|
|
92
144
|
'User does not have permissions to stream the screen share media, calling onMissingScreenShareStreamPermission handler if present',
|
|
93
145
|
);
|
|
94
146
|
onMissingScreenShareStreamPermission?.();
|
|
147
|
+
return;
|
|
95
148
|
}
|
|
149
|
+
|
|
96
150
|
if (!hasPublishedScreenShare) {
|
|
97
|
-
|
|
151
|
+
// Set audio mixing preference before starting screen share
|
|
152
|
+
if (includeAudio) {
|
|
153
|
+
call?.screenShare.enableScreenShareAudio();
|
|
154
|
+
} else {
|
|
155
|
+
try {
|
|
156
|
+
await call?.screenShare.disableScreenShareAudio();
|
|
157
|
+
} catch (error) {
|
|
158
|
+
const logger = videoLoggerSystem.getLogger('useScreenShareButton');
|
|
159
|
+
logger.warn('Failed to disable screen share audio', error);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
if (Platform.OS === 'ios' && screenShareType === 'inApp') {
|
|
164
|
+
// In-app screen sharing on iOS — uses RPScreenRecorder directly
|
|
165
|
+
try {
|
|
166
|
+
await screenShareAudioMixingManager.startInAppScreenCapture(
|
|
167
|
+
includeAudio,
|
|
168
|
+
);
|
|
169
|
+
await call?.screenShare.enable();
|
|
170
|
+
onScreenShareStartedHandler?.();
|
|
171
|
+
} catch (error) {
|
|
172
|
+
await screenShareAudioMixingManager.stopInAppScreenCapture();
|
|
173
|
+
const logger = videoLoggerSystem.getLogger('useScreenShareButton');
|
|
174
|
+
logger.warn('Failed to start in-app screen capture', error);
|
|
175
|
+
}
|
|
176
|
+
} else if (Platform.OS === 'ios') {
|
|
177
|
+
// Broadcast screen sharing on iOS — shows the system picker
|
|
98
178
|
const reactTag = findNodeHandle(screenCapturePickerViewiOSRef.current);
|
|
99
179
|
await NativeModules.ScreenCapturePickerViewManager.show(reactTag);
|
|
100
180
|
// After this the iOS screen share broadcast started/stopped event will be triggered
|
|
101
181
|
// and the useEffect listener will handle the rest
|
|
102
182
|
} else {
|
|
183
|
+
// Android screen sharing
|
|
103
184
|
try {
|
|
104
185
|
await call?.screenShare.enable();
|
|
105
186
|
onScreenShareStartedHandler?.();
|
|
@@ -114,6 +195,10 @@ export const useScreenShareButton = (
|
|
|
114
195
|
}
|
|
115
196
|
} else if (hasPublishedScreenShare) {
|
|
116
197
|
onScreenShareStoppedHandler?.();
|
|
198
|
+
// Stop in-app screen capture if it was active (iOS only)
|
|
199
|
+
if (Platform.OS === 'ios' && screenShareType === 'inApp') {
|
|
200
|
+
await screenShareAudioMixingManager.stopInAppScreenCapture();
|
|
201
|
+
}
|
|
117
202
|
await call?.screenShare.disable(true);
|
|
118
203
|
}
|
|
119
204
|
};
|
package/src/index.ts
CHANGED
|
@@ -9,6 +9,7 @@ import { registerGlobals } from '@stream-io/react-native-webrtc';
|
|
|
9
9
|
import Logger from '@stream-io/react-native-webrtc/src/Logger';
|
|
10
10
|
import { Platform } from 'react-native';
|
|
11
11
|
import { registerSDKGlobals } from './utils/internal/registerSDKGlobals';
|
|
12
|
+
import './utils/keepCallAliveHeadlessTask';
|
|
12
13
|
|
|
13
14
|
// We're registering globals, because our video JS client is serving SDKs that use browser based webRTC functions.
|
|
14
15
|
// This will result in creation of 2 global objects: `window` and `navigator`
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { NativeModules, Platform } from 'react-native';
|
|
2
|
+
|
|
3
|
+
const StreamVideoReactNative = NativeModules.StreamVideoReactNative;
|
|
4
|
+
|
|
5
|
+
export class ScreenShareAudioManager {
|
|
6
|
+
/**
|
|
7
|
+
* Starts mixing screen share audio into the microphone audio track.
|
|
8
|
+
* On iOS, this enables audio buffer processing on the prepared mixer.
|
|
9
|
+
* On Android, this registers an audio processor that captures system media
|
|
10
|
+
* audio via AudioPlaybackCaptureConfiguration and mixes it into the mic buffer.
|
|
11
|
+
*/
|
|
12
|
+
async startScreenShareAudioMixing(): Promise<void> {
|
|
13
|
+
return StreamVideoReactNative?.startScreenShareAudioMixing();
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Stops mixing screen share audio into the microphone audio track
|
|
18
|
+
* and restores the original audio pipeline.
|
|
19
|
+
*/
|
|
20
|
+
async stopScreenShareAudioMixing(): Promise<void> {
|
|
21
|
+
return StreamVideoReactNative?.stopScreenShareAudioMixing();
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Starts in-app screen capture using RPScreenRecorder (iOS only).
|
|
26
|
+
* Unlike broadcast screen sharing, in-app capture runs in the main app process
|
|
27
|
+
* and can directly provide `.audioApp` sample buffers for mixing.
|
|
28
|
+
*
|
|
29
|
+
* @param includeAudio Whether to capture and mix app audio.
|
|
30
|
+
*/
|
|
31
|
+
async startInAppScreenCapture(includeAudio: boolean): Promise<void> {
|
|
32
|
+
if (Platform.OS !== 'ios') {
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
return StreamVideoReactNative?.startInAppScreenCapture(includeAudio);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Stops in-app screen capture (iOS only).
|
|
40
|
+
*/
|
|
41
|
+
async stopInAppScreenCapture(): Promise<void> {
|
|
42
|
+
if (Platform.OS !== 'ios') {
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
return StreamVideoReactNative?.stopInAppScreenCapture();
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export const screenShareAudioMixingManager = new ScreenShareAudioManager();
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import { NativeEventEmitter, NativeModules, Platform } from 'react-native';
|
|
2
2
|
import { AudioDeviceStatus, StreamInCallManagerConfig } from './types';
|
|
3
|
+
import { getCallingxLibIfAvailable } from '../../utils/push/libs/callingx';
|
|
4
|
+
import { videoLoggerSystem } from '@stream-io/video-client';
|
|
3
5
|
|
|
4
6
|
const NativeManager = NativeModules.StreamInCallManager;
|
|
7
|
+
const CallingxModule = getCallingxLibIfAvailable();
|
|
5
8
|
|
|
6
9
|
const invariant = (condition: boolean, message: string) => {
|
|
7
10
|
if (!condition) throw new Error(message);
|
|
@@ -72,6 +75,19 @@ class SpeakerManager {
|
|
|
72
75
|
};
|
|
73
76
|
}
|
|
74
77
|
|
|
78
|
+
const shouldBypassForCallKit = (): boolean => {
|
|
79
|
+
if (Platform.OS !== 'ios') {
|
|
80
|
+
return false;
|
|
81
|
+
}
|
|
82
|
+
if (!CallingxModule) {
|
|
83
|
+
return false;
|
|
84
|
+
}
|
|
85
|
+
return (
|
|
86
|
+
CallingxModule.isSetup &&
|
|
87
|
+
(CallingxModule.hasRegisteredCall() || CallingxModule.isOngoingCallsEnabled)
|
|
88
|
+
);
|
|
89
|
+
};
|
|
90
|
+
|
|
75
91
|
export class CallManager {
|
|
76
92
|
android = new AndroidCallManager();
|
|
77
93
|
ios = new IOSCallManager();
|
|
@@ -95,6 +111,14 @@ export class CallManager {
|
|
|
95
111
|
* @param config.enableStereoAudioOutput Whether to enable stereo audio output. Only supported for listener audio role.
|
|
96
112
|
*/
|
|
97
113
|
start = (config?: StreamInCallManagerConfig): void => {
|
|
114
|
+
if (shouldBypassForCallKit()) {
|
|
115
|
+
videoLoggerSystem
|
|
116
|
+
.getLogger('CallManager')
|
|
117
|
+
.debug(
|
|
118
|
+
'start: skipping start as callkit is handling the audio session',
|
|
119
|
+
);
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
98
122
|
NativeManager.setAudioRole(config?.audioRole ?? 'communicator');
|
|
99
123
|
if (config?.audioRole === 'communicator') {
|
|
100
124
|
const type = config.deviceEndpointType ?? 'speaker';
|
|
@@ -110,6 +134,12 @@ export class CallManager {
|
|
|
110
134
|
* Stops the in call manager.
|
|
111
135
|
*/
|
|
112
136
|
stop = (): void => {
|
|
137
|
+
if (shouldBypassForCallKit()) {
|
|
138
|
+
videoLoggerSystem
|
|
139
|
+
.getLogger('CallManager')
|
|
140
|
+
.debug('stop: skipping stop as callkit is handling the audio session');
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
113
143
|
NativeManager.stop();
|
|
114
144
|
};
|
|
115
145
|
|
|
@@ -118,4 +148,10 @@ export class CallManager {
|
|
|
118
148
|
* in the native layer.
|
|
119
149
|
*/
|
|
120
150
|
logAudioState = (): void => NativeManager.logAudioState();
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* For debugging purposes, returns the current audio state as a string.
|
|
154
|
+
* @returns A string containing the current audio state information.
|
|
155
|
+
*/
|
|
156
|
+
getAudioStateLog = (): string => NativeManager.getAudioStateLog();
|
|
121
157
|
}
|
|
@@ -82,6 +82,13 @@ export interface CallManager extends NativeModule {
|
|
|
82
82
|
* Meant for debugging purposes.
|
|
83
83
|
*/
|
|
84
84
|
logAudioState: () => void;
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Get the current audio state as a string.
|
|
88
|
+
* Meant for debugging purposes.
|
|
89
|
+
* @returns A string containing the current audio state information.
|
|
90
|
+
*/
|
|
91
|
+
getAudioStateLog: () => string;
|
|
85
92
|
}
|
|
86
93
|
|
|
87
94
|
declare module 'react-native' {
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { StreamCallProvider } from '@stream-io/video-react-bindings';
|
|
2
2
|
import React, { type PropsWithChildren, useEffect } from 'react';
|
|
3
3
|
import { Call } from '@stream-io/video-client';
|
|
4
|
-
import { useIosCallkeepWithCallingStateEffect } from '../../hooks/push/useIosCallkeepWithCallingStateEffect';
|
|
5
4
|
import { canAddPushWSSubscriptionsRef } from '../../utils/push/internal/utils';
|
|
6
5
|
import { useAndroidKeepCallAliveEffect } from '../../hooks/useAndroidKeepCallAliveEffect';
|
|
6
|
+
import { useScreenShareAudioMixing } from '../../hooks/useScreenShareAudioMixing';
|
|
7
7
|
import { AppStateListener } from './AppStateListener';
|
|
8
8
|
import { DeviceStats } from './DeviceStats';
|
|
9
9
|
import { pushUnsubscriptionCallbacks } from '../../utils/push/internal/constants';
|
|
10
|
+
import { useCallingExpWithCallingStateEffect } from '../../hooks/push/useCallingExpWithCallingStateEffect';
|
|
10
11
|
|
|
11
12
|
// const PIP_CHANGE_EVENT = 'StreamVideoReactNative_PIP_CHANGE_EVENT';
|
|
12
13
|
|
|
@@ -34,8 +35,9 @@ export const StreamCall = ({
|
|
|
34
35
|
<StreamCallProvider call={call}>
|
|
35
36
|
<AppStateListener />
|
|
36
37
|
<AndroidKeepCallAlive />
|
|
37
|
-
<
|
|
38
|
+
<CallingExpWithCallingState />
|
|
38
39
|
<ClearPushWSSubscriptions />
|
|
40
|
+
<ScreenShareAudioMixer />
|
|
39
41
|
<DeviceStats />
|
|
40
42
|
{children}
|
|
41
43
|
</StreamCallProvider>
|
|
@@ -52,11 +54,20 @@ const AndroidKeepCallAlive = () => {
|
|
|
52
54
|
};
|
|
53
55
|
|
|
54
56
|
/**
|
|
55
|
-
* This is a renderless component to
|
|
56
|
-
*
|
|
57
|
+
* This is a renderless component to sync state between stream call and CallKit/Telecom.
|
|
58
|
+
* useCallingExpWithCallingStateEffect needs to called inside a child of StreamCallProvider.
|
|
59
|
+
*/
|
|
60
|
+
const CallingExpWithCallingState = () => {
|
|
61
|
+
useCallingExpWithCallingStateEffect();
|
|
62
|
+
return null;
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* This is a renderless component to manage screen share audio mixing lifecycle.
|
|
67
|
+
* It starts/stops native audio mixing based on screen share status and audio preference.
|
|
57
68
|
*/
|
|
58
|
-
const
|
|
59
|
-
|
|
69
|
+
const ScreenShareAudioMixer = () => {
|
|
70
|
+
useScreenShareAudioMixing();
|
|
60
71
|
return null;
|
|
61
72
|
};
|
|
62
73
|
|
|
@@ -3,9 +3,14 @@ import pushLogoutCallbacks from '../internal/pushLogoutCallback';
|
|
|
3
3
|
import newNotificationCallbacks, {
|
|
4
4
|
type NewCallNotificationCallback,
|
|
5
5
|
} from '../internal/newNotificationCallbacks';
|
|
6
|
-
import { setupIosCallKeepEvents } from '../push/setupIosCallKeepEvents';
|
|
7
6
|
import { setupIosVoipPushEvents } from '../push/setupIosVoipPushEvents';
|
|
7
|
+
import { setupCallingExpEvents } from '../push/setupCallingExpEvents';
|
|
8
|
+
import {
|
|
9
|
+
extractCallingExpOptions,
|
|
10
|
+
getCallingxLib,
|
|
11
|
+
} from '../push/libs/callingx';
|
|
8
12
|
import { NativeModules, Platform } from 'react-native';
|
|
13
|
+
import { videoLoggerSystem } from '@stream-io/video-client';
|
|
9
14
|
|
|
10
15
|
// Utility type for deep partial
|
|
11
16
|
type DeepPartial<T> = {
|
|
@@ -47,10 +52,7 @@ const DEFAULT_STREAM_VIDEO_CONFIG: StreamVideoConfig = {
|
|
|
47
52
|
android: {
|
|
48
53
|
channel: {
|
|
49
54
|
id: 'stream_call_foreground_service',
|
|
50
|
-
name: '
|
|
51
|
-
lights: false,
|
|
52
|
-
vibration: false,
|
|
53
|
-
importance: 3,
|
|
55
|
+
name: 'Ongoing calls',
|
|
54
56
|
},
|
|
55
57
|
notificationTexts: {
|
|
56
58
|
title: 'Call in progress',
|
|
@@ -76,20 +78,6 @@ export class StreamVideoRN {
|
|
|
76
78
|
this.config = deepMerge(this.config, updateConfig);
|
|
77
79
|
}
|
|
78
80
|
|
|
79
|
-
static updateAndroidIncomingCallChannel(
|
|
80
|
-
updateChannel: Partial<
|
|
81
|
-
NonNullable<StreamVideoConfig['push']>['android']['incomingCallChannel']
|
|
82
|
-
>,
|
|
83
|
-
) {
|
|
84
|
-
const prevChannel = this.config.push?.android?.incomingCallChannel;
|
|
85
|
-
if (prevChannel) {
|
|
86
|
-
this.config.push!.android.incomingCallChannel = {
|
|
87
|
-
...prevChannel,
|
|
88
|
-
...updateChannel,
|
|
89
|
-
};
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
|
|
93
81
|
/**
|
|
94
82
|
* Set the push config for StreamVideoRN.
|
|
95
83
|
* This method must be called **outside** of your application lifecycle, e.g. alongside your
|
|
@@ -102,7 +90,28 @@ export class StreamVideoRN {
|
|
|
102
90
|
* import App from './App';
|
|
103
91
|
* // Set push config
|
|
104
92
|
* const pushConfig = {}; // construct your config
|
|
105
|
-
*
|
|
93
|
+
* // Set CallKit/Android Telecom API integration options. All params are optional. If not provided, the default values will be used.
|
|
94
|
+
* const callingExpOptions = {
|
|
95
|
+
* ios: {
|
|
96
|
+
* callsHistory: true,
|
|
97
|
+
* displayCallTimeout: 60000,
|
|
98
|
+
* sound: 'ringtone',
|
|
99
|
+
* imageName: 'callkit_icon',
|
|
100
|
+
* },
|
|
101
|
+
* android: {
|
|
102
|
+
* incomingChannel: {
|
|
103
|
+
* id: 'stream_incoming_call_notifications',
|
|
104
|
+
* name: 'Call notifications',
|
|
105
|
+
* vibration: true,
|
|
106
|
+
* sound: 'default',
|
|
107
|
+
* },
|
|
108
|
+
* titleTransformer: (memberName: string, incoming: boolean) =>
|
|
109
|
+
* incoming
|
|
110
|
+
* ? `${memberName} is calling you`
|
|
111
|
+
* : `You are calling ${memberName}`,
|
|
112
|
+
* },
|
|
113
|
+
* };
|
|
114
|
+
* StreamVideoRN.setPushConfig(pushConfig, callingExpOptions);
|
|
106
115
|
* AppRegistry.registerComponent('app', () => App);
|
|
107
116
|
*/
|
|
108
117
|
static setPushConfig(pushConfig: NonNullable<StreamVideoConfig['push']>) {
|
|
@@ -110,20 +119,23 @@ export class StreamVideoRN {
|
|
|
110
119
|
// Ignoring this config as push config was already set
|
|
111
120
|
return;
|
|
112
121
|
}
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
122
|
+
|
|
123
|
+
this.config.push = pushConfig;
|
|
124
|
+
|
|
125
|
+
try {
|
|
126
|
+
const callingx = getCallingxLib();
|
|
127
|
+
videoLoggerSystem
|
|
128
|
+
.getLogger('StreamVideoRN.setPushConfig')
|
|
129
|
+
.info(JSON.stringify(this.config));
|
|
130
|
+
const options = extractCallingExpOptions(this.config);
|
|
131
|
+
callingx.setup(options);
|
|
132
|
+
} catch {
|
|
117
133
|
throw new Error(
|
|
118
|
-
|
|
119
|
-
Please watch for incoming and outgoing calls in the root component of your app.
|
|
120
|
-
Please see https://getstream.io/video/docs/react-native/advanced/ringing-calls/#watch-for-incoming-and-outgoing-calls for more information.`,
|
|
134
|
+
'react-native-callingx library is not installed. Please check the installation instructions: https://getstream.io/video/docs/react-native/incoming-calls/ringing-setup/react-native/.',
|
|
121
135
|
);
|
|
122
136
|
}
|
|
123
137
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
setupIosCallKeepEvents(pushConfig);
|
|
138
|
+
setupCallingExpEvents(pushConfig);
|
|
127
139
|
setupIosVoipPushEvents(pushConfig);
|
|
128
140
|
}
|
|
129
141
|
|