@stream-io/video-react-native-sdk 1.7.0 → 1.9.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 +19 -0
- package/README.md +1 -1
- package/android/src/main/java/com/streamvideo/reactnative/StreamVideoReactNative.kt +23 -11
- package/android/src/main/java/com/streamvideo/reactnative/StreamVideoReactNativeModule.kt +71 -23
- package/dist/commonjs/components/Call/CallContent/CallContent.js +1 -1
- package/dist/commonjs/components/Call/CallContent/CallContent.js.map +1 -1
- package/dist/commonjs/components/Call/CallLayout/CallParticipantsGrid.js +2 -3
- package/dist/commonjs/components/Call/CallLayout/CallParticipantsGrid.js.map +1 -1
- package/dist/commonjs/components/Call/CallLayout/CallParticipantsSpotlight.js +2 -3
- package/dist/commonjs/components/Call/CallLayout/CallParticipantsSpotlight.js.map +1 -1
- package/dist/commonjs/contexts/BackgroundFilters.js +0 -1
- package/dist/commonjs/contexts/BackgroundFilters.js.map +1 -1
- package/dist/commonjs/hooks/useAutoEnterPiPEffect.js +5 -3
- package/dist/commonjs/hooks/useAutoEnterPiPEffect.js.map +1 -1
- package/dist/commonjs/hooks/useIsInPiPMode.js +14 -24
- package/dist/commonjs/hooks/useIsInPiPMode.js.map +1 -1
- package/dist/commonjs/providers/StreamCall/AppStateListener.js +101 -0
- package/dist/commonjs/providers/StreamCall/AppStateListener.js.map +1 -0
- package/dist/commonjs/providers/StreamCall/DeviceStats.js +45 -0
- package/dist/commonjs/providers/StreamCall/DeviceStats.js.map +1 -0
- package/dist/commonjs/providers/StreamCall/index.js +69 -0
- package/dist/commonjs/providers/StreamCall/index.js.map +1 -0
- package/dist/commonjs/utils/internal/rxSubjects.js +10 -0
- package/dist/commonjs/utils/internal/rxSubjects.js.map +1 -0
- package/dist/commonjs/version.js +1 -1
- package/dist/module/components/Call/CallContent/CallContent.js +1 -1
- package/dist/module/components/Call/CallContent/CallContent.js.map +1 -1
- package/dist/module/components/Call/CallLayout/CallParticipantsGrid.js +2 -3
- package/dist/module/components/Call/CallLayout/CallParticipantsGrid.js.map +1 -1
- package/dist/module/components/Call/CallLayout/CallParticipantsSpotlight.js +2 -3
- package/dist/module/components/Call/CallLayout/CallParticipantsSpotlight.js.map +1 -1
- package/dist/module/contexts/BackgroundFilters.js +1 -3
- package/dist/module/contexts/BackgroundFilters.js.map +1 -1
- package/dist/module/hooks/useAutoEnterPiPEffect.js +5 -3
- package/dist/module/hooks/useAutoEnterPiPEffect.js.map +1 -1
- package/dist/module/hooks/useIsInPiPMode.js +14 -24
- package/dist/module/hooks/useIsInPiPMode.js.map +1 -1
- package/dist/module/providers/StreamCall/AppStateListener.js +94 -0
- package/dist/module/providers/StreamCall/AppStateListener.js.map +1 -0
- package/dist/module/providers/StreamCall/DeviceStats.js +38 -0
- package/dist/module/providers/StreamCall/DeviceStats.js.map +1 -0
- package/dist/module/providers/StreamCall/index.js +61 -0
- package/dist/module/providers/StreamCall/index.js.map +1 -0
- package/dist/module/utils/internal/rxSubjects.js +4 -0
- package/dist/module/utils/internal/rxSubjects.js.map +1 -0
- package/dist/module/version.js +1 -1
- package/dist/typescript/components/Call/CallContent/CallContent.d.ts.map +1 -1
- package/dist/typescript/components/Call/CallLayout/CallParticipantsGrid.d.ts +2 -2
- package/dist/typescript/components/Call/CallLayout/CallParticipantsGrid.d.ts.map +1 -1
- package/dist/typescript/components/Call/CallLayout/CallParticipantsSpotlight.d.ts +2 -2
- package/dist/typescript/components/Call/CallLayout/CallParticipantsSpotlight.d.ts.map +1 -1
- package/dist/typescript/contexts/BackgroundFilters.d.ts.map +1 -1
- package/dist/typescript/hooks/useAutoEnterPiPEffect.d.ts.map +1 -1
- package/dist/typescript/hooks/useIsInPiPMode.d.ts +1 -1
- package/dist/typescript/hooks/useIsInPiPMode.d.ts.map +1 -1
- package/dist/typescript/providers/StreamCall/AppStateListener.d.ts +2 -0
- package/dist/typescript/providers/StreamCall/AppStateListener.d.ts.map +1 -0
- package/dist/typescript/providers/StreamCall/DeviceStats.d.ts +5 -0
- package/dist/typescript/providers/StreamCall/DeviceStats.d.ts.map +1 -0
- package/dist/typescript/providers/{StreamCall.d.ts → StreamCall/index.d.ts} +1 -1
- package/dist/typescript/providers/StreamCall/index.d.ts.map +1 -0
- package/dist/typescript/utils/StreamVideoRN/types.d.ts +2 -2
- package/dist/typescript/utils/StreamVideoRN/types.d.ts.map +1 -1
- package/dist/typescript/utils/internal/rxSubjects.d.ts +4 -0
- package/dist/typescript/utils/internal/rxSubjects.d.ts.map +1 -0
- package/dist/typescript/version.d.ts +1 -1
- package/expo-config-plugin/dist/common/types.d.ts +1 -4
- package/expo-config-plugin/dist/withMainActivity.js +42 -36
- package/package.json +5 -5
- package/src/components/Call/CallContent/CallContent.tsx +2 -1
- package/src/components/Call/CallLayout/CallParticipantsGrid.tsx +2 -6
- package/src/components/Call/CallLayout/CallParticipantsSpotlight.tsx +2 -6
- package/src/contexts/BackgroundFilters.tsx +2 -5
- package/src/hooks/useAutoEnterPiPEffect.tsx +5 -2
- package/src/hooks/useIsInPiPMode.tsx +16 -52
- package/src/providers/StreamCall/AppStateListener.tsx +125 -0
- package/src/providers/StreamCall/DeviceStats.tsx +59 -0
- package/src/providers/StreamCall/index.tsx +78 -0
- package/src/utils/StreamVideoRN/types.ts +5 -2
- package/src/utils/internal/rxSubjects.ts +5 -0
- package/src/version.ts +1 -1
- package/dist/commonjs/providers/StreamCall.js +0 -155
- package/dist/commonjs/providers/StreamCall.js.map +0 -1
- package/dist/module/providers/StreamCall.js +0 -146
- package/dist/module/providers/StreamCall.js.map +0 -1
- package/dist/typescript/providers/StreamCall.d.ts.map +0 -1
- package/src/providers/StreamCall.tsx +0 -205
|
@@ -25,10 +25,7 @@ import { useIsInPiPMode } from '../../../hooks/useIsInPiPMode';
|
|
|
25
25
|
export type CallParticipantsSpotlightProps = ParticipantViewComponentProps &
|
|
26
26
|
Pick<
|
|
27
27
|
CallContentProps,
|
|
28
|
-
| '
|
|
29
|
-
| 'CallParticipantsList'
|
|
30
|
-
| 'ScreenShareOverlay'
|
|
31
|
-
| 'disablePictureInPicture'
|
|
28
|
+
'supportedReactions' | 'CallParticipantsList' | 'ScreenShareOverlay'
|
|
32
29
|
> &
|
|
33
30
|
Pick<CallParticipantsListComponentProps, 'ParticipantView'> & {
|
|
34
31
|
/**
|
|
@@ -53,7 +50,6 @@ export const CallParticipantsSpotlight = ({
|
|
|
53
50
|
VideoRenderer,
|
|
54
51
|
supportedReactions,
|
|
55
52
|
landscape,
|
|
56
|
-
disablePictureInPicture,
|
|
57
53
|
}: CallParticipantsSpotlightProps) => {
|
|
58
54
|
const {
|
|
59
55
|
theme: { callParticipantsSpotlight, variants },
|
|
@@ -69,7 +65,7 @@ export const CallParticipantsSpotlight = ({
|
|
|
69
65
|
participantInSpotlight && hasScreenShare(participantInSpotlight);
|
|
70
66
|
const isUserAloneInCall = _allParticipants?.length === 1;
|
|
71
67
|
|
|
72
|
-
const isInPiP = useIsInPiPMode(
|
|
68
|
+
const isInPiP = useIsInPiPMode();
|
|
73
69
|
|
|
74
70
|
const participantViewProps: ParticipantViewComponentProps = {
|
|
75
71
|
ParticipantLabel,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React, {
|
|
2
|
-
PropsWithChildren,
|
|
3
2
|
createContext,
|
|
3
|
+
PropsWithChildren,
|
|
4
4
|
useCallback,
|
|
5
5
|
useContext,
|
|
6
6
|
useMemo,
|
|
@@ -9,7 +9,7 @@ import React, {
|
|
|
9
9
|
} from 'react';
|
|
10
10
|
import { MediaStream } from '@stream-io/react-native-webrtc';
|
|
11
11
|
import { useCall } from '@stream-io/video-react-bindings';
|
|
12
|
-
import { Platform } from 'react-native';
|
|
12
|
+
import { Image, Platform } from 'react-native';
|
|
13
13
|
|
|
14
14
|
const isSupported = (function () {
|
|
15
15
|
if (Platform.OS === 'ios') {
|
|
@@ -29,8 +29,6 @@ try {
|
|
|
29
29
|
videoFiltersModule = require('@stream-io/video-filters-react-native');
|
|
30
30
|
} catch (_e) {}
|
|
31
31
|
|
|
32
|
-
import { Image } from 'react-native';
|
|
33
|
-
|
|
34
32
|
const resolveAssetSourceFunc = Image.resolveAssetSource;
|
|
35
33
|
|
|
36
34
|
// excluding array of images and only allow one image
|
|
@@ -173,7 +171,6 @@ export const BackgroundFiltersProvider = ({ children }: PropsWithChildren) => {
|
|
|
173
171
|
(call?.camera.state.mediaStream as MediaStream | undefined)
|
|
174
172
|
?.getVideoTracks()
|
|
175
173
|
.forEach((track) => {
|
|
176
|
-
// @ts-expect-error - webrtc typing is wrong, null is supported
|
|
177
174
|
track._setVideoEffect(null);
|
|
178
175
|
});
|
|
179
176
|
setCurrentBackgroundFilter(undefined);
|
|
@@ -2,6 +2,7 @@ import { CallingState } from '@stream-io/video-client';
|
|
|
2
2
|
import { useCallStateHooks } from '@stream-io/video-react-bindings';
|
|
3
3
|
import { useEffect } from 'react';
|
|
4
4
|
import { NativeModules, Platform } from 'react-native';
|
|
5
|
+
import { disablePiPMode$ } from '../utils/internal/rxSubjects';
|
|
5
6
|
|
|
6
7
|
export function useAutoEnterPiPEffect(
|
|
7
8
|
disablePictureInPicture: boolean | undefined
|
|
@@ -10,7 +11,7 @@ export function useAutoEnterPiPEffect(
|
|
|
10
11
|
|
|
11
12
|
const callingState = useCallCallingState();
|
|
12
13
|
|
|
13
|
-
// if we need to enable, only enable in joined state
|
|
14
|
+
// if we need to enable autoEnter, only enable in joined state
|
|
14
15
|
useEffect(() => {
|
|
15
16
|
if (Platform.OS !== 'android') {
|
|
16
17
|
return;
|
|
@@ -23,12 +24,14 @@ export function useAutoEnterPiPEffect(
|
|
|
23
24
|
}
|
|
24
25
|
}, [callingState, disablePictureInPicture]);
|
|
25
26
|
|
|
26
|
-
// on unmount always disable PiP mode
|
|
27
27
|
useEffect(() => {
|
|
28
|
+
disablePiPMode$.next(disablePictureInPicture === true);
|
|
29
|
+
|
|
28
30
|
if (Platform.OS !== 'android') {
|
|
29
31
|
return;
|
|
30
32
|
}
|
|
31
33
|
|
|
34
|
+
// on unmount always disable PiP mode auto enter
|
|
32
35
|
return () => {
|
|
33
36
|
NativeModules.StreamVideoReactNative.canAutoEnterPipMode(false);
|
|
34
37
|
};
|
|
@@ -1,60 +1,24 @@
|
|
|
1
1
|
import { useEffect, useState } from 'react';
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
NativeEventEmitter,
|
|
5
|
-
NativeModules,
|
|
6
|
-
Platform,
|
|
7
|
-
} from 'react-native';
|
|
2
|
+
import { RxUtils } from '@stream-io/video-client';
|
|
3
|
+
import { isInPiPModeAndroid$ } from '../utils/internal/rxSubjects';
|
|
8
4
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
export function useIsInPiPMode(disablePictureInPicture: boolean | undefined) {
|
|
14
|
-
const [isInPiPMode, setIsInPiPMode] = useState(
|
|
15
|
-
disablePictureInPicture &&
|
|
16
|
-
isAndroid8OrAbove &&
|
|
17
|
-
AppState.currentState === 'background'
|
|
18
|
-
);
|
|
5
|
+
export function useIsInPiPMode() {
|
|
6
|
+
const [value, setValue] = useState<boolean>(() => {
|
|
7
|
+
return RxUtils.getCurrentValue(isInPiPModeAndroid$);
|
|
8
|
+
});
|
|
19
9
|
|
|
20
10
|
useEffect(() => {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
);
|
|
28
|
-
|
|
29
|
-
const subscriptionPiPChange = eventEmitter.addListener(
|
|
30
|
-
PIP_CHANGE_EVENT,
|
|
31
|
-
setIsInPiPMode
|
|
32
|
-
);
|
|
33
|
-
|
|
34
|
-
const setFromNativeMethod = async () => {
|
|
35
|
-
const isInPiPNativeMethod: boolean | null | undefined =
|
|
36
|
-
await NativeModules?.StreamVideoReactNative?.isInPiPMode();
|
|
37
|
-
setIsInPiPMode(!!isInPiPNativeMethod);
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
const subscriptionAppState = AppState.addEventListener(
|
|
41
|
-
'change',
|
|
42
|
-
(nextAppState) => {
|
|
43
|
-
if (nextAppState === 'background') {
|
|
44
|
-
setIsInPiPMode(!disablePictureInPicture); // set with an assumption that its enabled so that UI disabling happens faster
|
|
45
|
-
// if PiP was not enabled anyway, then in the next code we ll set it to false and UI wont be shown anyway
|
|
46
|
-
}
|
|
47
|
-
setFromNativeMethod();
|
|
48
|
-
}
|
|
49
|
-
);
|
|
50
|
-
|
|
51
|
-
setFromNativeMethod();
|
|
52
|
-
|
|
11
|
+
const subscription = isInPiPModeAndroid$.subscribe({
|
|
12
|
+
next: setValue,
|
|
13
|
+
error: (err) => {
|
|
14
|
+
console.log('An error occurred while reading isInPiPModeAndroid$', err);
|
|
15
|
+
setValue(false);
|
|
16
|
+
},
|
|
17
|
+
});
|
|
53
18
|
return () => {
|
|
54
|
-
|
|
55
|
-
subscriptionAppState.remove();
|
|
19
|
+
subscription.unsubscribe();
|
|
56
20
|
};
|
|
57
|
-
}, [
|
|
21
|
+
}, []);
|
|
58
22
|
|
|
59
|
-
return
|
|
23
|
+
return value;
|
|
60
24
|
}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { useCall } from '@stream-io/video-react-bindings';
|
|
2
|
+
import { useEffect, useRef } from 'react';
|
|
3
|
+
import {
|
|
4
|
+
AppState,
|
|
5
|
+
NativeEventEmitter,
|
|
6
|
+
NativeModules,
|
|
7
|
+
Platform,
|
|
8
|
+
} from 'react-native';
|
|
9
|
+
import { shouldDisableIOSLocalVideoOnBackgroundRef } from '../../utils/internal/shouldDisableIOSLocalVideoOnBackground';
|
|
10
|
+
import {
|
|
11
|
+
disablePiPMode$,
|
|
12
|
+
isInPiPModeAndroid$,
|
|
13
|
+
} from '../../utils/internal/rxSubjects';
|
|
14
|
+
import { RxUtils } from '@stream-io/video-client';
|
|
15
|
+
|
|
16
|
+
const PIP_CHANGE_EVENT = 'StreamVideoReactNative_PIP_CHANGE_EVENT';
|
|
17
|
+
|
|
18
|
+
const isAndroid8OrAbove = Platform.OS === 'android' && Platform.Version >= 26;
|
|
19
|
+
|
|
20
|
+
// Does 2 functionalities:
|
|
21
|
+
// 1. Resume/Disable video stream tracks when app goes to background/foreground - To save on CPU resources
|
|
22
|
+
// 2. Handle PiP mode in Android
|
|
23
|
+
export const AppStateListener = () => {
|
|
24
|
+
const call = useCall();
|
|
25
|
+
const appState = useRef(AppState.currentState);
|
|
26
|
+
|
|
27
|
+
// on mount: set initial PiP mode and listen to PiP events
|
|
28
|
+
useEffect(() => {
|
|
29
|
+
if (!isAndroid8OrAbove) {
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const disablePiP = RxUtils.getCurrentValue(disablePiPMode$);
|
|
34
|
+
isInPiPModeAndroid$.next(
|
|
35
|
+
!disablePiP && AppState.currentState === 'background'
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
const eventEmitter = new NativeEventEmitter(
|
|
39
|
+
NativeModules.StreamVideoReactNative
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
const subscriptionPiPChange = eventEmitter.addListener(
|
|
43
|
+
PIP_CHANGE_EVENT,
|
|
44
|
+
(isInPiPMode: boolean) => {
|
|
45
|
+
isInPiPModeAndroid$.next(isInPiPMode);
|
|
46
|
+
}
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
return () => {
|
|
50
|
+
subscriptionPiPChange.remove();
|
|
51
|
+
};
|
|
52
|
+
}, []);
|
|
53
|
+
|
|
54
|
+
useEffect(() => {
|
|
55
|
+
// due to strange behavior in iOS when app goes to "inactive" state
|
|
56
|
+
// we dont check for inactive states
|
|
57
|
+
// ref: https://www.reddit.com/r/reactnative/comments/15kib42/appstate_behavior_in_ios_when_swiping_down_to/
|
|
58
|
+
const subscription = AppState.addEventListener('change', (nextAppState) => {
|
|
59
|
+
if (appState.current.match(/background/) && nextAppState === 'active') {
|
|
60
|
+
if (
|
|
61
|
+
call?.camera?.state.status === 'enabled' &&
|
|
62
|
+
Platform.OS === 'android'
|
|
63
|
+
) {
|
|
64
|
+
// when device is locked and resumed, the status isnt made disabled but stays enabled
|
|
65
|
+
// as a workaround we stop the track and enable again if its already in enabled state
|
|
66
|
+
call?.camera?.disable(true).then(() => {
|
|
67
|
+
call?.camera?.enable();
|
|
68
|
+
});
|
|
69
|
+
} else {
|
|
70
|
+
call?.camera?.resume();
|
|
71
|
+
}
|
|
72
|
+
appState.current = nextAppState;
|
|
73
|
+
} else if (
|
|
74
|
+
appState.current === 'active' &&
|
|
75
|
+
nextAppState.match(/background/)
|
|
76
|
+
) {
|
|
77
|
+
if (Platform.OS === 'android') {
|
|
78
|
+
// in Android, we need to check if we are in PiP mode
|
|
79
|
+
// in PiP mode, we don't want to disable the camera
|
|
80
|
+
const disableCameraIfNeeded = () => {
|
|
81
|
+
if (call?.camera?.state.status === 'enabled') {
|
|
82
|
+
call?.camera?.disable();
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
if (isAndroid8OrAbove) {
|
|
86
|
+
// set with an assumption that its enabled so that UI disabling happens faster
|
|
87
|
+
const disablePiP = RxUtils.getCurrentValue(disablePiPMode$);
|
|
88
|
+
isInPiPModeAndroid$.next(!disablePiP);
|
|
89
|
+
// if PiP was not enabled anyway, then in the next code we ll set it to false and UI wont be shown anyway
|
|
90
|
+
NativeModules?.StreamVideoReactNative?.isInPiPMode().then(
|
|
91
|
+
(isInPiP: boolean | null | undefined) => {
|
|
92
|
+
isInPiPModeAndroid$.next(!!isInPiP);
|
|
93
|
+
if (!isInPiP) {
|
|
94
|
+
if (AppState.currentState === 'active') {
|
|
95
|
+
// this is to handle the case that the app became active as soon as it went to background
|
|
96
|
+
// in this case, we dont want to disable the camera
|
|
97
|
+
// this happens on foreground push notifications
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
disableCameraIfNeeded();
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
);
|
|
104
|
+
} else {
|
|
105
|
+
disableCameraIfNeeded();
|
|
106
|
+
}
|
|
107
|
+
} else {
|
|
108
|
+
// shouldDisableIOSLocalVideoOnBackgroundRef is false, if local video is enabled on PiP
|
|
109
|
+
if (shouldDisableIOSLocalVideoOnBackgroundRef.current) {
|
|
110
|
+
if (call?.camera?.state.status === 'enabled') {
|
|
111
|
+
call?.camera?.disable();
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
appState.current = nextAppState;
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
return () => {
|
|
120
|
+
subscription.remove();
|
|
121
|
+
};
|
|
122
|
+
}, [call]);
|
|
123
|
+
|
|
124
|
+
return null;
|
|
125
|
+
};
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { useCallStateHooks } from '@stream-io/video-react-bindings';
|
|
2
|
+
import { useEffect } from 'react';
|
|
3
|
+
import {
|
|
4
|
+
CallingState,
|
|
5
|
+
setThermalState,
|
|
6
|
+
setPowerState,
|
|
7
|
+
} from '@stream-io/video-client';
|
|
8
|
+
import { NativeModules, Platform, NativeEventEmitter } from 'react-native';
|
|
9
|
+
|
|
10
|
+
const eventEmitter = NativeModules?.StreamVideoReactNative
|
|
11
|
+
? new NativeEventEmitter(NativeModules?.StreamVideoReactNative)
|
|
12
|
+
: undefined;
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* This is a renderless component to get the device stats like thermal state and power saver mode.
|
|
16
|
+
*/
|
|
17
|
+
export const DeviceStats = () => {
|
|
18
|
+
const { useCallCallingState } = useCallStateHooks();
|
|
19
|
+
const callingState = useCallCallingState();
|
|
20
|
+
|
|
21
|
+
useEffect(() => {
|
|
22
|
+
if (callingState !== CallingState.JOINED) {
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
NativeModules?.StreamVideoReactNative.isLowPowerModeEnabled().then(
|
|
27
|
+
(initialPowerMode: boolean) => setPowerState(initialPowerMode)
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
let powerModeSubscription = eventEmitter?.addListener(
|
|
31
|
+
'isLowPowerModeEnabled',
|
|
32
|
+
(isLowPowerMode: boolean) => setPowerState(isLowPowerMode)
|
|
33
|
+
);
|
|
34
|
+
|
|
35
|
+
NativeModules?.StreamVideoReactNative.currentThermalState().then(
|
|
36
|
+
(initialState: string) => setThermalState(initialState)
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
let thermalStateSubscription = eventEmitter?.addListener(
|
|
40
|
+
'thermalStateDidChange',
|
|
41
|
+
(thermalState: string) => setThermalState(thermalState)
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
// on android we need to explicitly start and stop the thermal status updates
|
|
45
|
+
if (Platform.OS === 'android') {
|
|
46
|
+
NativeModules?.StreamVideoReactNative.startThermalStatusUpdates();
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return () => {
|
|
50
|
+
powerModeSubscription?.remove();
|
|
51
|
+
thermalStateSubscription?.remove();
|
|
52
|
+
if (Platform.OS === 'android') {
|
|
53
|
+
NativeModules?.StreamVideoReactNative.stopThermalStatusUpdates();
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
}, [callingState]);
|
|
57
|
+
|
|
58
|
+
return null;
|
|
59
|
+
};
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { StreamCallProvider } from '@stream-io/video-react-bindings';
|
|
2
|
+
import React, { PropsWithChildren, useEffect } from 'react';
|
|
3
|
+
import { Call } from '@stream-io/video-client';
|
|
4
|
+
import { useIosCallkeepWithCallingStateEffect } from '../../hooks/push/useIosCallkeepWithCallingStateEffect';
|
|
5
|
+
import {
|
|
6
|
+
canAddPushWSSubscriptionsRef,
|
|
7
|
+
clearPushWSEventSubscriptions,
|
|
8
|
+
} from '../../utils/push/internal/utils';
|
|
9
|
+
import { useAndroidKeepCallAliveEffect } from '../../hooks/useAndroidKeepCallAliveEffect';
|
|
10
|
+
import { AppStateListener } from './AppStateListener';
|
|
11
|
+
import { DeviceStats } from './DeviceStats';
|
|
12
|
+
|
|
13
|
+
// const PIP_CHANGE_EVENT = 'StreamVideoReactNative_PIP_CHANGE_EVENT';
|
|
14
|
+
|
|
15
|
+
// const isAndroid8OrAbove = Platform.OS === 'android' && Platform.Version >= 26;
|
|
16
|
+
|
|
17
|
+
export type StreamCallProps = {
|
|
18
|
+
/**
|
|
19
|
+
* Stream Call instance propagated to the component's children as a part of StreamCallContext.
|
|
20
|
+
* Children can access it with useCall() hook.
|
|
21
|
+
*/
|
|
22
|
+
call: Call;
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* StreamCall is a wrapper component that orchestrates the call life cycle logic and
|
|
26
|
+
* provides the call object to the children components.
|
|
27
|
+
* @param PropsWithChildren<StreamCallProps>
|
|
28
|
+
*
|
|
29
|
+
* @category Client State
|
|
30
|
+
*/
|
|
31
|
+
export const StreamCall = ({
|
|
32
|
+
call,
|
|
33
|
+
children,
|
|
34
|
+
}: PropsWithChildren<StreamCallProps>) => {
|
|
35
|
+
return (
|
|
36
|
+
<StreamCallProvider call={call}>
|
|
37
|
+
<AppStateListener />
|
|
38
|
+
<AndroidKeepCallAlive />
|
|
39
|
+
<IosInformCallkeepCallEnd />
|
|
40
|
+
<ClearPushWSSubscriptions />
|
|
41
|
+
<DeviceStats />
|
|
42
|
+
{children}
|
|
43
|
+
</StreamCallProvider>
|
|
44
|
+
);
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* This is a renderless component to keep the call alive on Android device using useAndroidKeepCallAliveEffect.
|
|
49
|
+
* useAndroidKeepCallAliveEffect needs to called inside a child of StreamCallProvider.
|
|
50
|
+
*/
|
|
51
|
+
const AndroidKeepCallAlive = () => {
|
|
52
|
+
useAndroidKeepCallAliveEffect();
|
|
53
|
+
return null;
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* This is a renderless component to end the call in callkeep for ios.
|
|
58
|
+
* useAndroidKeepCallAliveEffect needs to called inside a child of StreamCallProvider.
|
|
59
|
+
*/
|
|
60
|
+
const IosInformCallkeepCallEnd = () => {
|
|
61
|
+
useIosCallkeepWithCallingStateEffect();
|
|
62
|
+
return null;
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* This is a renderless component to clear all push ws event subscriptions
|
|
67
|
+
* and set whether push ws subscriptions can be added or not.
|
|
68
|
+
*/
|
|
69
|
+
const ClearPushWSSubscriptions = () => {
|
|
70
|
+
useEffect(() => {
|
|
71
|
+
clearPushWSEventSubscriptions();
|
|
72
|
+
canAddPushWSSubscriptionsRef.current = false;
|
|
73
|
+
return () => {
|
|
74
|
+
canAddPushWSSubscriptionsRef.current = true;
|
|
75
|
+
};
|
|
76
|
+
}, []);
|
|
77
|
+
return null;
|
|
78
|
+
};
|
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
ClientPublishOptions,
|
|
3
|
+
StreamVideoClient,
|
|
4
|
+
} from '@stream-io/video-client';
|
|
2
5
|
import type { AndroidChannel } from '@notifee/react-native';
|
|
3
6
|
|
|
4
7
|
export type NonRingingPushEvent = 'call.live_started' | 'call.notification';
|
|
@@ -16,7 +19,7 @@ export type StreamVideoConfig = {
|
|
|
16
19
|
*
|
|
17
20
|
* @internal
|
|
18
21
|
*/
|
|
19
|
-
publishOptions?:
|
|
22
|
+
publishOptions?: ClientPublishOptions;
|
|
20
23
|
ios: {
|
|
21
24
|
/**
|
|
22
25
|
* The name for the alias of push provider used for iOS
|
package/src/version.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const version = '1.
|
|
1
|
+
export const version = '1.9.0';
|
|
@@ -1,155 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
exports.StreamCall = void 0;
|
|
7
|
-
var _videoReactBindings = require("@stream-io/video-react-bindings");
|
|
8
|
-
var _react = _interopRequireWildcard(require("react"));
|
|
9
|
-
var _videoClient = require("@stream-io/video-client");
|
|
10
|
-
var _useIosCallkeepWithCallingStateEffect = require("../hooks/push/useIosCallkeepWithCallingStateEffect");
|
|
11
|
-
var _utils = require("../utils/push/internal/utils");
|
|
12
|
-
var _useAndroidKeepCallAliveEffect = require("../hooks/useAndroidKeepCallAliveEffect");
|
|
13
|
-
var _reactNative = require("react-native");
|
|
14
|
-
var _shouldDisableIOSLocalVideoOnBackground = require("../utils/internal/shouldDisableIOSLocalVideoOnBackground");
|
|
15
|
-
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
|
|
16
|
-
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
|
|
17
|
-
/**
|
|
18
|
-
* StreamCall is a wrapper component that orchestrates the call life cycle logic and
|
|
19
|
-
* provides the call object to the children components.
|
|
20
|
-
* @param PropsWithChildren<StreamCallProps>
|
|
21
|
-
*
|
|
22
|
-
* @category Client State
|
|
23
|
-
*/
|
|
24
|
-
const StreamCall = ({
|
|
25
|
-
call,
|
|
26
|
-
children
|
|
27
|
-
}) => {
|
|
28
|
-
return /*#__PURE__*/_react.default.createElement(_videoReactBindings.StreamCallProvider, {
|
|
29
|
-
call: call
|
|
30
|
-
}, /*#__PURE__*/_react.default.createElement(AppStateListener, null), /*#__PURE__*/_react.default.createElement(AndroidKeepCallAlive, null), /*#__PURE__*/_react.default.createElement(IosInformCallkeepCallEnd, null), /*#__PURE__*/_react.default.createElement(ClearPushWSSubscriptions, null), /*#__PURE__*/_react.default.createElement(DeviceStats, null), children);
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
// Resume/Disable video stream tracks when app goes to background/foreground
|
|
34
|
-
// To save on CPU resources
|
|
35
|
-
exports.StreamCall = StreamCall;
|
|
36
|
-
const AppStateListener = () => {
|
|
37
|
-
const call = (0, _videoReactBindings.useCall)();
|
|
38
|
-
const appState = (0, _react.useRef)(_reactNative.AppState.currentState);
|
|
39
|
-
(0, _react.useEffect)(() => {
|
|
40
|
-
// due to strange behavior in iOS when app goes to "inactive" state
|
|
41
|
-
// we dont check for inactive states
|
|
42
|
-
// ref: https://www.reddit.com/r/reactnative/comments/15kib42/appstate_behavior_in_ios_when_swiping_down_to/
|
|
43
|
-
const subscription = _reactNative.AppState.addEventListener('change', nextAppState => {
|
|
44
|
-
if (appState.current.match(/background/) && nextAppState === 'active') {
|
|
45
|
-
if (call?.camera?.state.status === 'enabled' && _reactNative.Platform.OS === 'android') {
|
|
46
|
-
// when device is locked and resumed, the status isnt made disabled but stays enabled
|
|
47
|
-
// as a workaround we stop the track and enable again if its already in enabled state
|
|
48
|
-
call?.camera?.disable(true).then(() => {
|
|
49
|
-
call?.camera?.enable();
|
|
50
|
-
});
|
|
51
|
-
} else {
|
|
52
|
-
call?.camera?.resume();
|
|
53
|
-
}
|
|
54
|
-
appState.current = nextAppState;
|
|
55
|
-
} else if (appState.current === 'active' && nextAppState.match(/background/)) {
|
|
56
|
-
if (_reactNative.Platform.OS === 'android') {
|
|
57
|
-
// in Android, we need to check if we are in PiP mode
|
|
58
|
-
// in PiP mode, we don't want to disable the camera
|
|
59
|
-
_reactNative.NativeModules?.StreamVideoReactNative?.isInPiPMode().then(isInPiP => {
|
|
60
|
-
if (!isInPiP) {
|
|
61
|
-
if (_reactNative.AppState.currentState === 'active') {
|
|
62
|
-
// this is to handle the case that the app became active as soon as it went to background
|
|
63
|
-
// in this case, we dont want to disable the camera
|
|
64
|
-
// this happens on foreground push notifications
|
|
65
|
-
return;
|
|
66
|
-
}
|
|
67
|
-
if (call?.camera?.state.status === 'enabled') {
|
|
68
|
-
call?.camera?.disable();
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
});
|
|
72
|
-
} else {
|
|
73
|
-
// shouldDisableIOSLocalVideoOnBackgroundRef is false, if local video is enabled on PiP
|
|
74
|
-
if (_shouldDisableIOSLocalVideoOnBackground.shouldDisableIOSLocalVideoOnBackgroundRef.current) {
|
|
75
|
-
if (call?.camera?.state.status === 'enabled') {
|
|
76
|
-
call?.camera?.disable();
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
appState.current = nextAppState;
|
|
81
|
-
}
|
|
82
|
-
});
|
|
83
|
-
return () => {
|
|
84
|
-
subscription.remove();
|
|
85
|
-
};
|
|
86
|
-
}, [call]);
|
|
87
|
-
return null;
|
|
88
|
-
};
|
|
89
|
-
|
|
90
|
-
/**
|
|
91
|
-
* This is a renderless component to keep the call alive on Android device using useAndroidKeepCallAliveEffect.
|
|
92
|
-
* useAndroidKeepCallAliveEffect needs to called inside a child of StreamCallProvider.
|
|
93
|
-
*/
|
|
94
|
-
const AndroidKeepCallAlive = () => {
|
|
95
|
-
(0, _useAndroidKeepCallAliveEffect.useAndroidKeepCallAliveEffect)();
|
|
96
|
-
return null;
|
|
97
|
-
};
|
|
98
|
-
|
|
99
|
-
/**
|
|
100
|
-
* This is a renderless component to end the call in callkeep for ios.
|
|
101
|
-
* useAndroidKeepCallAliveEffect needs to called inside a child of StreamCallProvider.
|
|
102
|
-
*/
|
|
103
|
-
const IosInformCallkeepCallEnd = () => {
|
|
104
|
-
(0, _useIosCallkeepWithCallingStateEffect.useIosCallkeepWithCallingStateEffect)();
|
|
105
|
-
return null;
|
|
106
|
-
};
|
|
107
|
-
|
|
108
|
-
/**
|
|
109
|
-
* This is a renderless component to clear all push ws event subscriptions
|
|
110
|
-
* and set whether push ws subscriptions can be added or not.
|
|
111
|
-
*/
|
|
112
|
-
const ClearPushWSSubscriptions = () => {
|
|
113
|
-
(0, _react.useEffect)(() => {
|
|
114
|
-
(0, _utils.clearPushWSEventSubscriptions)();
|
|
115
|
-
_utils.canAddPushWSSubscriptionsRef.current = false;
|
|
116
|
-
return () => {
|
|
117
|
-
_utils.canAddPushWSSubscriptionsRef.current = true;
|
|
118
|
-
};
|
|
119
|
-
}, []);
|
|
120
|
-
return null;
|
|
121
|
-
};
|
|
122
|
-
const eventEmitter = _reactNative.NativeModules?.StreamVideoReactNative ? new _reactNative.NativeEventEmitter(_reactNative.NativeModules?.StreamVideoReactNative) : undefined;
|
|
123
|
-
|
|
124
|
-
/**
|
|
125
|
-
* This is a renderless component to get the device stats like thermal state and power saver mode.
|
|
126
|
-
*/
|
|
127
|
-
const DeviceStats = () => {
|
|
128
|
-
const {
|
|
129
|
-
useCallCallingState
|
|
130
|
-
} = (0, _videoReactBindings.useCallStateHooks)();
|
|
131
|
-
const callingState = useCallCallingState();
|
|
132
|
-
(0, _react.useEffect)(() => {
|
|
133
|
-
if (callingState !== _videoClient.CallingState.JOINED) {
|
|
134
|
-
return;
|
|
135
|
-
}
|
|
136
|
-
_reactNative.NativeModules?.StreamVideoReactNative.isLowPowerModeEnabled().then(initialPowerMode => (0, _videoClient.setPowerState)(initialPowerMode));
|
|
137
|
-
let powerModeSubscription = eventEmitter?.addListener('isLowPowerModeEnabled', isLowPowerMode => (0, _videoClient.setPowerState)(isLowPowerMode));
|
|
138
|
-
_reactNative.NativeModules?.StreamVideoReactNative.currentThermalState().then(initialState => (0, _videoClient.setThermalState)(initialState));
|
|
139
|
-
let thermalStateSubscription = eventEmitter?.addListener('thermalStateDidChange', thermalState => (0, _videoClient.setThermalState)(thermalState));
|
|
140
|
-
|
|
141
|
-
// on android we need to explicitly start and stop the thermal status updates
|
|
142
|
-
if (_reactNative.Platform.OS === 'android') {
|
|
143
|
-
_reactNative.NativeModules?.StreamVideoReactNative.startThermalStatusUpdates();
|
|
144
|
-
}
|
|
145
|
-
return () => {
|
|
146
|
-
powerModeSubscription?.remove();
|
|
147
|
-
thermalStateSubscription?.remove();
|
|
148
|
-
if (_reactNative.Platform.OS === 'android') {
|
|
149
|
-
_reactNative.NativeModules?.StreamVideoReactNative.stopThermalStatusUpdates();
|
|
150
|
-
}
|
|
151
|
-
};
|
|
152
|
-
}, [callingState]);
|
|
153
|
-
return null;
|
|
154
|
-
};
|
|
155
|
-
//# sourceMappingURL=StreamCall.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"names":["_videoReactBindings","require","_react","_interopRequireWildcard","_videoClient","_useIosCallkeepWithCallingStateEffect","_utils","_useAndroidKeepCallAliveEffect","_reactNative","_shouldDisableIOSLocalVideoOnBackground","_getRequireWildcardCache","e","WeakMap","r","t","__esModule","default","has","get","n","__proto__","a","Object","defineProperty","getOwnPropertyDescriptor","u","hasOwnProperty","call","i","set","StreamCall","children","createElement","StreamCallProvider","AppStateListener","AndroidKeepCallAlive","IosInformCallkeepCallEnd","ClearPushWSSubscriptions","DeviceStats","exports","useCall","appState","useRef","AppState","currentState","useEffect","subscription","addEventListener","nextAppState","current","match","camera","state","status","Platform","OS","disable","then","enable","resume","NativeModules","StreamVideoReactNative","isInPiPMode","isInPiP","shouldDisableIOSLocalVideoOnBackgroundRef","remove","useAndroidKeepCallAliveEffect","useIosCallkeepWithCallingStateEffect","clearPushWSEventSubscriptions","canAddPushWSSubscriptionsRef","eventEmitter","NativeEventEmitter","undefined","useCallCallingState","useCallStateHooks","callingState","CallingState","JOINED","isLowPowerModeEnabled","initialPowerMode","setPowerState","powerModeSubscription","addListener","isLowPowerMode","currentThermalState","initialState","setThermalState","thermalStateSubscription","thermalState","startThermalStatusUpdates","stopThermalStatusUpdates"],"sourceRoot":"../../../src","sources":["providers/StreamCall.tsx"],"mappings":"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","ignoreList":[]}
|