@100mslive/roomkit-react 0.1.6-alpha.0 → 0.1.6-alpha.2
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/dist/{HLSView-PY2FKWX3.js → HLSView-QMU5JK7U.js} +208 -118
- package/dist/HLSView-QMU5JK7U.js.map +7 -0
- package/dist/Prebuilt/AppContext.d.ts +1 -1
- package/dist/Prebuilt/components/Chat/ChatFooter.d.ts +7 -0
- package/dist/Prebuilt/components/Connection/ConnectionIndicator.d.ts +6 -0
- package/dist/Prebuilt/components/Connection/TileConnection.d.ts +10 -0
- package/dist/Prebuilt/components/Footer/ChatToggle.d.ts +2 -0
- package/dist/Prebuilt/components/Footer/RoleAccordion.d.ts +14 -0
- package/dist/Prebuilt/components/Footer/RoleOptions.d.ts +6 -0
- package/dist/Prebuilt/components/Header/StreamActions.d.ts +11 -0
- package/dist/Prebuilt/components/Leave/DesktopLeaveRoom.d.ts +4 -3
- package/dist/Prebuilt/components/Leave/EndSessionContent.d.ts +4 -3
- package/dist/Prebuilt/components/Leave/LeaveCard.d.ts +1 -2
- package/dist/Prebuilt/components/Leave/LeaveSessionContent.d.ts +3 -1
- package/dist/Prebuilt/components/Leave/MwebLeaveRoom.d.ts +4 -3
- package/dist/Prebuilt/components/MoreSettings/SplitComponents/MwebOptions.d.ts +6 -0
- package/dist/Prebuilt/components/Preview/PreviewContainer.d.ts +3 -0
- package/dist/Prebuilt/components/Preview/PreviewJoin.d.ts +16 -0
- package/dist/Prebuilt/components/RoleChangeRequestModal.d.ts +2 -0
- package/dist/Prebuilt/components/SecondaryTiles.d.ts +1 -1
- package/dist/Prebuilt/components/SidePaneTabs.d.ts +7 -0
- package/dist/Prebuilt/components/VideoLayouts/EqualProminence.d.ts +1 -1
- package/dist/Prebuilt/components/VideoLayouts/Grid.d.ts +1 -0
- package/dist/Prebuilt/components/VideoLayouts/GridLayout.d.ts +5 -3
- package/dist/Prebuilt/components/VideoLayouts/ProminenceLayout.d.ts +6 -3
- package/dist/Prebuilt/components/VideoLayouts/RoleProminence.d.ts +1 -1
- package/dist/Prebuilt/components/VideoLayouts/ScreenshareLayout.d.ts +1 -1
- package/dist/Prebuilt/components/VideoLayouts/interface.d.ts +1 -0
- package/dist/Prebuilt/components/hooks/useAutoStartStreaming.d.ts +1 -0
- package/dist/Prebuilt/components/hooks/useRedirectToLeave.d.ts +3 -0
- package/dist/Prebuilt/components/hooks/useTileLayout.d.ts +2 -1
- package/dist/Prebuilt/components/hooks/useVideoTileLayout.d.ts +2 -0
- package/dist/Prebuilt/layouts/SidePane.d.ts +4 -1
- package/dist/Prebuilt/layouts/VideoStreamingSection.d.ts +2 -1
- package/dist/{VirtualBackground-AYDHYLIZ.js → VirtualBackground-37FXUPYO.js} +6 -6
- package/dist/VirtualBackground-37FXUPYO.js.map +7 -0
- package/dist/{chunk-GQD2AGWW.js → chunk-KBVIZGYW.js} +12 -2
- package/dist/{chunk-GQD2AGWW.js.map → chunk-KBVIZGYW.js.map} +2 -2
- package/dist/{chunk-RXTHJUMZ.js → chunk-WVGGQZK4.js} +986 -436
- package/dist/chunk-WVGGQZK4.js.map +7 -0
- package/dist/{chunk-E2M2ZSOL.js → chunk-ZKE2N5LH.js} +2 -2
- package/dist/{conference-V2XZGTKU.js → conference-FJJQ4TXX.js} +1136 -1301
- package/dist/conference-FJJQ4TXX.js.map +7 -0
- package/dist/index.cjs.js +3565 -3092
- package/dist/index.cjs.js.map +4 -4
- package/dist/index.js +2 -2
- package/dist/meta.cjs.json +773 -525
- package/dist/meta.esbuild.json +833 -579
- package/package.json +8 -7
- package/src/Prebuilt/App.tsx +10 -21
- package/src/Prebuilt/AppContext.tsx +1 -1
- package/src/Prebuilt/IconButton.jsx +10 -0
- package/src/Prebuilt/common/PeersSorter.ts +1 -1
- package/src/Prebuilt/common/constants.js +1 -2
- package/src/Prebuilt/common/utils.js +1 -1
- package/src/Prebuilt/components/AppData/AppData.jsx +8 -2
- package/src/Prebuilt/components/AppData/useUISettings.js +6 -6
- package/src/Prebuilt/components/AudioVideoToggle.jsx +8 -6
- package/src/Prebuilt/components/Chat/Chat.jsx +24 -11
- package/src/Prebuilt/components/Chat/ChatBody.jsx +20 -21
- package/src/Prebuilt/components/Chat/{ChatFooter.jsx → ChatFooter.tsx} +38 -13
- package/src/Prebuilt/components/Chat/useEmojiPickerStyles.js +5 -4
- package/src/Prebuilt/components/Connection/{ConnectionIndicator.jsx → ConnectionIndicator.tsx} +12 -4
- package/src/Prebuilt/components/Connection/{TileConnection.jsx → TileConnection.tsx} +20 -6
- package/src/Prebuilt/components/EmojiReaction.jsx +2 -6
- package/src/Prebuilt/components/Footer/{ChatToggle.jsx → ChatToggle.tsx} +4 -1
- package/src/Prebuilt/components/Footer/Footer.tsx +30 -5
- package/src/Prebuilt/components/Footer/ParticipantList.jsx +15 -49
- package/src/Prebuilt/components/Footer/{RoleAccordion.jsx → RoleAccordion.tsx} +33 -17
- package/src/Prebuilt/components/Footer/RoleOptions.tsx +155 -0
- package/src/Prebuilt/components/FullPageProgress.jsx +3 -3
- package/src/Prebuilt/components/HMSVideo/Controls.jsx +1 -0
- package/src/Prebuilt/components/HMSVideo/HLSQualitySelector.jsx +39 -17
- package/src/Prebuilt/components/HMSVideo/HMSVideo.jsx +2 -2
- package/src/Prebuilt/components/HMSVideo/VideoProgress.jsx +5 -6
- package/src/Prebuilt/components/HMSVideo/VolumeControl.jsx +1 -1
- package/src/Prebuilt/components/Header/HeaderComponents.jsx +8 -1
- package/src/Prebuilt/components/Header/{StreamActions.jsx → StreamActions.tsx} +23 -9
- package/src/Prebuilt/components/Header/common.jsx +5 -2
- package/src/Prebuilt/components/IconButtonWithOptions/IconButtonWithOptions.jsx +6 -1
- package/src/Prebuilt/components/InsetTile.tsx +15 -8
- package/src/Prebuilt/components/Leave/DesktopLeaveRoom.tsx +21 -11
- package/src/Prebuilt/components/Leave/EndSessionContent.tsx +2 -5
- package/src/Prebuilt/components/Leave/LeaveCard.tsx +1 -3
- package/src/Prebuilt/components/Leave/LeaveRoom.tsx +28 -25
- package/src/Prebuilt/components/Leave/LeaveSessionContent.tsx +8 -2
- package/src/Prebuilt/components/Leave/MwebLeaveRoom.tsx +8 -8
- package/src/Prebuilt/components/MoreSettings/ChangeNameContent.jsx +4 -0
- package/src/Prebuilt/components/MoreSettings/MoreSettings.tsx +1 -1
- package/src/Prebuilt/components/MoreSettings/SplitComponents/DesktopOptions.tsx +9 -23
- package/src/Prebuilt/components/MoreSettings/SplitComponents/{MwebOptions.jsx → MwebOptions.tsx} +89 -28
- package/src/Prebuilt/components/Notifications/Notifications.jsx +44 -28
- package/src/Prebuilt/components/Notifications/ReconnectNotifications.jsx +5 -11
- package/src/Prebuilt/components/Pagination.tsx +14 -12
- package/src/Prebuilt/components/Preview/{PreviewContainer.jsx → PreviewContainer.tsx} +11 -2
- package/src/Prebuilt/components/Preview/PreviewForm.tsx +6 -8
- package/src/Prebuilt/components/Preview/{PreviewJoin.jsx → PreviewJoin.tsx} +44 -21
- package/src/Prebuilt/components/{RoleChangeRequestModal.jsx → RoleChangeRequestModal.tsx} +36 -17
- package/src/Prebuilt/components/ScreenshareTile.jsx +6 -7
- package/src/Prebuilt/components/SecondaryTiles.tsx +12 -10
- package/src/Prebuilt/components/SidePaneTabs.tsx +120 -0
- package/src/Prebuilt/components/TileMenu/TileMenu.jsx +1 -1
- package/src/Prebuilt/components/TileMenu/TileMenuContent.jsx +14 -10
- package/src/Prebuilt/components/Toast/ToastConfig.jsx +5 -4
- package/src/Prebuilt/components/VideoLayouts/EqualProminence.tsx +13 -10
- package/src/Prebuilt/components/VideoLayouts/Grid.tsx +36 -34
- package/src/Prebuilt/components/VideoLayouts/GridLayout.tsx +33 -15
- package/src/Prebuilt/components/VideoLayouts/ProminenceLayout.tsx +45 -31
- package/src/Prebuilt/components/VideoLayouts/RoleProminence.tsx +12 -9
- package/src/Prebuilt/components/VideoLayouts/ScreenshareLayout.tsx +25 -9
- package/src/Prebuilt/components/VideoLayouts/interface.ts +1 -0
- package/src/Prebuilt/components/VideoTile.jsx +45 -53
- package/src/Prebuilt/components/conference.jsx +71 -74
- package/src/Prebuilt/components/hooks/useAutoStartStreaming.tsx +57 -0
- package/src/Prebuilt/components/hooks/useMetadata.jsx +19 -28
- package/src/Prebuilt/components/hooks/useRedirectToLeave.tsx +34 -0
- package/src/Prebuilt/components/hooks/useRoleProminencePeers.tsx +1 -1
- package/src/Prebuilt/components/hooks/useTileLayout.tsx +24 -18
- package/src/Prebuilt/components/hooks/useVideoTileLayout.ts +4 -0
- package/src/Prebuilt/layouts/EmbedView.jsx +1 -11
- package/src/Prebuilt/layouts/HLSView.jsx +152 -82
- package/src/Prebuilt/layouts/SidePane.tsx +25 -11
- package/src/Prebuilt/layouts/VideoStreamingSection.tsx +11 -47
- package/src/Prebuilt/plugins/FlyingEmoji.jsx +14 -2
- package/src/Prebuilt/plugins/VirtualBackground/VirtualBackground.jsx +3 -3
- package/src/Prebuilt/provider/roomLayoutProvider/hooks/useFetchRoomLayout.ts +2 -2
- package/src/Prebuilt/services/FeatureFlags.jsx +0 -1
- package/src/VideoTile/StyledVideoTile.tsx +1 -0
- package/dist/HLSView-PY2FKWX3.js.map +0 -7
- package/dist/VirtualBackground-AYDHYLIZ.js.map +0 -7
- package/dist/chunk-RXTHJUMZ.js.map +0 -7
- package/dist/conference-V2XZGTKU.js.map +0 -7
- package/src/Prebuilt/components/AudioLevel/BeamSpeakerLabelsLogging.jsx +0 -16
- package/src/Prebuilt/components/Chat/ChatParticipantHeader.jsx +0 -73
- package/src/Prebuilt/components/VideoList.jsx +0 -73
- /package/dist/{chunk-E2M2ZSOL.js.map → chunk-ZKE2N5LH.js.map} +0 -0
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import React, { useState } from 'react';
|
|
2
|
+
import { DefaultConferencingScreen_Elements } from '@100mslive/types-prebuilt';
|
|
3
|
+
import { HMSPeer, selectPermissions, useHMSActions, useHMSStore, useHMSVanillaStore } from '@100mslive/react-sdk';
|
|
4
|
+
import {
|
|
5
|
+
MicOffIcon,
|
|
6
|
+
MicOnIcon,
|
|
7
|
+
PersonRectangleIcon,
|
|
8
|
+
RemoveUserIcon,
|
|
9
|
+
VerticalMenuIcon,
|
|
10
|
+
VideoOffIcon,
|
|
11
|
+
VideoOnIcon,
|
|
12
|
+
} from '@100mslive/react-icons';
|
|
13
|
+
import { Dropdown } from '../../../Dropdown';
|
|
14
|
+
import { Flex } from '../../../Layout';
|
|
15
|
+
import { Text } from '../../../Text';
|
|
16
|
+
import { useRoomLayoutConferencingScreen } from '../../provider/roomLayoutProvider/hooks/useRoomLayoutScreen';
|
|
17
|
+
// @ts-ignore: No implicit Any
|
|
18
|
+
import { getMetadata } from '../../common/utils';
|
|
19
|
+
|
|
20
|
+
const dropdownItemCSS = { backgroundColor: '$surface_default', gap: '$4', p: '$8' };
|
|
21
|
+
const optionTextCSS = { fontWeight: '$semiBold', color: '$on_surface_high', textTransform: 'none' };
|
|
22
|
+
|
|
23
|
+
export const RoleOptions = ({ roleName, peerList }: { roleName: string; peerList: HMSPeer[] }) => {
|
|
24
|
+
const [openOptions, setOpenOptions] = useState(false);
|
|
25
|
+
const permissions = useHMSStore(selectPermissions);
|
|
26
|
+
const hmsActions = useHMSActions();
|
|
27
|
+
const { elements } = useRoomLayoutConferencingScreen();
|
|
28
|
+
const { on_stage_role, off_stage_roles = [] } = (elements as DefaultConferencingScreen_Elements)?.on_stage_exp || {};
|
|
29
|
+
|
|
30
|
+
const vanillaStore = useHMSVanillaStore();
|
|
31
|
+
const store = vanillaStore.getState();
|
|
32
|
+
|
|
33
|
+
let allPeersHaveVideoOn = true;
|
|
34
|
+
let allPeersHaveAudioOn = true;
|
|
35
|
+
|
|
36
|
+
peerList.forEach(peer => {
|
|
37
|
+
const isAudioOn = !!peer.audioTrack && store.tracks[peer.audioTrack]?.enabled;
|
|
38
|
+
const isVideoOn = !!peer.videoTrack && store.tracks[peer.videoTrack]?.enabled;
|
|
39
|
+
allPeersHaveAudioOn = allPeersHaveAudioOn && isAudioOn;
|
|
40
|
+
allPeersHaveVideoOn = allPeersHaveVideoOn && isVideoOn;
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
const canMuteRole = permissions?.mute && roleName === on_stage_role;
|
|
44
|
+
const canRemoveRoleFromStage = permissions?.changeRole && roleName === on_stage_role;
|
|
45
|
+
// on stage and off stage roles
|
|
46
|
+
const canRemoveRoleFromRoom =
|
|
47
|
+
permissions?.removeOthers && (on_stage_role === roleName || off_stage_roles?.includes(roleName));
|
|
48
|
+
|
|
49
|
+
if (!(canMuteRole || canRemoveRoleFromStage || canRemoveRoleFromRoom)) {
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const removeAllFromStage = () => {
|
|
54
|
+
peerList.forEach(peer => {
|
|
55
|
+
const prevRole = getMetadata(peer.metadata).prevRole;
|
|
56
|
+
if (prevRole) {
|
|
57
|
+
hmsActions.changeRoleOfPeer(peer.id, prevRole, true);
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
const setTrackEnabled = async (type: 'audio' | 'video', enabled = false) => {
|
|
63
|
+
try {
|
|
64
|
+
await hmsActions.setRemoteTracksEnabled({ roles: [roleName], source: 'regular', type, enabled });
|
|
65
|
+
} catch (e) {
|
|
66
|
+
console.error(e);
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
const removePeersFromRoom = async () => {
|
|
71
|
+
try {
|
|
72
|
+
peerList.forEach(async peer => {
|
|
73
|
+
await hmsActions.removePeer(peer.id, '');
|
|
74
|
+
});
|
|
75
|
+
} catch (e) {
|
|
76
|
+
console.error(e);
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
return (
|
|
81
|
+
<Dropdown.Root open={openOptions} onOpenChange={setOpenOptions}>
|
|
82
|
+
<Dropdown.Trigger
|
|
83
|
+
onClick={e => e.stopPropagation()}
|
|
84
|
+
className="role_actions"
|
|
85
|
+
asChild
|
|
86
|
+
css={{
|
|
87
|
+
p: '$1',
|
|
88
|
+
r: '$0',
|
|
89
|
+
c: '$on_surface_high',
|
|
90
|
+
visibility: openOptions ? 'visible' : 'hidden',
|
|
91
|
+
'&:hover': {
|
|
92
|
+
c: '$on_surface_medium',
|
|
93
|
+
},
|
|
94
|
+
'@md': {
|
|
95
|
+
visibility: 'visible',
|
|
96
|
+
},
|
|
97
|
+
}}
|
|
98
|
+
>
|
|
99
|
+
<Flex>
|
|
100
|
+
<VerticalMenuIcon />
|
|
101
|
+
</Flex>
|
|
102
|
+
</Dropdown.Trigger>
|
|
103
|
+
<Dropdown.Content
|
|
104
|
+
onClick={e => e.stopPropagation()}
|
|
105
|
+
css={{ w: 'max-content', maxWidth: '$64', bg: '$surface_default', py: 0 }}
|
|
106
|
+
align="end"
|
|
107
|
+
>
|
|
108
|
+
{canRemoveRoleFromStage && (
|
|
109
|
+
<Dropdown.Item
|
|
110
|
+
css={{ ...dropdownItemCSS, borderBottom: '1px solid $border_bright' }}
|
|
111
|
+
onClick={removeAllFromStage}
|
|
112
|
+
>
|
|
113
|
+
<PersonRectangleIcon />
|
|
114
|
+
<Text variant="sm" css={optionTextCSS}>
|
|
115
|
+
Remove all from Stage
|
|
116
|
+
</Text>
|
|
117
|
+
</Dropdown.Item>
|
|
118
|
+
)}
|
|
119
|
+
|
|
120
|
+
{canMuteRole && (
|
|
121
|
+
<>
|
|
122
|
+
<Dropdown.Item css={dropdownItemCSS} onClick={() => setTrackEnabled('audio', !allPeersHaveAudioOn)}>
|
|
123
|
+
{allPeersHaveAudioOn ? <MicOffIcon /> : <MicOnIcon />}
|
|
124
|
+
<Text variant="sm" css={optionTextCSS}>
|
|
125
|
+
{allPeersHaveAudioOn ? 'Mute' : 'Unmute'} Audio
|
|
126
|
+
</Text>
|
|
127
|
+
</Dropdown.Item>
|
|
128
|
+
|
|
129
|
+
<Dropdown.Item
|
|
130
|
+
css={{ ...dropdownItemCSS, borderTop: '1px solid $border_bright' }}
|
|
131
|
+
onClick={() => setTrackEnabled('video', !allPeersHaveVideoOn)}
|
|
132
|
+
>
|
|
133
|
+
{allPeersHaveVideoOn ? <VideoOffIcon /> : <VideoOnIcon />}
|
|
134
|
+
<Text variant="sm" css={optionTextCSS}>
|
|
135
|
+
{allPeersHaveVideoOn ? 'Mute' : 'Unmute'} Video
|
|
136
|
+
</Text>
|
|
137
|
+
</Dropdown.Item>
|
|
138
|
+
</>
|
|
139
|
+
)}
|
|
140
|
+
|
|
141
|
+
{canRemoveRoleFromRoom && (
|
|
142
|
+
<Dropdown.Item
|
|
143
|
+
css={{ ...dropdownItemCSS, borderTop: '1px solid $border_bright', color: '$alert_error_default' }}
|
|
144
|
+
onClick={removePeersFromRoom}
|
|
145
|
+
>
|
|
146
|
+
<RemoveUserIcon />
|
|
147
|
+
<Text variant="sm" css={{ ...optionTextCSS, color: 'inherit' }}>
|
|
148
|
+
Remove all from Room
|
|
149
|
+
</Text>
|
|
150
|
+
</Dropdown.Item>
|
|
151
|
+
)}
|
|
152
|
+
</Dropdown.Content>
|
|
153
|
+
</Dropdown.Root>
|
|
154
|
+
);
|
|
155
|
+
};
|
|
@@ -3,10 +3,10 @@ import { Flex } from '../../Layout';
|
|
|
3
3
|
import { Loading } from '../../Loading';
|
|
4
4
|
import { Text } from '../../Text';
|
|
5
5
|
|
|
6
|
-
const FullPageProgress = ({ loaderColor = '$primary_default',
|
|
7
|
-
<Flex direction="column" justify="center" align="center" css={{ size: '100%', color: loaderColor }}>
|
|
6
|
+
const FullPageProgress = ({ loaderColor = '$primary_default', text = '', css = {} }) => (
|
|
7
|
+
<Flex direction="column" justify="center" align="center" css={{ size: '100%', color: loaderColor, ...css }}>
|
|
8
8
|
<Loading color="currentColor" size={100} />
|
|
9
|
-
{
|
|
9
|
+
{text ? <Text css={{ mt: '$10', color: '$on_surface_high' }}>{text}</Text> : null}
|
|
10
10
|
</Flex>
|
|
11
11
|
);
|
|
12
12
|
|
|
@@ -1,12 +1,10 @@
|
|
|
1
|
-
import React
|
|
2
|
-
import {
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { CheckIcon, SettingsIcon } from '@100mslive/react-icons';
|
|
3
3
|
import { Box, Dropdown, Flex, Text, Tooltip } from '../../../';
|
|
4
4
|
|
|
5
|
-
export function HLSQualitySelector({ layers, onQualityChange, selection, isAuto }) {
|
|
6
|
-
const [qualityDropDownOpen, setQualityDropDownOpen] = useState(false);
|
|
7
|
-
|
|
5
|
+
export function HLSQualitySelector({ open, onOpen, layers, onQualityChange, selection, isAuto }) {
|
|
8
6
|
return (
|
|
9
|
-
<Dropdown.Root open={
|
|
7
|
+
<Dropdown.Root open={open} onOpenChange={value => onOpen(value)}>
|
|
10
8
|
<Dropdown.Trigger asChild data-testid="quality_selector">
|
|
11
9
|
<Flex
|
|
12
10
|
css={{
|
|
@@ -24,6 +22,7 @@ export function HLSQualitySelector({ layers, onQualityChange, selection, isAuto
|
|
|
24
22
|
h: '$9',
|
|
25
23
|
display: 'inline-flex',
|
|
26
24
|
alignItems: 'center',
|
|
25
|
+
c: '$on_surface_high',
|
|
27
26
|
}}
|
|
28
27
|
>
|
|
29
28
|
<SettingsIcon />
|
|
@@ -44,7 +43,7 @@ export function HLSQualitySelector({ layers, onQualityChange, selection, isAuto
|
|
|
44
43
|
mx: '$2',
|
|
45
44
|
w: '$2',
|
|
46
45
|
h: '$2',
|
|
47
|
-
background: '$
|
|
46
|
+
background: '$on_surface_medium',
|
|
48
47
|
r: '$1',
|
|
49
48
|
}}
|
|
50
49
|
/>
|
|
@@ -60,7 +59,15 @@ export function HLSQualitySelector({ layers, onQualityChange, selection, isAuto
|
|
|
60
59
|
<Dropdown.Content
|
|
61
60
|
sideOffset={5}
|
|
62
61
|
align="end"
|
|
63
|
-
css={{
|
|
62
|
+
css={{
|
|
63
|
+
height: 'auto',
|
|
64
|
+
maxHeight: '$52',
|
|
65
|
+
w: '$40',
|
|
66
|
+
bg: '$surface_bright',
|
|
67
|
+
py: '$4',
|
|
68
|
+
gap: '$4',
|
|
69
|
+
display: 'grid',
|
|
70
|
+
}}
|
|
64
71
|
>
|
|
65
72
|
{layers.map(layer => {
|
|
66
73
|
return (
|
|
@@ -68,16 +75,26 @@ export function HLSQualitySelector({ layers, onQualityChange, selection, isAuto
|
|
|
68
75
|
onClick={() => onQualityChange(layer)}
|
|
69
76
|
key={layer.width}
|
|
70
77
|
css={{
|
|
71
|
-
bg:
|
|
78
|
+
bg:
|
|
79
|
+
!isAuto && layer.width === selection?.width && layer.height === selection?.height
|
|
80
|
+
? '$surface_default'
|
|
81
|
+
: '$surface_bright',
|
|
72
82
|
'&:hover': {
|
|
73
|
-
bg: '$
|
|
83
|
+
bg: '$surface_brighter',
|
|
74
84
|
},
|
|
85
|
+
p: '$2 $4 $2 $8',
|
|
86
|
+
h: '$12',
|
|
87
|
+
gap: '$2',
|
|
75
88
|
}}
|
|
76
89
|
>
|
|
77
|
-
<Text
|
|
78
|
-
|
|
90
|
+
<Text variant="caption" css={{ fontWeight: '$semiBold' }}>
|
|
91
|
+
{getQualityText(layer)}
|
|
92
|
+
</Text>
|
|
93
|
+
<Text variant="caption" css={{ flex: '1 1 0', c: '$on_surface_low', pl: '$2' }}>
|
|
94
|
+
{getBitrateText(layer)}
|
|
95
|
+
</Text>
|
|
79
96
|
{!isAuto && layer.width === selection?.width && layer.height === selection?.height && (
|
|
80
|
-
<
|
|
97
|
+
<CheckIcon width="16px" height="16px" />
|
|
81
98
|
)}
|
|
82
99
|
</Dropdown.Item>
|
|
83
100
|
);
|
|
@@ -86,14 +103,19 @@ export function HLSQualitySelector({ layers, onQualityChange, selection, isAuto
|
|
|
86
103
|
onClick={() => onQualityChange({ height: 'auto' })}
|
|
87
104
|
key="auto"
|
|
88
105
|
css={{
|
|
89
|
-
bg: '$surface_bright',
|
|
106
|
+
bg: !isAuto ? '$surface_bright' : '$surface_default',
|
|
90
107
|
'&:hover': {
|
|
91
|
-
bg: '$
|
|
108
|
+
bg: '$surface_brighter',
|
|
92
109
|
},
|
|
110
|
+
p: '$2 $4 $2 $8',
|
|
111
|
+
h: '$12',
|
|
112
|
+
gap: '$2',
|
|
93
113
|
}}
|
|
94
114
|
>
|
|
95
|
-
<Text css={{ flex: '1 1 0' }}>
|
|
96
|
-
|
|
115
|
+
<Text variant="caption" css={{ fontWeight: '$semiBold', flex: '1 1 0' }}>
|
|
116
|
+
Auto
|
|
117
|
+
</Text>
|
|
118
|
+
{isAuto && <CheckIcon width="16px" height="16px" />}
|
|
97
119
|
</Dropdown.Item>
|
|
98
120
|
</Dropdown.Content>
|
|
99
121
|
)}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import React, { forwardRef } from 'react';
|
|
2
2
|
import { Flex } from '../../../';
|
|
3
3
|
|
|
4
|
-
export const HMSVideo = forwardRef(({ children }, videoRef) => {
|
|
4
|
+
export const HMSVideo = forwardRef(({ children, ...props }, videoRef) => {
|
|
5
5
|
return (
|
|
6
|
-
<Flex data-testid="hms-video" css={{ size: '100%' }} direction="column">
|
|
6
|
+
<Flex data-testid="hms-video" css={{ size: '100%', position: 'relative' }} direction="column" {...props}>
|
|
7
7
|
<video style={{ flex: '1 1 0', margin: '0 auto', minHeight: '0' }} ref={videoRef} playsInline />
|
|
8
8
|
{children}
|
|
9
9
|
</Flex>
|
|
@@ -44,7 +44,7 @@ export const VideoProgress = ({ onValueChange, hlsPlayer }) => {
|
|
|
44
44
|
return hlsPlayer.getVideoElement() ? (
|
|
45
45
|
<Flex
|
|
46
46
|
ref={progressRootRef}
|
|
47
|
-
css={{
|
|
47
|
+
css={{ cursor: 'pointer', h: '$4', alignSelf: 'stretch' }}
|
|
48
48
|
onClick={onProgressChangeHandler}
|
|
49
49
|
>
|
|
50
50
|
<Box
|
|
@@ -53,23 +53,22 @@ export const VideoProgress = ({ onValueChange, hlsPlayer }) => {
|
|
|
53
53
|
display: 'inline',
|
|
54
54
|
width: `${videoProgress}%`,
|
|
55
55
|
background: '$primary_default',
|
|
56
|
-
height: '0.3rem',
|
|
57
56
|
}}
|
|
58
57
|
/>
|
|
59
58
|
<Box
|
|
60
59
|
id="video-buffer"
|
|
61
60
|
css={{
|
|
62
61
|
width: `${bufferProgress - videoProgress}%`,
|
|
63
|
-
background: '$
|
|
64
|
-
|
|
62
|
+
background: '$on_surface_high',
|
|
63
|
+
opacity: '25%',
|
|
65
64
|
}}
|
|
66
65
|
/>
|
|
67
66
|
<Box
|
|
68
67
|
id="video-rest"
|
|
69
68
|
css={{
|
|
70
69
|
width: `${100 - bufferProgress}%`,
|
|
71
|
-
background: '$
|
|
72
|
-
|
|
70
|
+
background: '$on_surface_high',
|
|
71
|
+
opacity: '10%',
|
|
73
72
|
}}
|
|
74
73
|
/>
|
|
75
74
|
</Flex>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { useState } from 'react';
|
|
1
|
+
import React, { useEffect, useState } from 'react';
|
|
2
2
|
import { useMedia } from 'react-use';
|
|
3
3
|
import { selectDominantSpeaker, selectIsConnectedToRoom, useHMSStore } from '@100mslive/react-sdk';
|
|
4
4
|
import { VolumeOneIcon } from '@100mslive/react-icons';
|
|
@@ -41,6 +41,13 @@ export const Logo = () => {
|
|
|
41
41
|
const isConnected = useHMSStore(selectIsConnectedToRoom);
|
|
42
42
|
const [hideImage, setHideImage] = useState(false);
|
|
43
43
|
// Hide logo for now as there is not enough space
|
|
44
|
+
useEffect(() => {
|
|
45
|
+
if (hideImage) {
|
|
46
|
+
setHideImage(false);
|
|
47
|
+
}
|
|
48
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
49
|
+
}, [logo]);
|
|
50
|
+
|
|
44
51
|
if (isConnected && isMobile) {
|
|
45
52
|
return null;
|
|
46
53
|
}
|
|
@@ -11,26 +11,31 @@ import {
|
|
|
11
11
|
useRecordingStreaming,
|
|
12
12
|
} from '@100mslive/react-sdk';
|
|
13
13
|
import { AlertTriangleIcon, CrossIcon, RecordIcon } from '@100mslive/react-icons';
|
|
14
|
-
import { Box, Button, config as cssConfig, Flex, HorizontalDivider, Loading, Popover, Text, Tooltip } from '
|
|
14
|
+
import { Box, Button, config as cssConfig, Flex, HorizontalDivider, Loading, Popover, Text, Tooltip } from '../../..';
|
|
15
15
|
import { Sheet } from '../../../Sheet';
|
|
16
|
+
// @ts-ignore
|
|
16
17
|
import { ToastManager } from '../Toast/ToastManager';
|
|
18
|
+
// @ts-ignore
|
|
17
19
|
import { AdditionalRoomState, getRecordingText } from './AdditionalRoomState';
|
|
20
|
+
// @ts-ignore
|
|
18
21
|
import { useSetAppDataByKey } from '../AppData/useUISettings';
|
|
22
|
+
// @ts-ignore
|
|
19
23
|
import { formatTime } from '../../common/utils';
|
|
24
|
+
// @ts-ignore
|
|
20
25
|
import { APP_DATA } from '../../common/constants';
|
|
21
26
|
|
|
22
27
|
export const LiveStatus = () => {
|
|
23
28
|
const { isHLSRunning, isRTMPRunning } = useRecordingStreaming();
|
|
24
29
|
const hlsState = useHMSStore(selectHLSState);
|
|
25
30
|
const isMobile = useMedia(cssConfig.media.md);
|
|
26
|
-
const intervalRef = useRef(null);
|
|
31
|
+
const intervalRef = useRef<NodeJS.Timeout | null>(null);
|
|
27
32
|
|
|
28
33
|
const [liveTime, setLiveTime] = useState(0);
|
|
29
34
|
|
|
30
35
|
const startTimer = useCallback(() => {
|
|
31
36
|
intervalRef.current = setInterval(() => {
|
|
32
|
-
if (hlsState?.running) {
|
|
33
|
-
setLiveTime(Date.now() - hlsState
|
|
37
|
+
if (hlsState?.running && hlsState?.variants[0]?.startedAt) {
|
|
38
|
+
setLiveTime(Date.now() - hlsState.variants[0].startedAt.getTime());
|
|
34
39
|
}
|
|
35
40
|
}, 1000);
|
|
36
41
|
}, [hlsState?.running, hlsState?.variants]);
|
|
@@ -90,6 +95,7 @@ export const RecordingStatus = () => {
|
|
|
90
95
|
|
|
91
96
|
return (
|
|
92
97
|
<Tooltip
|
|
98
|
+
boxCss={{ zIndex: 1 }}
|
|
93
99
|
title={getRecordingText({
|
|
94
100
|
isBrowserRecordingOn,
|
|
95
101
|
isServerRecordingOn,
|
|
@@ -130,7 +136,7 @@ const StartRecording = () => {
|
|
|
130
136
|
</Popover.Trigger>
|
|
131
137
|
<Popover.Portal>
|
|
132
138
|
<Popover.Content align="end" sideOffset={8} css={{ w: '$64' }}>
|
|
133
|
-
<Text variant="
|
|
139
|
+
<Text variant="body1" css={{ color: '$on_surface_medium' }}>
|
|
134
140
|
Are you sure you want to end the recording?
|
|
135
141
|
</Text>
|
|
136
142
|
<Button
|
|
@@ -142,8 +148,9 @@ const StartRecording = () => {
|
|
|
142
148
|
try {
|
|
143
149
|
await hmsActions.stopRTMPAndRecording();
|
|
144
150
|
} catch (error) {
|
|
151
|
+
const err = error as Error;
|
|
145
152
|
ToastManager.addToast({
|
|
146
|
-
title:
|
|
153
|
+
title: err.message,
|
|
147
154
|
variant: 'error',
|
|
148
155
|
});
|
|
149
156
|
}
|
|
@@ -170,14 +177,15 @@ const StartRecording = () => {
|
|
|
170
177
|
record: true,
|
|
171
178
|
});
|
|
172
179
|
} catch (error) {
|
|
173
|
-
|
|
180
|
+
const err = error as Error;
|
|
181
|
+
if (err.message.includes('stream already running')) {
|
|
174
182
|
ToastManager.addToast({
|
|
175
183
|
title: 'Recording already running',
|
|
176
184
|
variant: 'error',
|
|
177
185
|
});
|
|
178
186
|
} else {
|
|
179
187
|
ToastManager.addToast({
|
|
180
|
-
title:
|
|
188
|
+
title: err.message,
|
|
181
189
|
variant: 'error',
|
|
182
190
|
});
|
|
183
191
|
}
|
|
@@ -215,7 +223,13 @@ export const StreamActions = () => {
|
|
|
215
223
|
);
|
|
216
224
|
};
|
|
217
225
|
|
|
218
|
-
export const StopRecordingInSheet = ({
|
|
226
|
+
export const StopRecordingInSheet = ({
|
|
227
|
+
onStopRecording,
|
|
228
|
+
onClose,
|
|
229
|
+
}: {
|
|
230
|
+
onStopRecording: () => void;
|
|
231
|
+
onClose: () => void;
|
|
232
|
+
}) => {
|
|
219
233
|
return (
|
|
220
234
|
<Sheet.Root open={true}>
|
|
221
235
|
<Sheet.Content>
|
|
@@ -25,11 +25,13 @@ export const CamaraFlipActions = () => {
|
|
|
25
25
|
|
|
26
26
|
const videoTrackId = useHMSStore(selectLocalVideoTrackID);
|
|
27
27
|
const localVideoTrack = useHMSStore(selectVideoTrackByID(videoTrackId));
|
|
28
|
-
|
|
28
|
+
if (!videoInput || !videoInput?.length || !localVideoTrack?.facingMode) {
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
29
31
|
return (
|
|
30
32
|
<Box>
|
|
31
33
|
<IconButton
|
|
32
|
-
disabled={!
|
|
34
|
+
disabled={!isVideoOn}
|
|
33
35
|
onClick={async () => {
|
|
34
36
|
try {
|
|
35
37
|
await actions.switchCamera();
|
|
@@ -117,6 +119,7 @@ const AudioOutputSelectionSheet = ({ outputDevices, outputSelected, onChange, ch
|
|
|
117
119
|
{outputDevices.map(audioDevice => {
|
|
118
120
|
return (
|
|
119
121
|
<SelectWithLabel
|
|
122
|
+
key={audioDevice.deviceId}
|
|
120
123
|
label={audioDevice.label}
|
|
121
124
|
id={audioDevice.deviceId}
|
|
122
125
|
checked={audioDevice.deviceId === outputSelected}
|
|
@@ -14,6 +14,10 @@ const IconSection = styled(IconButton, {
|
|
|
14
14
|
borderTopRightRadius: 0,
|
|
15
15
|
borderColor: '$border_default',
|
|
16
16
|
borderBottomRightRadius: 0,
|
|
17
|
+
position: 'relative',
|
|
18
|
+
'&:not([disabled]):focus-visible': {
|
|
19
|
+
zIndex: 1,
|
|
20
|
+
},
|
|
17
21
|
'@md': {
|
|
18
22
|
mx: 0,
|
|
19
23
|
borderTopRightRadius: '$1',
|
|
@@ -30,8 +34,9 @@ const OptionsSection = styled(IconButton, {
|
|
|
30
34
|
borderColor: '$border_default',
|
|
31
35
|
borderBottomLeftRadius: 0,
|
|
32
36
|
borderLeftWidth: 0,
|
|
37
|
+
position: 'relative',
|
|
33
38
|
'&:not([disabled]):focus-visible': {
|
|
34
|
-
|
|
39
|
+
zIndex: 1,
|
|
35
40
|
},
|
|
36
41
|
'@md': {
|
|
37
42
|
display: 'none',
|
|
@@ -14,6 +14,7 @@ import { AudioVideoToggle } from './AudioVideoToggle';
|
|
|
14
14
|
import VideoTile from './VideoTile';
|
|
15
15
|
// @ts-ignore: No implicit Any
|
|
16
16
|
import { useSetAppDataByKey } from './AppData/useUISettings';
|
|
17
|
+
import { useVideoTileContext } from './hooks/useVideoTileLayout';
|
|
17
18
|
// @ts-ignore: No implicit Any
|
|
18
19
|
import { APP_DATA } from '../common/constants';
|
|
19
20
|
|
|
@@ -22,7 +23,11 @@ const MinimisedTile = ({ setMinimised }: { setMinimised: (value: boolean) => voi
|
|
|
22
23
|
<Flex align="center" css={{ gap: '$6', r: '$1', bg: '$surface_default', p: '$4', color: '$on_surface_high' }}>
|
|
23
24
|
<AudioVideoToggle hideOptions={true} />
|
|
24
25
|
<Text>You</Text>
|
|
25
|
-
<IconButton
|
|
26
|
+
<IconButton
|
|
27
|
+
className="__cancel-drag-event"
|
|
28
|
+
onClick={() => setMinimised(false)}
|
|
29
|
+
css={{ bg: 'transparent', border: 'transparent' }}
|
|
30
|
+
>
|
|
26
31
|
<ExpandIcon />
|
|
27
32
|
</IconButton>
|
|
28
33
|
</Flex>
|
|
@@ -41,12 +46,11 @@ export const InsetTile = () => {
|
|
|
41
46
|
const [minimised, setMinimised] = useSetAppDataByKey(APP_DATA.minimiseInset);
|
|
42
47
|
const videoTrack = useHMSStore(selectVideoTrackByID(localPeer?.videoTrack));
|
|
43
48
|
const isAllowedToPublish = useHMSStore(selectIsAllowedToPublish);
|
|
44
|
-
const
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
: desktopAspectRatio;
|
|
49
|
+
const videoTileProps = useVideoTileContext();
|
|
50
|
+
let aspectRatio = isMobile ? defaultMobileAspectRatio : desktopAspectRatio;
|
|
51
|
+
if (videoTrack?.width && videoTrack?.height && !isMobile) {
|
|
52
|
+
aspectRatio = videoTrack.width / videoTrack.height;
|
|
53
|
+
}
|
|
50
54
|
let height = insetHeightPx;
|
|
51
55
|
let width = height * aspectRatio;
|
|
52
56
|
// Convert to 16/9 in landscape mode with a max width of 240
|
|
@@ -82,7 +86,7 @@ export const InsetTile = () => {
|
|
|
82
86
|
}
|
|
83
87
|
|
|
84
88
|
return (
|
|
85
|
-
<Draggable bounds="parent" nodeRef={nodeRef}>
|
|
89
|
+
<Draggable bounds="parent" nodeRef={nodeRef} cancel=".__cancel-drag-event">
|
|
86
90
|
<Box
|
|
87
91
|
ref={nodeRef}
|
|
88
92
|
css={{
|
|
@@ -114,6 +118,9 @@ export const InsetTile = () => {
|
|
|
114
118
|
height={height}
|
|
115
119
|
containerCSS={{ background: '$surface_default' }}
|
|
116
120
|
canMinimise
|
|
121
|
+
isDragabble
|
|
122
|
+
{...videoTileProps}
|
|
123
|
+
hideParticipantNameOnTile
|
|
117
124
|
/>
|
|
118
125
|
)}
|
|
119
126
|
</Box>
|
|
@@ -15,11 +15,9 @@ import { useDropdownList } from '../hooks/useDropdownList';
|
|
|
15
15
|
|
|
16
16
|
export const DesktopLeaveRoom = ({
|
|
17
17
|
leaveRoom,
|
|
18
|
-
stopStream,
|
|
19
18
|
screenType,
|
|
20
19
|
}: {
|
|
21
|
-
leaveRoom: () => void;
|
|
22
|
-
stopStream: () => Promise<void>;
|
|
20
|
+
leaveRoom: (args: { endstream: boolean }) => void;
|
|
23
21
|
screenType: keyof ConferencingScreen;
|
|
24
22
|
}) => {
|
|
25
23
|
const [open, setOpen] = useState(false);
|
|
@@ -51,7 +49,7 @@ export const DesktopLeaveRoom = ({
|
|
|
51
49
|
if (screenType === 'hls_live_streaming') {
|
|
52
50
|
setShowLeaveRoomAlert(true);
|
|
53
51
|
} else {
|
|
54
|
-
leaveRoom();
|
|
52
|
+
leaveRoom({ endstream: false });
|
|
55
53
|
}
|
|
56
54
|
}}
|
|
57
55
|
>
|
|
@@ -75,7 +73,15 @@ export const DesktopLeaveRoom = ({
|
|
|
75
73
|
</MenuTriggerButton>
|
|
76
74
|
</Dropdown.Trigger>
|
|
77
75
|
<Dropdown.Content css={{ p: 0, w: '$100' }} alignOffset={-50} sideOffset={10}>
|
|
78
|
-
<Dropdown.Item
|
|
76
|
+
<Dropdown.Item
|
|
77
|
+
css={{
|
|
78
|
+
bg: '$surface_dim',
|
|
79
|
+
color: '$on_surface_low',
|
|
80
|
+
'&:hover': { bg: '$surface_default', color: '$on_surface_high' },
|
|
81
|
+
}}
|
|
82
|
+
onClick={() => leaveRoom({ endstream: false })}
|
|
83
|
+
data-testid="just_leave_btn"
|
|
84
|
+
>
|
|
79
85
|
<LeaveCard
|
|
80
86
|
title={showStream ? 'Leave Stream' : 'Leave Session'}
|
|
81
87
|
subtitle={`Others will continue after you leave. You can join the ${
|
|
@@ -83,14 +89,20 @@ export const DesktopLeaveRoom = ({
|
|
|
83
89
|
} again.`}
|
|
84
90
|
bg=""
|
|
85
91
|
titleColor="$on_surface_high"
|
|
86
|
-
subtitleColor="$on_surface_low"
|
|
87
92
|
icon={<ExitIcon height={24} width={24} style={{ transform: 'rotate(180deg)' }} />}
|
|
88
|
-
onClick={leaveRoom}
|
|
93
|
+
onClick={() => leaveRoom({ endstream: false })}
|
|
89
94
|
css={{ p: 0 }}
|
|
90
95
|
/>
|
|
91
96
|
</Dropdown.Item>
|
|
92
97
|
{isStreamingOn && permissions?.hlsStreaming ? (
|
|
93
|
-
<Dropdown.Item
|
|
98
|
+
<Dropdown.Item
|
|
99
|
+
css={{
|
|
100
|
+
bg: '$alert_error_dim',
|
|
101
|
+
color: '$alert_error_bright',
|
|
102
|
+
'&:hover': { bg: '$alert_error_dim', color: '$alert_error_brighter' },
|
|
103
|
+
}}
|
|
104
|
+
data-testid="end_room_btn"
|
|
105
|
+
>
|
|
94
106
|
<LeaveCard
|
|
95
107
|
title={showStream ? 'End Stream' : 'End Session'}
|
|
96
108
|
subtitle={`The ${
|
|
@@ -98,7 +110,6 @@ export const DesktopLeaveRoom = ({
|
|
|
98
110
|
} will end for everyone. You can't undo this action.`}
|
|
99
111
|
bg=""
|
|
100
112
|
titleColor="$alert_error_brighter"
|
|
101
|
-
subtitleColor="$alert_error_bright"
|
|
102
113
|
icon={<StopIcon height={24} width={24} />}
|
|
103
114
|
onClick={() => {
|
|
104
115
|
setOpen(false);
|
|
@@ -117,7 +128,7 @@ export const DesktopLeaveRoom = ({
|
|
|
117
128
|
if (screenType === 'hls_live_streaming') {
|
|
118
129
|
setShowLeaveRoomAlert(true);
|
|
119
130
|
} else {
|
|
120
|
-
leaveRoom();
|
|
131
|
+
leaveRoom({ endstream: false });
|
|
121
132
|
}
|
|
122
133
|
}}
|
|
123
134
|
key="LeaveRoom"
|
|
@@ -137,7 +148,6 @@ export const DesktopLeaveRoom = ({
|
|
|
137
148
|
<Dialog.Content css={{ w: 'min(420px, 90%)', p: '$8', bg: '$surface_dim' }}>
|
|
138
149
|
<EndSessionContent
|
|
139
150
|
setShowEndStreamAlert={setShowEndStreamAlert}
|
|
140
|
-
stopStream={stopStream}
|
|
141
151
|
leaveRoom={leaveRoom}
|
|
142
152
|
isStreamingOn={isStreamingOn}
|
|
143
153
|
isModal
|