@100mslive/roomkit-react 0.2.8-alpha.7 → 0.2.8-alpha.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/dist/{HLSView-MYKM5AXS.js → HLSView-TOMPA4E4.js} +191 -188
  2. package/dist/HLSView-TOMPA4E4.js.map +7 -0
  3. package/dist/Prebuilt/components/HMSVideo/HLSQualitySelector.d.ts +3 -2
  4. package/dist/Prebuilt/components/HMSVideo/VideoProgress.d.ts +1 -3
  5. package/dist/Prebuilt/components/HMSVideo/index.d.ts +1 -3
  6. package/dist/Prebuilt/components/HMSVideo/utils.d.ts +0 -1
  7. package/dist/Prebuilt/components/Leave/DesktopLeaveRoom.d.ts +2 -1
  8. package/dist/Prebuilt/components/Leave/LeaveRoom.d.ts +2 -1
  9. package/dist/Prebuilt/components/Leave/MwebLeaveRoom.d.ts +2 -1
  10. package/dist/Prebuilt/components/RaiseHand.d.ts +4 -1
  11. package/dist/Sheet/Sheet.d.ts +1 -0
  12. package/dist/{chunk-DRBTAFKN.js → chunk-FUDX3LDB.js} +820 -723
  13. package/dist/chunk-FUDX3LDB.js.map +7 -0
  14. package/dist/index.cjs.js +1324 -1220
  15. package/dist/index.cjs.js.map +4 -4
  16. package/dist/index.js +1 -1
  17. package/dist/meta.cjs.json +274 -209
  18. package/dist/meta.esbuild.json +283 -216
  19. package/package.json +6 -6
  20. package/src/Button/Button.tsx +4 -4
  21. package/src/Fieldset/Fieldset.tsx +1 -1
  22. package/src/Input/PasswordInput.stories.tsx +1 -1
  23. package/src/Pagination/StyledPagination.stories.tsx +2 -2
  24. package/src/Prebuilt/IconButton.tsx +1 -1
  25. package/src/Prebuilt/components/Chat/Chat.tsx +41 -1
  26. package/src/Prebuilt/components/Chat/ChatFooter.tsx +19 -15
  27. package/src/Prebuilt/components/EmojiReaction.jsx +32 -22
  28. package/src/Prebuilt/components/Footer/RoleOptions.tsx +125 -126
  29. package/src/Prebuilt/components/HMSVideo/HLSQualitySelector.tsx +85 -78
  30. package/src/Prebuilt/components/HMSVideo/HMSVideo.jsx +3 -4
  31. package/src/Prebuilt/components/HMSVideo/MwebHLSViewTitle.tsx +49 -56
  32. package/src/Prebuilt/components/HMSVideo/VideoProgress.tsx +6 -6
  33. package/src/Prebuilt/components/HMSVideo/VideoTime.tsx +2 -1
  34. package/src/Prebuilt/components/HMSVideo/utils.ts +0 -8
  35. package/src/Prebuilt/components/IconButtonWithOptions/IconButtonWithOptions.tsx +1 -1
  36. package/src/Prebuilt/components/Leave/DesktopLeaveRoom.tsx +50 -46
  37. package/src/Prebuilt/components/Leave/LeaveRoom.tsx +10 -5
  38. package/src/Prebuilt/components/Leave/MwebLeaveRoom.tsx +12 -6
  39. package/src/Prebuilt/components/MoreSettings/SplitComponents/MwebOptions.tsx +5 -2
  40. package/src/Prebuilt/components/Notifications/HandRaisedNotifications.tsx +4 -1
  41. package/src/Prebuilt/components/Polls/Voting/Voting.tsx +3 -2
  42. package/src/Prebuilt/components/Polls/common/OptionInputWithDelete.tsx +1 -1
  43. package/src/Prebuilt/components/Polls/common/utils.ts +2 -2
  44. package/src/Prebuilt/components/RaiseHand.tsx +8 -2
  45. package/src/Prebuilt/components/RoomDetails/RoomDetailsPane.tsx +41 -14
  46. package/src/Prebuilt/components/pdfAnnotator/shareScreenOptions.jsx +2 -2
  47. package/src/Prebuilt/components/pdfAnnotator/uploadedFile.jsx +1 -1
  48. package/src/Prebuilt/layouts/HLSView.jsx +58 -47
  49. package/src/Prebuilt/layouts/SidePane.tsx +1 -2
  50. package/src/Prebuilt/layouts/VideoStreamingSection.tsx +3 -2
  51. package/src/Prebuilt/primitives/DialogContent.jsx +1 -1
  52. package/src/Sheet/Sheet.tsx +3 -3
  53. package/dist/HLSView-MYKM5AXS.js.map +0 -7
  54. package/dist/chunk-DRBTAFKN.js.map +0 -7
