@100mslive/roomkit-react 0.1.6-alpha.1 → 0.1.6-alpha.2

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 (38) hide show
  1. package/dist/{HLSView-HNVYG5VE.js → HLSView-QMU5JK7U.js} +3 -3
  2. package/dist/Prebuilt/components/Footer/ChatToggle.d.ts +1 -3
  3. package/dist/Prebuilt/components/SidePaneTabs.d.ts +7 -0
  4. package/dist/{VirtualBackground-UM2FOUHQ.js → VirtualBackground-37FXUPYO.js} +6 -6
  5. package/dist/VirtualBackground-37FXUPYO.js.map +7 -0
  6. package/dist/{chunk-POE7H4IE.js → chunk-KBVIZGYW.js} +2 -2
  7. package/dist/{chunk-POE7H4IE.js.map → chunk-KBVIZGYW.js.map} +1 -1
  8. package/dist/{chunk-LYSAET4G.js → chunk-WVGGQZK4.js} +100 -106
  9. package/dist/{chunk-LYSAET4G.js.map → chunk-WVGGQZK4.js.map} +3 -3
  10. package/dist/{chunk-364HP22I.js → chunk-ZKE2N5LH.js} +2 -2
  11. package/dist/{conference-UWLJHMB2.js → conference-FJJQ4TXX.js} +419 -384
  12. package/dist/conference-FJJQ4TXX.js.map +7 -0
  13. package/dist/index.cjs.js +594 -570
  14. package/dist/index.cjs.js.map +4 -4
  15. package/dist/index.js +2 -2
  16. package/dist/meta.cjs.json +127 -127
  17. package/dist/meta.esbuild.json +161 -160
  18. package/package.json +6 -6
  19. package/src/Prebuilt/components/Chat/Chat.jsx +2 -6
  20. package/src/Prebuilt/components/Footer/ChatToggle.tsx +2 -9
  21. package/src/Prebuilt/components/Footer/Footer.tsx +22 -6
  22. package/src/Prebuilt/components/Footer/ParticipantList.jsx +0 -2
  23. package/src/Prebuilt/components/Header/HeaderComponents.jsx +8 -1
  24. package/src/Prebuilt/components/InsetTile.tsx +1 -0
  25. package/src/Prebuilt/components/MoreSettings/SplitComponents/MwebOptions.tsx +1 -1
  26. package/src/Prebuilt/components/Notifications/Notifications.jsx +14 -7
  27. package/src/Prebuilt/components/Preview/PreviewJoin.tsx +2 -3
  28. package/src/Prebuilt/components/RoleChangeRequestModal.tsx +6 -4
  29. package/src/Prebuilt/components/SidePaneTabs.tsx +120 -0
  30. package/src/Prebuilt/components/hooks/useMetadata.jsx +7 -25
  31. package/src/Prebuilt/layouts/SidePane.tsx +12 -10
  32. package/src/Prebuilt/plugins/VirtualBackground/VirtualBackground.jsx +3 -3
  33. package/src/Prebuilt/provider/roomLayoutProvider/hooks/useFetchRoomLayout.ts +2 -2
  34. package/dist/VirtualBackground-UM2FOUHQ.js.map +0 -7
  35. package/dist/conference-UWLJHMB2.js.map +0 -7
  36. package/src/Prebuilt/components/Chat/ChatParticipantHeader.jsx +0 -84
  37. /package/dist/{HLSView-HNVYG5VE.js.map → HLSView-QMU5JK7U.js.map} +0 -0
  38. /package/dist/{chunk-364HP22I.js.map → chunk-ZKE2N5LH.js.map} +0 -0
package/package.json CHANGED
@@ -10,7 +10,7 @@
10
10
  "prebuilt",
11
11
  "roomkit"
12
12
  ],
13
- "version": "0.1.6-alpha.1",
13
+ "version": "0.1.6-alpha.2",
14
14
  "author": "100ms",
15
15
  "license": "MIT",
16
16
  "files": [
@@ -76,10 +76,10 @@
76
76
  "react": ">=17.0.2 <19.0.0"
77
77
  },
78
78
  "dependencies": {
79
- "@100mslive/hls-player": "0.1.15-alpha.1",
80
- "@100mslive/hms-virtual-background": "1.11.15-alpha.1",
81
- "@100mslive/react-icons": "0.8.15-alpha.1",
82
- "@100mslive/react-sdk": "0.8.15-alpha.1",
79
+ "@100mslive/hls-player": "0.1.15-alpha.2",
80
+ "@100mslive/hms-virtual-background": "1.11.15-alpha.2",
81
+ "@100mslive/react-icons": "0.8.15-alpha.2",
82
+ "@100mslive/react-sdk": "0.8.15-alpha.2",
83
83
  "@100mslive/types-prebuilt": "0.12.0",
84
84
  "@emoji-mart/data": "^1.0.6",
85
85
  "@emoji-mart/react": "^1.0.1",
@@ -115,5 +115,5 @@
115
115
  "uuid": "^8.3.2",
116
116
  "worker-timers": "^7.0.40"
117
117
  },
118
- "gitHead": "d3f042d48bb30f16c6c63f2a75c406611c0f2831"
118
+ "gitHead": "e9017621fb9f9594f985d47483ccab4bed324a35"
119
119
  }
