diff --git a/packages/roomkit-react/src/IconButton/IconButton.tsx b/packages/roomkit-react/src/IconButton/IconButton.tsx
index c66cc5b0a8..297137cfb6 100644
--- a/packages/roomkit-react/src/IconButton/IconButton.tsx
+++ b/packages/roomkit-react/src/IconButton/IconButton.tsx
@@ -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',
diff --git a/packages/roomkit-react/src/Prebuilt/IconButton.tsx b/packages/roomkit-react/src/Prebuilt/IconButton.tsx
index 3694779ad8..e66d9a6330 100644
--- a/packages/roomkit-react/src/Prebuilt/IconButton.tsx
+++ b/packages/roomkit-react/src/Prebuilt/IconButton.tsx
@@ -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',
- },
},
},
});
diff --git a/packages/roomkit-react/src/Prebuilt/components/Footer/ChatToggle.tsx b/packages/roomkit-react/src/Prebuilt/components/Footer/ChatToggle.tsx
index 5ae0033156..8615b3bac4 100644
--- a/packages/roomkit-react/src/Prebuilt/components/Footer/ChatToggle.tsx
+++ b/packages/roomkit-react/src/Prebuilt/components/Footer/ChatToggle.tsx
@@ -9,7 +9,7 @@ import { useIsSidepaneTypeOpen, useSidepaneToggle } from '../AppData/useSidepane
// @ts-ignore: No implicit Any
import { SIDE_PANE_OPTIONS } from '../../common/constants';
-export const ChatToggle = () => {
+export const ChatToggle = ({ onClick }: { onClick?: () => void }) => {
const countUnreadMessages = useHMSStore(selectUnreadHMSMessagesCount);
const isChatOpen = useIsSidepaneTypeOpen(SIDE_PANE_OPTIONS.CHAT);
const toggleChat = useSidepaneToggle(SIDE_PANE_OPTIONS.CHAT);
@@ -21,7 +21,7 @@ export const ChatToggle = () => {
}}
>
-
+ (onClick ? onClick() : toggleChat())} active={!isChatOpen} data-testid="chat_btn">
diff --git a/packages/roomkit-react/src/Prebuilt/components/Footer/WhiteboardToggle.tsx b/packages/roomkit-react/src/Prebuilt/components/Footer/WhiteboardToggle.tsx
index a6abde09c3..0cb9efd262 100644
--- a/packages/roomkit-react/src/Prebuilt/components/Footer/WhiteboardToggle.tsx
+++ b/packages/roomkit-react/src/Prebuilt/components/Footer/WhiteboardToggle.tsx
@@ -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
@@ -9,14 +9,28 @@ 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 (
-
+
{
+ if (disabled) {
+ return;
+ }
try {
await toggle();
} catch (error) {
@@ -24,7 +38,7 @@ export const WhiteboardToggle = () => {
}
}}
active={!open}
- disabled={open && !isOwner}
+ disabled={disabled}
data-testid="whiteboard_btn"
>
diff --git a/packages/roomkit-react/src/Prebuilt/components/HMSVideo/HMSVideo.jsx b/packages/roomkit-react/src/Prebuilt/components/HMSVideo/HMSVideo.jsx
index d022f05a23..a673afef4a 100644
--- a/packages/roomkit-react/src/Prebuilt/components/HMSVideo/HMSVideo.jsx
+++ b/packages/roomkit-react/src/Prebuilt/components/HMSVideo/HMSVideo.jsx
@@ -9,6 +9,7 @@ export const HMSVideo = forwardRef(({ children, ...props }, videoRef) => {
size: '100%',
position: 'relative',
justifyContent: 'center',
+ transition: 'all 0.3s ease-in-out',
'@md': {
height: 'auto',
'& video': {
diff --git a/packages/roomkit-react/src/Prebuilt/components/HMSVideo/PlayPauseButton.tsx b/packages/roomkit-react/src/Prebuilt/components/HMSVideo/PlayPauseButton.tsx
index 2c950ab34b..ef29a128ae 100644
--- a/packages/roomkit-react/src/Prebuilt/components/HMSVideo/PlayPauseButton.tsx
+++ b/packages/roomkit-react/src/Prebuilt/components/HMSVideo/PlayPauseButton.tsx
@@ -9,8 +9,8 @@ export const PlayPauseButton = ({
height = 20,
}: {
isPaused: boolean;
- width: number;
- height: number;
+ width?: number;
+ height?: number;
}) => {
const { hlsPlayer } = useHMSPlayerContext();
const onClick = async (event: MouseEvent) => {
diff --git a/packages/roomkit-react/src/Prebuilt/components/HMSVideo/PlayPauseSeekControls.tsx b/packages/roomkit-react/src/Prebuilt/components/HMSVideo/PlayPauseSeekControls.tsx
new file mode 100644
index 0000000000..03267dbaca
--- /dev/null
+++ b/packages/roomkit-react/src/Prebuilt/components/HMSVideo/PlayPauseSeekControls.tsx
@@ -0,0 +1,158 @@
+import React from 'react';
+import { useMedia } from 'react-use';
+import { BackwardArrowIcon, ForwardArrowIcon } from '@100mslive/react-icons';
+import { Box, Flex } from '../../../Layout';
+import { Text } from '../../../Text';
+import { config } from '../../../Theme';
+import { PlayPauseButton } from './PlayPauseButton';
+import { SeekControl } from './SeekControl';
+import { useIsLandscape } from '../../common/hooks';
+
+// desktop buttons
+export const PlayPauseSeekControls = ({
+ isPaused,
+ onSeekTo,
+}: {
+ isPaused: boolean;
+ onSeekTo: (value: number) => void;
+}) => {
+ return (
+ <>
+ {
+ e.stopPropagation();
+ onSeekTo(-10);
+ }}
+ title="backward"
+ >
+
+
+
+ {
+ e.stopPropagation();
+ onSeekTo(10);
+ }}
+ title="forward"
+ >
+
+
+ >
+ );
+};
+
+// overlay handlers
+export const PlayPauseSeekOverlayControls = ({
+ isPaused,
+ showControls,
+ hoverControlsVisible,
+}: {
+ isPaused: boolean;
+ showControls: boolean;
+ hoverControlsVisible: {
+ seekBackward: boolean;
+ seekForward: boolean;
+ pausePlay: boolean;
+ };
+}) => {
+ const isMobile = useMedia(config.media.md);
+ const isLandscape = useIsLandscape();
+
+ if (!isMobile && !isLandscape) {
+ // show desktopOverflow icons
+ return (
+ <>
+
+
+
+
+
+ 10 secs
+
+
+
+
+
+
+
+
+
+
+ 10 secs
+
+
+ >
+ );
+ }
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+ );
+};
diff --git a/packages/roomkit-react/src/Prebuilt/components/HMSVideo/SeekControls.tsx b/packages/roomkit-react/src/Prebuilt/components/HMSVideo/SeekControl.tsx
similarity index 91%
rename from packages/roomkit-react/src/Prebuilt/components/HMSVideo/SeekControls.tsx
rename to packages/roomkit-react/src/Prebuilt/components/HMSVideo/SeekControl.tsx
index 830ed0a082..20ba919045 100644
--- a/packages/roomkit-react/src/Prebuilt/components/HMSVideo/SeekControls.tsx
+++ b/packages/roomkit-react/src/Prebuilt/components/HMSVideo/SeekControl.tsx
@@ -1,7 +1,7 @@
import React, { MouseEventHandler } from 'react';
import { IconButton, Tooltip } from '../../..';
-export const SeekControls = ({
+export const SeekControl = ({
title,
onClick,
children,
@@ -9,7 +9,7 @@ export const SeekControls = ({
}: {
title: string;
onClick?: MouseEventHandler;
- css: any;
+ css?: any;
children: React.ReactNode;
}) => {
return (
diff --git a/packages/roomkit-react/src/Prebuilt/components/HMSVideo/VideoProgress.tsx b/packages/roomkit-react/src/Prebuilt/components/HMSVideo/VideoProgress.tsx
index c2e637c10a..42f9eaafc4 100644
--- a/packages/roomkit-react/src/Prebuilt/components/HMSVideo/VideoProgress.tsx
+++ b/packages/roomkit-react/src/Prebuilt/components/HMSVideo/VideoProgress.tsx
@@ -25,8 +25,12 @@ export const VideoProgress = ({
if (videoEl.buffered.length > 0) {
bufferProgress = Math.floor(getPercentage(videoEl.buffered?.end(0), duration));
}
- setVideoProgress(isNaN(videoProgress) ? 0 : videoProgress);
- setBufferProgress(isNaN(bufferProgress) ? 0 : bufferProgress);
+ if (!isNaN(videoProgress)) {
+ setVideoProgress(videoProgress);
+ }
+ if (!isNaN(bufferProgress)) {
+ setBufferProgress(bufferProgress);
+ }
}, [videoEl]);
const timeupdateHandler = useCallback(() => {
if (!videoEl || seekProgress) {
@@ -42,7 +46,7 @@ export const VideoProgress = ({
return function cleanup() {
videoEl?.removeEventListener('timeupdate', timeupdateHandler);
};
- }, [timeupdateHandler, videoEl]);
+ }, [setProgress, timeupdateHandler, videoEl]);
const onProgress = (progress: number[]) => {
const progress1 = Math.floor(getPercentage(progress[0], 100));
diff --git a/packages/roomkit-react/src/Prebuilt/components/HMSVideo/index.ts b/packages/roomkit-react/src/Prebuilt/components/HMSVideo/index.ts
index e85f278b49..2a488a597c 100644
--- a/packages/roomkit-react/src/Prebuilt/components/HMSVideo/index.ts
+++ b/packages/roomkit-react/src/Prebuilt/components/HMSVideo/index.ts
@@ -2,15 +2,13 @@
import { LeftControls, RightControls, VideoControls } from './Controls';
// @ts-ignore
import { HMSVideo } from './HMSVideo';
-import { PlayPauseButton } from './PlayPauseButton';
-import { SeekControls } from './SeekControls';
+import { PlayPauseSeekControls, PlayPauseSeekOverlayControls } from './PlayPauseSeekControls';
import { VideoProgress } from './VideoProgress';
import { VideoTime } from './VideoTime';
import { VolumeControl } from './VolumeControl';
export const HMSVideoPlayer = {
Root: HMSVideo,
- PlayPauseButton: PlayPauseButton,
Progress: VideoProgress,
Duration: VideoTime,
Volume: VolumeControl,
@@ -19,5 +17,8 @@ export const HMSVideoPlayer = {
Left: LeftControls,
Right: RightControls,
},
- Seeker: SeekControls,
+ PlayPauseSeekControls: {
+ Overlay: PlayPauseSeekOverlayControls,
+ Button: PlayPauseSeekControls,
+ },
};
diff --git a/packages/roomkit-react/src/Prebuilt/components/IconButtonWithOptions/IconButtonWithOptions.tsx b/packages/roomkit-react/src/Prebuilt/components/IconButtonWithOptions/IconButtonWithOptions.tsx
index e6e9be3b62..cf36bc6c3f 100644
--- a/packages/roomkit-react/src/Prebuilt/components/IconButtonWithOptions/IconButtonWithOptions.tsx
+++ b/packages/roomkit-react/src/Prebuilt/components/IconButtonWithOptions/IconButtonWithOptions.tsx
@@ -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,
@@ -41,8 +41,8 @@ const IconSection = styled(IconButton, {
...variants,
hideOptions: {
true: {
- borderTopRightRadius: '$1',
- borderBottomRightRadius: '$1',
+ borderTopRightRadius: '$1 !important',
+ borderBottomRightRadius: '$1 !important',
},
},
},
@@ -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,
diff --git a/packages/roomkit-react/src/Prebuilt/components/VideoLayouts/GridLayout.tsx b/packages/roomkit-react/src/Prebuilt/components/VideoLayouts/GridLayout.tsx
index 6d64429aea..82b1d47186 100644
--- a/packages/roomkit-react/src/Prebuilt/components/VideoLayouts/GridLayout.tsx
+++ b/packages/roomkit-react/src/Prebuilt/components/VideoLayouts/GridLayout.tsx
@@ -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';
@@ -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);
@@ -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;
@@ -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]);
@@ -104,6 +116,17 @@ export const GridLayout = ({
/>
);
+ } else if (whiteboard?.open) {
+ return (
+
+
+
+ );
} else if (isRoleProminence) {
return (
diff --git a/packages/roomkit-react/src/Prebuilt/components/VideoLayouts/WhiteboardLayout.tsx b/packages/roomkit-react/src/Prebuilt/components/VideoLayouts/WhiteboardLayout.tsx
new file mode 100644
index 0000000000..56155fec88
--- /dev/null
+++ b/packages/roomkit-react/src/Prebuilt/components/VideoLayouts/WhiteboardLayout.tsx
@@ -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 (
+
+
+
+ );
+};
+
+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 (
+
+
+
+
+
+ {layoutMode === LayoutMode.SPOTLIGHT && whiteboardOwner && }
+
+ );
+};
diff --git a/packages/roomkit-react/src/Prebuilt/components/hooks/useCloseScreenshareWhiteboard.tsx b/packages/roomkit-react/src/Prebuilt/components/hooks/useCloseScreenshareWhiteboard.tsx
index 7918e123a8..4b921847ad 100644
--- a/packages/roomkit-react/src/Prebuilt/components/hooks/useCloseScreenshareWhiteboard.tsx
+++ b/packages/roomkit-react/src/Prebuilt/components/hooks/useCloseScreenshareWhiteboard.tsx
@@ -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,
+ ]);
};
diff --git a/packages/roomkit-react/src/Prebuilt/layouts/HLSView.jsx b/packages/roomkit-react/src/Prebuilt/layouts/HLSView.jsx
index 2be40db094..d8d2230a75 100644
--- a/packages/roomkit-react/src/Prebuilt/layouts/HLSView.jsx
+++ b/packages/roomkit-react/src/Prebuilt/layouts/HLSView.jsx
@@ -15,7 +15,7 @@ import {
useHMSStore,
useHMSVanillaStore,
} from '@100mslive/react-sdk';
-import { BackwardArrowIcon, ColoredHandIcon, ForwardArrowIcon, GoLiveIcon } from '@100mslive/react-icons';
+import { ColoredHandIcon, GoLiveIcon } from '@100mslive/react-icons';
import { ChatToggle } from '../components/Footer/ChatToggle';
import { HlsStatsOverlay } from '../components/HlsStatsOverlay';
import { HMSVideoPlayer } from '../components/HMSVideo';
@@ -42,7 +42,7 @@ import { APP_DATA, EMOJI_REACTION_TYPE, POLL_STATE, POLL_VIEWS, SIDE_PANE_OPTION
let hlsPlayer;
const toastMap = {};
-const ToggleChat = () => {
+const ToggleChat = ({ isFullScreen = false }) => {
const { elements } = useRoomLayoutConferencingScreen();
const sidepane = useHMSStore(selectAppData(APP_DATA.sidePane));
const toggleChat = useSidepaneToggle(SIDE_PANE_OPTIONS.CHAT);
@@ -51,7 +51,10 @@ const ToggleChat = () => {
const hmsActions = useHMSActions();
useEffect(() => {
- match({ sidepane, isMobile, showChat })
+ match({ sidepane, isMobile, showChat, isFullScreen })
+ .with({ isFullScreen: true }, () => {
+ hmsActions.setAppData(APP_DATA.sidePane, '');
+ })
.with({ isMobile: true, showChat: true, sidepane: P.when(value => !value) }, () => {
toggleChat();
})
@@ -61,12 +64,13 @@ const ToggleChat = () => {
.otherwise(() => {
//do nothing
});
- }, [sidepane, isMobile, toggleChat, showChat, hmsActions]);
+ }, [sidepane, isMobile, toggleChat, showChat, hmsActions, isFullScreen]);
return null;
};
const HLSView = () => {
const videoRef = useRef(null);
const hlsViewRef = useRef();
+ const { elements } = useRoomLayoutConferencingScreen();
const hlsState = useHMSStore(selectHLSState);
const enablHlsStats = useHMSStore(selectAppData(APP_DATA.hlsStats));
const notification = useHMSNotifications(HMSNotificationTypes.POLL_STOPPED);
@@ -81,7 +85,11 @@ const HLSView = () => {
const [hasCaptions, setHasCaptions] = useState(false);
const [currentSelectedQuality, setCurrentSelectedQuality] = useState(null);
const [isHlsAutoplayBlocked, setIsHlsAutoplayBlocked] = useState(false);
- const [isSeekEnabled, setIsSeekEnabled] = useState(false);
+ const [hoverControlsVisible, setHoverControlsVisible] = useState({
+ seekForward: false,
+ pausePlay: false,
+ seekBackward: false,
+ });
const [isPaused, setIsPaused] = useState(false);
const [show, toggle] = useToggle(false);
const lastHlsUrl = usePrevious(hlsUrl);
@@ -93,6 +101,8 @@ const HLSView = () => {
const controlsTimerRef = useRef();
const [seekProgress, setSeekProgress] = useState(false);
const isFullScreenSupported = screenfull.isEnabled;
+ const toggleChat = useSidepaneToggle(SIDE_PANE_OPTIONS.CHAT);
+ const showChat = !!elements?.chat;
const isMobile = useMedia(config.media.md);
const isLandscape = useIsLandscape();
@@ -233,7 +243,19 @@ const HLSView = () => {
setIsVideoLive(isLive);
};
- const playbackEventHandler = data => setIsPaused(data.state === HLSPlaybackState.paused);
+ const playbackEventHandler = data => {
+ setIsPaused(data.state === HLSPlaybackState.paused);
+ setHoverControlsVisible({
+ ...hoverControlsVisible,
+ pausePlay: true,
+ });
+ setTimeout(() => {
+ setHoverControlsVisible({
+ ...hoverControlsVisible,
+ pausePlay: false,
+ });
+ }, 2000);
+ };
const captionEnabledEventHandler = isCaptionEnabled => {
setIsCaptionEnabled(isCaptionEnabled);
};
@@ -314,28 +336,63 @@ const HLSView = () => {
};
}, [controlsVisible, isFullScreen, seekProgress, qualityDropDownOpen]);
- const onSeekTo = useCallback(seek => {
- hlsPlayer?.seekTo(videoRef.current?.currentTime + seek);
- }, []);
+ const onSeekTo = useCallback(
+ seek => {
+ match({ isLandscape, isMobile, seek })
+ .with({ seek: -10, isMobile: false, isLandscape: false }, () => {
+ setHoverControlsVisible({ ...hoverControlsVisible, seekBackward: true });
+ setTimeout(() => {
+ setHoverControlsVisible({
+ ...hoverControlsVisible,
+ seekBackward: false,
+ });
+ }, 1000);
+ })
+ .with({ seek: 10, isMobile: false, isLandscape: false }, () => {
+ setHoverControlsVisible({ ...hoverControlsVisible, seekForward: true });
+ setTimeout(() => {
+ setHoverControlsVisible({
+ ...hoverControlsVisible,
+ seekForward: false,
+ });
+ }, 1000);
+ })
+ .otherwise(() => null);
+ hlsPlayer?.seekTo(videoRef.current?.currentTime + seek);
+ },
+ [hoverControlsVisible, isLandscape, isMobile],
+ );
const onDoubleClickHandler = useCallback(
event => {
if (!(isMobile || isLandscape) || hlsState?.variants[0]?.playlist_type !== HLSPlaylistType.DVR) {
return;
}
const sidePercentage = (event.screenX * 100) / event.target.clientWidth;
- setIsSeekEnabled(true);
// there is space for pause/unpause button
if (sidePercentage < 45) {
+ setHoverControlsVisible({
+ ...hoverControlsVisible,
+ seekBackward: true,
+ });
onSeekTo(-10);
} else {
+ setHoverControlsVisible({
+ ...hoverControlsVisible,
+ seekForward: true,
+ });
onSeekTo(10);
}
setTimeout(() => {
- setIsSeekEnabled(false);
- }, 200);
+ setHoverControlsVisible({
+ ...hoverControlsVisible,
+ seekForward: false,
+ seekBackward: false,
+ });
+ }, 1000);
},
- [hlsState?.variants, isLandscape, isMobile, onSeekTo],
+ [hlsState?.variants, hoverControlsVisible, isLandscape, isMobile, onSeekTo],
);
+
const onClickHandler = useCallback(async () => {
match({ isMobile, isLandscape, playlist_type: hlsState?.variants[0]?.playlist_type })
.with({ playlist_type: HLSPlaylistType.DVR, isMobile: false, isLandscape: false }, async () => {
@@ -356,6 +413,7 @@ const HLSView = () => {
)
.otherwise(() => null);
}, [hlsState?.variants, isLandscape, isMobile, isPaused]);
+
const onHoverHandler = useCallback(
event => {
event.preventDefault();
@@ -423,6 +481,7 @@ const HLSView = () => {
justify="center"
css={{
flex: isLandscape ? '2 1 0' : '1 1 0',
+ transition: 'all 0.3s ease-in-out',
'&:fullscreen': {
'& video': {
height: 'unset !important',
@@ -484,53 +543,37 @@ const HLSView = () => {
}}
>
<>
+ {!(isMobile || isLandscape) && (
+
+ {!showLoader && hlsState?.variants[0]?.playlist_type === HLSPlaylistType.DVR && (
+
+ )}
+
+ )}
{isMobile || isLandscape ? (
<>
-
- {!showLoader && hlsState?.variants[0]?.playlist_type === HLSPlaylistType.DVR && (
- <>
-
-
-
-
-
-
-
-
-
- >
- )}
-
+ {!showLoader && hlsState?.variants[0]?.playlist_type === HLSPlaylistType.DVR && (
+
+ )}
{
}}
>
- {isLandscape && }
+ {(isLandscape || (isMobile && isFullScreen)) && showChat && (
+ {
+ if (isFullScreen) {
+ toggle();
+ }
+ toggleChat();
+ }}
+ />
+ )}
{hasCaptions && !isHlsAutoplayBlocked && }
{hlsViewRef.current && availableLayers.length > 0 && !isHlsAutoplayBlocked ? (
{
<>
{hlsState?.variants[0]?.playlist_type === HLSPlaylistType.DVR ? (
<>
- {
- onSeekTo(-10);
- }}
- title="backward"
- >
-
-
-
- {
- onSeekTo(10);
- }}
- title="forward"
- >
-
-
+
{!isVideoLive ? : null}
>
) : null}
@@ -631,7 +667,8 @@ const HLSView = () => {
)}
{
+ onClick={async e => {
+ e.stopPropagation();
await hlsPlayer?.seekToLivePosition();
setIsVideoLive(true);
}}
@@ -690,7 +727,7 @@ const HLSView = () => {
-
+
{isMobile && !isFullScreen && }
);
diff --git a/packages/roomkit-react/src/Prebuilt/layouts/VideoStreamingSection.tsx b/packages/roomkit-react/src/Prebuilt/layouts/VideoStreamingSection.tsx
index d19c00f368..95bae82e0a 100644
--- a/packages/roomkit-react/src/Prebuilt/layouts/VideoStreamingSection.tsx
+++ b/packages/roomkit-react/src/Prebuilt/layouts/VideoStreamingSection.tsx
@@ -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';
@@ -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,
@@ -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();
@@ -89,12 +79,6 @@ export const VideoStreamingSection = ({
ViewComponent = ;
} else if (urlToIframe) {
ViewComponent = ;
- } else if (peerSharing) {
- // screen share should take preference over whiteboard
- //@ts-ignore
- ViewComponent = ;
- } else if (isWhiteboardOpen) {
- ViewComponent = ;
} else {
//@ts-ignore
ViewComponent = ;
diff --git a/packages/roomkit-react/src/Prebuilt/layouts/WhiteboardView.tsx b/packages/roomkit-react/src/Prebuilt/layouts/WhiteboardView.tsx
deleted file mode 100644
index ad286bc111..0000000000
--- a/packages/roomkit-react/src/Prebuilt/layouts/WhiteboardView.tsx
+++ /dev/null
@@ -1,69 +0,0 @@
-import React, { useEffect, useMemo } from 'react';
-import { useMedia } from 'react-use';
-import { selectPeers, selectWhiteboard, useHMSStore, useWhiteboard } from '@100mslive/react-sdk';
-import { SecondaryTiles } from '../components/SecondaryTiles';
-import { ProminenceLayout } from '../components/VideoLayouts/ProminenceLayout';
-import { config as cssConfig } from '../../';
-import { Box } from '../../Layout';
-// @ts-ignore: No implicit Any
-import { useSetAppDataByKey } from '../components/AppData/useUISettings';
-import { APP_DATA } from '../common/constants';
-
-const EmbedComponent = () => {
- const isMobile = useMedia(cssConfig.media.md);
- const { iframeRef } = useWhiteboard(isMobile);
-
- return (
-
-
-
- );
-};
-
-export const WhiteboardView = () => {
- const peers = useHMSStore(selectPeers);
- const whiteboard = useHMSStore(selectWhiteboard);
- const [, setActiveScreenSharePeer] = useSetAppDataByKey(APP_DATA.activeScreensharePeerId);
-
- const smallTilePeers = useMemo(() => {
- const smallTilePeers = peers.filter(peer => peer.id !== whiteboard?.owner);
- return smallTilePeers;
- }, [peers, whiteboard?.owner]);
-
- useEffect(() => {
- setActiveScreenSharePeer(whiteboard?.owner || '');
- return () => {
- setActiveScreenSharePeer('');
- };
- }, [whiteboard?.owner, setActiveScreenSharePeer]);
-
- return (
-
-
-
-
-
-
- );
-};