package/package.json CHANGED
@@ -10,7 +10,7 @@
10
10
  "prebuilt",
11
11
  "roomkit"
12
12
  ],
13
- "version": "0.2.8-alpha.7",
13
+ "version": "0.2.8-alpha.9",
14
14
  "author": "100ms",
15
15
  "license": "MIT",
16
16
  "repository": {
@@ -82,11 +82,11 @@
82
82
  "react": ">=17.0.2 <19.0.0"
83
83
  },
84
84
  "dependencies": {
85
- "@100mslive/hls-player": "0.2.8-alpha.7",
85
+ "@100mslive/hls-player": "0.2.8-alpha.9",
86
86
  "@100mslive/hms-noise-cancellation": "0.0.0-alpha.1",
87
- "@100mslive/hms-virtual-background": "1.12.8-alpha.7",
88
- "@100mslive/react-icons": "0.9.8-alpha.7",
89
- "@100mslive/react-sdk": "0.9.8-alpha.7",
87
+ "@100mslive/hms-virtual-background": "1.12.8-alpha.9",
88
+ "@100mslive/react-icons": "0.9.8-alpha.9",
89
+ "@100mslive/react-sdk": "0.9.8-alpha.9",
90
90
  "@100mslive/types-prebuilt": "0.12.7",
91
91
  "@emoji-mart/data": "^1.0.6",
92
92
  "@emoji-mart/react": "^1.0.1",
@@ -122,5 +122,5 @@
122
122
  "uuid": "^8.3.2",
123
123
  "worker-timers": "^7.0.40"
124
124
  },
125
- "gitHead": "48bc1b57113a4245b79055a80f4f1f5d3b8795aa"
125
+ "gitHead": "2a735b6edf0b63927744abb555b47ab9be6e5891"
126
126
  }
