@stream-io/video-react-native-sdk 1.28.1 → 1.29.0-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/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 +42 -5
- package/android/src/main/java/com/streamvideo/reactnative/keepalive/KeepAliveNotification.kt +83 -0
- package/android/src/main/java/com/streamvideo/reactnative/keepalive/StreamCallKeepAliveHeadlessService.kt +134 -0
- package/dist/commonjs/hooks/push/useCallingExpWithCallingStateEffect.js +235 -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 +60 -97
- package/dist/commonjs/hooks/useAndroidKeepCallAliveEffect.js.map +1 -1
- package/dist/commonjs/index.js +1 -0
- package/dist/commonjs/index.js.map +1 -1
- package/dist/commonjs/modules/call-manager/CallManager.js +20 -0
- package/dist/commonjs/modules/call-manager/CallManager.js.map +1 -1
- package/dist/commonjs/providers/StreamCall/index.js +6 -6
- package/dist/commonjs/providers/StreamCall/index.js.map +1 -1
- package/dist/commonjs/utils/StreamVideoRN/index.js +33 -21
- package/dist/commonjs/utils/StreamVideoRN/index.js.map +1 -1
- package/dist/commonjs/utils/internal/registerSDKGlobals.js +47 -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 +145 -200
- package/dist/commonjs/utils/push/android.js.map +1 -1
- package/dist/commonjs/utils/push/internal/ios.js +16 -34
- package/dist/commonjs/utils/push/internal/ios.js.map +1 -1
- package/dist/commonjs/utils/push/internal/rxSubjects.js +1 -20
- package/dist/commonjs/utils/push/internal/rxSubjects.js.map +1 -1
- package/dist/commonjs/utils/push/internal/utils.js +17 -1
- 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 +75 -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/module/hooks/push/useCallingExpWithCallingStateEffect.js +228 -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 +62 -99
- package/dist/module/hooks/useAndroidKeepCallAliveEffect.js.map +1 -1
- package/dist/module/index.js +1 -0
- package/dist/module/index.js.map +1 -1
- package/dist/module/modules/call-manager/CallManager.js +20 -0
- package/dist/module/modules/call-manager/CallManager.js.map +1 -1
- package/dist/module/providers/StreamCall/index.js +6 -6
- package/dist/module/providers/StreamCall/index.js.map +1 -1
- package/dist/module/utils/StreamVideoRN/index.js +33 -21
- package/dist/module/utils/StreamVideoRN/index.js.map +1 -1
- package/dist/module/utils/internal/registerSDKGlobals.js +48 -4
- 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 +147 -202
- package/dist/module/utils/push/android.js.map +1 -1
- package/dist/module/utils/push/internal/ios.js +16 -34
- package/dist/module/utils/push/internal/ios.js.map +1 -1
- package/dist/module/utils/push/internal/rxSubjects.js +0 -19
- package/dist/module/utils/push/internal/rxSubjects.js.map +1 -1
- package/dist/module/utils/push/internal/utils.js +14 -0
- 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 +69 -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/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/index.d.ts +1 -0
- package/dist/typescript/index.d.ts.map +1 -1
- package/dist/typescript/modules/call-manager/CallManager.d.ts.map +1 -1
- package/dist/typescript/utils/StreamVideoRN/index.d.ts +20 -2
- package/dist/typescript/utils/StreamVideoRN/index.d.ts.map +1 -1
- package/dist/typescript/utils/StreamVideoRN/types.d.ts +54 -29
- package/dist/typescript/utils/StreamVideoRN/types.d.ts.map +1 -1
- 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 -12
- package/dist/typescript/utils/push/internal/rxSubjects.d.ts.map +1 -1
- package/dist/typescript/utils/push/internal/utils.d.ts +4 -0
- 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/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.swift +4 -0
- package/ios/StreamVideoReactNative.h +7 -4
- package/ios/StreamVideoReactNative.m +191 -82
- package/package.json +10 -15
- package/src/hooks/push/useCallingExpWithCallingStateEffect.ts +361 -0
- package/src/hooks/push/useIosVoipPushEventsSetupEffect.ts +21 -34
- package/src/hooks/useAndroidKeepCallAliveEffect.ts +95 -120
- package/src/index.ts +1 -0
- package/src/modules/call-manager/CallManager.ts +30 -0
- package/src/providers/StreamCall/index.tsx +6 -6
- package/src/utils/StreamVideoRN/index.ts +40 -30
- package/src/utils/StreamVideoRN/types.ts +56 -29
- package/src/utils/internal/registerSDKGlobals.ts +42 -4
- package/src/utils/keepCallAliveHeadlessTask.ts +54 -0
- package/src/utils/push/android.ts +223 -308
- package/src/utils/push/internal/ios.ts +25 -46
- package/src/utils/push/internal/rxSubjects.ts +0 -29
- package/src/utils/push/internal/utils.ts +25 -0
- package/src/utils/push/ios.ts +1 -6
- package/src/utils/push/libs/callingx.ts +90 -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 +100 -0
- package/src/utils/push/setupIosVoipPushEvents.ts +11 -7
- package/CHANGELOG.md +0 -3089
- 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/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/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/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/utils/push/libs/callkeep.ts +0 -16
- package/src/utils/push/libs/voipPushNotification.ts +0 -17
- package/src/utils/push/setupIosCallKeepEvents.ts +0 -252
|
@@ -5,76 +5,48 @@ import {
|
|
|
5
5
|
AppState,
|
|
6
6
|
type AppStateStatus,
|
|
7
7
|
NativeModules,
|
|
8
|
+
PermissionsAndroid,
|
|
8
9
|
Platform,
|
|
9
10
|
} from 'react-native';
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
} from '../utils/push/libs/notifee';
|
|
11
|
+
import { CallingState, videoLoggerSystem } from '@stream-io/video-client';
|
|
12
|
+
import { keepCallAliveCallRef } from '../utils/keepCallAliveHeadlessTask';
|
|
13
|
+
import { getNotifeeLibNoThrowForKeepCallAlive } from '../utils/push/libs/notifee';
|
|
14
|
+
import { getCallingxLibIfAvailable } from '../utils/push/libs';
|
|
15
15
|
|
|
16
16
|
const notifeeLib = getNotifeeLibNoThrowForKeepCallAlive();
|
|
17
|
-
const callToPassToForegroundService: { current: Call | undefined } = {
|
|
18
|
-
current: undefined,
|
|
19
|
-
};
|
|
20
17
|
|
|
21
|
-
function
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
(
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
);
|
|
29
|
-
logger.info(
|
|
30
|
-
'KeepCallAlive is not configured. Skipping foreground service setup.',
|
|
31
|
-
);
|
|
32
|
-
return;
|
|
33
|
-
}
|
|
34
|
-
notifeeLib.default.registerForegroundService(() => {
|
|
35
|
-
const task = new Promise((resolve) => {
|
|
36
|
-
const logger = videoLoggerSystem.getLogger(
|
|
37
|
-
'setForegroundService method',
|
|
38
|
-
);
|
|
39
|
-
logger.info('Foreground service running for call in progress');
|
|
40
|
-
// any task to run from SDK in the foreground service must be added
|
|
41
|
-
resolve(true);
|
|
42
|
-
});
|
|
43
|
-
const videoConfig = StreamVideoRN.getConfig();
|
|
44
|
-
const foregroundServiceConfig = videoConfig.foregroundService;
|
|
45
|
-
const { taskToRun } = foregroundServiceConfig.android;
|
|
46
|
-
const call = callToPassToForegroundService.current;
|
|
47
|
-
if (!call) {
|
|
48
|
-
const logger = videoLoggerSystem.getLogger(
|
|
49
|
-
'setForegroundService method',
|
|
50
|
-
);
|
|
51
|
-
logger.warn('No call to pass to foreground service');
|
|
52
|
-
return task.then(() => new Promise(() => {}));
|
|
53
|
-
}
|
|
54
|
-
callToPassToForegroundService.current = undefined;
|
|
55
|
-
return task.then(() => taskToRun(call));
|
|
56
|
-
});
|
|
57
|
-
},
|
|
58
|
-
);
|
|
18
|
+
async function stopForegroundServiceNoThrow() {
|
|
19
|
+
const logger = videoLoggerSystem.getLogger('stopForegroundServiceNoThrow');
|
|
20
|
+
try {
|
|
21
|
+
await NativeModules.StreamVideoReactNative.stopKeepCallAliveService();
|
|
22
|
+
} catch (e) {
|
|
23
|
+
logger.warn('Failed to stop keep-call-alive foreground service', e);
|
|
24
|
+
}
|
|
59
25
|
}
|
|
60
26
|
|
|
61
27
|
async function startForegroundService(call_cid: string) {
|
|
62
|
-
const
|
|
63
|
-
|
|
28
|
+
const logger = videoLoggerSystem.getLogger('startForegroundService');
|
|
29
|
+
const isCallAliveConfigured = await (async () => {
|
|
30
|
+
try {
|
|
31
|
+
return await NativeModules.StreamVideoReactNative.isCallAliveConfigured();
|
|
32
|
+
} catch (e) {
|
|
33
|
+
logger.warn('Failed to check whether KeepCallAlive is configured', e);
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
})();
|
|
64
37
|
if (!isCallAliveConfigured) {
|
|
65
|
-
const logger = videoLoggerSystem.getLogger('startForegroundService');
|
|
66
38
|
logger.info(
|
|
67
39
|
'KeepCallAlive is not configured. Skipping foreground service setup.',
|
|
68
40
|
);
|
|
69
41
|
return;
|
|
70
42
|
}
|
|
71
|
-
//
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
43
|
+
// Check for notification permission (Android 13+) before starting the service.
|
|
44
|
+
const hasPostNotificationsPermission =
|
|
45
|
+
Number(Platform.Version) < 33 ||
|
|
46
|
+
(await PermissionsAndroid.check(
|
|
47
|
+
PermissionsAndroid.PERMISSIONS.POST_NOTIFICATIONS,
|
|
48
|
+
));
|
|
49
|
+
if (!hasPostNotificationsPermission) {
|
|
78
50
|
logger.info(
|
|
79
51
|
'Notification permission not granted, can not start foreground service to keep the call alive',
|
|
80
52
|
);
|
|
@@ -83,38 +55,28 @@ async function startForegroundService(call_cid: string) {
|
|
|
83
55
|
const videoConfig = StreamVideoRN.getConfig();
|
|
84
56
|
const foregroundServiceConfig = videoConfig.foregroundService;
|
|
85
57
|
const notificationTexts = foregroundServiceConfig.android.notificationTexts;
|
|
86
|
-
const
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
);
|
|
90
|
-
const foregroundServiceTypes = await getKeepCallAliveForegroundServiceTypes();
|
|
58
|
+
const channel = foregroundServiceConfig.android.channel;
|
|
59
|
+
const smallIconName = videoConfig.push?.android.smallIcon;
|
|
60
|
+
|
|
91
61
|
// NOTE: we use requestAnimationFrame to ensure that the foreground service is started after all the current UI operations are done
|
|
92
62
|
// this is a workaround for the crash - android.app.RemoteServiceException$ForegroundServiceDidNotStartInTimeException: Context.startForegroundService() did not then call Service.startForeground()
|
|
93
63
|
// this crash was reproducible only in some android devices
|
|
94
|
-
requestAnimationFrame(() => {
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
id: 'default',
|
|
108
|
-
launchActivity: 'default', // open the app when the notification is pressed
|
|
109
|
-
},
|
|
110
|
-
},
|
|
111
|
-
});
|
|
64
|
+
requestAnimationFrame(async () => {
|
|
65
|
+
try {
|
|
66
|
+
await NativeModules.StreamVideoReactNative.startKeepCallAliveService(
|
|
67
|
+
call_cid,
|
|
68
|
+
channel.id,
|
|
69
|
+
channel.name,
|
|
70
|
+
notificationTexts.title,
|
|
71
|
+
notificationTexts.body,
|
|
72
|
+
smallIconName ?? null,
|
|
73
|
+
);
|
|
74
|
+
} catch (e) {
|
|
75
|
+
logger.warn('Failed to start keep-call-alive foreground service', e);
|
|
76
|
+
}
|
|
112
77
|
});
|
|
113
78
|
}
|
|
114
79
|
|
|
115
|
-
// flag to check if setForegroundService has already been run once
|
|
116
|
-
let isSetForegroundServiceRan = false;
|
|
117
|
-
|
|
118
80
|
/**
|
|
119
81
|
* This hook is used to keep the call alive in the background for Android.
|
|
120
82
|
* It starts a foreground service to keep the call alive as soon as the call is joined
|
|
@@ -125,7 +87,7 @@ export const useAndroidKeepCallAliveEffect = () => {
|
|
|
125
87
|
const foregroundServiceStartedRef = useRef(false);
|
|
126
88
|
|
|
127
89
|
const call = useCall();
|
|
128
|
-
|
|
90
|
+
keepCallAliveCallRef.current = call;
|
|
129
91
|
const activeCallCid = call?.cid;
|
|
130
92
|
const { useCallCallingState } = useCallStateHooks();
|
|
131
93
|
const callingState = useCallCallingState();
|
|
@@ -133,6 +95,7 @@ export const useAndroidKeepCallAliveEffect = () => {
|
|
|
133
95
|
const isOutgoingCall =
|
|
134
96
|
callingState === CallingState.RINGING && call?.isCreatedByMe;
|
|
135
97
|
const isCallJoined = callingState === CallingState.JOINED;
|
|
98
|
+
const isNonRingingCall = !call?.ringing;
|
|
136
99
|
|
|
137
100
|
const shouldStartForegroundService =
|
|
138
101
|
!foregroundServiceStartedRef.current && (isOutgoingCall || isCallJoined);
|
|
@@ -141,7 +104,15 @@ export const useAndroidKeepCallAliveEffect = () => {
|
|
|
141
104
|
if (Platform.OS === 'ios' || !activeCallCid) {
|
|
142
105
|
return undefined;
|
|
143
106
|
}
|
|
144
|
-
|
|
107
|
+
|
|
108
|
+
const callingx = getCallingxLibIfAvailable();
|
|
109
|
+
if (
|
|
110
|
+
callingx?.isSetup &&
|
|
111
|
+
isNonRingingCall &&
|
|
112
|
+
callingx?.isOngoingCallsEnabled
|
|
113
|
+
) {
|
|
114
|
+
return undefined;
|
|
115
|
+
}
|
|
145
116
|
|
|
146
117
|
// start foreground service as soon as the call is joined
|
|
147
118
|
if (shouldStartForegroundService) {
|
|
@@ -149,23 +120,21 @@ export const useAndroidKeepCallAliveEffect = () => {
|
|
|
149
120
|
if (foregroundServiceStartedRef.current) {
|
|
150
121
|
return;
|
|
151
122
|
}
|
|
152
|
-
if
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
notifee.cancelDisplayedNotification(activeCallCid);
|
|
123
|
+
// Optional compatibility cleanup: if the app uses Notifee for ringing push,
|
|
124
|
+
// we might have an incoming call notification running as a foreground service.
|
|
125
|
+
if (notifeeLib) {
|
|
126
|
+
const notifee = notifeeLib.default;
|
|
127
|
+
const displayedNotifications =
|
|
128
|
+
await notifee.getDisplayedNotifications();
|
|
129
|
+
const activeCallNotification = displayedNotifications.find(
|
|
130
|
+
(notification) => notification.id === activeCallCid,
|
|
131
|
+
);
|
|
132
|
+
if (activeCallNotification) {
|
|
133
|
+
// this means that we have a incoming call notification shown as foreground service and we must stop it
|
|
134
|
+
notifee.stopForegroundService();
|
|
135
|
+
notifee.cancelDisplayedNotification(activeCallCid);
|
|
136
|
+
}
|
|
167
137
|
}
|
|
168
|
-
// check for notification permission and then start the foreground service
|
|
169
138
|
|
|
170
139
|
await startForegroundService(activeCallCid);
|
|
171
140
|
foregroundServiceStartedRef.current = true;
|
|
@@ -174,7 +143,6 @@ export const useAndroidKeepCallAliveEffect = () => {
|
|
|
174
143
|
// ensure that app is active before running the function
|
|
175
144
|
if (AppState.currentState === 'active') {
|
|
176
145
|
run();
|
|
177
|
-
return undefined;
|
|
178
146
|
}
|
|
179
147
|
const sub = AppState.addEventListener(
|
|
180
148
|
'change',
|
|
@@ -192,42 +160,49 @@ export const useAndroidKeepCallAliveEffect = () => {
|
|
|
192
160
|
return () => {
|
|
193
161
|
// cancel any notifee displayed notification when the call has transitioned out of ringing
|
|
194
162
|
// NOTE: cancels only the non fg service notifications
|
|
195
|
-
notifeeLib
|
|
163
|
+
if (notifeeLib) {
|
|
164
|
+
notifeeLib.default.cancelDisplayedNotification(activeCallCid);
|
|
165
|
+
}
|
|
196
166
|
};
|
|
197
167
|
} else if (
|
|
198
168
|
callingState === CallingState.IDLE ||
|
|
199
169
|
callingState === CallingState.LEFT
|
|
200
170
|
) {
|
|
201
171
|
if (foregroundServiceStartedRef.current) {
|
|
202
|
-
|
|
172
|
+
keepCallAliveCallRef.current = undefined;
|
|
203
173
|
// stop foreground service when the call is not active
|
|
204
|
-
|
|
174
|
+
stopForegroundServiceNoThrow();
|
|
205
175
|
foregroundServiceStartedRef.current = false;
|
|
206
176
|
} else {
|
|
207
|
-
notifeeLib
|
|
208
|
-
.
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
177
|
+
if (notifeeLib) {
|
|
178
|
+
notifeeLib.default
|
|
179
|
+
.getDisplayedNotifications()
|
|
180
|
+
.then((displayedNotifications) => {
|
|
181
|
+
const activeCallNotification = displayedNotifications.find(
|
|
182
|
+
(notification) => notification.id === activeCallCid,
|
|
183
|
+
);
|
|
184
|
+
if (activeCallNotification) {
|
|
185
|
+
// this means that we have a incoming call notification shown as foreground service and we must stop it
|
|
186
|
+
notifeeLib.default.stopForegroundService();
|
|
187
|
+
}
|
|
188
|
+
});
|
|
189
|
+
}
|
|
219
190
|
}
|
|
220
191
|
}
|
|
221
192
|
return undefined;
|
|
222
|
-
}, [
|
|
193
|
+
}, [
|
|
194
|
+
activeCallCid,
|
|
195
|
+
callingState,
|
|
196
|
+
shouldStartForegroundService,
|
|
197
|
+
isNonRingingCall,
|
|
198
|
+
]);
|
|
223
199
|
|
|
224
200
|
useEffect(() => {
|
|
225
201
|
return () => {
|
|
226
202
|
// stop foreground service when this effect is unmounted
|
|
227
203
|
if (foregroundServiceStartedRef.current) {
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
notifeeLib.default.stopForegroundService();
|
|
204
|
+
keepCallAliveCallRef.current = undefined;
|
|
205
|
+
stopForegroundServiceNoThrow();
|
|
231
206
|
foregroundServiceStartedRef.current = false;
|
|
232
207
|
}
|
|
233
208
|
};
|
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`
|
|
@@ -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
|
|
|
@@ -1,12 +1,12 @@
|
|
|
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';
|
|
7
6
|
import { AppStateListener } from './AppStateListener';
|
|
8
7
|
import { DeviceStats } from './DeviceStats';
|
|
9
8
|
import { pushUnsubscriptionCallbacks } from '../../utils/push/internal/constants';
|
|
9
|
+
import { useCallingExpWithCallingStateEffect } from '../../hooks/push/useCallingExpWithCallingStateEffect';
|
|
10
10
|
|
|
11
11
|
// const PIP_CHANGE_EVENT = 'StreamVideoReactNative_PIP_CHANGE_EVENT';
|
|
12
12
|
|
|
@@ -34,7 +34,7 @@ export const StreamCall = ({
|
|
|
34
34
|
<StreamCallProvider call={call}>
|
|
35
35
|
<AppStateListener />
|
|
36
36
|
<AndroidKeepCallAlive />
|
|
37
|
-
<
|
|
37
|
+
<CallingExpWithCallingState />
|
|
38
38
|
<ClearPushWSSubscriptions />
|
|
39
39
|
<DeviceStats />
|
|
40
40
|
{children}
|
|
@@ -52,11 +52,11 @@ const AndroidKeepCallAlive = () => {
|
|
|
52
52
|
};
|
|
53
53
|
|
|
54
54
|
/**
|
|
55
|
-
* This is a renderless component to
|
|
56
|
-
*
|
|
55
|
+
* This is a renderless component to sync state between stream call and CallKit/Telecom.
|
|
56
|
+
* useCallingExpWithCallingStateEffect needs to called inside a child of StreamCallProvider.
|
|
57
57
|
*/
|
|
58
|
-
const
|
|
59
|
-
|
|
58
|
+
const CallingExpWithCallingState = () => {
|
|
59
|
+
useCallingExpWithCallingStateEffect();
|
|
60
60
|
return null;
|
|
61
61
|
};
|
|
62
62
|
|
|
@@ -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,26 @@ 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: (text: string) => text,
|
|
109
|
+
* subtitleTransformer: (text: string) => text,
|
|
110
|
+
* },
|
|
111
|
+
* };
|
|
112
|
+
* StreamVideoRN.setPushConfig(pushConfig, callingExpOptions);
|
|
106
113
|
* AppRegistry.registerComponent('app', () => App);
|
|
107
114
|
*/
|
|
108
115
|
static setPushConfig(pushConfig: NonNullable<StreamVideoConfig['push']>) {
|
|
@@ -110,20 +117,23 @@ export class StreamVideoRN {
|
|
|
110
117
|
// Ignoring this config as push config was already set
|
|
111
118
|
return;
|
|
112
119
|
}
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
120
|
+
|
|
121
|
+
this.config.push = pushConfig;
|
|
122
|
+
|
|
123
|
+
try {
|
|
124
|
+
const callingx = getCallingxLib();
|
|
125
|
+
videoLoggerSystem
|
|
126
|
+
.getLogger('StreamVideoRN.setPushConfig')
|
|
127
|
+
.info(JSON.stringify(this.config));
|
|
128
|
+
const options = extractCallingExpOptions(this.config);
|
|
129
|
+
callingx.setup(options);
|
|
130
|
+
} catch {
|
|
117
131
|
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.`,
|
|
132
|
+
'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
133
|
);
|
|
122
134
|
}
|
|
123
135
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
setupIosCallKeepEvents(pushConfig);
|
|
136
|
+
setupCallingExpEvents(pushConfig);
|
|
127
137
|
setupIosVoipPushEvents(pushConfig);
|
|
128
138
|
}
|
|
129
139
|
|
|
@@ -5,6 +5,18 @@ import {
|
|
|
5
5
|
} from '@stream-io/video-client';
|
|
6
6
|
import type { AndroidChannel } from '@notifee/react-native';
|
|
7
7
|
|
|
8
|
+
export type AndroidChannelConfig = {
|
|
9
|
+
id: string;
|
|
10
|
+
name: string;
|
|
11
|
+
sound?: string;
|
|
12
|
+
vibration?: boolean;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export type KeepAliveAndroidNotificationTexts = {
|
|
16
|
+
title: string;
|
|
17
|
+
body: string;
|
|
18
|
+
};
|
|
19
|
+
|
|
8
20
|
export type NonRingingPushEvent =
|
|
9
21
|
| 'call.live_started'
|
|
10
22
|
| 'call.notification'
|
|
@@ -32,6 +44,27 @@ export type StreamVideoConfig = {
|
|
|
32
44
|
* @example "production-apn-video" or "staging-apn-video" based on the environment
|
|
33
45
|
*/
|
|
34
46
|
pushProviderName?: string;
|
|
47
|
+
supportsVideo?: boolean;
|
|
48
|
+
/**
|
|
49
|
+
* Sound to play when an incoming call is received. Must be a valid sound resource name in the project.
|
|
50
|
+
* @default '' (no sound)
|
|
51
|
+
*/
|
|
52
|
+
sound?: string;
|
|
53
|
+
/**
|
|
54
|
+
* Image to display when an incoming call is received. Must be a valid image resource name in the project.
|
|
55
|
+
* @default '' (no image)
|
|
56
|
+
*/
|
|
57
|
+
imageName?: string;
|
|
58
|
+
/**
|
|
59
|
+
* Enable calls history. When enabled, the call will be added to the calls history.
|
|
60
|
+
* @default false
|
|
61
|
+
*/
|
|
62
|
+
callsHistory?: boolean;
|
|
63
|
+
/**
|
|
64
|
+
* Timeout to display an incoming call. When the call is displayed for more than the timeout, the call will be rejected.
|
|
65
|
+
* @default 60000 (1 minute)
|
|
66
|
+
*/
|
|
67
|
+
displayCallTimeout?: number;
|
|
35
68
|
};
|
|
36
69
|
android: {
|
|
37
70
|
/**
|
|
@@ -61,28 +94,21 @@ export type StreamVideoConfig = {
|
|
|
61
94
|
* The notification channel to be used for incoming calls for Android.
|
|
62
95
|
* @example
|
|
63
96
|
* {
|
|
64
|
-
* id: '
|
|
65
|
-
* name: 'Incoming
|
|
66
|
-
*
|
|
97
|
+
* id: 'incoming_calls_channel',
|
|
98
|
+
* name: 'Incoming calls',
|
|
99
|
+
* sound?: string;
|
|
100
|
+
* vibration?: boolean;
|
|
67
101
|
* }
|
|
68
102
|
*/
|
|
69
|
-
|
|
103
|
+
incomingChannel?: AndroidChannelConfig;
|
|
70
104
|
/**
|
|
71
|
-
*
|
|
72
|
-
* @example
|
|
73
|
-
* {
|
|
74
|
-
* getTitle: (createdUserName: string) => `Incoming call from ${createdUserName}`,
|
|
75
|
-
* getBody: (createdUserName: string) => `Tap to answer the call`
|
|
76
|
-
* getAcceptButtonTitle?: () => `Accept`,
|
|
77
|
-
* getDeclineButtonTitle?: () => `Decline`,
|
|
78
|
-
* }
|
|
105
|
+
* The transformer to be used to transform the call title in the notification for ringing and ongoing calls for Android.
|
|
79
106
|
*/
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
};
|
|
107
|
+
titleTransformer?: (memberName: string, incoming: boolean) => string;
|
|
108
|
+
/**
|
|
109
|
+
* The transformer to be used to transform the call subtitle for ringing and ongoing calls for Android.
|
|
110
|
+
*/
|
|
111
|
+
subtitleTransformer?: (call_cid: string, incoming: boolean) => string;
|
|
86
112
|
/**
|
|
87
113
|
* Functions to create the texts shown in the notification for non ringing calls in Android.
|
|
88
114
|
* @example
|
|
@@ -111,6 +137,16 @@ export type StreamVideoConfig = {
|
|
|
111
137
|
getBody: (type: NonRingingPushEvent, createdUserName: string) => string;
|
|
112
138
|
};
|
|
113
139
|
};
|
|
140
|
+
/**
|
|
141
|
+
* Whether to enable ongoing calls.
|
|
142
|
+
* @default false
|
|
143
|
+
*/
|
|
144
|
+
enableOngoingCalls?: boolean;
|
|
145
|
+
/**
|
|
146
|
+
* Whether to reject calls when the user is busy.
|
|
147
|
+
* @default false
|
|
148
|
+
*/
|
|
149
|
+
shouldRejectCallWhenBusy?: boolean;
|
|
114
150
|
/**
|
|
115
151
|
* This function is used to create a custom video client.
|
|
116
152
|
* This is used create a video client for incoming calls in the background and inform call events to the server.
|
|
@@ -130,12 +166,6 @@ export type StreamVideoConfig = {
|
|
|
130
166
|
* }
|
|
131
167
|
*/
|
|
132
168
|
createStreamVideoClient: () => Promise<StreamVideoClient | undefined>;
|
|
133
|
-
/** @deprecated This method will be removed in the future. Please watch for incoming and outgoing calls in the root component of your app.
|
|
134
|
-
Please see https://getstream.io/video/docs/react-native/advanced/ringing-calls/#watch-for-incoming-and-outgoing-calls for more information */
|
|
135
|
-
navigateAcceptCall?: () => void;
|
|
136
|
-
/** @deprecated This method will be removed in the future. Please watch for incoming and outgoing calls in the root component of your app.
|
|
137
|
-
Please see https://getstream.io/video/docs/react-native/advanced/ringing-calls/#watch-for-incoming-and-outgoing-calls for more information */
|
|
138
|
-
navigateToIncomingCall?: () => void;
|
|
139
169
|
/** Callback that is called when a non ringing push notification was tapped */
|
|
140
170
|
onTapNonRingingCallNotification?: (
|
|
141
171
|
call_cid: string,
|
|
@@ -147,14 +177,11 @@ export type StreamVideoConfig = {
|
|
|
147
177
|
/**
|
|
148
178
|
* The notification channel to keep call alive in the background for Android using a foreground service.
|
|
149
179
|
*/
|
|
150
|
-
channel:
|
|
180
|
+
channel: Omit<AndroidChannelConfig, 'sound' | 'vibration'>;
|
|
151
181
|
/**
|
|
152
182
|
* The texts shown in the notification to keep call alive in the background
|
|
153
183
|
*/
|
|
154
|
-
notificationTexts:
|
|
155
|
-
title: string;
|
|
156
|
-
body: string;
|
|
157
|
-
};
|
|
184
|
+
notificationTexts: KeepAliveAndroidNotificationTexts;
|
|
158
185
|
/**
|
|
159
186
|
* The task to run in the foreground service
|
|
160
187
|
* The task must resolve a promise once complete
|