@@ -17,7 +17,6 @@ import { Text } from '../../../Text';
17
17
  import { config as cssConfig } from '../../../Theme';
18
18
  import { AnnotisedMessage, ChatBody } from './ChatBody';
19
19
  import { ChatFooter } from './ChatFooter';
20
- import { ChatParticipantHeader } from './ChatParticipantHeader';
21
20
  import { useRoomLayoutConferencingScreen } from '../../provider/roomLayoutProvider/hooks/useRoomLayoutScreen';
22
21
  import { useSetSubscribedChatSelector } from '../AppData/useUISettings';
23
22
  import { useSetPinnedMessage } from '../hooks/useSetPinnedMessage';
@@ -77,7 +76,7 @@ export const Chat = ({ screenType, hideControls = false }) => {
77
76
  peerId: peerSelector && peerName ? peerSelector : '',
78
77
  selection: roleSelector ? roleSelector : peerSelector && peerName ? peerName : 'Everyone',
79
78
  });
80
- const [isSelectorOpen, setSelectorOpen] = useState(false);
79
+ const [isSelectorOpen] = useState(false);
81
80
  const listRef = useRef(null);
82
81
  const hmsActions = useHMSActions();
83
82
  const { setPinnedMessage } = useSetPinnedMessage();
@@ -128,10 +127,7 @@ export const Chat = ({ screenType, hideControls = false }) => {
128
127
  }}
129
128
  >
130
129
  {isMobile && elements?.chat?.is_overlay ? null : (
131
- <>
132
- <ChatParticipantHeader selectorOpen={isSelectorOpen} onToggle={() => setSelectorOpen(value => !value)} />
133
- {elements?.chat?.allow_pinning_messages ? <PinnedMessage clearPinnedMessage={setPinnedMessage} /> : null}
134
- </>
130
+ <>{elements?.chat?.allow_pinning_messages ? <PinnedMessage clearPinnedMessage={setPinnedMessage} /> : null}</>
135
131
  )}
136
132
 
137
133
  <ChatBody
@@ -1,4 +1,4 @@
1
- import React, { useEffect } from 'react';
1
+ import React from 'react';
2
2
  import { selectUnreadHMSMessagesCount, useHMSStore } from '@100mslive/react-sdk';
3
3
  import { ChatIcon, ChatUnreadIcon } from '@100mslive/react-icons';
4
4
  import { Tooltip } from '../../..';
@@ -9,18 +9,11 @@ import { useIsSidepaneTypeOpen, useSidepaneToggle } from '../AppData/useSidepane
9
9
  // @ts-ignore: No implicit Any
10
10
  import { SIDE_PANE_OPTIONS } from '../../common/constants';
11
11
 
