Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: whiteboard layout, toggle with screenshare #2719

Merged
merged 6 commits into from
Mar 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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}
eswarclynn marked this conversation as resolved.
Show resolved Hide resolved
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
Loading