@100mslive/roomkit-react 0.1.4-alpha.1 → 0.1.5
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
};
|