@100mslive/roomkit-react 0.1.4-alpha.1 → 0.1.5
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-F2K5VSTS.js → HLSView-P57IRMAR.js} +7 -11
- package/dist/{HLSView-F2K5VSTS.js.map → HLSView-P57IRMAR.js.map} +1 -1
- package/dist/PinnedTrackView-4FYJEBTB.js +102 -0
- package/dist/PinnedTrackView-4FYJEBTB.js.map +7 -0
- package/dist/Popover/index.d.ts +1 -0
- package/dist/Prebuilt/App.d.ts +25 -0
- package/dist/Prebuilt/index.d.ts +1 -0
- package/dist/Prebuilt/provider/roomLayoutProvider/index.d.ts +1 -1
- package/dist/Sheet/Sheet.d.ts +3093 -0
- package/dist/Sheet/index.d.ts +1 -0
- package/dist/Theme/ThemeProvider.d.ts +4 -286
- package/dist/Theme/stitches.config.d.ts +1 -1
- package/dist/{VirtualBackground-S3XEPZ2T.js → VirtualBackground-GGCQJ5JM.js} +31 -7
- package/dist/VirtualBackground-GGCQJ5JM.js.map +7 -0
- package/dist/chunk-IVTWKQI3.js +827 -0
- package/dist/chunk-IVTWKQI3.js.map +7 -0
- package/dist/{chunk-42SWPN2C.js → chunk-OSM4QEQG.js} +3020 -2189
- package/dist/chunk-OSM4QEQG.js.map +7 -0
- package/dist/chunk-P5X32KOD.js +67 -0
- package/dist/chunk-P5X32KOD.js.map +7 -0
- package/dist/chunk-RVCZPPTL.js +1100 -0
- package/dist/chunk-RVCZPPTL.js.map +7 -0
- package/dist/{chunk-ESUJK7AT.js → conference-P6I6ESVF.js} +3136 -653
- package/dist/conference-P6I6ESVF.js.map +7 -0
- package/dist/index.cjs.js +15733 -15498
- package/dist/index.cjs.js.map +4 -4
- package/dist/index.js +4 -8
- package/dist/meta.cjs.json +3355 -3017
- package/dist/meta.esbuild.json +3534 -3329
- package/dist/utils/animations.d.ts +16 -0
- package/package.json +8 -10
- package/src/Button/Button.tsx +4 -4
- package/src/Dropdown/Dropdown.tsx +2 -2
- package/src/IconButton/IconButton.tsx +4 -2
- package/src/Pagination/StyledPagination.tsx +1 -0
- package/src/Popover/index.tsx +2 -1
- package/src/Prebuilt/{App.jsx → App.tsx} +95 -48
- package/src/Prebuilt/Prebuilt.stories.tsx +22 -8
- package/src/Prebuilt/common/constants.js +1 -2
- package/src/Prebuilt/common/hooks.js +8 -0
- package/src/Prebuilt/common/utils.js +15 -0
- package/src/Prebuilt/components/AppData/AppData.jsx +1 -2
- package/src/Prebuilt/components/AppData/useUISettings.js +0 -5
- package/src/Prebuilt/components/AudioVideoToggle.jsx +69 -26
- package/src/Prebuilt/components/AuthToken.jsx +3 -2
- package/src/Prebuilt/components/Chat/ChatSelector.jsx +1 -1
- package/src/Prebuilt/components/Connection/TileConnection.jsx +0 -1
- package/src/Prebuilt/components/EmojiReaction.jsx +23 -73
- package/src/Prebuilt/components/EndSessionContent.jsx +57 -0
- package/src/Prebuilt/components/EqualProminence.jsx +180 -0
- package/src/Prebuilt/components/ErrorBoundary.jsx +4 -10
- package/src/Prebuilt/components/Footer/EmojiCard.jsx +34 -0
- package/src/Prebuilt/components/Footer/Footer.jsx +73 -0
- package/src/Prebuilt/components/{Header → Footer}/ParticipantList.jsx +5 -5
- package/src/Prebuilt/components/Header/ConferencingHeader.jsx +27 -7
- package/src/Prebuilt/components/Header/HeaderComponents.jsx +16 -14
- package/src/Prebuilt/components/Header/StreamActions.jsx +101 -36
- package/src/Prebuilt/components/Header/StreamingHeader.jsx +1 -1
- package/src/Prebuilt/components/Header/common.jsx +164 -0
- package/src/Prebuilt/components/IconButtonWithOptions/IconButtonWithOptions.jsx +1 -2
- package/src/Prebuilt/components/LeaveCard.jsx +19 -0
- package/src/Prebuilt/components/LeaveRoom.jsx +35 -143
- package/src/Prebuilt/components/LeaveSessionContent.jsx +45 -0
- package/src/Prebuilt/components/MoreSettings/ActionTile.jsx +55 -0
- package/src/Prebuilt/components/MoreSettings/ChangeNameContent.jsx +96 -0
- package/src/Prebuilt/components/MoreSettings/ChangeNameModal.jsx +31 -54
- package/src/Prebuilt/components/MoreSettings/EmbedUrl.jsx +48 -73
- package/src/Prebuilt/components/MoreSettings/MoreSettings.jsx +5 -221
- package/src/Prebuilt/components/MoreSettings/MuteAllContent.jsx +61 -0
- package/src/Prebuilt/components/MoreSettings/MuteAllModal.jsx +32 -49
- package/src/Prebuilt/components/MoreSettings/SplitComponents/DesktopLeaveRoom.jsx +129 -0
- package/src/Prebuilt/components/MoreSettings/SplitComponents/DesktopOptions.jsx +219 -0
- package/src/Prebuilt/components/MoreSettings/SplitComponents/MwebLeaveRoom.jsx +100 -0
- package/src/Prebuilt/components/MoreSettings/SplitComponents/MwebOptions.jsx +259 -0
- package/src/Prebuilt/components/Notifications/Notifications.jsx +0 -2
- package/src/Prebuilt/components/Notifications/ReconnectNotifications.jsx +0 -4
- package/src/Prebuilt/components/PIP/PIPComponent.jsx +30 -26
- package/src/Prebuilt/components/PIP/PIPManager.js +13 -0
- package/src/Prebuilt/components/PIP/index.jsx +2 -7
- package/src/Prebuilt/components/Pagination.jsx +4 -4
- package/src/Prebuilt/components/Preview/PreviewContainer.jsx +5 -13
- package/src/Prebuilt/components/Preview/PreviewForm.jsx +9 -5
- package/src/Prebuilt/components/Preview/PreviewJoin.jsx +20 -27
- package/src/Prebuilt/components/RaiseHand.jsx +27 -0
- package/src/Prebuilt/components/ScreenShare.jsx +1 -1
- package/src/Prebuilt/components/ScreenshareDisplay.jsx +2 -2
- package/src/Prebuilt/components/ScreenshareTile.jsx +2 -2
- package/src/Prebuilt/components/Settings/DeviceSettings.jsx +2 -1
- package/src/Prebuilt/components/Settings/LayoutSettings.jsx +1 -24
- package/src/Prebuilt/components/Settings/SettingsModal.jsx +152 -17
- package/src/Prebuilt/components/ShareMenuIcon.jsx +1 -0
- package/src/Prebuilt/components/TileMenu/TileMenu.jsx +133 -0
- package/src/Prebuilt/components/TileMenu/TileMenuContent.jsx +313 -0
- package/src/Prebuilt/components/VideoList.jsx +5 -33
- package/src/Prebuilt/components/VideoTile.jsx +30 -8
- package/src/Prebuilt/components/conference.jsx +14 -1
- package/src/Prebuilt/components/init/Init.jsx +0 -27
- package/src/Prebuilt/components/init/initUtils.js +0 -23
- package/src/Prebuilt/components/pdfAnnotator/pdfFileOptions.jsx +2 -1
- package/src/Prebuilt/components/pdfAnnotator/pdfInfo.jsx +1 -1
- package/src/Prebuilt/components/pdfAnnotator/shareScreenOptions.jsx +19 -8
- package/src/Prebuilt/components/pdfAnnotator/uploadedFile.jsx +1 -0
- package/src/Prebuilt/images/pdf-share.png +0 -0
- package/src/Prebuilt/images/screen-share.png +0 -0
- package/src/Prebuilt/index.ts +1 -0
- package/src/Prebuilt/layouts/EmbedView.jsx +0 -1
- package/src/Prebuilt/layouts/InsetView.jsx +65 -24
- package/src/Prebuilt/layouts/PDFView.jsx +0 -1
- package/src/Prebuilt/layouts/SidePane.jsx +8 -7
- package/src/Prebuilt/layouts/mainView.jsx +22 -31
- package/src/Prebuilt/layouts/screenShareView.jsx +0 -2
- package/src/Prebuilt/plugins/VirtualBackground/VirtualBackground.jsx +25 -1
- package/src/Prebuilt/primitives/DialogContent.jsx +1 -1
- package/src/Prebuilt/provider/roomLayoutProvider/index.tsx +1 -1
- package/src/Sheet/Sheet.mdx +19 -0
- package/src/Sheet/Sheet.stories.tsx +103 -0
- package/src/Sheet/Sheet.tsx +118 -0
- package/src/Sheet/index.ts +1 -0
- package/src/Theme/ThemeProvider.tsx +10 -13
- package/src/Theme/base.config.ts +1 -1
- package/src/Theme/stitches.config.ts +1 -1
- package/src/TileMenu/StyledMenuTile.tsx +2 -2
- package/src/TileMenu/TileMenu.tsx +2 -0
- package/src/VideoTile/StyledVideoTile.tsx +5 -0
- package/src/utils/animations.ts +18 -0
- package/dist/ActiveSpeakerView-V6O4K3BV.js +0 -39
- package/dist/ActiveSpeakerView-V6O4K3BV.js.map +0 -7
- package/dist/PinnedTrackView-7YQG4QKC.js +0 -70
- package/dist/PinnedTrackView-7YQG4QKC.js.map +0 -7
- package/dist/VirtualBackground-S3XEPZ2T.js.map +0 -7
- package/dist/chunk-42SWPN2C.js.map +0 -7
- package/dist/chunk-4NEZLVVH.js +0 -811
- package/dist/chunk-4NEZLVVH.js.map +0 -7
- package/dist/chunk-4ZBEFSRC.js +0 -58
- package/dist/chunk-4ZBEFSRC.js.map +0 -7
- package/dist/chunk-ESUJK7AT.js.map +0 -7
- package/dist/chunk-R6PDR5WZ.js +0 -243
- package/dist/chunk-R6PDR5WZ.js.map +0 -7
- package/dist/conference-7QKOMJPP.js +0 -3697
- package/dist/conference-7QKOMJPP.js.map +0 -7
- package/dist/transcription-RJA4V6PC.js +0 -356
- package/dist/transcription-RJA4V6PC.js.map +0 -7
- package/src/Prebuilt/common/useSortedPeers.js +0 -28
- package/src/Prebuilt/components/BottomActionSheet/BottomActionSheet.jsx +0 -96
- package/src/Prebuilt/components/BottomActionSheet/BottomActionSheet.stories.tsx +0 -46
- package/src/Prebuilt/components/Footer/ConferencingFooter.jsx +0 -101
- package/src/Prebuilt/components/Footer/StreamingFooter.jsx +0 -71
- package/src/Prebuilt/components/Footer.jsx +0 -8
- package/src/Prebuilt/components/MoreSettings/ChangeSelfRole.jsx +0 -67
- package/src/Prebuilt/components/TileMenu.jsx +0 -268
- package/src/Prebuilt/index.d.ts +0 -20
- package/src/Prebuilt/index.js +0 -2
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { useMedia } from 'react-use';
|
|
3
|
+
import { selectLocalPeerRoleName, useHMSStore } from '@100mslive/react-sdk';
|
|
4
|
+
import { config as cssConfig, Footer as AppFooter } from '../../..';
|
|
5
|
+
import { AudioVideoToggle } from '../AudioVideoToggle';
|
|
6
|
+
import { EmojiReaction } from '../EmojiReaction';
|
|
7
|
+
import { LeaveRoom } from '../LeaveRoom';
|
|
8
|
+
import { MoreSettings } from '../MoreSettings/MoreSettings';
|
|
9
|
+
import { RaiseHand } from '../RaiseHand';
|
|
10
|
+
import { ScreenshareToggle } from '../ScreenShare';
|
|
11
|
+
import { ChatToggle } from './ChatToggle';
|
|
12
|
+
import { ParticipantCount } from './ParticipantList';
|
|
13
|
+
import { useHLSViewerRole } from '../AppData/useUISettings';
|
|
14
|
+
|
|
15
|
+
export const Footer = () => {
|
|
16
|
+
const isMobile = useMedia(cssConfig.media.md);
|
|
17
|
+
const localPeerRole = useHMSStore(selectLocalPeerRoleName);
|
|
18
|
+
const hlsViewerRole = useHLSViewerRole();
|
|
19
|
+
const isHlsViewer = hlsViewerRole === localPeerRole;
|
|
20
|
+
|
|
21
|
+
return (
|
|
22
|
+
<AppFooter.Root
|
|
23
|
+
css={{
|
|
24
|
+
flexWrap: 'nowrap',
|
|
25
|
+
'@md': {
|
|
26
|
+
justifyContent: 'center',
|
|
27
|
+
gap: '$10',
|
|
28
|
+
},
|
|
29
|
+
}}
|
|
30
|
+
>
|
|
31
|
+
<AppFooter.Left
|
|
32
|
+
css={{
|
|
33
|
+
'@md': {
|
|
34
|
+
w: 'unset',
|
|
35
|
+
p: '0',
|
|
36
|
+
gap: '$10',
|
|
37
|
+
},
|
|
38
|
+
}}
|
|
39
|
+
>
|
|
40
|
+
{isMobile ? <LeaveRoom /> : null}
|
|
41
|
+
<AudioVideoToggle />
|
|
42
|
+
</AppFooter.Left>
|
|
43
|
+
<AppFooter.Center
|
|
44
|
+
css={{
|
|
45
|
+
'@md': {
|
|
46
|
+
w: 'unset',
|
|
47
|
+
gap: '$10',
|
|
48
|
+
},
|
|
49
|
+
}}
|
|
50
|
+
>
|
|
51
|
+
{isMobile ? (
|
|
52
|
+
<>
|
|
53
|
+
{isHlsViewer ? <RaiseHand /> : null}
|
|
54
|
+
<ChatToggle />
|
|
55
|
+
<MoreSettings />
|
|
56
|
+
</>
|
|
57
|
+
) : (
|
|
58
|
+
<>
|
|
59
|
+
<ScreenshareToggle />
|
|
60
|
+
{isHlsViewer ? <RaiseHand /> : null}
|
|
61
|
+
<EmojiReaction />
|
|
62
|
+
<LeaveRoom />
|
|
63
|
+
</>
|
|
64
|
+
)}
|
|
65
|
+
</AppFooter.Center>
|
|
66
|
+
<AppFooter.Right>
|
|
67
|
+
<ChatToggle />
|
|
68
|
+
<ParticipantCount />
|
|
69
|
+
<MoreSettings />
|
|
70
|
+
</AppFooter.Right>
|
|
71
|
+
</AppFooter.Root>
|
|
72
|
+
);
|
|
73
|
+
};
|
|
@@ -21,11 +21,11 @@ import {
|
|
|
21
21
|
SpeakerIcon,
|
|
22
22
|
VerticalMenuIcon,
|
|
23
23
|
} from '@100mslive/react-icons';
|
|
24
|
-
import { Avatar, Box, Dropdown, Flex, Input, Slider, Text, textEllipsis } from '
|
|
24
|
+
import { Avatar, Box, Dropdown, Flex, Input, Slider, Text, textEllipsis } from '../../..';
|
|
25
25
|
import IconButton from '../../IconButton';
|
|
26
26
|
import { ConnectionIndicator } from '../Connection/ConnectionIndicator';
|
|
27
|
+
import { ParticipantFilter } from '../Header/ParticipantFilter';
|
|
27
28
|
import { RoleChangeModal } from '../RoleChangeModal';
|
|
28
|
-
import { ParticipantFilter } from './ParticipantFilter';
|
|
29
29
|
import { useIsSidepaneTypeOpen, useSidepaneToggle } from '../AppData/useSidepane';
|
|
30
30
|
import { isInternalRole } from '../../common/utils';
|
|
31
31
|
import { SIDE_PANE_OPTIONS } from '../../common/constants';
|
|
@@ -232,7 +232,7 @@ const ParticipantMoreActions = ({ onRoleChange, peerId }) => {
|
|
|
232
232
|
const actions = useHMSActions();
|
|
233
233
|
const [open, setOpen] = useState(false);
|
|
234
234
|
return (
|
|
235
|
-
<Dropdown.Root open={open} onOpenChange={value => setOpen(value)}>
|
|
235
|
+
<Dropdown.Root open={open} onOpenChange={value => setOpen(value)} modal={false}>
|
|
236
236
|
<Dropdown.Trigger asChild data-testid="participant_more_actions" css={{ p: '$2', r: '$0' }} tabIndex={0}>
|
|
237
237
|
<Text>
|
|
238
238
|
<VerticalMenuIcon />
|
|
@@ -320,8 +320,8 @@ export const ParticipantSearch = ({ onSearch, placeholder }) => {
|
|
|
320
320
|
</Box>
|
|
321
321
|
<Input
|
|
322
322
|
type="text"
|
|
323
|
-
placeholder={placeholder || '
|
|
324
|
-
css={{ w: '100%', pl: '$14' }}
|
|
323
|
+
placeholder={placeholder || 'Search among participants'}
|
|
324
|
+
css={{ w: '100%', pl: '$14', bg: '$surface_bright' }}
|
|
325
325
|
value={value}
|
|
326
326
|
onKeyDown={event => {
|
|
327
327
|
event.stopPropagation();
|
|
@@ -1,16 +1,31 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
2
|
+
import { useMedia } from 'react-use';
|
|
3
|
+
import { HMSRoomState, selectRoomState, useHMSStore } from '@100mslive/react-sdk';
|
|
4
|
+
import { config as cssConfig, Flex } from '../../../';
|
|
5
|
+
import { Logo, SpeakerTag } from './HeaderComponents';
|
|
6
|
+
import { LiveStatus, RecordingStatus, StreamActions } from './StreamActions';
|
|
7
|
+
import { AudioOutputActions, CamaraFlipActions } from './common';
|
|
6
8
|
|
|
7
9
|
export const ConferencingHeader = () => {
|
|
10
|
+
const roomState = useHMSStore(selectRoomState);
|
|
11
|
+
const isMobile = useMedia(cssConfig.media.md);
|
|
12
|
+
const isPreview = roomState === HMSRoomState.Preview;
|
|
13
|
+
// no header if there in preview
|
|
14
|
+
if (isPreview) {
|
|
15
|
+
return <></>;
|
|
16
|
+
}
|
|
8
17
|
return (
|
|
9
18
|
<Flex justify="between" align="center" css={{ position: 'relative', height: '100%' }}>
|
|
10
|
-
<Flex align="center" css={{ position: 'absolute', left: '$10' }}>
|
|
19
|
+
<Flex align="center" gap="2" css={{ position: 'absolute', left: '$10' }}>
|
|
20
|
+
<Logo />
|
|
11
21
|
<SpeakerTag />
|
|
22
|
+
{isMobile && (
|
|
23
|
+
<Flex align="center" css={{ gap: '$4' }}>
|
|
24
|
+
<LiveStatus />
|
|
25
|
+
<RecordingStatus />
|
|
26
|
+
</Flex>
|
|
27
|
+
)}
|
|
12
28
|
</Flex>
|
|
13
|
-
|
|
14
29
|
<Flex
|
|
15
30
|
align="center"
|
|
16
31
|
css={{
|
|
@@ -20,7 +35,12 @@ export const ConferencingHeader = () => {
|
|
|
20
35
|
}}
|
|
21
36
|
>
|
|
22
37
|
<StreamActions />
|
|
23
|
-
|
|
38
|
+
{isMobile && (
|
|
39
|
+
<>
|
|
40
|
+
<CamaraFlipActions />
|
|
41
|
+
<AudioOutputActions />
|
|
42
|
+
</>
|
|
43
|
+
)}
|
|
24
44
|
</Flex>
|
|
25
45
|
</Flex>
|
|
26
46
|
);
|
|
@@ -2,25 +2,27 @@ import React 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';
|
|
5
|
-
import { config as cssConfig, Flex, styled, Text, textEllipsis } from '../../../';
|
|
5
|
+
import { config as cssConfig, Flex, styled, Text, textEllipsis, VerticalDivider } from '../../../';
|
|
6
6
|
import { useRoomLayout } from '../../provider/roomLayoutProvider';
|
|
7
7
|
import { isStreamingKit } from '../../common/utils';
|
|
8
8
|
|
|
9
9
|
export const SpeakerTag = () => {
|
|
10
10
|
const dominantSpeaker = useHMSStore(selectDominantSpeaker);
|
|
11
|
-
return
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
{
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
11
|
+
return (
|
|
12
|
+
dominantSpeaker &&
|
|
13
|
+
dominantSpeaker.name && (
|
|
14
|
+
<Flex
|
|
15
|
+
align="center"
|
|
16
|
+
justify="center"
|
|
17
|
+
css={{ flex: '1 1 0', color: '$on_primary_high', '@md': { display: 'none' } }}
|
|
18
|
+
>
|
|
19
|
+
<VerticalDivider css={{ ml: '$8' }} />
|
|
20
|
+
<VolumeOneIcon />
|
|
21
|
+
<Text variant="md" css={{ ...textEllipsis(200), ml: '$2' }} title={dominantSpeaker.name}>
|
|
22
|
+
{dominantSpeaker.name}
|
|
23
|
+
</Text>
|
|
24
|
+
</Flex>
|
|
25
|
+
)
|
|
24
26
|
);
|
|
25
27
|
};
|
|
26
28
|
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import React, {
|
|
1
|
+
import React, { useCallback, useEffect, useRef, useState } from 'react';
|
|
2
2
|
import { useMedia } from 'react-use';
|
|
3
3
|
import {
|
|
4
4
|
HMSRoomState,
|
|
5
|
+
selectHLSState,
|
|
5
6
|
selectIsConnectedToRoom,
|
|
6
7
|
selectPermissions,
|
|
7
8
|
selectRoomState,
|
|
@@ -9,31 +10,65 @@ import {
|
|
|
9
10
|
useHMSStore,
|
|
10
11
|
useRecordingStreaming,
|
|
11
12
|
} from '@100mslive/react-sdk';
|
|
12
|
-
import {
|
|
13
|
-
import { Box, Button, config as cssConfig, Flex, Loading, Popover, Text, Tooltip } from '../../../';
|
|
14
|
-
import
|
|
13
|
+
import { AlertTriangleIcon, CrossIcon, RecordIcon } from '@100mslive/react-icons';
|
|
14
|
+
import { Box, Button, config as cssConfig, Flex, HorizontalDivider, Loading, Popover, Text, Tooltip } from '../../../';
|
|
15
|
+
import { Sheet } from '../../../Sheet';
|
|
15
16
|
import { ResolutionInput } from '../Streaming/ResolutionInput';
|
|
16
17
|
import { getResolution } from '../Streaming/RTMPStreaming';
|
|
17
18
|
import { ToastManager } from '../Toast/ToastManager';
|
|
18
19
|
import { AdditionalRoomState, getRecordingText } from './AdditionalRoomState';
|
|
19
|
-
import { useSidepaneToggle } from '../AppData/useSidepane';
|
|
20
20
|
import { useSetAppDataByKey } from '../AppData/useUISettings';
|
|
21
|
-
import {
|
|
21
|
+
import { formatTime } from '../../common/utils';
|
|
22
|
+
import { APP_DATA, RTMP_RECORD_DEFAULT_RESOLUTION } from '../../common/constants';
|
|
22
23
|
|
|
23
24
|
export const LiveStatus = () => {
|
|
24
25
|
const { isHLSRunning, isRTMPRunning } = useRecordingStreaming();
|
|
26
|
+
const hlsState = useHMSStore(selectHLSState);
|
|
27
|
+
const isMobile = useMedia(cssConfig.media.md);
|
|
28
|
+
const intervalRef = useRef(null);
|
|
29
|
+
|
|
30
|
+
const [liveTime, setLiveTime] = useState(0);
|
|
31
|
+
|
|
32
|
+
const startTimer = useCallback(() => {
|
|
33
|
+
intervalRef.current = setInterval(() => {
|
|
34
|
+
if (hlsState?.running) {
|
|
35
|
+
setLiveTime(Date.now() - hlsState?.variants[0]?.startedAt.getTime());
|
|
36
|
+
}
|
|
37
|
+
}, 1000);
|
|
38
|
+
}, [hlsState?.running, hlsState?.variants]);
|
|
39
|
+
|
|
40
|
+
useEffect(() => {
|
|
41
|
+
if (hlsState?.running) {
|
|
42
|
+
startTimer();
|
|
43
|
+
}
|
|
44
|
+
if (!hlsState?.running && intervalRef.current) {
|
|
45
|
+
clearInterval(intervalRef.current);
|
|
46
|
+
}
|
|
47
|
+
return () => {
|
|
48
|
+
if (intervalRef.current) {
|
|
49
|
+
clearInterval(intervalRef.current);
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
}, [hlsState.running, isMobile, startTimer]);
|
|
53
|
+
|
|
25
54
|
if (!isHLSRunning && !isRTMPRunning) {
|
|
26
55
|
return null;
|
|
27
56
|
}
|
|
28
57
|
return (
|
|
29
|
-
<Flex
|
|
58
|
+
<Flex
|
|
59
|
+
align="center"
|
|
60
|
+
gap="1"
|
|
61
|
+
css={{
|
|
62
|
+
border: '1px solid $border_default',
|
|
63
|
+
padding: '$4 $6 $4 $6',
|
|
64
|
+
borderRadius: '$1',
|
|
65
|
+
}}
|
|
66
|
+
>
|
|
30
67
|
<Box css={{ w: '$4', h: '$4', r: '$round', bg: '$alert_error_default', mr: '$2' }} />
|
|
31
|
-
<
|
|
32
|
-
|
|
33
|
-
<Text
|
|
34
|
-
|
|
35
|
-
</Text>
|
|
36
|
-
</Text>
|
|
68
|
+
<Flex align="center" gap="2">
|
|
69
|
+
<Text variant={!isMobile ? 'button' : 'body2'}>LIVE</Text>
|
|
70
|
+
<Text variant="caption">{hlsState?.variants?.length > 0 ? formatTime(liveTime) : ''}</Text>
|
|
71
|
+
</Flex>
|
|
37
72
|
</Flex>
|
|
38
73
|
);
|
|
39
74
|
};
|
|
@@ -41,6 +76,7 @@ export const LiveStatus = () => {
|
|
|
41
76
|
export const RecordingStatus = () => {
|
|
42
77
|
const { isBrowserRecordingOn, isServerRecordingOn, isHLSRecordingOn, isRecordingOn } = useRecordingStreaming();
|
|
43
78
|
const permissions = useHMSStore(selectPermissions);
|
|
79
|
+
const isMobile = useMedia(cssConfig.media.md);
|
|
44
80
|
|
|
45
81
|
if (
|
|
46
82
|
!isRecordingOn ||
|
|
@@ -50,8 +86,10 @@ export const RecordingStatus = () => {
|
|
|
50
86
|
value => !!value,
|
|
51
87
|
)
|
|
52
88
|
) {
|
|
53
|
-
|
|
89
|
+
// show recording icon in mobile without popover
|
|
90
|
+
if (!(isMobile && isRecordingOn)) return null;
|
|
54
91
|
}
|
|
92
|
+
|
|
55
93
|
return (
|
|
56
94
|
<Tooltip
|
|
57
95
|
title={getRecordingText({
|
|
@@ -60,28 +98,18 @@ export const RecordingStatus = () => {
|
|
|
60
98
|
isHLSRecordingOn,
|
|
61
99
|
})}
|
|
62
100
|
>
|
|
63
|
-
<
|
|
101
|
+
<Flex
|
|
64
102
|
css={{
|
|
65
103
|
color: '$alert_error_default',
|
|
104
|
+
alignItems: 'center',
|
|
66
105
|
}}
|
|
67
106
|
>
|
|
68
107
|
<RecordIcon width={24} height={24} />
|
|
69
|
-
</
|
|
108
|
+
</Flex>
|
|
70
109
|
</Tooltip>
|
|
71
110
|
);
|
|
72
111
|
};
|
|
73
112
|
|
|
74
|
-
const EndStream = () => {
|
|
75
|
-
const toggleStreaming = useSidepaneToggle(SIDE_PANE_OPTIONS.STREAMING);
|
|
76
|
-
|
|
77
|
-
return (
|
|
78
|
-
<Button data-testid="end_stream" variant="danger" icon onClick={toggleStreaming}>
|
|
79
|
-
<WrenchIcon />
|
|
80
|
-
Manage Stream
|
|
81
|
-
</Button>
|
|
82
|
-
);
|
|
83
|
-
};
|
|
84
|
-
|
|
85
113
|
const StartRecording = () => {
|
|
86
114
|
const permissions = useHMSStore(selectPermissions);
|
|
87
115
|
const [resolution, setResolution] = useState(RTMP_RECORD_DEFAULT_RESOLUTION);
|
|
@@ -192,24 +220,61 @@ const StartRecording = () => {
|
|
|
192
220
|
);
|
|
193
221
|
};
|
|
194
222
|
|
|
223
|
+
/**
|
|
224
|
+
* @description only start recording button will be shown.
|
|
225
|
+
*/
|
|
195
226
|
export const StreamActions = () => {
|
|
196
227
|
const isConnected = useHMSStore(selectIsConnectedToRoom);
|
|
197
|
-
const permissions = useHMSStore(selectPermissions);
|
|
198
228
|
const isMobile = useMedia(cssConfig.media.md);
|
|
199
|
-
const { isStreamingOn } = useRecordingStreaming();
|
|
200
229
|
const roomState = useHMSStore(selectRoomState);
|
|
201
230
|
|
|
202
231
|
return (
|
|
203
232
|
<Flex align="center" css={{ gap: '$4' }}>
|
|
204
233
|
<AdditionalRoomState />
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
{isConnected && (permissions.hlsStreaming || permissions.rtmpStreaming) && (
|
|
211
|
-
<Fragment>{isStreamingOn ? <EndStream /> : <GoLiveButton />}</Fragment>
|
|
234
|
+
{!isMobile && (
|
|
235
|
+
<Flex align="center" css={{ gap: '$4' }}>
|
|
236
|
+
<RecordingStatus />
|
|
237
|
+
{roomState !== HMSRoomState.Preview ? <LiveStatus /> : null}
|
|
238
|
+
</Flex>
|
|
212
239
|
)}
|
|
240
|
+
{isConnected && !isMobile ? <StartRecording /> : null}
|
|
213
241
|
</Flex>
|
|
214
242
|
);
|
|
215
243
|
};
|
|
244
|
+
|
|
245
|
+
export const StopRecordingInSheet = ({ onStopRecording, onClose }) => {
|
|
246
|
+
return (
|
|
247
|
+
<Sheet.Root open={true}>
|
|
248
|
+
<Sheet.Content>
|
|
249
|
+
<Sheet.Title css={{ p: '$10' }}>
|
|
250
|
+
<Flex direction="row" justify="between" css={{ w: '100%', c: '$alert_error_default' }}>
|
|
251
|
+
<Flex justify="start" align="center" gap="3">
|
|
252
|
+
<AlertTriangleIcon />
|
|
253
|
+
<Text variant="h5" css={{ c: '$alert_error_default' }}>
|
|
254
|
+
Stop Recording
|
|
255
|
+
</Text>
|
|
256
|
+
</Flex>
|
|
257
|
+
<Sheet.Close css={{ color: 'white' }} onClick={onClose}>
|
|
258
|
+
<CrossIcon />
|
|
259
|
+
</Sheet.Close>
|
|
260
|
+
</Flex>
|
|
261
|
+
</Sheet.Title>
|
|
262
|
+
<HorizontalDivider />
|
|
263
|
+
<Box as="div" css={{ p: '$10', overflowY: 'scroll', maxHeight: '70vh' }}>
|
|
264
|
+
<Text variant="caption" css={{ c: '$on_surface_medium', pb: '$8' }}>
|
|
265
|
+
Are you sure you want to stop recording? You can’t undo this action.
|
|
266
|
+
</Text>
|
|
267
|
+
<Button
|
|
268
|
+
variant="danger"
|
|
269
|
+
css={{ width: '100%' }}
|
|
270
|
+
type="submit"
|
|
271
|
+
data-testid="popup_change_btn"
|
|
272
|
+
onClick={onStopRecording}
|
|
273
|
+
>
|
|
274
|
+
Stop
|
|
275
|
+
</Button>
|
|
276
|
+
</Box>
|
|
277
|
+
</Sheet.Content>
|
|
278
|
+
</Sheet.Root>
|
|
279
|
+
);
|
|
280
|
+
};
|
|
@@ -2,10 +2,10 @@ import React from 'react';
|
|
|
2
2
|
import { useMedia } from 'react-use';
|
|
3
3
|
import { config as cssConfig, Flex } from '../../../';
|
|
4
4
|
import { EmojiReaction } from '../EmojiReaction';
|
|
5
|
+
import { ParticipantCount } from '../Footer/ParticipantList';
|
|
5
6
|
import { LeaveRoom } from '../LeaveRoom';
|
|
6
7
|
import MetaActions from '../MetaActions';
|
|
7
8
|
import { SpeakerTag } from './HeaderComponents';
|
|
8
|
-
import { ParticipantCount } from './ParticipantList';
|
|
9
9
|
import { LiveStatus, RecordingStatus, StreamActions } from './StreamActions';
|
|
10
10
|
|
|
11
11
|
export const StreamingHeader = () => {
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import {
|
|
3
|
+
DeviceType,
|
|
4
|
+
selectIsLocalVideoEnabled,
|
|
5
|
+
selectLocalVideoTrackID,
|
|
6
|
+
selectVideoTrackByID,
|
|
7
|
+
useDevices,
|
|
8
|
+
useHMSActions,
|
|
9
|
+
useHMSStore,
|
|
10
|
+
} from '@100mslive/react-sdk';
|
|
11
|
+
import { CameraFlipIcon, CheckIcon, CrossIcon, SpeakerIcon } from '@100mslive/react-icons';
|
|
12
|
+
import { HorizontalDivider } from '../../../Divider';
|
|
13
|
+
import { Label } from '../../../Label';
|
|
14
|
+
import { Box, Flex } from '../../../Layout';
|
|
15
|
+
import { Sheet } from '../../../Sheet';
|
|
16
|
+
import { Text } from '../../../Text';
|
|
17
|
+
import IconButton from '../../IconButton';
|
|
18
|
+
import { ToastManager } from '../Toast/ToastManager';
|
|
19
|
+
|
|
20
|
+
export const CamaraFlipActions = () => {
|
|
21
|
+
const actions = useHMSActions();
|
|
22
|
+
const { allDevices } = useDevices();
|
|
23
|
+
const { videoInput } = allDevices;
|
|
24
|
+
const isVideoOn = useHMSStore(selectIsLocalVideoEnabled);
|
|
25
|
+
|
|
26
|
+
const videoTrackId = useHMSStore(selectLocalVideoTrackID);
|
|
27
|
+
const localVideoTrack = useHMSStore(selectVideoTrackByID(videoTrackId));
|
|
28
|
+
|
|
29
|
+
return (
|
|
30
|
+
<Box>
|
|
31
|
+
<IconButton
|
|
32
|
+
disabled={!videoInput?.length || !isVideoOn || !localVideoTrack?.facingMode}
|
|
33
|
+
onClick={async () => {
|
|
34
|
+
try {
|
|
35
|
+
await actions.switchCamera();
|
|
36
|
+
} catch (e) {
|
|
37
|
+
ToastManager.addToast({
|
|
38
|
+
title: `Error while flipping camera ${e.message || ''}`,
|
|
39
|
+
variant: 'error',
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
}}
|
|
43
|
+
>
|
|
44
|
+
<CameraFlipIcon />
|
|
45
|
+
</IconButton>
|
|
46
|
+
</Box>
|
|
47
|
+
);
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
export const AudioOutputActions = () => {
|
|
51
|
+
const { allDevices, selectedDeviceIDs, updateDevice } = useDevices();
|
|
52
|
+
const { audioOutput } = allDevices;
|
|
53
|
+
// don't show speaker selector where the API is not supported, and use
|
|
54
|
+
// a generic word("Audio") for Mic. In some cases(Chrome Android for e.g.) this changes both mic and speaker keeping them in sync.
|
|
55
|
+
const shouldShowAudioOutput = 'setSinkId' in HTMLMediaElement.prototype;
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Chromium browsers return an audioOutput with empty label when no permissions are given
|
|
59
|
+
*/
|
|
60
|
+
const audioOutputFiltered = audioOutput?.filter(item => !!item.label) ?? [];
|
|
61
|
+
if (!shouldShowAudioOutput || !audioOutputFiltered?.length > 0) {
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
return (
|
|
65
|
+
<AudioOutputSelectionSheet
|
|
66
|
+
outputDevices={audioOutput}
|
|
67
|
+
outputSelected={selectedDeviceIDs.outputDevices}
|
|
68
|
+
onChange={async deviceId => {
|
|
69
|
+
try {
|
|
70
|
+
await updateDevice({
|
|
71
|
+
deviceId,
|
|
72
|
+
deviceType: DeviceType.audioOutput,
|
|
73
|
+
});
|
|
74
|
+
} catch (e) {
|
|
75
|
+
ToastManager.addToast({
|
|
76
|
+
title: `Error while changing audio output ${e.message || ''}`,
|
|
77
|
+
variant: 'error',
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
}}
|
|
81
|
+
>
|
|
82
|
+
<Box>
|
|
83
|
+
<IconButton>
|
|
84
|
+
<SpeakerIcon />
|
|
85
|
+
</IconButton>
|
|
86
|
+
</Box>
|
|
87
|
+
</AudioOutputSelectionSheet>
|
|
88
|
+
);
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
const AudioOutputSelectionSheet = ({ outputDevices, outputSelected, onChange, children }) => {
|
|
92
|
+
return (
|
|
93
|
+
<Sheet.Root>
|
|
94
|
+
<Sheet.Trigger asChild>{children}</Sheet.Trigger>
|
|
95
|
+
<Sheet.Content>
|
|
96
|
+
<Sheet.Title css={{ py: '$10', px: '$8', alignItems: 'center' }}>
|
|
97
|
+
<Flex direction="row" justify="between" css={{ w: '100%' }}>
|
|
98
|
+
<Text variant="h6" css={{ display: 'flex' }}>
|
|
99
|
+
Audio Output
|
|
100
|
+
</Text>
|
|
101
|
+
<Sheet.Close>
|
|
102
|
+
<IconButton as="div" data-testid="dialog_cross_icon">
|
|
103
|
+
<CrossIcon />
|
|
104
|
+
</IconButton>
|
|
105
|
+
</Sheet.Close>
|
|
106
|
+
</Flex>
|
|
107
|
+
</Sheet.Title>
|
|
108
|
+
<HorizontalDivider />
|
|
109
|
+
<Flex
|
|
110
|
+
direction="column"
|
|
111
|
+
css={{
|
|
112
|
+
px: '$8',
|
|
113
|
+
maxHeight: '80vh',
|
|
114
|
+
overflowY: 'scroll',
|
|
115
|
+
}}
|
|
116
|
+
>
|
|
117
|
+
{outputDevices.map(audioDevice => {
|
|
118
|
+
return (
|
|
119
|
+
<SelectWithLabel
|
|
120
|
+
label={audioDevice.label}
|
|
121
|
+
id={audioDevice.deviceId}
|
|
122
|
+
checked={audioDevice.deviceId === outputSelected}
|
|
123
|
+
onChange={() => onChange(audioDevice.deviceId)}
|
|
124
|
+
/>
|
|
125
|
+
);
|
|
126
|
+
})}
|
|
127
|
+
</Flex>
|
|
128
|
+
</Sheet.Content>
|
|
129
|
+
</Sheet.Root>
|
|
130
|
+
);
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
const SelectWithLabel = ({ label, icon = <></>, checked, id, onChange }) => {
|
|
134
|
+
return (
|
|
135
|
+
<Flex
|
|
136
|
+
align="center"
|
|
137
|
+
css={{
|
|
138
|
+
my: '$2',
|
|
139
|
+
py: '$8',
|
|
140
|
+
w: '100%',
|
|
141
|
+
borderBottom: '1px solid $border_default',
|
|
142
|
+
}}
|
|
143
|
+
onClick={onChange}
|
|
144
|
+
>
|
|
145
|
+
<Label
|
|
146
|
+
htmlFor={id}
|
|
147
|
+
css={{
|
|
148
|
+
fontSize: '$md',
|
|
149
|
+
fontWeight: '$semiBold',
|
|
150
|
+
color: checked ? '$on_surface_high' : '$on_surface_low',
|
|
151
|
+
cursor: 'pointer',
|
|
152
|
+
display: 'flex',
|
|
153
|
+
alignItems: 'center',
|
|
154
|
+
gap: '$8',
|
|
155
|
+
flex: '1 1 0',
|
|
156
|
+
}}
|
|
157
|
+
>
|
|
158
|
+
{icon}
|
|
159
|
+
{label}
|
|
160
|
+
</Label>
|
|
161
|
+
{checked && <CheckIcon width={24} height={24} />}
|
|
162
|
+
</Flex>
|
|
163
|
+
);
|
|
164
|
+
};
|
|
@@ -46,13 +46,12 @@ export const IconButtonWithOptions = ({
|
|
|
46
46
|
onClick = () => {
|
|
47
47
|
return;
|
|
48
48
|
},
|
|
49
|
-
key = '',
|
|
50
49
|
}) => {
|
|
51
50
|
const bgCss = { backgroundColor: active ? '$transparent' : '$secondary_dim' };
|
|
52
51
|
const iconCss = { color: active ? '$on_surface_high' : '$on_primary_high' };
|
|
53
52
|
return (
|
|
54
53
|
<Flex>
|
|
55
|
-
<IconSection css={bgCss} onClick={onClick}
|
|
54
|
+
<IconSection css={bgCss} onClick={onClick}>
|
|
56
55
|
<Tooltip disabled={!tooltipMessage} title={tooltipMessage}>
|
|
57
56
|
<Flex align="center" justify="center" css={iconCss}>
|
|
58
57
|
{icon}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Box, Flex } from '../../Layout';
|
|
3
|
+
import { Text } from '../../Text';
|
|
4
|
+
|
|
5
|
+
export const LeaveCard = ({ icon, title, subtitle, onClick, bg, titleColor, subtitleColor, css = {} }) => {
|
|
6
|
+
return (
|
|
7
|
+
<Flex css={{ p: '$10', flexGrow: 1, gap: '$8', bg, ...css }} onClick={onClick}>
|
|
8
|
+
<Box css={{ color: titleColor }}>{icon}</Box>
|
|
9
|
+
<Box css={{ gap: '$2' }}>
|
|
10
|
+
<Text variant="lg" css={{ color: titleColor }}>
|
|
11
|
+
{title}
|
|
12
|
+
</Text>
|
|
13
|
+
<Text variant="sm" css={{ color: subtitleColor }}>
|
|
14
|
+
{subtitle}
|
|
15
|
+
</Text>
|
|
16
|
+
</Box>
|
|
17
|
+
</Flex>
|
|
18
|
+
);
|
|
19
|
+
};
|