@stream-io/video-react-sdk 0.0.1-alpha.9 → 0.0.1-alpha.91
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 +22 -150
- package/README.md +1 -1
- package/dist/css/styles.css +273 -407
- package/dist/css/styles.css.map +1 -1
- package/dist/src/components/Button/CompositeButton.js +2 -4
- package/dist/src/components/Button/CompositeButton.js.map +1 -1
- package/dist/src/components/CallControls/AcceptCallButton.d.ts +7 -0
- package/dist/src/components/CallControls/AcceptCallButton.js +27 -0
- package/dist/src/components/CallControls/AcceptCallButton.js.map +1 -0
- package/dist/src/components/CallControls/CallControls.d.ts +1 -3
- package/dist/src/components/CallControls/CallControls.js +2 -5
- package/dist/src/components/CallControls/CallControls.js.map +1 -1
- package/dist/src/components/CallControls/CallStatsButton.d.ts +1 -5
- package/dist/src/components/CallControls/CallStatsButton.js +2 -4
- package/dist/src/components/CallControls/CallStatsButton.js.map +1 -1
- package/dist/src/components/CallControls/CancelCallButton.d.ts +2 -3
- package/dist/src/components/CallControls/CancelCallButton.js +4 -2
- package/dist/src/components/CallControls/CancelCallButton.js.map +1 -1
- package/dist/src/components/CallControls/ReactionsButton.js +1 -2
- package/dist/src/components/CallControls/ReactionsButton.js.map +1 -1
- package/dist/src/components/CallControls/RecordCallButton.d.ts +1 -3
- package/dist/src/components/CallControls/RecordCallButton.js +10 -6
- package/dist/src/components/CallControls/RecordCallButton.js.map +1 -1
- package/dist/src/components/CallControls/ScreenShareButton.d.ts +1 -3
- package/dist/src/components/CallControls/ScreenShareButton.js +7 -7
- package/dist/src/components/CallControls/ScreenShareButton.js.map +1 -1
- package/dist/src/components/CallControls/ToggleAudioButton.d.ts +1 -1
- package/dist/src/components/CallControls/ToggleAudioButton.js +17 -10
- package/dist/src/components/CallControls/ToggleAudioButton.js.map +1 -1
- package/dist/src/components/CallControls/ToggleVideoButton.d.ts +10 -0
- package/dist/src/components/CallControls/{ToggleCameraButton.js → ToggleVideoButton.js} +17 -11
- package/dist/src/components/CallControls/ToggleVideoButton.js.map +1 -0
- package/dist/src/components/CallControls/index.d.ts +2 -2
- package/dist/src/components/CallControls/index.js +2 -2
- package/dist/src/components/CallControls/index.js.map +1 -1
- package/dist/src/components/CallParticipantsList/BlockedUserListing.js +1 -2
- package/dist/src/components/CallParticipantsList/BlockedUserListing.js.map +1 -1
- package/dist/src/components/CallParticipantsList/CallParticipantListingItem.d.ts +2 -1
- package/dist/src/components/CallParticipantsList/CallParticipantListingItem.js +13 -5
- package/dist/src/components/CallParticipantsList/CallParticipantListingItem.js.map +1 -1
- package/dist/src/components/CallParticipantsList/CallParticipantsList.js +1 -2
- package/dist/src/components/CallParticipantsList/CallParticipantsList.js.map +1 -1
- package/dist/src/components/CallStats/CallStats.d.ts +6 -0
- package/dist/src/components/{StreamCall → CallStats}/CallStats.js +3 -3
- package/dist/src/components/CallStats/CallStats.js.map +1 -0
- package/dist/src/components/CallStats/CallStatsLatencyChart.js.map +1 -0
- package/dist/src/components/CallStats/index.d.ts +2 -0
- package/dist/src/components/CallStats/index.js +3 -0
- package/dist/src/components/CallStats/index.js.map +1 -0
- package/dist/src/components/Debug/DebugStatsView.d.ts +1 -1
- package/dist/src/components/Debug/DebugStatsView.js +32 -7
- package/dist/src/components/Debug/DebugStatsView.js.map +1 -1
- package/dist/src/components/DeviceSettings/DeviceSelectorAudio.js +5 -3
- package/dist/src/components/DeviceSettings/DeviceSelectorAudio.js.map +1 -1
- package/dist/src/components/DeviceSettings/DeviceSelectorVideo.js +3 -2
- package/dist/src/components/DeviceSettings/DeviceSelectorVideo.js.map +1 -1
- package/dist/src/components/Notification/SpeakingWhileMutedNotification.js +4 -2
- package/dist/src/components/Notification/SpeakingWhileMutedNotification.js.map +1 -1
- package/dist/src/components/PendingCallPanel/PendingCallControls.d.ts +2 -0
- package/dist/src/components/PendingCallPanel/PendingCallControls.js +13 -0
- package/dist/src/components/PendingCallPanel/PendingCallControls.js.map +1 -0
- package/dist/src/components/PendingCallPanel/PendingCallPanel.d.ts +2 -0
- package/dist/src/components/PendingCallPanel/PendingCallPanel.js +34 -0
- package/dist/src/components/PendingCallPanel/PendingCallPanel.js.map +1 -0
- package/dist/src/components/PendingCallPanel/index.d.ts +2 -0
- package/dist/src/components/PendingCallPanel/index.js +3 -0
- package/dist/src/components/PendingCallPanel/index.js.map +1 -0
- package/dist/src/components/Permissions/PermissionRequests.js +2 -8
- package/dist/src/components/Permissions/PermissionRequests.js.map +1 -1
- package/dist/src/components/StreamCall/CallParticipantsScreenView.js +3 -3
- package/dist/src/components/StreamCall/CallParticipantsScreenView.js.map +1 -1
- package/dist/src/components/StreamCall/CallParticipantsView.js +2 -3
- package/dist/src/components/StreamCall/CallParticipantsView.js.map +1 -1
- package/dist/src/components/StreamTheme/StreamTheme.d.ts +5 -0
- package/dist/src/components/StreamTheme/StreamTheme.js +18 -0
- package/dist/src/components/StreamTheme/StreamTheme.js.map +1 -0
- package/dist/src/components/StreamTheme/index.d.ts +1 -0
- package/dist/src/components/StreamTheme/index.js +2 -0
- package/dist/src/components/StreamTheme/index.js.map +1 -0
- package/dist/src/components/Video/VideoPreview.js +10 -5
- package/dist/src/components/Video/VideoPreview.js.map +1 -1
- package/dist/src/components/Video/index.d.ts +1 -1
- package/dist/src/components/Video/index.js +1 -1
- package/dist/src/components/Video/index.js.map +1 -1
- package/dist/src/components/index.d.ts +2 -2
- package/dist/src/components/index.js +2 -2
- package/dist/src/components/index.js.map +1 -1
- package/dist/src/core/components/CallLayout/PaginatedGridLayout.d.ts +3 -7
- package/dist/src/core/components/CallLayout/PaginatedGridLayout.js +13 -14
- package/dist/src/core/components/CallLayout/PaginatedGridLayout.js.map +1 -1
- package/dist/src/core/components/CallLayout/SpeakerLayout.d.ts +6 -1
- package/dist/src/core/components/CallLayout/SpeakerLayout.js +13 -7
- package/dist/src/core/components/CallLayout/SpeakerLayout.js.map +1 -1
- package/dist/src/core/components/ParticipantView/DefaultParticipantViewUI.d.ts +18 -0
- package/dist/src/core/components/ParticipantView/DefaultParticipantViewUI.js +36 -0
- package/dist/src/core/components/ParticipantView/DefaultParticipantViewUI.js.map +1 -0
- package/dist/src/core/components/ParticipantView/ParticipantView.d.ts +79 -0
- package/dist/src/core/components/ParticipantView/ParticipantView.js +33 -0
- package/dist/src/core/components/ParticipantView/ParticipantView.js.map +1 -0
- package/dist/src/core/components/ParticipantView/index.d.ts +2 -0
- package/dist/src/core/components/ParticipantView/index.js +3 -0
- package/dist/src/core/components/ParticipantView/index.js.map +1 -0
- package/dist/src/core/components/StreamCall/StreamCall.d.ts +73 -0
- package/dist/src/core/components/StreamCall/StreamCall.js +60 -0
- package/dist/src/core/components/StreamCall/StreamCall.js.map +1 -0
- package/dist/src/core/components/StreamCall/index.d.ts +1 -0
- package/dist/src/core/components/StreamCall/index.js +2 -0
- package/dist/src/core/components/StreamCall/index.js.map +1 -0
- package/dist/src/core/components/Video/BaseVideo.d.ts +3 -3
- package/dist/src/core/components/Video/BaseVideo.js +6 -12
- package/dist/src/core/components/Video/BaseVideo.js.map +1 -1
- package/dist/src/core/components/Video/DefaultVideoPlaceholder.d.ts +6 -0
- package/dist/src/core/components/Video/DefaultVideoPlaceholder.js +9 -0
- package/dist/src/core/components/Video/DefaultVideoPlaceholder.js.map +1 -0
- package/dist/src/core/components/Video/Video.d.ts +11 -6
- package/dist/src/core/components/Video/Video.js +31 -28
- package/dist/src/core/components/Video/Video.js.map +1 -1
- package/dist/src/core/components/index.d.ts +3 -2
- package/dist/src/core/components/index.js +2 -1
- package/dist/src/core/components/index.js.map +1 -1
- package/dist/src/core/contexts/MediaDevicesContext.d.ts +117 -19
- package/dist/src/core/contexts/MediaDevicesContext.js +52 -90
- package/dist/src/core/contexts/MediaDevicesContext.js.map +1 -1
- package/dist/src/core/hooks/index.d.ts +2 -0
- package/dist/src/core/hooks/index.js +2 -0
- package/dist/src/core/hooks/index.js.map +1 -1
- package/dist/src/core/hooks/useAudioPublisher.js +9 -3
- package/dist/src/core/hooks/useAudioPublisher.js.map +1 -1
- package/dist/src/core/hooks/useDevices.d.ts +80 -0
- package/dist/src/core/hooks/useDevices.js +113 -0
- package/dist/src/core/hooks/useDevices.js.map +1 -0
- package/dist/src/core/hooks/useTrackElementVisibility.d.ts +6 -0
- package/dist/src/core/hooks/useTrackElementVisibility.js +27 -0
- package/dist/src/core/hooks/useTrackElementVisibility.js.map +1 -0
- package/dist/src/core/hooks/useVideoPublisher.js +35 -6
- package/dist/src/core/hooks/useVideoPublisher.js.map +1 -1
- package/dist/src/hooks/index.d.ts +0 -1
- package/dist/src/hooks/index.js +0 -1
- package/dist/src/hooks/index.js.map +1 -1
- package/dist/src/utilities/applyElementToRef.d.ts +2 -0
- package/dist/src/utilities/applyElementToRef.js +8 -0
- package/dist/src/utilities/applyElementToRef.js.map +1 -0
- package/dist/src/utilities/chunk.d.ts +1 -0
- package/dist/src/utilities/chunk.js +5 -0
- package/dist/src/utilities/chunk.js.map +1 -0
- package/dist/src/utilities/index.d.ts +3 -0
- package/dist/src/utilities/index.js +4 -0
- package/dist/src/utilities/index.js.map +1 -0
- package/dist/src/utilities/isComponentType.d.ts +2 -0
- package/dist/src/utilities/isComponentType.js +7 -0
- package/dist/src/utilities/isComponentType.js.map +1 -0
- package/package.json +12 -10
- package/src/components/Button/CompositeButton.tsx +4 -13
- package/src/components/CallControls/AcceptCallButton.tsx +36 -0
- package/src/components/CallControls/CallControls.tsx +13 -19
- package/src/components/CallControls/CallStatsButton.tsx +6 -14
- package/src/components/CallControls/CancelCallButton.tsx +12 -4
- package/src/components/CallControls/ReactionsButton.tsx +1 -2
- package/src/components/CallControls/RecordCallButton.tsx +12 -7
- package/src/components/CallControls/ScreenShareButton.tsx +7 -8
- package/src/components/CallControls/ToggleAudioButton.tsx +23 -12
- package/src/components/CallControls/{ToggleCameraButton.tsx → ToggleVideoButton.tsx} +20 -13
- package/src/components/CallControls/index.ts +2 -2
- package/src/components/CallParticipantsList/BlockedUserListing.tsx +1 -2
- package/src/components/CallParticipantsList/CallParticipantListingItem.tsx +27 -3
- package/src/components/CallParticipantsList/CallParticipantsList.tsx +1 -1
- package/src/components/{StreamCall → CallStats}/CallStats.tsx +3 -3
- package/src/components/CallStats/index.ts +2 -0
- package/src/components/Debug/DebugStatsView.tsx +60 -7
- package/src/components/DeviceSettings/DeviceSelectorAudio.tsx +9 -4
- package/src/components/DeviceSettings/DeviceSelectorVideo.tsx +3 -3
- package/src/components/Notification/SpeakingWhileMutedNotification.tsx +9 -8
- package/src/components/PendingCallPanel/PendingCallControls.tsx +27 -0
- package/src/components/PendingCallPanel/PendingCallPanel.tsx +71 -0
- package/src/components/PendingCallPanel/index.ts +2 -0
- package/src/components/Permissions/PermissionRequests.tsx +2 -8
- package/src/components/StreamCall/CallParticipantsScreenView.tsx +3 -4
- package/src/components/StreamCall/CallParticipantsView.tsx +3 -4
- package/src/components/StreamTheme/StreamTheme.tsx +19 -0
- package/src/components/StreamTheme/index.ts +1 -0
- package/src/components/Video/VideoPreview.tsx +16 -6
- package/src/components/Video/index.ts +1 -1
- package/src/components/index.ts +2 -2
- package/src/core/components/CallLayout/PaginatedGridLayout.tsx +32 -36
- package/src/core/components/CallLayout/SpeakerLayout.tsx +48 -25
- package/src/core/components/ParticipantView/DefaultParticipantViewUI.tsx +160 -0
- package/src/core/components/ParticipantView/ParticipantView.tsx +156 -0
- package/src/core/components/ParticipantView/index.ts +2 -0
- package/src/core/components/StreamCall/StreamCall.tsx +157 -0
- package/src/core/components/StreamCall/index.ts +1 -0
- package/src/core/components/Video/BaseVideo.tsx +9 -24
- package/src/core/components/Video/DefaultVideoPlaceholder.tsx +36 -0
- package/src/core/components/Video/Video.tsx +62 -48
- package/src/core/components/index.ts +3 -2
- package/src/core/contexts/MediaDevicesContext.tsx +179 -136
- package/src/core/hooks/index.ts +2 -0
- package/src/core/hooks/useAudioPublisher.ts +9 -3
- package/src/core/hooks/useDevices.ts +161 -0
- package/src/core/hooks/useTrackElementVisibility.ts +44 -0
- package/src/core/hooks/useVideoPublisher.ts +36 -4
- package/src/hooks/index.ts +0 -1
- package/src/utilities/applyElementToRef.ts +12 -0
- package/src/utilities/chunk.ts +8 -0
- package/src/utilities/index.ts +3 -0
- package/src/utilities/isComponentType.ts +9 -0
- package/dist/src/components/CallControls/ToggleCameraButton.d.ts +0 -10
- package/dist/src/components/CallControls/ToggleCameraButton.js.map +0 -1
- package/dist/src/components/CallControls/ToggleParticipantListButton.d.ts +0 -6
- package/dist/src/components/CallControls/ToggleParticipantListButton.js +0 -7
- package/dist/src/components/CallControls/ToggleParticipantListButton.js.map +0 -1
- package/dist/src/components/Moderation/Restricted.d.ts +0 -19
- package/dist/src/components/Moderation/Restricted.js +0 -13
- package/dist/src/components/Moderation/Restricted.js.map +0 -1
- package/dist/src/components/Moderation/index.d.ts +0 -1
- package/dist/src/components/Moderation/index.js +0 -2
- package/dist/src/components/Moderation/index.js.map +0 -1
- package/dist/src/components/StreamCall/CallStats.d.ts +0 -2
- package/dist/src/components/StreamCall/CallStats.js.map +0 -1
- package/dist/src/components/StreamCall/CallStatsLatencyChart.js.map +0 -1
- package/dist/src/components/StreamMeeting/StreamMeeting.d.ts +0 -34
- package/dist/src/components/StreamMeeting/StreamMeeting.js +0 -26
- package/dist/src/components/StreamMeeting/StreamMeeting.js.map +0 -1
- package/dist/src/components/StreamMeeting/index.d.ts +0 -1
- package/dist/src/components/StreamMeeting/index.js +0 -2
- package/dist/src/components/StreamMeeting/index.js.map +0 -1
- package/dist/src/core/components/ParticipantBox/ParticipantBox.d.ts +0 -48
- package/dist/src/core/components/ParticipantBox/ParticipantBox.js +0 -58
- package/dist/src/core/components/ParticipantBox/ParticipantBox.js.map +0 -1
- package/dist/src/core/components/ParticipantBox/index.d.ts +0 -1
- package/dist/src/core/components/ParticipantBox/index.js +0 -2
- package/dist/src/core/components/ParticipantBox/index.js.map +0 -1
- package/dist/src/core/components/Video/VideoPlaceholder.d.ts +0 -6
- package/dist/src/core/components/Video/VideoPlaceholder.js +0 -12
- package/dist/src/core/components/Video/VideoPlaceholder.js.map +0 -1
- package/dist/src/hooks/useRtcStats.d.ts +0 -11
- package/dist/src/hooks/useRtcStats.js +0 -39
- package/dist/src/hooks/useRtcStats.js.map +0 -1
- package/src/components/CallControls/ToggleParticipantListButton.tsx +0 -17
- package/src/components/Moderation/Restricted.tsx +0 -38
- package/src/components/Moderation/index.ts +0 -1
- package/src/components/StreamMeeting/StreamMeeting.tsx +0 -80
- package/src/components/StreamMeeting/index.ts +0 -1
- package/src/core/components/ParticipantBox/ParticipantBox.tsx +0 -248
- package/src/core/components/ParticipantBox/index.ts +0 -1
- package/src/core/components/Video/VideoPlaceholder.tsx +0 -40
- package/src/hooks/useRtcStats.ts +0 -36
- /package/dist/src/components/{StreamCall → CallStats}/CallStatsLatencyChart.d.ts +0 -0
- /package/dist/src/components/{StreamCall → CallStats}/CallStatsLatencyChart.js +0 -0
- /package/src/components/{StreamCall → CallStats}/CallStatsLatencyChart.tsx +0 -0
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { useCallback, useEffect, useState } from 'react';
|
|
2
2
|
import {
|
|
3
|
+
Restricted,
|
|
3
4
|
useCall,
|
|
4
5
|
useHasPermissions,
|
|
5
6
|
useLocalParticipant,
|
|
@@ -7,17 +8,16 @@ import {
|
|
|
7
8
|
|
|
8
9
|
import { OwnCapability, SfuModels } from '@stream-io/video-client';
|
|
9
10
|
import { CompositeButton, IconButton } from '../Button/';
|
|
10
|
-
import { useMediaDevices } from '../../core
|
|
11
|
+
import { DEVICE_STATE, useMediaDevices } from '../../core';
|
|
11
12
|
import { DeviceSelectorVideo } from '../DeviceSettings';
|
|
12
13
|
import { PermissionNotification } from '../Notification';
|
|
13
|
-
import { Restricted } from '../Moderation';
|
|
14
14
|
|
|
15
|
-
export type
|
|
15
|
+
export type ToggleVideoPreviewButtonProps = { caption?: string };
|
|
16
16
|
|
|
17
|
-
export const
|
|
17
|
+
export const ToggleVideoPreviewButton = ({
|
|
18
18
|
caption = 'Video',
|
|
19
|
-
}:
|
|
20
|
-
const {
|
|
19
|
+
}: ToggleVideoPreviewButtonProps) => {
|
|
20
|
+
const { toggleInitialVideoMuteState, initialVideoState } = useMediaDevices();
|
|
21
21
|
|
|
22
22
|
return (
|
|
23
23
|
<CompositeButton
|
|
@@ -27,20 +27,21 @@ export const ToggleCameraPreviewButton = ({
|
|
|
27
27
|
>
|
|
28
28
|
<IconButton
|
|
29
29
|
icon={initialVideoState.enabled ? 'camera' : 'camera-off'}
|
|
30
|
-
onClick={
|
|
30
|
+
onClick={toggleInitialVideoMuteState}
|
|
31
31
|
/>
|
|
32
32
|
</CompositeButton>
|
|
33
33
|
);
|
|
34
34
|
};
|
|
35
35
|
|
|
36
|
-
type
|
|
36
|
+
type ToggleVideoPublishingButtonProps = {
|
|
37
37
|
caption?: string;
|
|
38
38
|
};
|
|
39
39
|
|
|
40
|
-
export const
|
|
40
|
+
export const ToggleVideoPublishingButton = ({
|
|
41
41
|
caption = 'Video',
|
|
42
|
-
}:
|
|
43
|
-
const { publishVideoStream, stopPublishingVideo } =
|
|
42
|
+
}: ToggleVideoPublishingButtonProps) => {
|
|
43
|
+
const { publishVideoStream, stopPublishingVideo, setInitialVideoState } =
|
|
44
|
+
useMediaDevices();
|
|
44
45
|
const localParticipant = useLocalParticipant();
|
|
45
46
|
const isVideoMute = !localParticipant?.publishedTracks.includes(
|
|
46
47
|
SfuModels.TrackType.VIDEO,
|
|
@@ -71,8 +72,13 @@ export const ToggleCameraPublishingButton = ({
|
|
|
71
72
|
});
|
|
72
73
|
return;
|
|
73
74
|
}
|
|
74
|
-
if (isVideoMute
|
|
75
|
-
|
|
75
|
+
if (isVideoMute) {
|
|
76
|
+
if (hasPermission) {
|
|
77
|
+
setInitialVideoState(DEVICE_STATE.playing);
|
|
78
|
+
await publishVideoStream();
|
|
79
|
+
} else {
|
|
80
|
+
console.log('Cannot publish video. Insufficient permissions.');
|
|
81
|
+
}
|
|
76
82
|
} else {
|
|
77
83
|
stopPublishingVideo();
|
|
78
84
|
}
|
|
@@ -81,6 +87,7 @@ export const ToggleCameraPublishingButton = ({
|
|
|
81
87
|
hasPermission,
|
|
82
88
|
isVideoMute,
|
|
83
89
|
publishVideoStream,
|
|
90
|
+
setInitialVideoState,
|
|
84
91
|
stopPublishingVideo,
|
|
85
92
|
]);
|
|
86
93
|
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
export * from './AcceptCallButton';
|
|
1
2
|
export * from './CallControls';
|
|
2
3
|
export * from './CallStatsButton';
|
|
3
4
|
export * from './CancelCallButton';
|
|
@@ -5,6 +6,5 @@ export * from './ReactionsButton';
|
|
|
5
6
|
export * from './RecordCallButton';
|
|
6
7
|
export * from './ScreenShareButton';
|
|
7
8
|
export * from './ToggleAudioButton';
|
|
8
|
-
export * from './ToggleCameraButton';
|
|
9
9
|
export * from './ToggleAudioOutputButton';
|
|
10
|
-
export * from './
|
|
10
|
+
export * from './ToggleVideoButton';
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import { useCall } from '@stream-io/video-react-bindings';
|
|
1
|
+
import { Restricted, useCall } from '@stream-io/video-react-bindings';
|
|
2
2
|
import { OwnCapability } from '@stream-io/video-client';
|
|
3
3
|
|
|
4
|
-
import { Restricted } from '../Moderation';
|
|
5
4
|
import { TextButton } from '../Button';
|
|
6
5
|
|
|
7
6
|
export const BlockedUserListing = ({ data }: { data: string[] }) => {
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import clsx from 'clsx';
|
|
2
|
-
import { ComponentProps, ComponentType, forwardRef } from 'react';
|
|
3
|
-
import {
|
|
2
|
+
import { ComponentProps, ComponentType, forwardRef, useState } from 'react';
|
|
3
|
+
import {
|
|
4
|
+
Restricted,
|
|
5
|
+
useCall,
|
|
6
|
+
useConnectedUser,
|
|
7
|
+
} from '@stream-io/video-react-bindings';
|
|
4
8
|
import {
|
|
5
9
|
OwnCapability,
|
|
6
10
|
SfuModels,
|
|
@@ -13,7 +17,6 @@ import {
|
|
|
13
17
|
MenuToggle,
|
|
14
18
|
ToggleMenuButtonProps,
|
|
15
19
|
} from '../Menu';
|
|
16
|
-
import { Restricted } from '../Moderation';
|
|
17
20
|
import { WithTooltip } from '../Tooltip';
|
|
18
21
|
import { Icon } from '../Icon';
|
|
19
22
|
|
|
@@ -116,9 +119,14 @@ const ToggleButton = forwardRef<HTMLButtonElement, ToggleMenuButtonProps>(
|
|
|
116
119
|
|
|
117
120
|
export const ParticipantActionsContextMenu = ({
|
|
118
121
|
participant,
|
|
122
|
+
participantViewElement,
|
|
119
123
|
}: {
|
|
120
124
|
participant: StreamVideoParticipant;
|
|
125
|
+
participantViewElement?: HTMLDivElement | null;
|
|
121
126
|
}) => {
|
|
127
|
+
const [fullscreenModeOn, setFullscreenModeOn] = useState(
|
|
128
|
+
!!document.fullscreenElement,
|
|
129
|
+
);
|
|
122
130
|
const activeCall = useCall();
|
|
123
131
|
|
|
124
132
|
const blockUser = () => {
|
|
@@ -165,6 +173,19 @@ export const ParticipantActionsContextMenu = ({
|
|
|
165
173
|
);
|
|
166
174
|
};
|
|
167
175
|
|
|
176
|
+
const toggleFullscreenMode = () => {
|
|
177
|
+
if (!fullscreenModeOn)
|
|
178
|
+
return participantViewElement
|
|
179
|
+
?.requestFullscreen()
|
|
180
|
+
.then(() => setFullscreenModeOn(true))
|
|
181
|
+
.catch(console.error);
|
|
182
|
+
|
|
183
|
+
document
|
|
184
|
+
.exitFullscreen()
|
|
185
|
+
.catch(console.error)
|
|
186
|
+
.finally(() => setFullscreenModeOn(false));
|
|
187
|
+
};
|
|
188
|
+
|
|
168
189
|
return (
|
|
169
190
|
<GenericMenu>
|
|
170
191
|
<GenericMenuButtonItem onClick={toggleParticipantPinnedAt}>
|
|
@@ -211,6 +232,9 @@ export const ParticipantActionsContextMenu = ({
|
|
|
211
232
|
Mute audio
|
|
212
233
|
</GenericMenuButtonItem>
|
|
213
234
|
</Restricted>
|
|
235
|
+
<GenericMenuButtonItem onClick={toggleFullscreenMode}>
|
|
236
|
+
{fullscreenModeOn ? 'Leave' : 'Enter'} fullscreen
|
|
237
|
+
</GenericMenuButtonItem>
|
|
214
238
|
<Restricted requiredGrants={[OwnCapability.UPDATE_CALL_PERMISSIONS]}>
|
|
215
239
|
<GenericMenuButtonItem
|
|
216
240
|
onClick={grantPermission(OwnCapability.SEND_AUDIO)}
|
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
ComponentProps,
|
|
7
7
|
} from 'react';
|
|
8
8
|
import {
|
|
9
|
+
Restricted,
|
|
9
10
|
useCall,
|
|
10
11
|
useCallMetadata,
|
|
11
12
|
useOwnCapabilities,
|
|
@@ -30,7 +31,6 @@ import { EmptyParticipantSearchList } from './EmptyParticipantSearchList';
|
|
|
30
31
|
import { LoadingIndicator } from '../LoadingIndicator';
|
|
31
32
|
import { SearchInput, SearchResults } from '../Search';
|
|
32
33
|
import { useSearch, UseSearchParams } from '../Search/hooks';
|
|
33
|
-
import { Restricted } from '../Moderation';
|
|
34
34
|
import {
|
|
35
35
|
GenericMenu,
|
|
36
36
|
GenericMenuButtonItem,
|
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
AggregatedStatsReport,
|
|
4
4
|
CallStatsReport,
|
|
5
5
|
} from '@stream-io/video-client';
|
|
6
|
-
import {
|
|
6
|
+
import { useCallStatsReport } from '@stream-io/video-react-bindings';
|
|
7
7
|
import { CallStatsLatencyChart } from './CallStatsLatencyChart';
|
|
8
8
|
|
|
9
9
|
export const CallStats = () => {
|
|
@@ -17,7 +17,7 @@ export const CallStats = () => {
|
|
|
17
17
|
const [publishBitrate, setPublishBitrate] = useState('-');
|
|
18
18
|
const [subscribeBitrate, setSubscribeBitrate] = useState('-');
|
|
19
19
|
const previousStats = useRef<CallStatsReport>();
|
|
20
|
-
const callStatsReport =
|
|
20
|
+
const callStatsReport = useCallStatsReport();
|
|
21
21
|
|
|
22
22
|
useEffect(() => {
|
|
23
23
|
if (!callStatsReport) return;
|
|
@@ -95,7 +95,7 @@ export const CallStats = () => {
|
|
|
95
95
|
);
|
|
96
96
|
};
|
|
97
97
|
|
|
98
|
-
const StatCard = (props: { label: string; value: string }) => {
|
|
98
|
+
export const StatCard = (props: { label: string; value: string }) => {
|
|
99
99
|
const { label, value } = props;
|
|
100
100
|
return (
|
|
101
101
|
<div className="str-video__call-stats__card">
|
|
@@ -1,15 +1,26 @@
|
|
|
1
|
-
import { useState } from 'react';
|
|
1
|
+
import { useEffect, useState } from 'react';
|
|
2
2
|
import { Call } from '@stream-io/video-client';
|
|
3
|
-
import { useRtcStats } from '../../hooks/useRtcStats';
|
|
4
3
|
import { useFloatingUIPreset } from '../../hooks';
|
|
4
|
+
import { StatCard } from '../CallStats';
|
|
5
|
+
import { useCallStatsReport } from '@stream-io/video-react-bindings';
|
|
5
6
|
|
|
6
7
|
export const DebugStatsView = (props: {
|
|
7
8
|
call: Call;
|
|
8
|
-
kind: 'subscriber' | 'publisher';
|
|
9
9
|
mediaStream?: MediaStream;
|
|
10
|
+
sessionId: string;
|
|
10
11
|
}) => {
|
|
11
|
-
const { call,
|
|
12
|
-
const
|
|
12
|
+
const { call, mediaStream, sessionId } = props;
|
|
13
|
+
const callStatsReport = useCallStatsReport();
|
|
14
|
+
|
|
15
|
+
useEffect(() => {
|
|
16
|
+
call.startReportingStatsFor(sessionId);
|
|
17
|
+
return () => {
|
|
18
|
+
call.stopReportingStatsFor(sessionId);
|
|
19
|
+
};
|
|
20
|
+
}, [call, sessionId]);
|
|
21
|
+
|
|
22
|
+
const reportForTracks = callStatsReport?.participants[sessionId];
|
|
23
|
+
const trackStats = reportForTracks?.flatMap((report) => report.streams);
|
|
13
24
|
|
|
14
25
|
const { refs, strategy, y, x } = useFloatingUIPreset({
|
|
15
26
|
placement: 'top',
|
|
@@ -38,7 +49,7 @@ export const DebugStatsView = (props: {
|
|
|
38
49
|
/>
|
|
39
50
|
{isPopperOpen && (
|
|
40
51
|
<div
|
|
41
|
-
className="str-video__debug__track-stats"
|
|
52
|
+
className="str-video__debug__track-stats str-video__call-stats"
|
|
42
53
|
ref={refs.setFloating}
|
|
43
54
|
style={{
|
|
44
55
|
position: strategy,
|
|
@@ -47,9 +58,51 @@ export const DebugStatsView = (props: {
|
|
|
47
58
|
overflowY: 'auto',
|
|
48
59
|
}}
|
|
49
60
|
>
|
|
50
|
-
<
|
|
61
|
+
<h3>Participant stats</h3>
|
|
62
|
+
<div className="str-video__call-stats__card-container">
|
|
63
|
+
{trackStats
|
|
64
|
+
?.map((track) => {
|
|
65
|
+
if (track.kind === 'video') {
|
|
66
|
+
return (
|
|
67
|
+
<StatCard
|
|
68
|
+
key={`${track.rid}/${track.ssrc}/${track.codec}/${track.kind}`}
|
|
69
|
+
label={
|
|
70
|
+
`${track.kind}: ${track.codec} ` +
|
|
71
|
+
(track.rid ? ` (${track.rid})` : '')
|
|
72
|
+
}
|
|
73
|
+
value={`${track.frameWidth || 0}x${
|
|
74
|
+
track.frameHeight || 0
|
|
75
|
+
}@${track.framesPerSecond || 0}fps`}
|
|
76
|
+
/>
|
|
77
|
+
);
|
|
78
|
+
} else if (track.kind === 'audio') {
|
|
79
|
+
return (
|
|
80
|
+
<StatCard
|
|
81
|
+
key={`${track.ssrc}/${track.codec}/${track.kind}`}
|
|
82
|
+
label={track.codec || 'N/A'}
|
|
83
|
+
value={`Jitter: ${track.jitter || 0}ms`}
|
|
84
|
+
/>
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
return null;
|
|
88
|
+
})
|
|
89
|
+
.filter(Boolean)}
|
|
90
|
+
</div>
|
|
91
|
+
{reportForTracks?.map((report, index) => (
|
|
92
|
+
<pre key={index}>
|
|
93
|
+
{JSON.stringify(unwrapStats(report.rawStats), null, 2)}
|
|
94
|
+
</pre>
|
|
95
|
+
))}
|
|
51
96
|
</div>
|
|
52
97
|
)}
|
|
53
98
|
</>
|
|
54
99
|
);
|
|
55
100
|
};
|
|
101
|
+
|
|
102
|
+
const unwrapStats = (rawStats?: RTCStatsReport) => {
|
|
103
|
+
const decodedStats: Record<string, string> = {};
|
|
104
|
+
rawStats?.forEach((s) => {
|
|
105
|
+
decodedStats[s.id] = s;
|
|
106
|
+
});
|
|
107
|
+
return decodedStats;
|
|
108
|
+
};
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import { DeviceSelector } from './DeviceSelector';
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
useMediaDevices,
|
|
4
|
+
useAudioInputDevices,
|
|
5
|
+
useAudioOutputDevices,
|
|
6
|
+
} from '../../core';
|
|
3
7
|
|
|
4
8
|
export type DeviceSelectorAudioInputProps = {
|
|
5
9
|
title?: string;
|
|
@@ -8,8 +12,8 @@ export type DeviceSelectorAudioInputProps = {
|
|
|
8
12
|
export const DeviceSelectorAudioInput = ({
|
|
9
13
|
title = 'Select a Mic',
|
|
10
14
|
}: DeviceSelectorAudioInputProps) => {
|
|
11
|
-
const {
|
|
12
|
-
|
|
15
|
+
const { selectedAudioInputDeviceId, switchDevice } = useMediaDevices();
|
|
16
|
+
const audioInputDevices = useAudioInputDevices();
|
|
13
17
|
|
|
14
18
|
return (
|
|
15
19
|
<DeviceSelector
|
|
@@ -31,12 +35,13 @@ export const DeviceSelectorAudioOutput = ({
|
|
|
31
35
|
title = 'Select speakers',
|
|
32
36
|
}: DeviceSelectorAudioOutputProps) => {
|
|
33
37
|
const {
|
|
34
|
-
audioOutputDevices,
|
|
35
38
|
isAudioOutputChangeSupported,
|
|
36
39
|
selectedAudioOutputDeviceId,
|
|
37
40
|
switchDevice,
|
|
38
41
|
} = useMediaDevices();
|
|
39
42
|
|
|
43
|
+
const audioOutputDevices = useAudioOutputDevices();
|
|
44
|
+
|
|
40
45
|
if (!isAudioOutputChangeSupported) return null;
|
|
41
46
|
|
|
42
47
|
return (
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { DeviceSelector } from './DeviceSelector';
|
|
2
|
-
import { useMediaDevices } from '../../core
|
|
2
|
+
import { useMediaDevices, useVideoDevices } from '../../core';
|
|
3
3
|
|
|
4
4
|
export type DeviceSelectorVideoProps = {
|
|
5
5
|
title?: string;
|
|
6
6
|
};
|
|
7
7
|
|
|
8
8
|
export const DeviceSelectorVideo = ({ title }: DeviceSelectorVideoProps) => {
|
|
9
|
-
const {
|
|
10
|
-
|
|
9
|
+
const { selectedVideoDeviceId, switchDevice } = useMediaDevices();
|
|
10
|
+
const videoDevices = useVideoDevices();
|
|
11
11
|
|
|
12
12
|
return (
|
|
13
13
|
<DeviceSelector
|
|
@@ -2,7 +2,7 @@ import { useEffect, useState } from 'react';
|
|
|
2
2
|
import { createSoundDetector, SfuModels } from '@stream-io/video-client';
|
|
3
3
|
import { useLocalParticipant } from '@stream-io/video-react-bindings';
|
|
4
4
|
|
|
5
|
-
import { useMediaDevices } from '../../core
|
|
5
|
+
import { useMediaDevices } from '../../core';
|
|
6
6
|
import { Notification } from './Notification';
|
|
7
7
|
import { ChildrenOnly } from '../../types';
|
|
8
8
|
|
|
@@ -18,13 +18,14 @@ export const SpeakingWhileMutedNotification = ({ children }: ChildrenOnly) => {
|
|
|
18
18
|
useEffect(() => {
|
|
19
19
|
// do nothing when not muted
|
|
20
20
|
if (!isAudioMute) return;
|
|
21
|
-
const disposeSoundDetector = getAudioStream(
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
21
|
+
const disposeSoundDetector = getAudioStream({
|
|
22
|
+
deviceId: audioDeviceId,
|
|
23
|
+
}).then((audioStream) =>
|
|
24
|
+
createSoundDetector(audioStream, (isSpeechDetected) => {
|
|
25
|
+
setIsSpeakingWhileMuted((isNotified) =>
|
|
26
|
+
isNotified ? isNotified : isSpeechDetected,
|
|
27
|
+
);
|
|
28
|
+
}),
|
|
28
29
|
);
|
|
29
30
|
disposeSoundDetector.catch((err) => {
|
|
30
31
|
console.error('Error while creating sound detector', err);
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { CallingState } from '@stream-io/video-client';
|
|
2
|
+
import { AcceptCallButton, CancelCallButton } from '../CallControls';
|
|
3
|
+
import { useCall, useCallCallingState } from '@stream-io/video-react-bindings';
|
|
4
|
+
|
|
5
|
+
export const PendingCallControls = () => {
|
|
6
|
+
const call = useCall();
|
|
7
|
+
const callCallingState = useCallCallingState();
|
|
8
|
+
|
|
9
|
+
if (!call) return null;
|
|
10
|
+
|
|
11
|
+
const buttonsDisabled = callCallingState !== CallingState.RINGING;
|
|
12
|
+
return (
|
|
13
|
+
<div className="str-video__pending-call-controls">
|
|
14
|
+
{call.isCreatedByMe ? (
|
|
15
|
+
<CancelCallButton disabled={buttonsDisabled} />
|
|
16
|
+
) : (
|
|
17
|
+
<>
|
|
18
|
+
<AcceptCallButton disabled={buttonsDisabled} />
|
|
19
|
+
<CancelCallButton
|
|
20
|
+
onClick={() => call.leave({ reject: true })}
|
|
21
|
+
disabled={buttonsDisabled}
|
|
22
|
+
/>
|
|
23
|
+
</>
|
|
24
|
+
)}
|
|
25
|
+
</div>
|
|
26
|
+
);
|
|
27
|
+
};
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { CallingState } from '@stream-io/video-client';
|
|
2
|
+
import {
|
|
3
|
+
useCall,
|
|
4
|
+
useCallCallingState,
|
|
5
|
+
useCallMembers,
|
|
6
|
+
useCallMetadata,
|
|
7
|
+
useI18n,
|
|
8
|
+
} from '@stream-io/video-react-bindings';
|
|
9
|
+
import { Avatar } from '../Avatar';
|
|
10
|
+
import { PendingCallControls } from './PendingCallControls';
|
|
11
|
+
|
|
12
|
+
const CALLING_STATE_TO_LABEL: Record<CallingState, string> = {
|
|
13
|
+
[CallingState.JOINING]: 'Joining',
|
|
14
|
+
[CallingState.RINGING]: 'Ringing',
|
|
15
|
+
[CallingState.RECONNECTING]: 'Re-connecting',
|
|
16
|
+
[CallingState.RECONNECTING_FAILED]: 'Failed',
|
|
17
|
+
[CallingState.OFFLINE]: 'No internet connection',
|
|
18
|
+
[CallingState.IDLE]: '',
|
|
19
|
+
[CallingState.UNKNOWN]: '',
|
|
20
|
+
[CallingState.JOINED]: 'Joined',
|
|
21
|
+
[CallingState.LEFT]: 'Left call',
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export const PendingCallPanel = () => {
|
|
25
|
+
const call = useCall();
|
|
26
|
+
const callingState = useCallCallingState();
|
|
27
|
+
const { t } = useI18n();
|
|
28
|
+
const metadata = useCallMetadata();
|
|
29
|
+
const members = useCallMembers();
|
|
30
|
+
|
|
31
|
+
if (!call) return null;
|
|
32
|
+
|
|
33
|
+
const caller = metadata?.created_by;
|
|
34
|
+
const membersToShow = call.isCreatedByMe
|
|
35
|
+
? members
|
|
36
|
+
?.slice(0, 3)
|
|
37
|
+
.map(({ user }) => user)
|
|
38
|
+
.filter((u) => !!u) || []
|
|
39
|
+
: caller
|
|
40
|
+
? [caller]
|
|
41
|
+
: [];
|
|
42
|
+
|
|
43
|
+
const callingStateLabel = CALLING_STATE_TO_LABEL[callingState];
|
|
44
|
+
|
|
45
|
+
return (
|
|
46
|
+
<div className="str-video__call-panel str-video__call-panel--pending">
|
|
47
|
+
<div className="str-video__call-panel__members-list">
|
|
48
|
+
{membersToShow.map((user) => (
|
|
49
|
+
<div key={user.id} className="str-video__call-panel__member-box">
|
|
50
|
+
<Avatar name={user.name} imageSrc={user.image} />
|
|
51
|
+
{user.name && (
|
|
52
|
+
<div className="str-video__member_details">
|
|
53
|
+
<span className="str-video__member_name">{user.name}</span>
|
|
54
|
+
</div>
|
|
55
|
+
)}
|
|
56
|
+
</div>
|
|
57
|
+
))}
|
|
58
|
+
</div>
|
|
59
|
+
|
|
60
|
+
{callingStateLabel && (
|
|
61
|
+
<div className="str-video__call-panel__calling-state-label">
|
|
62
|
+
{t(callingStateLabel)}
|
|
63
|
+
</div>
|
|
64
|
+
)}
|
|
65
|
+
|
|
66
|
+
{[CallingState.RINGING, CallingState.JOINING].includes(callingState) && (
|
|
67
|
+
<PendingCallControls />
|
|
68
|
+
)}
|
|
69
|
+
</div>
|
|
70
|
+
);
|
|
71
|
+
};
|
|
@@ -53,15 +53,9 @@ export const PermissionRequests = () => {
|
|
|
53
53
|
return async () => {
|
|
54
54
|
const { user, permissions } = request;
|
|
55
55
|
if (allow) {
|
|
56
|
-
await call?.
|
|
57
|
-
user_id: user.id,
|
|
58
|
-
grant_permissions: permissions,
|
|
59
|
-
});
|
|
56
|
+
await call?.grantPermissions(user.id, permissions);
|
|
60
57
|
} else {
|
|
61
|
-
await call?.
|
|
62
|
-
user_id: user.id,
|
|
63
|
-
revoke_permissions: permissions,
|
|
64
|
-
});
|
|
58
|
+
await call?.revokePermissions(user.id, permissions);
|
|
65
59
|
}
|
|
66
60
|
setPermissionRequests((requests) =>
|
|
67
61
|
requests.filter((r) => r !== request),
|
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
useLocalParticipant,
|
|
6
6
|
useParticipants,
|
|
7
7
|
} from '@stream-io/video-react-bindings';
|
|
8
|
-
import {
|
|
8
|
+
import { ParticipantView, DefaultParticipantViewUI } from '../../core';
|
|
9
9
|
import { Video } from '../Video';
|
|
10
10
|
|
|
11
11
|
import { useVerticalScrollPosition } from './hooks';
|
|
@@ -60,7 +60,6 @@ export const CallParticipantsScreenView = (props: { call: Call }) => {
|
|
|
60
60
|
<Video
|
|
61
61
|
className="str-video__screen-share"
|
|
62
62
|
participant={firstScreenSharingParticipant}
|
|
63
|
-
call={call}
|
|
64
63
|
kind="screen"
|
|
65
64
|
autoPlay
|
|
66
65
|
muted
|
|
@@ -104,11 +103,11 @@ export const CallParticipantsScreenView = (props: { call: Call }) => {
|
|
|
104
103
|
>
|
|
105
104
|
<div className="str-video__call-participants-screen-view__participants">
|
|
106
105
|
{allParticipants.map((participant) => (
|
|
107
|
-
<
|
|
106
|
+
<ParticipantView
|
|
108
107
|
key={participant.sessionId}
|
|
109
108
|
participant={participant}
|
|
110
|
-
call={call}
|
|
111
109
|
sinkId={localParticipant?.audioOutputDeviceId}
|
|
110
|
+
ParticipantViewUI={DefaultParticipantViewUI}
|
|
112
111
|
/>
|
|
113
112
|
))}
|
|
114
113
|
</div>
|
|
@@ -1,23 +1,22 @@
|
|
|
1
1
|
import { Call } from '@stream-io/video-client';
|
|
2
|
-
import {
|
|
2
|
+
import { DefaultParticipantViewUI, ParticipantView } from '../../core';
|
|
3
3
|
import {
|
|
4
4
|
useLocalParticipant,
|
|
5
5
|
useParticipants,
|
|
6
6
|
} from '@stream-io/video-react-bindings';
|
|
7
7
|
|
|
8
8
|
export const CallParticipantsView = (props: { call: Call }) => {
|
|
9
|
-
const { call } = props;
|
|
10
9
|
const localParticipant = useLocalParticipant();
|
|
11
10
|
const participants = useParticipants();
|
|
12
11
|
const grid = `str-video__grid-${participants.length || 1}`;
|
|
13
12
|
return (
|
|
14
13
|
<div className={`str-video__call-participants-view ${grid}`}>
|
|
15
14
|
{participants.map((participant) => (
|
|
16
|
-
<
|
|
15
|
+
<ParticipantView
|
|
17
16
|
key={participant.sessionId}
|
|
18
17
|
participant={participant}
|
|
19
|
-
call={call}
|
|
20
18
|
sinkId={localParticipant?.audioOutputDeviceId}
|
|
19
|
+
ParticipantViewUI={DefaultParticipantViewUI}
|
|
21
20
|
/>
|
|
22
21
|
))}
|
|
23
22
|
</div>
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { ElementType, HTMLProps, PropsWithChildren } from 'react';
|
|
2
|
+
import clsx from 'clsx';
|
|
3
|
+
|
|
4
|
+
export type StreamThemeProps = HTMLProps<HTMLElement> & {
|
|
5
|
+
as?: ElementType;
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
export const StreamTheme = ({
|
|
9
|
+
as: Component = 'div',
|
|
10
|
+
className,
|
|
11
|
+
children,
|
|
12
|
+
...props
|
|
13
|
+
}: PropsWithChildren<StreamThemeProps>) => {
|
|
14
|
+
return (
|
|
15
|
+
<Component {...props} className={clsx('str-video', className)}>
|
|
16
|
+
{children}
|
|
17
|
+
</Component>
|
|
18
|
+
);
|
|
19
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './StreamTheme';
|
|
@@ -7,8 +7,13 @@ import {
|
|
|
7
7
|
} from 'react';
|
|
8
8
|
import clsx from 'clsx';
|
|
9
9
|
import { disposeOfMediaStream } from '@stream-io/video-client';
|
|
10
|
-
import { BaseVideo } from '../../core/components/Video
|
|
11
|
-
import {
|
|
10
|
+
import { BaseVideo } from '../../core/components/Video';
|
|
11
|
+
import {
|
|
12
|
+
DEVICE_STATE,
|
|
13
|
+
useMediaDevices,
|
|
14
|
+
useOnUnavailableVideoDevices,
|
|
15
|
+
useVideoDevices,
|
|
16
|
+
} from '../../core';
|
|
12
17
|
import { LoadingIndicator } from '../LoadingIndicator';
|
|
13
18
|
|
|
14
19
|
const DefaultDisabledVideoPreview = () => {
|
|
@@ -47,19 +52,24 @@ export const VideoPreview = ({
|
|
|
47
52
|
VideoErrorPreview = DefaultVideoErrorPreview,
|
|
48
53
|
}: VideoPreviewProps) => {
|
|
49
54
|
const [stream, setStream] = useState<MediaStream>();
|
|
50
|
-
|
|
51
55
|
const {
|
|
52
|
-
videoDevices,
|
|
53
56
|
selectedVideoDeviceId,
|
|
54
57
|
getVideoStream,
|
|
55
58
|
initialVideoState,
|
|
56
59
|
setInitialVideoState,
|
|
57
60
|
} = useMediaDevices();
|
|
61
|
+
// When there are 0 video devices (e.g. when laptop lid closed),
|
|
62
|
+
// we do not restart the video automatically when the device is again available,
|
|
63
|
+
// but rather leave turning the video on manually to the user.
|
|
64
|
+
useOnUnavailableVideoDevices(() =>
|
|
65
|
+
setInitialVideoState(DEVICE_STATE.stopped),
|
|
66
|
+
);
|
|
67
|
+
const videoDevices = useVideoDevices();
|
|
58
68
|
|
|
59
69
|
useEffect(() => {
|
|
60
|
-
if (!initialVideoState.enabled
|
|
70
|
+
if (!initialVideoState.enabled) return;
|
|
61
71
|
|
|
62
|
-
getVideoStream(selectedVideoDeviceId)
|
|
72
|
+
getVideoStream({ deviceId: selectedVideoDeviceId })
|
|
63
73
|
.then((s) => {
|
|
64
74
|
setStream((previousStream) => {
|
|
65
75
|
if (previousStream) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export * from '../../core/components/Video/Video';
|
|
2
2
|
export * from '../../core/components/Video/BaseVideo';
|
|
3
|
-
export * from '../../core/components/Video/
|
|
3
|
+
export * from '../../core/components/Video/DefaultVideoPlaceholder';
|
|
4
4
|
export * from './VideoPreview';
|