@stream-io/video-react-native-sdk 0.9.7 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/dist/commonjs/hooks/useAndroidKeepCallAliveEffect.js +21 -18
  3. package/dist/commonjs/hooks/useAndroidKeepCallAliveEffect.js.map +1 -1
  4. package/dist/commonjs/utils/push/android.js +36 -29
  5. package/dist/commonjs/utils/push/android.js.map +1 -1
  6. package/dist/commonjs/utils/push/ios.js +3 -5
  7. package/dist/commonjs/utils/push/ios.js.map +1 -1
  8. package/dist/commonjs/utils/push/libs/index.js +11 -0
  9. package/dist/commonjs/utils/push/libs/index.js.map +1 -1
  10. package/dist/commonjs/utils/push/libs/notifee.js +27 -0
  11. package/dist/commonjs/utils/push/libs/notifee.js.map +1 -0
  12. package/dist/commonjs/version.js +1 -1
  13. package/dist/commonjs/version.js.map +1 -1
  14. package/dist/module/hooks/useAndroidKeepCallAliveEffect.js +15 -10
  15. package/dist/module/hooks/useAndroidKeepCallAliveEffect.js.map +1 -1
  16. package/dist/module/utils/push/android.js +20 -11
  17. package/dist/module/utils/push/android.js.map +1 -1
  18. package/dist/module/utils/push/ios.js +4 -4
  19. package/dist/module/utils/push/ios.js.map +1 -1
  20. package/dist/module/utils/push/libs/index.js +1 -0
  21. package/dist/module/utils/push/libs/index.js.map +1 -1
  22. package/dist/module/utils/push/libs/notifee.js +20 -0
  23. package/dist/module/utils/push/libs/notifee.js.map +1 -0
  24. package/dist/module/version.js +1 -1
  25. package/dist/module/version.js.map +1 -1
  26. package/dist/typescript/hooks/useAndroidKeepCallAliveEffect.d.ts.map +1 -1
  27. package/dist/typescript/utils/StreamVideoRN/types.d.ts +1 -1
  28. package/dist/typescript/utils/StreamVideoRN/types.d.ts.map +1 -1
  29. package/dist/typescript/utils/push/android.d.ts.map +1 -1
  30. package/dist/typescript/utils/push/ios.d.ts.map +1 -1
  31. package/dist/typescript/utils/push/libs/index.d.ts +1 -0
  32. package/dist/typescript/utils/push/libs/index.d.ts.map +1 -1
  33. package/dist/typescript/utils/push/libs/notifee.d.ts +4 -0
  34. package/dist/typescript/utils/push/libs/notifee.d.ts.map +1 -0
  35. package/dist/typescript/version.d.ts +1 -1
  36. package/dist/typescript/version.d.ts.map +1 -1
  37. package/expo-config-plugin/dist/withAndroidManifest.js +27 -32
  38. package/expo-config-plugin/dist/withAndroidPermissions.js +12 -11
  39. package/expo-config-plugin/dist/withMainActivity.js +13 -18
  40. package/package.json +5 -2
  41. package/src/hooks/useAndroidKeepCallAliveEffect.ts +29 -17
  42. package/src/utils/StreamVideoRN/types.ts +1 -1
  43. package/src/utils/push/android.ts +32 -13
  44. package/src/utils/push/ios.ts +9 -4
  45. package/src/utils/push/libs/index.ts +1 -0
  46. package/src/utils/push/libs/notifee.ts +33 -0
  47. package/src/version.ts +1 -1
