@stream-io/video-react-native-sdk 1.21.2 → 1.22.1-alpha.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/gradle.properties +3 -3
- package/android/src/main/java/com/streamvideo/reactnative/StreamVideoReactNativeModule.kt +10 -0
- package/android/src/main/java/com/streamvideo/reactnative/StreamVideoReactNativePackage.kt +2 -1
- package/android/src/main/java/com/streamvideo/reactnative/audio/AudioDeviceManager.kt +592 -0
- package/android/src/main/java/com/streamvideo/reactnative/audio/BluetoothManager.kt +755 -0
- package/android/src/main/java/com/streamvideo/reactnative/audio/utils/AudioDeviceEndpointUtils.kt +192 -0
- package/android/src/main/java/com/streamvideo/reactnative/audio/utils/AudioFocusUtil.kt +62 -0
- package/android/src/main/java/com/streamvideo/reactnative/audio/utils/AudioManagerUtil.kt +159 -0
- package/android/src/main/java/com/streamvideo/reactnative/audio/utils/AudioSetupStoreUtil.kt +41 -0
- package/android/src/main/java/com/streamvideo/reactnative/audio/utils/WebRtcAudioUtils.kt +250 -0
- package/android/src/main/java/com/streamvideo/reactnative/callmanager/StreamInCallManagerModule.kt +191 -0
- package/android/src/main/java/com/streamvideo/reactnative/model/AudioDeviceEndpoint.kt +136 -0
- package/android/src/main/java/org/webrtc/audio/WebRtcAudioTrackHelper.kt +12 -0
- package/dist/commonjs/components/Call/CallContent/CallContent.js +13 -9
- package/dist/commonjs/components/Call/CallContent/CallContent.js.map +1 -1
- package/dist/commonjs/components/Call/CallContent/RTCViewPipIOS.js +9 -2
- package/dist/commonjs/components/Call/CallContent/RTCViewPipIOS.js.map +1 -1
- package/dist/commonjs/components/Call/CallContent/RTCViewPipNative.js +3 -0
- package/dist/commonjs/components/Call/CallContent/RTCViewPipNative.js.map +1 -1
- package/dist/commonjs/components/Livestream/HostLivestream/HostLivestream.js +10 -6
- package/dist/commonjs/components/Livestream/HostLivestream/HostLivestream.js.map +1 -1
- package/dist/commonjs/components/Livestream/LivestreamControls/ViewerLivestreamControls.js +8 -4
- package/dist/commonjs/components/Livestream/LivestreamControls/ViewerLivestreamControls.js.map +1 -1
- package/dist/commonjs/components/Livestream/LivestreamLayout/LivestreamLayout.js +26 -27
- package/dist/commonjs/components/Livestream/LivestreamLayout/LivestreamLayout.js.map +1 -1
- package/dist/commonjs/components/Livestream/ViewerLivestream/ViewerLivestream.js +10 -6
- package/dist/commonjs/components/Livestream/ViewerLivestream/ViewerLivestream.js.map +1 -1
- package/dist/commonjs/hooks/useIsInPiPMode.js +3 -3
- package/dist/commonjs/hooks/useIsInPiPMode.js.map +1 -1
- package/dist/commonjs/hooks/usePermissionNotification.js +5 -5
- package/dist/commonjs/hooks/usePermissionNotification.js.map +1 -1
- package/dist/commonjs/index.js +12 -0
- package/dist/commonjs/index.js.map +1 -1
- package/dist/commonjs/modules/call-manager/CallManager.js +113 -0
- package/dist/commonjs/modules/call-manager/CallManager.js.map +1 -0
- package/dist/commonjs/modules/call-manager/PrevLibDetection.js +18 -0
- package/dist/commonjs/modules/call-manager/PrevLibDetection.js.map +1 -0
- package/dist/commonjs/modules/call-manager/index.js +24 -0
- package/dist/commonjs/modules/call-manager/index.js.map +1 -0
- package/dist/commonjs/modules/call-manager/native-module.d.js +4 -0
- package/dist/commonjs/modules/call-manager/native-module.d.js.map +1 -0
- package/dist/commonjs/modules/call-manager/types.js +2 -0
- package/dist/commonjs/modules/call-manager/types.js.map +1 -0
- package/dist/commonjs/providers/StreamCall/AppStateListener.js +5 -5
- package/dist/commonjs/providers/StreamCall/AppStateListener.js.map +1 -1
- package/dist/commonjs/theme/theme.js.map +1 -1
- package/dist/commonjs/utils/internal/rxSubjects.js +2 -2
- package/dist/commonjs/utils/internal/rxSubjects.js.map +1 -1
- package/dist/commonjs/version.js +1 -1
- package/dist/commonjs/version.js.map +1 -1
- package/dist/module/components/Call/CallContent/CallContent.js +14 -9
- package/dist/module/components/Call/CallContent/CallContent.js.map +1 -1
- package/dist/module/components/Call/CallContent/RTCViewPipIOS.js +9 -2
- package/dist/module/components/Call/CallContent/RTCViewPipIOS.js.map +1 -1
- package/dist/module/components/Call/CallContent/RTCViewPipNative.js +3 -0
- package/dist/module/components/Call/CallContent/RTCViewPipNative.js.map +1 -1
- package/dist/module/components/Livestream/HostLivestream/HostLivestream.js +10 -5
- package/dist/module/components/Livestream/HostLivestream/HostLivestream.js.map +1 -1
- package/dist/module/components/Livestream/LivestreamControls/ViewerLivestreamControls.js +9 -4
- package/dist/module/components/Livestream/LivestreamControls/ViewerLivestreamControls.js.map +1 -1
- package/dist/module/components/Livestream/LivestreamLayout/LivestreamLayout.js +26 -27
- package/dist/module/components/Livestream/LivestreamLayout/LivestreamLayout.js.map +1 -1
- package/dist/module/components/Livestream/ViewerLivestream/ViewerLivestream.js +10 -5
- package/dist/module/components/Livestream/ViewerLivestream/ViewerLivestream.js.map +1 -1
- package/dist/module/hooks/useIsInPiPMode.js +4 -4
- package/dist/module/hooks/useIsInPiPMode.js.map +1 -1
- package/dist/module/hooks/usePermissionNotification.js +7 -6
- package/dist/module/hooks/usePermissionNotification.js.map +1 -1
- package/dist/module/icons/Back.js +1 -1
- package/dist/module/icons/Back.js.map +1 -1
- package/dist/module/icons/CameraSwitch.js +1 -1
- package/dist/module/icons/CameraSwitch.js.map +1 -1
- package/dist/module/icons/Mic.js +1 -1
- package/dist/module/icons/Mic.js.map +1 -1
- package/dist/module/icons/MicOff.js +1 -1
- package/dist/module/icons/MicOff.js.map +1 -1
- package/dist/module/icons/Phone.js +1 -1
- package/dist/module/icons/Phone.js.map +1 -1
- package/dist/module/icons/PinVertical.js +1 -1
- package/dist/module/icons/PinVertical.js.map +1 -1
- package/dist/module/icons/Reaction.js +1 -1
- package/dist/module/icons/Reaction.js.map +1 -1
- package/dist/module/icons/Spotlight.js +1 -1
- package/dist/module/icons/Spotlight.js.map +1 -1
- package/dist/module/icons/Video.js +1 -1
- package/dist/module/icons/Video.js.map +1 -1
- package/dist/module/icons/VideoSlash.js +1 -1
- package/dist/module/icons/VideoSlash.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 +106 -0
- package/dist/module/modules/call-manager/CallManager.js.map +1 -0
- package/dist/module/modules/call-manager/PrevLibDetection.js +12 -0
- package/dist/module/modules/call-manager/PrevLibDetection.js.map +1 -0
- package/dist/module/modules/call-manager/index.js +4 -0
- package/dist/module/modules/call-manager/index.js.map +1 -0
- package/dist/module/modules/call-manager/native-module.d.js +2 -0
- package/dist/module/modules/call-manager/native-module.d.js.map +1 -0
- package/dist/module/modules/call-manager/types.js +2 -0
- package/dist/module/modules/call-manager/types.js.map +1 -0
- package/dist/module/providers/StreamCall/AppStateListener.js +6 -6
- package/dist/module/providers/StreamCall/AppStateListener.js.map +1 -1
- package/dist/module/theme/theme.js.map +1 -1
- package/dist/module/utils/internal/rxSubjects.js +1 -1
- package/dist/module/utils/internal/rxSubjects.js.map +1 -1
- package/dist/module/version.js +1 -1
- package/dist/module/version.js.map +1 -1
- package/dist/typescript/components/Call/CallContent/CallContent.d.ts +3 -2
- package/dist/typescript/components/Call/CallContent/CallContent.d.ts.map +1 -1
- package/dist/typescript/components/Call/CallContent/RTCViewPipIOS.d.ts +5 -0
- package/dist/typescript/components/Call/CallContent/RTCViewPipIOS.d.ts.map +1 -1
- package/dist/typescript/components/Call/CallContent/RTCViewPipNative.d.ts +6 -0
- package/dist/typescript/components/Call/CallContent/RTCViewPipNative.d.ts.map +1 -1
- package/dist/typescript/components/Livestream/HostLivestream/HostLivestream.d.ts.map +1 -1
- package/dist/typescript/components/Livestream/LivestreamControls/ViewerLivestreamControls.d.ts.map +1 -1
- package/dist/typescript/components/Livestream/LivestreamLayout/LivestreamLayout.d.ts.map +1 -1
- package/dist/typescript/components/Livestream/ViewerLivestream/ViewerLivestream.d.ts.map +1 -1
- package/dist/typescript/hooks/usePermissionNotification.d.ts.map +1 -1
- package/dist/typescript/icons/Back.d.ts +1 -1
- package/dist/typescript/icons/Back.d.ts.map +1 -1
- package/dist/typescript/icons/BadNetwork.d.ts +1 -1
- package/dist/typescript/icons/BadNetwork.d.ts.map +1 -1
- package/dist/typescript/icons/CameraSwitch.d.ts +1 -1
- package/dist/typescript/icons/CameraSwitch.d.ts.map +1 -1
- package/dist/typescript/icons/LivestreamControls.d.ts +1 -1
- package/dist/typescript/icons/LivestreamControls.d.ts.map +1 -1
- package/dist/typescript/icons/Lock.d.ts +1 -1
- package/dist/typescript/icons/Lock.d.ts.map +1 -1
- package/dist/typescript/icons/Maximize.d.ts +1 -1
- package/dist/typescript/icons/Maximize.d.ts.map +1 -1
- package/dist/typescript/icons/Mic.d.ts +1 -1
- package/dist/typescript/icons/Mic.d.ts.map +1 -1
- package/dist/typescript/icons/MicOff.d.ts +1 -1
- package/dist/typescript/icons/MicOff.d.ts.map +1 -1
- package/dist/typescript/icons/Phone.d.ts +1 -1
- package/dist/typescript/icons/Phone.d.ts.map +1 -1
- package/dist/typescript/icons/PhoneDown.d.ts +1 -1
- package/dist/typescript/icons/PhoneDown.d.ts.map +1 -1
- package/dist/typescript/icons/PinVertical.d.ts +1 -1
- package/dist/typescript/icons/PinVertical.d.ts.map +1 -1
- package/dist/typescript/icons/Reaction.d.ts +1 -1
- package/dist/typescript/icons/Reaction.d.ts.map +1 -1
- package/dist/typescript/icons/ScreenShare.d.ts +1 -1
- package/dist/typescript/icons/ScreenShare.d.ts.map +1 -1
- package/dist/typescript/icons/ScreenShareIndicator.d.ts +1 -1
- package/dist/typescript/icons/ScreenShareIndicator.d.ts.map +1 -1
- package/dist/typescript/icons/Spotlight.d.ts +1 -1
- package/dist/typescript/icons/Spotlight.d.ts.map +1 -1
- package/dist/typescript/icons/StopScreenShare.d.ts +1 -1
- package/dist/typescript/icons/StopScreenShare.d.ts.map +1 -1
- package/dist/typescript/icons/Video.d.ts +1 -1
- package/dist/typescript/icons/Video.d.ts.map +1 -1
- package/dist/typescript/icons/VideoSlash.d.ts +1 -1
- package/dist/typescript/icons/VideoSlash.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 +67 -0
- package/dist/typescript/modules/call-manager/CallManager.d.ts.map +1 -0
- package/dist/typescript/modules/call-manager/PrevLibDetection.d.ts +13 -0
- package/dist/typescript/modules/call-manager/PrevLibDetection.d.ts.map +1 -0
- package/dist/typescript/modules/call-manager/index.d.ts +4 -0
- package/dist/typescript/modules/call-manager/index.d.ts.map +1 -0
- package/dist/typescript/modules/call-manager/types.d.ts +15 -0
- package/dist/typescript/modules/call-manager/types.d.ts.map +1 -0
- package/dist/typescript/providers/StreamCall/AppStateListener.d.ts.map +1 -1
- package/dist/typescript/theme/theme.d.ts +1 -2
- package/dist/typescript/theme/theme.d.ts.map +1 -1
- package/dist/typescript/utils/internal/rxSubjects.d.ts +1 -1
- package/dist/typescript/utils/internal/rxSubjects.d.ts.map +1 -1
- package/dist/typescript/version.d.ts +1 -1
- package/dist/typescript/version.d.ts.map +1 -1
- package/ios/PictureInPicture/StreamPictureInPictureController.swift +5 -0
- package/ios/RTCViewPip.swift +15 -0
- package/ios/RTCViewPipManager.mm +1 -0
- package/ios/StreamInCallManager.m +26 -0
- package/ios/StreamInCallManager.swift +303 -0
- package/ios/StreamVideoReactNative-Bridging-Header.h +1 -0
- package/ios/StreamVideoReactNative.m +6 -5
- package/ios/StreamVideoReactNative.xcodeproj/project.xcworkspace/xcuserdata/santhoshvaiyapuri.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
- package/ios/StreamVideoReactNative.xcodeproj/xcuserdata/santhoshvaiyapuri.xcuserdatad/xcschemes/xcschememanagement.plist +14 -0
- package/package.json +33 -35
- package/src/components/Call/CallContent/CallContent.tsx +14 -10
- package/src/components/Call/CallContent/RTCViewPipIOS.tsx +17 -2
- package/src/components/Call/CallContent/RTCViewPipNative.tsx +8 -0
- package/src/components/Livestream/HostLivestream/HostLivestream.tsx +8 -3
- package/src/components/Livestream/LivestreamControls/ViewerLivestreamControls.tsx +11 -5
- package/src/components/Livestream/LivestreamLayout/LivestreamLayout.tsx +38 -29
- package/src/components/Livestream/ViewerLivestream/ViewerLivestream.tsx +8 -3
- package/src/hooks/useIsInPiPMode.tsx +4 -4
- package/src/hooks/usePermissionNotification.tsx +7 -12
- package/src/icons/Back.tsx +2 -2
- package/src/icons/BadNetwork.tsx +1 -1
- package/src/icons/CameraSwitch.tsx +2 -2
- package/src/icons/LivestreamControls.tsx +1 -1
- package/src/icons/Lock.tsx +1 -1
- package/src/icons/Maximize.tsx +1 -1
- package/src/icons/Mic.tsx +2 -2
- package/src/icons/MicOff.tsx +2 -2
- package/src/icons/Phone.tsx +2 -2
- package/src/icons/PhoneDown.tsx +1 -1
- package/src/icons/PinVertical.tsx +2 -2
- package/src/icons/Reaction.tsx +2 -2
- package/src/icons/ScreenShare.tsx +1 -1
- package/src/icons/ScreenShareIndicator.tsx +1 -1
- package/src/icons/Spotlight.tsx +2 -2
- package/src/icons/StopScreenShare.tsx +1 -1
- package/src/icons/Video.tsx +2 -2
- package/src/icons/VideoSlash.tsx +2 -2
- package/src/index.ts +1 -0
- package/src/modules/call-manager/CallManager.ts +116 -0
- package/src/modules/call-manager/PrevLibDetection.ts +27 -0
- package/src/modules/call-manager/index.ts +5 -0
- package/src/modules/call-manager/native-module.d.ts +80 -0
- package/src/modules/call-manager/types.ts +25 -0
- package/src/providers/StreamCall/AppStateListener.tsx +6 -9
- package/src/theme/theme.ts +2 -2
- package/src/utils/internal/rxSubjects.ts +1 -1
- package/src/version.ts +1 -1
- package/CHANGELOG.md +0 -2783
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
ViewerLeaveStreamButton as DefaultViewerLeaveStreamButton,
|
|
11
11
|
type ViewerLeaveStreamButtonProps,
|
|
12
12
|
} from './ViewerLeaveStreamButton';
|
|
13
|
+
import { callManager } from '../../../modules/call-manager';
|
|
13
14
|
import { useTheme } from '../../../contexts';
|
|
14
15
|
import { Z_INDEX } from '../../../constants';
|
|
15
16
|
import {
|
|
@@ -18,12 +19,11 @@ import {
|
|
|
18
19
|
LiveIndicator,
|
|
19
20
|
} from '../LivestreamTopView';
|
|
20
21
|
import { IconWrapper, Maximize } from '../../../icons';
|
|
21
|
-
import InCallManager from 'react-native-incall-manager';
|
|
22
22
|
import {
|
|
23
|
-
VolumeOff,
|
|
24
|
-
VolumeOn,
|
|
25
23
|
PauseIcon,
|
|
26
24
|
PlayIcon,
|
|
25
|
+
VolumeOff,
|
|
26
|
+
VolumeOn,
|
|
27
27
|
} from '../../../icons/LivestreamControls';
|
|
28
28
|
|
|
29
29
|
/**
|
|
@@ -104,10 +104,16 @@ export const ViewerLivestreamControls = ({
|
|
|
104
104
|
};
|
|
105
105
|
|
|
106
106
|
const toggleAudio = () => {
|
|
107
|
-
|
|
108
|
-
|
|
107
|
+
const shouldMute = !isMuted;
|
|
108
|
+
callManager.speaker.setMute(shouldMute);
|
|
109
|
+
setIsMuted(shouldMute);
|
|
109
110
|
};
|
|
110
111
|
|
|
112
|
+
useEffect(() => {
|
|
113
|
+
// always unmute audio output on mount for consistency
|
|
114
|
+
callManager.speaker.setMute(false);
|
|
115
|
+
}, []);
|
|
116
|
+
|
|
111
117
|
const togglePlayPause = () => {
|
|
112
118
|
setIsPlaying(!isPlaying);
|
|
113
119
|
showPlayPauseButtonWithTimeout();
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import React, { useCallback, useEffect, useState } from 'react';
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
hasScreenShare,
|
|
4
|
+
SfuModels,
|
|
5
|
+
StreamVideoParticipant,
|
|
6
|
+
} from '@stream-io/video-client';
|
|
3
7
|
import { useCall, useCallStateHooks } from '@stream-io/video-react-bindings';
|
|
4
8
|
import { StyleSheet, View, type ViewStyle } from 'react-native';
|
|
5
9
|
import { usePaginatedLayoutSortPreset } from '../../../hooks/usePaginatedLayoutSortPreset';
|
|
@@ -9,6 +13,7 @@ import {
|
|
|
9
13
|
type VideoRendererProps,
|
|
10
14
|
} from '../../Participant';
|
|
11
15
|
import type { ScreenShareOverlayProps } from '../../utility/ScreenShareOverlay';
|
|
16
|
+
import { useTrackDimensions } from '../../../hooks';
|
|
12
17
|
|
|
13
18
|
/**
|
|
14
19
|
* Props for the LivestreamLayout component.
|
|
@@ -56,11 +61,6 @@ export const LivestreamLayout = ({
|
|
|
56
61
|
React.ComponentProps<NonNullable<typeof VideoRenderer>>['objectFit']
|
|
57
62
|
>();
|
|
58
63
|
|
|
59
|
-
// no need to pass object fit for local participant as the dimensions are for remote tracks
|
|
60
|
-
const objectFitToBeSet = currentSpeaker?.isLocalParticipant
|
|
61
|
-
? undefined
|
|
62
|
-
: objectFit;
|
|
63
|
-
|
|
64
64
|
const onDimensionsChange = useCallback(
|
|
65
65
|
(d: SfuModels.VideoDimension | undefined) => {
|
|
66
66
|
if (d) {
|
|
@@ -84,48 +84,57 @@ export const LivestreamLayout = ({
|
|
|
84
84
|
livestreamLayout.container,
|
|
85
85
|
]}
|
|
86
86
|
>
|
|
87
|
-
<RemoteVideoTrackDimensionsRenderLessComponent
|
|
88
|
-
onDimensionsChange={onDimensionsChange}
|
|
89
|
-
/>
|
|
90
87
|
{VideoRenderer &&
|
|
91
88
|
hasOngoingScreenShare &&
|
|
92
89
|
presenter &&
|
|
93
90
|
(presenter.isLocalParticipant && ScreenShareOverlay ? (
|
|
94
91
|
<ScreenShareOverlay />
|
|
95
92
|
) : (
|
|
96
|
-
|
|
93
|
+
<>
|
|
94
|
+
<VideoRenderer
|
|
95
|
+
trackType="screenShareTrack"
|
|
96
|
+
objectFit={objectFit}
|
|
97
|
+
participant={presenter}
|
|
98
|
+
/>
|
|
99
|
+
<VideoTrackDimensionsRenderLessComponent
|
|
100
|
+
onDimensionsChange={onDimensionsChange}
|
|
101
|
+
participant={presenter}
|
|
102
|
+
trackType="screenShareTrack"
|
|
103
|
+
/>
|
|
104
|
+
</>
|
|
97
105
|
))}
|
|
98
106
|
{VideoRenderer && !hasOngoingScreenShare && currentSpeaker && (
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
107
|
+
<>
|
|
108
|
+
<VideoRenderer
|
|
109
|
+
participant={currentSpeaker}
|
|
110
|
+
objectFit={objectFit}
|
|
111
|
+
trackType="videoTrack"
|
|
112
|
+
/>
|
|
113
|
+
<VideoTrackDimensionsRenderLessComponent
|
|
114
|
+
onDimensionsChange={onDimensionsChange}
|
|
115
|
+
participant={currentSpeaker}
|
|
116
|
+
trackType="videoTrack"
|
|
117
|
+
/>
|
|
118
|
+
</>
|
|
104
119
|
)}
|
|
105
120
|
</View>
|
|
106
121
|
);
|
|
107
122
|
};
|
|
108
123
|
|
|
109
|
-
const
|
|
124
|
+
const VideoTrackDimensionsRenderLessComponent = ({
|
|
110
125
|
onDimensionsChange,
|
|
126
|
+
participant,
|
|
127
|
+
trackType,
|
|
111
128
|
}: {
|
|
112
129
|
onDimensionsChange: (d: SfuModels.VideoDimension | undefined) => void;
|
|
130
|
+
participant: StreamVideoParticipant;
|
|
131
|
+
trackType: 'videoTrack' | 'screenShareTrack';
|
|
113
132
|
}) => {
|
|
114
|
-
const
|
|
115
|
-
const { useCallStatsReport } = useCallStateHooks();
|
|
116
|
-
const statsReport = useCallStatsReport();
|
|
117
|
-
const highestFrameHeight = statsReport?.subscriberStats?.highestFrameHeight;
|
|
118
|
-
const highestFrameWidth = statsReport?.subscriberStats?.highestFrameWidth;
|
|
119
|
-
|
|
120
|
-
useEffect(() => {
|
|
121
|
-
if (highestFrameHeight && highestFrameWidth) {
|
|
122
|
-
setDimension({ height: highestFrameHeight, width: highestFrameWidth });
|
|
123
|
-
}
|
|
124
|
-
}, [highestFrameHeight, highestFrameWidth]);
|
|
133
|
+
const { width, height } = useTrackDimensions(participant, trackType);
|
|
125
134
|
|
|
126
135
|
useEffect(() => {
|
|
127
|
-
onDimensionsChange(
|
|
128
|
-
}, [
|
|
136
|
+
onDimensionsChange({ width, height });
|
|
137
|
+
}, [width, height, onDimensionsChange]);
|
|
129
138
|
|
|
130
139
|
return null;
|
|
131
140
|
};
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import React, { useEffect, useMemo, useState } from 'react';
|
|
2
2
|
import { StyleSheet, View } from 'react-native';
|
|
3
|
-
import InCallManager from 'react-native-incall-manager';
|
|
4
3
|
import { useTheme } from '../../../contexts';
|
|
5
4
|
import { type ViewerLivestreamTopViewProps } from '../LivestreamTopView/ViewerLivestreamTopView';
|
|
6
5
|
import {
|
|
@@ -20,6 +19,7 @@ import {
|
|
|
20
19
|
import { CallingState, hasVideo } from '@stream-io/video-client';
|
|
21
20
|
import { CallEndedView } from '../LivestreamPlayer/LivestreamEnded';
|
|
22
21
|
import { ViewerLobby } from './ViewerLobby';
|
|
22
|
+
import { getRNInCallManagerLibNoThrow } from '../../../modules/call-manager/PrevLibDetection';
|
|
23
23
|
|
|
24
24
|
/**
|
|
25
25
|
* Props for the ViewerLivestream component.
|
|
@@ -102,8 +102,13 @@ export const ViewerLivestream = ({
|
|
|
102
102
|
|
|
103
103
|
// Automatically route audio to speaker devices as relevant for watching videos.
|
|
104
104
|
useEffect(() => {
|
|
105
|
-
|
|
106
|
-
|
|
105
|
+
const prevInCallManager = getRNInCallManagerLibNoThrow();
|
|
106
|
+
if (prevInCallManager) {
|
|
107
|
+
prevInCallManager.start({ media: 'video' });
|
|
108
|
+
return () => {
|
|
109
|
+
prevInCallManager.stop();
|
|
110
|
+
};
|
|
111
|
+
}
|
|
107
112
|
}, []);
|
|
108
113
|
|
|
109
114
|
useEffect(() => {
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import { useEffect, useState } from 'react';
|
|
2
2
|
import { RxUtils } from '@stream-io/video-client';
|
|
3
|
-
import {
|
|
3
|
+
import { isInPiPMode$ } from '../utils/internal/rxSubjects';
|
|
4
4
|
|
|
5
5
|
export function useIsInPiPMode() {
|
|
6
6
|
const [value, setValue] = useState<boolean>(() => {
|
|
7
|
-
return RxUtils.getCurrentValue(
|
|
7
|
+
return RxUtils.getCurrentValue(isInPiPMode$);
|
|
8
8
|
});
|
|
9
9
|
|
|
10
10
|
useEffect(() => {
|
|
11
|
-
const subscription =
|
|
11
|
+
const subscription = isInPiPMode$.subscribe({
|
|
12
12
|
next: setValue,
|
|
13
13
|
error: (err) => {
|
|
14
|
-
console.log('An error occurred while reading
|
|
14
|
+
console.log('An error occurred while reading isInPiPMode$', err);
|
|
15
15
|
setValue(false);
|
|
16
16
|
},
|
|
17
17
|
});
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { CallingState, OwnCapability } from '@stream-io/video-client';
|
|
2
2
|
import { useCallStateHooks } from '@stream-io/video-react-bindings';
|
|
3
|
-
import {
|
|
3
|
+
import { useEffect } from 'react';
|
|
4
4
|
import { Alert } from 'react-native';
|
|
5
5
|
import { usePrevious } from '../utils/hooks/usePrevious';
|
|
6
|
+
import { useEffectEvent } from '@stream-io/video-react-bindings';
|
|
6
7
|
|
|
7
8
|
export type PermissionNotificationProps = {
|
|
8
9
|
/**
|
|
@@ -32,13 +33,13 @@ export const usePermissionNotification = (
|
|
|
32
33
|
const previousHasPermission = usePrevious(hasPermission);
|
|
33
34
|
const callingState = useCallCallingState();
|
|
34
35
|
|
|
35
|
-
const showGrantedNotification =
|
|
36
|
+
const showGrantedNotification = useEffectEvent(() => {
|
|
36
37
|
Alert.alert(messageApproved);
|
|
37
|
-
}
|
|
38
|
+
});
|
|
38
39
|
|
|
39
|
-
const showRevokedNotification =
|
|
40
|
+
const showRevokedNotification = useEffectEvent(() => {
|
|
40
41
|
Alert.alert(messageRevoked);
|
|
41
|
-
}
|
|
42
|
+
});
|
|
42
43
|
|
|
43
44
|
useEffect(() => {
|
|
44
45
|
// Permission state is not reliable before the call is joined,
|
|
@@ -51,11 +52,5 @@ export const usePermissionNotification = (
|
|
|
51
52
|
} else if (!hasPermission && previousHasPermission) {
|
|
52
53
|
showRevokedNotification();
|
|
53
54
|
}
|
|
54
|
-
}, [
|
|
55
|
-
callingState,
|
|
56
|
-
hasPermission,
|
|
57
|
-
previousHasPermission,
|
|
58
|
-
showGrantedNotification,
|
|
59
|
-
showRevokedNotification,
|
|
60
|
-
]);
|
|
55
|
+
}, [callingState, hasPermission, previousHasPermission]);
|
|
61
56
|
};
|
package/src/icons/Back.tsx
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import {
|
|
3
|
-
import { type ColorValue } from 'react-native
|
|
2
|
+
import { Path, Svg } from 'react-native-svg';
|
|
3
|
+
import { type ColorValue } from 'react-native';
|
|
4
4
|
|
|
5
5
|
type Props = {
|
|
6
6
|
color: ColorValue;
|
package/src/icons/BadNetwork.tsx
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import {
|
|
3
|
-
import { type ColorValue } from 'react-native
|
|
2
|
+
import { Path, Svg } from 'react-native-svg';
|
|
3
|
+
import { type ColorValue } from 'react-native';
|
|
4
4
|
|
|
5
5
|
type Props = {
|
|
6
6
|
color: ColorValue;
|
package/src/icons/Lock.tsx
CHANGED
package/src/icons/Maximize.tsx
CHANGED
package/src/icons/Mic.tsx
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import {
|
|
3
|
-
import { type ColorValue } from 'react-native
|
|
2
|
+
import { Path, Svg } from 'react-native-svg';
|
|
3
|
+
import { type ColorValue } from 'react-native';
|
|
4
4
|
|
|
5
5
|
type Props = {
|
|
6
6
|
color: ColorValue;
|
package/src/icons/MicOff.tsx
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import {
|
|
3
|
-
import { type ColorValue } from 'react-native
|
|
2
|
+
import { Path, Svg } from 'react-native-svg';
|
|
3
|
+
import { type ColorValue } from 'react-native';
|
|
4
4
|
|
|
5
5
|
type Props = {
|
|
6
6
|
color: ColorValue;
|
package/src/icons/Phone.tsx
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import {
|
|
3
|
-
import { type ColorValue } from 'react-native
|
|
2
|
+
import { Path, Svg } from 'react-native-svg';
|
|
3
|
+
import { type ColorValue } from 'react-native';
|
|
4
4
|
import { IconTestIds } from '../constants/TestIds';
|
|
5
5
|
|
|
6
6
|
type Props = {
|
package/src/icons/PhoneDown.tsx
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import {
|
|
3
|
-
import { type ColorValue } from 'react-native
|
|
2
|
+
import { Path, Svg } from 'react-native-svg';
|
|
3
|
+
import { type ColorValue } from 'react-native';
|
|
4
4
|
|
|
5
5
|
type Props = {
|
|
6
6
|
color: ColorValue;
|
package/src/icons/Reaction.tsx
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import {
|
|
3
|
-
import { type ColorValue } from 'react-native
|
|
2
|
+
import { Path, Svg } from 'react-native-svg';
|
|
3
|
+
import { type ColorValue } from 'react-native';
|
|
4
4
|
|
|
5
5
|
type Props = {
|
|
6
6
|
color: ColorValue;
|
package/src/icons/Spotlight.tsx
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import {
|
|
3
|
-
import { type ColorValue } from 'react-native
|
|
2
|
+
import { Path, Svg } from 'react-native-svg';
|
|
3
|
+
import { type ColorValue } from 'react-native';
|
|
4
4
|
|
|
5
5
|
type Props = {
|
|
6
6
|
color: ColorValue;
|
package/src/icons/Video.tsx
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import {
|
|
3
|
-
import { type ColorValue } from 'react-native
|
|
2
|
+
import { Path, Svg } from 'react-native-svg';
|
|
3
|
+
import { type ColorValue } from 'react-native';
|
|
4
4
|
|
|
5
5
|
type Props = {
|
|
6
6
|
color: ColorValue;
|
package/src/icons/VideoSlash.tsx
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import {
|
|
3
|
-
import { type ColorValue } from 'react-native
|
|
2
|
+
import { Path, Svg } from 'react-native-svg';
|
|
3
|
+
import { type ColorValue } from 'react-native';
|
|
4
4
|
import { IconTestIds } from '../constants/TestIds';
|
|
5
5
|
|
|
6
6
|
type Props = {
|
package/src/index.ts
CHANGED
|
@@ -27,6 +27,7 @@ export * from './hooks';
|
|
|
27
27
|
export * from './theme';
|
|
28
28
|
export * from './utils';
|
|
29
29
|
export * from './translations';
|
|
30
|
+
export * from './modules/call-manager';
|
|
30
31
|
|
|
31
32
|
// Overriding 'StreamVideo' and 'StreamCall' from '@stream-io/video-react-bindings'
|
|
32
33
|
// Explicitly re-exporting to resolve ambiguity.
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { NativeEventEmitter, NativeModules, Platform } from 'react-native';
|
|
2
|
+
import { AudioDeviceStatus, StreamInCallManagerConfig } from './types';
|
|
3
|
+
|
|
4
|
+
const NativeManager = NativeModules.StreamInCallManager;
|
|
5
|
+
|
|
6
|
+
const invariant = (condition: boolean, message: string) => {
|
|
7
|
+
if (!condition) throw new Error(message);
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
class AndroidCallManager {
|
|
11
|
+
private eventEmitter?: NativeEventEmitter;
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Get the current audio device status.
|
|
15
|
+
*/
|
|
16
|
+
getAudioDeviceStatus = async (): Promise<AudioDeviceStatus> => {
|
|
17
|
+
invariant(Platform.OS === 'android', 'Supported only on Android');
|
|
18
|
+
return NativeManager.getAudioDeviceStatus();
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Switches the audio device to the specified endpoint.
|
|
23
|
+
*
|
|
24
|
+
* @param endpointName the device name.
|
|
25
|
+
*/
|
|
26
|
+
selectAudioDevice = (endpointName: string): void => {
|
|
27
|
+
invariant(Platform.OS === 'android', 'Supported only on Android');
|
|
28
|
+
NativeManager.chooseAudioDeviceEndpoint(endpointName);
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Register a listener for audio device changes.
|
|
33
|
+
* @param onChange callback to be called when the audio device changes.
|
|
34
|
+
*/
|
|
35
|
+
addAudioDeviceChangeListener = (
|
|
36
|
+
onChange: (audioDeviceStatus: AudioDeviceStatus) => void,
|
|
37
|
+
): (() => void) => {
|
|
38
|
+
invariant(Platform.OS === 'android', 'Supported only on Android');
|
|
39
|
+
this.eventEmitter ??= new NativeEventEmitter(NativeManager);
|
|
40
|
+
const s = this.eventEmitter.addListener('onAudioDeviceChanged', onChange);
|
|
41
|
+
return () => s.remove();
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
class IOSCallManager {
|
|
46
|
+
/**
|
|
47
|
+
* Will trigger the iOS device selector.
|
|
48
|
+
*/
|
|
49
|
+
showDeviceSelector = (): void => {
|
|
50
|
+
invariant(Platform.OS === 'ios', 'Supported only on iOS');
|
|
51
|
+
NativeManager.showAudioRoutePicker();
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
class SpeakerManager {
|
|
56
|
+
/**
|
|
57
|
+
* Mutes or unmutes the speaker.
|
|
58
|
+
*/
|
|
59
|
+
setMute = (mute: boolean): void => {
|
|
60
|
+
if (mute) {
|
|
61
|
+
NativeManager.muteAudioOutput();
|
|
62
|
+
} else {
|
|
63
|
+
NativeManager.unmuteAudioOutput();
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Forces speakerphone on/off.
|
|
69
|
+
*/
|
|
70
|
+
setForceSpeakerphoneOn = (force: boolean): void => {
|
|
71
|
+
NativeManager.setForceSpeakerphoneOn(force);
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export class CallManager {
|
|
76
|
+
android = new AndroidCallManager();
|
|
77
|
+
ios = new IOSCallManager();
|
|
78
|
+
speaker = new SpeakerManager();
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Starts the in call manager.
|
|
82
|
+
*
|
|
83
|
+
* @param config.audioRole The audio role to set. It can be one of the following:
|
|
84
|
+
* - `'communicator'`: (Default) For use cases like video or voice calls.
|
|
85
|
+
* It prioritizes low latency and allows manual audio device switching.
|
|
86
|
+
* Audio routing is controlled by the SDK.
|
|
87
|
+
* - `'listener'`: For use cases like livestream viewing.
|
|
88
|
+
* It prioritizes high-quality stereo audio streaming.
|
|
89
|
+
* Audio routing is controlled by the OS, and manual switching is not supported.
|
|
90
|
+
*
|
|
91
|
+
* @param config.deviceEndpointType The default audio device endpoint type to set. It can be one of the following:
|
|
92
|
+
* - `'speaker'`: (Default) For normal video or voice calls.
|
|
93
|
+
* - `'earpiece'`: For voice-only mobile call type scenarios.
|
|
94
|
+
*/
|
|
95
|
+
start = (config?: StreamInCallManagerConfig): void => {
|
|
96
|
+
NativeManager.setAudioRole(config?.audioRole ?? 'communicator');
|
|
97
|
+
if (config?.audioRole === 'communicator') {
|
|
98
|
+
const type = config.deviceEndpointType ?? 'speaker';
|
|
99
|
+
NativeManager.setDefaultAudioDeviceEndpointType(type);
|
|
100
|
+
}
|
|
101
|
+
NativeManager.start();
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Stops the in call manager.
|
|
106
|
+
*/
|
|
107
|
+
stop = (): void => {
|
|
108
|
+
NativeManager.stop();
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* For debugging purposes, will emit a log event with the current audio state.
|
|
113
|
+
* in the native layer.
|
|
114
|
+
*/
|
|
115
|
+
logAudioState = (): void => NativeManager.logAudioState();
|
|
116
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { getLogger } from '@stream-io/video-client';
|
|
2
|
+
|
|
3
|
+
declare class RNInCallManagerLib {
|
|
4
|
+
start(setup?: {
|
|
5
|
+
auto?: boolean;
|
|
6
|
+
media?: 'video' | 'audio';
|
|
7
|
+
ringback?: string;
|
|
8
|
+
}): void;
|
|
9
|
+
|
|
10
|
+
stop(setup?: { busytone?: string }): void;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
let rnInCallManagerLib: RNInCallManagerLib | undefined;
|
|
14
|
+
|
|
15
|
+
try {
|
|
16
|
+
rnInCallManagerLib = require('react-native-incall-manager').default;
|
|
17
|
+
} catch {}
|
|
18
|
+
|
|
19
|
+
export function getRNInCallManagerLibNoThrow() {
|
|
20
|
+
if (rnInCallManagerLib) {
|
|
21
|
+
getLogger(['getRNInCallManagerLibNoThrow'])(
|
|
22
|
+
'debug',
|
|
23
|
+
'react-native-incall-manager library is not required to be installed from 1.22.0 version of the @stream-io/video-react-native-sdk. Please check the migration documentation at https://getstream.io/video/docs/react-native/migration-guides/1.22.0/ for more details.',
|
|
24
|
+
);
|
|
25
|
+
}
|
|
26
|
+
return rnInCallManagerLib;
|
|
27
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import 'react-native';
|
|
2
|
+
import type { NativeModule } from 'react-native';
|
|
3
|
+
import type { AudioDeviceStatus, AudioRole, DeviceEndpointType } from './types';
|
|
4
|
+
|
|
5
|
+
export interface CallManager extends NativeModule {
|
|
6
|
+
/**
|
|
7
|
+
* Sets the audio role for the call. This should be done before calling **start()**.
|
|
8
|
+
*
|
|
9
|
+
* @param role The audio role to set. It can be one of the following:
|
|
10
|
+
* - `'communicator'`: (Default) For use cases like video or voice calls.
|
|
11
|
+
* It prioritizes low latency and allows manual audio device switching.
|
|
12
|
+
* Audio routing is controlled by the SDK.
|
|
13
|
+
* - `'listener'`: For use cases like livestream viewing.
|
|
14
|
+
* It prioritizes high-quality stereo audio streaming.
|
|
15
|
+
* Audio routing is controlled by the OS and manual switching is not supported.
|
|
16
|
+
*/
|
|
17
|
+
setAudioRole: (role: AudioRole) => void;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Sets the default audio device endpoint type for the call. This should be done before calling **start()**.
|
|
21
|
+
* @param type The default audio device endpoint type to set. It can be one of the following:
|
|
22
|
+
* - `'speaker'`: (Default) For normal video or voice calls.
|
|
23
|
+
* - `'earpiece'`: For voice only mobile call type scenarios.
|
|
24
|
+
*/
|
|
25
|
+
setDefaultAudioDeviceEndpointType: (type: DeviceEndpointType) => void;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Choose an audio device endpoint.
|
|
29
|
+
* @param endpointName - The name of the audio device endpoint to choose.
|
|
30
|
+
*/
|
|
31
|
+
chooseAudioDeviceEndpoint: (endpoint: string) => void;
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Get the current audio device status.
|
|
35
|
+
* @returns The audio device status.
|
|
36
|
+
*/
|
|
37
|
+
getAudioDeviceStatus: () => Promise<AudioDeviceStatus>;
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Shows the iOS audio route picker.
|
|
41
|
+
*/
|
|
42
|
+
showAudioRoutePicker: () => void;
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Start the in call manager.
|
|
46
|
+
*/
|
|
47
|
+
start: () => void;
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Stop the in call manager.
|
|
51
|
+
*/
|
|
52
|
+
stop: () => void;
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Mutes the speaker
|
|
56
|
+
*/
|
|
57
|
+
muteAudioOutput: () => void;
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Unmutes the speaker
|
|
61
|
+
*/
|
|
62
|
+
unmuteAudioOutput: () => void;
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Forces speakerphone on/off.
|
|
66
|
+
*/
|
|
67
|
+
setForceSpeakerphoneOn: (boolean) => void;
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Log the current audio state natively.
|
|
71
|
+
* Meant for debugging purposes.
|
|
72
|
+
*/
|
|
73
|
+
logAudioState: () => void;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
declare module 'react-native' {
|
|
77
|
+
interface NativeModulesStatic {
|
|
78
|
+
StreamInCallManager: CallManager;
|
|
79
|
+
}
|
|
80
|
+
}
|