@100mslive/roomkit-react 0.3.3-alpha.2 → 0.3.3-alpha.3
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-GI5NXBYN.js → HLSView-BCIIVR2T.js} +331 -166
- package/dist/HLSView-BCIIVR2T.js.map +7 -0
- package/dist/IconButton/IconButton.d.ts +1 -1
- package/dist/Modal/Dialog.d.ts +1 -1
- package/dist/Prebuilt/IconButton.d.ts +2 -3
- package/dist/Prebuilt/components/Footer/ChatToggle.d.ts +3 -1
- package/dist/Prebuilt/components/HMSVideo/PlayPauseButton.d.ts +2 -2
- package/dist/Prebuilt/components/HMSVideo/PlayPauseSeekControls.d.ts +14 -0
- package/dist/Prebuilt/components/HMSVideo/{SeekControls.d.ts → SeekControl.d.ts} +2 -2
- package/dist/Prebuilt/components/HMSVideo/index.d.ts +15 -11
- package/dist/Prebuilt/components/Leave/LeaveAtoms.d.ts +2 -2
- package/dist/Prebuilt/components/VideoLayouts/WhiteboardLayout.d.ts +3 -0
- package/dist/Sheet/Sheet.d.ts +1 -1
- package/dist/{chunk-KUFQ5ONV.js → chunk-W47ZJGSD.js} +207 -163
- package/dist/chunk-W47ZJGSD.js.map +7 -0
- package/dist/index.cjs.js +918 -694
- package/dist/index.cjs.js.map +4 -4
- package/dist/index.js +1 -1
- package/dist/meta.cjs.json +193 -109
- package/dist/meta.esbuild.json +207 -122
- package/package.json +6 -6
- package/src/IconButton/IconButton.tsx +2 -7
- package/src/Prebuilt/IconButton.tsx +6 -10
- package/src/Prebuilt/components/Footer/ChatToggle.tsx +2 -2
- package/src/Prebuilt/components/Footer/WhiteboardToggle.tsx +17 -3
- package/src/Prebuilt/components/HMSVideo/HMSVideo.jsx +1 -0
- package/src/Prebuilt/components/HMSVideo/PlayPauseButton.tsx +2 -2
- package/src/Prebuilt/components/HMSVideo/PlayPauseSeekControls.tsx +158 -0
- package/src/Prebuilt/components/HMSVideo/{SeekControls.tsx → SeekControl.tsx} +2 -2
- package/src/Prebuilt/components/HMSVideo/VideoProgress.tsx +7 -3
- package/src/Prebuilt/components/HMSVideo/index.ts +5 -4
- package/src/Prebuilt/components/IconButtonWithOptions/IconButtonWithOptions.tsx +7 -7
- package/src/Prebuilt/components/VideoLayouts/GridLayout.tsx +27 -4
- package/src/Prebuilt/components/VideoLayouts/WhiteboardLayout.tsx +95 -0
- package/src/Prebuilt/components/hooks/useCloseScreenshareWhiteboard.tsx +13 -5
- package/src/Prebuilt/layouts/HLSView.jsx +115 -78
- package/src/Prebuilt/layouts/VideoStreamingSection.tsx +1 -17
- package/dist/HLSView-GI5NXBYN.js.map +0 -7
- package/dist/Prebuilt/layouts/WhiteboardView.d.ts +0 -2
- package/dist/chunk-KUFQ5ONV.js.map +0 -7
- package/src/Prebuilt/layouts/WhiteboardView.tsx +0 -69
@@ -25,19 +25,14 @@ export const IconButton = styled('button', {
|
|
25
25
|
'&[disabled]': {
|
26
26
|
opacity: 0.5,
|
27
27
|
cursor: 'not-allowed',
|
28
|
+
backgroundColor: '$secondary_dim',
|
29
|
+
color: '$on_primary_high',
|
28
30
|
},
|
29
31
|
'&:focus': {
|
30
32
|
outline: 'none',
|
31
33
|
},
|
32
34
|
variants: {
|
33
35
|
active: {
|
34
|
-
false: {
|
35
|
-
backgroundColor: '$secondary_dim',
|
36
|
-
color: '$on_primary_high',
|
37
|
-
'&:not([disabled]):hover': {
|
38
|
-
backgroundColor: '$secondary_default',
|
39
|
-
},
|
40
|
-
},
|
41
36
|
true: {
|
42
37
|
'&:not([disabled]):hover': {
|
43
38
|
backgroundColor: '$on_surface_low',
|
@@ -7,22 +7,18 @@ const IconButton = styled(BaseIconButton, {
|
|
7
7
|
border: '1px solid $border_bright',
|
8
8
|
bg: '$background_dim',
|
9
9
|
r: '$1',
|
10
|
+
'&[disabled]': {
|
11
|
+
opacity: 0.5,
|
12
|
+
cursor: 'not-allowed',
|
13
|
+
backgroundColor: '$secondary_dim',
|
14
|
+
color: '$on_primary_high',
|
15
|
+
},
|
10
16
|
variants: {
|
11
17
|
active: {
|
12
18
|
true: {
|
13
19
|
color: '$on_surface_high',
|
14
20
|
backgroundColor: 'transparent',
|
15
21
|
},
|
16
|
-
false: {
|
17
|
-
border: '1px solid transparent',
|
18
|
-
color: '$on_primary_high',
|
19
|
-
},
|
20
|
-
},
|
21
|
-
disabled: {
|
22
|
-
true: {
|
23
|
-
backgroundColor: '$surface_brighter',
|
24
|
-
color: '$on_surface_low',
|
25
|
-
},
|
26
22
|
},
|
27
23
|
},
|
28
24
|
});
|
@@ -9,7 +9,7 @@ import { useIsSidepaneTypeOpen, useSidepaneToggle } from '../AppData/useSidepane
|
|
9
9
|
// @ts-ignore: No implicit Any
|
10
10
|
import { SIDE_PANE_OPTIONS } from '../../common/constants';
|
11
11
|
|
12
|
-
export const ChatToggle = () => {
|
12
|
+
export const ChatToggle = ({ onClick }: { onClick?: () => void }) => {
|
13
13
|
const countUnreadMessages = useHMSStore(selectUnreadHMSMessagesCount);
|
14
14
|
const isChatOpen = useIsSidepaneTypeOpen(SIDE_PANE_OPTIONS.CHAT);
|
15
15
|
const toggleChat = useSidepaneToggle(SIDE_PANE_OPTIONS.CHAT);
|
@@ -21,7 +21,7 @@ export const ChatToggle = () => {
|
|
21
21
|
}}
|
22
22
|
>
|
23
23
|
<Tooltip key="chat" title={`${isChatOpen ? 'Close' : 'Open'} chat`}>
|
24
|
-
<IconButton onClick={toggleChat} active={!isChatOpen} data-testid="chat_btn">
|
24
|
+
<IconButton onClick={() => (onClick ? onClick() : toggleChat())} active={!isChatOpen} data-testid="chat_btn">
|
25
25
|
<ChatIcon />
|
26
26
|
</IconButton>
|
27
27
|
</Tooltip>
|
@@ -1,5 +1,5 @@
|
|
1
1
|
import React from 'react';
|
2
|
-
import { useWhiteboard } from '@100mslive/react-sdk';
|
2
|
+
import { useScreenShare, useWhiteboard } from '@100mslive/react-sdk';
|
3
3
|
import { PencilDrawIcon } from '@100mslive/react-icons';
|
4
4
|
import { Tooltip } from '../../..';
|
5
5
|
// @ts-ignore: No implicit Any
|
@@ -9,14 +9,28 @@ import { ToastManager } from '../Toast/ToastManager';
|
|
9
9
|
|
10
10
|
export const WhiteboardToggle = () => {
|
11
11
|
const { toggle, open, isOwner } = useWhiteboard();
|
12
|
+
const { screenSharingPeerId, amIScreenSharing } = useScreenShare();
|
13
|
+
const remoteScreenShare = screenSharingPeerId && !amIScreenSharing;
|
14
|
+
const disabled = remoteScreenShare || (open && !isOwner);
|
15
|
+
|
12
16
|
if (!toggle) {
|
13
17
|
return null;
|
14
18
|
}
|
15
19
|
|
16
20
|
return (
|
17
|
-
<Tooltip
|
21
|
+
<Tooltip
|
22
|
+
key="whiteboard"
|
23
|
+
title={
|
24
|
+
remoteScreenShare
|
25
|
+
? 'Cannot open whiteboard when viewing a shared screen'
|
26
|
+
: `${open ? 'Close' : 'Open'} Whiteboard`
|
27
|
+
}
|
28
|
+
>
|
18
29
|
<IconButton
|
19
30
|
onClick={async () => {
|
31
|
+
if (disabled) {
|
32
|
+
return;
|
33
|
+
}
|
20
34
|
try {
|
21
35
|
await toggle();
|
22
36
|
} catch (error) {
|
@@ -24,7 +38,7 @@ export const WhiteboardToggle = () => {
|
|
24
38
|
}
|
25
39
|
}}
|
26
40
|
active={!open}
|
27
|
-
disabled={
|
41
|
+
disabled={disabled}
|
28
42
|
data-testid="whiteboard_btn"
|
29
43
|
>
|
30
44
|
<PencilDrawIcon />
|
@@ -9,8 +9,8 @@ export const PlayPauseButton = ({
|
|
9
9
|
height = 20,
|
10
10
|
}: {
|
11
11
|
isPaused: boolean;
|
12
|
-
width
|
13
|
-
height
|
12
|
+
width?: number;
|
13
|
+
height?: number;
|
14
14
|
}) => {
|
15
15
|
const { hlsPlayer } = useHMSPlayerContext();
|
16
16
|
const onClick = async (event: MouseEvent) => {
|
@@ -0,0 +1,158 @@
|
|
1
|
+
import React from 'react';
|
2
|
+
import { useMedia } from 'react-use';
|
3
|
+
import { BackwardArrowIcon, ForwardArrowIcon } from '@100mslive/react-icons';
|
4
|
+
import { Box, Flex } from '../../../Layout';
|
5
|
+
import { Text } from '../../../Text';
|
6
|
+
import { config } from '../../../Theme';
|
7
|
+
import { PlayPauseButton } from './PlayPauseButton';
|
8
|
+
import { SeekControl } from './SeekControl';
|
9
|
+
import { useIsLandscape } from '../../common/hooks';
|
10
|
+
|
11
|
+
// desktop buttons
|
12
|
+
export const PlayPauseSeekControls = ({
|
13
|
+
isPaused,
|
14
|
+
onSeekTo,
|
15
|
+
}: {
|
16
|
+
isPaused: boolean;
|
17
|
+
onSeekTo: (value: number) => void;
|
18
|
+
}) => {
|
19
|
+
return (
|
20
|
+
<>
|
21
|
+
<SeekControl
|
22
|
+
onClick={e => {
|
23
|
+
e.stopPropagation();
|
24
|
+
onSeekTo(-10);
|
25
|
+
}}
|
26
|
+
title="backward"
|
27
|
+
>
|
28
|
+
<BackwardArrowIcon width={20} height={20} />
|
29
|
+
</SeekControl>
|
30
|
+
<PlayPauseButton isPaused={isPaused} />
|
31
|
+
<SeekControl
|
32
|
+
onClick={e => {
|
33
|
+
e.stopPropagation();
|
34
|
+
onSeekTo(10);
|
35
|
+
}}
|
36
|
+
title="forward"
|
37
|
+
>
|
38
|
+
<ForwardArrowIcon width={20} height={20} />
|
39
|
+
</SeekControl>
|
40
|
+
</>
|
41
|
+
);
|
42
|
+
};
|
43
|
+
|
44
|
+
// overlay handlers
|
45
|
+
export const PlayPauseSeekOverlayControls = ({
|
46
|
+
isPaused,
|
47
|
+
showControls,
|
48
|
+
hoverControlsVisible,
|
49
|
+
}: {
|
50
|
+
isPaused: boolean;
|
51
|
+
showControls: boolean;
|
52
|
+
hoverControlsVisible: {
|
53
|
+
seekBackward: boolean;
|
54
|
+
seekForward: boolean;
|
55
|
+
pausePlay: boolean;
|
56
|
+
};
|
57
|
+
}) => {
|
58
|
+
const isMobile = useMedia(config.media.md);
|
59
|
+
const isLandscape = useIsLandscape();
|
60
|
+
|
61
|
+
if (!isMobile && !isLandscape) {
|
62
|
+
// show desktopOverflow icons
|
63
|
+
return (
|
64
|
+
<>
|
65
|
+
<Flex
|
66
|
+
css={{
|
67
|
+
bg: 'rgba(0, 0, 0, 0.6)',
|
68
|
+
r: '$round',
|
69
|
+
size: '$24',
|
70
|
+
visibility: hoverControlsVisible.seekBackward ? `` : `hidden`,
|
71
|
+
opacity: hoverControlsVisible.seekBackward ? `1` : '0',
|
72
|
+
}}
|
73
|
+
direction="column"
|
74
|
+
align="center"
|
75
|
+
>
|
76
|
+
<SeekControl title="backward">
|
77
|
+
<BackwardArrowIcon width={52} height={52} />
|
78
|
+
</SeekControl>
|
79
|
+
<Text variant="body2" css={{ fontWeight: '$regular' }}>
|
80
|
+
10 secs
|
81
|
+
</Text>
|
82
|
+
</Flex>
|
83
|
+
<Box
|
84
|
+
css={{
|
85
|
+
bg: 'rgba(0, 0, 0, 0.6)',
|
86
|
+
r: '$round',
|
87
|
+
visibility: hoverControlsVisible.pausePlay ? `` : `hidden`,
|
88
|
+
opacity: hoverControlsVisible.pausePlay ? `1` : '0',
|
89
|
+
}}
|
90
|
+
>
|
91
|
+
<PlayPauseButton isPaused={isPaused} width={48} height={48} />
|
92
|
+
</Box>
|
93
|
+
<Flex
|
94
|
+
css={{
|
95
|
+
bg: 'rgba(0, 0, 0, 0.6)',
|
96
|
+
r: '$round',
|
97
|
+
size: '$24',
|
98
|
+
visibility: hoverControlsVisible.seekForward ? `` : `hidden`,
|
99
|
+
opacity: hoverControlsVisible.seekForward ? `1` : '0',
|
100
|
+
}}
|
101
|
+
direction="column"
|
102
|
+
align="center"
|
103
|
+
>
|
104
|
+
<SeekControl title="forward">
|
105
|
+
<ForwardArrowIcon width={52} height={52} />
|
106
|
+
</SeekControl>
|
107
|
+
<Text variant="body2" css={{ fontWeight: '$regular' }}>
|
108
|
+
10 secs
|
109
|
+
</Text>
|
110
|
+
</Flex>
|
111
|
+
</>
|
112
|
+
);
|
113
|
+
}
|
114
|
+
|
115
|
+
return (
|
116
|
+
<Flex
|
117
|
+
align="center"
|
118
|
+
justify="center"
|
119
|
+
css={{
|
120
|
+
position: 'absolute',
|
121
|
+
bg: '#00000066',
|
122
|
+
display: 'inline-flex',
|
123
|
+
gap: '$2',
|
124
|
+
zIndex: 1,
|
125
|
+
size: '100%',
|
126
|
+
visibility: showControls ? `` : `hidden`,
|
127
|
+
opacity: showControls ? `1` : '0',
|
128
|
+
}}
|
129
|
+
>
|
130
|
+
<SeekControl
|
131
|
+
title="backward"
|
132
|
+
css={{
|
133
|
+
visibility: hoverControlsVisible.seekBackward ? `` : `hidden`,
|
134
|
+
opacity: hoverControlsVisible.seekBackward ? `1` : '0',
|
135
|
+
}}
|
136
|
+
>
|
137
|
+
<BackwardArrowIcon width={32} height={32} />
|
138
|
+
</SeekControl>
|
139
|
+
<Box
|
140
|
+
css={{
|
141
|
+
bg: 'rgba(0, 0, 0, 0.6)',
|
142
|
+
r: '$round',
|
143
|
+
}}
|
144
|
+
>
|
145
|
+
<PlayPauseButton isPaused={isPaused} width={48} height={48} />
|
146
|
+
</Box>
|
147
|
+
<SeekControl
|
148
|
+
title="forward"
|
149
|
+
css={{
|
150
|
+
visibility: hoverControlsVisible.seekForward ? `` : `hidden`,
|
151
|
+
opacity: hoverControlsVisible.seekForward ? `1` : '0',
|
152
|
+
}}
|
153
|
+
>
|
154
|
+
<ForwardArrowIcon width={32} height={32} />
|
155
|
+
</SeekControl>
|
156
|
+
</Flex>
|
157
|
+
);
|
158
|
+
};
|
@@ -1,7 +1,7 @@
|
|
1
1
|
import React, { MouseEventHandler } from 'react';
|
2
2
|
import { IconButton, Tooltip } from '../../..';
|
3
3
|
|
4
|
-
export const
|
4
|
+
export const SeekControl = ({
|
5
5
|
title,
|
6
6
|
onClick,
|
7
7
|
children,
|
@@ -9,7 +9,7 @@ export const SeekControls = ({
|
|
9
9
|
}: {
|
10
10
|
title: string;
|
11
11
|
onClick?: MouseEventHandler<HTMLButtonElement>;
|
12
|
-
css
|
12
|
+
css?: any;
|
13
13
|
children: React.ReactNode;
|
14
14
|
}) => {
|
15
15
|
return (
|
@@ -25,8 +25,12 @@ export const VideoProgress = ({
|
|
25
25
|
if (videoEl.buffered.length > 0) {
|
26
26
|
bufferProgress = Math.floor(getPercentage(videoEl.buffered?.end(0), duration));
|
27
27
|
}
|
28
|
-
|
29
|
-
|
28
|
+
if (!isNaN(videoProgress)) {
|
29
|
+
setVideoProgress(videoProgress);
|
30
|
+
}
|
31
|
+
if (!isNaN(bufferProgress)) {
|
32
|
+
setBufferProgress(bufferProgress);
|
33
|
+
}
|
30
34
|
}, [videoEl]);
|
31
35
|
const timeupdateHandler = useCallback(() => {
|
32
36
|
if (!videoEl || seekProgress) {
|
@@ -42,7 +46,7 @@ export const VideoProgress = ({
|
|
42
46
|
return function cleanup() {
|
43
47
|
videoEl?.removeEventListener('timeupdate', timeupdateHandler);
|
44
48
|
};
|
45
|
-
}, [timeupdateHandler, videoEl]);
|
49
|
+
}, [setProgress, timeupdateHandler, videoEl]);
|
46
50
|
|
47
51
|
const onProgress = (progress: number[]) => {
|
48
52
|
const progress1 = Math.floor(getPercentage(progress[0], 100));
|
@@ -2,15 +2,13 @@
|
|
2
2
|
import { LeftControls, RightControls, VideoControls } from './Controls';
|
3
3
|
// @ts-ignore
|
4
4
|
import { HMSVideo } from './HMSVideo';
|
5
|
-
import {
|
6
|
-
import { SeekControls } from './SeekControls';
|
5
|
+
import { PlayPauseSeekControls, PlayPauseSeekOverlayControls } from './PlayPauseSeekControls';
|
7
6
|
import { VideoProgress } from './VideoProgress';
|
8
7
|
import { VideoTime } from './VideoTime';
|
9
8
|
import { VolumeControl } from './VolumeControl';
|
10
9
|
|
11
10
|
export const HMSVideoPlayer = {
|
12
11
|
Root: HMSVideo,
|
13
|
-
PlayPauseButton: PlayPauseButton,
|
14
12
|
Progress: VideoProgress,
|
15
13
|
Duration: VideoTime,
|
16
14
|
Volume: VolumeControl,
|
@@ -19,5 +17,8 @@ export const HMSVideoPlayer = {
|
|
19
17
|
Left: LeftControls,
|
20
18
|
Right: RightControls,
|
21
19
|
},
|
22
|
-
|
20
|
+
PlayPauseSeekControls: {
|
21
|
+
Overlay: PlayPauseSeekOverlayControls,
|
22
|
+
Button: PlayPauseSeekControls,
|
23
|
+
},
|
23
24
|
};
|
@@ -25,9 +25,9 @@ const IconSection = styled(IconButton, {
|
|
25
25
|
p: '$4',
|
26
26
|
r: '$1',
|
27
27
|
bg: 'transparent',
|
28
|
-
borderTopRightRadius: 0,
|
28
|
+
borderTopRightRadius: '0 !important',
|
29
29
|
borderColor: '$border_bright',
|
30
|
-
borderBottomRightRadius: 0,
|
30
|
+
borderBottomRightRadius: '0 !important',
|
31
31
|
position: 'relative',
|
32
32
|
'&:not([disabled]):focus-visible': {
|
33
33
|
zIndex: 1,
|
@@ -41,8 +41,8 @@ const IconSection = styled(IconButton, {
|
|
41
41
|
...variants,
|
42
42
|
hideOptions: {
|
43
43
|
true: {
|
44
|
-
borderTopRightRadius: '$1',
|
45
|
-
borderBottomRightRadius: '$1',
|
44
|
+
borderTopRightRadius: '$1 !important',
|
45
|
+
borderBottomRightRadius: '$1 !important',
|
46
46
|
},
|
47
47
|
},
|
48
48
|
},
|
@@ -53,10 +53,10 @@ const OptionsSection = styled(IconButton, {
|
|
53
53
|
h: '$14',
|
54
54
|
p: '$4 $2',
|
55
55
|
r: '$1',
|
56
|
-
borderTopLeftRadius: 0,
|
56
|
+
borderTopLeftRadius: '0 !important',
|
57
57
|
borderColor: '$border_bright',
|
58
|
-
borderBottomLeftRadius: 0,
|
59
|
-
borderLeftWidth: 0,
|
58
|
+
borderBottomLeftRadius: '0 !important',
|
59
|
+
borderLeftWidth: '0 !important',
|
60
60
|
position: 'relative',
|
61
61
|
'&:not([disabled]):focus-visible': {
|
62
62
|
zIndex: 1,
|
@@ -5,12 +5,14 @@ import {
|
|
5
5
|
selectLocalPeerRoleName,
|
6
6
|
selectPeers,
|
7
7
|
selectPeerScreenSharing,
|
8
|
+
selectWhiteboard,
|
8
9
|
useHMSStore,
|
9
10
|
useHMSVanillaStore,
|
10
11
|
} from '@100mslive/react-sdk';
|
11
12
|
import { EqualProminence } from './EqualProminence';
|
12
13
|
import { RoleProminence } from './RoleProminence';
|
13
14
|
import { ScreenshareLayout } from './ScreenshareLayout';
|
15
|
+
import { WhiteboardLayout } from './WhiteboardLayout';
|
14
16
|
// @ts-ignore: No implicit Any
|
15
17
|
import { usePinnedTrack, useSetAppDataByKey } from '../AppData/useUISettings';
|
16
18
|
import { VideoTileContext } from '../hooks/useVideoTileLayout';
|
@@ -40,6 +42,7 @@ export const GridLayout = ({
|
|
40
42
|
hide_metadata_on_tile = false,
|
41
43
|
}: GridLayoutProps) => {
|
42
44
|
const peerSharing = useHMSStore(selectPeerScreenSharing);
|
45
|
+
const whiteboard = useHMSStore(selectWhiteboard);
|
43
46
|
const pinnedTrack = usePinnedTrack();
|
44
47
|
const peers = useHMSStore(selectPeers);
|
45
48
|
const localPeerRole = useHMSStore(selectLocalPeerRoleName);
|
@@ -53,9 +56,9 @@ export const GridLayout = ({
|
|
53
56
|
)) ||
|
54
57
|
pinnedTrack;
|
55
58
|
const updatedPeers = useMemo(() => {
|
56
|
-
// remove screenshare peer from active speaker sorting
|
57
|
-
if (activeScreensharePeerId) {
|
58
|
-
return peers.filter(peer => peer.id !== activeScreensharePeerId);
|
59
|
+
// remove screenshare/whiteboard peer from active speaker sorting
|
60
|
+
if (activeScreensharePeerId || whiteboard?.open) {
|
61
|
+
return peers.filter(peer => peer.id !== activeScreensharePeerId || peer.customerUserId !== whiteboard?.owner);
|
59
62
|
}
|
60
63
|
if (isInsetEnabled) {
|
61
64
|
const isLocalPeerPinned = localPeerID === pinnedTrack?.peerId;
|
@@ -67,7 +70,16 @@ export const GridLayout = ({
|
|
67
70
|
}
|
68
71
|
}
|
69
72
|
return peers;
|
70
|
-
}, [
|
73
|
+
}, [
|
74
|
+
isInsetEnabled,
|
75
|
+
whiteboard,
|
76
|
+
activeScreensharePeerId,
|
77
|
+
localPeerRole,
|
78
|
+
localPeerID,
|
79
|
+
prominentRoles,
|
80
|
+
peers,
|
81
|
+
pinnedTrack,
|
82
|
+
]);
|
71
83
|
const vanillaStore = useHMSVanillaStore();
|
72
84
|
const [sortedPeers, setSortedPeers] = useState(updatedPeers);
|
73
85
|
const peersSorter = useMemo(() => new PeersSorter(vanillaStore), [vanillaStore]);
|
@@ -104,6 +116,17 @@ export const GridLayout = ({
|
|
104
116
|
/>
|
105
117
|
</VideoTileContext.Provider>
|
106
118
|
);
|
119
|
+
} else if (whiteboard?.open) {
|
120
|
+
return (
|
121
|
+
<VideoTileContext.Provider value={tileLayout}>
|
122
|
+
<WhiteboardLayout
|
123
|
+
peers={sortedPeers}
|
124
|
+
onPageSize={setPageSize}
|
125
|
+
onPageChange={setMainPage}
|
126
|
+
edgeToEdge={edge_to_edge}
|
127
|
+
/>
|
128
|
+
</VideoTileContext.Provider>
|
129
|
+
);
|
107
130
|
} else if (isRoleProminence) {
|
108
131
|
return (
|
109
132
|
<VideoTileContext.Provider value={tileLayout}>
|
@@ -0,0 +1,95 @@
|
|
1
|
+
import React, { useEffect, useMemo } from 'react';
|
2
|
+
import { useMedia } from 'react-use';
|
3
|
+
import { selectPeerByCondition, selectWhiteboard, useHMSStore, useWhiteboard } from '@100mslive/react-sdk';
|
4
|
+
import { Box } from '../../../Layout';
|
5
|
+
import { config as cssConfig } from '../../../Theme';
|
6
|
+
import { InsetTile } from '../InsetTile';
|
7
|
+
import { SecondaryTiles } from '../SecondaryTiles';
|
8
|
+
import { LayoutMode } from '../Settings/LayoutSettings';
|
9
|
+
import { LayoutProps } from './interface';
|
10
|
+
import { ProminenceLayout } from './ProminenceLayout';
|
11
|
+
// @ts-ignore: No implicit Any
|
12
|
+
import { useSetUiSettings } from '../AppData/useUISettings';
|
13
|
+
import { UI_SETTINGS } from '../../common/constants';
|
14
|
+
|
15
|
+
const WhiteboardEmbed = () => {
|
16
|
+
const isMobile = useMedia(cssConfig.media.md);
|
17
|
+
const { iframeRef } = useWhiteboard(isMobile);
|
18
|
+
|
19
|
+
return (
|
20
|
+
<Box
|
21
|
+
css={{
|
22
|
+
mx: '$8',
|
23
|
+
flex: '3 1 0',
|
24
|
+
'@lg': {
|
25
|
+
flex: '2 1 0',
|
26
|
+
display: 'flex',
|
27
|
+
alignItems: 'center',
|
28
|
+
},
|
29
|
+
}}
|
30
|
+
>
|
31
|
+
<iframe
|
32
|
+
title="Whiteboard View"
|
33
|
+
ref={iframeRef}
|
34
|
+
style={{
|
35
|
+
width: '100%',
|
36
|
+
height: '100%',
|
37
|
+
border: 0,
|
38
|
+
borderRadius: '0.75rem',
|
39
|
+
}}
|
40
|
+
allow="autoplay; clipboard-write;"
|
41
|
+
referrerPolicy="no-referrer"
|
42
|
+
/>
|
43
|
+
</Box>
|
44
|
+
);
|
45
|
+
};
|
46
|
+
|
47
|
+
export const WhiteboardLayout = ({ peers, onPageChange, onPageSize, edgeToEdge }: LayoutProps) => {
|
48
|
+
const whiteboard = useHMSStore(selectWhiteboard);
|
49
|
+
const whiteboardOwner = useHMSStore(selectPeerByCondition(peer => peer.customerUserId === whiteboard?.owner));
|
50
|
+
const [layoutMode, setLayoutMode] = useSetUiSettings(UI_SETTINGS.layoutMode);
|
51
|
+
const isMobile = useMedia(cssConfig.media.md);
|
52
|
+
const hasSidebar = !isMobile && layoutMode === LayoutMode.SIDEBAR;
|
53
|
+
const secondaryPeers = useMemo(() => {
|
54
|
+
if (layoutMode === LayoutMode.SPOTLIGHT) {
|
55
|
+
return [];
|
56
|
+
}
|
57
|
+
if (isMobile || layoutMode === LayoutMode.SIDEBAR) {
|
58
|
+
return whiteboardOwner
|
59
|
+
? [whiteboardOwner, ...peers.filter(p => p.id !== whiteboardOwner?.id)] //keep active sharing peer as first tile
|
60
|
+
: peers;
|
61
|
+
}
|
62
|
+
return peers.filter(p => p.id !== whiteboardOwner?.id);
|
63
|
+
}, [whiteboardOwner, peers, isMobile, layoutMode]);
|
64
|
+
|
65
|
+
useEffect(() => {
|
66
|
+
if (isMobile) {
|
67
|
+
setLayoutMode(LayoutMode.GALLERY);
|
68
|
+
return;
|
69
|
+
}
|
70
|
+
if (layoutMode === LayoutMode.SIDEBAR) {
|
71
|
+
return;
|
72
|
+
}
|
73
|
+
setLayoutMode(LayoutMode.SIDEBAR);
|
74
|
+
return () => {
|
75
|
+
// reset to gallery once whiteboard is stopped
|
76
|
+
setLayoutMode(LayoutMode.GALLERY);
|
77
|
+
};
|
78
|
+
}, [isMobile]); // eslint-disable-line react-hooks/exhaustive-deps
|
79
|
+
|
80
|
+
return (
|
81
|
+
<ProminenceLayout.Root edgeToEdge={edgeToEdge} hasSidebar={hasSidebar}>
|
82
|
+
<ProminenceLayout.ProminentSection>
|
83
|
+
<WhiteboardEmbed />
|
84
|
+
</ProminenceLayout.ProminentSection>
|
85
|
+
<SecondaryTiles
|
86
|
+
peers={secondaryPeers}
|
87
|
+
onPageChange={onPageChange}
|
88
|
+
onPageSize={onPageSize}
|
89
|
+
edgeToEdge={edgeToEdge}
|
90
|
+
hasSidebar={hasSidebar}
|
91
|
+
/>
|
92
|
+
{layoutMode === LayoutMode.SPOTLIGHT && whiteboardOwner && <InsetTile peerId={whiteboardOwner?.id} />}
|
93
|
+
</ProminenceLayout.Root>
|
94
|
+
);
|
95
|
+
};
|
@@ -6,19 +6,27 @@ import { useScreenShare, useWhiteboard } from '@100mslive/react-sdk';
|
|
6
6
|
* close existing screenshare or whiteboard when the other is started
|
7
7
|
*/
|
8
8
|
export const useCloseScreenshareWhiteboard = () => {
|
9
|
-
const { amIScreenSharing, toggleScreenShare } = useScreenShare();
|
9
|
+
const { amIScreenSharing, screenSharingPeerId, toggleScreenShare } = useScreenShare();
|
10
10
|
const { isOwner: isWhiteboardOwner, toggle: toggleWhiteboard } = useWhiteboard();
|
11
|
-
const prevScreenSharer = usePrevious(
|
11
|
+
const prevScreenSharer = usePrevious(screenSharingPeerId);
|
12
12
|
const prevWhiteboardOwner = usePrevious(isWhiteboardOwner);
|
13
13
|
|
14
14
|
// if both screenshare and whiteboard are open, close the one that was open earlier
|
15
15
|
useEffect(() => {
|
16
|
-
if (isWhiteboardOwner &&
|
17
|
-
if (prevScreenSharer && !prevWhiteboardOwner) {
|
16
|
+
if (isWhiteboardOwner && screenSharingPeerId) {
|
17
|
+
if (prevScreenSharer && amIScreenSharing && !prevWhiteboardOwner) {
|
18
18
|
toggleScreenShare?.();
|
19
19
|
} else if (prevWhiteboardOwner && !prevScreenSharer) {
|
20
20
|
toggleWhiteboard?.();
|
21
21
|
}
|
22
22
|
}
|
23
|
-
}, [
|
23
|
+
}, [
|
24
|
+
isWhiteboardOwner,
|
25
|
+
screenSharingPeerId,
|
26
|
+
amIScreenSharing,
|
27
|
+
prevScreenSharer,
|
28
|
+
prevWhiteboardOwner,
|
29
|
+
toggleScreenShare,
|
30
|
+
toggleWhiteboard,
|
31
|
+
]);
|
24
32
|
};
|