@@ -9,25 +9,20 @@ const addNewLinesToMainActivity_1 = __importDefault(require("./common/addNewLine
9
9
  const withStreamVideoReactNativeSDKMainActivity = (configuration, props) => {
10
10
  return (0, config_plugins_1.withMainActivity)(configuration, (config) => {
11
11
  const isMainActivityJava = config.modResults.language === 'java';
12
- try {
13
- config.modResults.contents = (0, codeMod_1.addImports)(config.modResults.contents, [
14
- 'com.streamvideo.reactnative.StreamVideoReactNative',
15
- 'android.os.Build',
16
- 'android.util.Rational',
17
- 'androidx.lifecycle.Lifecycle',
18
- 'android.app.PictureInPictureParams',
19
- 'com.oney.WebRTCModule.WebRTCModuleOptions',
20
- ], isMainActivityJava);
21
- config.modResults.contents = addOnPictureInPictureModeChanged(config.modResults.contents, isMainActivityJava);
22
- if (props?.androidPictureInPicture?.enableAutomaticEnter) {
23
- config.modResults.contents = addOnUserLeaveHint(config.modResults.contents, isMainActivityJava);
24
- }
25
- if (props?.enableScreenshare) {
26
- config.modResults.contents = addInsideOnCreate(config.modResults.contents, isMainActivityJava);
27
- }
12
+ config.modResults.contents = (0, codeMod_1.addImports)(config.modResults.contents, [
13
+ 'com.streamvideo.reactnative.StreamVideoReactNative',
14
+ 'android.os.Build',
15
+ 'android.util.Rational',
16
+ 'androidx.lifecycle.Lifecycle',
17
+ 'android.app.PictureInPictureParams',
18
+ 'com.oney.WebRTCModule.WebRTCModuleOptions',
19
+ ], isMainActivityJava);
20
+ config.modResults.contents = addOnPictureInPictureModeChanged(config.modResults.contents, isMainActivityJava);
21
+ if (props?.androidPictureInPicture?.enableAutomaticEnter) {
22
+ config.modResults.contents = addOnUserLeaveHint(config.modResults.contents, isMainActivityJava);
28
23
  }
29
- catch (error) {
30
- throw new Error("Cannot add StreamVideoReactNativeSDK to the project's MainApplication because it's malformed.");
24
+ if (props?.enableScreenshare) {
25
+ config.modResults.contents = addInsideOnCreate(config.modResults.contents, isMainActivityJava);
31
26
  }
32
27
  return config;
33
28
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stream-io/video-react-native-sdk",
3
- "version": "0.9.7",
3
+ "version": "0.10.0",
4
4
  "packageManager": "yarn@3.2.4",
5
5
  "main": "dist/commonjs/index.js",
6
6
  "module": "dist/module/index.js",
@@ -17,7 +17,7 @@
17
17
  "build:expo-plugin": "rimraf expo-config-plugin/dist && tsc --project expo-config-plugin/tsconfig.json",
18
18
  "build": "yarn clean && yarn copy-version && bob build && yarn build:expo-plugin",
19
19
  "test:expo-plugin": "jest expo-config-plugin --coverage",
20
- "test": "jest --coverage && yarn test:expo-plugin",
20
+ "test": "yarn copy-version && jest --coverage && yarn test:expo-plugin",
21
21
  "copy-version": "echo \"export const version = '$npm_package_version';\" > ./src/version.ts"
22
22
  },
23
23
  "files": [
@@ -75,6 +75,9 @@
75
75
  "react-native-voip-push-notification": ">=3.3.1"
76
76
  },
77
77
  "peerDependenciesMeta": {
78
+ "@notifee/react-native": {
79
+ "optional": true
80
+ },
78
81
  "@react-native-community/push-notification-ios": {
79
82
  "optional": true
80
83
  },
@@ -1,15 +1,19 @@
1
1
  import { useCall, useCallStateHooks } from '@stream-io/video-react-bindings';
2
2
  import { useEffect, useRef } from 'react';
3
- import notifee, { AuthorizationStatus } from '@notifee/react-native';
4
3
  import { StreamVideoRN } from '../utils';
5
4
  import { Platform } from 'react-native';
6
5
  import { CallingState, getLogger } from '@stream-io/video-client';
6
+ import { getNotifeeLibNoThrowForKeepCallAlive } from '../utils/push/libs/notifee';
7
7
 
8
8
  const isAndroid7OrBelow = Platform.OS === 'android' && Platform.Version < 26;
9
9
 
10
+ const notifeeLib = isAndroid7OrBelow
11
+ ? getNotifeeLibNoThrowForKeepCallAlive()
12
+ : undefined;
13
+
10
14
  function setForegroundService() {
11
15
  if (!isAndroid7OrBelow) return;
12
- notifee.registerForegroundService(() => {
16
+ notifeeLib?.default.registerForegroundService(() => {
13
17
  return new Promise(() => {
14
18
  const logger = getLogger(['setForegroundService method']);
15
19
  logger('info', 'Foreground service running for call in progress');
@@ -23,8 +27,11 @@ async function startForegroundService(call_cid: string) {
23
27
  const { title, body } = foregroundServiceConfig.android.notificationTexts;
24
28
 
25
29
  // request for notification permission and then start the foreground service
26
- const settings = await notifee.getNotificationSettings();
27
- if (settings.authorizationStatus !== AuthorizationStatus.AUTHORIZED) {
30
+ if (!notifeeLib) return;
31
+ const settings = await notifeeLib.default.getNotificationSettings();
32
+ if (
33
+ settings.authorizationStatus !== notifeeLib.AuthorizationStatus.AUTHORIZED
34
+ ) {
28
35
  const logger = getLogger(['startForegroundService']);
29
36
  logger(
30
37
  'info',
@@ -32,7 +39,7 @@ async function startForegroundService(call_cid: string) {
32
39
  );
33
40
  return;
34
41
  }
35
- await notifee.displayNotification({
42
+ await notifeeLib.default.displayNotification({
36
43
  id: call_cid,
37
44
  title,
38
45
  body,
@@ -69,6 +76,7 @@ export const useAndroidKeepCallAliveEffect = () => {
69
76
  const callingState = useCallCallingState();
70
77
 
71
78
  useEffect((): (() => void) | undefined => {
79
+ if (!notifeeLib) return;
72
80
  if (Platform.OS === 'ios' || !activeCallCid) {
73
81
  return;
74
82
  }
@@ -79,6 +87,7 @@ export const useAndroidKeepCallAliveEffect = () => {
79
87
  if (foregroundServiceStartedRef.current) {
80
88
  return;
81
89
  }
90
+ const notifee = notifeeLib.default;
82
91
  notifee.getDisplayedNotifications().then((displayedNotifications) => {
83
92
  const activeCallNotification = displayedNotifications.find(
84
93
  (notification) => notification.id === activeCallCid
@@ -99,7 +108,7 @@ export const useAndroidKeepCallAliveEffect = () => {
99
108
  // cancel any notifee displayed notification when the call has transitioned out of ringing
100
109
  return () => {
101
110
  // cancels the non fg service notifications
102
- notifee.cancelDisplayedNotification(activeCallCid);
111
+ notifeeLib.default.cancelDisplayedNotification(activeCallCid);
103
112
  };
104
113
  } else if (
105
114
  callingState === CallingState.IDLE ||
@@ -107,18 +116,20 @@ export const useAndroidKeepCallAliveEffect = () => {
107
116
  ) {
108
117
  if (foregroundServiceStartedRef.current) {
109
118
  // stop foreground service when the call is not active
110
- notifee.stopForegroundService();
119
+ notifeeLib.default.stopForegroundService();
111
120
  foregroundServiceStartedRef.current = false;
112
121
  } else {
113
- notifee.getDisplayedNotifications().then((displayedNotifications) => {
114
- const activeCallNotification = displayedNotifications.find(
115
- (notification) => notification.id === activeCallCid
116
- );
117
- if (activeCallNotification) {
118
- // this means that we have a incoming call notification shown as foreground service and we must stop it
119
- notifee.stopForegroundService();
120
- }
121
- });
122
+ notifeeLib.default
123
+ .getDisplayedNotifications()
124
+ .then((displayedNotifications) => {
125
+ const activeCallNotification = displayedNotifications.find(
126
+ (notification) => notification.id === activeCallCid
127
+ );
128
+ if (activeCallNotification) {
129
+ // this means that we have a incoming call notification shown as foreground service and we must stop it
130
+ notifeeLib.default.stopForegroundService();
131
+ }
132
+ });
122
133
  }
123
134
  }
124
135
  }, [activeCallCid, callingState]);
@@ -127,7 +138,8 @@ export const useAndroidKeepCallAliveEffect = () => {
127
138
  return () => {
128
139
  // stop foreground service when this effect is unmounted
129
140
  if (foregroundServiceStartedRef.current) {
130
- notifee.stopForegroundService();
141
+ if (!notifeeLib) return;
142
+ notifeeLib.default.stopForegroundService();
131
143
  foregroundServiceStartedRef.current = false;
132
144
  }
133
145
  };
@@ -1,5 +1,5 @@
1
1
  import { StreamVideoClient } from '@stream-io/video-client';
2
- import { AndroidChannel } from '@notifee/react-native';
2
+ import type { AndroidChannel } from '@notifee/react-native';
3
3
 
4
4
  export type NonRingingPushEvent = 'call.live_started' | 'call.notification';
5
5
 
@@ -1,8 +1,3 @@
1
- import notifee, {
2
- EventType,
3
- Event,
4
- AndroidCategory,
5
- } from '@notifee/react-native';
6
1
  import { FirebaseMessagingTypes } from '@react-native-firebase/messaging';
7
2
  import {
8
3
  Call,
@@ -20,6 +15,8 @@ import {
20
15
  getFirebaseMessagingLibNoThrow,
21
16
  getExpoNotificationsLib,
22
17
  getExpoTaskManagerLib,
18
+ getNotifeeLibThrowIfNotInstalledForPush,
19
+ NotifeeLib,
23
20
  } from './libs';
24
21
  import {
25
22
  pushAcceptedIncomingCallCId$,
@@ -43,6 +40,14 @@ const DECLINE_CALL_ACTION_ID = 'decline';
43
40
 
44
41
  type PushConfig = NonNullable<StreamVideoConfig['push']>;
45
42
 
43
+ type onBackgroundEventFunctionParams = Parameters<
44
+ NotifeeLib['default']['onBackgroundEvent']
45
+ >[0];
46
+
47
+ type Event = Parameters<onBackgroundEventFunctionParams>[0];
48
+
49
+ // EventType = NotifeeLib['EventType'];
50
+
46
51
  /** Setup Firebase push message handler **/
47
52
  export function setupFirebaseHandlerAndroid(pushConfig: PushConfig) {
48
53
  if (Platform.OS !== 'android') {
@@ -114,6 +119,8 @@ export function setupFirebaseHandlerAndroid(pushConfig: PushConfig) {
114
119
  }
115
120
 
116
121
  // the notification tap handlers are always registered with notifee for both expo and non-expo in android
122
+ const notifeeLib = getNotifeeLibThrowIfNotInstalledForPush();
123
+ const notifee = notifeeLib.default;
117
124
  notifee.onBackgroundEvent(async (event) => {
118
125
  await onNotifeeEvent(event, pushConfig, true);
119
126
  });
@@ -208,6 +215,9 @@ const firebaseMessagingOnMessageHandler = async (
208
215
  AppState.currentState !== 'active';
209
216
  const asForegroundService = canListenToWS();
210
217
 
218
+ const notifeeLib = getNotifeeLibThrowIfNotInstalledForPush();
219
+ const notifee = notifeeLib.default;
220
+
211
221
  if (asForegroundService) {
212
222
  // Listen to call events from WS through fg service
213
223
  // note: this will replace the current empty fg service runner
@@ -291,7 +301,7 @@ const firebaseMessagingOnMessageHandler = async (
291
301
  },
292
302
  },
293
303
  ],
294
- category: AndroidCategory.CALL,
304
+ category: notifeeLib.AndroidCategory.CALL,
295
305
  fullScreenAction: {
296
306
  id: 'stream_ringing_incoming_call',
297
307
  },
@@ -316,6 +326,8 @@ const firebaseMessagingOnMessageHandler = async (
316
326
  return;
317
327
  }
318
328
  } else {
329
+ const notifeeLib = getNotifeeLibThrowIfNotInstalledForPush();
330
+ const notifee = notifeeLib.default;
319
331
  // the other types are call.live_started and call.notification
320
332
  const callChannel = pushConfig.android.callChannel;
321
333
  const callNotificationTextGetters =
@@ -376,18 +388,24 @@ const onNotifeeEvent = async (
376
388
  pushAcceptedIncomingCallCId$.observed &&
377
389
  pushRejectedIncomingCallCId$.observed;
378
390
 
391
+ const notifeeLib = getNotifeeLibThrowIfNotInstalledForPush();
392
+ const notifee = notifeeLib.default;
379
393
  // Check if we need to decline the call
380
394
  const didPressDecline =
381
- type === EventType.ACTION_PRESS &&
395
+ type === notifeeLib.EventType.ACTION_PRESS &&
382
396
  pressAction?.id === DECLINE_CALL_ACTION_ID;
383
- const didDismiss = type === EventType.DISMISSED;
397
+ const didDismiss = type === notifeeLib.EventType.DISMISSED;
384
398
  const mustDecline = didPressDecline || didDismiss;
385
399
  // Check if we need to accept the call
386
400
  const mustAccept =
387
- type === EventType.ACTION_PRESS &&
401
+ type === notifeeLib.EventType.ACTION_PRESS &&
388
402
  pressAction?.id === ACCEPT_CALL_ACTION_ID;
389
403
 
390
- if (mustAccept || mustDecline || type === EventType.ACTION_PRESS) {
404
+ if (
405
+ mustAccept ||
406
+ mustDecline ||
407
+ type === notifeeLib.EventType.ACTION_PRESS
408
+ ) {
391
409
  clearPushWSEventSubscriptions();
392
410
  notifee.stopForegroundService();
393
411
  }
@@ -403,16 +421,17 @@ const onNotifeeEvent = async (
403
421
  }
404
422
  await processCallFromPushInBackground(pushConfig, call_cid, 'decline');
405
423
  } else {
406
- if (type === EventType.PRESS) {
424
+ if (type === notifeeLib.EventType.PRESS) {
407
425
  pushTappedIncomingCallCId$.next(call_cid);
408
426
  // pressed state will be handled by the app with rxjs observers as the app will go to foreground always
409
- } else if (isBackground && type === EventType.DELIVERED) {
427
+ } else if (isBackground && type === notifeeLib.EventType.DELIVERED) {
410
428
  pushAndroidBackgroundDeliveredIncomingCallCId$.next(call_cid);
411
429
  // background delivered state will be handled by the app with rxjs observers as processing needs to happen only when app is opened
412
430
  }
413
431
  }
414
432
  } else {
415
- if (type === EventType.PRESS) {
433
+ const notifeeLib = getNotifeeLibThrowIfNotInstalledForPush();
434
+ if (type === notifeeLib.EventType.PRESS) {
416
435
  pushTappedIncomingCallCId$.next(call_cid);
417
436
  pushConfig.onTapNonRingingCallNotification?.(
418
437
  call_cid,
@@ -14,10 +14,13 @@ import {
14
14
  clearPushWSEventSubscriptions,
15
15
  processCallFromPushInBackground,
16
16
  } from './utils';
17
- import { getExpoNotificationsLib, getPushNotificationIosLib } from './libs';
17
+ import {
18
+ getExpoNotificationsLib,
19
+ getNotifeeLibThrowIfNotInstalledForPush,
20
+ getPushNotificationIosLib,
21
+ } from './libs';
18
22
  import { StreamVideoClient, getLogger } from '@stream-io/video-client';
19
23
  import { setPushLogoutCallback } from '../internal/pushLogoutCallback';
20
- import notifee, { EventType } from '@notifee/react-native';
21
24
 
22
25
  type PushConfig = NonNullable<StreamVideoConfig['push']>;
23
26
 
@@ -96,8 +99,10 @@ export const setupRemoteNotificationsHandleriOS = (pushConfig: PushConfig) => {
96
99
  if (Platform.OS !== 'ios') {
97
100
  return;
98
101
  }
99
- notifee.onForegroundEvent(({ type, detail }) => {
100
- if (type === EventType.PRESS) {
102
+ const notifeeLib = getNotifeeLibThrowIfNotInstalledForPush();
103
+
104
+ notifeeLib.default.onForegroundEvent(({ type, detail }) => {
105
+ if (type === notifeeLib.EventType.PRESS) {
101
106
  const streamPayload = detail.notification?.data?.stream as
102
107
  | StreamPayload
103
108
  | undefined;
@@ -4,6 +4,7 @@ export * from './firebaseMessaging';
4
4
  export * from './iosPushNotification';
5
5
  export * from './voipPushNotification';
6
6
  export * from './callkeep';
7
+ export * from './notifee';
7
8
 
8
9
  /*
9
10
  NOTE: must keep each libs in different files
@@ -0,0 +1,33 @@
1
+ import { getLogger } from '../../..';
2
+
3
+ export type NotifeeLib = typeof import('@notifee/react-native');
4
+
5
+ let notifeeLib: NotifeeLib | undefined;
6
+
7
+ try {
8
+ notifeeLib = require('@notifee/react-native');
9
+ } catch (_e) {}
10
+
11
+ const INSTALLATION_INSTRUCTION =
12
+ 'Please see https://notifee.app/react-native/docs/installation for installation instructions';
13
+
14
+ export function getNotifeeLibThrowIfNotInstalledForPush() {
15
+ if (!notifeeLib) {
16
+ throw Error(
17
+ '@notifee/react-native is not installed. It is required for implementing push notifications. ' +
18
+ INSTALLATION_INSTRUCTION
19
+ );
20
+ }
21
+ return notifeeLib;
22
+ }
23
+
24
+ export function getNotifeeLibNoThrowForKeepCallAlive() {
25
+ if (!notifeeLib) {
26
+ const logger = getLogger(['getNotifeeLibNoThrow']);
27
+ logger(
28
+ 'info',
29
+ `${'@notifee/react-native library not installed. It is required to keep call alive in the background for Android < 26. '}${INSTALLATION_INSTRUCTION}`
30
+ );
31
+ }
32
+ return notifeeLib;
33
+ }
package/src/version.ts CHANGED
@@ -1 +1 @@
1
- export const version = '0.9.7';
1
+ export const version = '0.10.0';