12
- export const ChatToggle = ({ openByDefault }: { openByDefault: boolean }) => {
12
+ export const ChatToggle = () => {
13
13
  const countUnreadMessages = useHMSStore(selectUnreadHMSMessagesCount);
14
14
  const isChatOpen = useIsSidepaneTypeOpen(SIDE_PANE_OPTIONS.CHAT);
15
15
  const toggleChat = useSidepaneToggle(SIDE_PANE_OPTIONS.CHAT);
16
16
 
17
- useEffect(() => {
18
- if (!isChatOpen && openByDefault) {
19
- toggleChat();
20
- }
21
- // eslint-disable-next-line react-hooks/exhaustive-deps
22
- }, [toggleChat, openByDefault]);
23
-
24
17
  return (
25
18
  <Tooltip key="chat" title={`${isChatOpen ? 'Close' : 'Open'} chat`}>
26
19
  <IconButton onClick={toggleChat} active={!isChatOpen} data-testid="chat_btn">
@@ -1,4 +1,4 @@
1
- import React, { Suspense } from 'react';
1
+ import React, { Suspense, useEffect } from 'react';
2
2
  import { useMedia } from 'react-use';
3
3
  import {
4
4
  ConferencingScreen,
@@ -6,7 +6,6 @@ import {
6
6
  HLSLiveStreamingScreen_Elements,
7
7
  } from '@100mslive/types-prebuilt';
8
8
  import { Chat_ChatState } from '@100mslive/types-prebuilt/elements/chat';
9
- import { selectIsLocalVideoEnabled, useHMSStore } from '@100mslive/react-sdk';
10
9
  import { config as cssConfig, Footer as AppFooter } from '../../..';
11
10
  // @ts-ignore: No implicit Any
12
11
  import { AudioVideoToggle } from '../AudioVideoToggle';
@@ -25,6 +24,10 @@ import { ChatToggle } from './ChatToggle';
25
24
  // @ts-ignore: No implicit Any
26
25
  import { ParticipantCount } from './ParticipantList';
27
26
  // @ts-ignore: No implicit Any
27
+ import { useIsSidepaneTypeOpen, useSidepaneToggle } from '../AppData/useSidepane';
28
+ // @ts-ignore: No implicit Any
29
+ import { SIDE_PANE_OPTIONS } from '../../common/constants';
30
+ // @ts-ignore: No implicit Any
28
31
  const VirtualBackground = React.lazy(() => import('../../plugins/VirtualBackground/VirtualBackground'));
29
32
 
30
33
  export const Footer = ({
@@ -37,7 +40,16 @@ export const Footer = ({
37
40
  const isMobile = useMedia(cssConfig.media.md);
38
41
  const isOverlayChat = !!elements?.chat?.is_overlay;
39
42
  const openByDefault = elements?.chat?.initial_state === Chat_ChatState.CHAT_STATE_OPEN;
40
- const isVideoOn = useHMSStore(selectIsLocalVideoEnabled);
43
+
44
+ const isChatOpen = useIsSidepaneTypeOpen(SIDE_PANE_OPTIONS.CHAT);
45
+ const toggleChat = useSidepaneToggle(SIDE_PANE_OPTIONS.CHAT);
46
+
47
+ useEffect(() => {
48
+ if (!isChatOpen && openByDefault) {
49
+ toggleChat();
50
+ }
51
+ // eslint-disable-next-line react-hooks/exhaustive-deps
52
+ }, [toggleChat, openByDefault]);
41
53
 
42
54
  return (
43
55
  <AppFooter.Root
@@ -63,7 +75,11 @@ export const Footer = ({
63
75
  >
64
76
  {isMobile ? <LeaveRoom screenType={screenType} /> : null}
65
77
  <AudioVideoToggle />
66
- {isMobile ? null : <Suspense fallback={<></>}>{isVideoOn ? <VirtualBackground /> : null}</Suspense>}
78
+ {isMobile ? null : (
79
+ <Suspense fallback={<></>}>
80
+ <VirtualBackground />
81
+ </Suspense>
82
+ )}
67
83
  </AppFooter.Left>
68
84
  <AppFooter.Center
69
85
  css={{
@@ -76,7 +92,7 @@ export const Footer = ({
76
92
  {isMobile ? (
77
93
  <>
78
94
  {screenType === 'hls_live_streaming' ? <RaiseHand /> : null}
79
- {elements?.chat && <ChatToggle openByDefault={openByDefault} />}
95
+ {elements?.chat && <ChatToggle />}
80
96
  <MoreSettings elements={elements} screenType={screenType} />
81
97
  </>
82
98
  ) : (
@@ -89,7 +105,7 @@ export const Footer = ({
89
105
  )}
90
106
  </AppFooter.Center>
91
107
  <AppFooter.Right>
92
- {!isMobile && elements?.chat && <ChatToggle openByDefault={openByDefault} />}
108
+ {!isMobile && elements?.chat && <ChatToggle />}
93
109
  {elements?.participant_list && <ParticipantCount />}
94
110
  <MoreSettings elements={elements} screenType={screenType} />
95
111
  </AppFooter.Right>
@@ -21,7 +21,6 @@ import {
21
21
  } from '@100mslive/react-icons';
22
22
  import { Box, config as cssConfig, Dropdown, Flex, Input, Text, textEllipsis } from '../../..';
23
23
  import IconButton from '../../IconButton';
24
- import { ChatParticipantHeader } from '../Chat/ChatParticipantHeader';
25
24
  import { ConnectionIndicator } from '../Connection/ConnectionIndicator';
26
25
  import { ToastManager } from '../Toast/ToastManager';
27
26
  import { RoleAccordion } from './RoleAccordion';
@@ -61,7 +60,6 @@ export const ParticipantList = () => {
61
60
  return (
62
61
  <Fragment>
63
62
  <Flex direction="column" css={{ size: '100%', gap: '$4' }}>
64
- <ChatParticipantHeader activeTabValue={SIDE_PANE_OPTIONS.PARTICIPANTS} />
65
63
  {!filter?.search && participants.length === 0 ? null : <ParticipantSearch onSearch={onSearch} inSidePane />}
66
64
  {participants.length === 0 ? (
67
65
  <Flex align="center" justify="center" css={{ w: '100%', p: '$8 0' }}>
@@ -1,4 +1,4 @@
1
- import React, { useState } from 'react';
1
+ import React, { useEffect, useState } from 'react';
2
2
  import { useMedia } from 'react-use';
3
3
  import { selectDominantSpeaker, selectIsConnectedToRoom, useHMSStore } from '@100mslive/react-sdk';
4
4
  import { VolumeOneIcon } from '@100mslive/react-icons';
@@ -41,6 +41,13 @@ export const Logo = () => {
41
41
  const isConnected = useHMSStore(selectIsConnectedToRoom);
42
42
  const [hideImage, setHideImage] = useState(false);
43
43
  // Hide logo for now as there is not enough space
44
+ useEffect(() => {
45
+ if (hideImage) {
46
+ setHideImage(false);
47
+ }
48
+ // eslint-disable-next-line react-hooks/exhaustive-deps
49
+ }, [logo]);
50
+
44
51
  if (isConnected && isMobile) {
45
52
  return null;
46
53
  }
@@ -120,6 +120,7 @@ export const InsetTile = () => {
120
120
  canMinimise
121
121
  isDragabble
122
122
  {...videoTileProps}
123
+ hideParticipantNameOnTile
123
124
  />
124
125
  )}
125
126
  </Box>
@@ -266,7 +266,7 @@ export const MwebOptions = ({
266
266
  </Box>
267
267
  </Sheet.Content>
268
268
  </Sheet.Root>
269
- <SettingsModal open={openSettingsSheet} onOpenChange={setOpenSettingsSheet} />
269
+ <SettingsModal open={openSettingsSheet} onOpenChange={setOpenSettingsSheet} screenType={screenType} />
270
270
  {openModals.has(MODALS.MUTE_ALL) && (
271
271
  <MuteAllModal onOpenChange={(value: boolean) => updateState(MODALS.MUTE_ALL, value)} isMobile />
272
272
  )}
@@ -4,10 +4,12 @@ import { useNavigate, useParams } from 'react-router-dom';
4
4
  import {
5
5
  HMSNotificationTypes,
6
6
  HMSRoomState,
7
+ selectPeerMetadata,
7
8
  selectRoomState,
8
9
  useCustomEvent,
9
10
  useHMSNotifications,
10
11
  useHMSStore,
12
+ useHMSVanillaStore,
11
13
  } from '@100mslive/react-sdk';
12
14
  import { Button } from '../../../';
13
15
  import { useUpdateRoomLayout } from '../../provider/roomLayoutProvider';
@@ -29,6 +31,7 @@ export function Notifications() {
29
31
  const notification = useHMSNotifications();
30
32
  const navigate = useNavigate();
31
33
  const params = useParams();
34
+ const vanillaStore = useHMSVanillaStore();
32
35
  const subscribedNotifications = useSubscribedNotifications() || {};
33
36
  const roomState = useHMSStore(selectRoomState);
34
37
  const updateRoomLayoutForRole = useUpdateRoomLayout();
@@ -53,8 +56,8 @@ export function Notifications() {
53
56
  if (roomState !== HMSRoomState.Connected) {
54
57
  return;
55
58
  }
56
- // Don't toast message when metadata is updated and raiseHand is false.
57
- // Don't toast message in case of local peer.
59
+ // Don't show toast message when metadata is updated and raiseHand is false.
60
+ // Don't show toast message in case of local peer.
58
61
  const metadata = getMetadata(notification.data?.metadata);
59
62
  if (!metadata?.isHandRaised || notification.data.isLocal) return;
60
63
 
@@ -108,14 +111,18 @@ export function Notifications() {
108
111
  title: `Error: ${notification.data?.message} - ${notification.data?.description}`,
109
112
  });
110
113
  break;
111
- case HMSNotificationTypes.ROLE_UPDATED:
114
+ case HMSNotificationTypes.ROLE_UPDATED: {
112
115
  if (notification.data?.isLocal) {
113
- ToastManager.addToast({
114
- title: `You are now a ${notification.data.roleName}`,
115
- });
116
- updateRoomLayoutForRole(notification.data.roleName);
116
+ const { prevRole } = vanillaStore.getState(selectPeerMetadata(notification.data?.id));
117
+ if (prevRole !== notification?.data?.roleName) {
118
+ ToastManager.addToast({
119
+ title: `You are now a ${notification.data.roleName}`,
120
+ });
121
+ updateRoomLayoutForRole(notification.data.roleName);
122
+ }
117
123
  }
118
124
  break;
125
+ }
119
126
  case HMSNotificationTypes.CHANGE_TRACK_STATE_REQUEST:
120
127
  const track = notification.data?.track;
121
128
  if (!notification.data.enabled) {
@@ -246,7 +246,6 @@ export const PreviewTile = ({ name, error }: { name: string; error?: boolean })
246
246
  };
247
247
 
248
248
  export const PreviewControls = ({ hideSettings }: { hideSettings: boolean }) => {
249
- const isVideoOn = useHMSStore(selectIsLocalVideoEnabled);
250
249
  const isMobile = useMedia(cssConfig.media.md);
251
250
 
252
251
  return (
@@ -258,8 +257,8 @@ export const PreviewControls = ({ hideSettings }: { hideSettings: boolean }) =>
258
257
  }}
259
258
  >
260
259
  <Flex css={{ gap: '$4' }}>
261
- <AudioVideoToggle compact />
262
- <Suspense fallback="">{isVideoOn && !isMobile ? <VirtualBackground /> : null}</Suspense>
260
+ <AudioVideoToggle />
261
+ <Suspense fallback="">{!isMobile ? <VirtualBackground /> : null}</Suspense>
263
262
  </Flex>
264
263
  {!hideSettings ? <PreviewSettings /> : null}
265
264
  </Flex>
@@ -27,9 +27,11 @@ export const RoleChangeRequestModal = () => {
27
27
  if (!roleChangeRequest?.role) {
28
28
  return;
29
29
  }
30
-
31
- hmsActions.preview({ asRole: roleChangeRequest.role.name });
32
- }, [hmsActions, roleChangeRequest]);
30
+ (async () => {
31
+ await updateMetaData({ prevRole: currentRole });
32
+ await hmsActions.preview({ asRole: roleChangeRequest.role.name });
33
+ })();
34
+ }, [hmsActions, roleChangeRequest, currentRole, updateMetaData]);
33
35
 
34
36
  if (!roleChangeRequest?.role) {
35
37
  return null;
@@ -69,7 +71,7 @@ export const RoleChangeRequestModal = () => {
69
71
  body={body}
70
72
  onAction={async () => {
71
73
  await hmsActions.acceptChangeRole(roleChangeRequest);
72
- await updateMetaData({ isHandRaised: false, prevRole: currentRole });
74
+ await updateMetaData({ isHandRaised: false });
73
75
  }}
74
76
  actionText="Accept"
75
77
  />
@@ -0,0 +1,120 @@
1
+ import React, { useEffect, useState } from 'react';
2
+ import { ConferencingScreen } from '@100mslive/types-prebuilt';
3
+ import { selectPeerCount, useHMSStore } from '@100mslive/react-sdk';
4
+ import { CrossIcon } from '@100mslive/react-icons';
5
+ // @ts-ignore: No implicit Any
6
+ import { Chat } from './Chat/Chat';
7
+ // @ts-ignore: No implicit Any
8
+ import { ParticipantList } from './Footer/ParticipantList';
9
+ import { Flex, IconButton, Tabs, Text } from '../..';
10
+ import { useRoomLayoutConferencingScreen } from '../provider/roomLayoutProvider/hooks/useRoomLayoutScreen';
11
+ // @ts-ignore: No implicit Any
12
+ import { useSidepaneReset, useSidepaneToggle } from './AppData/useSidepane';
13
+ // @ts-ignore: No implicit Any
14
+ import { SIDE_PANE_OPTIONS } from '../common/constants';
15
+
16
+ const tabTriggerCSS = {
17
+ color: '$on_surface_high',
18
+ p: '$4',
19
+ fontWeight: '$semiBold',
20
+ fontSize: '$sm',
21
+ w: '100%',
22
+ justifyContent: 'center',
23
+ };
24
+
25
+ export const SidePaneTabs = React.memo<{
26
+ active: 'Participants | Chat';
27
+ screenType: keyof ConferencingScreen;
28
+ hideControls?: boolean;
29
+ }>(({ active = SIDE_PANE_OPTIONS.CHAT, screenType, hideControls }) => {
30
+ const toggleChat = useSidepaneToggle(SIDE_PANE_OPTIONS.CHAT);
31
+ const toggleParticipants = useSidepaneToggle(SIDE_PANE_OPTIONS.PARTICIPANTS);
32
+ const resetSidePane = useSidepaneReset();
33
+ const [activeTab, setActiveTab] = useState(active);
34
+ const peerCount = useHMSStore(selectPeerCount);
35
+ const { elements } = useRoomLayoutConferencingScreen();
36
+ const showChat = !!elements?.chat;
37
+ const showParticipants = !!elements?.participant_list;
38
+ const hideTabs = !(showChat && showParticipants);
39
+
40
+ useEffect(() => {
41
+ if (activeTab === SIDE_PANE_OPTIONS.CHAT && !showChat && showParticipants) {
42
+ setActiveTab(SIDE_PANE_OPTIONS.PARTICIPANTS);
43
+ } else if (activeTab === SIDE_PANE_OPTIONS.PARTICIPANTS && showChat && !showParticipants) {
44
+ setActiveTab(SIDE_PANE_OPTIONS.CHAT);
45
+ } else if (!showChat && !showParticipants) {
46
+ resetSidePane();
47
+ }
48
+ }, [showChat, activeTab, showParticipants, resetSidePane]);
49
+
50
+ return (
51
+ <Flex
52
+ direction="column"
53
+ css={{
54
+ color: '$on_primary_high',
55
+ h: '100%',
56
+ }}
57
+ >
58
+ {hideTabs ? (
59
+ <>
60
+ <Text variant="sm" css={{ fontWeight: '$semiBold', p: '$4', c: '$on_surface_high', pr: '$12' }}>
61
+ {showChat ? 'Chat' : `Participants (${peerCount})`}
62
+ </Text>
63
+ {showChat ? <Chat screenType={screenType} hideControls={hideControls} /> : <ParticipantList />}
64
+ </>
65
+ ) : (
66
+ <Tabs.Root
67
+ value={activeTab}
68
+ onValueChange={setActiveTab}
69
+ css={{
70
+ flexDirection: 'column',
71
+ size: '100%',
72
+ }}
73
+ >
74
+ <Tabs.List css={{ w: 'calc(100% - $12)', p: '$2', borderRadius: '$2', bg: '$surface_default' }}>
75
+ <Tabs.Trigger
76
+ value={SIDE_PANE_OPTIONS.CHAT}
77
+ onClick={toggleChat}
78
+ css={{
79
+ ...tabTriggerCSS,
80
+ color: activeTab !== SIDE_PANE_OPTIONS.CHAT ? '$on_surface_low' : '$on_surface_high',
81
+ }}
82
+ >
83
+ Chat
84
+ </Tabs.Trigger>
85
+ <Tabs.Trigger
86
+ value={SIDE_PANE_OPTIONS.PARTICIPANTS}
87
+ onClick={toggleParticipants}
88
+ css={{
89
+ ...tabTriggerCSS,
90
+ color: activeTab !== SIDE_PANE_OPTIONS.PARTICIPANTS ? '$on_surface_low' : '$on_surface_high',
91
+ }}
92
+ >
93
+ Participants ({peerCount})
94
+ </Tabs.Trigger>
95
+ </Tabs.List>
96
+ <Tabs.Content value={SIDE_PANE_OPTIONS.PARTICIPANTS} css={{ p: 0 }}>
97
+ <ParticipantList />
98
+ </Tabs.Content>
99
+ <Tabs.Content value={SIDE_PANE_OPTIONS.CHAT} css={{ p: 0 }}>
100
+ <Chat screenType={screenType} hideControls={hideControls} />
101
+ </Tabs.Content>
102
+ </Tabs.Root>
103
+ )}
104
+ <IconButton
105
+ css={{ position: 'absolute', right: '$10', top: '$11' }}
106
+ onClick={e => {
107
+ e.stopPropagation();
108
+ if (activeTab === SIDE_PANE_OPTIONS.CHAT) {
109
+ toggleChat();
110
+ } else {
111
+ toggleParticipants();
112
+ }
113
+ }}
114
+ data-testid="close_chat"
115
+ >
116
+ <CrossIcon />
117
+ </IconButton>
118
+ </Flex>
119
+ );
120
+ });
@@ -1,4 +1,4 @@
1
- import { useCallback, useState } from 'react';
1
+ import { useCallback } from 'react';
2
2
  import {
3
3
  selectLocalPeerID,
4
4
  selectPeerMetadata,
@@ -12,8 +12,6 @@ export const useMyMetadata = () => {
12
12
  const localPeerId = useHMSStore(selectLocalPeerID);
13
13
  const vanillaStore = useHMSVanillaStore();
14
14
  const metaData = useHMSStore(selectPeerMetadata(localPeerId));
15
- const [isHandRaised, setHandRaised] = useState(metaData?.isHandRaised || false);
16
- const [isBRBOn, setBRBOn] = useState(metaData?.isBRBOn || false); // BRB = be right back
17
15
 
18
16
  const update = async updatedFields => {
19
17
  try {
@@ -27,28 +25,12 @@ export const useMyMetadata = () => {
27
25
  };
28
26
 
29
27
  const toggleHandRaise = useCallback(async () => {
30
- const brbUpdate = !isHandRaised ? false : isBRBOn;
31
- const success = await update({
32
- isHandRaised: !isHandRaised,
33
- isBRBOn: brbUpdate,
34
- });
35
- if (success) {
36
- setBRBOn(brbUpdate);
37
- setHandRaised(!isHandRaised);
38
- }
39
- }, [isHandRaised, isBRBOn]); //eslint-disable-line
28
+ await update({ isHandRaised: !metaData?.isHandRaised, isBRBOn: false });
29
+ }, [metaData?.isHandRaised]); //eslint-disable-line
40
30
 
41
31
  const toggleBRB = useCallback(async () => {
42
- const handRaiseUpdate = !isBRBOn ? false : isHandRaised;
43
- const success = await update({
44
- isHandRaised: handRaiseUpdate,
45
- isBRBOn: !isBRBOn,
46
- });
47
- if (success) {
48
- setBRBOn(!isBRBOn);
49
- setHandRaised(handRaiseUpdate);
50
- }
51
- }, [isHandRaised, isBRBOn]); //eslint-disable-line
32
+ await update({ isBRBOn: !metaData?.isBRBOn, isHandRaised: false });
33
+ }, [metaData?.isBRBOn]); //eslint-disable-line
52
34
 
53
35
  const setPrevRole = async role => {
54
36
  await update({
@@ -57,8 +39,8 @@ export const useMyMetadata = () => {
57
39
  };
58
40
 
59
41
  return {
60
- isHandRaised,
61
- isBRBOn,
42
+ isHandRaised: !!metaData?.isHandRaised,
43
+ isBRBOn: !!metaData?.isBRBOn,
62
44
  metaData,
63
45
  updateMetaData: update,
64
46
  toggleHandRaise,
@@ -2,10 +2,7 @@ import React from 'react';
2
2
  import { useMedia } from 'react-use';
3
3
  import { ConferencingScreen } from '@100mslive/types-prebuilt';
4
4
  import { selectAppData, selectVideoTrackByPeerID, useHMSStore } from '@100mslive/react-sdk';
5
- // @ts-ignore: No implicit Any
6
- import { Chat } from '../components/Chat/Chat';
7
- // @ts-ignore: No implicit Any
8
- import { ParticipantList } from '../components/Footer/ParticipantList';
5
+ import { SidePaneTabs } from '../components/SidePaneTabs';
9
6
  // @ts-ignore: No implicit Any
10
7
  import { StreamingLanding } from '../components/Streaming/StreamingLanding';
11
8
  import { TileCustomisationProps } from '../components/VideoLayouts/GridLayout';
@@ -32,10 +29,8 @@ const SidePane = ({
32
29
  const trackId = useHMSStore(selectVideoTrackByPeerID(activeScreensharePeerId))?.id;
33
30
  const { elements } = useRoomLayoutConferencingScreen();
34
31
  let ViewComponent;
35
- if (sidepane === SIDE_PANE_OPTIONS.PARTICIPANTS) {
36
- ViewComponent = <ParticipantList />;
37
- } else if (sidepane === SIDE_PANE_OPTIONS.CHAT) {
38
- ViewComponent = <Chat screenType={screenType} hideControls={hideControls} />;
32
+ if (sidepane === SIDE_PANE_OPTIONS.PARTICIPANTS || sidepane === SIDE_PANE_OPTIONS.CHAT) {
33
+ ViewComponent = <SidePaneTabs screenType={screenType} hideControls={hideControls} active={sidepane} />;
39
34
  } else if (sidepane === SIDE_PANE_OPTIONS.STREAMING) {
40
35
  ViewComponent = <StreamingLanding />;
41
36
  }
@@ -43,6 +38,14 @@ const SidePane = ({
43
38
  return null;
44
39
  }
45
40
 
41
+ const tileLayout = {
42
+ hideParticipantNameOnTile: tileProps?.hide_participant_name_on_tile,
43
+ roundedVideoTile: tileProps?.rounded_video_tile,
44
+ hideAudioMuteOnTile: tileProps?.hide_audio_mute_on_tile,
45
+ hideMetadataOnTile: tileProps?.hide_metadata_on_tile,
46
+ objectFit: tileProps?.video_object_fit,
47
+ };
48
+
46
49
  const mwebStreamingChat = isMobile && sidepane === SIDE_PANE_OPTIONS.CHAT && elements?.chat?.is_overlay;
47
50
 
48
51
  return (
@@ -64,8 +67,7 @@ const SidePane = ({
64
67
  width="100%"
65
68
  height={225}
66
69
  rootCSS={{ p: 0, alignSelf: 'start', flexShrink: 0 }}
67
- objectFit="contain"
68
- {...tileProps}
70
+ {...tileLayout}
69
71
  />
70
72
  )}
71
73
  {!!ViewComponent && (
@@ -1,7 +1,7 @@
1
1
  import React, { useEffect, useRef, useState } from 'react';
2
2
  import { HMSVirtualBackgroundTypes } from '@100mslive/hms-virtual-background';
3
3
  import {
4
- selectIsAllowedToPublish,
4
+ selectIsLocalVideoEnabled,
5
5
  selectIsLocalVideoPluginPresent,
6
6
  selectLocalPeerRole,
7
7
  selectLocalVideoTrackID,
@@ -23,8 +23,8 @@ export const VirtualBackground = ({
23
23
  }) => {
24
24
  const pluginRef = useRef(null);
25
25
  const hmsActions = useHMSActions();
26
- const isAllowedToPublish = useHMSStore(selectIsAllowedToPublish);
27
26
  const role = useHMSStore(selectLocalPeerRole);
27
+ const isVideoOn = useHMSStore(selectIsLocalVideoEnabled);
28
28
  const [isVBLoading, setIsVBLoading] = useState(false);
29
29
  const [isVBSupported, setIsVBSupported] = useState(false);
30
30
  const [isVBOn, setIsVBOn] = useState(false);
@@ -69,7 +69,7 @@ export const VirtualBackground = ({
69
69
  }
70
70
  }
71
71
 
72
- if (!isAllowedToPublish.video || !isVBSupported) {
72
+ if (!isVBSupported || !isVideoOn) {
73
73
  return null;
74
74
  }
75
75
  if (asActionTile) {
@@ -29,7 +29,7 @@ export type useFetchRoomLayoutResponse = {
29
29
  };
30
30
 
31
31
  export const useFetchRoomLayout = ({
32
- endpoint = 'https://api.100ms.live/v2/layouts/ui',
32
+ endpoint = '',
33
33
  authToken = '',
34
34
  }: useFetchRoomLayoutProps): useFetchRoomLayoutResponse => {
35
35
  const [layout, setLayout] = useState<Layout | undefined>(undefined);
@@ -51,7 +51,7 @@ export const useFetchRoomLayout = ({
51
51
  }
52
52
  isFetchInProgress.current = true;
53
53
  try {
54
- const resp = await fetchWithRetry(endpoint, {
54
+ const resp = await fetchWithRetry(endpoint || 'https://api.100ms.live/v2/layouts/ui', {
55
55
  headers: {
56
56
  Authorization: `Bearer ${authToken}`,
57
57
  },
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../src/Prebuilt/plugins/VirtualBackground/VirtualBackground.jsx", "../src/Prebuilt/plugins/VirtualBackground/vbutils.js"],
4
- "sourcesContent": ["import React, { useEffect, useRef, useState } from 'react';\nimport { HMSVirtualBackgroundTypes } from '@100mslive/hms-virtual-background';\nimport {\n selectIsAllowedToPublish,\n selectIsLocalVideoPluginPresent,\n selectLocalPeerRole,\n selectLocalVideoTrackID,\n useHMSActions,\n useHMSStore,\n} from '@100mslive/react-sdk';\nimport { VirtualBackgroundIcon } from '@100mslive/react-icons';\nimport { ActionTile } from '../../components/MoreSettings/ActionTile';\nimport { Loading } from '../../../Loading';\nimport { Tooltip } from '../../../Tooltip';\nimport IconButton from '../../IconButton';\nimport { getRandomVirtualBackground } from './vbutils';\n\nexport const VirtualBackground = ({\n asActionTile = false,\n onVBClick = () => {\n return;\n },\n}) => {\n const pluginRef = useRef(null);\n const hmsActions = useHMSActions();\n const isAllowedToPublish = useHMSStore(selectIsAllowedToPublish);\n const role = useHMSStore(selectLocalPeerRole);\n const [isVBLoading, setIsVBLoading] = useState(false);\n const [isVBSupported, setIsVBSupported] = useState(false);\n const [isVBOn, setIsVBOn] = useState(false);\n const localPeerVideoTrackID = useHMSStore(selectLocalVideoTrackID);\n const isVBPresent = useHMSStore(selectIsLocalVideoPluginPresent('HMSVB'));\n\n async function createPlugin() {\n if (!pluginRef.current) {\n const { HMSVBPlugin } = await import('@100mslive/hms-virtual-background');\n pluginRef.current = new HMSVBPlugin(HMSVirtualBackgroundTypes.NONE, HMSVirtualBackgroundTypes.NONE);\n }\n }\n useEffect(() => {\n if (!localPeerVideoTrackID) {\n return;\n }\n createPlugin().then(() => {\n //check support of plugin\n const pluginSupport = hmsActions.validateVideoPluginSupport(pluginRef.current);\n setIsVBSupported(pluginSupport.isSupported);\n });\n }, [hmsActions, localPeerVideoTrackID]);\n\n async function addPlugin() {\n setIsVBLoading(true);\n try {\n await createPlugin();\n window.HMS.virtualBackground = pluginRef.current;\n const { background, backgroundType } = getRandomVirtualBackground();\n await pluginRef.current.setBackground(background, backgroundType);\n await hmsActions.addPluginToVideoTrack(pluginRef.current, Math.floor(role.publishParams.video.frameRate / 2));\n } catch (err) {\n console.error('add virtual background plugin failed', err);\n }\n setIsVBLoading(false);\n }\n\n async function removePlugin() {\n if (pluginRef.current) {\n await hmsActions.removePluginFromVideoTrack(pluginRef.current);\n pluginRef.current = null;\n }\n }\n\n if (!isAllowedToPublish.video || !isVBSupported) {\n return null;\n }\n if (asActionTile) {\n return (\n <ActionTile.Root\n data-testid=\"virtual_bg_btn\"\n active={isVBPresent}\n disabled={isVBLoading}\n onClick={() => {\n setIsVBOn(!isVBOn);\n !isVBPresent ? addPlugin() : removePlugin();\n onVBClick();\n }}\n >\n <VirtualBackgroundIcon />\n <ActionTile.Title>Virtual Background</ActionTile.Title>\n </ActionTile.Root>\n );\n }\n\n return (\n <Tooltip\n boxCss={{ zIndex: '100' }}\n title={isVBLoading ? 'Adding virtual background' : `Turn ${!isVBPresent ? 'on' : 'off'} virtual background`}\n >\n <IconButton\n active={!isVBPresent}\n disabled={isVBLoading}\n onClick={() => {\n !isVBPresent ? addPlugin() : removePlugin();\n }}\n data-testid=\"virtual_bg_btn\"\n >\n {isVBLoading ? <Loading /> : <VirtualBackgroundIcon />}\n </IconButton>\n </Tooltip>\n );\n};\n\nexport default VirtualBackground;\n", "/* eslint-disable no-case-declarations */\nimport { HMSVirtualBackgroundTypes } from '@100mslive/hms-virtual-background';\nexport function getRandomVirtualBackground() {\n const backgroundList = [\n {\n background: HMSVirtualBackgroundTypes.BLUR,\n backgroundType: HMSVirtualBackgroundTypes.BLUR,\n },\n ];\n\n const images = [\n 'https://www.100ms.live/images/vb-1.jpeg',\n 'https://www.100ms.live/images/vb-2.jpg',\n 'https://www.100ms.live/images/vb-3.png',\n 'https://d2qi07yyjujoxr.cloudfront.net/webapp/vb/hms1.png',\n 'https://d2qi07yyjujoxr.cloudfront.net/webapp/vb/hms2.png',\n 'https://d2qi07yyjujoxr.cloudfront.net/webapp/vb/hms3.png',\n 'https://d2qi07yyjujoxr.cloudfront.net/webapp/vb/hms4.png',\n ].map(url => ({\n background: url,\n backgroundType: HMSVirtualBackgroundTypes.IMAGE,\n }));\n\n backgroundList.push(...images);\n\n /* \n //TODO: update with a better quality gif.\n const gifList = [\n {\n background: \"https://www.100ms.live/images/vb-1.gif\",\n backgroundType: HMSVirtualBackgroundTypes.GIF,\n },\n ];\n backgroundList.push(...gifList); \n */\n\n const videoList = [\n 'https://www.100ms.live/images/video-1.mp4',\n 'https://www.100ms.live/images/video-2.mp4',\n 'https://www.100ms.live/images/video-5.mp4',\n 'https://www.100ms.live/images/video-7.mp4',\n 'https://www.100ms.live/images/video-8.mp4',\n ].map(url => ({\n background: url,\n backgroundType: HMSVirtualBackgroundTypes.VIDEO,\n }));\n backgroundList.push(...videoList);\n\n const randomIdx = Math.floor(Math.random() * backgroundList.length);\n const virtualBackground = backgroundList[randomIdx];\n switch (virtualBackground.backgroundType) {\n case HMSVirtualBackgroundTypes.IMAGE:\n const img = document.createElement('img');\n img.alt = 'VB';\n img.src = backgroundList[randomIdx].background;\n virtualBackground.background = img;\n return virtualBackground;\n case HMSVirtualBackgroundTypes.VIDEO:\n const videoEl = document.createElement('video');\n videoEl.src = backgroundList[randomIdx].background;\n virtualBackground.background = videoEl;\n return virtualBackground;\n default:\n return virtualBackground;\n }\n}\n"],
5
- "mappings": "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",
6
- "names": ["HMSVirtualBackgroundTypes", "HMSVirtualBackgroundTypes"]
7
- }