@stream-io/video-react-native-sdk 1.2.14 → 1.3.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 +13 -0
- package/dist/commonjs/hooks/push/useIosCallKeepEventsSetupEffect.js +43 -6
- package/dist/commonjs/hooks/push/useIosCallKeepEventsSetupEffect.js.map +1 -1
- package/dist/commonjs/hooks/push/useIosCallkeepWithCallingStateEffect.js +1 -1
- package/dist/commonjs/hooks/push/useIosVoipPushEventsSetupEffect.js +2 -2
- package/dist/commonjs/hooks/push/useProcessPushCallEffect.js +2 -7
- package/dist/commonjs/hooks/push/useProcessPushCallEffect.js.map +1 -1
- package/dist/commonjs/hooks/push/useProcessPushNonRingingCallEffect.js +3 -3
- package/dist/commonjs/hooks/useAndroidKeepCallAliveEffect.js +1 -0
- package/dist/commonjs/hooks/useAndroidKeepCallAliveEffect.js.map +1 -1
- package/dist/commonjs/providers/StreamCall.js +1 -1
- package/dist/commonjs/utils/StreamVideoRN/index.js +5 -6
- package/dist/commonjs/utils/StreamVideoRN/index.js.map +1 -1
- package/dist/commonjs/utils/index.js +12 -0
- package/dist/commonjs/utils/index.js.map +1 -1
- package/dist/commonjs/utils/push/android.js +23 -79
- package/dist/commonjs/utils/push/android.js.map +1 -1
- package/dist/commonjs/utils/push/index.js +39 -0
- package/dist/commonjs/utils/push/index.js.map +1 -0
- package/dist/commonjs/utils/push/internal/rxSubjects.js.map +1 -0
- package/dist/commonjs/utils/push/internal/utils.js +157 -0
- package/dist/commonjs/utils/push/internal/utils.js.map +1 -0
- package/dist/commonjs/utils/push/ios.js +43 -84
- package/dist/commonjs/utils/push/ios.js.map +1 -1
- package/dist/commonjs/utils/push/libs/expoNotifications.js.map +1 -1
- package/dist/commonjs/utils/push/libs/index.js +0 -11
- package/dist/commonjs/utils/push/libs/index.js.map +1 -1
- package/dist/commonjs/utils/push/libs/iosPushNotification.js.map +1 -1
- package/dist/commonjs/utils/push/utils.js +29 -150
- package/dist/commonjs/utils/push/utils.js.map +1 -1
- package/dist/commonjs/version.js +1 -1
- package/dist/commonjs/version.js.map +1 -1
- package/dist/module/hooks/push/useIosCallKeepEventsSetupEffect.js +41 -4
- package/dist/module/hooks/push/useIosCallKeepEventsSetupEffect.js.map +1 -1
- package/dist/module/hooks/push/useIosCallkeepWithCallingStateEffect.js +1 -1
- package/dist/module/hooks/push/useIosCallkeepWithCallingStateEffect.js.map +1 -1
- package/dist/module/hooks/push/useIosVoipPushEventsSetupEffect.js +2 -2
- package/dist/module/hooks/push/useIosVoipPushEventsSetupEffect.js.map +1 -1
- package/dist/module/hooks/push/useProcessPushCallEffect.js +2 -7
- package/dist/module/hooks/push/useProcessPushCallEffect.js.map +1 -1
- package/dist/module/hooks/push/useProcessPushNonRingingCallEffect.js +3 -3
- package/dist/module/hooks/push/useProcessPushNonRingingCallEffect.js.map +1 -1
- package/dist/module/hooks/useAndroidKeepCallAliveEffect.js +1 -0
- package/dist/module/hooks/useAndroidKeepCallAliveEffect.js.map +1 -1
- package/dist/module/providers/StreamCall.js +1 -1
- package/dist/module/providers/StreamCall.js.map +1 -1
- package/dist/module/utils/StreamVideoRN/index.js +5 -6
- package/dist/module/utils/StreamVideoRN/index.js.map +1 -1
- package/dist/module/utils/index.js +1 -0
- package/dist/module/utils/index.js.map +1 -1
- package/dist/module/utils/push/android.js +20 -79
- package/dist/module/utils/push/android.js.map +1 -1
- package/dist/module/utils/push/index.js +4 -0
- package/dist/module/utils/push/index.js.map +1 -0
- package/dist/module/utils/push/internal/rxSubjects.js.map +1 -0
- package/dist/module/utils/push/internal/utils.js +146 -0
- package/dist/module/utils/push/internal/utils.js.map +1 -0
- package/dist/module/utils/push/ios.js +40 -81
- package/dist/module/utils/push/ios.js.map +1 -1
- package/dist/module/utils/push/libs/expoNotifications.js.map +1 -1
- package/dist/module/utils/push/libs/index.js +0 -1
- package/dist/module/utils/push/libs/index.js.map +1 -1
- package/dist/module/utils/push/libs/iosPushNotification.js.map +1 -1
- package/dist/module/utils/push/utils.js +25 -144
- package/dist/module/utils/push/utils.js.map +1 -1
- package/dist/module/version.js +1 -1
- package/dist/module/version.js.map +1 -1
- package/dist/typescript/hooks/push/useIosCallKeepEventsSetupEffect.d.ts.map +1 -1
- package/dist/typescript/hooks/useAndroidKeepCallAliveEffect.d.ts.map +1 -1
- package/dist/typescript/utils/StreamVideoRN/index.d.ts.map +1 -1
- package/dist/typescript/utils/StreamVideoRN/types.d.ts +6 -4
- package/dist/typescript/utils/StreamVideoRN/types.d.ts.map +1 -1
- package/dist/typescript/utils/index.d.ts +1 -0
- package/dist/typescript/utils/index.d.ts.map +1 -1
- package/dist/typescript/utils/push/android.d.ts +12 -2
- package/dist/typescript/utils/push/android.d.ts.map +1 -1
- package/dist/typescript/utils/push/index.d.ts +4 -0
- package/dist/typescript/utils/push/index.d.ts.map +1 -0
- package/dist/typescript/utils/push/{rxSubjects.d.ts → internal/rxSubjects.d.ts} +1 -1
- package/dist/typescript/utils/push/internal/rxSubjects.d.ts.map +1 -0
- package/dist/typescript/utils/push/internal/utils.d.ts +43 -0
- package/dist/typescript/utils/push/internal/utils.d.ts.map +1 -0
- package/dist/typescript/utils/push/ios.d.ts +8 -3
- package/dist/typescript/utils/push/ios.d.ts.map +1 -1
- package/dist/typescript/utils/push/libs/expoNotifications.d.ts +2 -0
- package/dist/typescript/utils/push/libs/expoNotifications.d.ts.map +1 -1
- package/dist/typescript/utils/push/libs/index.d.ts +0 -1
- package/dist/typescript/utils/push/libs/index.d.ts.map +1 -1
- package/dist/typescript/utils/push/libs/iosPushNotification.d.ts +2 -0
- package/dist/typescript/utils/push/libs/iosPushNotification.d.ts.map +1 -1
- package/dist/typescript/utils/push/utils.d.ts +14 -42
- package/dist/typescript/utils/push/utils.d.ts.map +1 -1
- package/dist/typescript/version.d.ts +1 -1
- package/dist/typescript/version.d.ts.map +1 -1
- package/package.json +6 -11
- package/src/hooks/push/useIosCallKeepEventsSetupEffect.ts +62 -6
- package/src/hooks/push/useIosCallkeepWithCallingStateEffect.ts +1 -1
- package/src/hooks/push/useIosVoipPushEventsSetupEffect.ts +2 -2
- package/src/hooks/push/useProcessPushCallEffect.ts +2 -7
- package/src/hooks/push/useProcessPushNonRingingCallEffect.ts +3 -3
- package/src/hooks/useAndroidKeepCallAliveEffect.ts +1 -0
- package/src/providers/StreamCall.tsx +1 -1
- package/src/utils/StreamVideoRN/index.ts +11 -6
- package/src/utils/StreamVideoRN/types.ts +6 -4
- package/src/utils/index.ts +1 -0
- package/src/utils/push/android.ts +28 -99
- package/src/utils/push/index.ts +3 -0
- package/src/utils/push/{rxSubjects.ts → internal/rxSubjects.ts} +1 -1
- package/src/utils/push/internal/utils.ts +178 -0
- package/src/utils/push/ios.ts +49 -115
- package/src/utils/push/libs/expoNotifications.ts +4 -0
- package/src/utils/push/libs/index.ts +0 -1
- package/src/utils/push/libs/iosPushNotification.ts +4 -0
- package/src/utils/push/utils.ts +44 -175
- package/src/version.ts +1 -1
- package/dist/commonjs/utils/push/libs/expoTaskManager.js +0 -17
- package/dist/commonjs/utils/push/libs/expoTaskManager.js.map +0 -1
- package/dist/commonjs/utils/push/rxSubjects.js.map +0 -1
- package/dist/module/utils/push/libs/expoTaskManager.js +0 -11
- package/dist/module/utils/push/libs/expoTaskManager.js.map +0 -1
- package/dist/module/utils/push/rxSubjects.js.map +0 -1
- package/dist/typescript/utils/push/libs/expoTaskManager.d.ts +0 -3
- package/dist/typescript/utils/push/libs/expoTaskManager.d.ts.map +0 -1
- package/dist/typescript/utils/push/rxSubjects.d.ts.map +0 -1
- package/src/utils/push/libs/expoTaskManager.ts +0 -16
- /package/dist/commonjs/utils/push/{rxSubjects.js → internal/rxSubjects.js} +0 -0
- /package/dist/module/utils/push/{rxSubjects.js → internal/rxSubjects.js} +0 -0
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { FirebaseMessagingTypes } from '@react-native-firebase/messaging';
|
|
2
1
|
import {
|
|
3
2
|
Call,
|
|
4
3
|
RxUtils,
|
|
@@ -12,11 +11,10 @@ import type {
|
|
|
12
11
|
} from '../StreamVideoRN/types';
|
|
13
12
|
import {
|
|
14
13
|
getFirebaseMessagingLib,
|
|
15
|
-
getFirebaseMessagingLibNoThrow,
|
|
16
14
|
getExpoNotificationsLib,
|
|
17
|
-
getExpoTaskManagerLib,
|
|
18
15
|
getNotifeeLibThrowIfNotInstalledForPush,
|
|
19
16
|
NotifeeLib,
|
|
17
|
+
FirebaseMessagingTypes,
|
|
20
18
|
} from './libs';
|
|
21
19
|
import {
|
|
22
20
|
pushAcceptedIncomingCallCId$,
|
|
@@ -25,15 +23,16 @@ import {
|
|
|
25
23
|
pushNonRingingCallData$,
|
|
26
24
|
pushUnsubscriptionCallbacks$,
|
|
27
25
|
pushAndroidBackgroundDeliveredIncomingCallCId$,
|
|
28
|
-
} from './rxSubjects';
|
|
26
|
+
} from './internal/rxSubjects';
|
|
29
27
|
import {
|
|
30
28
|
canAddPushWSSubscriptionsRef,
|
|
31
29
|
clearPushWSEventSubscriptions,
|
|
32
30
|
processCallFromPushInBackground,
|
|
33
31
|
shouldCallBeEnded,
|
|
34
|
-
} from './utils';
|
|
32
|
+
} from './internal/utils';
|
|
35
33
|
import { setPushLogoutCallback } from '../internal/pushLogoutCallback';
|
|
36
34
|
import { getAndroidDefaultRingtoneUrl } from '../getAndroidDefaultRingtoneUrl';
|
|
35
|
+
import { StreamVideoRN } from '../StreamVideoRN';
|
|
37
36
|
|
|
38
37
|
const ACCEPT_CALL_ACTION_ID = 'accept';
|
|
39
38
|
const DECLINE_CALL_ACTION_ID = 'decline';
|
|
@@ -48,89 +47,6 @@ type Event = Parameters<onBackgroundEventFunctionParams>[0];
|
|
|
48
47
|
|
|
49
48
|
let lastFirebaseToken = { token: '', userId: '' };
|
|
50
49
|
|
|
51
|
-
// EventType = NotifeeLib['EventType'];
|
|
52
|
-
|
|
53
|
-
/** Setup Firebase push message handler **/
|
|
54
|
-
export function setupFirebaseHandlerAndroid(pushConfig: PushConfig) {
|
|
55
|
-
if (Platform.OS !== 'android') {
|
|
56
|
-
return;
|
|
57
|
-
}
|
|
58
|
-
if (pushConfig.isExpo) {
|
|
59
|
-
const messaging = getFirebaseMessagingLibNoThrow(true);
|
|
60
|
-
if (messaging) {
|
|
61
|
-
// handles on app killed state in expo, expo-notifications cannot handle that
|
|
62
|
-
messaging().setBackgroundMessageHandler(
|
|
63
|
-
async (msg) =>
|
|
64
|
-
await firebaseMessagingOnMessageHandler(msg.data, pushConfig)
|
|
65
|
-
);
|
|
66
|
-
messaging().onMessage((msg) =>
|
|
67
|
-
firebaseMessagingOnMessageHandler(msg.data, pushConfig)
|
|
68
|
-
); // this is to listen to foreground messages, which we dont need for now
|
|
69
|
-
} else {
|
|
70
|
-
const Notifications = getExpoNotificationsLib();
|
|
71
|
-
const TaskManager = getExpoTaskManagerLib();
|
|
72
|
-
const BACKGROUND_NOTIFICATION_TASK =
|
|
73
|
-
'STREAM-VIDEO-SDK-INTERNAL-BACKGROUND-NOTIFICATION-TASK';
|
|
74
|
-
|
|
75
|
-
TaskManager.defineTask(
|
|
76
|
-
BACKGROUND_NOTIFICATION_TASK,
|
|
77
|
-
({ data, error }) => {
|
|
78
|
-
if (error) {
|
|
79
|
-
return;
|
|
80
|
-
}
|
|
81
|
-
// @ts-ignore
|
|
82
|
-
const dataToProcess = data.notification?.data;
|
|
83
|
-
firebaseMessagingOnMessageHandler(dataToProcess, pushConfig);
|
|
84
|
-
}
|
|
85
|
-
);
|
|
86
|
-
// background handler (does not handle on app killed state)
|
|
87
|
-
Notifications.registerTaskAsync(BACKGROUND_NOTIFICATION_TASK);
|
|
88
|
-
// foreground handler
|
|
89
|
-
Notifications.setNotificationHandler({
|
|
90
|
-
handleNotification: async (notification) => {
|
|
91
|
-
// @ts-ignore
|
|
92
|
-
const trigger = notification?.request?.trigger;
|
|
93
|
-
if (trigger.type === 'push') {
|
|
94
|
-
const data = trigger?.remoteMessage?.data;
|
|
95
|
-
if (data?.sender === 'stream.video') {
|
|
96
|
-
await firebaseMessagingOnMessageHandler(data, pushConfig);
|
|
97
|
-
return {
|
|
98
|
-
shouldShowAlert: false,
|
|
99
|
-
shouldPlaySound: false,
|
|
100
|
-
shouldSetBadge: false,
|
|
101
|
-
};
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
return {
|
|
105
|
-
shouldShowAlert: true,
|
|
106
|
-
shouldPlaySound: false,
|
|
107
|
-
shouldSetBadge: false,
|
|
108
|
-
};
|
|
109
|
-
},
|
|
110
|
-
});
|
|
111
|
-
}
|
|
112
|
-
} else {
|
|
113
|
-
const messaging = getFirebaseMessagingLib();
|
|
114
|
-
messaging().setBackgroundMessageHandler(
|
|
115
|
-
async (msg) =>
|
|
116
|
-
await firebaseMessagingOnMessageHandler(msg.data, pushConfig)
|
|
117
|
-
);
|
|
118
|
-
messaging().onMessage((msg) =>
|
|
119
|
-
firebaseMessagingOnMessageHandler(msg.data, pushConfig)
|
|
120
|
-
); // this is to listen to foreground messages, which we dont need for now
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
// the notification tap handlers are always registered with notifee for both expo and non-expo in android
|
|
124
|
-
const notifeeLib = getNotifeeLibThrowIfNotInstalledForPush();
|
|
125
|
-
const notifee = notifeeLib.default;
|
|
126
|
-
notifee.onBackgroundEvent(async (event) => {
|
|
127
|
-
await onNotifeeEvent(event, pushConfig, true);
|
|
128
|
-
});
|
|
129
|
-
notifee.onForegroundEvent((event) => {
|
|
130
|
-
onNotifeeEvent(event, pushConfig, false);
|
|
131
|
-
});
|
|
132
|
-
}
|
|
133
|
-
|
|
134
50
|
/** Send token to stream, create notification channel, */
|
|
135
51
|
export async function initAndroidPushToken(
|
|
136
52
|
client: StreamVideoClient,
|
|
@@ -184,10 +100,14 @@ export async function initAndroidPushToken(
|
|
|
184
100
|
}
|
|
185
101
|
}
|
|
186
102
|
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
103
|
+
/**
|
|
104
|
+
* Creates notification from the push message data.
|
|
105
|
+
* For Ringing and Non-Ringing calls.
|
|
106
|
+
*/
|
|
107
|
+
export const firebaseDataHandler = async (
|
|
108
|
+
data: FirebaseMessagingTypes.RemoteMessage['data']
|
|
190
109
|
) => {
|
|
110
|
+
if (Platform.OS !== 'android') return;
|
|
191
111
|
/* Example data from firebase
|
|
192
112
|
"message": {
|
|
193
113
|
"data": {
|
|
@@ -203,7 +123,8 @@ const firebaseMessagingOnMessageHandler = async (
|
|
|
203
123
|
// other stuff
|
|
204
124
|
}
|
|
205
125
|
*/
|
|
206
|
-
|
|
126
|
+
const pushConfig = StreamVideoRN.getConfig().push;
|
|
127
|
+
if (!pushConfig || !data || data.sender !== 'stream.video') {
|
|
207
128
|
return;
|
|
208
129
|
}
|
|
209
130
|
|
|
@@ -377,16 +298,25 @@ const firebaseMessagingOnMessageHandler = async (
|
|
|
377
298
|
}
|
|
378
299
|
};
|
|
379
300
|
|
|
380
|
-
const
|
|
381
|
-
event
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
301
|
+
export const onAndroidNotifeeEvent = async ({
|
|
302
|
+
event,
|
|
303
|
+
isBackground,
|
|
304
|
+
}: {
|
|
305
|
+
event: Event;
|
|
306
|
+
isBackground: boolean;
|
|
307
|
+
}) => {
|
|
308
|
+
if (Platform.OS !== 'android') return;
|
|
385
309
|
const { type, detail } = event;
|
|
386
310
|
const { notification, pressAction } = detail;
|
|
387
311
|
const notificationId = notification?.id;
|
|
388
312
|
const data = notification?.data;
|
|
389
|
-
|
|
313
|
+
const pushConfig = StreamVideoRN.getConfig().push;
|
|
314
|
+
if (
|
|
315
|
+
!pushConfig ||
|
|
316
|
+
!data ||
|
|
317
|
+
!notificationId ||
|
|
318
|
+
data.sender !== 'stream.video'
|
|
319
|
+
) {
|
|
390
320
|
return;
|
|
391
321
|
}
|
|
392
322
|
|
|
@@ -443,7 +373,6 @@ const onNotifeeEvent = async (
|
|
|
443
373
|
} else {
|
|
444
374
|
const notifeeLib = getNotifeeLibThrowIfNotInstalledForPush();
|
|
445
375
|
if (type === notifeeLib.EventType.PRESS) {
|
|
446
|
-
pushTappedIncomingCallCId$.next(call_cid);
|
|
447
376
|
pushConfig.onTapNonRingingCallNotification?.(
|
|
448
377
|
call_cid,
|
|
449
378
|
data.type as NonRingingPushEvent
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { BehaviorSubject } from 'rxjs';
|
|
2
|
-
import { NonRingingPushEvent } from '
|
|
2
|
+
import { NonRingingPushEvent } from '../../StreamVideoRN/types';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* This rxjs subject is used to store the call cid of the accepted incoming call from push notification
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Call,
|
|
3
|
+
RxUtils,
|
|
4
|
+
StreamVideoClient,
|
|
5
|
+
getLogger,
|
|
6
|
+
} from '@stream-io/video-client';
|
|
7
|
+
import type {
|
|
8
|
+
NonRingingPushEvent,
|
|
9
|
+
StreamVideoConfig,
|
|
10
|
+
} from '../../StreamVideoRN/types';
|
|
11
|
+
import { onNewCallNotification } from '../../internal/newNotificationCallbacks';
|
|
12
|
+
import { pushUnsubscriptionCallbacks$ } from './rxSubjects';
|
|
13
|
+
|
|
14
|
+
type PushConfig = NonNullable<StreamVideoConfig['push']>;
|
|
15
|
+
|
|
16
|
+
type CanAddPushWSSubscriptionsRef = { current: boolean };
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* This function is used to check if the call should be ended based on the push notification
|
|
20
|
+
* Useful for callkeep management to end the call if necessary (with reportEndCallWithUUID)
|
|
21
|
+
*/
|
|
22
|
+
export const shouldCallBeEnded = (
|
|
23
|
+
callFromPush: Call,
|
|
24
|
+
created_by_id: string | undefined,
|
|
25
|
+
receiver_id: string | undefined
|
|
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
|
+
*/
|
|
35
|
+
const callSession = callFromPush.state.session;
|
|
36
|
+
const rejected_by = callSession?.rejected_by;
|
|
37
|
+
const accepted_by = callSession?.accepted_by;
|
|
38
|
+
let mustEndCall = false;
|
|
39
|
+
let callkeepReason = 0;
|
|
40
|
+
if (created_by_id && rejected_by) {
|
|
41
|
+
if (rejected_by[created_by_id]) {
|
|
42
|
+
// call was cancelled by the caller
|
|
43
|
+
mustEndCall = true;
|
|
44
|
+
callkeepReason = 2;
|
|
45
|
+
}
|
|
46
|
+
} else if (receiver_id && rejected_by) {
|
|
47
|
+
if (rejected_by[receiver_id]) {
|
|
48
|
+
// call was rejected by the receiver in some other device
|
|
49
|
+
mustEndCall = true;
|
|
50
|
+
callkeepReason = 5;
|
|
51
|
+
}
|
|
52
|
+
} else if (receiver_id && accepted_by) {
|
|
53
|
+
if (accepted_by[receiver_id]) {
|
|
54
|
+
// call was accepted by the receiver in some other device
|
|
55
|
+
mustEndCall = true;
|
|
56
|
+
callkeepReason = 4;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return { mustEndCall, callkeepReason };
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
/* An action for the notification or callkeep and app does not have JS context setup yet, so we need to do two steps:
|
|
63
|
+
1. we need to create a new client and connect the user to decline the call
|
|
64
|
+
2. this is because the app is in background state and we don't have a client to get the call and do an action
|
|
65
|
+
*/
|
|
66
|
+
export const processCallFromPushInBackground = async (
|
|
67
|
+
pushConfig: PushConfig,
|
|
68
|
+
call_cid: string,
|
|
69
|
+
action: Parameters<typeof processCallFromPush>[2]
|
|
70
|
+
) => {
|
|
71
|
+
let videoClient: StreamVideoClient | undefined;
|
|
72
|
+
|
|
73
|
+
try {
|
|
74
|
+
videoClient = await pushConfig.createStreamVideoClient();
|
|
75
|
+
if (!videoClient) {
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
} catch (e) {
|
|
79
|
+
const logger = getLogger(['processCallFromPushInBackground']);
|
|
80
|
+
logger('error', 'failed to create video client', e);
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
await processCallFromPush(videoClient, call_cid, action, pushConfig);
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* This function is used process the call from push notifications due to incoming call
|
|
88
|
+
* It does the following steps:
|
|
89
|
+
* 1. Get the call from the client if present or create a new call
|
|
90
|
+
* 2. Fetch the latest state of the call from the server if its not already in ringing state
|
|
91
|
+
* 3. Join or leave the call based on the user's action.
|
|
92
|
+
*/
|
|
93
|
+
export const processCallFromPush = async (
|
|
94
|
+
client: StreamVideoClient,
|
|
95
|
+
call_cid: string,
|
|
96
|
+
action: 'accept' | 'decline' | 'pressed' | 'backgroundDelivered',
|
|
97
|
+
pushConfig: PushConfig
|
|
98
|
+
) => {
|
|
99
|
+
let callFromPush: Call;
|
|
100
|
+
try {
|
|
101
|
+
callFromPush = await client.onRingingCall(call_cid);
|
|
102
|
+
} catch (e) {
|
|
103
|
+
const logger = getLogger(['processCallFromPush']);
|
|
104
|
+
logger('error', 'failed to fetch call from push notification', e);
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
// note: when action was pressed or delivered, we dont need to do anything as the only thing is to do is to get the call which adds it to the client
|
|
108
|
+
try {
|
|
109
|
+
if (action === 'accept') {
|
|
110
|
+
if (pushConfig.publishOptions) {
|
|
111
|
+
callFromPush.updatePublishOptions(pushConfig.publishOptions);
|
|
112
|
+
}
|
|
113
|
+
await callFromPush.join();
|
|
114
|
+
} else if (action === 'decline') {
|
|
115
|
+
await callFromPush.leave({ reject: true });
|
|
116
|
+
}
|
|
117
|
+
} catch (e) {
|
|
118
|
+
const logger = getLogger(['processCallFromPush']);
|
|
119
|
+
logger(
|
|
120
|
+
'error',
|
|
121
|
+
`failed to process ${action} call from push notification`,
|
|
122
|
+
e
|
|
123
|
+
);
|
|
124
|
+
}
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* This function is used process the call from push notifications due to non ringing calls
|
|
129
|
+
* It does the following steps:
|
|
130
|
+
* 1. Get the call from the client if present or create a new call
|
|
131
|
+
* 2. Fetch the latest state of the call from the server
|
|
132
|
+
* 3. Call all the callbacks to inform the app about the call
|
|
133
|
+
*/
|
|
134
|
+
export const processNonIncomingCallFromPush = async (
|
|
135
|
+
client: StreamVideoClient,
|
|
136
|
+
call_cid: string,
|
|
137
|
+
nonRingingNotificationType: NonRingingPushEvent
|
|
138
|
+
) => {
|
|
139
|
+
let callFromPush: Call;
|
|
140
|
+
try {
|
|
141
|
+
const _callFromPush = client.state.calls.find((c) => c.cid === call_cid);
|
|
142
|
+
if (_callFromPush) {
|
|
143
|
+
callFromPush = _callFromPush;
|
|
144
|
+
} else {
|
|
145
|
+
// if not it means that WS is not alive when receiving the push notifications and we need to fetch the call
|
|
146
|
+
const [callType, callId] = call_cid.split(':');
|
|
147
|
+
callFromPush = client.call(callType as string, callId as string);
|
|
148
|
+
await callFromPush.get();
|
|
149
|
+
}
|
|
150
|
+
} catch (e) {
|
|
151
|
+
const logger = getLogger(['processNonIncomingCallFromPush']);
|
|
152
|
+
logger('error', 'failed to fetch call from push notification', e);
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
onNewCallNotification(callFromPush, nonRingingNotificationType);
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* This function is used to clear all the push related WS subscriptions
|
|
160
|
+
* note: events are subscribed in push for accept/decline through WS
|
|
161
|
+
*/
|
|
162
|
+
export const clearPushWSEventSubscriptions = () => {
|
|
163
|
+
const unsubscriptionCallbacks = RxUtils.getCurrentValue(
|
|
164
|
+
pushUnsubscriptionCallbacks$
|
|
165
|
+
);
|
|
166
|
+
if (unsubscriptionCallbacks) {
|
|
167
|
+
unsubscriptionCallbacks.forEach((cb) => cb());
|
|
168
|
+
}
|
|
169
|
+
pushUnsubscriptionCallbacks$.next(undefined);
|
|
170
|
+
};
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* This ref is used to check if the push WS subscriptions can be added
|
|
174
|
+
* It is used to avoid adding the push WS subscriptions when the client is connected to WS in the foreground
|
|
175
|
+
*/
|
|
176
|
+
export const canAddPushWSSubscriptionsRef: CanAddPushWSSubscriptionsRef = {
|
|
177
|
+
current: true,
|
|
178
|
+
};
|
package/src/utils/push/ios.ts
CHANGED
|
@@ -1,41 +1,24 @@
|
|
|
1
1
|
import { Platform } from 'react-native';
|
|
2
|
-
import type {
|
|
3
|
-
|
|
4
|
-
StreamVideoConfig,
|
|
5
|
-
} from '../StreamVideoRN/types';
|
|
6
|
-
import {
|
|
7
|
-
pushAcceptedIncomingCallCId$,
|
|
8
|
-
voipPushNotificationCallCId$,
|
|
9
|
-
voipCallkeepCallOnForegroundMap$,
|
|
10
|
-
voipCallkeepAcceptedCallOnNativeDialerMap$,
|
|
11
|
-
pushNonRingingCallData$,
|
|
12
|
-
} from './rxSubjects';
|
|
13
|
-
import {
|
|
14
|
-
clearPushWSEventSubscriptions,
|
|
15
|
-
processCallFromPushInBackground,
|
|
16
|
-
} from './utils';
|
|
2
|
+
import type { StreamVideoConfig } from '../StreamVideoRN/types';
|
|
3
|
+
import { pushNonRingingCallData$ } from './internal/rxSubjects';
|
|
17
4
|
import {
|
|
5
|
+
ExpoNotification,
|
|
18
6
|
getExpoNotificationsLib,
|
|
19
|
-
getNotifeeLibThrowIfNotInstalledForPush,
|
|
20
7
|
getPushNotificationIosLib,
|
|
8
|
+
PushNotificationiOSType,
|
|
21
9
|
} from './libs';
|
|
22
10
|
import { StreamVideoClient, getLogger } from '@stream-io/video-client';
|
|
23
11
|
import { setPushLogoutCallback } from '../internal/pushLogoutCallback';
|
|
12
|
+
import { EventType, Event } from '@notifee/react-native';
|
|
13
|
+
import { StreamVideoRN } from '../StreamVideoRN';
|
|
14
|
+
import { StreamPushPayload } from './utils';
|
|
24
15
|
|
|
25
16
|
type PushConfig = NonNullable<StreamVideoConfig['push']>;
|
|
26
17
|
|
|
27
|
-
type StreamPayload =
|
|
28
|
-
| {
|
|
29
|
-
call_cid: string;
|
|
30
|
-
type: 'call.ring' | NonRingingPushEvent;
|
|
31
|
-
sender: string;
|
|
32
|
-
}
|
|
33
|
-
| undefined;
|
|
34
|
-
|
|
35
18
|
let lastApnToken = { token: '', userId: '' };
|
|
36
19
|
|
|
37
20
|
function processNonRingingNotificationStreamPayload(
|
|
38
|
-
streamPayload:
|
|
21
|
+
streamPayload: StreamPushPayload
|
|
39
22
|
) {
|
|
40
23
|
if (
|
|
41
24
|
streamPayload?.sender === 'stream.video' &&
|
|
@@ -48,87 +31,56 @@ function processNonRingingNotificationStreamPayload(
|
|
|
48
31
|
}
|
|
49
32
|
}
|
|
50
33
|
|
|
51
|
-
export const
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
)
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
// to call end callkeep later if ended in app and not through callkeep
|
|
60
|
-
voipCallkeepAcceptedCallOnNativeDialerMap$.next({
|
|
61
|
-
uuid: callUUIDFromCallkeep,
|
|
62
|
-
cid: call_cid,
|
|
63
|
-
});
|
|
64
|
-
// to process the call in the app
|
|
65
|
-
pushAcceptedIncomingCallCId$.next(call_cid);
|
|
66
|
-
// no need to keep these references anymore
|
|
67
|
-
voipCallkeepCallOnForegroundMap$.next(undefined);
|
|
68
|
-
};
|
|
69
|
-
|
|
70
|
-
export const iosCallkeepRejectCall = async (
|
|
71
|
-
call_cid: string | undefined,
|
|
72
|
-
callUUIDFromCallkeep: string,
|
|
73
|
-
pushConfig: PushConfig
|
|
74
|
-
) => {
|
|
75
|
-
if (!shouldProcessCallFromCallkeep(call_cid, callUUIDFromCallkeep)) {
|
|
76
|
-
return;
|
|
34
|
+
export const oniOSExpoNotificationEvent = (event: ExpoNotification) => {
|
|
35
|
+
const pushConfig = StreamVideoRN.getConfig().push;
|
|
36
|
+
if (pushConfig) {
|
|
37
|
+
if (event.request.trigger.type === 'push') {
|
|
38
|
+
const streamPayload = event.request.trigger.payload
|
|
39
|
+
?.stream as StreamPushPayload;
|
|
40
|
+
processNonRingingNotificationStreamPayload(streamPayload);
|
|
41
|
+
}
|
|
77
42
|
}
|
|
78
|
-
clearPushWSEventSubscriptions();
|
|
79
|
-
// no need to keep these references anymore
|
|
80
|
-
voipCallkeepAcceptedCallOnNativeDialerMap$.next(undefined);
|
|
81
|
-
voipCallkeepCallOnForegroundMap$.next(undefined);
|
|
82
|
-
voipPushNotificationCallCId$.next(undefined);
|
|
83
|
-
await processCallFromPushInBackground(pushConfig, call_cid, 'decline');
|
|
84
43
|
};
|
|
85
44
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
45
|
+
export const oniOSNotifeeEvent = ({
|
|
46
|
+
event,
|
|
47
|
+
}: {
|
|
48
|
+
event: Event;
|
|
49
|
+
isBackground: boolean;
|
|
50
|
+
}) => {
|
|
51
|
+
if (Platform.OS !== 'ios') return;
|
|
52
|
+
const pushConfig = StreamVideoRN.getConfig().push;
|
|
53
|
+
const { type, detail } = event;
|
|
54
|
+
if (pushConfig && type === EventType.PRESS) {
|
|
55
|
+
const streamPayload = detail.notification?.data?.stream as
|
|
56
|
+
| StreamPushPayload
|
|
57
|
+
| undefined;
|
|
58
|
+
const result = processNonRingingNotificationStreamPayload(streamPayload);
|
|
59
|
+
if (result) {
|
|
60
|
+
pushConfig.onTapNonRingingCallNotification?.(result.cid, result.type);
|
|
61
|
+
}
|
|
96
62
|
}
|
|
97
|
-
return true;
|
|
98
63
|
};
|
|
99
64
|
|
|
100
|
-
export
|
|
101
|
-
|
|
65
|
+
export function onPushNotificationiOSStreamVideoEvent(
|
|
66
|
+
notification: PushNotificationiOSType
|
|
67
|
+
) {
|
|
68
|
+
const pushNotificationIosLib = getPushNotificationIosLib();
|
|
69
|
+
const data = notification.getData();
|
|
70
|
+
const streamPayload = data?.stream as StreamPushPayload;
|
|
71
|
+
const isClicked = data.userInteraction === 1;
|
|
72
|
+
const pushConfig = StreamVideoRN.getConfig().push;
|
|
73
|
+
if (!streamPayload || !isClicked || !pushConfig) {
|
|
74
|
+
notification.finish(pushNotificationIosLib.FetchResult.NoData);
|
|
102
75
|
return;
|
|
103
76
|
}
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
const streamPayload = detail.notification?.data?.stream as
|
|
109
|
-
| StreamPayload
|
|
110
|
-
| undefined;
|
|
111
|
-
const result = processNonRingingNotificationStreamPayload(streamPayload);
|
|
112
|
-
if (result) {
|
|
113
|
-
pushConfig.onTapNonRingingCallNotification?.(result.cid, result.type);
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
});
|
|
117
|
-
if (pushConfig.isExpo) {
|
|
118
|
-
const Notifications = getExpoNotificationsLib();
|
|
119
|
-
|
|
120
|
-
// foreground handler (just to show the notifications on foreground)
|
|
121
|
-
Notifications.setNotificationHandler({
|
|
122
|
-
handleNotification: async () => {
|
|
123
|
-
return {
|
|
124
|
-
shouldShowAlert: true,
|
|
125
|
-
shouldPlaySound: true,
|
|
126
|
-
shouldSetBadge: false,
|
|
127
|
-
};
|
|
128
|
-
},
|
|
129
|
-
});
|
|
77
|
+
// listen to foreground notifications
|
|
78
|
+
const result = processNonRingingNotificationStreamPayload(streamPayload);
|
|
79
|
+
if (result) {
|
|
80
|
+
pushConfig.onTapNonRingingCallNotification?.(result.cid, result.type);
|
|
130
81
|
}
|
|
131
|
-
|
|
82
|
+
notification.finish(pushNotificationIosLib.FetchResult.NoData);
|
|
83
|
+
}
|
|
132
84
|
|
|
133
85
|
/** Send token to stream */
|
|
134
86
|
export async function initIosNonVoipToken(
|
|
@@ -171,34 +123,16 @@ export async function initIosNonVoipToken(
|
|
|
171
123
|
setDeviceToken(devicePushToken.data);
|
|
172
124
|
}
|
|
173
125
|
);
|
|
174
|
-
const subscriptionForReceive =
|
|
175
|
-
expoNotificationsLib.addNotificationReceivedListener((event) => {
|
|
176
|
-
// listen to foreground notifications
|
|
177
|
-
if (event.request.trigger.type === 'push') {
|
|
178
|
-
const streamPayload = event.request.trigger.payload
|
|
179
|
-
?.stream as StreamPayload;
|
|
180
|
-
processNonRingingNotificationStreamPayload(streamPayload);
|
|
181
|
-
}
|
|
182
|
-
});
|
|
183
126
|
setUnsubscribeListener(() => {
|
|
184
127
|
subscription.remove();
|
|
185
|
-
subscriptionForReceive.remove();
|
|
186
128
|
});
|
|
187
129
|
} else {
|
|
188
130
|
const pushNotificationIosLib = getPushNotificationIosLib();
|
|
189
131
|
pushNotificationIosLib.addEventListener('register', (token) => {
|
|
190
132
|
setDeviceToken(token);
|
|
191
133
|
});
|
|
192
|
-
pushNotificationIosLib.addEventListener('notification', (notification) => {
|
|
193
|
-
const data = notification.getData();
|
|
194
|
-
const streamPayload = data?.stream as StreamPayload;
|
|
195
|
-
// listen to foreground notifications
|
|
196
|
-
processNonRingingNotificationStreamPayload(streamPayload);
|
|
197
|
-
notification.finish(pushNotificationIosLib.FetchResult.NoData);
|
|
198
|
-
});
|
|
199
134
|
setUnsubscribeListener(() => {
|
|
200
135
|
pushNotificationIosLib.removeEventListener('register');
|
|
201
|
-
pushNotificationIosLib.removeEventListener('notification');
|
|
202
136
|
});
|
|
203
137
|
}
|
|
204
138
|
}
|
|
@@ -3,6 +3,10 @@ export type PushNotificationIosLib =
|
|
|
3
3
|
|
|
4
4
|
let pushNotificationIosLib: PushNotificationIosLib | undefined;
|
|
5
5
|
|
|
6
|
+
import type { PushNotification } from '@react-native-community/push-notification-ios';
|
|
7
|
+
|
|
8
|
+
export type PushNotificationiOSType = PushNotification;
|
|
9
|
+
|
|
6
10
|
try {
|
|
7
11
|
pushNotificationIosLib =
|
|
8
12
|
require('@react-native-community/push-notification-ios').default;
|