Skip to content

Commit

Permalink
fix: whiteboard layout, toggle with screenshare
Browse files Browse the repository at this point in the history
  • Loading branch information
eswarclynn authored Mar 19, 2024
1 parent 09e61ff commit ab349b4
Show file tree
Hide file tree
Showing 9 changed files with 168 additions and 122 deletions.
9 changes: 2 additions & 7 deletions packages/roomkit-react/src/IconButton/IconButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,19 +25,14 @@ export const IconButton = styled('button', {
'&[disabled]': {
opacity: 0.5,
cursor: 'not-allowed',
backgroundColor: '$secondary_dim',
color: '$on_primary_high',
},
'&:focus': {
outline: 'none',
},
variants: {
active: {
false: {
backgroundColor: '$secondary_dim',
color: '$on_primary_high',
'&:not([disabled]):hover': {
backgroundColor: '$secondary_default',
},
},
true: {
'&:not([disabled]):hover': {
backgroundColor: '$on_surface_low',
Expand Down
16 changes: 6 additions & 10 deletions packages/roomkit-react/src/Prebuilt/IconButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,18 @@ const IconButton = styled(BaseIconButton, {
border: '1px solid $border_bright',
bg: '$background_dim',
r: '$1',
'&[disabled]': {
opacity: 0.5,
cursor: 'not-allowed',
backgroundColor: '$secondary_dim',
color: '$on_primary_high',
},
variants: {
active: {
true: {
color: '$on_surface_high',
backgroundColor: 'transparent',
},
false: {
border: '1px solid transparent',
color: '$on_primary_high',
},
},
disabled: {
true: {
backgroundColor: '$surface_brighter',
color: '$on_surface_low',
},
},
},
});
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from 'react';
import { useWhiteboard } from '@100mslive/react-sdk';
import { useScreenShare, useWhiteboard } from '@100mslive/react-sdk';
import { PencilDrawIcon } from '@100mslive/react-icons';
import { Tooltip } from '../../..';
// @ts-ignore: No implicit Any
Expand All @@ -9,22 +9,36 @@ import { ToastManager } from '../Toast/ToastManager';

export const WhiteboardToggle = () => {
const { toggle, open, isOwner } = useWhiteboard();
const { screenSharingPeerId, amIScreenSharing } = useScreenShare();
const remoteScreenShare = screenSharingPeerId && !amIScreenSharing;
const disabled = remoteScreenShare || (open && !isOwner);

if (!toggle) {
return null;
}

return (
<Tooltip key="whiteboard" title={`${open ? 'Close' : 'Open'} Whiteboard`}>
<Tooltip
key="whiteboard"
title={
remoteScreenShare
? 'Cannot open whiteboard when viewing a shared screen'
: `${open ? 'Close' : 'Open'} Whiteboard`
}
>
<IconButton
onClick={async () => {
if (disabled) {
return;
}
try {
await toggle();
} catch (error) {
ToastManager.addToast({ title: (error as Error).message, variant: 'error' });
}
}}
active={!open}
disabled={open && !isOwner}
disabled={disabled}
data-testid="whiteboard_btn"
>
<PencilDrawIcon />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@ const IconSection = styled(IconButton, {
p: '$4',
r: '$1',
bg: 'transparent',
borderTopRightRadius: 0,
borderTopRightRadius: '0 !important',
borderColor: '$border_bright',
borderBottomRightRadius: 0,
borderBottomRightRadius: '0 !important',
position: 'relative',
'&:not([disabled]):focus-visible': {
zIndex: 1,
Expand All @@ -41,8 +41,8 @@ const IconSection = styled(IconButton, {
...variants,
hideOptions: {
true: {
borderTopRightRadius: '$1',
borderBottomRightRadius: '$1',
borderTopRightRadius: '$1 !important',
borderBottomRightRadius: '$1 !important',
},
},
},
Expand All @@ -53,10 +53,10 @@ const OptionsSection = styled(IconButton, {
h: '$14',
p: '$4 $2',
r: '$1',
borderTopLeftRadius: 0,
borderTopLeftRadius: '0 !important',
borderColor: '$border_bright',
borderBottomLeftRadius: 0,
borderLeftWidth: 0,
borderBottomLeftRadius: '0 !important',
borderLeftWidth: '0 !important',
position: 'relative',
'&:not([disabled]):focus-visible': {
zIndex: 1,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@ import {
selectLocalPeerRoleName,
selectPeers,
selectPeerScreenSharing,
selectWhiteboard,
useHMSStore,
useHMSVanillaStore,
} from '@100mslive/react-sdk';
import { EqualProminence } from './EqualProminence';
import { RoleProminence } from './RoleProminence';
import { ScreenshareLayout } from './ScreenshareLayout';
import { WhiteboardLayout } from './WhiteboardLayout';
// @ts-ignore: No implicit Any
import { usePinnedTrack, useSetAppDataByKey } from '../AppData/useUISettings';
import { VideoTileContext } from '../hooks/useVideoTileLayout';
Expand Down Expand Up @@ -40,6 +42,7 @@ export const GridLayout = ({
hide_metadata_on_tile = false,
}: GridLayoutProps) => {
const peerSharing = useHMSStore(selectPeerScreenSharing);
const whiteboard = useHMSStore(selectWhiteboard);
const pinnedTrack = usePinnedTrack();
const peers = useHMSStore(selectPeers);
const localPeerRole = useHMSStore(selectLocalPeerRoleName);
Expand All @@ -53,9 +56,9 @@ export const GridLayout = ({
)) ||
pinnedTrack;
const updatedPeers = useMemo(() => {
// remove screenshare peer from active speaker sorting
if (activeScreensharePeerId) {
return peers.filter(peer => peer.id !== activeScreensharePeerId);
// remove screenshare/whiteboard peer from active speaker sorting
if (activeScreensharePeerId || whiteboard?.open) {
return peers.filter(peer => peer.id !== activeScreensharePeerId || peer.customerUserId !== whiteboard?.owner);
}
if (isInsetEnabled) {
const isLocalPeerPinned = localPeerID === pinnedTrack?.peerId;
Expand All @@ -67,7 +70,16 @@ export const GridLayout = ({
}
}
return peers;
}, [isInsetEnabled, activeScreensharePeerId, localPeerRole, localPeerID, prominentRoles, peers, pinnedTrack]);
}, [
isInsetEnabled,
whiteboard,
activeScreensharePeerId,
localPeerRole,
localPeerID,
prominentRoles,
peers,
pinnedTrack,
]);
const vanillaStore = useHMSVanillaStore();
const [sortedPeers, setSortedPeers] = useState(updatedPeers);
const peersSorter = useMemo(() => new PeersSorter(vanillaStore), [vanillaStore]);
Expand Down Expand Up @@ -104,6 +116,17 @@ export const GridLayout = ({
/>
</VideoTileContext.Provider>
);
} else if (whiteboard?.open) {
return (
<VideoTileContext.Provider value={tileLayout}>
<WhiteboardLayout
peers={sortedPeers}
onPageSize={setPageSize}
onPageChange={setMainPage}
edgeToEdge={edge_to_edge}
/>
</VideoTileContext.Provider>
);
} else if (isRoleProminence) {
return (
<VideoTileContext.Provider value={tileLayout}>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import React, { useEffect, useMemo } from 'react';
import { useMedia } from 'react-use';
import { selectPeerByCondition, selectWhiteboard, useHMSStore, useWhiteboard } from '@100mslive/react-sdk';
import { Box } from '../../../Layout';
import { config as cssConfig } from '../../../Theme';
import { InsetTile } from '../InsetTile';
import { SecondaryTiles } from '../SecondaryTiles';
import { LayoutMode } from '../Settings/LayoutSettings';
import { LayoutProps } from './interface';
import { ProminenceLayout } from './ProminenceLayout';
// @ts-ignore: No implicit Any
import { useSetUiSettings } from '../AppData/useUISettings';
import { UI_SETTINGS } from '../../common/constants';

const WhiteboardEmbed = () => {
const isMobile = useMedia(cssConfig.media.md);
const { iframeRef } = useWhiteboard(isMobile);

return (
<Box
css={{
mx: '$8',
flex: '3 1 0',
'@lg': {
flex: '2 1 0',
display: 'flex',
alignItems: 'center',
},
}}
>
<iframe
title="Whiteboard View"
ref={iframeRef}
style={{
width: '100%',
height: '100%',
border: 0,
borderRadius: '0.75rem',
}}
allow="autoplay; clipboard-write;"
referrerPolicy="no-referrer"
/>
</Box>
);
};

export const WhiteboardLayout = ({ peers, onPageChange, onPageSize, edgeToEdge }: LayoutProps) => {
const whiteboard = useHMSStore(selectWhiteboard);
const whiteboardOwner = useHMSStore(selectPeerByCondition(peer => peer.customerUserId === whiteboard?.owner));
const [layoutMode, setLayoutMode] = useSetUiSettings(UI_SETTINGS.layoutMode);
const isMobile = useMedia(cssConfig.media.md);
const hasSidebar = !isMobile && layoutMode === LayoutMode.SIDEBAR;
const secondaryPeers = useMemo(() => {
if (layoutMode === LayoutMode.SPOTLIGHT) {
return [];
}
if (isMobile || layoutMode === LayoutMode.SIDEBAR) {
return whiteboardOwner
? [whiteboardOwner, ...peers.filter(p => p.id !== whiteboardOwner?.id)] //keep active sharing peer as first tile
: peers;
}
return peers.filter(p => p.id !== whiteboardOwner?.id);
}, [whiteboardOwner, peers, isMobile, layoutMode]);

useEffect(() => {
if (isMobile) {
setLayoutMode(LayoutMode.GALLERY);
return;
}
if (layoutMode === LayoutMode.SIDEBAR) {
return;
}
setLayoutMode(LayoutMode.SIDEBAR);
return () => {
// reset to gallery once whiteboard is stopped
setLayoutMode(LayoutMode.GALLERY);
};
}, [isMobile]); // eslint-disable-line react-hooks/exhaustive-deps

return (
<ProminenceLayout.Root edgeToEdge={edgeToEdge} hasSidebar={hasSidebar}>
<ProminenceLayout.ProminentSection>
<WhiteboardEmbed />
</ProminenceLayout.ProminentSection>
<SecondaryTiles
peers={secondaryPeers}
onPageChange={onPageChange}
onPageSize={onPageSize}
edgeToEdge={edgeToEdge}
hasSidebar={hasSidebar}
/>
{layoutMode === LayoutMode.SPOTLIGHT && whiteboardOwner && <InsetTile peerId={whiteboardOwner?.id} />}
</ProminenceLayout.Root>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,27 @@ import { useScreenShare, useWhiteboard } from '@100mslive/react-sdk';
* close existing screenshare or whiteboard when the other is started
*/
export const useCloseScreenshareWhiteboard = () => {
const { amIScreenSharing, toggleScreenShare } = useScreenShare();
const { amIScreenSharing, screenSharingPeerId, toggleScreenShare } = useScreenShare();
const { isOwner: isWhiteboardOwner, toggle: toggleWhiteboard } = useWhiteboard();
const prevScreenSharer = usePrevious(amIScreenSharing);
const prevScreenSharer = usePrevious(screenSharingPeerId);
const prevWhiteboardOwner = usePrevious(isWhiteboardOwner);

// if both screenshare and whiteboard are open, close the one that was open earlier
useEffect(() => {
if (isWhiteboardOwner && amIScreenSharing) {
if (prevScreenSharer && !prevWhiteboardOwner) {
if (isWhiteboardOwner && screenSharingPeerId) {
if (prevScreenSharer && amIScreenSharing && !prevWhiteboardOwner) {
toggleScreenShare?.();
} else if (prevWhiteboardOwner && !prevScreenSharer) {
toggleWhiteboard?.();
}
}
}, [isWhiteboardOwner, amIScreenSharing, prevScreenSharer, prevWhiteboardOwner, toggleScreenShare, toggleWhiteboard]);
}, [
isWhiteboardOwner,
screenSharingPeerId,
amIScreenSharing,
prevScreenSharer,
prevWhiteboardOwner,
toggleScreenShare,
toggleWhiteboard,
]);
};
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,7 @@ import {
HLSLiveStreamingScreen_Elements,
} from '@100mslive/types-prebuilt';
import { match } from 'ts-pattern';
import {
selectIsConnectedToRoom,
selectLocalPeerRoleName,
selectPeerScreenSharing,
selectWhiteboard,
useHMSActions,
useHMSStore,
} from '@100mslive/react-sdk';
import { selectIsConnectedToRoom, selectLocalPeerRoleName, useHMSActions, useHMSStore } from '@100mslive/react-sdk';
// @ts-ignore: No implicit Any
import FullPageProgress from '../components/FullPageProgress';
import { GridLayout } from '../components/VideoLayouts/GridLayout';
Expand All @@ -24,7 +17,6 @@ import { PDFView } from './PDFView';
import SidePane from './SidePane';
// @ts-ignore: No implicit Any
import { WaitingView } from './WaitingView';
import { WhiteboardView } from './WhiteboardView';
import {
usePDFConfig,
useUrlToEmbed,
Expand All @@ -50,8 +42,6 @@ export const VideoStreamingSection = ({
}) => {
const localPeerRole = useHMSStore(selectLocalPeerRoleName);
const isConnected = useHMSStore(selectIsConnectedToRoom);
const peerSharing = useHMSStore(selectPeerScreenSharing);
const isWhiteboardOpen = useHMSStore(selectWhiteboard)?.open;

const hmsActions = useHMSActions();
const waitingViewerRole = useWaitingViewerRole();
Expand Down Expand Up @@ -89,12 +79,6 @@ export const VideoStreamingSection = ({
ViewComponent = <PDFView />;
} else if (urlToIframe) {
ViewComponent = <EmbedView />;
} else if (peerSharing) {
// screen share should take preference over whiteboard
//@ts-ignore
ViewComponent = <GridLayout {...(elements as DefaultConferencingScreen_Elements)?.video_tile_layout?.grid} />;
} else if (isWhiteboardOpen) {
ViewComponent = <WhiteboardView />;
} else {
//@ts-ignore
ViewComponent = <GridLayout {...(elements as DefaultConferencingScreen_Elements)?.video_tile_layout?.grid} />;
Expand Down
Loading

0 comments on commit ab349b4

Please sign in to comment.