@@ -20,22 +20,22 @@ const getOutlinedVariants = (
20
20
  textDisabled: string,
21
21
  ) => {
22
22
  return {
23
- bg: '$transparent',
23
+ bg: 'transparent',
24
24
  border: `solid $space$px $colors${base}`,
25
25
  c: text,
26
26
  '&[disabled]': {
27
27
  c: textDisabled,
28
- bg: '$transparent',
28
+ bg: 'transparent',
29
29
  border: `solid $space$px $colors${disabled}`,
30
30
  cursor: 'not-allowed',
31
31
  },
32
32
  '&:not([disabled]):hover': {
33
33
  border: `solid $space$px $colors${hover}`,
34
- bg: '$transparent',
34
+ bg: 'transparent',
35
35
  },
36
36
  '&:not([disabled]):active': {
37
37
  border: `solid $space$px $colors${active}`,
38
- bg: '$transparent',
38
+ bg: 'transparent',
39
39
  },
40
40
  '&:not([disabled]):focus-visible': {
41
41
  boxShadow: `0 0 0 3px $colors${base}`,
@@ -5,7 +5,7 @@ const StyledFieldset = styled('fieldset', {
5
5
  alignItems: 'center',
6
6
  justifyContent: 'space-between',
7
7
  border: 'none',
8
- backgroundColor: '$transparent',
8
+ backgroundColor: 'transparent',
9
9
  });
10
10
 
11
11
  export const Fieldset = StyledFieldset;
@@ -25,7 +25,7 @@ const Template: ComponentStory<typeof PasswordInput.Root> = args => {
25
25
  showPassword={showPassword}
26
26
  onChange={e => setText(e.target.value)}
27
27
  />
28
- <PasswordInput.Icons ref={ref} css={{ bg: '$transparent' }}>
28
+ <PasswordInput.Icons ref={ref} css={{ bg: 'transparent' }}>
29
29
  <PasswordInput.ShowIcon
30
30
  showPassword={showPassword}
31
31
  onClick={() => {
@@ -41,7 +41,7 @@ const PaginationComponent = ({ page: propsPage, setPage: propsSetPage, numPages
41
41
  disabled={disableLeft}
42
42
  onClick={prevPage}
43
43
  type="button"
44
- css={{ padding: 0, border: 'none', backgroundColor: '$transparent' }}
44
+ css={{ padding: 0, border: 'none', backgroundColor: 'transparent' }}
45
45
  >
46
46
  <ChevronLeftIcon width={16} height={16} style={{ cursor: disableLeft ? 'not-allowed' : 'pointer' }} />
47
47
  </StyledPagination.Chevron>
@@ -54,7 +54,7 @@ const PaginationComponent = ({ page: propsPage, setPage: propsSetPage, numPages
54
54
  disabled={disableRight}
55
55
  onClick={nextPage}
56
56
  type="button"
57
- css={{ padding: 0, border: 'none', backgroundColor: '$transparent' }}
57
+ css={{ padding: 0, border: 'none', backgroundColor: 'transparent' }}
58
58
  >
59
59
  <ChevronRightIcon width={16} height={16} style={{ cursor: disableRight ? 'not-allowed' : 'pointer' }} />
60
60
  </StyledPagination.Chevron>
@@ -11,7 +11,7 @@ const IconButton = styled(BaseIconButton, {
11
11
  active: {
12
12
  true: {
13
13
  color: '$on_surface_high',
14
- backgroundColor: '$transparent',
14
+ backgroundColor: 'transparent',
15
15
  },
16
16
  false: {
17
17
  border: '1px solid transparent',
@@ -2,16 +2,20 @@ import React, { MutableRefObject, useCallback, useRef } from 'react';
2
2
  import { useMedia } from 'react-use';
3
3
  import { VariableSizeList } from 'react-window';
4
4
  import { selectSessionStore, selectUnreadHMSMessagesCount } from '@100mslive/hms-video-store';
5
+ import { match } from 'ts-pattern';
5
6
  import { selectHMSMessagesCount, useHMSActions, useHMSStore, useHMSVanillaStore } from '@100mslive/react-sdk';
6
7
  import { ChevronDownIcon } from '@100mslive/react-icons';
7
8
  import { Button } from '../../../Button';
8
- import { Flex } from '../../../Layout';
9
+ import { Box, Flex } from '../../../Layout';
9
10
  import { config as cssConfig } from '../../../Theme';
11
+ // @ts-ignore: No implicit any
12
+ import { EmojiReaction } from '../EmojiReaction';
10
13
  import { ChatBody } from './ChatBody';
11
14
  import { ChatFooter } from './ChatFooter';
12
15
  import { ChatBlocked, ChatPaused } from './ChatStates';
13
16
  import { PinnedMessage } from './PinnedMessage';
14
17
  import { useRoomLayoutConferencingScreen } from '../../provider/roomLayoutProvider/hooks/useRoomLayoutScreen';
18
+ import { useLandscapeHLSStream, useMobileHLSStream } from '../../common/hooks';
15
19
  import { SESSION_STORE_KEY } from '../../common/constants';
16
20
 
17
21
  export const Chat = () => {
@@ -21,6 +25,9 @@ export const Chat = () => {
21
25
  const vanillaStore = useHMSVanillaStore();
22
26
  const { enabled: isChatEnabled = true } = useHMSStore(selectSessionStore(SESSION_STORE_KEY.CHAT_STATE)) || {};
23
27
  const isMobile = useMedia(cssConfig.media.md);
28
+ const isMobileHLSStream = useMobileHLSStream();
29
+ const isLandscapeStream = useLandscapeHLSStream();
30
+
24
31
  const scrollToBottom = useCallback(
25
32
  (unreadCount = 0) => {
26
33
  if (listRef.current && listRef.current.scrollToItem && unreadCount > 0) {
@@ -46,6 +53,7 @@ export const Chat = () => {
46
53
  >
47
54
  {isMobile && elements?.chat?.is_overlay ? null : <PinnedMessage />}
48
55
  <ChatBody ref={listRef} scrollToBottom={scrollToBottom} />
56
+
49
57
  <ChatPaused />
50
58
  <ChatBlocked />
51
59
  {isMobile && elements?.chat?.is_overlay ? <PinnedMessage /> : null}
@@ -54,6 +62,38 @@ export const Chat = () => {
54
62
  <NewMessageIndicator scrollToBottom={scrollToBottom} listRef={listRef} />
55
63
  </ChatFooter>
56
64
  ) : null}
65
+ {(isMobileHLSStream || isLandscapeStream) && (
66
+ <Box
67
+ css={{
68
+ position: 'absolute',
69
+ ...match({ isLandscapeStream, isChatEnabled })
70
+ .with(
71
+ {
72
+ isLandscapeStream: true,
73
+ isChatEnabled: true,
74
+ },
75
+ () => ({ bottom: '$19', right: '$10' }),
76
+ )
77
+ .with(
78
+ {
79
+ isLandscapeStream: true,
80
+ isChatEnabled: false,
81
+ },
82
+ () => ({ bottom: '$20', right: '$10' }),
83
+ )
84
+ .with(
85
+ {
86
+ isLandscapeStream: false,
87
+ isChatEnabled: true,
88
+ },
89
+ () => ({ bottom: '$19', right: '$8' }),
90
+ )
91
+ .otherwise(() => ({})),
92
+ }}
93
+ >
94
+ <EmojiReaction />
95
+ </Box>
96
+ )}
57
97
  </Flex>
58
98
  );
59
99
  };
@@ -8,16 +8,16 @@ import { Box, config as cssConfig, Flex, IconButton as BaseIconButton, Popover,
8
8
  import { IconButton } from '../../../IconButton';
9
9
  import { MoreSettings } from '../MoreSettings/MoreSettings';
10
10
  import { RaiseHand } from '../RaiseHand';
11
- // @ts-ignore
11
+ // @ts-ignore: No implicit any
12
12
  import { ToastManager } from '../Toast/ToastManager';
13
13
  import { ChatSelectorContainer } from './ChatSelectorContainer';
14
14
  import { useRoomLayoutConferencingScreen } from '../../provider/roomLayoutProvider/hooks/useRoomLayoutScreen';
15
- // @ts-ignore
15
+ // @ts-ignore: No implicit any
16
16
  import { useChatDraftMessage } from '../AppData/useChatState';
17
- // @ts-ignore
17
+ // @ts-ignore: No implicit any
18
18
  import { useSetSubscribedChatSelector, useSubscribeChatSelector } from '../AppData/useUISettings';
19
19
  import { useIsPeerBlacklisted } from '../hooks/useChatBlacklist';
20
- // @ts-ignore
20
+ // @ts-ignore: No implicit any
21
21
  import { useEmojiPickerStyles } from './useEmojiPickerStyles';
22
22
  import { useDefaultChatSelection, useLandscapeHLSStream, useMobileHLSStream } from '../../common/hooks';
23
23
  import { CHAT_SELECTOR, SESSION_STORE_KEY } from '../../common/constants';
@@ -148,7 +148,7 @@ export const ChatFooter = ({ onSend, children }: { onSend: (count: number) => vo
148
148
  }
149
149
 
150
150
  return (
151
- <Box>
151
+ <Box css={{ position: 'relative' }}>
152
152
  <Flex>
153
153
  <ChatSelectorContainer />
154
154
  {canDisableChat && isMobile && isOverlayChat ? (
@@ -202,10 +202,12 @@ export const ChatFooter = ({ onSend, children }: { onSend: (count: number) => vo
202
202
  align="center"
203
203
  css={{
204
204
  bg: isOverlayChat && isMobile ? '$surface_dim' : '$surface_default',
205
+ minHeight: '$16',
205
206
  maxHeight: '$24',
206
207
  position: 'relative',
208
+ py: '$6',
207
209
  pl: '$8',
208
- flexGrow: '1',
210
+ flexGrow: 1,
209
211
  r: '$1',
210
212
  '@md': {
211
213
  minHeight: 'unset',
@@ -266,15 +268,17 @@ export const ChatFooter = ({ onSend, children }: { onSend: (count: number) => vo
266
268
  </BaseIconButton>
267
269
  </Flex>
268
270
  {(isMwebHLSStream || isLandscapeHLSStream) && (
269
- <Flex
270
- css={{
271
- alignItems: 'center',
272
- }}
273
- gap="1"
274
- >
275
- {noAVPermissions ? <RaiseHand /> : null}
276
- <MoreSettings elements={elements} screenType={screenType} />
277
- </Flex>
271
+ <>
272
+ <Flex
273
+ css={{
274
+ alignItems: 'center',
275
+ }}
276
+ gap="1"
277
+ >
278
+ {noAVPermissions ? <RaiseHand css={{ bg: '$surface_default' }} /> : null}
279
+ <MoreSettings elements={elements} screenType={screenType} />
280
+ </Flex>
281
+ </>
278
282
  )}
279
283
  </Flex>
280
284
  )}
@@ -1,4 +1,4 @@
1
- import React, { Fragment, useState } from 'react';
1
+ import React, { useState } from 'react';
2
2
  import { useMedia } from 'react-use';
3
3
  import data from '@emoji-mart/data/sets/14/apple.json';
4
4
  import { init } from 'emoji-mart';
@@ -7,9 +7,7 @@ import {
7
7
  selectIsConnectedToRoom,
8
8
  selectLocalPeerID,
9
9
  useCustomEvent,
10
- // useHMSActions,
11
10
  useHMSStore,
12
- // useRecordingStreaming,
13
11
  } from '@100mslive/react-sdk';
14
12
  import { EmojiIcon } from '@100mslive/react-icons';
15
13
  import { EmojiCard } from './Footer/EmojiCard';
@@ -20,6 +18,7 @@ import { config as cssConfig } from '../../Theme';
20
18
  import { Tooltip } from '../../Tooltip';
21
19
  import IconButton from '../IconButton';
22
20
  import { useDropdownList } from './hooks/useDropdownList';
21
+ import { useLandscapeHLSStream, useMobileHLSStream } from '../common/hooks';
23
22
  import { EMOJI_REACTION_TYPE } from '../common/constants';
24
23
 
25
24
  init({ data });
@@ -33,6 +32,9 @@ export const EmojiReaction = () => {
33
32
  const localPeerId = useHMSStore(selectLocalPeerID);
34
33
  // const { isStreamingOn } = useRecordingStreaming();
35
34
  const isMobile = useMedia(cssConfig.media.md);
35
+ const isLandscape = useMedia(cssConfig.media.ls);
36
+ const isMobileHLSStream = useMobileHLSStream();
37
+ const isLandscapeStream = useLandscapeHLSStream();
36
38
 
37
39
  const { sendEvent } = useCustomEvent({
38
40
  type: EMOJI_REACTION_TYPE,
@@ -65,24 +67,32 @@ export const EmojiReaction = () => {
65
67
  if (!isConnected) {
66
68
  return null;
67
69
  }
68
- return isMobile ? (
69
- <EmojiCard sendReaction={sendReaction} />
70
- ) : (
71
- <Fragment>
72
- <Dropdown.Root open={open} onOpenChange={setOpen}>
73
- <Dropdown.Trigger asChild data-testid="emoji_reaction_btn">
74
- <IconButton>
75
- <Tooltip title="Emoji reaction">
76
- <Box>
77
- <EmojiIcon />
78
- </Box>
79
- </Tooltip>
80
- </IconButton>
81
- </Dropdown.Trigger>
82
- <Dropdown.Content sideOffset={5} align="center" css={{ p: '$8', bg: '$surface_default' }}>
83
- <EmojiCard sendReaction={sendReaction} />
84
- </Dropdown.Content>
85
- </Dropdown.Root>
86
- </Fragment>
70
+
71
+ if ((isMobile || isLandscape) && !(isLandscapeStream || isMobileHLSStream)) {
72
+ return <EmojiCard sendReaction={sendReaction} />;
73
+ }
74
+ return (
75
+ <Dropdown.Root open={open} onOpenChange={setOpen}>
76
+ <Dropdown.Trigger asChild data-testid="emoji_reaction_btn">
77
+ <IconButton
78
+ css={
79
+ isMobile || isLandscape ? { bg: '$surface_default', r: '$round', border: '1px solid $border_bright' } : {}
80
+ }
81
+ >
82
+ <Tooltip title="Emoji reaction">
83
+ <Box>
84
+ <EmojiIcon />
85
+ </Box>
86
+ </Tooltip>
87
+ </IconButton>
88
+ </Dropdown.Trigger>
89
+ <Dropdown.Content
90
+ sideOffset={5}
91
+ align={isMobileHLSStream || isLandscapeStream ? 'end' : 'center'}
92
+ css={{ p: '$8', bg: '$surface_default' }}
93
+ >
94
+ <EmojiCard sendReaction={sendReaction} />
95
+ </Dropdown.Content>
96
+ </Dropdown.Root>
87
97
  );
88
98
  };
@@ -1,12 +1,13 @@
1
1
  import React, { useState } from 'react';
2
2
  import { DefaultConferencingScreen_Elements } from '@100mslive/types-prebuilt';
3
+ import { match } from 'ts-pattern';
3
4
  import {
4
5
  HMSPeer,
5
6
  selectPermissions,
6
7
  selectRoleByRoleName,
8
+ selectTracksMap,
7
9
  useHMSActions,
8
10
  useHMSStore,
9
- useHMSVanillaStore,
10
11
  } from '@100mslive/react-sdk';
11
12
  import {
12
13
  MicOffIcon,
@@ -32,12 +33,59 @@ const optionTextCSS = {
32
33
  whiteSpace: 'nowrap',
33
34
  };
34
35
 
35
- const MuteUnmuteOption = ({ roleName, peerList }: { peerList: HMSPeer[]; roleName: string }) => {
36
- const vanillaStore = useHMSVanillaStore();
37
- const store = vanillaStore.getState();
38
- const hmsActions = useHMSActions();
36
+ const DropdownWrapper = ({ children }: { children: React.ReactNode }) => {
37
+ const [openOptions, setOpenOptions] = useState(false);
38
+ if (React.Children.toArray(children).length === 0) {
39
+ return null;
40
+ }
41
+ React.Children.map(children, child => {
42
+ console.log({ child });
43
+ });
44
+ return (
45
+ <Dropdown.Root open={openOptions} onOpenChange={setOpenOptions}>
46
+ <Dropdown.Trigger
47
+ data-testid="role_group_options"
48
+ onClick={e => e.stopPropagation()}
49
+ className="role_actions"
50
+ asChild
51
+ css={{
52
+ p: '$1',
53
+ r: '$0',
54
+ c: '$on_surface_high',
55
+ visibility: openOptions ? 'visible' : 'hidden',
56
+ '&:hover': {
57
+ c: '$on_surface_medium',
58
+ },
59
+ '@md': {
60
+ visibility: 'visible',
61
+ },
62
+ }}
63
+ >
64
+ <Flex>
65
+ <VerticalMenuIcon />
66
+ </Flex>
67
+ </Dropdown.Trigger>
68
+ <Dropdown.Content
69
+ onClick={e => e.stopPropagation()}
70
+ css={{ w: 'max-content', bg: '$surface_default', py: 0 }}
71
+ align="end"
72
+ >
73
+ {children}
74
+ </Dropdown.Content>
75
+ </Dropdown.Root>
76
+ );
77
+ };
78
+
79
+ export const RoleOptions = ({ roleName, peerList }: { roleName: string; peerList: HMSPeer[] }) => {
39
80
  const permissions = useHMSStore(selectPermissions);
81
+ const hmsActions = useHMSActions();
82
+ const { elements } = useRoomLayoutConferencingScreen();
83
+ const { on_stage_role, off_stage_roles = [] } = (elements as DefaultConferencingScreen_Elements)?.on_stage_exp || {};
84
+ const canRemoveRoleFromStage = permissions?.changeRole && roleName === on_stage_role;
40
85
  const role = useHMSStore(selectRoleByRoleName(roleName));
86
+ const canPublishAudio = role.publishParams.allowed.includes('audio');
87
+ const canPublishVideo = role.publishParams.allowed.includes('video');
88
+ const tracks = useHMSStore(selectTracksMap);
41
89
 
42
90
  let isVideoOnForSomePeers = false;
43
91
  let isAudioOnForSomePeers = false;
@@ -46,8 +94,8 @@ const MuteUnmuteOption = ({ roleName, peerList }: { peerList: HMSPeer[]; roleNam
46
94
  if (peer.isLocal) {
47
95
  return;
48
96
  }
49
- const isAudioOn = !!peer.audioTrack && store.tracks[peer.audioTrack]?.enabled;
50
- const isVideoOn = !!peer.videoTrack && store.tracks[peer.videoTrack]?.enabled;
97
+ const isAudioOn = !!peer.audioTrack && tracks[peer.audioTrack]?.enabled;
98
+ const isVideoOn = !!peer.videoTrack && tracks[peer.videoTrack]?.enabled;
51
99
  isAudioOnForSomePeers = isAudioOnForSomePeers || isAudioOn;
52
100
  isVideoOnForSomePeers = isVideoOnForSomePeers || isVideoOn;
53
101
  });
@@ -60,75 +108,11 @@ const MuteUnmuteOption = ({ roleName, peerList }: { peerList: HMSPeer[]; roleNam
60
108
  }
61
109
  };
62
110
 
63
- if (!role) {
64
- return null;
65
- }
66
-
67
- return (
68
- <>
69
- {role.publishParams.allowed.includes('audio') && (
70
- <>
71
- {isAudioOnForSomePeers && permissions?.mute ? (
72
- <Dropdown.Item css={dropdownItemCSS} onClick={() => setTrackEnabled('audio', false)}>
73
- <MicOffIcon />
74
- <Text variant="sm" css={optionTextCSS}>
75
- Mute Audio for All
76
- </Text>
77
- </Dropdown.Item>
78
- ) : null}
79
-
80
- {!isAudioOnForSomePeers && permissions?.unmute ? (
81
- <Dropdown.Item css={dropdownItemCSS} onClick={() => setTrackEnabled('audio', true)}>
82
- <MicOnIcon />
83
- <Text variant="sm" css={optionTextCSS}>
84
- Request to Unmute Audio for All
85
- </Text>
86
- </Dropdown.Item>
87
- ) : null}
88
- </>
89
- )}
90
-
91
- {role.publishParams.allowed.includes('video') && (
92
- <>
93
- {isVideoOnForSomePeers && permissions?.mute ? (
94
- <Dropdown.Item css={dropdownItemCSS} onClick={() => setTrackEnabled('video', false)}>
95
- <VideoOffIcon />
96
- <Text variant="sm" css={optionTextCSS}>
97
- Mute Video for All
98
- </Text>
99
- </Dropdown.Item>
100
- ) : null}
101
-
102
- {!isVideoOnForSomePeers && permissions?.unmute ? (
103
- <Dropdown.Item css={dropdownItemCSS} onClick={() => setTrackEnabled('video', true)}>
104
- <VideoOnIcon />
105
- <Text variant="sm" css={optionTextCSS}>
106
- Request to Unmute Video for All
107
- </Text>
108
- </Dropdown.Item>
109
- ) : null}
110
- </>
111
- )}
112
- </>
113
- );
114
- };
115
-
116
- export const RoleOptions = ({ roleName, peerList }: { roleName: string; peerList: HMSPeer[] }) => {
117
- const [openOptions, setOpenOptions] = useState(false);
118
- const permissions = useHMSStore(selectPermissions);
119
- const hmsActions = useHMSActions();
120
- const { elements } = useRoomLayoutConferencingScreen();
121
- const { on_stage_role, off_stage_roles = [] } = (elements as DefaultConferencingScreen_Elements)?.on_stage_exp || {};
122
- const canMuteOrUnmute = permissions?.mute || permissions?.unmute;
123
- const canRemoveRoleFromStage = permissions?.changeRole && roleName === on_stage_role;
124
- const role = useHMSStore(selectRoleByRoleName(roleName));
125
-
126
111
  // on stage and off stage roles
127
112
  const canRemoveRoleFromRoom =
128
113
  permissions?.removeOthers && (on_stage_role === roleName || off_stage_roles?.includes(roleName));
129
114
 
130
115
  if (
131
- !(canMuteOrUnmute || canRemoveRoleFromStage || canRemoveRoleFromRoom) ||
132
116
  peerList.length === 0 ||
133
117
  // if only local peer is present no need to show any options
134
118
  (peerList.length === 1 && peerList[0].isLocal) ||
@@ -157,60 +141,75 @@ export const RoleOptions = ({ roleName, peerList }: { roleName: string; peerList
157
141
  };
158
142
 
159
143
  return (
160
- <Dropdown.Root open={openOptions} onOpenChange={setOpenOptions}>
161
- <Dropdown.Trigger
162
- data-testid="role_group_options"
163
- onClick={e => e.stopPropagation()}
164
- className="role_actions"
165
- asChild
166
- css={{
167
- p: '$1',
168
- r: '$0',
169
- c: '$on_surface_high',
170
- visibility: openOptions ? 'visible' : 'hidden',
171
- '&:hover': {
172
- c: '$on_surface_medium',
173
- },
174
- '@md': {
175
- visibility: 'visible',
176
- },
177
- }}
178
- >
179
- <Flex>
180
- <VerticalMenuIcon />
181
- </Flex>
182
- </Dropdown.Trigger>
183
- <Dropdown.Content
184
- onClick={e => e.stopPropagation()}
185
- css={{ w: 'max-content', bg: '$surface_default', py: 0 }}
186
- align="end"
187
- >
188
- {canRemoveRoleFromStage && (
189
- <Dropdown.Item
190
- css={{ ...dropdownItemCSS, borderBottom: '1px solid $border_bright' }}
191
- onClick={removeAllFromStage}
192
- >
193
- <PersonRectangleIcon />
194
- <Text variant="sm" css={optionTextCSS}>
195
- Remove all from Stage
196
- </Text>
197
- </Dropdown.Item>
198
- )}
199
-
200
- {canMuteOrUnmute && <MuteUnmuteOption peerList={peerList} roleName={roleName} />}
201
-
202
- {canRemoveRoleFromRoom && (
203
- <Dropdown.Item
204
- css={{ ...dropdownItemCSS, borderTop: '1px solid $border_bright', color: '$alert_error_default' }}
205
- onClick={removePeersFromRoom}
206
- >
207
- <RemoveUserIcon />
208
- <Text variant="sm" css={{ ...optionTextCSS, color: 'inherit' }}>
209
- Remove all from Room
210
- </Text>
211
- </Dropdown.Item>
212
- )}
213
- </Dropdown.Content>
214
- </Dropdown.Root>
144
+ <DropdownWrapper>
145
+ {canRemoveRoleFromStage ? (
146
+ <Dropdown.Item
147
+ css={{ ...dropdownItemCSS, borderBottom: '1px solid $border_bright' }}
148
+ onClick={removeAllFromStage}
149
+ >
150
+ <PersonRectangleIcon />
151
+ <Text variant="sm" css={optionTextCSS}>
152
+ Remove all from Stage
153
+ </Text>
154
+ </Dropdown.Item>
155
+ ) : null}
156
+
157
+ {match({ canPublishAudio, isAudioOnForSomePeers, canMute: permissions?.mute, canUnmute: permissions?.unmute })
158
+ .with({ canPublishAudio: true, isAudioOnForSomePeers: true, canMute: true }, () => {
159
+ return (
160
+ <Dropdown.Item css={dropdownItemCSS} onClick={() => setTrackEnabled('audio', false)}>
161
+ <MicOffIcon />
162
+ <Text variant="sm" css={optionTextCSS}>
163
+ Mute Audio for All
164
+ </Text>
165
+ </Dropdown.Item>
166
+ );
167
+ })
168
+ .with({ canPublishAudio: true, isAudioOnForSomePeers: false, canUnmute: true }, () => {
169
+ return (
170
+ <Dropdown.Item css={dropdownItemCSS} onClick={() => setTrackEnabled('audio', true)}>
171
+ <MicOnIcon />
172
+ <Text variant="sm" css={optionTextCSS}>
173
+ Request to Unmute Audio for All
174
+ </Text>
175
+ </Dropdown.Item>
176
+ );
177
+ })
178
+ .otherwise(() => null)}
179
+ {match({ canPublishVideo, isVideoOnForSomePeers, canMute: permissions?.mute, canUnmute: permissions?.unmute })
180
+ .with({ canPublishVideo: true, isVideoOnForSomePeers: true, canMute: true }, () => {
181
+ return (
182
+ <Dropdown.Item css={dropdownItemCSS} onClick={() => setTrackEnabled('video', false)}>
183
+ <VideoOffIcon />
184
+ <Text variant="sm" css={optionTextCSS}>
185
+ Mute Video for All
186
+ </Text>
187
+ </Dropdown.Item>
188
+ );
189
+ })
190
+ .with({ canPublishVideo: true, isVideoOnForSomePeers: false, canUnmute: true }, () => {
191
+ return (
192
+ <Dropdown.Item css={dropdownItemCSS} onClick={() => setTrackEnabled('video', true)}>
193
+ <VideoOnIcon />
194
+ <Text variant="sm" css={optionTextCSS}>
195
+ Request to Unmute Video for All
196
+ </Text>
197
+ </Dropdown.Item>
198
+ );
199
+ })
200
+ .otherwise(() => null)}
201
+
202
+ {canRemoveRoleFromRoom ? (
203
+ <Dropdown.Item
204
+ css={{ ...dropdownItemCSS, borderTop: '1px solid $border_bright', color: '$alert_error_default' }}
205
+ onClick={removePeersFromRoom}
206
+ >
207
+ <RemoveUserIcon />
208
+ <Text variant="sm" css={{ ...optionTextCSS, color: 'inherit' }}>
209
+ Remove all from Room
210
+ </Text>
211
+ </Dropdown.Item>
212
+ ) : null}
213
+ </DropdownWrapper>
215
214
  );
216
215
  };