From 2ba763f7feee4263462b0c67576ae1f95fdc3279 Mon Sep 17 00:00:00 2001 From: amar-1995 Date: Fri, 4 Aug 2023 11:36:15 +0530 Subject: [PATCH 01/21] fix: initial update --- packages/roomkit-react/src/Popover/index.tsx | 3 +- .../BottomActionSheet/BottomActionSheet.jsx | 254 +++++++++++++----- .../BottomActionSheet.stories.tsx | 2 +- .../components/Preview/PreviewJoin.jsx | 20 +- .../components/Settings/SettingsModal.jsx | 149 +++++----- 5 files changed, 269 insertions(+), 159 deletions(-) diff --git a/packages/roomkit-react/src/Popover/index.tsx b/packages/roomkit-react/src/Popover/index.tsx index e2768ed96d..9b4325a029 100644 --- a/packages/roomkit-react/src/Popover/index.tsx +++ b/packages/roomkit-react/src/Popover/index.tsx @@ -1,4 +1,4 @@ -import { Arrow, Content, Popover as Root, Portal, Trigger } from '@radix-ui/react-popover'; +import { Arrow, Close, Content, Popover as Root, Portal, Trigger } from '@radix-ui/react-popover'; import { styled } from '../Theme'; import { popoverAnimation } from '../utils/animations'; @@ -23,4 +23,5 @@ export const Popover = { Trigger: StyledTrigger, Portal: Portal, Arrow: StyledArrow, + Close: Close, }; diff --git a/packages/roomkit-react/src/Prebuilt/components/BottomActionSheet/BottomActionSheet.jsx b/packages/roomkit-react/src/Prebuilt/components/BottomActionSheet/BottomActionSheet.jsx index 8f339d15f8..fe62119eb7 100644 --- a/packages/roomkit-react/src/Prebuilt/components/BottomActionSheet/BottomActionSheet.jsx +++ b/packages/roomkit-react/src/Prebuilt/components/BottomActionSheet/BottomActionSheet.jsx @@ -1,22 +1,24 @@ import React, { useEffect, useRef, useState } from 'react'; import { CrossIcon } from '@100mslive/react-icons'; -import { Box, Flex, Popover, Text } from '../../..'; +import { Box, Flex } from '../../../Layout'; +import { Text } from '../../../Text'; import { getUpdatedHeight } from '../../common/utils'; +import { Dialog } from '../../../Modal'; -const BottomActionSheet = ({ +export const BottomActionSheet = ({ title = '', - children = <>, triggerContent, containerCSS = {}, - // By default the component starts just above the trigger. - // A negative offset allows it to start from the bottom of the screen. + sheetOpen = false, + setSheetOpen, sideOffset = -50, defaultHeight = 50, + children, }) => { const MINIMUM_HEIGHT = 40; // vh - const [sheetOpen, setSheetOpen] = useState(false); const [sheetHeight, setSheetHeight] = useState(`${Math.min(Math.max(MINIMUM_HEIGHT, defaultHeight), 100)}vh`); const closeRef = useRef(null); + console.log('here ', sheetOpen); // Close the sheet if height goes under MINIMUM_HEIGHT useEffect(() => { @@ -25,72 +27,188 @@ const BottomActionSheet = ({ // Delay for showing the opacity animation, can be removed if not needed setTimeout(() => closeRef.current?.click(), 200); } - }, [sheetHeight]); + }, [setSheetOpen, sheetHeight]); return ( - <> - { - if (!open) { - setSheetHeight('0'); - } - setSheetOpen(open); - }} - > - {triggerContent} - - - + {triggerContent} + + + + + { + const updatedSheetHeight = getUpdatedHeight(e, MINIMUM_HEIGHT); + setSheetHeight(updatedSheetHeight); + }} + css={{ + borderBottom: '1px solid $border_bright', + px: '$8', + pb: '$4', + mb: '$4', + w: '100%', + }} + > + + {title} + + + + + + + + {children} + + + + + /* + { + if (!open) { + setSheetHeight('0'); + } + setSheetOpen(open); + }} + > + {triggerContent} + + + + { + const updatedSheetHeight = getUpdatedHeight(e, MINIMUM_HEIGHT); + setSheetHeight(updatedSheetHeight); + }} css={{ - w: '100vw', - py: '$8', - opacity: sheetOpen ? '1' : '0.5', - h: sheetHeight, - minHeight: '50vh', - overflowY: 'auto', - backgroundColor: '$surface_default', - transition: 'all 0.2s linear', - ...containerCSS, + borderBottom: '1px solid $border_bright', + px: '$8', + pb: '$4', + mb: '$4', + w: '100%', }} > - { - const updatedSheetHeight = getUpdatedHeight(e, MINIMUM_HEIGHT); - setSheetHeight(updatedSheetHeight); - }} - css={{ - borderBottom: '1px solid $border_bright', - px: '$8', - pb: '$4', - mb: '$4', - w: '100%', - }} - > - - {title} - - - - - - - - {children} - - - - - + + {title} + + + + + + + + {children} + + + + + */ + /* + { + if (!open) { + setSheetHeight('0'); + } + setSheetOpen(open); + }} + > + {triggerContent} + + + + { + const updatedSheetHeight = getUpdatedHeight(e, MINIMUM_HEIGHT); + setSheetHeight(updatedSheetHeight); + }} + css={{ + borderBottom: '1px solid $border_bright', + px: '$8', + pb: '$4', + mb: '$4', + w: '100%', + }} + > + + {title} + + + + + + + + {children} + + + + + */ ); }; - -export default BottomActionSheet; diff --git a/packages/roomkit-react/src/Prebuilt/components/BottomActionSheet/BottomActionSheet.stories.tsx b/packages/roomkit-react/src/Prebuilt/components/BottomActionSheet/BottomActionSheet.stories.tsx index 1c2caa4bcb..8ede72e419 100644 --- a/packages/roomkit-react/src/Prebuilt/components/BottomActionSheet/BottomActionSheet.stories.tsx +++ b/packages/roomkit-react/src/Prebuilt/components/BottomActionSheet/BottomActionSheet.stories.tsx @@ -4,7 +4,7 @@ import { Button } from '../../../Button'; import { Box } from '../../../Layout'; import { Text } from '../../../Text'; import { CSS } from '../../../Theme'; -import BottomActionSheet from './BottomActionSheet'; +import { BottomActionSheet } from './BottomActionSheet'; // WIP diff --git a/packages/roomkit-react/src/Prebuilt/components/Preview/PreviewJoin.jsx b/packages/roomkit-react/src/Prebuilt/components/Preview/PreviewJoin.jsx index f549b7677b..b560ce0e46 100644 --- a/packages/roomkit-react/src/Prebuilt/components/Preview/PreviewJoin.jsx +++ b/packages/roomkit-react/src/Prebuilt/components/Preview/PreviewJoin.jsx @@ -28,6 +28,7 @@ import { useHMSPrebuiltContext } from '../../AppContext'; import IconButton from '../../IconButton'; import { useRoomLayout } from '../../provider/roomLayoutProvider'; import { AudioVideoToggle } from '../AudioVideoToggle'; +import { BottomActionSheet } from '../BottomActionSheet'; import Chip from '../Chip'; import TileConnection from '../Connection/TileConnection'; import FullPageProgress from '../FullPageProgress'; @@ -246,14 +247,21 @@ const PreviewControls = ({ hideSettings }) => { // Bottom action sheet goes here, if isMobile export const PreviewSettings = React.memo(() => { const [open, setOpen] = useState(false); + const [title, setTitle] = useState('Settings'); return ( - - setOpen(value => !value)}> - - - {open && } - + + + + } + setSheetOpen={setOpen} + sheetOpen={open} + > + + ); }); diff --git a/packages/roomkit-react/src/Prebuilt/components/Settings/SettingsModal.jsx b/packages/roomkit-react/src/Prebuilt/components/Settings/SettingsModal.jsx index b2d2ee2179..501ba17fd2 100644 --- a/packages/roomkit-react/src/Prebuilt/components/Settings/SettingsModal.jsx +++ b/packages/roomkit-react/src/Prebuilt/components/Settings/SettingsModal.jsx @@ -1,8 +1,9 @@ -import React, { useCallback, useEffect, useState } from 'react'; +import React, { Fragment, useCallback, useEffect, useState } from 'react'; import { useMedia } from 'react-use'; import { selectLocalPeerRoleName, useHMSStore } from '@100mslive/react-sdk'; import { ChevronLeftIcon, CrossIcon } from '@100mslive/react-icons'; -import { Box, config as cssConfig, Dialog, Flex, IconButton, Tabs, Text } from '../../../'; +import { Box, config as cssConfig, Flex, IconButton, Tabs, Text } from '../../../'; +import { BottomActionSheet } from '../BottomActionSheet/BottomActionSheet'; import { useHLSViewerRole } from '../AppData/useUISettings'; import { settingContent, settingsList } from './common.js'; @@ -42,92 +43,74 @@ const SettingsModal = ({ open, onOpenChange, children }) => { setSelection(firstNotHiddenTabName); } }, [isMobile, showSetting]); - + console.log('here sheet open ', open); return ( - - {children} - - - + + - Settings + + {settingsList + .filter(({ tabName }) => showSetting[tabName]) + .map(({ icon: Icon, tabName, title }) => { + return ( + + + {title} + + ); + })} + + + {selection && ( + - - Settings - - {settingsList - .filter(({ tabName }) => showSetting[tabName]) - .map(({ icon: Icon, tabName, title }) => { - return ( - - - {title} - - ); - })} - - - {selection && ( - - {settingsList - .filter(({ tabName }) => showSetting[tabName]) - .map(({ content: Content, title, tabName }) => { - return ( - - - {title} - - - - ); - })} - - )} - - - - - - - - - + {settingsList + .filter(({ tabName }) => showSetting[tabName]) + .map(({ content: Content, title, tabName }) => { + return ( + + + {title} + + + + ); + })} + + )} + + ); }; From aa28429840570bc105b799fca6708b3456219c11 Mon Sep 17 00:00:00 2001 From: amar-1995 Date: Fri, 4 Aug 2023 11:36:51 +0530 Subject: [PATCH 02/21] fix: index.js file added --- .../src/Prebuilt/components/BottomActionSheet/index.jsx | 1 + 1 file changed, 1 insertion(+) create mode 100644 packages/roomkit-react/src/Prebuilt/components/BottomActionSheet/index.jsx diff --git a/packages/roomkit-react/src/Prebuilt/components/BottomActionSheet/index.jsx b/packages/roomkit-react/src/Prebuilt/components/BottomActionSheet/index.jsx new file mode 100644 index 0000000000..4b13879c20 --- /dev/null +++ b/packages/roomkit-react/src/Prebuilt/components/BottomActionSheet/index.jsx @@ -0,0 +1 @@ +export { BottomActionSheet } from './BottomActionSheet'; From 11f70317447ed2c81b32a53efbb879f4c7c29575 Mon Sep 17 00:00:00 2001 From: amar-1995 Date: Fri, 4 Aug 2023 18:41:24 +0530 Subject: [PATCH 03/21] fix: added sheet stories --- .../components/Preview/PreviewJoin.jsx | 20 +-- .../components/Settings/SettingsModal.jsx | 152 ++++++++++-------- packages/roomkit-react/src/Sheet/Sheet.mdx | 19 +++ .../roomkit-react/src/Sheet/Sheet.stories.tsx | 60 +++++++ packages/roomkit-react/src/Sheet/Sheet.tsx | 133 +++++++++++++++ packages/roomkit-react/src/Sheet/index.ts | 1 + 6 files changed, 306 insertions(+), 79 deletions(-) create mode 100644 packages/roomkit-react/src/Sheet/Sheet.mdx create mode 100644 packages/roomkit-react/src/Sheet/Sheet.stories.tsx create mode 100644 packages/roomkit-react/src/Sheet/Sheet.tsx create mode 100644 packages/roomkit-react/src/Sheet/index.ts diff --git a/packages/roomkit-react/src/Prebuilt/components/Preview/PreviewJoin.jsx b/packages/roomkit-react/src/Prebuilt/components/Preview/PreviewJoin.jsx index a7d4c67546..5d0fc28409 100644 --- a/packages/roomkit-react/src/Prebuilt/components/Preview/PreviewJoin.jsx +++ b/packages/roomkit-react/src/Prebuilt/components/Preview/PreviewJoin.jsx @@ -28,7 +28,6 @@ import { useHMSPrebuiltContext } from '../../AppContext'; import IconButton from '../../IconButton'; import { useRoomLayout } from '../../provider/roomLayoutProvider'; import { AudioVideoToggle } from '../AudioVideoToggle'; -import { BottomActionSheet } from '../BottomActionSheet'; import Chip from '../Chip'; import TileConnection from '../Connection/TileConnection'; import FullPageProgress from '../FullPageProgress'; @@ -248,21 +247,14 @@ const PreviewControls = ({ hideSettings }) => { // Bottom action sheet goes here, if isMobile export const PreviewSettings = React.memo(() => { const [open, setOpen] = useState(false); - const [title, setTitle] = useState('Settings'); return ( - - - - } - setSheetOpen={setOpen} - sheetOpen={open} - > - - + + setOpen(value => !value)}> + + + {open && } + ); }); diff --git a/packages/roomkit-react/src/Prebuilt/components/Settings/SettingsModal.jsx b/packages/roomkit-react/src/Prebuilt/components/Settings/SettingsModal.jsx index 501ba17fd2..d26cf769bd 100644 --- a/packages/roomkit-react/src/Prebuilt/components/Settings/SettingsModal.jsx +++ b/packages/roomkit-react/src/Prebuilt/components/Settings/SettingsModal.jsx @@ -1,9 +1,13 @@ -import React, { Fragment, useCallback, useEffect, useState } from 'react'; +import React, { useCallback, useEffect, useState } from 'react'; import { useMedia } from 'react-use'; import { selectLocalPeerRoleName, useHMSStore } from '@100mslive/react-sdk'; import { ChevronLeftIcon, CrossIcon } from '@100mslive/react-icons'; -import { Box, config as cssConfig, Flex, IconButton, Tabs, Text } from '../../../'; -import { BottomActionSheet } from '../BottomActionSheet/BottomActionSheet'; +import { IconButton } from '../../../IconButton'; +import { Box, Flex } from '../../../Layout'; +import { Sheet } from '../../../Sheet'; +import { Tabs } from '../../../Tabs'; +import { Text } from '../../../Text'; +import { config as cssConfig } from '../../../Theme'; import { useHLSViewerRole } from '../AppData/useUISettings'; import { settingContent, settingsList } from './common.js'; @@ -45,72 +49,90 @@ const SettingsModal = ({ open, onOpenChange, children }) => { }, [isMobile, showSetting]); console.log('here sheet open ', open); return ( - <> - - + {children} + + + - Settings - - {settingsList - .filter(({ tabName }) => showSetting[tabName]) - .map(({ icon: Icon, tabName, title }) => { - return ( - - - {title} - - ); - })} - - - {selection && ( - - {settingsList - .filter(({ tabName }) => showSetting[tabName]) - .map(({ content: Content, title, tabName }) => { - return ( - - - {title} - - - - ); - })} - - )} - - + + Settings + + {settingsList + .filter(({ tabName }) => showSetting[tabName]) + .map(({ icon: Icon, tabName, title }) => { + return ( + + + {title} + + ); + })} + + + {selection && ( + + {settingsList + .filter(({ tabName }) => showSetting[tabName]) + .map(({ content: Content, title, tabName }) => { + return ( + + + {title} + + + + ); + })} + + )} + + + + + + + + + ); }; diff --git a/packages/roomkit-react/src/Sheet/Sheet.mdx b/packages/roomkit-react/src/Sheet/Sheet.mdx new file mode 100644 index 0000000000..cd0b1e220a --- /dev/null +++ b/packages/roomkit-react/src/Sheet/Sheet.mdx @@ -0,0 +1,19 @@ +# Replacing DocsPage with custom `MDX` content + +This file is a documentation-only `MDX`file to customize Storybook's [DocsPage](https://storybook.js.org/docs/react/writing-docs/docs-page#replacing-docspage). + +It can be further expanded with your own code snippets and include specific information related to your stories. + +For example: + +import { Story } from '@storybook/addon-docs'; + +## Sheet + +Sheet is an hover component used to have a focus-mode like UI for users. + +- [Example](#example) + +### Example + + diff --git a/packages/roomkit-react/src/Sheet/Sheet.stories.tsx b/packages/roomkit-react/src/Sheet/Sheet.stories.tsx new file mode 100644 index 0000000000..94a4b15de3 --- /dev/null +++ b/packages/roomkit-react/src/Sheet/Sheet.stories.tsx @@ -0,0 +1,60 @@ +import React from 'react'; +import { ComponentMeta, ComponentStory } from '@storybook/react'; +import { CrossIcon, InfoIcon } from '@100mslive/react-icons'; +import { Button } from '../Button'; +import { Fieldset } from '../Fieldset'; +import { Input } from '../Input'; +import { Label } from '../Label'; +import { Flex } from '../Layout'; +import { Text } from '../Text'; +import { Sheet } from './Sheet'; +import SheetDocs from './Sheet.mdx'; + +export default { + title: 'UI Components/Sheet', + component: Sheet.Root, + argTypes: { onClick: { action: 'clicked' } }, + parameters: { + docs: { + page: SheetDocs, + }, + }, +} as ComponentMeta; + +//👇 We create a “template” of how args map to rendering +const Template: ComponentStory = () => ( + + + + + + + + + + Sheet Heading + + + + + + + + Body 2: Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et + dolore magna aliqua. Ut enim ad minim veniam,im venitetur adipiscing elit, sed do eiusmod tempor incididunt ut + labore et dolore magna aliqua. Ut enim ad minim veniam,im veni + +
+ + +
+
+ + +
+
+
+); + +export const Example = Template.bind({}); +Example.storyName = 'Sheet'; diff --git a/packages/roomkit-react/src/Sheet/Sheet.tsx b/packages/roomkit-react/src/Sheet/Sheet.tsx new file mode 100644 index 0000000000..f500428487 --- /dev/null +++ b/packages/roomkit-react/src/Sheet/Sheet.tsx @@ -0,0 +1,133 @@ +import React from 'react'; +import * as DialogPrimitive from '@radix-ui/react-dialog'; +import { CSS, keyframes, styled, VariantProps } from '@stitches/react'; +import { Dialog } from '../Modal'; + +const SheetRoot = DialogPrimitive.Root; +const SheetTrigger = DialogPrimitive.Trigger; + +const fadeIn = keyframes({ + from: { opacity: '0' }, + to: { opacity: '1' }, +}); + +const fadeOut = keyframes({ + from: { opacity: '1' }, + to: { opacity: '0' }, +}); + +const StyledOverlay = styled(Dialog.Overlay, { + top: 0, + right: 0, + bottom: 0, + left: 0, + + '&[data-state="open"]': { + animation: `${fadeIn} 150ms cubic-bezier(0.22, 1, 0.36, 1)`, + }, + + '&[data-state="closed"]': { + animation: `${fadeOut} 150ms cubic-bezier(0.22, 1, 0.36, 1)`, + }, +}); + +const slideIn = keyframes({ + from: { transform: '$$transformValue' }, + to: { transform: 'translate3d(0,0,0)' }, +}); + +const slideOut = keyframes({ + from: { transform: 'translate3d(0,0,0)' }, + to: { transform: '$$transformValue' }, +}); + +const StyledContent = styled(DialogPrimitive.Content, { + color: '$hms-ui$colors$on_surface_medium', + backgroundColor: '$hms-ui$colors$surface_default', + borderRadius: '16px 16px 0px 0px', + boxShadow: '0 10px 20px rgba(0,0,0,0.19), 0 6px 6px rgba(0,0,0,0.23)', + position: 'fixed', + zIndex: 999, + padding: '0px 0px 34px 0px', + top: 0, + right: 0, + left: 0, + bottom: 0, + width: 250, + + // Among other things, prevents text alignment inconsistencies when dialog can't be centered in the viewport evenly. + // Affects animated and non-animated dialogs alike. + willChange: 'transform', + + '&:focus': { + outline: 'none', + }, + '@allowMotion': { + '&[data-state="open"]': { + animation: `${slideIn} 150ms cubic-bezier(0.22, 1, 0.36, 1)`, + }, + + '&[data-state="closed"]': { + animation: `${slideOut} 150ms cubic-bezier(0.22, 1, 0.36, 1)`, + }, + }, + + variants: { + side: { + top: { + $$transformValue: 'translate3d(0,-100%,0)', + width: '100%', + height: 300, + bottom: 'auto', + }, + right: { + $$transformValue: 'translate3d(100%,0,0)', + right: 0, + }, + bottom: { + $$transformValue: 'translate3d(0,100%,0)', + width: '100%', + height: 300, + bottom: 0, + top: 'auto', + }, + left: { + $$transformValue: 'translate3d(-100%,0,0)', + left: 0, + }, + }, + }, + + defaultVariants: { + side: 'bottom', + }, +}); + +type SheetContentVariants = VariantProps; +type DialogContentPrimitiveProps = React.ComponentProps; +type SheetContentProps = DialogContentPrimitiveProps & SheetContentVariants & { css?: CSS }; + +const SheetContent = React.forwardRef, SheetContentProps>( + ({ children, ...props }, forwardedRef) => ( + + + + {children} + + + ), +); +const SheetClose = Dialog.Close; +const SheetTitle = Dialog.Title; +const SheetDescription = Dialog.Description; +const SheetDefaultCloseIcon = Dialog.DefaultClose; + +export const Sheet = { + Root: SheetRoot, + Trigger: SheetTrigger, + Content: SheetContent, + Description: SheetDescription, + Title: SheetTitle, + Close: SheetClose, + DefaultClose: SheetDefaultCloseIcon, +}; diff --git a/packages/roomkit-react/src/Sheet/index.ts b/packages/roomkit-react/src/Sheet/index.ts new file mode 100644 index 0000000000..3a9dafd2c3 --- /dev/null +++ b/packages/roomkit-react/src/Sheet/index.ts @@ -0,0 +1 @@ +export { Sheet } from './Sheet'; From 250f6674e7f9eb5543ec7863f26c7888d056611b Mon Sep 17 00:00:00 2001 From: amar-1995 Date: Fri, 4 Aug 2023 19:46:00 +0530 Subject: [PATCH 04/21] fix: added padding --- packages/roomkit-react/src/Sheet/Sheet.stories.tsx | 2 +- packages/roomkit-react/src/Sheet/Sheet.tsx | 9 +++++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/packages/roomkit-react/src/Sheet/Sheet.stories.tsx b/packages/roomkit-react/src/Sheet/Sheet.stories.tsx index 94a4b15de3..108a6fac0e 100644 --- a/packages/roomkit-react/src/Sheet/Sheet.stories.tsx +++ b/packages/roomkit-react/src/Sheet/Sheet.stories.tsx @@ -27,7 +27,7 @@ const Template: ComponentStory = () => ( - + diff --git a/packages/roomkit-react/src/Sheet/Sheet.tsx b/packages/roomkit-react/src/Sheet/Sheet.tsx index f500428487..9474e43477 100644 --- a/packages/roomkit-react/src/Sheet/Sheet.tsx +++ b/packages/roomkit-react/src/Sheet/Sheet.tsx @@ -3,8 +3,13 @@ import * as DialogPrimitive from '@radix-ui/react-dialog'; import { CSS, keyframes, styled, VariantProps } from '@stitches/react'; import { Dialog } from '../Modal'; -const SheetRoot = DialogPrimitive.Root; -const SheetTrigger = DialogPrimitive.Trigger; +const SheetRoot = styled(DialogPrimitive.Root, { + minHeight: '300px', + maxWidth: 'fit-content', +}); +const SheetTrigger = styled(DialogPrimitive.Trigger, { + appearance: 'none !important', // Needed for safari it shows white overlay +}); const fadeIn = keyframes({ from: { opacity: '0' }, From 7d7034d3fdcbec1d6ff7943c16e9e7f1e56af4c2 Mon Sep 17 00:00:00 2001 From: amar-1995 Date: Sun, 6 Aug 2023 10:29:10 +0530 Subject: [PATCH 05/21] fix: added sheet to setting mobile view --- .../components/Settings/SettingsModal.jsx | 104 ++++++++++++++++-- packages/roomkit-react/src/Sheet/Sheet.tsx | 3 +- 2 files changed, 94 insertions(+), 13 deletions(-) diff --git a/packages/roomkit-react/src/Prebuilt/components/Settings/SettingsModal.jsx b/packages/roomkit-react/src/Prebuilt/components/Settings/SettingsModal.jsx index d26cf769bd..b850881358 100644 --- a/packages/roomkit-react/src/Prebuilt/components/Settings/SettingsModal.jsx +++ b/packages/roomkit-react/src/Prebuilt/components/Settings/SettingsModal.jsx @@ -4,6 +4,7 @@ import { selectLocalPeerRoleName, useHMSStore } from '@100mslive/react-sdk'; import { ChevronLeftIcon, CrossIcon } from '@100mslive/react-icons'; import { IconButton } from '../../../IconButton'; import { Box, Flex } from '../../../Layout'; +import { Dialog } from '../../../Modal'; import { Sheet } from '../../../Sheet'; import { Tabs } from '../../../Tabs'; import { Text } from '../../../Text'; @@ -11,7 +12,7 @@ import { config as cssConfig } from '../../../Theme'; import { useHLSViewerRole } from '../AppData/useUISettings'; import { settingContent, settingsList } from './common.js'; -const SettingsModal = ({ open, onOpenChange, children }) => { +const SettingsModal = ({ open, onOpenChange, children = <> }) => { const mediaQueryLg = cssConfig.media.md; const isMobile = useMedia(mediaQueryLg); @@ -47,13 +48,94 @@ const SettingsModal = ({ open, onOpenChange, children }) => { setSelection(firstNotHiddenTabName); } }, [isMobile, showSetting]); - console.log('here sheet open ', open); - return ( + return isMobile ? ( {children} - - - + + + Settings + + {settingsList + .filter(({ tabName }) => showSetting[tabName]) + .map(({ icon: Icon, tabName, title }) => { + return ( + + + {title} + + ); + })} + + + {selection && ( + + {settingsList + .filter(({ tabName }) => showSetting[tabName]) + .map(({ content: Content, title, tabName }) => { + return ( + + + {title} + + + + ); + })} + + )} + + + + + + + + + ) : ( + + {children} + + + { )} - + - - - - + + + + ); }; diff --git a/packages/roomkit-react/src/Sheet/Sheet.tsx b/packages/roomkit-react/src/Sheet/Sheet.tsx index 9474e43477..2fbb7b46ad 100644 --- a/packages/roomkit-react/src/Sheet/Sheet.tsx +++ b/packages/roomkit-react/src/Sheet/Sheet.tsx @@ -49,11 +49,10 @@ const slideOut = keyframes({ const StyledContent = styled(DialogPrimitive.Content, { color: '$hms-ui$colors$on_surface_medium', backgroundColor: '$hms-ui$colors$surface_default', - borderRadius: '16px 16px 0px 0px', + borderRadius: '8px', boxShadow: '0 10px 20px rgba(0,0,0,0.19), 0 6px 6px rgba(0,0,0,0.23)', position: 'fixed', zIndex: 999, - padding: '0px 0px 34px 0px', top: 0, right: 0, left: 0, From 841d7649c007557efb0439e592d781db97ea440d Mon Sep 17 00:00:00 2001 From: amar-1995 Date: Sun, 6 Aug 2023 14:05:23 +0530 Subject: [PATCH 06/21] fix: added sheet stories --- .../src/Prebuilt/components/Settings/SettingsModal.jsx | 4 +--- packages/roomkit-react/src/Sheet/Sheet.stories.tsx | 8 +++++--- packages/roomkit-react/src/Sheet/Sheet.tsx | 3 ++- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/packages/roomkit-react/src/Prebuilt/components/Settings/SettingsModal.jsx b/packages/roomkit-react/src/Prebuilt/components/Settings/SettingsModal.jsx index b850881358..0a46522bd7 100644 --- a/packages/roomkit-react/src/Prebuilt/components/Settings/SettingsModal.jsx +++ b/packages/roomkit-react/src/Prebuilt/components/Settings/SettingsModal.jsx @@ -63,7 +63,7 @@ const SettingsModal = ({ open, onOpenChange, children = <> }) => { value={selection} activationMode={isMobile ? 'manual' : 'automatic'} onValueChange={setSelection} - css={{ size: '100%', position: 'relative' }} + css={{ size: '100%', position: 'relative', borderTopLeftRadius: '$4', borderTopRightRadius: '$4' }} > }) => { flexDirection: 'column', bg: '$background_default', p: '$14 $10', - borderTopLeftRadius: '$4', - borderTopRightRadius: '$4', }} > Settings diff --git a/packages/roomkit-react/src/Sheet/Sheet.stories.tsx b/packages/roomkit-react/src/Sheet/Sheet.stories.tsx index 108a6fac0e..00d981fbc6 100644 --- a/packages/roomkit-react/src/Sheet/Sheet.stories.tsx +++ b/packages/roomkit-react/src/Sheet/Sheet.stories.tsx @@ -2,6 +2,7 @@ import React from 'react'; import { ComponentMeta, ComponentStory } from '@storybook/react'; import { CrossIcon, InfoIcon } from '@100mslive/react-icons'; import { Button } from '../Button'; +import { HorizontalDivider } from '../Divider'; import { Fieldset } from '../Fieldset'; import { Input } from '../Input'; import { Label } from '../Label'; @@ -34,11 +35,12 @@ const Template: ComponentStory = () => ( Sheet Heading - + + Body 2: Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,im venitetur adipiscing elit, sed do eiusmod tempor incididunt ut @@ -46,11 +48,11 @@ const Template: ComponentStory = () => (
- +
- +
diff --git a/packages/roomkit-react/src/Sheet/Sheet.tsx b/packages/roomkit-react/src/Sheet/Sheet.tsx index 2fbb7b46ad..7a04f8c960 100644 --- a/packages/roomkit-react/src/Sheet/Sheet.tsx +++ b/packages/roomkit-react/src/Sheet/Sheet.tsx @@ -49,7 +49,8 @@ const slideOut = keyframes({ const StyledContent = styled(DialogPrimitive.Content, { color: '$hms-ui$colors$on_surface_medium', backgroundColor: '$hms-ui$colors$surface_default', - borderRadius: '8px', + borderTopLeftRadius: '16px', + borderTopRightRadius: '16px', boxShadow: '0 10px 20px rgba(0,0,0,0.19), 0 6px 6px rgba(0,0,0,0.23)', position: 'fixed', zIndex: 999, From c3f5e0eb44556b7ef53fd3af7614cecd21f63408 Mon Sep 17 00:00:00 2001 From: KaustubhKumar05 Date: Mon, 7 Aug 2023 09:55:32 +0530 Subject: [PATCH 07/21] fix: sheet position --- .../BottomActionSheet/BottomActionSheet.jsx | 149 +++--------------- 1 file changed, 18 insertions(+), 131 deletions(-) diff --git a/packages/roomkit-react/src/Prebuilt/components/BottomActionSheet/BottomActionSheet.jsx b/packages/roomkit-react/src/Prebuilt/components/BottomActionSheet/BottomActionSheet.jsx index fe62119eb7..bdf91c3d68 100644 --- a/packages/roomkit-react/src/Prebuilt/components/BottomActionSheet/BottomActionSheet.jsx +++ b/packages/roomkit-react/src/Prebuilt/components/BottomActionSheet/BottomActionSheet.jsx @@ -18,14 +18,12 @@ export const BottomActionSheet = ({ const MINIMUM_HEIGHT = 40; // vh const [sheetHeight, setSheetHeight] = useState(`${Math.min(Math.max(MINIMUM_HEIGHT, defaultHeight), 100)}vh`); const closeRef = useRef(null); - console.log('here ', sheetOpen); // Close the sheet if height goes under MINIMUM_HEIGHT useEffect(() => { if (closeRef?.current && parseFloat(sheetHeight.slice(0, -2)) <= MINIMUM_HEIGHT) { setSheetOpen(false); - // Delay for showing the opacity animation, can be removed if not needed - setTimeout(() => closeRef.current?.click(), 200); + closeRef.current?.click(); } }, [setSheetOpen, sheetHeight]); @@ -34,7 +32,22 @@ export const BottomActionSheet = ({ {triggerContent} - + @@ -84,131 +97,5 @@ export const BottomActionSheet = ({ - /* - { - if (!open) { - setSheetHeight('0'); - } - setSheetOpen(open); - }} - > - {triggerContent} - - - - { - const updatedSheetHeight = getUpdatedHeight(e, MINIMUM_HEIGHT); - setSheetHeight(updatedSheetHeight); - }} - css={{ - borderBottom: '1px solid $border_bright', - px: '$8', - pb: '$4', - mb: '$4', - w: '100%', - }} - > - - {title} - - - - - - - - {children} - - - - - */ - /* - { - if (!open) { - setSheetHeight('0'); - } - setSheetOpen(open); - }} - > - {triggerContent} - - - - { - const updatedSheetHeight = getUpdatedHeight(e, MINIMUM_HEIGHT); - setSheetHeight(updatedSheetHeight); - }} - css={{ - borderBottom: '1px solid $border_bright', - px: '$8', - pb: '$4', - mb: '$4', - w: '100%', - }} - > - - {title} - - - - - - - - {children} - - - - - */ ); }; From 461b89e27310548144cf6e97a1179617ecc8aa55 Mon Sep 17 00:00:00 2001 From: amar-1995 Date: Mon, 7 Aug 2023 15:02:25 +0530 Subject: [PATCH 08/21] fix: design related fix --- packages/roomkit-react/src/Sheet/Sheet.stories.tsx | 4 ++-- packages/roomkit-react/src/Sheet/Sheet.tsx | 7 +++++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/packages/roomkit-react/src/Sheet/Sheet.stories.tsx b/packages/roomkit-react/src/Sheet/Sheet.stories.tsx index 00d981fbc6..e74eb0c245 100644 --- a/packages/roomkit-react/src/Sheet/Sheet.stories.tsx +++ b/packages/roomkit-react/src/Sheet/Sheet.stories.tsx @@ -28,7 +28,7 @@ const Template: ComponentStory = () => ( - + @@ -40,7 +40,7 @@ const Template: ComponentStory = () => ( - + Body 2: Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,im venitetur adipiscing elit, sed do eiusmod tempor incididunt ut diff --git a/packages/roomkit-react/src/Sheet/Sheet.tsx b/packages/roomkit-react/src/Sheet/Sheet.tsx index 7a04f8c960..754dea0399 100644 --- a/packages/roomkit-react/src/Sheet/Sheet.tsx +++ b/packages/roomkit-react/src/Sheet/Sheet.tsx @@ -4,7 +4,7 @@ import { CSS, keyframes, styled, VariantProps } from '@stitches/react'; import { Dialog } from '../Modal'; const SheetRoot = styled(DialogPrimitive.Root, { - minHeight: '300px', + minHeight: '240px', maxWidth: 'fit-content', }); const SheetTrigger = styled(DialogPrimitive.Trigger, { @@ -53,6 +53,7 @@ const StyledContent = styled(DialogPrimitive.Content, { borderTopRightRadius: '16px', boxShadow: '0 10px 20px rgba(0,0,0,0.19), 0 6px 6px rgba(0,0,0,0.23)', position: 'fixed', + padding: '24px', zIndex: 999, top: 0, right: 0, @@ -123,7 +124,9 @@ const SheetContent = React.forwardRef, Sh ), ); const SheetClose = Dialog.Close; -const SheetTitle = Dialog.Title; +const SheetTitle = styled(DialogPrimitive.Title, { + margin: 0, +}); const SheetDescription = Dialog.Description; const SheetDefaultCloseIcon = Dialog.DefaultClose; From 4bcf4edf42510b7344eba835377f0c9e91c765a8 Mon Sep 17 00:00:00 2001 From: KaustubhKumar05 Date: Mon, 7 Aug 2023 15:12:58 +0530 Subject: [PATCH 09/21] fix: opacity --- .../components/BottomActionSheet/BottomActionSheet.jsx | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/packages/roomkit-react/src/Prebuilt/components/BottomActionSheet/BottomActionSheet.jsx b/packages/roomkit-react/src/Prebuilt/components/BottomActionSheet/BottomActionSheet.jsx index bdf91c3d68..ed59e777ee 100644 --- a/packages/roomkit-react/src/Prebuilt/components/BottomActionSheet/BottomActionSheet.jsx +++ b/packages/roomkit-react/src/Prebuilt/components/BottomActionSheet/BottomActionSheet.jsx @@ -38,6 +38,8 @@ export const BottomActionSheet = ({ position: 'fixed', bottom: '0', top: 'unset', + p: '0', + w: '100%', transform: 'translate(-50%)', transition: '0', '&[data-state="open"]': { @@ -50,9 +52,8 @@ export const BottomActionSheet = ({ > From 3610658520f7274fbaa6dde424749c91de6372f3 Mon Sep 17 00:00:00 2001 From: amar-1995 Date: Mon, 7 Aug 2023 17:41:35 +0530 Subject: [PATCH 10/21] fix: added some design in modal --- .../components/Settings/SettingsModal.jsx | 102 ++++++++++-------- packages/roomkit-react/src/Sheet/Sheet.tsx | 15 ++- 2 files changed, 61 insertions(+), 56 deletions(-) diff --git a/packages/roomkit-react/src/Prebuilt/components/Settings/SettingsModal.jsx b/packages/roomkit-react/src/Prebuilt/components/Settings/SettingsModal.jsx index 0a46522bd7..808798bf30 100644 --- a/packages/roomkit-react/src/Prebuilt/components/Settings/SettingsModal.jsx +++ b/packages/roomkit-react/src/Prebuilt/components/Settings/SettingsModal.jsx @@ -2,6 +2,7 @@ import React, { useCallback, useEffect, useState } from 'react'; import { useMedia } from 'react-use'; import { selectLocalPeerRoleName, useHMSStore } from '@100mslive/react-sdk'; import { ChevronLeftIcon, CrossIcon } from '@100mslive/react-icons'; +import { HorizontalDivider } from '../../../Divider'; import { IconButton } from '../../../IconButton'; import { Box, Flex } from '../../../Layout'; import { Dialog } from '../../../Modal'; @@ -48,17 +49,30 @@ const SettingsModal = ({ open, onOpenChange, children = <> }) => { setSelection(firstNotHiddenTabName); } }, [isMobile, showSetting]); + console.log('show setting ', selection, settingsList); + return isMobile ? ( {children} - + + + {!selection ? ( + + + Settings + + + ) : ( + + + + + {selection} + + )} + + + }) => { > - Settings - - {settingsList - .filter(({ tabName }) => showSetting[tabName]) - .map(({ icon: Icon, tabName, title }) => { - return ( - - - {title} - - ); - })} - + {/* + + Sheet Heading + */} + {settingsList + .filter(({ tabName }) => showSetting[tabName]) + .map(({ icon: Icon, tabName, title }) => { + return ( + + + {title} + + ); + })} {selection && ( - + <> {settingsList .filter(({ tabName }) => showSetting[tabName]) .map(({ content: Content, title, tabName }) => { return ( - - - {title} - + + {/* + {selection} + */} ); })} - + )} diff --git a/packages/roomkit-react/src/Sheet/Sheet.tsx b/packages/roomkit-react/src/Sheet/Sheet.tsx index 754dea0399..e61329730b 100644 --- a/packages/roomkit-react/src/Sheet/Sheet.tsx +++ b/packages/roomkit-react/src/Sheet/Sheet.tsx @@ -1,11 +1,13 @@ import React from 'react'; import * as DialogPrimitive from '@radix-ui/react-dialog'; -import { CSS, keyframes, styled, VariantProps } from '@stitches/react'; +import { CSS, keyframes, VariantProps } from '@stitches/react'; import { Dialog } from '../Modal'; +import { styled } from '../Theme'; const SheetRoot = styled(DialogPrimitive.Root, { minHeight: '240px', - maxWidth: 'fit-content', + maxWidth: '100%', + maxHeight: 'fit-content', }); const SheetTrigger = styled(DialogPrimitive.Trigger, { appearance: 'none !important', // Needed for safari it shows white overlay @@ -47,8 +49,8 @@ const slideOut = keyframes({ }); const StyledContent = styled(DialogPrimitive.Content, { - color: '$hms-ui$colors$on_surface_medium', - backgroundColor: '$hms-ui$colors$surface_default', + color: '$on_surface_medium', + backgroundColor: '$surface_default', borderTopLeftRadius: '16px', borderTopRightRadius: '16px', boxShadow: '0 10px 20px rgba(0,0,0,0.19), 0 6px 6px rgba(0,0,0,0.23)', @@ -59,7 +61,6 @@ const StyledContent = styled(DialogPrimitive.Content, { right: 0, left: 0, bottom: 0, - width: 250, // Among other things, prevents text alignment inconsistencies when dialog can't be centered in the viewport evenly. // Affects animated and non-animated dialogs alike. @@ -82,8 +83,6 @@ const StyledContent = styled(DialogPrimitive.Content, { side: { top: { $$transformValue: 'translate3d(0,-100%,0)', - width: '100%', - height: 300, bottom: 'auto', }, right: { @@ -92,8 +91,6 @@ const StyledContent = styled(DialogPrimitive.Content, { }, bottom: { $$transformValue: 'translate3d(0,100%,0)', - width: '100%', - height: 300, bottom: 0, top: 'auto', }, From d348f9f01891e94cd612ef672fc114d6095ecc2d Mon Sep 17 00:00:00 2001 From: amar-1995 Date: Wed, 9 Aug 2023 01:12:59 +0530 Subject: [PATCH 11/21] feat: completed setting modal preview --- .../components/Settings/SettingsModal.jsx | 211 +++++++++++------- .../roomkit-react/src/Sheet/Sheet.stories.tsx | 73 ++++-- packages/roomkit-react/src/Sheet/Sheet.tsx | 7 +- 3 files changed, 186 insertions(+), 105 deletions(-) diff --git a/packages/roomkit-react/src/Prebuilt/components/Settings/SettingsModal.jsx b/packages/roomkit-react/src/Prebuilt/components/Settings/SettingsModal.jsx index 808798bf30..d7d9c8f13f 100644 --- a/packages/roomkit-react/src/Prebuilt/components/Settings/SettingsModal.jsx +++ b/packages/roomkit-react/src/Prebuilt/components/Settings/SettingsModal.jsx @@ -49,94 +49,146 @@ const SettingsModal = ({ open, onOpenChange, children = <> }) => { setSelection(firstNotHiddenTabName); } }, [isMobile, showSetting]); - console.log('show setting ', selection, settingsList); return isMobile ? ( + + ) : ( + + ); +}; + +const MobileSettingModal = ({ + open, + onOpenChange, + selection, + setSelection, + showSetting, + hideSettingByTabName, + resetSelection, + children = <>, +}) => { + return ( {children} - - - {!selection ? ( - - - Settings - - - ) : ( - - - - - {selection} - - )} + + + + {!selection ? ( + + Settings + + ) : ( + + + + + {selection?.charAt(0).toUpperCase() + selection.slice(1)} + + )} + + + + + + - - - - + {!selection ? ( + - {/* - - Sheet Heading - */} {settingsList .filter(({ tabName }) => showSetting[tabName]) .map(({ icon: Icon, tabName, title }) => { return ( - + { + setSelection(tabName); + }} + as="div" + css={{ + all: 'unset', + fontFamily: '$sans', + py: '$10', + display: 'flex', + alignItems: 'center', + fontSize: '$sm', + lineHeight: '$sm', + color: '$on_surface_high', + userSelect: 'none', + gap: '$8', + cursor: 'pointer', + '&:hover': { + bg: '$surface_brighter', + r: '$1', + gap: '$8', + border: 'none', + }, + borderBottom: '1px solid $border_default', + }} + > {title} - + ); })} - - {selection && ( - <> - {settingsList - .filter(({ tabName }) => showSetting[tabName]) - .map(({ content: Content, title, tabName }) => { - return ( - - {/* - {selection} - */} - - - ); - })} - - )} - - - - - - + + ) : ( + + {settingsList + .filter(({ tabName }) => showSetting[tabName] && selection === tabName) + .map(({ content: Content, title, tabName }) => { + return ; + })} + + )} - ) : ( + ); +}; +const DesktopSettingModal = ({ + open, + onOpenChange, + selection, + setSelection, + showSetting, + hideSettingByTabName, + resetSelection, + children = <>, +}) => { + return ( {children} @@ -151,13 +203,13 @@ const SettingsModal = ({ open, onOpenChange, children = <> }) => { > }) => { }} > Settings - + {settingsList .filter(({ tabName }) => showSetting[tabName]) .map(({ icon: Icon, tabName, title }) => { @@ -186,16 +238,6 @@ const SettingsModal = ({ open, onOpenChange, children = <> }) => { flex: '1 1 0', minWidth: 0, mr: '$4', - ...(isMobile - ? { - position: 'absolute', - left: 0, - right: 0, - bg: '$surface_default', - width: '100%', - height: '100%', - } - : {}), }} > {settingsList @@ -203,7 +245,7 @@ const SettingsModal = ({ open, onOpenChange, children = <> }) => { .map(({ content: Content, title, tabName }) => { return ( - + {title} @@ -223,7 +265,6 @@ const SettingsModal = ({ open, onOpenChange, children = <> }) => { ); }; - const SettingsContentHeader = ({ children, isMobile, onBack }) => { return ( diff --git a/packages/roomkit-react/src/Sheet/Sheet.stories.tsx b/packages/roomkit-react/src/Sheet/Sheet.stories.tsx index e74eb0c245..f8c610dd29 100644 --- a/packages/roomkit-react/src/Sheet/Sheet.stories.tsx +++ b/packages/roomkit-react/src/Sheet/Sheet.stories.tsx @@ -6,7 +6,7 @@ import { HorizontalDivider } from '../Divider'; import { Fieldset } from '../Fieldset'; import { Input } from '../Input'; import { Label } from '../Label'; -import { Flex } from '../Layout'; +import { Box, Flex } from '../Layout'; import { Text } from '../Text'; import { Sheet } from './Sheet'; import SheetDocs from './Sheet.mdx'; @@ -29,7 +29,7 @@ const Template: ComponentStory = () => ( - + @@ -40,20 +40,61 @@ const Template: ComponentStory = () => ( - - - Body 2: Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et - dolore magna aliqua. Ut enim ad minim veniam,im venitetur adipiscing elit, sed do eiusmod tempor incididunt ut - labore et dolore magna aliqua. Ut enim ad minim veniam,im veni - -
- - -
-
- - -
+ + + + Body 2: Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et + dolore magna aliqua. Ut enim ad minim veniam,im venitetur adipiscing elit, sed do eiusmod tempor incididunt ut + labore et dolore magna aliqua. Ut enim ad minim veniam,im veni + +
+ + +
+
+ + +
+ + Body 2: Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et + dolore magna aliqua. Ut enim ad minim veniam,im venitetur adipiscing elit, sed do eiusmod tempor incididunt ut + labore et dolore magna aliqua. Ut enim ad minim veniam,im veni + +
+ + +
+
+ + +
+ + Body 2: Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et + dolore magna aliqua. Ut enim ad minim veniam,im venitetur adipiscing elit, sed do eiusmod tempor incididunt ut + labore et dolore magna aliqua. Ut enim ad minim veniam,im veni + +
+ + +
+
+ + +
+ + Body 2: Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et + dolore magna aliqua. Ut enim ad minim veniam,im venitetur adipiscing elit, sed do eiusmod tempor incididunt ut + labore et dolore magna aliqua. Ut enim ad minim veniam,im veni + +
+ + +
+
+ + +
+
); diff --git a/packages/roomkit-react/src/Sheet/Sheet.tsx b/packages/roomkit-react/src/Sheet/Sheet.tsx index e61329730b..f1e4babd28 100644 --- a/packages/roomkit-react/src/Sheet/Sheet.tsx +++ b/packages/roomkit-react/src/Sheet/Sheet.tsx @@ -7,7 +7,6 @@ import { styled } from '../Theme'; const SheetRoot = styled(DialogPrimitive.Root, { minHeight: '240px', maxWidth: '100%', - maxHeight: 'fit-content', }); const SheetTrigger = styled(DialogPrimitive.Trigger, { appearance: 'none !important', // Needed for safari it shows white overlay @@ -51,16 +50,16 @@ const slideOut = keyframes({ const StyledContent = styled(DialogPrimitive.Content, { color: '$on_surface_medium', backgroundColor: '$surface_default', - borderTopLeftRadius: '16px', - borderTopRightRadius: '16px', + borderTopLeftRadius: '$3', + borderTopRightRadius: '$3', boxShadow: '0 10px 20px rgba(0,0,0,0.19), 0 6px 6px rgba(0,0,0,0.23)', position: 'fixed', - padding: '24px', zIndex: 999, top: 0, right: 0, left: 0, bottom: 0, + maxHeight: '96%', // Among other things, prevents text alignment inconsistencies when dialog can't be centered in the viewport evenly. // Affects animated and non-animated dialogs alike. From 67846a5ee33b08f94ebc1e9bc65ec59d72f8c74b Mon Sep 17 00:00:00 2001 From: amar-1995 Date: Wed, 9 Aug 2023 02:58:03 +0530 Subject: [PATCH 12/21] fix: removed bottomsheet --- .../BottomActionSheet/BottomActionSheet.jsx | 102 ------------------ .../BottomActionSheet.stories.tsx | 46 -------- .../components/BottomActionSheet/index.jsx | 1 - 3 files changed, 149 deletions(-) delete mode 100644 packages/roomkit-react/src/Prebuilt/components/BottomActionSheet/BottomActionSheet.jsx delete mode 100644 packages/roomkit-react/src/Prebuilt/components/BottomActionSheet/BottomActionSheet.stories.tsx delete mode 100644 packages/roomkit-react/src/Prebuilt/components/BottomActionSheet/index.jsx diff --git a/packages/roomkit-react/src/Prebuilt/components/BottomActionSheet/BottomActionSheet.jsx b/packages/roomkit-react/src/Prebuilt/components/BottomActionSheet/BottomActionSheet.jsx deleted file mode 100644 index ed59e777ee..0000000000 --- a/packages/roomkit-react/src/Prebuilt/components/BottomActionSheet/BottomActionSheet.jsx +++ /dev/null @@ -1,102 +0,0 @@ -import React, { useEffect, useRef, useState } from 'react'; -import { CrossIcon } from '@100mslive/react-icons'; -import { Box, Flex } from '../../../Layout'; -import { Text } from '../../../Text'; -import { getUpdatedHeight } from '../../common/utils'; -import { Dialog } from '../../../Modal'; - -export const BottomActionSheet = ({ - title = '', - triggerContent, - containerCSS = {}, - sheetOpen = false, - setSheetOpen, - sideOffset = -50, - defaultHeight = 50, - children, -}) => { - const MINIMUM_HEIGHT = 40; // vh - const [sheetHeight, setSheetHeight] = useState(`${Math.min(Math.max(MINIMUM_HEIGHT, defaultHeight), 100)}vh`); - const closeRef = useRef(null); - - // Close the sheet if height goes under MINIMUM_HEIGHT - useEffect(() => { - if (closeRef?.current && parseFloat(sheetHeight.slice(0, -2)) <= MINIMUM_HEIGHT) { - setSheetOpen(false); - closeRef.current?.click(); - } - }, [setSheetOpen, sheetHeight]); - - return ( - - {triggerContent} - - - - - { - const updatedSheetHeight = getUpdatedHeight(e, MINIMUM_HEIGHT); - setSheetHeight(updatedSheetHeight); - }} - css={{ - borderBottom: '1px solid $border_bright', - px: '$8', - pb: '$4', - mb: '$4', - maxWidth: '100%', - }} - > - - {title} - - - - - - - - {children} - - - - - ); -}; diff --git a/packages/roomkit-react/src/Prebuilt/components/BottomActionSheet/BottomActionSheet.stories.tsx b/packages/roomkit-react/src/Prebuilt/components/BottomActionSheet/BottomActionSheet.stories.tsx deleted file mode 100644 index 8ede72e419..0000000000 --- a/packages/roomkit-react/src/Prebuilt/components/BottomActionSheet/BottomActionSheet.stories.tsx +++ /dev/null @@ -1,46 +0,0 @@ -import React, { ReactElement } from 'react'; -import { Meta } from '@storybook/react'; -import { Button } from '../../../Button'; -import { Box } from '../../../Layout'; -import { Text } from '../../../Text'; -import { CSS } from '../../../Theme'; -import { BottomActionSheet } from './BottomActionSheet'; - -// WIP - -export default { - title: 'Components/BottomActionSheet', - component: BottomActionSheet, - argTypes: { - title: { control: 'text' }, - triggerContent: { control: 'jsx' }, - containerCSS: { control: 'object' }, - sideOffset: { control: 'number' }, - defaultHeight: { control: 'number' }, - }, -} as Meta; - -interface BottomActionSheetProps { - title: string; - triggerContent: ReactElement; - children: ReactElement; - containerCSS: CSS; - sideOffset: number; - defaultHeight: number; -} - -const Template = (args: BottomActionSheetProps) => ( - - - This is the content of the BottomActionSheet. - You can put any content you like here. - - -); - -// Example story with default props -export const Default = Template.bind({}); -Default.args = { - title: 'Example BottomActionSheet', - triggerContent: , -}; diff --git a/packages/roomkit-react/src/Prebuilt/components/BottomActionSheet/index.jsx b/packages/roomkit-react/src/Prebuilt/components/BottomActionSheet/index.jsx deleted file mode 100644 index 4b13879c20..0000000000 --- a/packages/roomkit-react/src/Prebuilt/components/BottomActionSheet/index.jsx +++ /dev/null @@ -1 +0,0 @@ -export { BottomActionSheet } from './BottomActionSheet'; From ee8b88244254d86cf8ad3c1677d5268e0ae36c36 Mon Sep 17 00:00:00 2001 From: amar-1995 Date: Wed, 9 Aug 2023 13:27:13 +0530 Subject: [PATCH 13/21] fix: separate animation in utils --- packages/roomkit-react/src/Sheet/Sheet.tsx | 31 ++++--------------- .../roomkit-react/src/utils/animations.ts | 18 +++++++++++ 2 files changed, 24 insertions(+), 25 deletions(-) diff --git a/packages/roomkit-react/src/Sheet/Sheet.tsx b/packages/roomkit-react/src/Sheet/Sheet.tsx index f1e4babd28..57a35482d1 100644 --- a/packages/roomkit-react/src/Sheet/Sheet.tsx +++ b/packages/roomkit-react/src/Sheet/Sheet.tsx @@ -1,8 +1,9 @@ import React from 'react'; import * as DialogPrimitive from '@radix-ui/react-dialog'; -import { CSS, keyframes, VariantProps } from '@stitches/react'; +import { CSS, VariantProps } from '@stitches/react'; import { Dialog } from '../Modal'; import { styled } from '../Theme'; +import { sheetFadeIn, sheetFadeOut, sheetSlideIn, sheetSlideOut } from '../utils'; const SheetRoot = styled(DialogPrimitive.Root, { minHeight: '240px', @@ -12,16 +13,6 @@ const SheetTrigger = styled(DialogPrimitive.Trigger, { appearance: 'none !important', // Needed for safari it shows white overlay }); -const fadeIn = keyframes({ - from: { opacity: '0' }, - to: { opacity: '1' }, -}); - -const fadeOut = keyframes({ - from: { opacity: '1' }, - to: { opacity: '0' }, -}); - const StyledOverlay = styled(Dialog.Overlay, { top: 0, right: 0, @@ -29,24 +20,14 @@ const StyledOverlay = styled(Dialog.Overlay, { left: 0, '&[data-state="open"]': { - animation: `${fadeIn} 150ms cubic-bezier(0.22, 1, 0.36, 1)`, + animation: `${sheetFadeIn} 150ms cubic-bezier(0.22, 1, 0.36, 1)`, }, '&[data-state="closed"]': { - animation: `${fadeOut} 150ms cubic-bezier(0.22, 1, 0.36, 1)`, + animation: `${sheetFadeOut} 150ms cubic-bezier(0.22, 1, 0.36, 1)`, }, }); -const slideIn = keyframes({ - from: { transform: '$$transformValue' }, - to: { transform: 'translate3d(0,0,0)' }, -}); - -const slideOut = keyframes({ - from: { transform: 'translate3d(0,0,0)' }, - to: { transform: '$$transformValue' }, -}); - const StyledContent = styled(DialogPrimitive.Content, { color: '$on_surface_medium', backgroundColor: '$surface_default', @@ -70,11 +51,11 @@ const StyledContent = styled(DialogPrimitive.Content, { }, '@allowMotion': { '&[data-state="open"]': { - animation: `${slideIn} 150ms cubic-bezier(0.22, 1, 0.36, 1)`, + animation: `${sheetSlideIn} 150ms cubic-bezier(0.22, 1, 0.36, 1)`, }, '&[data-state="closed"]': { - animation: `${slideOut} 150ms cubic-bezier(0.22, 1, 0.36, 1)`, + animation: `${sheetSlideOut} 150ms cubic-bezier(0.22, 1, 0.36, 1)`, }, }, diff --git a/packages/roomkit-react/src/utils/animations.ts b/packages/roomkit-react/src/utils/animations.ts index 977ab0f591..0ed9484084 100644 --- a/packages/roomkit-react/src/utils/animations.ts +++ b/packages/roomkit-react/src/utils/animations.ts @@ -34,6 +34,24 @@ export const slideRightAndFade = (start = '-2px') => '100%': { opacity: 1, transform: 'translateX(0)' }, }); +export const sheetSlideIn = keyframes({ + from: { transform: '$$transformValue' }, + to: { transform: 'translate3d(0,0,0)' }, +}); + +export const sheetSlideOut = keyframes({ + from: { transform: 'translate3d(0,0,0)' }, + to: { transform: '$$transformValue' }, +}); +export const sheetFadeIn = keyframes({ + from: { opacity: '0' }, + to: { opacity: '1' }, +}); + +export const sheetFadeOut = keyframes({ + from: { opacity: '1' }, + to: { opacity: '0' }, +}); export const slideDownAndFade = (start = '-2px') => keyframes({ '0%': { opacity: 0, transform: `translateY(${start})` }, From 2198bdbcf11584dddd856470719907e984378385 Mon Sep 17 00:00:00 2001 From: Kaustubh Kumar Date: Wed, 9 Aug 2023 16:15:17 +0530 Subject: [PATCH 14/21] fix: prebuilt footer update --- .../src/components/Header/ParticipantList.jsx | 4 +- .../roomkit-react/src/Dropdown/Dropdown.tsx | 4 +- .../src/Prebuilt/Prebuilt.stories.tsx | 4 +- .../src/Prebuilt/common/hooks.js | 8 ++ .../src/Prebuilt/common/utils.js | 6 + .../Prebuilt/components/AudioVideoToggle.jsx | 4 +- .../Prebuilt/components/Chat/ChatSelector.jsx | 2 +- .../src/Prebuilt/components/EmojiReaction.jsx | 31 +---- .../src/Prebuilt/components/Footer.jsx | 5 +- .../components/Footer/ConferencingFooter.jsx | 121 ++++++------------ .../{Header => Footer}/ParticipantList.jsx | 8 +- .../components/Footer/StreamingFooter.jsx | 50 +++----- .../components/Header/ConferencingHeader.jsx | 2 - .../components/Header/StreamingHeader.jsx | 2 +- .../IconButtonWithOptions.jsx | 17 ++- .../src/Prebuilt/components/LeaveRoom.jsx | 109 +++++++++------- .../components/MoreSettings/EmbedUrl.jsx | 121 +++++++----------- .../components/MoreSettings/MoreSettings.jsx | 99 +++++++++----- .../Prebuilt/components/PIP/PIPComponent.jsx | 20 ++- .../src/Prebuilt/components/PIP/index.jsx | 8 +- .../components/Preview/PreviewForm.jsx | 8 +- .../components/Preview/PreviewJoin.jsx | 4 +- .../src/Prebuilt/components/ScreenShare.jsx | 2 +- .../components/ScreenshareDisplay.jsx | 4 +- .../src/Prebuilt/components/ShareMenuIcon.jsx | 1 + .../pdfAnnotator/pdfFileOptions.jsx | 3 +- .../components/pdfAnnotator/pdfInfo.jsx | 2 +- .../pdfAnnotator/shareScreenOptions.jsx | 1 + .../components/pdfAnnotator/uploadedFile.jsx | 1 + .../src/Prebuilt/layouts/SidePane.jsx | 2 +- .../src/Prebuilt/layouts/mainView.jsx | 17 +-- .../src/Prebuilt/primitives/DialogContent.jsx | 2 +- 32 files changed, 316 insertions(+), 356 deletions(-) rename packages/roomkit-react/src/Prebuilt/components/{Header => Footer}/ParticipantList.jsx (97%) diff --git a/apps/100ms-web/src/components/Header/ParticipantList.jsx b/apps/100ms-web/src/components/Header/ParticipantList.jsx index bb1c7a0577..06cf5204d3 100644 --- a/apps/100ms-web/src/components/Header/ParticipantList.jsx +++ b/apps/100ms-web/src/components/Header/ParticipantList.jsx @@ -373,8 +373,8 @@ export const ParticipantSearch = ({ onSearch, placeholder }) => { { event.stopPropagation(); diff --git a/packages/roomkit-react/src/Dropdown/Dropdown.tsx b/packages/roomkit-react/src/Dropdown/Dropdown.tsx index 9a382a8c12..141d16af8a 100644 --- a/packages/roomkit-react/src/Dropdown/Dropdown.tsx +++ b/packages/roomkit-react/src/Dropdown/Dropdown.tsx @@ -53,7 +53,7 @@ const DropdownItem = styled(Item, { display: 'flex', alignItems: 'center', outline: 'none', - backgroundColor: '$surface_default', + backgroundColor: '$surface_dim', '&:hover': { cursor: 'pointer', bg: '$surface_bright', @@ -74,7 +74,7 @@ const DropdownContent = styled(Content, { maxHeight: '$64', r: '$1', py: '$4', - backgroundColor: '$surface_default', + backgroundColor: '$surface_dim', overflowY: 'auto', boxShadow: '0 10px 20px rgba(0,0,0,0.19), 0 6px 6px rgba(0,0,0,0.23)', zIndex: 20, diff --git a/packages/roomkit-react/src/Prebuilt/Prebuilt.stories.tsx b/packages/roomkit-react/src/Prebuilt/Prebuilt.stories.tsx index 3468752840..b8920ca71a 100644 --- a/packages/roomkit-react/src/Prebuilt/Prebuilt.stories.tsx +++ b/packages/roomkit-react/src/Prebuilt/Prebuilt.stories.tsx @@ -6,7 +6,7 @@ export default { title: 'UI Components/Prebuilt', component: HMSPrebuilt, argTypes: { - roomCode: { control: { type: 'text' }, defaultValue: 'tsj-obqh-lwx' }, + roomCode: { control: { type: 'text' }, defaultValue: 'cuf-wywo-trf' }, logo: { control: { type: 'object' }, defaultValue: undefined }, typography: { control: { type: 'object' }, defaultValue: 'Roboto' }, }, @@ -18,7 +18,7 @@ const PrebuiltRoomCodeStory: StoryFn = ({ roomCode = '', log export const Example = PrebuiltRoomCodeStory.bind({}); Example.args = { - roomCode: 'tsj-obqh-lwx', + roomCode: 'cuf-wywo-trf', options: { endpoints: { roomLayout: 'https://demo8271564.mockable.io/v2/layouts/ui', diff --git a/packages/roomkit-react/src/Prebuilt/common/hooks.js b/packages/roomkit-react/src/Prebuilt/common/hooks.js index 60fc49c1d0..82df0d3278 100644 --- a/packages/roomkit-react/src/Prebuilt/common/hooks.js +++ b/packages/roomkit-react/src/Prebuilt/common/hooks.js @@ -1,6 +1,8 @@ // @ts-check import { useEffect, useRef, useState } from 'react'; +import { JoinForm_JoinBtnType } from '@100mslive/types-prebuilt/elements/join_form'; import { selectAvailableRoleNames, selectIsConnectedToRoom, selectPeerCount, useHMSStore } from '@100mslive/react-sdk'; +import { useRoomLayout } from '../provider/roomLayoutProvider'; import { isInternalRole } from './utils'; /** @@ -45,3 +47,9 @@ export const useFilteredRoles = () => { const roles = useHMSStore(selectAvailableRoleNames).filter(role => !isInternalRole(role)); return roles; }; + +export const useShowStreamingUI = () => { + const layout = useRoomLayout(); + const { join_form } = layout?.screens?.preview?.default?.elements || {}; + return join_form?.join_btn_type === JoinForm_JoinBtnType.JOIN_BTN_TYPE_JOIN_AND_GO_LIVE; +}; diff --git a/packages/roomkit-react/src/Prebuilt/common/utils.js b/packages/roomkit-react/src/Prebuilt/common/utils.js index b3a876c703..e319dec0e7 100644 --- a/packages/roomkit-react/src/Prebuilt/common/utils.js +++ b/packages/roomkit-react/src/Prebuilt/common/utils.js @@ -83,3 +83,9 @@ export const getUpdatedHeight = (e, MINIMUM_HEIGHT) => { const sheetHeightInVH = Math.max(MINIMUM_HEIGHT, heightToPercentage > 80 ? 100 : heightToPercentage); return `${sheetHeightInVH}vh`; }; + +export const getFormattedCount = num => { + const formatter = new Intl.NumberFormat('en', { notation: 'compact', maximumFractionDigits: 2 }); + const formattedNum = formatter.format(num); + return formattedNum; +}; diff --git a/packages/roomkit-react/src/Prebuilt/components/AudioVideoToggle.jsx b/packages/roomkit-react/src/Prebuilt/components/AudioVideoToggle.jsx index 4b68f82746..e90a333709 100644 --- a/packages/roomkit-react/src/Prebuilt/components/AudioVideoToggle.jsx +++ b/packages/roomkit-react/src/Prebuilt/components/AudioVideoToggle.jsx @@ -18,7 +18,7 @@ import { isMacOS } from '../common/constants'; const optionsCSS = { fontWeight: '$semiBold', color: '$on_surface_high', w: '100%', p: '$8' }; -export const AudioVideoToggle = () => { +export const AudioVideoToggle = ({ hideOptions = false }) => { const { allDevices, selectedDeviceIDs, updateDevice } = useDevices(); const { videoInput, audioInput } = allDevices; @@ -77,6 +77,7 @@ export const AudioVideoToggle = () => { active={isLocalAudioEnabled} onClick={toggleAudio} key="toggleAudio" + hideOptions={hideOptions} /> ) : null} @@ -94,6 +95,7 @@ export const AudioVideoToggle = () => { key="toggleVideo" active={isLocalVideoEnabled} onClick={toggleVideo} + hideOptions={hideOptions} /> ) : null} diff --git a/packages/roomkit-react/src/Prebuilt/components/Chat/ChatSelector.jsx b/packages/roomkit-react/src/Prebuilt/components/Chat/ChatSelector.jsx index 5513c124d6..fe99845ce5 100644 --- a/packages/roomkit-react/src/Prebuilt/components/Chat/ChatSelector.jsx +++ b/packages/roomkit-react/src/Prebuilt/components/Chat/ChatSelector.jsx @@ -10,7 +10,7 @@ import { } from '@100mslive/react-sdk'; import { CheckIcon } from '@100mslive/react-icons'; import { Box, Dropdown, Flex, HorizontalDivider, Text, Tooltip } from '../../../'; -import { ParticipantSearch } from '../Header/ParticipantList'; +import { ParticipantSearch } from '../Footer/ParticipantList'; import { useFilteredRoles } from '../../common/hooks'; const ChatDotIcon = () => { diff --git a/packages/roomkit-react/src/Prebuilt/components/EmojiReaction.jsx b/packages/roomkit-react/src/Prebuilt/components/EmojiReaction.jsx index 2024d5ec9b..9de48c77c9 100644 --- a/packages/roomkit-react/src/Prebuilt/components/EmojiReaction.jsx +++ b/packages/roomkit-react/src/Prebuilt/components/EmojiReaction.jsx @@ -14,14 +14,13 @@ import { import { EmojiIcon } from '@100mslive/react-icons'; import { Dropdown } from '../../Dropdown'; import { Flex } from '../../Layout'; -import { Text } from '../../Text'; import { styled } from '../../Theme'; import { Tooltip } from '../../Tooltip'; import IconButton from '../IconButton'; import { useHLSViewerRole } from './AppData/useUISettings'; import { useDropdownList } from './hooks/useDropdownList'; import { useIsFeatureEnabled } from './hooks/useFeatures'; -import { EMOJI_REACTION_TYPE, FEATURE_LIST, HLS_TIMED_METADATA_DOC_URL } from '../common/constants'; +import { EMOJI_REACTION_TYPE, FEATURE_LIST } from '../common/constants'; init({ data }); @@ -93,34 +92,6 @@ export const EmojiReaction = () => { ))} ))} -
- - Reactions will be timed for Live Streaming viewers.{' '} - - - - Learn more. - - -
diff --git a/packages/roomkit-react/src/Prebuilt/components/Footer.jsx b/packages/roomkit-react/src/Prebuilt/components/Footer.jsx index 03f8f564b7..c205d31b12 100644 --- a/packages/roomkit-react/src/Prebuilt/components/Footer.jsx +++ b/packages/roomkit-react/src/Prebuilt/components/Footer.jsx @@ -1,8 +1,9 @@ import React from 'react'; import { ConferencingFooter } from './Footer/ConferencingFooter'; import { StreamingFooter } from './Footer/StreamingFooter'; -import { isStreamingKit } from '../common/utils'; +import { useShowStreamingUI } from '../common/hooks'; export const Footer = () => { - return isStreamingKit() ? : ; + const showStreamingUI = useShowStreamingUI(); + return showStreamingUI ? : ; }; diff --git a/packages/roomkit-react/src/Prebuilt/components/Footer/ConferencingFooter.jsx b/packages/roomkit-react/src/Prebuilt/components/Footer/ConferencingFooter.jsx index fa169876e6..c5175d2f84 100644 --- a/packages/roomkit-react/src/Prebuilt/components/Footer/ConferencingFooter.jsx +++ b/packages/roomkit-react/src/Prebuilt/components/Footer/ConferencingFooter.jsx @@ -1,101 +1,58 @@ -import React, { Fragment, Suspense, useState } from 'react'; +import React, { Suspense } from 'react'; import { useMedia } from 'react-use'; -import { selectIsAllowedToPublish, useHMSStore, useScreenShare } from '@100mslive/react-sdk'; -import { MusicIcon } from '@100mslive/react-icons'; -import { config as cssConfig, Flex, Footer as AppFooter, Tooltip } from '../../../'; -import IconButton from '../../IconButton'; +import { selectIsLocalVideoEnabled, useHMSStore } from '@100mslive/react-sdk'; +import { config as cssConfig, Footer as AppFooter } from '../../../'; import { AudioVideoToggle } from '../AudioVideoToggle'; import { EmojiReaction } from '../EmojiReaction'; import { LeaveRoom } from '../LeaveRoom'; -import MetaActions from '../MetaActions'; import { MoreSettings } from '../MoreSettings/MoreSettings'; -import { PIP } from '../PIP'; +// import { PIP } from '../PIP'; import { ScreenshareToggle } from '../ScreenShare'; -import { ScreenShareHintModal } from '../ScreenshareHintModal'; import { ChatToggle } from './ChatToggle'; -import { useIsFeatureEnabled } from '../hooks/useFeatures'; -import { isScreenshareSupported } from '../../common/utils'; +import { ParticipantCount } from './ParticipantList'; import { FeatureFlags } from '../../services/FeatureFlags'; -import { FEATURE_LIST } from '../../common/constants'; const TranscriptionButton = React.lazy(() => import('../../plugins/transcription')); const VirtualBackground = React.lazy(() => import('../../plugins/VirtualBackground/VirtualBackground')); -const ScreenshareAudio = () => { - const { - amIScreenSharing, - screenShareVideoTrackId: video, - screenShareAudioTrackId: audio, - toggleScreenShare, - } = useScreenShare(); - const isAllowedToPublish = useHMSStore(selectIsAllowedToPublish); - const isAudioScreenshare = amIScreenSharing && !video && !!audio; - const [showModal, setShowModal] = useState(false); - const isFeatureEnabled = useIsFeatureEnabled(FEATURE_LIST.AUDIO_ONLY_SCREENSHARE); - if (!isFeatureEnabled || !isAllowedToPublish.screen || !isScreenshareSupported()) { - return null; - } - return ( - - - { - if (amIScreenSharing) { - toggleScreenShare(); - } else { - setShowModal(true); - } - }} - data-testid="screenshare_audio" - > - - - - {showModal && setShowModal(false)} />} - - ); -}; - export const ConferencingFooter = () => { const isMobile = useMedia(cssConfig.media.md); + const isVideoOn = useHMSStore(selectIsLocalVideoEnabled); + return ( - - - - - - {FeatureFlags.enableTranscription ? : null} - - {isMobile && } - - - - - - - - - - - - - - - {!isMobile && } - - - + {isMobile ? ( + <> + + + + + + + + ) : ( + <> + + {isVideoOn ? ( + + + + ) : null} + {FeatureFlags.enableTranscription ? : null} + + + + + + + + + + + + + + )} ); }; diff --git a/packages/roomkit-react/src/Prebuilt/components/Header/ParticipantList.jsx b/packages/roomkit-react/src/Prebuilt/components/Footer/ParticipantList.jsx similarity index 97% rename from packages/roomkit-react/src/Prebuilt/components/Header/ParticipantList.jsx rename to packages/roomkit-react/src/Prebuilt/components/Footer/ParticipantList.jsx index eaed314876..c528cc08d9 100644 --- a/packages/roomkit-react/src/Prebuilt/components/Header/ParticipantList.jsx +++ b/packages/roomkit-react/src/Prebuilt/components/Footer/ParticipantList.jsx @@ -21,11 +21,11 @@ import { SpeakerIcon, VerticalMenuIcon, } from '@100mslive/react-icons'; -import { Avatar, Box, Dropdown, Flex, Input, Slider, Text, textEllipsis } from '../../../'; +import { Avatar, Box, Dropdown, Flex, Input, Slider, Text, textEllipsis } from '../../..'; import IconButton from '../../IconButton'; import { ConnectionIndicator } from '../Connection/ConnectionIndicator'; +import { ParticipantFilter } from '../Header/ParticipantFilter'; import { RoleChangeModal } from '../RoleChangeModal'; -import { ParticipantFilter } from './ParticipantFilter'; import { useIsSidepaneTypeOpen, useSidepaneToggle } from '../AppData/useSidepane'; import { isInternalRole } from '../../common/utils'; import { SIDE_PANE_OPTIONS } from '../../common/constants'; @@ -320,8 +320,8 @@ export const ParticipantSearch = ({ onSearch, placeholder }) => { { event.stopPropagation(); diff --git a/packages/roomkit-react/src/Prebuilt/components/Footer/StreamingFooter.jsx b/packages/roomkit-react/src/Prebuilt/components/Footer/StreamingFooter.jsx index a1addf548f..46a7055285 100644 --- a/packages/roomkit-react/src/Prebuilt/components/Footer/StreamingFooter.jsx +++ b/packages/roomkit-react/src/Prebuilt/components/Footer/StreamingFooter.jsx @@ -1,16 +1,16 @@ import React from 'react'; -import { Box, Flex, Footer as AppFooter } from '../../../'; +import { useMedia } from 'react-use'; +import { config as cssConfig, Footer as AppFooter } from '../../../'; import { AudioVideoToggle } from '../AudioVideoToggle'; import { EmojiReaction } from '../EmojiReaction'; -import { StreamActions } from '../Header/StreamActions'; import { LeaveRoom } from '../LeaveRoom'; -import MetaActions from '../MetaActions'; import { MoreSettings } from '../MoreSettings/MoreSettings'; -import { PIP } from '../PIP'; import { ScreenshareToggle } from '../ScreenShare'; import { ChatToggle } from './ChatToggle'; +import { ParticipantCount } from './ParticipantList'; export const StreamingFooter = () => { + const isMobile = useMedia(cssConfig.media.md); return ( { }, }} > - + {isMobile ? : null} + { }, }} > - - - - - - - - - - - - - - + {isMobile ? ( + <> + + + + ) : ( + <> + + + + + )} - - + + ); diff --git a/packages/roomkit-react/src/Prebuilt/components/Header/ConferencingHeader.jsx b/packages/roomkit-react/src/Prebuilt/components/Header/ConferencingHeader.jsx index 6f68d1570f..e0eed5e50c 100644 --- a/packages/roomkit-react/src/Prebuilt/components/Header/ConferencingHeader.jsx +++ b/packages/roomkit-react/src/Prebuilt/components/Header/ConferencingHeader.jsx @@ -1,7 +1,6 @@ import React from 'react'; import { Flex } from '../../../'; import { SpeakerTag } from './HeaderComponents'; -import { ParticipantCount } from './ParticipantList'; import { StreamActions } from './StreamActions'; export const ConferencingHeader = () => { @@ -20,7 +19,6 @@ export const ConferencingHeader = () => { }} > - ); diff --git a/packages/roomkit-react/src/Prebuilt/components/Header/StreamingHeader.jsx b/packages/roomkit-react/src/Prebuilt/components/Header/StreamingHeader.jsx index 71dd67fb2c..de16f09399 100644 --- a/packages/roomkit-react/src/Prebuilt/components/Header/StreamingHeader.jsx +++ b/packages/roomkit-react/src/Prebuilt/components/Header/StreamingHeader.jsx @@ -2,10 +2,10 @@ import React from 'react'; import { useMedia } from 'react-use'; import { config as cssConfig, Flex } from '../../../'; import { EmojiReaction } from '../EmojiReaction'; +import { ParticipantCount } from '../Footer/ParticipantList'; import { LeaveRoom } from '../LeaveRoom'; import MetaActions from '../MetaActions'; import { SpeakerTag } from './HeaderComponents'; -import { ParticipantCount } from './ParticipantList'; import { LiveStatus, RecordingStatus, StreamActions } from './StreamActions'; export const StreamingHeader = () => { diff --git a/packages/roomkit-react/src/Prebuilt/components/IconButtonWithOptions/IconButtonWithOptions.jsx b/packages/roomkit-react/src/Prebuilt/components/IconButtonWithOptions/IconButtonWithOptions.jsx index dbf3ef5da0..24cf1d7e51 100644 --- a/packages/roomkit-react/src/Prebuilt/components/IconButtonWithOptions/IconButtonWithOptions.jsx +++ b/packages/roomkit-react/src/Prebuilt/components/IconButtonWithOptions/IconButtonWithOptions.jsx @@ -5,6 +5,12 @@ import { styled } from '../../../Theme'; import { Tooltip } from '../../../Tooltip'; import IconButton from '../../IconButton'; +const iconButtonWIthoutOptionsCSS = { + mx: 0, + borderTopRightRadius: '$1', + borderBottomRightRadius: '$1', +}; + const IconSection = styled(IconButton, { w: 'unset', h: '$14', @@ -13,11 +19,7 @@ const IconSection = styled(IconButton, { borderTopRightRadius: 0, borderColor: '$border_default', borderBottomRightRadius: 0, - '@md': { - mx: 0, - borderTopRightRadius: '$1', - borderBottomRightRadius: '$1', - }, + '@md': iconButtonWIthoutOptionsCSS, }); const OptionsSection = styled(IconButton, { @@ -46,12 +48,13 @@ export const IconButtonWithOptions = ({ return; }, key = '', + hideOptions = false, }) => { const bgCss = { backgroundColor: active ? '$transparent' : '$secondary_dim' }; const iconCss = { color: active ? '$on_surface_high' : '$on_primary_high' }; return ( - + {icon} @@ -60,7 +63,7 @@ export const IconButtonWithOptions = ({ - + diff --git a/packages/roomkit-react/src/Prebuilt/components/LeaveRoom.jsx b/packages/roomkit-react/src/Prebuilt/components/LeaveRoom.jsx index c7d2c508ce..7728572f0f 100644 --- a/packages/roomkit-react/src/Prebuilt/components/LeaveRoom.jsx +++ b/packages/roomkit-react/src/Prebuilt/components/LeaveRoom.jsx @@ -1,7 +1,7 @@ import React, { Fragment, useState } from 'react'; import { useParams } from 'react-router-dom'; import { selectIsConnectedToRoom, selectPermissions, useHMSActions, useHMSStore } from '@100mslive/react-sdk'; -import { AlertTriangleIcon, ExitIcon, HangUpIcon, VerticalMenuIcon } from '@100mslive/react-icons'; +import { AlertTriangleIcon, ExitIcon, HangUpIcon, StopIcon, VerticalMenuIcon } from '@100mslive/react-icons'; import { ToastManager } from './Toast/ToastManager'; import { Button } from '../../Button'; import { Dropdown } from '../../Dropdown'; @@ -12,17 +12,14 @@ import { Text } from '../../Text'; import { styled } from '../../Theme'; import { Tooltip } from '../../Tooltip'; import { useHMSPrebuiltContext } from '../AppContext'; -import { DialogCheckbox, DialogContent, DialogRow } from '../primitives/DialogContent'; import { useDropdownList } from './hooks/useDropdownList'; import { useNavigation } from './hooks/useNavigation'; -import { isStreamingKit } from '../common/utils'; -export const LeaveRoom = () => { +export const LeaveRoom = ({ showStreamingUI = false }) => { const navigate = useNavigation(); const params = useParams(); const [open, setOpen] = useState(false); const [showEndRoomModal, setShowEndRoomModal] = useState(false); - const [lockRoom, setLockRoom] = useState(false); const isConnected = useHMSStore(selectIsConnectedToRoom); const permissions = useHMSStore(selectPermissions); const hmsActions = useHMSActions(); @@ -47,11 +44,10 @@ export const LeaveRoom = () => { }; const endRoom = () => { - hmsActions.endRoom(lockRoom, 'End Room'); + hmsActions.endRoom(false, 'End Room'); redirectToLeavePage(); }; - const isStreamKit = isStreamingKit(); if (!permissions || !isConnected) { return null; } @@ -64,11 +60,15 @@ export const LeaveRoom = () => { variant="danger" key="LeaveRoom" data-testid="leave_room_btn" - css={{ borderTopRightRadius: 0, borderBottomRightRadius: 0 }} + css={{ + borderTopRightRadius: 0, + borderBottomRightRadius: 0, + '@md': { borderTopRightRadius: '$1', borderBottomRightRadius: '$1' }, + }} onClick={leaveRoom} > - {!isStreamKit ? ( + {!showStreamingUI ? ( @@ -97,7 +97,23 @@ export const LeaveRoom = () => { - + + + + + + + + + Leave {showStreamingUI ? 'Studio' : 'Session'} + + + Others will continue after you leave. You can join the {showStreamingUI ? 'studio ' : 'room '} + again. + + + + { @@ -107,27 +123,14 @@ export const LeaveRoom = () => { > - + - - End Room for All - - - Warning: You can’t undo this action + + End Session - - - - - - - - - - Leave {isStreamKit ? 'Studio' : 'Room'} - - You can always rejoin later + + The session will end for everyone. You can't undo this action. @@ -139,7 +142,7 @@ export const LeaveRoom = () => { - {isStreamKit ? ( + {showStreamingUI ? ( @@ -151,23 +154,33 @@ export const LeaveRoom = () => { )} - { - if (!value) { - setLockRoom(false); - } - setShowEndRoomModal(value); - }} - > - - - - - - + + + + + + + End Session + + + The session will end for everyone and all the activities will stop. You can't undo this action. + + + + + + + ); @@ -176,7 +189,7 @@ export const LeaveRoom = () => { const LeaveIconButton = styled(IconButton, { color: '$on_primary_high', h: '$14', - px: '$8', + px: '$6', r: '$1', bg: '$alert_error_default', '&:not([disabled]):hover': { @@ -197,6 +210,6 @@ const MenuTriggerButton = styled(LeaveIconButton, { borderBottomLeftRadius: 0, px: '$3', '@md': { - px: '$2', + display: 'none', }, }); diff --git a/packages/roomkit-react/src/Prebuilt/components/MoreSettings/EmbedUrl.jsx b/packages/roomkit-react/src/Prebuilt/components/MoreSettings/EmbedUrl.jsx index 577a82edff..7e7ba13350 100644 --- a/packages/roomkit-react/src/Prebuilt/components/MoreSettings/EmbedUrl.jsx +++ b/packages/roomkit-react/src/Prebuilt/components/MoreSettings/EmbedUrl.jsx @@ -1,7 +1,6 @@ import React, { useState } from 'react'; -import { ViewIcon } from '@100mslive/react-icons'; -import { Button, Dialog, Dropdown, Text } from '../../../'; -import { DialogContent, DialogInput, DialogRow } from '../../primitives/DialogContent'; +import { LinkIcon } from '@100mslive/react-icons'; +import { Button, Dialog, Dropdown, Flex, Input, Text } from '../../../'; import { useSetAppDataByKey } from '../AppData/useUISettings'; import { APP_DATA } from '../../common/constants'; @@ -17,7 +16,7 @@ export const EmbedUrl = ({ setShowOpenUrl }) => { }} data-testid="embed_url_btn" > - + Embed URL @@ -29,78 +28,54 @@ export function EmbedUrlModal({ onOpenChange }) { const [embedConfig, setEmbedConfig] = useSetAppDataByKey(APP_DATA.embedConfig); const [url, setUrl] = useState(embedConfig?.url || ''); - const isAnythingEmbedded = !!embedConfig?.url; - const isModifying = isAnythingEmbedded && url && url !== embedConfig.url; - return ( - - - - - Embed a url and share with everyone in the room. Ensure that you're sharing the current tab when the prompt - opens. Note that not all websites support being embedded. + + + + + Embed URL + + + Ensure that you're sharing the current tab when the prompt opens. Note that not all websites support being + embedded. + + + URL - - - {isAnythingEmbedded ? ( - <> - - - - ) : ( - <> - - - - )} - - + setUrl(e.target.value)} + type="url" + /> + + + + + + ); } diff --git a/packages/roomkit-react/src/Prebuilt/components/MoreSettings/MoreSettings.jsx b/packages/roomkit-react/src/Prebuilt/components/MoreSettings/MoreSettings.jsx index 5eb7c4c588..d5645b68ef 100644 --- a/packages/roomkit-react/src/Prebuilt/components/MoreSettings/MoreSettings.jsx +++ b/packages/roomkit-react/src/Prebuilt/components/MoreSettings/MoreSettings.jsx @@ -1,5 +1,4 @@ import React, { Fragment, useState } from 'react'; -import { useMedia } from 'react-use'; import Hls from 'hls.js'; import { selectAppData, @@ -9,20 +8,21 @@ import { selectPermissions, useHMSActions, useHMSStore, - useRecordingStreaming, } from '@100mslive/react-sdk'; import { - ChangeRoleIcon, + BrbIcon, CheckIcon, + DragHandleIcon, + HandIcon, InfoIcon, MicOffIcon, PencilIcon, - RecordIcon, + PipIcon, SettingsIcon, - VerticalMenuIcon, } from '@100mslive/react-icons'; -import { Box, Checkbox, config as cssConfig, Dropdown, Flex, Text, Tooltip } from '../../../'; +import { Box, Checkbox, Dropdown, Flex, Text, Tooltip } from '../../../'; import IconButton from '../../IconButton'; +import { PIP } from '../PIP'; import { RoleChangeModal } from '../RoleChangeModal'; import SettingsModal from '../Settings/SettingsModal'; import StartRecording from '../Settings/StartRecording'; @@ -35,6 +35,7 @@ import { FullScreenItem } from './FullScreenItem'; import { MuteAllModal } from './MuteAllModal'; import { useDropdownList } from '../hooks/useDropdownList'; import { useIsFeatureEnabled } from '../hooks/useFeatures'; +import { useMyMetadata } from '../hooks/useMetadata'; import { FeatureFlags } from '../../services/FeatureFlags'; import { APP_DATA, FEATURE_LIST, isAndroid, isIOS, isMacOS } from '../../common/constants'; @@ -52,19 +53,22 @@ const MODALS = { EMBED_URL: 'embedUrl', }; -export const MoreSettings = () => { +export const MoreSettings = ({ showStreamingUI = false }) => { const permissions = useHMSStore(selectPermissions); const isAllowedToPublish = useHMSStore(selectIsAllowedToPublish); const localPeerId = useHMSStore(selectLocalPeerID); const localPeerRole = useHMSStore(selectLocalPeerRoleName); const hmsActions = useHMSActions(); const enablHlsStats = useHMSStore(selectAppData(APP_DATA.hlsStats)); - const isMobile = useMedia(cssConfig.media.md); - const { isBrowserRecordingOn } = useRecordingStreaming(); const isChangeNameEnabled = useIsFeatureEnabled(FEATURE_LIST.CHANGE_NAME); const isEmbedEnabled = useIsFeatureEnabled(FEATURE_LIST.EMBED_URL); const isSFNEnabled = useIsFeatureEnabled(FEATURE_LIST.STARTS_FOR_NERDS); const [openModals, setOpenModals] = useState(new Set()); + const { isHandRaised, isBRBOn, toggleHandRaise, toggleBRB } = useMyMetadata(); + const isHandRaiseEnabled = useIsFeatureEnabled(FEATURE_LIST.HAND_RAISE); + const isBRBEnabled = useIsFeatureEnabled(FEATURE_LIST.BRB); + const isPIPEnabled = useIsFeatureEnabled(FEATURE_LIST.PICTURE_IN_PICTURE); + useDropdownList({ open: openModals.size > 0, name: 'MoreSettings' }); const updateState = (modalName, value) => { @@ -89,7 +93,7 @@ export const MoreSettings = () => { - + @@ -97,27 +101,62 @@ export const MoreSettings = () => { - {isMobile && permissions?.browserRecording ? ( - <> - updateState(MODALS.START_RECORDING, true)}> - - - {isBrowserRecordingOn ? 'Stop' : 'Start'} Recording - - - - + {isHandRaiseEnabled && !showStreamingUI ? ( + + + + Raise Hand + + + {isHandRaised ? : null} + + + ) : null} + + {isBRBEnabled && !showStreamingUI ? ( + + + + Be Right Back + + + {isBRBOn ? : null} + + + ) : null} + + {(isBRBEnabled || isHandRaiseEnabled) && !showStreamingUI ? ( + + ) : null} + + {isPIPEnabled ? ( + + + + + Picture in picture mode + + + } + /> + ) : null} + {isChangeNameEnabled && ( updateState(MODALS.CHANGE_NAME, true)} data-testid="change_name_btn"> @@ -127,21 +166,11 @@ export const MoreSettings = () => { )} updateState(MODALS.SELF_ROLE_CHANGE, true)} /> - {permissions?.changeRole && ( - updateState(MODALS.BULK_ROLE_CHANGE, true)} - data-testid="bulk_role_change_btn" - > - - - Bulk Role Change - - - )} {isAllowedToPublish.screen && isEmbedEnabled && ( updateState(MODALS.EMBED_URL, true)} /> )} + {permissions.mute && ( updateState(MODALS.MUTE_ALL, true)} data-testid="mute_all_btn"> @@ -150,13 +179,15 @@ export const MoreSettings = () => {
)} - + + updateState(MODALS.DEVICE_SETTINGS, true)} data-testid="device_settings_btn"> Settings + {FeatureFlags.enableStatsForNerds && isSFNEnabled && (localPeerRole === 'hls-viewer' ? ( diff --git a/packages/roomkit-react/src/Prebuilt/components/PIP/PIPComponent.jsx b/packages/roomkit-react/src/Prebuilt/components/PIP/PIPComponent.jsx index 17c8c04ba7..3a6a7368cc 100644 --- a/packages/roomkit-react/src/Prebuilt/components/PIP/PIPComponent.jsx +++ b/packages/roomkit-react/src/Prebuilt/components/PIP/PIPComponent.jsx @@ -9,7 +9,7 @@ import { useHMSVanillaStore, } from '@100mslive/react-sdk'; import { PipIcon } from '@100mslive/react-icons'; -import { Tooltip } from '../../../'; +import { Flex, Tooltip } from '../../../'; import IconButton from '../../IconButton'; import { PictureInPicture } from './PIPManager'; import { MediaSession } from './SetupMediaSession'; @@ -20,7 +20,7 @@ import { DEFAULT_HLS_VIEWER_ROLE, FEATURE_LIST } from '../../common/constants'; * shows a button which when clicked shows some videos in PIP, clicking * again turns it off. */ -const PIPComponent = ({ peers, showLocalPeer }) => { +const PIPComponent = ({ peers, showLocalPeer, content = null }) => { const localPeerRole = useHMSStore(selectLocalPeerRoleName); const [isPipOn, setIsPipOn] = useState(PictureInPicture.isOn()); const hmsActions = useHMSActions(); @@ -48,11 +48,17 @@ const PIPComponent = ({ peers, showLocalPeer }) => { } return ( <> - - onPipToggle()} data-testid="pip_btn"> - - - + {content ? ( + onPipToggle()} data-testid="pip_btn"> + {content} + + ) : ( + + onPipToggle()} data-testid="pip_btn"> + + + + )} {isPipOn && } ); diff --git a/packages/roomkit-react/src/Prebuilt/components/PIP/index.jsx b/packages/roomkit-react/src/Prebuilt/components/PIP/index.jsx index f0a62b5396..e17018678c 100644 --- a/packages/roomkit-react/src/Prebuilt/components/PIP/index.jsx +++ b/packages/roomkit-react/src/Prebuilt/components/PIP/index.jsx @@ -2,10 +2,14 @@ import React from 'react'; import PIPComponent from './PIPComponent'; import { usePinnedTrack } from '../AppData/useUISettings'; -export const PIP = () => { +export const PIP = ({ content = null }) => { const pinnedTrack = usePinnedTrack(); return ( - + ); }; diff --git a/packages/roomkit-react/src/Prebuilt/components/Preview/PreviewForm.jsx b/packages/roomkit-react/src/Prebuilt/components/Preview/PreviewForm.jsx index 819ac92604..5efbc73f80 100644 --- a/packages/roomkit-react/src/Prebuilt/components/Preview/PreviewForm.jsx +++ b/packages/roomkit-react/src/Prebuilt/components/Preview/PreviewForm.jsx @@ -1,11 +1,11 @@ import React from 'react'; import { useMedia } from 'react-use'; -import { JoinForm_JoinBtnType } from '@100mslive/types-prebuilt/elements/join_form'; import { selectPermissions, useHMSStore, useRecordingStreaming } from '@100mslive/react-sdk'; import { RadioIcon } from '@100mslive/react-icons'; import { Button, config as cssConfig, Flex, Input, styled } from '../../..'; import { useRoomLayout } from '../../provider/roomLayoutProvider'; import { PreviewSettings } from './PreviewJoin'; +import { useShowStreamingUI } from '../../common/hooks'; const PreviewForm = ({ name, @@ -24,10 +24,8 @@ const PreviewForm = ({ const permissions = useHMSStore(selectPermissions); const layout = useRoomLayout(); const { join_form: joinForm = {} } = layout?.screens?.preview?.default?.elements || {}; - const showGoLive = - joinForm.join_btn_type === JoinForm_JoinBtnType.JOIN_BTN_TYPE_JOIN_AND_GO_LIVE && - !isHLSRunning && - permissions?.hlsStreaming; + const showStreamingUI = useShowStreamingUI(); + const showGoLive = showStreamingUI && !isHLSRunning && permissions?.hlsStreaming; return (
import('../../plugins/VirtualBackground/VirtualBackground')); @@ -44,8 +45,7 @@ const getParticipantChipContent = (peerCount = 0) => { if (peerCount === 0) { return 'You are the first to join'; } - const formatter = new Intl.NumberFormat('en', { notation: 'compact', maximumFractionDigits: 2 }); - const formattedNum = formatter.format(peerCount); + const formattedNum = getFormattedCount(peerCount); return `${formattedNum} other${parseInt(formattedNum) === 1 ? '' : 's'} in the session`; }; diff --git a/packages/roomkit-react/src/Prebuilt/components/ScreenShare.jsx b/packages/roomkit-react/src/Prebuilt/components/ScreenShare.jsx index 7d9d27f001..c6d4514383 100644 --- a/packages/roomkit-react/src/Prebuilt/components/ScreenShare.jsx +++ b/packages/roomkit-react/src/Prebuilt/components/ScreenShare.jsx @@ -21,7 +21,7 @@ export const ScreenshareToggle = ({ css = {} }) => { return ( - + { r: '$3', m: '0 auto', color: '$on_surface_high', - bg: '$surface_default', + bg: '$background_default', textAlign: 'center', }} > - + You are sharing your screen + + + + ); +}; diff --git a/packages/roomkit-react/src/Prebuilt/components/LeaveCard.jsx b/packages/roomkit-react/src/Prebuilt/components/LeaveCard.jsx new file mode 100644 index 0000000000..e8b4be06cf --- /dev/null +++ b/packages/roomkit-react/src/Prebuilt/components/LeaveCard.jsx @@ -0,0 +1,18 @@ +import { Box, Flex } from '../../Layout'; +import { Text } from '../../Text'; + +export const LeaveCard = ({ icon, title, subtitle, onClick, bg, titleColor, subtitleColor, css = {} }) => { + return ( + + {icon} + + + {title} + + + {subtitle} + + + + ); +}; diff --git a/packages/roomkit-react/src/Prebuilt/components/LeaveRoom.jsx b/packages/roomkit-react/src/Prebuilt/components/LeaveRoom.jsx index 7728572f0f..f5d1c65a70 100644 --- a/packages/roomkit-react/src/Prebuilt/components/LeaveRoom.jsx +++ b/packages/roomkit-react/src/Prebuilt/components/LeaveRoom.jsx @@ -1,29 +1,35 @@ import React, { Fragment, useState } from 'react'; import { useParams } from 'react-router-dom'; +import { useMedia } from 'react-use'; import { selectIsConnectedToRoom, selectPermissions, useHMSActions, useHMSStore } from '@100mslive/react-sdk'; -import { AlertTriangleIcon, ExitIcon, HangUpIcon, StopIcon, VerticalMenuIcon } from '@100mslive/react-icons'; +import { ExitIcon, HangUpIcon, StopIcon, VerticalMenuIcon } from '@100mslive/react-icons'; import { ToastManager } from './Toast/ToastManager'; -import { Button } from '../../Button'; import { Dropdown } from '../../Dropdown'; import { IconButton } from '../../IconButton'; import { Box, Flex } from '../../Layout'; import { Dialog } from '../../Modal'; +import { Sheet } from '../../Sheet'; import { Text } from '../../Text'; -import { styled } from '../../Theme'; +import { config as cssConfig, styled } from '../../Theme'; import { Tooltip } from '../../Tooltip'; import { useHMSPrebuiltContext } from '../AppContext'; +import { EndSessionContent } from './EndSessionContent'; +import { LeaveCard } from './LeaveCard'; import { useDropdownList } from './hooks/useDropdownList'; import { useNavigation } from './hooks/useNavigation'; +import { useShowStreamingUI } from '../common/hooks'; -export const LeaveRoom = ({ showStreamingUI = false }) => { +export const LeaveRoom = ({}) => { const navigate = useNavigation(); const params = useParams(); const [open, setOpen] = useState(false); - const [showEndRoomModal, setShowEndRoomModal] = useState(false); + const [showEndRoomAlert, setShowEndRoomAlert] = useState(false); const isConnected = useHMSStore(selectIsConnectedToRoom); const permissions = useHMSStore(selectPermissions); const hmsActions = useHMSActions(); const { showLeave, onLeave } = useHMSPrebuiltContext(); + const isMobile = useMedia(cssConfig.media.md); + const showStreamingUI = useShowStreamingUI(); useDropdownList({ open, name: 'LeaveRoom' }); const redirectToLeavePage = () => { @@ -52,6 +58,88 @@ export const LeaveRoom = ({ showStreamingUI = false }) => { return null; } + if (isMobile) { + return ( + + {permissions.endRoom ? ( + + + + + {!showStreamingUI ? ( + + + + ) : ( + + + + + + Leave Studio + + + )} + + + + + } + onClick={leaveRoom} + css={{ pt: 0, mt: '$10' }} + /> + } + onClick={() => { + setOpen(false); + setShowEndRoomAlert(true); + }} + /> + + + ) : ( + + + + {showStreamingUI ? ( + + + + ) : ( + + )} + + + + )} + + + + + + + ); + } + return ( {permissions.endRoom ? ( @@ -99,41 +187,31 @@ export const LeaveRoom = ({ showStreamingUI = false }) => { - - - - - - - Leave {showStreamingUI ? 'Studio' : 'Session'} - - - Others will continue after you leave. You can join the {showStreamingUI ? 'studio ' : 'room '} - again. - - - + } + onClick={leaveRoom} + css={{ p: 0 }} + /> - { - setShowEndRoomModal(true); - }} - data-testid="end_room_btn" - > - - - - - - - End Session - - - The session will end for everyone. You can't undo this action. - - - + + } + onClick={() => { + setOpen(false); + setShowEndRoomAlert(true); + }} + css={{ p: 0 }} + /> @@ -154,31 +232,11 @@ export const LeaveRoom = ({ showStreamingUI = false }) => { )} - + - - - End Session - - - The session will end for everyone and all the activities will stop. You can't undo this action. - - - - - + From 504204ce26cb6ec666cd46199086ac4f3729da83 Mon Sep 17 00:00:00 2001 From: KaustubhKumar05 Date: Thu, 10 Aug 2023 19:21:49 +0530 Subject: [PATCH 16/21] fix: use custom hook --- .../src/Prebuilt/components/MoreSettings/MoreSettings.jsx | 4 +++- packages/roomkit-react/src/Prebuilt/layouts/mainView.jsx | 8 ++------ 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/packages/roomkit-react/src/Prebuilt/components/MoreSettings/MoreSettings.jsx b/packages/roomkit-react/src/Prebuilt/components/MoreSettings/MoreSettings.jsx index d5645b68ef..34f4f1d9b8 100644 --- a/packages/roomkit-react/src/Prebuilt/components/MoreSettings/MoreSettings.jsx +++ b/packages/roomkit-react/src/Prebuilt/components/MoreSettings/MoreSettings.jsx @@ -36,6 +36,7 @@ import { MuteAllModal } from './MuteAllModal'; import { useDropdownList } from '../hooks/useDropdownList'; import { useIsFeatureEnabled } from '../hooks/useFeatures'; import { useMyMetadata } from '../hooks/useMetadata'; +import { useShowStreamingUI } from '../../common/hooks'; import { FeatureFlags } from '../../services/FeatureFlags'; import { APP_DATA, FEATURE_LIST, isAndroid, isIOS, isMacOS } from '../../common/constants'; @@ -53,7 +54,7 @@ const MODALS = { EMBED_URL: 'embedUrl', }; -export const MoreSettings = ({ showStreamingUI = false }) => { +export const MoreSettings = ({}) => { const permissions = useHMSStore(selectPermissions); const isAllowedToPublish = useHMSStore(selectIsAllowedToPublish); const localPeerId = useHMSStore(selectLocalPeerID); @@ -68,6 +69,7 @@ export const MoreSettings = ({ showStreamingUI = false }) => { const isHandRaiseEnabled = useIsFeatureEnabled(FEATURE_LIST.HAND_RAISE); const isBRBEnabled = useIsFeatureEnabled(FEATURE_LIST.BRB); const isPIPEnabled = useIsFeatureEnabled(FEATURE_LIST.PICTURE_IN_PICTURE); + const showStreamingUI = useShowStreamingUI(); useDropdownList({ open: openModals.size > 0, name: 'MoreSettings' }); diff --git a/packages/roomkit-react/src/Prebuilt/layouts/mainView.jsx b/packages/roomkit-react/src/Prebuilt/layouts/mainView.jsx index e2ea0ebf51..cdb4129fd9 100644 --- a/packages/roomkit-react/src/Prebuilt/layouts/mainView.jsx +++ b/packages/roomkit-react/src/Prebuilt/layouts/mainView.jsx @@ -84,17 +84,13 @@ export const ConferenceMainView = () => { } // Is a streaming kit and broadcaster joins - if ( - permissions?.hlsStreaming && - !isHLSRunning && - joinForm.join_btn_type === JoinForm_JoinBtnType.JOIN_BTN_TYPE_JOIN_AND_GO_LIVE - ) { + if (permissions?.hlsStreaming && !isHLSRunning && showStreamingUI) { startHLS(); } hmsActions.sessionStore.observe([SESSION_STORE_KEY.PINNED_MESSAGE, SESSION_STORE_KEY.SPOTLIGHT]); // eslint-disable-next-line react-hooks/exhaustive-deps - }, [isConnected, hmsActions, permissions, joinForm]); + }, [isConnected, hmsActions, permissions, showStreamingUI]); if (!localPeerRole) { // we don't know the role yet to decide how to render UI From 14d26b95f4ea0994009af556dc5d48bbe33ae4d3 Mon Sep 17 00:00:00 2001 From: Kaustubh Kumar Date: Fri, 11 Aug 2023 11:39:32 +0530 Subject: [PATCH 17/21] feat: move options to bottom sheet --- .../Prebuilt/components/AudioVideoToggle.jsx | 78 +++-- .../Prebuilt/components/EndSessionContent.jsx | 9 +- .../components/Footer/ConferencingFooter.jsx | 5 +- .../components/Footer/StreamingFooter.jsx | 3 + .../IconButtonWithOptions.jsx | 18 +- .../src/Prebuilt/components/LeaveRoom.jsx | 223 ++------------- .../components/MoreSettings/ActionTile.jsx | 29 ++ .../MoreSettings/ChangeNameContent.jsx | 89 ++++++ .../MoreSettings/ChangeNameModal.jsx | 85 ++---- .../components/MoreSettings/MoreSettings.jsx | 267 +----------------- .../MoreSettings/MuteAllContent.jsx | 60 ++++ .../components/MoreSettings/MuteAllModal.jsx | 81 +++--- .../SplitComponents/DesktopLeaveRoom.jsx | 116 ++++++++ .../SplitComponents/DesktopOptions.jsx | 249 ++++++++++++++++ .../SplitComponents/MwebLeaveRoom.jsx | 87 ++++++ .../SplitComponents/MwebOptions.jsx | 146 ++++++++++ .../VirtualBackground/VirtualBackground.jsx | 19 +- 17 files changed, 954 insertions(+), 610 deletions(-) create mode 100644 packages/roomkit-react/src/Prebuilt/components/MoreSettings/ActionTile.jsx create mode 100644 packages/roomkit-react/src/Prebuilt/components/MoreSettings/ChangeNameContent.jsx create mode 100644 packages/roomkit-react/src/Prebuilt/components/MoreSettings/MuteAllContent.jsx create mode 100644 packages/roomkit-react/src/Prebuilt/components/MoreSettings/SplitComponents/DesktopLeaveRoom.jsx create mode 100644 packages/roomkit-react/src/Prebuilt/components/MoreSettings/SplitComponents/DesktopOptions.jsx create mode 100644 packages/roomkit-react/src/Prebuilt/components/MoreSettings/SplitComponents/MwebLeaveRoom.jsx create mode 100644 packages/roomkit-react/src/Prebuilt/components/MoreSettings/SplitComponents/MwebOptions.jsx diff --git a/packages/roomkit-react/src/Prebuilt/components/AudioVideoToggle.jsx b/packages/roomkit-react/src/Prebuilt/components/AudioVideoToggle.jsx index e90a333709..50b1bfd3ba 100644 --- a/packages/roomkit-react/src/Prebuilt/components/AudioVideoToggle.jsx +++ b/packages/roomkit-react/src/Prebuilt/components/AudioVideoToggle.jsx @@ -68,35 +68,61 @@ export const AudioVideoToggle = ({ hideOptions = false }) => { return ( {toggleAudio ? ( - : - } - active={isLocalAudioEnabled} - onClick={toggleAudio} - key="toggleAudio" - hideOptions={hideOptions} - /> + hideOptions ? ( + + + {!isLocalAudioEnabled ? ( + + ) : ( + + )} + + + ) : ( + + ) : ( + + ) + } + active={isLocalAudioEnabled} + onClick={toggleAudio} + key="toggleAudio" + /> + ) ) : null} {toggleVideo ? ( - - ) : ( - - ) - } - key="toggleVideo" - active={isLocalVideoEnabled} - onClick={toggleVideo} - hideOptions={hideOptions} - /> + hideOptions ? ( + + + {!isLocalVideoEnabled ? ( + + ) : ( + + )} + + + ) : ( + + ) : ( + + ) + } + key="toggleVideo" + active={isLocalVideoEnabled} + onClick={toggleVideo} + /> + ) ) : null} {localVideoTrack?.facingMode ? ( diff --git a/packages/roomkit-react/src/Prebuilt/components/EndSessionContent.jsx b/packages/roomkit-react/src/Prebuilt/components/EndSessionContent.jsx index 4d76eb2780..5eeba636d8 100644 --- a/packages/roomkit-react/src/Prebuilt/components/EndSessionContent.jsx +++ b/packages/roomkit-react/src/Prebuilt/components/EndSessionContent.jsx @@ -2,8 +2,10 @@ import { AlertTriangleIcon, CrossIcon } from '@100mslive/react-icons'; import { Button } from '../../Button'; import { Box, Flex } from '../../Layout'; import { Text } from '../../Text'; +import { useShowStreamingUI } from '../common/hooks'; export const EndSessionContent = ({ setShowEndRoomAlert, endRoom, isModal = false }) => { + const showStreamingUI = useShowStreamingUI(); return ( - End Session + End {showStreamingUI ? 'Stream' : 'Session'} {isModal ? null : ( setShowEndRoomAlert(false)}> @@ -24,7 +26,8 @@ export const EndSessionContent = ({ setShowEndRoomAlert, endRoom, isModal = fals )} - The session will end for everyone and all the activities will stop. You can't undo this action. + The {showStreamingUI ? 'stream' : 'session'} will end for everyone and all the activities will stop. You can't + undo this action. diff --git a/packages/roomkit-react/src/Prebuilt/components/Footer/ConferencingFooter.jsx b/packages/roomkit-react/src/Prebuilt/components/Footer/ConferencingFooter.jsx index c5175d2f84..51c3d28cf4 100644 --- a/packages/roomkit-react/src/Prebuilt/components/Footer/ConferencingFooter.jsx +++ b/packages/roomkit-react/src/Prebuilt/components/Footer/ConferencingFooter.jsx @@ -6,7 +6,6 @@ import { AudioVideoToggle } from '../AudioVideoToggle'; import { EmojiReaction } from '../EmojiReaction'; import { LeaveRoom } from '../LeaveRoom'; import { MoreSettings } from '../MoreSettings/MoreSettings'; -// import { PIP } from '../PIP'; import { ScreenshareToggle } from '../ScreenShare'; import { ChatToggle } from './ChatToggle'; import { ParticipantCount } from './ParticipantList'; @@ -20,10 +19,10 @@ export const ConferencingFooter = () => { const isVideoOn = useHMSStore(selectIsLocalVideoEnabled); return ( - + {isMobile ? ( <> - + diff --git a/packages/roomkit-react/src/Prebuilt/components/Footer/StreamingFooter.jsx b/packages/roomkit-react/src/Prebuilt/components/Footer/StreamingFooter.jsx index 46a7055285..83708e75c9 100644 --- a/packages/roomkit-react/src/Prebuilt/components/Footer/StreamingFooter.jsx +++ b/packages/roomkit-react/src/Prebuilt/components/Footer/StreamingFooter.jsx @@ -17,6 +17,7 @@ export const StreamingFooter = () => { flexWrap: 'nowrap', '@md': { justifyContent: 'center', + gap: '$10', }, }} > @@ -25,6 +26,7 @@ export const StreamingFooter = () => { '@md': { w: 'unset', p: '0', + gap: '$10', }, }} > @@ -35,6 +37,7 @@ export const StreamingFooter = () => { css={{ '@md': { w: 'unset', + gap: '$10', }, }} > diff --git a/packages/roomkit-react/src/Prebuilt/components/IconButtonWithOptions/IconButtonWithOptions.jsx b/packages/roomkit-react/src/Prebuilt/components/IconButtonWithOptions/IconButtonWithOptions.jsx index 395d4b84a1..b5d20a6c80 100644 --- a/packages/roomkit-react/src/Prebuilt/components/IconButtonWithOptions/IconButtonWithOptions.jsx +++ b/packages/roomkit-react/src/Prebuilt/components/IconButtonWithOptions/IconButtonWithOptions.jsx @@ -5,12 +5,6 @@ import { styled } from '../../../Theme'; import { Tooltip } from '../../../Tooltip'; import IconButton from '../../IconButton'; -const iconButtonWithoutOptionsCSS = { - mx: 0, - borderTopRightRadius: '$1', - borderBottomRightRadius: '$1', -}; - const IconSection = styled(IconButton, { w: 'unset', h: '$14', @@ -19,7 +13,11 @@ const IconSection = styled(IconButton, { borderTopRightRadius: 0, borderColor: '$border_default', borderBottomRightRadius: 0, - '@md': iconButtonWithoutOptionsCSS, + '@md': { + mx: 0, + borderTopRightRadius: '$1', + borderBottomRightRadius: '$1', + }, }); const OptionsSection = styled(IconButton, { @@ -47,14 +45,12 @@ export const IconButtonWithOptions = ({ onClick = () => { return; }, - - hideOptions = false, }) => { const bgCss = { backgroundColor: active ? '$transparent' : '$secondary_dim' }; const iconCss = { color: active ? '$on_surface_high' : '$on_primary_high' }; return ( - + {icon} @@ -63,7 +59,7 @@ export const IconButtonWithOptions = ({ - + diff --git a/packages/roomkit-react/src/Prebuilt/components/LeaveRoom.jsx b/packages/roomkit-react/src/Prebuilt/components/LeaveRoom.jsx index f5d1c65a70..d851cf3f5c 100644 --- a/packages/roomkit-react/src/Prebuilt/components/LeaveRoom.jsx +++ b/packages/roomkit-react/src/Prebuilt/components/LeaveRoom.jsx @@ -1,36 +1,24 @@ -import React, { Fragment, useState } from 'react'; +import React from 'react'; import { useParams } from 'react-router-dom'; import { useMedia } from 'react-use'; import { selectIsConnectedToRoom, selectPermissions, useHMSActions, useHMSStore } from '@100mslive/react-sdk'; -import { ExitIcon, HangUpIcon, StopIcon, VerticalMenuIcon } from '@100mslive/react-icons'; +import { DesktopLeaveRoom } from './MoreSettings/SplitComponents/DesktopLeaveRoom'; +import { MwebLeaveRoom } from './MoreSettings/SplitComponents/MwebLeaveRoom'; import { ToastManager } from './Toast/ToastManager'; -import { Dropdown } from '../../Dropdown'; import { IconButton } from '../../IconButton'; -import { Box, Flex } from '../../Layout'; -import { Dialog } from '../../Modal'; -import { Sheet } from '../../Sheet'; -import { Text } from '../../Text'; import { config as cssConfig, styled } from '../../Theme'; -import { Tooltip } from '../../Tooltip'; import { useHMSPrebuiltContext } from '../AppContext'; -import { EndSessionContent } from './EndSessionContent'; -import { LeaveCard } from './LeaveCard'; -import { useDropdownList } from './hooks/useDropdownList'; import { useNavigation } from './hooks/useNavigation'; -import { useShowStreamingUI } from '../common/hooks'; -export const LeaveRoom = ({}) => { +export const LeaveRoom = () => { const navigate = useNavigation(); const params = useParams(); - const [open, setOpen] = useState(false); - const [showEndRoomAlert, setShowEndRoomAlert] = useState(false); const isConnected = useHMSStore(selectIsConnectedToRoom); const permissions = useHMSStore(selectPermissions); + const isMobile = useMedia(cssConfig.media.md); + const hmsActions = useHMSActions(); const { showLeave, onLeave } = useHMSPrebuiltContext(); - const isMobile = useMedia(cssConfig.media.md); - const showStreamingUI = useShowStreamingUI(); - useDropdownList({ open, name: 'LeaveRoom' }); const redirectToLeavePage = () => { if (showLeave) { @@ -57,201 +45,26 @@ export const LeaveRoom = ({}) => { if (!permissions || !isConnected) { return null; } - - if (isMobile) { - return ( - - {permissions.endRoom ? ( - - - - - {!showStreamingUI ? ( - - - - ) : ( - - - - - - Leave Studio - - - )} - - - - - } - onClick={leaveRoom} - css={{ pt: 0, mt: '$10' }} - /> - } - onClick={() => { - setOpen(false); - setShowEndRoomAlert(true); - }} - /> - - - ) : ( - - - - {showStreamingUI ? ( - - - - ) : ( - - )} - - - - )} - - - - - - - ); - } - - return ( - - {permissions.endRoom ? ( - - - - {!showStreamingUI ? ( - - - - ) : ( - - - - - - Leave Studio - - - )} - - - - - - - - - - - } - onClick={leaveRoom} - css={{ p: 0 }} - /> - - - } - onClick={() => { - setOpen(false); - setShowEndRoomAlert(true); - }} - css={{ p: 0 }} - /> - - - - - ) : ( - - - - {showStreamingUI ? ( - - - - ) : ( - - )} - - - - )} - - - - - - - - - - + return isMobile ? ( + + ) : ( + ); }; const LeaveIconButton = styled(IconButton, { color: '$on_primary_high', h: '$14', - px: '$6', + px: '$8', r: '$1', bg: '$alert_error_default', '&:not([disabled]):hover': { - bg: '$alert_error_default', + bg: '$alert_error_bright', }, '&:not([disabled]):active': { bg: '$alert_error_default', @@ -268,6 +81,6 @@ const MenuTriggerButton = styled(LeaveIconButton, { borderBottomLeftRadius: 0, px: '$3', '@md': { - display: 'none', + px: '$2', }, }); diff --git a/packages/roomkit-react/src/Prebuilt/components/MoreSettings/ActionTile.jsx b/packages/roomkit-react/src/Prebuilt/components/MoreSettings/ActionTile.jsx new file mode 100644 index 0000000000..c1107e2058 --- /dev/null +++ b/packages/roomkit-react/src/Prebuilt/components/MoreSettings/ActionTile.jsx @@ -0,0 +1,29 @@ +import { Flex } from '../../../Layout'; +import { Text } from '../../../Text'; + +export const ActionTile = ({ icon, title, active, onClick, disabled = false, setOpenSettingsSheet: setSheet }) => { + return ( + { + if (!disabled) { + onClick(); + setSheet(false); + } + }} + css={{ + p: '$4 $2', + bg: active ? '$surface_bright' : '', + color: disabled ? '$on_surface_low' : '$on_surface_high', + gap: '$4', + r: '$1', + }} + > + {icon} + + {title} + + + ); +}; diff --git a/packages/roomkit-react/src/Prebuilt/components/MoreSettings/ChangeNameContent.jsx b/packages/roomkit-react/src/Prebuilt/components/MoreSettings/ChangeNameContent.jsx new file mode 100644 index 0000000000..8b680c3b7d --- /dev/null +++ b/packages/roomkit-react/src/Prebuilt/components/MoreSettings/ChangeNameContent.jsx @@ -0,0 +1,89 @@ +import { ChevronLeftIcon, CrossIcon } from '@100mslive/react-icons'; +import { Button } from '../../../Button'; +import { Input } from '../../../Input'; +import { Box, Flex } from '../../../Layout'; +import { Text } from '../../../Text'; + +export const ChangeNameContent = ({ + changeName, + setCurrentName, + currentName, + localPeerName, + isMobile, + onExit, + onBackClick, +}) => { + return ( + { + e.preventDefault(); + await changeName(); + }} + > + + {isMobile ? : null} + Change Name + + + + + + { + setCurrentName(e.target.value); + }} + autoComplete="name" + required + data-testid="change_name_field" + /> + + + + {isMobile ? null : ( + + )} + + + + + ); +}; diff --git a/packages/roomkit-react/src/Prebuilt/components/MoreSettings/ChangeNameModal.jsx b/packages/roomkit-react/src/Prebuilt/components/MoreSettings/ChangeNameModal.jsx index d0e99e667b..bcdeb9eae3 100644 --- a/packages/roomkit-react/src/Prebuilt/components/MoreSettings/ChangeNameModal.jsx +++ b/packages/roomkit-react/src/Prebuilt/components/MoreSettings/ChangeNameModal.jsx @@ -1,14 +1,18 @@ import React, { useState } from 'react'; +import { useMedia } from 'react-use'; import { selectLocalPeerName, useHMSActions, useHMSStore } from '@100mslive/react-sdk'; -import { Box, Button, Dialog, Flex, Input, Text } from '../../../'; +import { config as cssConfig, Dialog } from '../../../'; +import { Sheet } from '../../../Sheet'; import { ToastManager } from '../Toast/ToastManager'; +import { ChangeNameContent } from './ChangeNameContent'; import { UserPreferencesKeys, useUserPreferences } from '../hooks/useUserPreferences'; -export const ChangeNameModal = ({ onOpenChange }) => { +export const ChangeNameModal = ({ onOpenChange, openParentSheet = null }) => { const [previewPreference, setPreviewPreference] = useUserPreferences(UserPreferencesKeys.PREVIEW); const hmsActions = useHMSActions(); const localPeerName = useHMSStore(selectLocalPeerName); const [currentName, setCurrentName] = useState(localPeerName); + const isMobile = useMedia(cssConfig.media.md); const changeName = async () => { const name = currentName.trim(); @@ -29,62 +33,35 @@ export const ChangeNameModal = ({ onOpenChange }) => { } }; + const props = { + changeName, + setCurrentName, + currentName, + localPeerName, + isMobile, + onExit: () => onOpenChange(false), + onBackClick: () => { + onOpenChange(false); + openParentSheet(); + }, + }; + + if (isMobile) { + return ( + + + + + + ); + } + return ( - - - Change Name - -
{ - e.preventDefault(); - await changeName(); - }} - > - - { - setCurrentName(e.target.value); - }} - autoComplete="name" - required - data-testid="change_name_field" - /> - - - - - - - - - - - - -
+ +
diff --git a/packages/roomkit-react/src/Prebuilt/components/MoreSettings/MoreSettings.jsx b/packages/roomkit-react/src/Prebuilt/components/MoreSettings/MoreSettings.jsx index 34f4f1d9b8..6ab8112628 100644 --- a/packages/roomkit-react/src/Prebuilt/components/MoreSettings/MoreSettings.jsx +++ b/packages/roomkit-react/src/Prebuilt/components/MoreSettings/MoreSettings.jsx @@ -1,259 +1,10 @@ -import React, { Fragment, useState } from 'react'; -import Hls from 'hls.js'; -import { - selectAppData, - selectIsAllowedToPublish, - selectLocalPeerID, - selectLocalPeerRoleName, - selectPermissions, - useHMSActions, - useHMSStore, -} from '@100mslive/react-sdk'; -import { - BrbIcon, - CheckIcon, - DragHandleIcon, - HandIcon, - InfoIcon, - MicOffIcon, - PencilIcon, - PipIcon, - SettingsIcon, -} from '@100mslive/react-icons'; -import { Box, Checkbox, Dropdown, Flex, Text, Tooltip } from '../../../'; -import IconButton from '../../IconButton'; -import { PIP } from '../PIP'; -import { RoleChangeModal } from '../RoleChangeModal'; -import SettingsModal from '../Settings/SettingsModal'; -import StartRecording from '../Settings/StartRecording'; -import { StatsForNerds } from '../StatsForNerds'; -import { BulkRoleChangeModal } from './BulkRoleChangeModal'; -import { ChangeNameModal } from './ChangeNameModal'; -import { ChangeSelfRole } from './ChangeSelfRole'; -import { EmbedUrl, EmbedUrlModal } from './EmbedUrl'; -import { FullScreenItem } from './FullScreenItem'; -import { MuteAllModal } from './MuteAllModal'; -import { useDropdownList } from '../hooks/useDropdownList'; -import { useIsFeatureEnabled } from '../hooks/useFeatures'; -import { useMyMetadata } from '../hooks/useMetadata'; -import { useShowStreamingUI } from '../../common/hooks'; -import { FeatureFlags } from '../../services/FeatureFlags'; -import { APP_DATA, FEATURE_LIST, isAndroid, isIOS, isMacOS } from '../../common/constants'; - -const isMobileOS = isAndroid || isIOS; - -const MODALS = { - CHANGE_NAME: 'changeName', - SELF_ROLE_CHANGE: 'selfRoleChange', - MORE_SETTINGS: 'moreSettings', - START_RECORDING: 'startRecording', - DEVICE_SETTINGS: 'deviceSettings', - STATS_FOR_NERDS: 'statsForNerds', - BULK_ROLE_CHANGE: 'bulkRoleChange', - MUTE_ALL: 'muteAll', - EMBED_URL: 'embedUrl', -}; - -export const MoreSettings = ({}) => { - const permissions = useHMSStore(selectPermissions); - const isAllowedToPublish = useHMSStore(selectIsAllowedToPublish); - const localPeerId = useHMSStore(selectLocalPeerID); - const localPeerRole = useHMSStore(selectLocalPeerRoleName); - const hmsActions = useHMSActions(); - const enablHlsStats = useHMSStore(selectAppData(APP_DATA.hlsStats)); - const isChangeNameEnabled = useIsFeatureEnabled(FEATURE_LIST.CHANGE_NAME); - const isEmbedEnabled = useIsFeatureEnabled(FEATURE_LIST.EMBED_URL); - const isSFNEnabled = useIsFeatureEnabled(FEATURE_LIST.STARTS_FOR_NERDS); - const [openModals, setOpenModals] = useState(new Set()); - const { isHandRaised, isBRBOn, toggleHandRaise, toggleBRB } = useMyMetadata(); - const isHandRaiseEnabled = useIsFeatureEnabled(FEATURE_LIST.HAND_RAISE); - const isBRBEnabled = useIsFeatureEnabled(FEATURE_LIST.BRB); - const isPIPEnabled = useIsFeatureEnabled(FEATURE_LIST.PICTURE_IN_PICTURE); - const showStreamingUI = useShowStreamingUI(); - - useDropdownList({ open: openModals.size > 0, name: 'MoreSettings' }); - - const updateState = (modalName, value) => { - setOpenModals(modals => { - const copy = new Set(modals); - if (value) { - copy.add(modalName); - } else { - copy.delete(modalName); - } - return copy; - }); - }; - - return ( - - updateState(MODALS.MORE_SETTINGS, value)} - > - - - - - - - - - - - - {isHandRaiseEnabled && !showStreamingUI ? ( - - - - Raise Hand - - - {isHandRaised ? : null} - - - ) : null} - - {isBRBEnabled && !showStreamingUI ? ( - - - - Be Right Back - - - {isBRBOn ? : null} - - - ) : null} - - {(isBRBEnabled || isHandRaiseEnabled) && !showStreamingUI ? ( - - ) : null} - - {isPIPEnabled ? ( - - - - - Picture in picture mode - -
- } - /> - - ) : null} - - {isChangeNameEnabled && ( - updateState(MODALS.CHANGE_NAME, true)} data-testid="change_name_btn"> - - - Change Name - - - )} - updateState(MODALS.SELF_ROLE_CHANGE, true)} /> - - {isAllowedToPublish.screen && isEmbedEnabled && ( - updateState(MODALS.EMBED_URL, true)} /> - )} - - {permissions.mute && ( - updateState(MODALS.MUTE_ALL, true)} data-testid="mute_all_btn"> - - - Mute All - - - )} - - - updateState(MODALS.DEVICE_SETTINGS, true)} data-testid="device_settings_btn"> - - - Settings - - - - {FeatureFlags.enableStatsForNerds && - isSFNEnabled && - (localPeerRole === 'hls-viewer' ? ( - Hls.isSupported() ? ( - hmsActions.setAppData(APP_DATA.hlsStats, !enablHlsStats)} - data-testid="hls_stats" - > - hmsActions.setAppData(APP_DATA.hlsStats, !enablHlsStats)} - > - - - - - - - Show HLS Stats - - {!isMobileOS ? ( - - {`${isMacOS ? '⌘' : 'ctrl'} + ]`} - - ) : null} - - - ) : null - ) : ( - updateState(MODALS.STATS_FOR_NERDS, true)} - data-testid="stats_for_nreds_btn" - > - - - Stats for Nerds - - - ))} - - - {openModals.has(MODALS.BULK_ROLE_CHANGE) && ( - updateState(MODALS.BULK_ROLE_CHANGE, value)} /> - )} - {openModals.has(MODALS.MUTE_ALL) && updateState(MODALS.MUTE_ALL, value)} />} - {openModals.has(MODALS.CHANGE_NAME) && ( - updateState(MODALS.CHANGE_NAME, value)} /> - )} - {openModals.has(MODALS.DEVICE_SETTINGS) && ( - updateState(MODALS.DEVICE_SETTINGS, value)} /> - )} - {FeatureFlags.enableStatsForNerds && openModals.has(MODALS.STATS_FOR_NERDS) && ( - updateState(MODALS.STATS_FOR_NERDS, value)} /> - )} - {openModals.has(MODALS.SELF_ROLE_CHANGE) && ( - updateState(MODALS.SELF_ROLE_CHANGE, value)} /> - )} - {openModals.has(MODALS.START_RECORDING) && ( - updateState(MODALS.START_RECORDING, value)} /> - )} - {openModals.has(MODALS.EMBED_URL) && ( - updateState(MODALS.EMBED_URL, value)} /> - )} -
- ); +import React from 'react'; +import { useMedia } from 'react-use'; +import { DesktopOptions } from './SplitComponents/DesktopOptions'; +import { MwebOptions } from './SplitComponents/MwebOptions'; +import { config as cssConfig } from '../../../'; + +export const MoreSettings = () => { + const isMobile = useMedia(cssConfig.media.md); + return isMobile ? : ; }; diff --git a/packages/roomkit-react/src/Prebuilt/components/MoreSettings/MuteAllContent.jsx b/packages/roomkit-react/src/Prebuilt/components/MoreSettings/MuteAllContent.jsx new file mode 100644 index 0000000000..2b67ab0bc2 --- /dev/null +++ b/packages/roomkit-react/src/Prebuilt/components/MoreSettings/MuteAllContent.jsx @@ -0,0 +1,60 @@ +import { Button } from '../../../Button'; +import { Label } from '../../../Label'; +import { Flex } from '../../../Layout'; +import { RadioGroup } from '../../../RadioGroup'; +import { Text } from '../../../Text'; +import { DialogRow, DialogSelect } from '../../primitives/DialogContent'; + +export const MuteAllContent = props => { + const roles = props.roles || []; + return ( + <> + ({ label: role, value: role }))]} + selected={props.selectedRole} + keyField="value" + labelField="label" + onChange={props.setRole} + /> + + + + Track status + + + + + + + + + + + + + + + + + + + + ); +}; diff --git a/packages/roomkit-react/src/Prebuilt/components/MoreSettings/MuteAllModal.jsx b/packages/roomkit-react/src/Prebuilt/components/MoreSettings/MuteAllModal.jsx index c6b7e0252b..aca0d15517 100644 --- a/packages/roomkit-react/src/Prebuilt/components/MoreSettings/MuteAllModal.jsx +++ b/packages/roomkit-react/src/Prebuilt/components/MoreSettings/MuteAllModal.jsx @@ -1,8 +1,10 @@ import React, { useCallback, useState } from 'react'; import { useHMSActions } from '@100mslive/react-sdk'; import { MicOffIcon } from '@100mslive/react-icons'; -import { Button, Dialog, Flex, Label, RadioGroup, Text } from '../../../'; -import { DialogContent, DialogRow, DialogSelect } from '../../primitives/DialogContent'; +import { Dialog } from '../../../'; +import { Sheet } from '../../../Sheet'; +import { DialogContent } from '../../primitives/DialogContent'; +import { MuteAllContent } from './MuteAllContent'; import { useFilteredRoles } from '../../common/hooks'; const trackSourceOptions = [ @@ -17,7 +19,7 @@ const trackTypeOptions = [ { label: 'audio', value: 'audio' }, { label: 'video', value: 'video' }, ]; -export const MuteAllModal = ({ onOpenChange }) => { +export const MuteAllModal = ({ onOpenChange, isMobile = false }) => { const roles = useFilteredRoles(); const hmsActions = useHMSActions(); const [enabled, setEnabled] = useState(false); @@ -35,55 +37,36 @@ export const MuteAllModal = ({ onOpenChange }) => { onOpenChange(false); }, [selectedRole, enabled, trackType, selectedSource, hmsActions, onOpenChange]); + const props = { + muteAll, + roles, + enabled, + setEnabled, + trackType, + setTrackType, + selectedRole, + setRole, + selectedSource, + setSource, + trackSourceOptions, + trackTypeOptions, + isMobile, + }; + + if (isMobile) { + return ( + + + + + + ); + } + return ( - ({ label: role, value: role }))]} - selected={selectedRole} - keyField="value" - labelField="label" - onChange={setRole} - /> - - - - Track status - - - - - - - - - - - - - - - - - - + ); diff --git a/packages/roomkit-react/src/Prebuilt/components/MoreSettings/SplitComponents/DesktopLeaveRoom.jsx b/packages/roomkit-react/src/Prebuilt/components/MoreSettings/SplitComponents/DesktopLeaveRoom.jsx new file mode 100644 index 0000000000..66b29aaa50 --- /dev/null +++ b/packages/roomkit-react/src/Prebuilt/components/MoreSettings/SplitComponents/DesktopLeaveRoom.jsx @@ -0,0 +1,116 @@ +import React, { Fragment, useState } from 'react'; +import { selectIsConnectedToRoom, selectPermissions, useHMSStore } from '@100mslive/react-sdk'; +import { ExitIcon, HangUpIcon, StopIcon, VerticalMenuIcon } from '@100mslive/react-icons'; +import { Dropdown } from '../../../../Dropdown'; +import { Box, Flex } from '../../../../Layout'; +import { Dialog } from '../../../../Modal'; +import { Tooltip } from '../../../../Tooltip'; +import { EndSessionContent } from '../../EndSessionContent'; +import { LeaveCard } from '../../LeaveCard'; +import { useDropdownList } from '../../hooks/useDropdownList'; +import { useShowStreamingUI } from '../../../common/hooks'; + +export const DesktopLeaveRoom = ({ + menuTriggerButton: MenuTriggerButton, + leaveIconButton: LeaveIconButton, + leaveRoom, + endRoom, +}) => { + const [open, setOpen] = useState(false); + const [showEndRoomAlert, setShowEndRoomAlert] = useState(false); + const isConnected = useHMSStore(selectIsConnectedToRoom); + const permissions = useHMSStore(selectPermissions); + const showStreamingUI = useShowStreamingUI(); + useDropdownList({ open, name: 'LeaveRoom' }); + + if (!permissions || !isConnected) { + return null; + } + + return ( + + {permissions.endRoom ? ( + + + + + + + + + + + + + + + + + } + onClick={leaveRoom} + css={{ p: 0 }} + /> + + + } + onClick={() => { + setOpen(false); + setShowEndRoomAlert(true); + }} + css={{ p: 0 }} + /> + + + + + ) : ( + + + {showStreamingUI ? : } + + + )} + + + + + + + + + + + ); +}; diff --git a/packages/roomkit-react/src/Prebuilt/components/MoreSettings/SplitComponents/DesktopOptions.jsx b/packages/roomkit-react/src/Prebuilt/components/MoreSettings/SplitComponents/DesktopOptions.jsx new file mode 100644 index 0000000000..b809e9d08f --- /dev/null +++ b/packages/roomkit-react/src/Prebuilt/components/MoreSettings/SplitComponents/DesktopOptions.jsx @@ -0,0 +1,249 @@ +import React, { Fragment, useState } from 'react'; +import Hls from 'hls.js'; +import { + selectAppData, + selectIsAllowedToPublish, + selectLocalPeerID, + selectLocalPeerRoleName, + selectPermissions, + useHMSActions, + useHMSStore, +} from '@100mslive/react-sdk'; +import { + BrbIcon, + CheckIcon, + DragHandleIcon, + HandIcon, + InfoIcon, + MicOffIcon, + PencilIcon, + PipIcon, + SettingsIcon, +} from '@100mslive/react-icons'; +import { Checkbox, Dropdown, Flex, Text, Tooltip } from '../../../../'; +import IconButton from '../../../IconButton'; +import { PIP } from '../../PIP'; +import { RoleChangeModal } from '../../RoleChangeModal'; +import SettingsModal from '../../Settings/SettingsModal'; +import StartRecording from '../../Settings/StartRecording'; +import { StatsForNerds } from '../../StatsForNerds'; +import { BulkRoleChangeModal } from '.././BulkRoleChangeModal'; +import { ChangeNameModal } from '.././ChangeNameModal'; +import { ChangeSelfRole } from '.././ChangeSelfRole'; +import { EmbedUrl, EmbedUrlModal } from '.././EmbedUrl'; +import { FullScreenItem } from '.././FullScreenItem'; +import { MuteAllModal } from '.././MuteAllModal'; +import { useDropdownList } from '../../hooks/useDropdownList'; +import { useIsFeatureEnabled } from '../../hooks/useFeatures'; +import { useMyMetadata } from '../../hooks/useMetadata'; +import { FeatureFlags } from '../../../services/FeatureFlags'; +import { APP_DATA, FEATURE_LIST, isMacOS } from '../../../common/constants'; + +const MODALS = { + CHANGE_NAME: 'changeName', + SELF_ROLE_CHANGE: 'selfRoleChange', + MORE_SETTINGS: 'moreSettings', + START_RECORDING: 'startRecording', + DEVICE_SETTINGS: 'deviceSettings', + STATS_FOR_NERDS: 'statsForNerds', + BULK_ROLE_CHANGE: 'bulkRoleChange', + MUTE_ALL: 'muteAll', + EMBED_URL: 'embedUrl', +}; + +export const DesktopOptions = ({ showStreamingUI = false }) => { + const permissions = useHMSStore(selectPermissions); + const isAllowedToPublish = useHMSStore(selectIsAllowedToPublish); + const localPeerId = useHMSStore(selectLocalPeerID); + const localPeerRole = useHMSStore(selectLocalPeerRoleName); + const hmsActions = useHMSActions(); + const enablHlsStats = useHMSStore(selectAppData(APP_DATA.hlsStats)); + const isChangeNameEnabled = useIsFeatureEnabled(FEATURE_LIST.CHANGE_NAME); + const isEmbedEnabled = useIsFeatureEnabled(FEATURE_LIST.EMBED_URL); + const isSFNEnabled = useIsFeatureEnabled(FEATURE_LIST.STARTS_FOR_NERDS); + const [openModals, setOpenModals] = useState(new Set()); + const { isHandRaised, isBRBOn, toggleHandRaise, toggleBRB } = useMyMetadata(); + const isHandRaiseEnabled = useIsFeatureEnabled(FEATURE_LIST.HAND_RAISE); + const isBRBEnabled = useIsFeatureEnabled(FEATURE_LIST.BRB); + const isPIPEnabled = useIsFeatureEnabled(FEATURE_LIST.PICTURE_IN_PICTURE); + + useDropdownList({ open: openModals.size > 0, name: 'MoreSettings' }); + + const updateState = (modalName, value) => { + setOpenModals(modals => { + const copy = new Set(modals); + if (value) { + copy.add(modalName); + } else { + copy.delete(modalName); + } + return copy; + }); + }; + + return ( + + updateState(MODALS.MORE_SETTINGS, value)} + > + + + + + + + + + + {isHandRaiseEnabled && !showStreamingUI ? ( + + + + Raise Hand + + + {isHandRaised ? : null} + + + ) : null} + + {isBRBEnabled && !showStreamingUI ? ( + + + + Be Right Back + + + {isBRBOn ? : null} + + + ) : null} + + {(isBRBEnabled || isHandRaiseEnabled) && !showStreamingUI ? ( + + ) : null} + + {isPIPEnabled ? ( + + + + + Picture in picture mode + +
+ } + /> + + ) : null} + + {isChangeNameEnabled && ( + updateState(MODALS.CHANGE_NAME, true)} data-testid="change_name_btn"> + + + Change Name + + + )} + updateState(MODALS.SELF_ROLE_CHANGE, true)} /> + + {isAllowedToPublish.screen && isEmbedEnabled && ( + updateState(MODALS.EMBED_URL, true)} /> + )} + + {permissions.mute && ( + updateState(MODALS.MUTE_ALL, true)} data-testid="mute_all_btn"> + + + Mute All + + + )} + + + updateState(MODALS.DEVICE_SETTINGS, true)} data-testid="device_settings_btn"> + + + Settings + + + + {FeatureFlags.enableStatsForNerds && + isSFNEnabled && + (localPeerRole === 'hls-viewer' ? ( + Hls.isSupported() ? ( + hmsActions.setAppData(APP_DATA.hlsStats, !enablHlsStats)} + data-testid="hls_stats" + > + hmsActions.setAppData(APP_DATA.hlsStats, !enablHlsStats)} + > + + + + + + + Show HLS Stats + + + + {`${isMacOS ? '⌘' : 'ctrl'} + ]`} + + + + ) : null + ) : ( + updateState(MODALS.STATS_FOR_NERDS, true)} + data-testid="stats_for_nreds_btn" + > + + + Stats for Nerds + + + ))} + + + {openModals.has(MODALS.BULK_ROLE_CHANGE) && ( + updateState(MODALS.BULK_ROLE_CHANGE, value)} /> + )} + {openModals.has(MODALS.MUTE_ALL) && updateState(MODALS.MUTE_ALL, value)} />} + {openModals.has(MODALS.CHANGE_NAME) && ( + updateState(MODALS.CHANGE_NAME, value)} /> + )} + {openModals.has(MODALS.START_RECORDING) && ( + updateState(MODALS.START_RECORDING, value)} /> + )} + {openModals.has(MODALS.DEVICE_SETTINGS) && ( + updateState(MODALS.DEVICE_SETTINGS, value)} /> + )} + {FeatureFlags.enableStatsForNerds && openModals.has(MODALS.STATS_FOR_NERDS) && ( + updateState(MODALS.STATS_FOR_NERDS, value)} /> + )} + {openModals.has(MODALS.SELF_ROLE_CHANGE) && ( + updateState(MODALS.SELF_ROLE_CHANGE, value)} /> + )} + {openModals.has(MODALS.EMBED_URL) && ( + updateState(MODALS.EMBED_URL, value)} /> + )} +
+ ); +}; diff --git a/packages/roomkit-react/src/Prebuilt/components/MoreSettings/SplitComponents/MwebLeaveRoom.jsx b/packages/roomkit-react/src/Prebuilt/components/MoreSettings/SplitComponents/MwebLeaveRoom.jsx new file mode 100644 index 0000000000..489eb2495c --- /dev/null +++ b/packages/roomkit-react/src/Prebuilt/components/MoreSettings/SplitComponents/MwebLeaveRoom.jsx @@ -0,0 +1,87 @@ +import React, { Fragment, useState } from 'react'; +import { selectIsConnectedToRoom, selectPermissions, useHMSStore } from '@100mslive/react-sdk'; +import { ExitIcon, HangUpIcon, StopIcon } from '@100mslive/react-icons'; +import { Box } from '../../../../Layout'; +import { Sheet } from '../../../../Sheet'; +import { Tooltip } from '../../../../Tooltip'; +import { EndSessionContent } from '../../EndSessionContent'; +import { LeaveCard } from '../../LeaveCard'; +import { useDropdownList } from '../../hooks/useDropdownList'; +import { useShowStreamingUI } from '../../../common/hooks'; + +export const MwebLeaveRoom = ({ leaveIconButton: LeaveIconButton, endRoom, leaveRoom }) => { + const [open, setOpen] = useState(false); + const [showEndRoomAlert, setShowEndRoomAlert] = useState(false); + const isConnected = useHMSStore(selectIsConnectedToRoom); + const permissions = useHMSStore(selectPermissions); + + const showStreamingUI = useShowStreamingUI(); + useDropdownList({ open, name: 'LeaveRoom' }); + + if (!permissions || !isConnected) { + return null; + } + + return ( + + {permissions.endRoom ? ( + + + + + {!showStreamingUI ? : } + + + + + } + onClick={leaveRoom} + css={{ pt: 0, mt: '$10' }} + /> + } + onClick={() => { + setOpen(false); + setShowEndRoomAlert(true); + }} + /> + + + ) : ( + + + {showStreamingUI ? : } + + + )} + + + + + + + ); +}; diff --git a/packages/roomkit-react/src/Prebuilt/components/MoreSettings/SplitComponents/MwebOptions.jsx b/packages/roomkit-react/src/Prebuilt/components/MoreSettings/SplitComponents/MwebOptions.jsx new file mode 100644 index 0000000000..2b4ac1bad4 --- /dev/null +++ b/packages/roomkit-react/src/Prebuilt/components/MoreSettings/SplitComponents/MwebOptions.jsx @@ -0,0 +1,146 @@ +import React, { Suspense, useState } from 'react'; +import { selectIsLocalVideoEnabled, selectPermissions, useHMSStore } from '@100mslive/react-sdk'; +import { BrbIcon, CrossIcon, DragHandleIcon, HandIcon, MicOffIcon, PencilIcon } from '@100mslive/react-icons'; +import { Box, Tooltip } from '../../../../'; +import { Sheet } from '../../../../Sheet'; +import IconButton from '../../../IconButton'; +import { ActionTile } from '.././ActionTile'; +import { ChangeNameModal } from '.././ChangeNameModal'; +import { MuteAllModal } from '.././MuteAllModal'; +import { useDropdownList } from '../../hooks/useDropdownList'; +import { useIsFeatureEnabled } from '../../hooks/useFeatures'; +import { useMyMetadata } from '../../hooks/useMetadata'; +import { FEATURE_LIST } from '../../../common/constants'; + +const VirtualBackground = React.lazy(() => import('../../../plugins/VirtualBackground/VirtualBackground')); + +const MODALS = { + CHANGE_NAME: 'changeName', + SELF_ROLE_CHANGE: 'selfRoleChange', + MORE_SETTINGS: 'moreSettings', + START_RECORDING: 'startRecording', + DEVICE_SETTINGS: 'deviceSettings', + STATS_FOR_NERDS: 'statsForNerds', + BULK_ROLE_CHANGE: 'bulkRoleChange', + MUTE_ALL: 'muteAll', + EMBED_URL: 'embedUrl', +}; + +export const MwebOptions = () => { + const permissions = useHMSStore(selectPermissions); + const [openModals, setOpenModals] = useState(new Set()); + const { isHandRaised, isBRBOn, toggleHandRaise, toggleBRB } = useMyMetadata(); + const isHandRaiseEnabled = useIsFeatureEnabled(FEATURE_LIST.HAND_RAISE); + const isBRBEnabled = useIsFeatureEnabled(FEATURE_LIST.BRB); + const isVideoOn = useHMSStore(selectIsLocalVideoEnabled); + const [openSettingsSheet, setOpenSettingsSheet] = useState(false); + + useDropdownList({ open: openModals.size > 0, name: 'MoreSettings' }); + + const updateState = (modalName, value) => { + setOpenModals(modals => { + const copy = new Set(modals); + if (value) { + copy.add(modalName); + } else { + copy.delete(modalName); + } + return copy; + }); + }; + + return ( + <> + + + + + + + + + + + Options + + + + + + + + {isHandRaiseEnabled ? ( + } + onClick={toggleHandRaise} + active={isHandRaised} + setOpenSettingsSheet={setOpenSettingsSheet} + /> + ) : null} + {isBRBEnabled ? ( + } + onClick={toggleBRB} + active={isBRBOn} + setOpenSettingsSheet={setOpenSettingsSheet} + /> + ) : null} + {permissions.mute ? ( + } + onClick={() => updateState(MODALS.MUTE_ALL, true)} + setOpenSettingsSheet={setOpenSettingsSheet} + /> + ) : null} + } + onClick={() => updateState(MODALS.CHANGE_NAME, true)} + setOpenSettingsSheet={setOpenSettingsSheet} + /> + {isVideoOn ? ( + + + + ) : null} + + + + {openModals.has(MODALS.MUTE_ALL) && ( + updateState(MODALS.MUTE_ALL, value)} isMobile /> + )} + {openModals.has(MODALS.CHANGE_NAME) && ( + updateState(MODALS.CHANGE_NAME, value)} + openParentSheet={() => setOpenSettingsSheet(true)} + /> + )} + + ); +}; diff --git a/packages/roomkit-react/src/Prebuilt/plugins/VirtualBackground/VirtualBackground.jsx b/packages/roomkit-react/src/Prebuilt/plugins/VirtualBackground/VirtualBackground.jsx index 1c7258c4ff..31e1fdd434 100644 --- a/packages/roomkit-react/src/Prebuilt/plugins/VirtualBackground/VirtualBackground.jsx +++ b/packages/roomkit-react/src/Prebuilt/plugins/VirtualBackground/VirtualBackground.jsx @@ -9,6 +9,7 @@ import { useHMSStore, } from '@100mslive/react-sdk'; import { VirtualBackgroundIcon } from '@100mslive/react-icons'; +import { ActionTile } from '../../components/MoreSettings/ActionTile'; import { Loading } from '../../../Loading'; import { Tooltip } from '../../../Tooltip'; import IconButton from '../../IconButton'; @@ -16,13 +17,14 @@ import { useIsFeatureEnabled } from '../../components/hooks/useFeatures'; import { getRandomVirtualBackground } from './vbutils'; import { FEATURE_LIST } from '../../common/constants'; -export const VirtualBackground = () => { +export const VirtualBackground = ({ asActionTile = false }) => { const pluginRef = useRef(null); const hmsActions = useHMSActions(); const isAllowedToPublish = useHMSStore(selectIsAllowedToPublish); const role = useHMSStore(selectLocalPeerRole); const [isVBLoading, setIsVBLoading] = useState(false); const [isVBSupported, setIsVBSupported] = useState(false); + const [isVBOn, setIsVBOn] = useState(false); const localPeerVideoTrackID = useHMSStore(selectLocalVideoTrackID); const isVBPresent = useHMSStore(selectIsLocalVideoPluginPresent('HMSVB')); const isFeatureEnabled = useIsFeatureEnabled(FEATURE_LIST.VIDEO_PLUGINS); @@ -68,6 +70,21 @@ export const VirtualBackground = () => { if (!isAllowedToPublish.video || !isVBSupported || !isFeatureEnabled) { return null; } + if (asActionTile) { + return ( + } + onClick={() => { + setIsVBOn(!isVBOn); + !isVBPresent ? addPlugin() : removePlugin(); + }} + active={isVBOn} + disabled={isVBLoading} + data-testid="virtual_bg_btn" + /> + ); + } return ( Date: Fri, 11 Aug 2023 11:58:43 +0530 Subject: [PATCH 18/21] feat: flying emojis in bottom sheet --- .../src/Prebuilt/components/EmojiReaction.jsx | 83 ++----------------- .../Prebuilt/components/Footer/EmojiCard.jsx | 80 ++++++++++++++++++ .../components/MoreSettings/ActionTile.jsx | 7 +- .../SplitComponents/MwebOptions.jsx | 68 +++++++++++++-- .../components/Preview/PreviewJoin.jsx | 1 - .../components/Settings/DeviceSettings.jsx | 1 + .../components/Settings/SettingsModal.jsx | 3 +- 7 files changed, 153 insertions(+), 90 deletions(-) create mode 100644 packages/roomkit-react/src/Prebuilt/components/Footer/EmojiCard.jsx diff --git a/packages/roomkit-react/src/Prebuilt/components/EmojiReaction.jsx b/packages/roomkit-react/src/Prebuilt/components/EmojiReaction.jsx index 9de48c77c9..2fa9c8751b 100644 --- a/packages/roomkit-react/src/Prebuilt/components/EmojiReaction.jsx +++ b/packages/roomkit-react/src/Prebuilt/components/EmojiReaction.jsx @@ -1,75 +1,25 @@ -import React, { Fragment, useCallback, useMemo, useState } from 'react'; +import React, { Fragment, useState } from 'react'; import data from '@emoji-mart/data/sets/14/apple.json'; import { init } from 'emoji-mart'; -import { - selectAvailableRoleNames, - selectIsConnectedToRoom, - selectLocalPeerID, - selectLocalPeerRoleName, - useCustomEvent, - useHMSActions, - useHMSStore, - useRecordingStreaming, -} from '@100mslive/react-sdk'; +import { selectIsConnectedToRoom, useHMSStore } from '@100mslive/react-sdk'; import { EmojiIcon } from '@100mslive/react-icons'; +import { EmojiCard } from './Footer/EmojiCard'; import { Dropdown } from '../../Dropdown'; -import { Flex } from '../../Layout'; -import { styled } from '../../Theme'; import { Tooltip } from '../../Tooltip'; import IconButton from '../IconButton'; -import { useHLSViewerRole } from './AppData/useUISettings'; import { useDropdownList } from './hooks/useDropdownList'; import { useIsFeatureEnabled } from './hooks/useFeatures'; -import { EMOJI_REACTION_TYPE, FEATURE_LIST } from '../common/constants'; +import { FEATURE_LIST } from '../common/constants'; init({ data }); -// When changing emojis in the grid, keep in mind that the payload used in sendHLSTimedMetadata has a limit of 100 characters. Using bigger emoji Ids can cause the limit to be exceeded. -const emojiReactionList = [ - [{ emojiId: '+1' }, { emojiId: '-1' }, { emojiId: 'wave' }, { emojiId: 'clap' }, { emojiId: 'fire' }], - [{ emojiId: 'tada' }, { emojiId: 'heart_eyes' }, { emojiId: 'joy' }, { emojiId: 'open_mouth' }, { emojiId: 'sob' }], -]; - export const EmojiReaction = () => { const [open, setOpen] = useState(false); - const hmsActions = useHMSActions(); const isConnected = useHMSStore(selectIsConnectedToRoom); - const roles = useHMSStore(selectAvailableRoleNames); - const localPeerRole = useHMSStore(selectLocalPeerRoleName); - const localPeerId = useHMSStore(selectLocalPeerID); - const hlsViewerRole = useHLSViewerRole(); - const { isStreamingOn } = useRecordingStreaming(); const isFeatureEnabled = useIsFeatureEnabled(FEATURE_LIST.EMOJI_REACTION); - const filteredRoles = useMemo(() => roles.filter(role => role !== hlsViewerRole), [roles, hlsViewerRole]); useDropdownList({ open: open, name: 'EmojiReaction' }); - const onEmojiEvent = useCallback(data => { - window.showFlyingEmoji(data?.emojiId, data?.senderId); - }, []); - - const { sendEvent } = useCustomEvent({ - type: EMOJI_REACTION_TYPE, - onEvent: onEmojiEvent, - }); - - const sendReaction = async emojiId => { - const data = { - type: EMOJI_REACTION_TYPE, - emojiId: emojiId, - senderId: localPeerId, - }; - sendEvent(data, { roleNames: filteredRoles }); - if (isStreamingOn) { - await hmsActions.sendHLSTimedMetadata([ - { - payload: JSON.stringify(data), - duration: 2, - }, - ]); - } - }; - - if (!isConnected || localPeerRole === hlsViewerRole || !isFeatureEnabled) { + if (!isConnected || !isFeatureEnabled) { return null; } return ( @@ -83,30 +33,9 @@ export const EmojiReaction = () => { - {emojiReactionList.map((emojiLine, index) => ( - - {emojiLine.map(emoji => ( - sendReaction(emoji.emojiId)}> - - - ))} - - ))} + ); }; - -const EmojiContainer = styled('span', { - position: 'relative', - cursor: 'pointer', - width: '$16', - height: '$16', - p: '$4', - '&:hover': { - p: '7px', - bg: '$surface_brighter', - borderRadius: '$1', - }, -}); diff --git a/packages/roomkit-react/src/Prebuilt/components/Footer/EmojiCard.jsx b/packages/roomkit-react/src/Prebuilt/components/Footer/EmojiCard.jsx new file mode 100644 index 0000000000..09a2a0896b --- /dev/null +++ b/packages/roomkit-react/src/Prebuilt/components/Footer/EmojiCard.jsx @@ -0,0 +1,80 @@ +import React, { useCallback, useMemo } from 'react'; +import data from '@emoji-mart/data/sets/14/apple.json'; +import { init } from 'emoji-mart'; +import { + selectAvailableRoleNames, + selectLocalPeerID, + useCustomEvent, + useHMSActions, + useHMSStore, + useRecordingStreaming, +} from '@100mslive/react-sdk'; +import { Flex } from '../../../Layout'; +import { styled } from '../../../Theme'; +import { useHLSViewerRole } from '../AppData/useUISettings'; +import { EMOJI_REACTION_TYPE } from '../../common/constants'; + +init({ data }); + +// When changing emojis in the grid, keep in mind that the payload used in sendHLSTimedMetadata has a limit of 100 characters. Using bigger emoji Ids can cause the limit to be exceeded. +const emojiReactionList = [ + [{ emojiId: '+1' }, { emojiId: '-1' }, { emojiId: 'wave' }, { emojiId: 'clap' }, { emojiId: 'fire' }], + [{ emojiId: 'tada' }, { emojiId: 'heart_eyes' }, { emojiId: 'joy' }, { emojiId: 'open_mouth' }, { emojiId: 'sob' }], +]; + +export const EmojiCard = () => { + const hmsActions = useHMSActions(); + const roles = useHMSStore(selectAvailableRoleNames); + const localPeerId = useHMSStore(selectLocalPeerID); + const hlsViewerRole = useHLSViewerRole(); + const { isStreamingOn } = useRecordingStreaming(); + const filteredRoles = useMemo(() => roles.filter(role => role !== hlsViewerRole), [roles, hlsViewerRole]); + + const onEmojiEvent = useCallback(data => { + window.showFlyingEmoji(data?.emojiId, data?.senderId); + }, []); + + const { sendEvent } = useCustomEvent({ + type: EMOJI_REACTION_TYPE, + onEvent: onEmojiEvent, + }); + + const sendReaction = async emojiId => { + const data = { + type: EMOJI_REACTION_TYPE, + emojiId: emojiId, + senderId: localPeerId, + }; + sendEvent(data, { roleNames: filteredRoles }); + if (isStreamingOn) { + await hmsActions.sendHLSTimedMetadata([ + { + payload: JSON.stringify(data), + duration: 2, + }, + ]); + } + }; + return emojiReactionList.map((emojiLine, index) => ( + + {emojiLine.map(emoji => ( + sendReaction(emoji.emojiId)}> + + + ))} + + )); +}; + +const EmojiContainer = styled('span', { + position: 'relative', + cursor: 'pointer', + width: '$16', + height: '$16', + p: '$4', + '&:hover': { + p: '7px', + bg: '$surface_brighter', + borderRadius: '$1', + }, +}); diff --git a/packages/roomkit-react/src/Prebuilt/components/MoreSettings/ActionTile.jsx b/packages/roomkit-react/src/Prebuilt/components/MoreSettings/ActionTile.jsx index c1107e2058..cd9f37242e 100644 --- a/packages/roomkit-react/src/Prebuilt/components/MoreSettings/ActionTile.jsx +++ b/packages/roomkit-react/src/Prebuilt/components/MoreSettings/ActionTile.jsx @@ -1,7 +1,7 @@ import { Flex } from '../../../Layout'; import { Text } from '../../../Text'; -export const ActionTile = ({ icon, title, active, onClick, disabled = false, setOpenSettingsSheet: setSheet }) => { +export const ActionTile = ({ icon, title, active, onClick, disabled = false, setOpenOptionsSheet }) => { return ( { if (!disabled) { onClick(); - setSheet(false); + setOpenOptionsSheet(false); } }} css={{ @@ -18,6 +18,9 @@ export const ActionTile = ({ icon, title, active, onClick, disabled = false, set color: disabled ? '$on_surface_low' : '$on_surface_high', gap: '$4', r: '$1', + '&:hover': { + bg: '$surface_bright', + }, }} > {icon} diff --git a/packages/roomkit-react/src/Prebuilt/components/MoreSettings/SplitComponents/MwebOptions.jsx b/packages/roomkit-react/src/Prebuilt/components/MoreSettings/SplitComponents/MwebOptions.jsx index 2b4ac1bad4..71e7324204 100644 --- a/packages/roomkit-react/src/Prebuilt/components/MoreSettings/SplitComponents/MwebOptions.jsx +++ b/packages/roomkit-react/src/Prebuilt/components/MoreSettings/SplitComponents/MwebOptions.jsx @@ -1,9 +1,21 @@ -import React, { Suspense, useState } from 'react'; +import React, { Suspense, useRef, useState } from 'react'; +import { useClickAway } from 'react-use'; import { selectIsLocalVideoEnabled, selectPermissions, useHMSStore } from '@100mslive/react-sdk'; -import { BrbIcon, CrossIcon, DragHandleIcon, HandIcon, MicOffIcon, PencilIcon } from '@100mslive/react-icons'; +import { + BrbIcon, + CrossIcon, + DragHandleIcon, + EmojiIcon, + HandIcon, + MicOffIcon, + PencilIcon, + SettingsIcon, +} from '@100mslive/react-icons'; import { Box, Tooltip } from '../../../../'; import { Sheet } from '../../../../Sheet'; import IconButton from '../../../IconButton'; +import { EmojiCard } from '../../Footer/EmojiCard'; +import SettingsModal from '../../Settings/SettingsModal'; import { ActionTile } from '.././ActionTile'; import { ChangeNameModal } from '.././ChangeNameModal'; import { MuteAllModal } from '.././MuteAllModal'; @@ -32,8 +44,13 @@ export const MwebOptions = () => { const { isHandRaised, isBRBOn, toggleHandRaise, toggleBRB } = useMyMetadata(); const isHandRaiseEnabled = useIsFeatureEnabled(FEATURE_LIST.HAND_RAISE); const isBRBEnabled = useIsFeatureEnabled(FEATURE_LIST.BRB); - const isVideoOn = useHMSStore(selectIsLocalVideoEnabled); + + const [openOptionsSheet, setOpenOptionsSheet] = useState(false); const [openSettingsSheet, setOpenSettingsSheet] = useState(false); + const [showEmojiCard, setShowEmojiCard] = useState(false); + + const emojiCardRef = useRef(null); + const isVideoOn = useHMSStore(selectIsLocalVideoEnabled); useDropdownList({ open: openModals.size > 0, name: 'MoreSettings' }); @@ -49,9 +66,11 @@ export const MwebOptions = () => { }); }; + useClickAway(emojiCardRef, () => setShowEmojiCard(false)); + return ( <> - + @@ -98,7 +117,7 @@ export const MwebOptions = () => { icon={} onClick={toggleHandRaise} active={isHandRaised} - setOpenSettingsSheet={setOpenSettingsSheet} + setOpenOptionsSheet={setOpenOptionsSheet} /> ) : null} {isBRBEnabled ? ( @@ -107,7 +126,7 @@ export const MwebOptions = () => { icon={} onClick={toggleBRB} active={isBRBOn} - setOpenSettingsSheet={setOpenSettingsSheet} + setOpenOptionsSheet={setOpenOptionsSheet} /> ) : null} {permissions.mute ? ( @@ -115,32 +134,63 @@ export const MwebOptions = () => { title="Mute All" icon={} onClick={() => updateState(MODALS.MUTE_ALL, true)} - setOpenSettingsSheet={setOpenSettingsSheet} + setOpenOptionsSheet={setOpenOptionsSheet} /> ) : null} } onClick={() => updateState(MODALS.CHANGE_NAME, true)} - setOpenSettingsSheet={setOpenSettingsSheet} + setOpenOptionsSheet={setOpenOptionsSheet} /> {isVideoOn ? ( ) : null} + } + onClick={() => setShowEmojiCard(true)} + setOpenOptionsSheet={setOpenOptionsSheet} + /> + } onClick={() => setOpenSettingsSheet(true)} />
+ {openModals.has(MODALS.MUTE_ALL) && ( updateState(MODALS.MUTE_ALL, value)} isMobile /> )} {openModals.has(MODALS.CHANGE_NAME) && ( updateState(MODALS.CHANGE_NAME, value)} - openParentSheet={() => setOpenSettingsSheet(true)} + openParentSheet={() => setOpenOptionsSheet(true)} /> )} + + {showEmojiCard && ( + setShowEmojiCard(false)} + ref={emojiCardRef} + css={{ + maxWidth: '100%', + w: '100%', + position: 'absolute', + left: 0, + right: 0, + bottom: '$18', + bg: '$surface_default', + zIndex: '10', + p: '$8', + pb: 0, + r: '$1', + mx: '$4', + }} + > + + + )} ); }; diff --git a/packages/roomkit-react/src/Prebuilt/components/Preview/PreviewJoin.jsx b/packages/roomkit-react/src/Prebuilt/components/Preview/PreviewJoin.jsx index a5fbb7d79c..4eb8685ce1 100644 --- a/packages/roomkit-react/src/Prebuilt/components/Preview/PreviewJoin.jsx +++ b/packages/roomkit-react/src/Prebuilt/components/Preview/PreviewJoin.jsx @@ -246,7 +246,6 @@ const PreviewControls = ({ hideSettings }) => { ); }; -// Bottom action sheet goes here, if isMobile export const PreviewSettings = React.memo(() => { const [open, setOpen] = useState(false); diff --git a/packages/roomkit-react/src/Prebuilt/components/Settings/DeviceSettings.jsx b/packages/roomkit-react/src/Prebuilt/components/Settings/DeviceSettings.jsx index 79ea8f75df..2f6ec91a17 100644 --- a/packages/roomkit-react/src/Prebuilt/components/Settings/DeviceSettings.jsx +++ b/packages/roomkit-react/src/Prebuilt/components/Settings/DeviceSettings.jsx @@ -131,6 +131,7 @@ const DeviceSelector = ({ title, devices, selection, onChange, icon, children = position: 'relative', flex: '1 1 0', minWidth: 0, + w: '100%', maxWidth: '100%', '@md': { mb: children ? '$8' : 0, diff --git a/packages/roomkit-react/src/Prebuilt/components/Settings/SettingsModal.jsx b/packages/roomkit-react/src/Prebuilt/components/Settings/SettingsModal.jsx index d7d9c8f13f..48ddd97de5 100644 --- a/packages/roomkit-react/src/Prebuilt/components/Settings/SettingsModal.jsx +++ b/packages/roomkit-react/src/Prebuilt/components/Settings/SettingsModal.jsx @@ -90,7 +90,8 @@ const MobileSettingModal = ({ {children} From 0863c43abe5ae517a520601cb102c8757608fc76 Mon Sep 17 00:00:00 2001 From: amar-1995 <110378139+amar-1995@users.noreply.github.com> Date: Fri, 11 Aug 2023 14:24:42 +0530 Subject: [PATCH 19/21] feat: header for desktop and mweb --- .../src/Prebuilt/common/utils.js | 9 + .../components/Header/ConferencingHeader.jsx | 39 ++++- .../components/Header/StreamActions.jsx | 94 ++++++---- .../src/Prebuilt/components/Header/common.jsx | 163 ++++++++++++++++++ 4 files changed, 270 insertions(+), 35 deletions(-) create mode 100644 packages/roomkit-react/src/Prebuilt/components/Header/common.jsx diff --git a/packages/roomkit-react/src/Prebuilt/common/utils.js b/packages/roomkit-react/src/Prebuilt/common/utils.js index e319dec0e7..819f001fda 100644 --- a/packages/roomkit-react/src/Prebuilt/common/utils.js +++ b/packages/roomkit-react/src/Prebuilt/common/utils.js @@ -89,3 +89,12 @@ export const getFormattedCount = num => { const formattedNum = formatter.format(num); return formattedNum; }; + +export const formatTime = timeInSeconds => { + timeInSeconds = Math.floor(timeInSeconds / 1000); + const hours = Math.floor(timeInSeconds / 3600); + const minutes = Math.floor((timeInSeconds % 3600) / 60); + const seconds = timeInSeconds % 60; + const hour = hours !== 0 ? `${hours < 10 ? '0' : ''}${hours}:` : ''; + return `${hour}${minutes < 10 ? '0' : ''}${minutes}:${seconds < 10 ? '0' : ''}${seconds}`; +}; diff --git a/packages/roomkit-react/src/Prebuilt/components/Header/ConferencingHeader.jsx b/packages/roomkit-react/src/Prebuilt/components/Header/ConferencingHeader.jsx index e0eed5e50c..a5cc671816 100644 --- a/packages/roomkit-react/src/Prebuilt/components/Header/ConferencingHeader.jsx +++ b/packages/roomkit-react/src/Prebuilt/components/Header/ConferencingHeader.jsx @@ -1,15 +1,42 @@ import React from 'react'; -import { Flex } from '../../../'; -import { SpeakerTag } from './HeaderComponents'; +import { useMedia } from 'react-use'; +import { HMSRoomState, selectRoomState, useHMSStore } from '@100mslive/react-sdk'; +import { config as cssConfig, Flex, VerticalDivider } from '../../../'; +import { Logo, SpeakerTag } from './HeaderComponents'; import { StreamActions } from './StreamActions'; +import { AudioOutputActions, CamaraFlipActions } from './common'; export const ConferencingHeader = () => { + const roomState = useHMSStore(selectRoomState); + const isMobile = useMedia(cssConfig.media.md); + const isPreview = roomState === HMSRoomState.Preview; + + if (isPreview) { + return ( + + + + + + + + + ); + } return ( + + - { }} > + {isMobile && ( + <> + + {' '} + + )} ); diff --git a/packages/roomkit-react/src/Prebuilt/components/Header/StreamActions.jsx b/packages/roomkit-react/src/Prebuilt/components/Header/StreamActions.jsx index 3813f9ac7f..51ceee7981 100644 --- a/packages/roomkit-react/src/Prebuilt/components/Header/StreamActions.jsx +++ b/packages/roomkit-react/src/Prebuilt/components/Header/StreamActions.jsx @@ -1,7 +1,8 @@ -import React, { Fragment, useState } from 'react'; +import React, { useCallback, useEffect, useRef, useState } from 'react'; import { useMedia } from 'react-use'; import { HMSRoomState, + selectHLSState, selectIsConnectedToRoom, selectPermissions, selectRoomState, @@ -9,30 +10,68 @@ import { useHMSStore, useRecordingStreaming, } from '@100mslive/react-sdk'; -import { RecordIcon, WrenchIcon } from '@100mslive/react-icons'; +import { RecordIcon } from '@100mslive/react-icons'; import { Box, Button, config as cssConfig, Flex, Loading, Popover, Text, Tooltip } from '../../../'; -import GoLiveButton from '../GoLiveButton'; import { ResolutionInput } from '../Streaming/ResolutionInput'; import { getResolution } from '../Streaming/RTMPStreaming'; import { ToastManager } from '../Toast/ToastManager'; import { AdditionalRoomState, getRecordingText } from './AdditionalRoomState'; -import { useSidepaneToggle } from '../AppData/useSidepane'; import { useSetAppDataByKey } from '../AppData/useUISettings'; -import { APP_DATA, RTMP_RECORD_DEFAULT_RESOLUTION, SIDE_PANE_OPTIONS } from '../../common/constants'; +import { formatTime } from '../../common/utils'; +import { APP_DATA, RTMP_RECORD_DEFAULT_RESOLUTION } from '../../common/constants'; export const LiveStatus = () => { const { isHLSRunning, isRTMPRunning } = useRecordingStreaming(); + const hlsState = useHMSStore(selectHLSState); + const isMobile = useMedia(cssConfig.media.md); + const intervalRef = useRef(null); + + const [liveTime, setLiveTime] = useState(0); + + const startTimer = useCallback(() => { + intervalRef.current = setInterval(() => { + if (hlsState?.running) { + setLiveTime(Date.now() - hlsState?.variants[0]?.startedAt.getTime()); + } + }, 1000); + }, []); + + useEffect(() => { + if (hlsState?.running && !isMobile) { + startTimer(); + } + if (!hlsState?.running && intervalRef.current) { + clearInterval(intervalRef.current); + } + return () => { + if (intervalRef.current) { + clearInterval(intervalRef.current); + } + }; + }, [hlsState.running, isMobile, startTimer]); + if (!isHLSRunning && !isRTMPRunning) { return null; } return ( - - - - Live - -  with {isHLSRunning ? 'HLS' : 'RTMP'} + + + {isMobile ? ( + + Live + ) : ( + LIVE + )} + + {hlsState?.variants?.length > 0 ? formatTime(liveTime) : ''} ); @@ -41,6 +80,7 @@ export const LiveStatus = () => { export const RecordingStatus = () => { const { isBrowserRecordingOn, isServerRecordingOn, isHLSRecordingOn, isRecordingOn } = useRecordingStreaming(); const permissions = useHMSStore(selectPermissions); + const isMobile = useMedia(cssConfig.media.md); if ( !isRecordingOn || @@ -50,8 +90,10 @@ export const RecordingStatus = () => { value => !!value, ) ) { - return null; + // show recording icon in mobile without popover + if (!(isMobile && isRecordingOn)) return null; } + return ( { isHLSRecordingOn, })} > - - + ); }; -const EndStream = () => { - const toggleStreaming = useSidepaneToggle(SIDE_PANE_OPTIONS.STREAMING); - - return ( - - ); -}; - const StartRecording = () => { const permissions = useHMSStore(selectPermissions); const [resolution, setResolution] = useState(RTMP_RECORD_DEFAULT_RESOLUTION); @@ -192,24 +224,22 @@ const StartRecording = () => { ); }; +/** + * @description only start recording button will be shown. + */ export const StreamActions = () => { const isConnected = useHMSStore(selectIsConnectedToRoom); - const permissions = useHMSStore(selectPermissions); const isMobile = useMedia(cssConfig.media.md); - const { isStreamingOn } = useRecordingStreaming(); const roomState = useHMSStore(selectRoomState); return ( - - {roomState !== HMSRoomState.Preview ? : null} + + {roomState !== HMSRoomState.Preview ? : null} {isConnected && !isMobile ? : null} - {isConnected && (permissions.hlsStreaming || permissions.rtmpStreaming) && ( - {isStreamingOn ? : } - )} ); }; diff --git a/packages/roomkit-react/src/Prebuilt/components/Header/common.jsx b/packages/roomkit-react/src/Prebuilt/components/Header/common.jsx new file mode 100644 index 0000000000..7825a3972b --- /dev/null +++ b/packages/roomkit-react/src/Prebuilt/components/Header/common.jsx @@ -0,0 +1,163 @@ +import { + DeviceType, + selectIsLocalVideoEnabled, + selectLocalVideoTrackID, + selectVideoTrackByID, + useDevices, + useHMSActions, + useHMSStore, +} from '@100mslive/react-sdk'; +import { CameraFlipIcon, CheckIcon, CrossIcon, SpeakerIcon } from '@100mslive/react-icons'; +import { HorizontalDivider } from '../../../Divider'; +import { Label } from '../../../Label'; +import { Box, Flex } from '../../../Layout'; +import { Sheet } from '../../../Sheet'; +import { Text } from '../../../Text'; +import IconButton from '../../IconButton'; +import { ToastManager } from '../Toast/ToastManager'; + +export const CamaraFlipActions = () => { + const actions = useHMSActions(); + const { allDevices } = useDevices(); + const { videoInput } = allDevices; + const isVideoOn = useHMSStore(selectIsLocalVideoEnabled); + + const videoTrackId = useHMSStore(selectLocalVideoTrackID); + const localVideoTrack = useHMSStore(selectVideoTrackByID(videoTrackId)); + + return ( + + { + try { + await actions.switchCamera(); + } catch (e) { + ToastManager.addToast({ + title: `Error while flipping camera ${e.message || ''}`, + variant: 'error', + }); + } + }} + > + + + + ); +}; + +export const AudioOutputActions = () => { + const { allDevices, selectedDeviceIDs, updateDevice } = useDevices(); + const { audioOutput } = allDevices; + // don't show speaker selector where the API is not supported, and use + // a generic word("Audio") for Mic. In some cases(Chrome Android for e.g.) this changes both mic and speaker keeping them in sync. + const shouldShowAudioOutput = 'setSinkId' in HTMLMediaElement.prototype; + + /** + * Chromium browsers return an audioOutput with empty label when no permissions are given + */ + const audioOutputFiltered = audioOutput?.filter(item => !!item.label) ?? []; + if (!shouldShowAudioOutput || !audioOutputFiltered?.length > 0) { + return null; + } + return ( + { + try { + await updateDevice({ + deviceId, + deviceType: DeviceType.audioOutput, + }); + } catch (e) { + ToastManager.addToast({ + title: `Error while changing audio output ${e.message || ''}`, + variant: 'error', + }); + } + }} + > + + + + + + + ); +}; + +const AudioOutputSelectionSheet = ({ outputDevices, outputSelected, onChange, children }) => { + return ( + + {children} + + + + + Audio Output + + + + + + + + + + + {outputDevices.map(audioDevice => { + return ( + onChange(audioDevice.deviceId)} + /> + ); + })} + + + + ); +}; + +const SelectWithLabel = ({ label, icon = <>, checked, id, onChange }) => { + return ( + + + {checked && } + + ); +}; From adc556d7ee8cd02551d8ff72c59e6fc0c78faed9 Mon Sep 17 00:00:00 2001 From: amar-1995 <110378139+amar-1995@users.noreply.github.com> Date: Fri, 11 Aug 2023 17:12:28 +0530 Subject: [PATCH 20/21] feat: recording start/stop mweb --- .../Prebuilt/components/EndSessionContent.jsx | 1 + .../components/Header/StreamActions.jsx | 42 +++++++++++- .../src/Prebuilt/components/Header/common.jsx | 1 + .../src/Prebuilt/components/LeaveCard.jsx | 1 + .../components/MoreSettings/ActionTile.jsx | 1 + .../MoreSettings/ChangeNameContent.jsx | 1 + .../MoreSettings/MuteAllContent.jsx | 1 + .../SplitComponents/MwebOptions.jsx | 66 ++++++++++++++++++- 8 files changed, 110 insertions(+), 4 deletions(-) diff --git a/packages/roomkit-react/src/Prebuilt/components/EndSessionContent.jsx b/packages/roomkit-react/src/Prebuilt/components/EndSessionContent.jsx index 5eeba636d8..865c79104b 100644 --- a/packages/roomkit-react/src/Prebuilt/components/EndSessionContent.jsx +++ b/packages/roomkit-react/src/Prebuilt/components/EndSessionContent.jsx @@ -1,3 +1,4 @@ +import React from 'react'; import { AlertTriangleIcon, CrossIcon } from '@100mslive/react-icons'; import { Button } from '../../Button'; import { Box, Flex } from '../../Layout'; diff --git a/packages/roomkit-react/src/Prebuilt/components/Header/StreamActions.jsx b/packages/roomkit-react/src/Prebuilt/components/Header/StreamActions.jsx index 51ceee7981..a062b0d6ec 100644 --- a/packages/roomkit-react/src/Prebuilt/components/Header/StreamActions.jsx +++ b/packages/roomkit-react/src/Prebuilt/components/Header/StreamActions.jsx @@ -10,8 +10,9 @@ import { useHMSStore, useRecordingStreaming, } from '@100mslive/react-sdk'; -import { RecordIcon } from '@100mslive/react-icons'; -import { Box, Button, config as cssConfig, Flex, Loading, Popover, Text, Tooltip } from '../../../'; +import { AlertTriangleIcon, CrossIcon, RecordIcon } from '@100mslive/react-icons'; +import { Box, Button, config as cssConfig, Flex, HorizontalDivider, Loading, Popover, Text, Tooltip } from '../../../'; +import { Sheet } from '../../../Sheet'; import { ResolutionInput } from '../Streaming/ResolutionInput'; import { getResolution } from '../Streaming/RTMPStreaming'; import { ToastManager } from '../Toast/ToastManager'; @@ -34,7 +35,7 @@ export const LiveStatus = () => { setLiveTime(Date.now() - hlsState?.variants[0]?.startedAt.getTime()); } }, 1000); - }, []); + }, [hlsState?.running, hlsState?.variants]); useEffect(() => { if (hlsState?.running && !isMobile) { @@ -243,3 +244,38 @@ export const StreamActions = () => { ); }; + +export const StopRecordingInSheet = ({ onStopRecording, onClose }) => { + return ( + + + + + + + Stop Recording + + + + + + + + + + Are you sure you want to stop recording? You can’t undo this action. + + + + + + ); +}; diff --git a/packages/roomkit-react/src/Prebuilt/components/Header/common.jsx b/packages/roomkit-react/src/Prebuilt/components/Header/common.jsx index 7825a3972b..bf2c575c0d 100644 --- a/packages/roomkit-react/src/Prebuilt/components/Header/common.jsx +++ b/packages/roomkit-react/src/Prebuilt/components/Header/common.jsx @@ -1,3 +1,4 @@ +import React from 'react'; import { DeviceType, selectIsLocalVideoEnabled, diff --git a/packages/roomkit-react/src/Prebuilt/components/LeaveCard.jsx b/packages/roomkit-react/src/Prebuilt/components/LeaveCard.jsx index e8b4be06cf..32beacc46e 100644 --- a/packages/roomkit-react/src/Prebuilt/components/LeaveCard.jsx +++ b/packages/roomkit-react/src/Prebuilt/components/LeaveCard.jsx @@ -1,3 +1,4 @@ +import React from 'react'; import { Box, Flex } from '../../Layout'; import { Text } from '../../Text'; diff --git a/packages/roomkit-react/src/Prebuilt/components/MoreSettings/ActionTile.jsx b/packages/roomkit-react/src/Prebuilt/components/MoreSettings/ActionTile.jsx index cd9f37242e..962ac2b85a 100644 --- a/packages/roomkit-react/src/Prebuilt/components/MoreSettings/ActionTile.jsx +++ b/packages/roomkit-react/src/Prebuilt/components/MoreSettings/ActionTile.jsx @@ -1,3 +1,4 @@ +import React from 'react'; import { Flex } from '../../../Layout'; import { Text } from '../../../Text'; diff --git a/packages/roomkit-react/src/Prebuilt/components/MoreSettings/ChangeNameContent.jsx b/packages/roomkit-react/src/Prebuilt/components/MoreSettings/ChangeNameContent.jsx index 8b680c3b7d..af1b3dc6ff 100644 --- a/packages/roomkit-react/src/Prebuilt/components/MoreSettings/ChangeNameContent.jsx +++ b/packages/roomkit-react/src/Prebuilt/components/MoreSettings/ChangeNameContent.jsx @@ -1,3 +1,4 @@ +import React from 'react'; import { ChevronLeftIcon, CrossIcon } from '@100mslive/react-icons'; import { Button } from '../../../Button'; import { Input } from '../../../Input'; diff --git a/packages/roomkit-react/src/Prebuilt/components/MoreSettings/MuteAllContent.jsx b/packages/roomkit-react/src/Prebuilt/components/MoreSettings/MuteAllContent.jsx index 2b67ab0bc2..d7af0a9080 100644 --- a/packages/roomkit-react/src/Prebuilt/components/MoreSettings/MuteAllContent.jsx +++ b/packages/roomkit-react/src/Prebuilt/components/MoreSettings/MuteAllContent.jsx @@ -1,3 +1,4 @@ +import React from 'react'; import { Button } from '../../../Button'; import { Label } from '../../../Label'; import { Flex } from '../../../Layout'; diff --git a/packages/roomkit-react/src/Prebuilt/components/MoreSettings/SplitComponents/MwebOptions.jsx b/packages/roomkit-react/src/Prebuilt/components/MoreSettings/SplitComponents/MwebOptions.jsx index 71e7324204..b98b6376e0 100644 --- a/packages/roomkit-react/src/Prebuilt/components/MoreSettings/SplitComponents/MwebOptions.jsx +++ b/packages/roomkit-react/src/Prebuilt/components/MoreSettings/SplitComponents/MwebOptions.jsx @@ -1,6 +1,13 @@ import React, { Suspense, useRef, useState } from 'react'; import { useClickAway } from 'react-use'; -import { selectIsLocalVideoEnabled, selectPermissions, useHMSStore } from '@100mslive/react-sdk'; +import { + selectIsConnectedToRoom, + selectIsLocalVideoEnabled, + selectPermissions, + useHMSActions, + useHMSStore, + useRecordingStreaming, +} from '@100mslive/react-sdk'; import { BrbIcon, CrossIcon, @@ -9,13 +16,16 @@ import { HandIcon, MicOffIcon, PencilIcon, + RecordIcon, SettingsIcon, } from '@100mslive/react-icons'; import { Box, Tooltip } from '../../../../'; import { Sheet } from '../../../../Sheet'; import IconButton from '../../../IconButton'; import { EmojiCard } from '../../Footer/EmojiCard'; +import { StopRecordingInSheet } from '../../Header/StreamActions'; import SettingsModal from '../../Settings/SettingsModal'; +import { ToastManager } from '../../Toast/ToastManager'; import { ActionTile } from '.././ActionTile'; import { ChangeNameModal } from '.././ChangeNameModal'; import { MuteAllModal } from '.././MuteAllModal'; @@ -39,7 +49,11 @@ const MODALS = { }; export const MwebOptions = () => { + const hmsActions = useHMSActions(); const permissions = useHMSStore(selectPermissions); + const isConnected = useHMSStore(selectIsConnectedToRoom); + const { isBrowserRecordingOn, isStreamingOn, isHLSRunning } = useRecordingStreaming(); + const [openModals, setOpenModals] = useState(new Set()); const { isHandRaised, isBRBOn, toggleHandRaise, toggleBRB } = useMyMetadata(); const isHandRaiseEnabled = useIsFeatureEnabled(FEATURE_LIST.HAND_RAISE); @@ -48,6 +62,7 @@ export const MwebOptions = () => { const [openOptionsSheet, setOpenOptionsSheet] = useState(false); const [openSettingsSheet, setOpenSettingsSheet] = useState(false); const [showEmojiCard, setShowEmojiCard] = useState(false); + const [showRecordingOn, setShowRecordingOn] = useState(false); const emojiCardRef = useRef(null); const isVideoOn = useHMSStore(selectIsLocalVideoEnabled); @@ -155,6 +170,39 @@ export const MwebOptions = () => { setOpenOptionsSheet={setOpenOptionsSheet} /> } onClick={() => setOpenSettingsSheet(true)} /> + {isConnected && permissions?.browserRecording && ( + } + onClick={async () => { + if (isBrowserRecordingOn || isStreamingOn) { + setShowRecordingOn(true); + } else { + // start recording + setOpenOptionsSheet(false); + try { + await hmsActions.startRTMPOrRecording({ + record: true, + }); + } catch (error) { + if (error.message.includes('stream already running')) { + ToastManager.addToast({ + title: 'Recording already running', + variant: 'error', + }); + } else { + ToastManager.addToast({ + title: error.message, + variant: 'error', + }); + } + } + } + }} + setOpenOptionsSheet={setOpenOptionsSheet} + /> + )} @@ -191,6 +239,22 @@ export const MwebOptions = () => { )} + {showRecordingOn && ( + setShowRecordingOn(false)} + onStopRecording={async () => { + try { + await hmsActions.stopRTMPAndRecording(); + setShowRecordingOn(false); + } catch (error) { + ToastManager.addToast({ + title: error.message, + variant: 'error', + }); + } + }} + /> + )} ); }; From f32a002a072c71d721941d71ab4686d65a8c52dc Mon Sep 17 00:00:00 2001 From: Kaustubh Kumar Date: Fri, 11 Aug 2023 17:14:48 +0530 Subject: [PATCH 21/21] feat: tile menu in bottom sheet --- .../SplitComponents/MwebLeaveRoom.jsx | 2 +- .../Prebuilt/components/ScreenshareTile.jsx | 2 +- .../components/{ => TileMenu}/TileMenu.jsx | 196 +++++++++--------- .../components/TileMenu/TileMenuContent.jsx | 131 ++++++++++++ .../src/Prebuilt/components/VideoTile.jsx | 2 +- .../src/Prebuilt/layouts/mainView.jsx | 18 +- 6 files changed, 239 insertions(+), 112 deletions(-) rename packages/roomkit-react/src/Prebuilt/components/{ => TileMenu}/TileMenu.jsx (56%) create mode 100644 packages/roomkit-react/src/Prebuilt/components/TileMenu/TileMenuContent.jsx diff --git a/packages/roomkit-react/src/Prebuilt/components/MoreSettings/SplitComponents/MwebLeaveRoom.jsx b/packages/roomkit-react/src/Prebuilt/components/MoreSettings/SplitComponents/MwebLeaveRoom.jsx index 489eb2495c..c62c144d93 100644 --- a/packages/roomkit-react/src/Prebuilt/components/MoreSettings/SplitComponents/MwebLeaveRoom.jsx +++ b/packages/roomkit-react/src/Prebuilt/components/MoreSettings/SplitComponents/MwebLeaveRoom.jsx @@ -37,7 +37,7 @@ export const MwebLeaveRoom = ({ leaveIconButton: LeaveIconButton, endRoom, leave }} > - {!showStreamingUI ? : } + {showStreamingUI ? : } diff --git a/packages/roomkit-react/src/Prebuilt/components/ScreenshareTile.jsx b/packages/roomkit-react/src/Prebuilt/components/ScreenshareTile.jsx index eafbc8cc62..e09116c466 100644 --- a/packages/roomkit-react/src/Prebuilt/components/ScreenshareTile.jsx +++ b/packages/roomkit-react/src/Prebuilt/components/ScreenshareTile.jsx @@ -9,11 +9,11 @@ import { useHMSStore, } from '@100mslive/react-sdk'; import { ExpandIcon, ShrinkIcon } from '@100mslive/react-icons'; +import TileMenu from './TileMenu/TileMenu'; import { VideoTileStats } from '../../Stats'; import { Video } from '../../Video'; import { StyledVideoTile } from '../../VideoTile'; import { getVideoTileLabel } from './peerTileUtils'; -import TileMenu from './TileMenu'; import { useIsHeadless, useUISettings } from './AppData/useUISettings'; import { UI_SETTINGS } from '../common/constants'; diff --git a/packages/roomkit-react/src/Prebuilt/components/TileMenu.jsx b/packages/roomkit-react/src/Prebuilt/components/TileMenu/TileMenu.jsx similarity index 56% rename from packages/roomkit-react/src/Prebuilt/components/TileMenu.jsx rename to packages/roomkit-react/src/Prebuilt/components/TileMenu/TileMenu.jsx index 6d487e1f3b..a1324c9101 100644 --- a/packages/roomkit-react/src/Prebuilt/components/TileMenu.jsx +++ b/packages/roomkit-react/src/Prebuilt/components/TileMenu/TileMenu.jsx @@ -1,43 +1,42 @@ import React, { Fragment, useState } from 'react'; +import { useMedia } from 'react-use'; import { selectLocalPeerID, + selectPeerByID, selectPermissions, selectSessionStore, selectTemplateAppData, selectTrackByID, selectVideoTrackByPeerID, - useCustomEvent, useHMSActions, useHMSStore, useRemoteAVToggle, } from '@100mslive/react-sdk'; -import { - HorizontalMenuIcon, - MicOffIcon, - MicOnIcon, - PinIcon, - RemoveUserIcon, - ShareScreenIcon, - SpeakerIcon, - StarIcon, - VideoOffIcon, - VideoOnIcon, -} from '@100mslive/react-icons'; -import { ToastManager } from './Toast/ToastManager'; -import { Box, Flex } from '../../Layout'; -import { Slider } from '../../Slider'; -import { Text } from '../../Text'; -import { StyledMenuTile } from '../../TileMenu'; -import { useSetAppDataByKey } from './AppData/useUISettings'; -import { useDropdownList } from './hooks/useDropdownList'; -import { useDropdownSelection } from './hooks/useDropdownSelection'; -import { useIsFeatureEnabled } from './hooks/useFeatures'; -import { APP_DATA, FEATURE_LIST, REMOTE_STOP_SCREENSHARE_TYPE, SESSION_STORE_KEY } from '../common/constants'; +import { CrossIcon, HorizontalMenuIcon, PinIcon, StarIcon } from '@100mslive/react-icons'; +import { Box, Flex } from '../../../Layout'; +import { Sheet } from '../../../Sheet'; +import { Text } from '../../../Text'; +import { config as cssConfig } from '../../../Theme'; +import { StyledMenuTile } from '../../../TileMenu'; +import { ToastManager } from '../Toast/ToastManager'; +import { TileMenuContent } from './TileMenuContent'; +import { useSetAppDataByKey } from '../AppData/useUISettings'; +import { useDropdownList } from '../hooks/useDropdownList'; +import { useDropdownSelection } from '../hooks/useDropdownSelection'; +import { useIsFeatureEnabled } from '../hooks/useFeatures'; +import { APP_DATA, FEATURE_LIST, SESSION_STORE_KEY } from '../../common/constants'; const isSameTile = ({ trackId, videoTrackID, audioTrackID }) => trackId && ((videoTrackID && videoTrackID === trackId) || (audioTrackID && audioTrackID === trackId)); -const SpotlightActions = ({ peerId }) => { +const spacingCSS = { '@md': { my: '$8', fontWeight: '$semiBold', fontSize: 'sm' } }; + +const SpotlightActions = ({ + peerId, + onSpotLightClick = () => { + return; + }, +}) => { const hmsActions = useHMSActions(); const spotlightPeerId = useHMSStore(selectSessionStore(SESSION_STORE_KEY.SPOTLIGHT)); const isTileSpotlighted = spotlightPeerId === peerId; @@ -48,7 +47,17 @@ const SpotlightActions = ({ peerId }) => { .catch(err => ToastManager.addToast({ title: err.description })); return ( - (isTileSpotlighted ? setSpotlightPeerId() : setSpotlightPeerId(peerId))}> + { + if (isTileSpotlighted) { + setSpotlightPeerId(); + } else { + setSpotlightPeerId(peerId); + } + onSpotLightClick(); + }} + > {isTileSpotlighted ? 'Remove from Spotlight' : 'Spotlight Tile for everyone'} @@ -67,6 +76,7 @@ const PinActions = ({ audioTrackID, videoTrackID }) => { return ( <> (isTilePinned ? setPinnedTrackId() : setPinnedTrackId(videoTrackID || audioTrackID))} > @@ -81,18 +91,11 @@ const PinActions = ({ audioTrackID, videoTrackID }) => { */ const TileMenu = ({ audioTrackID, videoTrackID, peerID, isScreenshare = false }) => { const [open, setOpen] = useState(false); - const actions = useHMSActions(); const localPeerID = useHMSStore(selectLocalPeerID); const isLocal = localPeerID === peerID; const { removeOthers, changeRole } = useHMSStore(selectPermissions); - const { isAudioEnabled, isVideoEnabled, setVolume, toggleAudio, toggleVideo, volume } = useRemoteAVToggle( - audioTrackID, - videoTrackID, - ); + const { setVolume, toggleAudio, toggleVideo } = useRemoteAVToggle(audioTrackID, videoTrackID); const showSpotlight = changeRole; - const { sendEvent } = useCustomEvent({ - type: REMOTE_STOP_SCREENSHARE_TYPE, - }); const isPrimaryVideoTrack = useHMSStore(selectVideoTrackByPeerID(peerID))?.id === videoTrackID; const uiMode = useHMSStore(selectTemplateAppData).uiMode; @@ -103,6 +106,8 @@ const TileMenu = ({ audioTrackID, videoTrackID, peerID, isScreenshare = false }) const track = useHMSStore(selectTrackByID(videoTrackID)); const hideSimulcastLayers = !track?.layerDefinitions?.length || track.degraded || !track.enabled; + const isMobile = useMedia(cssConfig.media.md); + const peer = useHMSStore(selectPeerByID(peerID)); useDropdownList({ open, name: 'TileMenu' }); @@ -113,83 +118,68 @@ const TileMenu = ({ audioTrackID, videoTrackID, peerID, isScreenshare = false }) if (isInset && isLocal) { return null; } + const props = { + isLocal, + isScreenshare, + audioTrackID, + videoTrackID, + peerID, + isPrimaryVideoTrack, + showSpotlight, + showPinAction, + pinActions: PinActions, + spotlightActions: SpotlightActions, + simulcastLayers: SimulcastLayers, + spacingCSS, + }; return ( e.stopPropagation()}> - - {isLocal ? ( - showPinAction && ( - <> - - {showSpotlight && } - - ) - ) : ( - <> - {toggleVideo ? ( - - {isVideoEnabled ? : } - {isVideoEnabled ? 'Mute' : 'Request Unmute'} - - ) : null} - {toggleAudio ? ( - - {isAudioEnabled ? : } - {isAudioEnabled ? 'Mute' : 'Request Unmute'} - - ) : null} - {audioTrackID ? ( - - - - - Volume ({volume}) - - - setVolume(e[0])} /> - - ) : null} - {showPinAction && ( - <> - - {showSpotlight && } - - )} - - {removeOthers ? ( - { - try { - await actions.removePeer(peerID, ''); - } catch (error) { - // TODO: Toast here - } - }} - data-testid="remove_participant_btn" - > - - Remove Participant - - ) : null} - {removeOthers && isScreenshare ? ( - sendEvent({})}> - - Stop Screenshare - - ) : null} - - )} - + {isMobile ? ( + + + + + + {peer.name} + {isLocal ? ` (You)` : null} + + {peer?.roleName ? ( + + {peer.roleName} + + ) : null} + + + + + + + + setOpen(false)} /> + + + + ) : ( + + + + )} ); }; diff --git a/packages/roomkit-react/src/Prebuilt/components/TileMenu/TileMenuContent.jsx b/packages/roomkit-react/src/Prebuilt/components/TileMenu/TileMenuContent.jsx new file mode 100644 index 0000000000..e2203d1d5e --- /dev/null +++ b/packages/roomkit-react/src/Prebuilt/components/TileMenu/TileMenuContent.jsx @@ -0,0 +1,131 @@ +import React from 'react'; +import { selectPermissions, useCustomEvent, useHMSActions, useHMSStore, useRemoteAVToggle } from '@100mslive/react-sdk'; +import { + MicOffIcon, + MicOnIcon, + RemoveUserIcon, + ShareScreenIcon, + SpeakerIcon, + VideoOffIcon, + VideoOnIcon, +} from '@100mslive/react-icons'; +import { Box, Flex } from '../../../Layout'; +import { Slider } from '../../../Slider'; +import { StyledMenuTile } from '../../../TileMenu'; +import { REMOTE_STOP_SCREENSHARE_TYPE } from '../../common/constants'; + +export const TileMenuContent = props => { + const actions = useHMSActions(); + const { removeOthers } = useHMSStore(selectPermissions); + const { + pinActions: PinActions, + spotlightActions: SpotlightActions, + simulcastLayers: SimulcastLayers, + videoTrackID, + audioTrackID, + isLocal, + isScreenshare, + showSpotlight, + showPinAction, + peerID, + spacingCSS, + closeSheetOnClick = () => { + return; + }, + } = props; + + const { isAudioEnabled, isVideoEnabled, setVolume, toggleAudio, toggleVideo, volume } = useRemoteAVToggle( + audioTrackID, + videoTrackID, + ); + + const { sendEvent } = useCustomEvent({ + type: REMOTE_STOP_SCREENSHARE_TYPE, + }); + + return isLocal ? ( + showPinAction && ( + <> + + {showSpotlight && closeSheetOnClick()} />} + + ) + ) : ( + <> + {toggleVideo ? ( + { + toggleVideo(); + closeSheetOnClick(); + }} + data-testid={isVideoEnabled ? 'mute_video_participant_btn' : 'unmute_video_participant_btn'} + > + {isVideoEnabled ? : } + {isVideoEnabled ? 'Mute' : 'Request Unmute'} + + ) : null} + {toggleAudio ? ( + { + toggleAudio(); + closeSheetOnClick(); + }} + data-testid={isVideoEnabled ? 'mute_audio_participant_btn' : 'unmute_audio_participant_btn'} + > + {isAudioEnabled ? : } + {isAudioEnabled ? 'Mute' : 'Request Unmute'} + + ) : null} + {audioTrackID ? ( + + + + + Volume ({volume}) + + + setVolume(e[0])} /> + + ) : null} + {showPinAction && ( + <> + + {showSpotlight && closeSheetOnClick()} />} + + )} + + {removeOthers ? ( + { + try { + await actions.removePeer(peerID, ''); + } catch (error) { + // TODO: Toast here + } + closeSheetOnClick(); + }} + data-testid="remove_participant_btn" + > + + Remove Participant + + ) : null} + + {removeOthers && isScreenshare ? ( + { + sendEvent({}); + closeSheetOnClick(); + }} + css={spacingCSS} + > + + Stop Screenshare + + ) : null} + + ); +}; diff --git a/packages/roomkit-react/src/Prebuilt/components/VideoTile.jsx b/packages/roomkit-react/src/Prebuilt/components/VideoTile.jsx index b3d450b1af..57b95ebbbe 100644 --- a/packages/roomkit-react/src/Prebuilt/components/VideoTile.jsx +++ b/packages/roomkit-react/src/Prebuilt/components/VideoTile.jsx @@ -11,13 +11,13 @@ import { } from '@100mslive/react-sdk'; import { BrbIcon, HandRaiseFilledIcon, MicOffIcon } from '@100mslive/react-icons'; import TileConnection from './Connection/TileConnection'; +import TileMenu from './TileMenu/TileMenu'; import { useBorderAudioLevel } from '../../AudioLevel'; import { Avatar } from '../../Avatar'; import { VideoTileStats } from '../../Stats'; import { Video } from '../../Video'; import { StyledVideoTile } from '../../VideoTile'; import { getVideoTileLabel } from './peerTileUtils'; -import TileMenu from './TileMenu'; import { useAppConfig } from './AppData/useAppConfig'; import { useIsHeadless, useUISettings } from './AppData/useUISettings'; import { UI_SETTINGS } from '../common/constants'; diff --git a/packages/roomkit-react/src/Prebuilt/layouts/mainView.jsx b/packages/roomkit-react/src/Prebuilt/layouts/mainView.jsx index cdb4129fd9..b23cbf159d 100644 --- a/packages/roomkit-react/src/Prebuilt/layouts/mainView.jsx +++ b/packages/roomkit-react/src/Prebuilt/layouts/mainView.jsx @@ -70,6 +70,17 @@ export const ConferenceMainView = () => { } }, [hmsActions, isHLSStarted, setHLSStarted]); + useEffect(() => { + if (!isConnected) { + return; + } + // Is a streaming kit and broadcaster joins + if (permissions?.hlsStreaming && !isHLSRunning && showStreamingUI) { + startHLS(); + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [isConnected]); + useEffect(() => { if (!isConnected) { return; @@ -83,14 +94,9 @@ export const ConferenceMainView = () => { hmsActions.audioPlaylist.setList(audioPlaylist); } - // Is a streaming kit and broadcaster joins - if (permissions?.hlsStreaming && !isHLSRunning && showStreamingUI) { - startHLS(); - } - hmsActions.sessionStore.observe([SESSION_STORE_KEY.PINNED_MESSAGE, SESSION_STORE_KEY.SPOTLIGHT]); // eslint-disable-next-line react-hooks/exhaustive-deps - }, [isConnected, hmsActions, permissions, showStreamingUI]); + }, [isConnected, hmsActions]); if (!localPeerRole) { // we don't know the role yet to decide how to render UI