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

Sign up to get free protection for your applications and to get access to all the features.
Files changed (136) hide show
  1. package/dist/{HLSView-PY2FKWX3.js → HLSView-QMU5JK7U.js} +208 -118
  2. package/dist/HLSView-QMU5JK7U.js.map +7 -0
  3. package/dist/Prebuilt/AppContext.d.ts +1 -1
  4. package/dist/Prebuilt/components/Chat/ChatFooter.d.ts +7 -0
  5. package/dist/Prebuilt/components/Connection/ConnectionIndicator.d.ts +6 -0
  6. package/dist/Prebuilt/components/Connection/TileConnection.d.ts +10 -0
  7. package/dist/Prebuilt/components/Footer/ChatToggle.d.ts +2 -0
  8. package/dist/Prebuilt/components/Footer/RoleAccordion.d.ts +14 -0
  9. package/dist/Prebuilt/components/Footer/RoleOptions.d.ts +6 -0
  10. package/dist/Prebuilt/components/Header/StreamActions.d.ts +11 -0
  11. package/dist/Prebuilt/components/Leave/DesktopLeaveRoom.d.ts +4 -3
  12. package/dist/Prebuilt/components/Leave/EndSessionContent.d.ts +4 -3
  13. package/dist/Prebuilt/components/Leave/LeaveCard.d.ts +1 -2
  14. package/dist/Prebuilt/components/Leave/LeaveSessionContent.d.ts +3 -1
  15. package/dist/Prebuilt/components/Leave/MwebLeaveRoom.d.ts +4 -3
  16. package/dist/Prebuilt/components/MoreSettings/SplitComponents/MwebOptions.d.ts +6 -0
  17. package/dist/Prebuilt/components/Preview/PreviewContainer.d.ts +3 -0
  18. package/dist/Prebuilt/components/Preview/PreviewJoin.d.ts +16 -0
  19. package/dist/Prebuilt/components/RoleChangeRequestModal.d.ts +2 -0
  20. package/dist/Prebuilt/components/SecondaryTiles.d.ts +1 -1
  21. package/dist/Prebuilt/components/SidePaneTabs.d.ts +7 -0
  22. package/dist/Prebuilt/components/VideoLayouts/EqualProminence.d.ts +1 -1
  23. package/dist/Prebuilt/components/VideoLayouts/Grid.d.ts +1 -0
  24. package/dist/Prebuilt/components/VideoLayouts/GridLayout.d.ts +5 -3
  25. package/dist/Prebuilt/components/VideoLayouts/ProminenceLayout.d.ts +6 -3
  26. package/dist/Prebuilt/components/VideoLayouts/RoleProminence.d.ts +1 -1
  27. package/dist/Prebuilt/components/VideoLayouts/ScreenshareLayout.d.ts +1 -1
  28. package/dist/Prebuilt/components/VideoLayouts/interface.d.ts +1 -0
  29. package/dist/Prebuilt/components/hooks/useAutoStartStreaming.d.ts +1 -0
  30. package/dist/Prebuilt/components/hooks/useRedirectToLeave.d.ts +3 -0
  31. package/dist/Prebuilt/components/hooks/useTileLayout.d.ts +2 -1
  32. package/dist/Prebuilt/components/hooks/useVideoTileLayout.d.ts +2 -0
  33. package/dist/Prebuilt/layouts/SidePane.d.ts +4 -1
  34. package/dist/Prebuilt/layouts/VideoStreamingSection.d.ts +2 -1
  35. package/dist/{VirtualBackground-AYDHYLIZ.js → VirtualBackground-37FXUPYO.js} +6 -6
  36. package/dist/VirtualBackground-37FXUPYO.js.map +7 -0
  37. package/dist/{chunk-GQD2AGWW.js → chunk-KBVIZGYW.js} +12 -2
  38. package/dist/{chunk-GQD2AGWW.js.map → chunk-KBVIZGYW.js.map} +2 -2
  39. package/dist/{chunk-RXTHJUMZ.js → chunk-WVGGQZK4.js} +986 -436
  40. package/dist/chunk-WVGGQZK4.js.map +7 -0
  41. package/dist/{chunk-E2M2ZSOL.js → chunk-ZKE2N5LH.js} +2 -2
  42. package/dist/{conference-V2XZGTKU.js → conference-FJJQ4TXX.js} +1136 -1301
  43. package/dist/conference-FJJQ4TXX.js.map +7 -0
  44. package/dist/index.cjs.js +3565 -3092
  45. package/dist/index.cjs.js.map +4 -4
  46. package/dist/index.js +2 -2
  47. package/dist/meta.cjs.json +773 -525
  48. package/dist/meta.esbuild.json +833 -579
  49. package/package.json +8 -7
  50. package/src/Prebuilt/App.tsx +10 -21
  51. package/src/Prebuilt/AppContext.tsx +1 -1
  52. package/src/Prebuilt/IconButton.jsx +10 -0
  53. package/src/Prebuilt/common/PeersSorter.ts +1 -1
  54. package/src/Prebuilt/common/constants.js +1 -2
  55. package/src/Prebuilt/common/utils.js +1 -1
  56. package/src/Prebuilt/components/AppData/AppData.jsx +8 -2
  57. package/src/Prebuilt/components/AppData/useUISettings.js +6 -6
  58. package/src/Prebuilt/components/AudioVideoToggle.jsx +8 -6
  59. package/src/Prebuilt/components/Chat/Chat.jsx +24 -11
  60. package/src/Prebuilt/components/Chat/ChatBody.jsx +20 -21
  61. package/src/Prebuilt/components/Chat/{ChatFooter.jsx → ChatFooter.tsx} +38 -13
  62. package/src/Prebuilt/components/Chat/useEmojiPickerStyles.js +5 -4
  63. package/src/Prebuilt/components/Connection/{ConnectionIndicator.jsx → ConnectionIndicator.tsx} +12 -4
  64. package/src/Prebuilt/components/Connection/{TileConnection.jsx → TileConnection.tsx} +20 -6
  65. package/src/Prebuilt/components/EmojiReaction.jsx +2 -6
  66. package/src/Prebuilt/components/Footer/{ChatToggle.jsx → ChatToggle.tsx} +4 -1
  67. package/src/Prebuilt/components/Footer/Footer.tsx +30 -5
  68. package/src/Prebuilt/components/Footer/ParticipantList.jsx +15 -49
  69. package/src/Prebuilt/components/Footer/{RoleAccordion.jsx → RoleAccordion.tsx} +33 -17
  70. package/src/Prebuilt/components/Footer/RoleOptions.tsx +155 -0
  71. package/src/Prebuilt/components/FullPageProgress.jsx +3 -3
  72. package/src/Prebuilt/components/HMSVideo/Controls.jsx +1 -0
  73. package/src/Prebuilt/components/HMSVideo/HLSQualitySelector.jsx +39 -17
  74. package/src/Prebuilt/components/HMSVideo/HMSVideo.jsx +2 -2
  75. package/src/Prebuilt/components/HMSVideo/VideoProgress.jsx +5 -6
  76. package/src/Prebuilt/components/HMSVideo/VolumeControl.jsx +1 -1
  77. package/src/Prebuilt/components/Header/HeaderComponents.jsx +8 -1
  78. package/src/Prebuilt/components/Header/{StreamActions.jsx → StreamActions.tsx} +23 -9
  79. package/src/Prebuilt/components/Header/common.jsx +5 -2
  80. package/src/Prebuilt/components/IconButtonWithOptions/IconButtonWithOptions.jsx +6 -1
  81. package/src/Prebuilt/components/InsetTile.tsx +15 -8
  82. package/src/Prebuilt/components/Leave/DesktopLeaveRoom.tsx +21 -11
  83. package/src/Prebuilt/components/Leave/EndSessionContent.tsx +2 -5
  84. package/src/Prebuilt/components/Leave/LeaveCard.tsx +1 -3
  85. package/src/Prebuilt/components/Leave/LeaveRoom.tsx +28 -25
  86. package/src/Prebuilt/components/Leave/LeaveSessionContent.tsx +8 -2
  87. package/src/Prebuilt/components/Leave/MwebLeaveRoom.tsx +8 -8
  88. package/src/Prebuilt/components/MoreSettings/ChangeNameContent.jsx +4 -0
  89. package/src/Prebuilt/components/MoreSettings/MoreSettings.tsx +1 -1
  90. package/src/Prebuilt/components/MoreSettings/SplitComponents/DesktopOptions.tsx +9 -23
  91. package/src/Prebuilt/components/MoreSettings/SplitComponents/{MwebOptions.jsx → MwebOptions.tsx} +89 -28
  92. package/src/Prebuilt/components/Notifications/Notifications.jsx +44 -28
  93. package/src/Prebuilt/components/Notifications/ReconnectNotifications.jsx +5 -11
  94. package/src/Prebuilt/components/Pagination.tsx +14 -12
  95. package/src/Prebuilt/components/Preview/{PreviewContainer.jsx → PreviewContainer.tsx} +11 -2
  96. package/src/Prebuilt/components/Preview/PreviewForm.tsx +6 -8
  97. package/src/Prebuilt/components/Preview/{PreviewJoin.jsx → PreviewJoin.tsx} +44 -21
  98. package/src/Prebuilt/components/{RoleChangeRequestModal.jsx → RoleChangeRequestModal.tsx} +36 -17
  99. package/src/Prebuilt/components/ScreenshareTile.jsx +6 -7
  100. package/src/Prebuilt/components/SecondaryTiles.tsx +12 -10
  101. package/src/Prebuilt/components/SidePaneTabs.tsx +120 -0
  102. package/src/Prebuilt/components/TileMenu/TileMenu.jsx +1 -1
  103. package/src/Prebuilt/components/TileMenu/TileMenuContent.jsx +14 -10
  104. package/src/Prebuilt/components/Toast/ToastConfig.jsx +5 -4
  105. package/src/Prebuilt/components/VideoLayouts/EqualProminence.tsx +13 -10
  106. package/src/Prebuilt/components/VideoLayouts/Grid.tsx +36 -34
  107. package/src/Prebuilt/components/VideoLayouts/GridLayout.tsx +33 -15
  108. package/src/Prebuilt/components/VideoLayouts/ProminenceLayout.tsx +45 -31
  109. package/src/Prebuilt/components/VideoLayouts/RoleProminence.tsx +12 -9
  110. package/src/Prebuilt/components/VideoLayouts/ScreenshareLayout.tsx +25 -9
  111. package/src/Prebuilt/components/VideoLayouts/interface.ts +1 -0
  112. package/src/Prebuilt/components/VideoTile.jsx +45 -53
  113. package/src/Prebuilt/components/conference.jsx +71 -74
  114. package/src/Prebuilt/components/hooks/useAutoStartStreaming.tsx +57 -0
  115. package/src/Prebuilt/components/hooks/useMetadata.jsx +19 -28
  116. package/src/Prebuilt/components/hooks/useRedirectToLeave.tsx +34 -0
  117. package/src/Prebuilt/components/hooks/useRoleProminencePeers.tsx +1 -1
  118. package/src/Prebuilt/components/hooks/useTileLayout.tsx +24 -18
  119. package/src/Prebuilt/components/hooks/useVideoTileLayout.ts +4 -0
  120. package/src/Prebuilt/layouts/EmbedView.jsx +1 -11
  121. package/src/Prebuilt/layouts/HLSView.jsx +152 -82
  122. package/src/Prebuilt/layouts/SidePane.tsx +25 -11
  123. package/src/Prebuilt/layouts/VideoStreamingSection.tsx +11 -47
  124. package/src/Prebuilt/plugins/FlyingEmoji.jsx +14 -2
  125. package/src/Prebuilt/plugins/VirtualBackground/VirtualBackground.jsx +3 -3
  126. package/src/Prebuilt/provider/roomLayoutProvider/hooks/useFetchRoomLayout.ts +2 -2
  127. package/src/Prebuilt/services/FeatureFlags.jsx +0 -1
  128. package/src/VideoTile/StyledVideoTile.tsx +1 -0
  129. package/dist/HLSView-PY2FKWX3.js.map +0 -7
  130. package/dist/VirtualBackground-AYDHYLIZ.js.map +0 -7
  131. package/dist/chunk-RXTHJUMZ.js.map +0 -7
  132. package/dist/conference-V2XZGTKU.js.map +0 -7
  133. package/src/Prebuilt/components/AudioLevel/BeamSpeakerLabelsLogging.jsx +0 -16
  134. package/src/Prebuilt/components/Chat/ChatParticipantHeader.jsx +0 -73
  135. package/src/Prebuilt/components/VideoList.jsx +0 -73
  136. /package/dist/{chunk-E2M2ZSOL.js.map → chunk-ZKE2N5LH.js.map} +0 -0
@@ -1,12 +1,15 @@
1
1
  /* eslint-disable no-case-declarations */
2
- import React, { useEffect } from 'react';
3
- import { useNavigate } from 'react-router-dom';
2
+ import React, { useCallback, useEffect } from 'react';
3
+ import { useNavigate, useParams } from 'react-router-dom';
4
4
  import {
5
5
  HMSNotificationTypes,
6
6
  HMSRoomState,
7
+ selectPeerMetadata,
7
8
  selectRoomState,
9
+ useCustomEvent,
8
10
  useHMSNotifications,
9
11
  useHMSStore,
12
+ useHMSVanillaStore,
10
13
  } from '@100mslive/react-sdk';
11
14
  import { Button } from '../../../';
12
15
  import { useUpdateRoomLayout } from '../../provider/roomLayoutProvider';
@@ -20,19 +23,32 @@ import { ReconnectNotifications } from './ReconnectNotifications';
20
23
  import { TrackBulkUnmuteModal } from './TrackBulkUnmuteModal';
21
24
  import { TrackNotifications } from './TrackNotifications';
22
25
  import { TrackUnmuteModal } from './TrackUnmuteModal';
23
- import { useIsHeadless, useSubscribedNotifications } from '../AppData/useUISettings';
26
+ import { useIsNotificationDisabled, useSubscribedNotifications } from '../AppData/useUISettings';
27
+ import { useRedirectToLeave } from '../hooks/useRedirectToLeave';
24
28
  import { getMetadata } from '../../common/utils';
25
-
29
+ import { ROLE_CHANGE_DECLINED } from '../../common/constants';
26
30
  export function Notifications() {
27
31
  const notification = useHMSNotifications();
28
32
  const navigate = useNavigate();
33
+ const params = useParams();
34
+ const vanillaStore = useHMSVanillaStore();
29
35
  const subscribedNotifications = useSubscribedNotifications() || {};
30
- const isHeadless = useIsHeadless();
31
36
  const roomState = useHMSStore(selectRoomState);
32
37
  const updateRoomLayoutForRole = useUpdateRoomLayout();
38
+ const isNotificationDisabled = useIsNotificationDisabled();
39
+ const { redirectToLeave } = useRedirectToLeave();
40
+
41
+ const handleRoleChangeDenied = useCallback(request => {
42
+ ToastManager.addToast({
43
+ title: `${request.peerName} denied your request to join the ${request.role.name} role`,
44
+ variant: 'error',
45
+ });
46
+ }, []);
47
+
48
+ useCustomEvent({ type: ROLE_CHANGE_DECLINED, onEvent: handleRoleChangeDenied });
33
49
 
34
50
  useEffect(() => {
35
- if (!notification) {
51
+ if (!notification || isNotificationDisabled) {
36
52
  return;
37
53
  }
38
54
  switch (notification.type) {
@@ -40,14 +56,14 @@ export function Notifications() {
40
56
  if (roomState !== HMSRoomState.Connected) {
41
57
  return;
42
58
  }
43
- // Don't toast message when metadata is updated and raiseHand is false.
44
- // 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.
45
61
  const metadata = getMetadata(notification.data?.metadata);
46
- if (!metadata?.isHandRaised || notification.data.isLocal || isHeadless) return;
62
+ if (!metadata?.isHandRaised || notification.data.isLocal) return;
47
63
 
48
64
  console.debug('Metadata updated', notification.data);
49
65
  if (!subscribedNotifications.METADATA_UPDATED) return;
50
- ToastBatcher.showToast({ notification });
66
+ ToastBatcher.showToast({ notification, type: 'RAISE_HAND' });
51
67
  break;
52
68
  case HMSNotificationTypes.NAME_UPDATED:
53
69
  console.log(notification.data.id + ' changed their name to ' + notification.data.name);
@@ -69,7 +85,7 @@ export function Notifications() {
69
85
  <Button
70
86
  onClick={() => {
71
87
  ToastManager.removeToast(toastId);
72
- window.location.reload();
88
+ navigate(`/${params.roomId}${params.role ? `/${params.role}` : ''}`);
73
89
  }}
74
90
  >
75
91
  Rejoin
@@ -80,11 +96,7 @@ export function Notifications() {
80
96
  }
81
97
  // goto leave for terminal if any action is not performed within 2secs
82
98
  // if network is still unavailable going to preview will throw an error
83
- setTimeout(() => {
84
- const previewLocation = window.location.pathname.replace('meeting', 'leave');
85
- ToastManager.clearAllToast();
86
- navigate(previewLocation);
87
- }, 2000);
99
+ redirectToLeave(1000);
88
100
  return;
89
101
  }
90
102
  // Autoplay error or user denied screen share (cancelled browser pop-up)
@@ -99,14 +111,18 @@ export function Notifications() {
99
111
  title: `Error: ${notification.data?.message} - ${notification.data?.description}`,
100
112
  });
101
113
  break;
102
- case HMSNotificationTypes.ROLE_UPDATED:
114
+ case HMSNotificationTypes.ROLE_UPDATED: {
103
115
  if (notification.data?.isLocal) {
104
- ToastManager.addToast({
105
- title: `You are now a ${notification.data.roleName}`,
106
- });
107
- 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
+ }
108
123
  }
109
124
  break;
125
+ }
110
126
  case HMSNotificationTypes.CHANGE_TRACK_STATE_REQUEST:
111
127
  const track = notification.data?.track;
112
128
  if (!notification.data.enabled) {
@@ -122,11 +138,7 @@ export function Notifications() {
122
138
  title: `${notification.message}.
123
139
  ${notification.data.reason && `Reason: ${notification.data.reason}`}`,
124
140
  });
125
- setTimeout(() => {
126
- const leaveLocation = window.location.pathname.replace('meeting', 'leave');
127
- navigate(leaveLocation);
128
- ToastManager.clearAllToast();
129
- }, 2000);
141
+ redirectToLeave(1000);
130
142
  break;
131
143
  case HMSNotificationTypes.DEVICE_CHANGE_UPDATE:
132
144
  ToastManager.addToast({
@@ -139,10 +151,14 @@ export function Notifications() {
139
151
  // eslint-disable-next-line react-hooks/exhaustive-deps
140
152
  }, [notification, subscribedNotifications.ERROR, subscribedNotifications.METADATA_UPDATED]);
141
153
 
154
+ if (isNotificationDisabled) {
155
+ return null;
156
+ }
157
+
142
158
  return (
143
159
  <>
144
- {!isHeadless && <TrackUnmuteModal />}
145
- {!isHeadless && <TrackBulkUnmuteModal />}
160
+ <TrackUnmuteModal />
161
+ <TrackBulkUnmuteModal />
146
162
  <TrackNotifications />
147
163
  <PeerNotifications />
148
164
  <ReconnectNotifications />
@@ -11,7 +11,6 @@ const notificationTypes = [
11
11
  ];
12
12
  let notificationId = null;
13
13
 
14
- const isQA = process.env.REACT_APP_ENV === 'qa';
15
14
  export const ReconnectNotifications = () => {
16
15
  const notification = useHMSNotifications(notificationTypes);
17
16
  const [open, setOpen] = useState(false);
@@ -22,18 +21,13 @@ export const ReconnectNotifications = () => {
22
21
  notificationId = ToastManager.replaceToast(notificationId, ToastConfig.RECONNECTED.single());
23
22
  setOpen(false);
24
23
  } else if (notification?.type === HMSNotificationTypes.RECONNECTING) {
25
- if (isQA) {
26
- ToastManager.removeToast(notificationId);
27
- setOpen(true);
28
- } else {
29
- notificationId = ToastManager.replaceToast(
30
- notificationId,
31
- ToastConfig.RECONNECTING.single(notification.data.message),
32
- );
33
- }
24
+ notificationId = ToastManager.replaceToast(
25
+ notificationId,
26
+ ToastConfig.RECONNECTING.single(notification.data.message),
27
+ );
34
28
  }
35
29
  }, [notification]);
36
- if (!open || !isQA) return null;
30
+ if (!open) return null;
37
31
  return (
38
32
  <Dialog.Root open={open} modal={true}>
39
33
  <Dialog.Portal container={document.getElementById('conferencing')}>
@@ -38,18 +38,20 @@ export const Pagination = ({
38
38
  <StyledPagination.Chevron disabled={disableLeft} onClick={prevPage}>
39
39
  <ChevronLeftIcon width={16} height={16} style={{ cursor: disableLeft ? 'not-allowed' : 'pointer' }} />
40
40
  </StyledPagination.Chevron>
41
- <StyledPagination.Dots>
42
- {[...Array(numPages)].map((_, i) => (
43
- <StyledPagination.Dot
44
- key={i}
45
- active={page === i}
46
- onClick={e => {
47
- e.stopPropagation();
48
- onPageChange(i);
49
- }}
50
- />
51
- ))}
52
- </StyledPagination.Dots>
41
+ {numPages <= 5 ? (
42
+ <StyledPagination.Dots>
43
+ {[...Array(numPages)].map((_, i) => (
44
+ <StyledPagination.Dot
45
+ key={i}
46
+ active={page === i}
47
+ onClick={e => {
48
+ e.stopPropagation();
49
+ onPageChange(i);
50
+ }}
51
+ />
52
+ ))}
53
+ </StyledPagination.Dots>
54
+ ) : null}
53
55
  <StyledPagination.Chevron disabled={disableRight} onClick={nextPage}>
54
56
  <ChevronRightIcon width={16} height={16} style={{ cursor: disableRight ? 'not-allowed' : 'pointer' }} />
55
57
  </StyledPagination.Chevron>
@@ -1,13 +1,17 @@
1
1
  import React from 'react';
2
2
  import { useNavigate, useParams } from 'react-router-dom';
3
3
  import { useSearchParam } from 'react-use';
4
- import { Flex } from '../../../';
4
+ import { Flex } from '../../..';
5
5
  import { useHMSPrebuiltContext } from '../../AppContext';
6
6
  import { useRoomLayout } from '../../provider/roomLayoutProvider';
7
+ // @ts-ignore: No implicit Any
7
8
  import FullPageProgress from '../FullPageProgress';
9
+ // @ts-ignore: No implicit Any
8
10
  import PreviewJoin from './PreviewJoin';
9
11
  import { useRoomLayoutPreviewScreen } from '../../provider/roomLayoutProvider/hooks/useRoomLayoutScreen';
12
+ // @ts-ignore: No implicit Any
10
13
  import { useAuthToken } from '../AppData/useUISettings';
14
+ // @ts-ignore: No implicit Any
11
15
  import { QUERY_PARAM_PREVIEW_AS_ROLE } from '../../common/constants';
12
16
 
13
17
  const PreviewContainer = () => {
@@ -37,7 +41,12 @@ const PreviewContainer = () => {
37
41
  align="center"
38
42
  >
39
43
  {authToken && Object.keys(previewHeader).length > 0 ? (
40
- <PreviewJoin initialName={initialName} skipPreview={skipPreview} asRole={previewAsRole} onJoin={onJoin} />
44
+ <PreviewJoin
45
+ initialName={initialName}
46
+ skipPreview={skipPreview}
47
+ asRole={previewAsRole ?? undefined}
48
+ onJoin={onJoin}
49
+ />
41
50
  ) : (
42
51
  <FullPageProgress />
43
52
  )}
@@ -1,7 +1,7 @@
1
1
  import React from 'react';
2
2
  import { useMedia } from 'react-use';
3
3
  import { JoinForm_JoinBtnType } from '@100mslive/types-prebuilt/elements/join_form';
4
- import { selectPermissions, useHMSStore, useRecordingStreaming } from '@100mslive/react-sdk';
4
+ import { useRecordingStreaming } from '@100mslive/react-sdk';
5
5
  import { RadioIcon } from '@100mslive/react-icons';
6
6
  import { Button, config as cssConfig, Flex, Input, styled } from '../../..';
7
7
  import { useRoomLayout } from '../../provider/roomLayoutProvider';
@@ -26,16 +26,11 @@ const PreviewForm = ({
26
26
  const formSubmit = (e: React.SyntheticEvent) => {
27
27
  e.preventDefault();
28
28
  };
29
- const mediaQueryLg = cssConfig.media.md;
30
- const isMobile = useMedia(mediaQueryLg);
29
+ const isMobile = useMedia(cssConfig.media.md);
31
30
  const { isHLSRunning } = useRecordingStreaming();
32
- const permissions = useHMSStore(selectPermissions);
33
31
  const layout = useRoomLayout();
34
32
  const { join_form: joinForm = {} } = layout?.screens?.preview?.default?.elements || {};
35
- const showGoLive =
36
- joinForm?.join_btn_type === JoinForm_JoinBtnType.JOIN_BTN_TYPE_JOIN_AND_GO_LIVE &&
37
- !isHLSRunning &&
38
- permissions?.hlsStreaming;
33
+ const showGoLive = joinForm?.join_btn_type === JoinForm_JoinBtnType.JOIN_BTN_TYPE_JOIN_AND_GO_LIVE && !isHLSRunning;
39
34
 
40
35
  return (
41
36
  <Form
@@ -55,6 +50,9 @@ const PreviewForm = ({
55
50
  onKeyDown={e => {
56
51
  if (e.key === 'Enter' && name.trim().length > 0) {
57
52
  e.preventDefault();
53
+ if (isMobile) {
54
+ return;
55
+ }
58
56
  onJoin();
59
57
  }
60
58
  }}
@@ -1,4 +1,5 @@
1
1
  import React, { Fragment, Suspense, useCallback, useEffect, useState } from 'react';
2
+ import { useMedia } from 'react-use';
2
3
  import {
3
4
  HMSRoomState,
4
5
  selectIsLocalVideoEnabled,
@@ -12,23 +13,37 @@ import {
12
13
  useRecordingStreaming,
13
14
  } from '@100mslive/react-sdk';
14
15
  import { MicOffIcon, SettingsIcon } from '@100mslive/react-icons';
15
- import { Avatar, Box, Flex, flexCenter, styled, StyledVideoTile, Text, Video } from '../../../';
16
+ import { Avatar, Box, config as cssConfig, Flex, flexCenter, styled, StyledVideoTile, Text, Video } from '../../..';
16
17
  import { useHMSPrebuiltContext } from '../../AppContext';
18
+ // @ts-ignore: No implicit Any
17
19
  import IconButton from '../../IconButton';
18
20
  import { useRoomLayout } from '../../provider/roomLayoutProvider';
21
+ // @ts-ignore: No implicit Any
19
22
  import { AudioVideoToggle } from '../AudioVideoToggle';
23
+ // @ts-ignore: No implicit Any
20
24
  import Chip from '../Chip';
25
+ // @ts-ignore: No implicit Any
21
26
  import TileConnection from '../Connection/TileConnection';
27
+ // @ts-ignore: No implicit Any
22
28
  import FullPageProgress from '../FullPageProgress';
29
+ // @ts-ignore: No implicit Any
23
30
  import { Logo } from '../Header/HeaderComponents';
31
+ // @ts-ignore: No implicit Any
24
32
  import SettingsModal from '../Settings/SettingsModal';
33
+ // @ts-ignore: No implicit Any
25
34
  import { AudioLevel } from '../VideoTile';
35
+ // @ts-ignore: No implicit Any
26
36
  import PreviewForm from './PreviewForm';
37
+ // @ts-ignore: No implicit Any
27
38
  import { useAuthToken, useUISettings } from '../AppData/useUISettings';
39
+ // @ts-ignore: No implicit Any
28
40
  import { defaultPreviewPreference, UserPreferencesKeys, useUserPreferences } from '../hooks/useUserPreferences';
41
+ // @ts-ignore: No implicit Any
29
42
  import { getFormattedCount } from '../../common/utils';
43
+ // @ts-ignore: No implicit Any
30
44
  import { UI_SETTINGS } from '../../common/constants';
31
45
 
46
+ // @ts-ignore: No implicit Any
32
47
  const VirtualBackground = React.lazy(() => import('../../plugins/VirtualBackground/VirtualBackground'));
33
48
 
34
49
  const getParticipantChipContent = (peerCount = 0) => {
@@ -39,7 +54,17 @@ const getParticipantChipContent = (peerCount = 0) => {
39
54
  return `${formattedNum} other${parseInt(formattedNum) === 1 ? '' : 's'} in the session`;
40
55
  };
41
56
 
42
- const PreviewJoin = ({ onJoin, skipPreview, initialName, asRole }) => {
57
+ const PreviewJoin = ({
58
+ onJoin,
59
+ skipPreview,
60
+ initialName,
61
+ asRole,
62
+ }: {
63
+ onJoin: () => void;
64
+ skipPreview?: boolean;
65
+ initialName?: string;
66
+ asRole?: string;
67
+ }) => {
43
68
  const [previewPreference, setPreviewPreference] = useUserPreferences(
44
69
  UserPreferencesKeys.PREVIEW,
45
70
  defaultPreviewPreference,
@@ -47,7 +72,7 @@ const PreviewJoin = ({ onJoin, skipPreview, initialName, asRole }) => {
47
72
  const { isStreamingOn } = useRecordingStreaming();
48
73
  const authToken = useAuthToken();
49
74
  const [name, setName] = useState(initialName || previewPreference.name);
50
- const { isLocalAudioEnabled, isLocalVideoEnabled, toggleAudio, toggleVideo } = useAVToggle();
75
+ const { toggleAudio, toggleVideo } = useAVToggle();
51
76
  const [previewError, setPreviewError] = useState(false);
52
77
  const { endpoints } = useHMSPrebuiltContext();
53
78
  const { peerCount } = useParticipants();
@@ -73,12 +98,10 @@ const PreviewJoin = ({ onJoin, skipPreview, initialName, asRole }) => {
73
98
  const savePreferenceAndJoin = useCallback(() => {
74
99
  setPreviewPreference({
75
100
  name,
76
- isAudioMuted: !isLocalAudioEnabled,
77
- isVideoMuted: !isLocalVideoEnabled,
78
101
  });
79
102
  join();
80
103
  onJoin && onJoin();
81
- }, [join, isLocalAudioEnabled, isLocalVideoEnabled, name, setPreviewPreference, onJoin]);
104
+ }, [join, name, setPreviewPreference, onJoin]);
82
105
  const roomLayout = useRoomLayout();
83
106
 
84
107
  const { preview_header: previewHeader = {} } = roomLayout?.screens?.preview?.default?.elements || {};
@@ -144,11 +167,7 @@ const PreviewJoin = ({ onJoin, skipPreview, initialName, asRole }) => {
144
167
  </Flex>
145
168
  ) : null}
146
169
  <Box css={{ w: '100%', maxWidth: '640px' }}>
147
- <PreviewControls
148
- enableJoin={enableJoin}
149
- savePreferenceAndJoin={savePreferenceAndJoin}
150
- hideSettings={!toggleVideo && !toggleAudio}
151
- />
170
+ <PreviewControls hideSettings={!toggleVideo && !toggleAudio} />
152
171
  <PreviewForm
153
172
  name={name}
154
173
  onChange={setName}
@@ -171,7 +190,7 @@ const Container = styled('div', {
171
190
  px: '$10',
172
191
  });
173
192
 
174
- export const PreviewTile = ({ name, error }) => {
193
+ export const PreviewTile = ({ name, error }: { name: string; error?: boolean }) => {
175
194
  const localPeer = useHMSStore(selectLocalPeer);
176
195
  const { isLocalAudioEnabled, toggleAudio } = useAVToggle();
177
196
  const isVideoOn = useHMSStore(selectIsLocalVideoEnabled);
@@ -179,16 +198,19 @@ export const PreviewTile = ({ name, error }) => {
179
198
  const trackSelector = selectVideoTrackByID(localPeer?.videoTrack);
180
199
  const track = useHMSStore(trackSelector);
181
200
  const showMuteIcon = !isLocalAudioEnabled || !toggleAudio;
182
-
201
+ const videoTrack = useHMSStore(selectVideoTrackByID(localPeer?.videoTrack));
202
+ const isMobile = useMedia(cssConfig.media.md);
203
+ const aspectRatio =
204
+ videoTrack?.width && videoTrack?.height ? videoTrack.width / videoTrack.height : isMobile ? 9 / 16 : 16 / 9;
183
205
  return (
184
206
  <StyledVideoTile.Container
185
207
  css={{
186
208
  bg: '$surface_default',
187
- aspectRatio: 16 / 9,
188
- width: 'min(640px, 80vw)',
209
+ aspectRatio,
210
+ height: 'min(640px, 40vh)',
211
+ maxWidth: '640px',
189
212
  overflow: 'clip',
190
213
  '@md': {
191
- aspectRatio: 9 / 16,
192
214
  width: 'min(220px, 70vw)',
193
215
  maxWidth: '100%',
194
216
  my: '$4',
@@ -217,14 +239,15 @@ export const PreviewTile = ({ name, error }) => {
217
239
  <MicOffIcon />
218
240
  </StyledVideoTile.AudioIndicator>
219
241
  ) : (
220
- <AudioLevel trackId={localPeer.audioTrack} />
242
+ <AudioLevel trackId={localPeer?.audioTrack} />
221
243
  )}
222
244
  </StyledVideoTile.Container>
223
245
  );
224
246
  };
225
247
 
226
- export const PreviewControls = ({ hideSettings }) => {
227
- const isVideoOn = useHMSStore(selectIsLocalVideoEnabled);
248
+ export const PreviewControls = ({ hideSettings }: { hideSettings: boolean }) => {
249
+ const isMobile = useMedia(cssConfig.media.md);
250
+
228
251
  return (
229
252
  <Flex
230
253
  justify="between"
@@ -234,8 +257,8 @@ export const PreviewControls = ({ hideSettings }) => {
234
257
  }}
235
258
  >
236
259
  <Flex css={{ gap: '$4' }}>
237
- <AudioVideoToggle compact />
238
- <Suspense fallback="">{isVideoOn ? <VirtualBackground /> : null}</Suspense>
260
+ <AudioVideoToggle />
261
+ <Suspense fallback="">{!isMobile ? <VirtualBackground /> : null}</Suspense>
239
262
  </Flex>
240
263
  {!hideSettings ? <PreviewSettings /> : null}
241
264
  </Flex>
@@ -3,32 +3,37 @@ import {
3
3
  selectLocalPeerName,
4
4
  selectLocalPeerRoleName,
5
5
  selectRoleChangeRequest,
6
+ useCustomEvent,
6
7
  useHMSActions,
7
8
  useHMSStore,
8
9
  } from '@100mslive/react-sdk';
10
+ // @ts-ignore: No implicit Any
9
11
  import { PreviewControls, PreviewTile } from './Preview/PreviewJoin';
10
- import { Box, Button, Dialog, Flex, Text } from '../../';
11
- import { useIsHeadless } from './AppData/useUISettings';
12
+ import { Box, Button, Dialog, Flex, Text } from '../..';
13
+ // @ts-ignore: No implicit Any
12
14
  import { useMyMetadata } from './hooks/useMetadata';
15
+ // @ts-ignore: No implicit Any
13
16
  import { ROLE_CHANGE_DECLINED } from '../common/constants';
14
17
 
15
18
  export const RoleChangeRequestModal = () => {
16
19
  const hmsActions = useHMSActions();
17
- const isHeadless = useIsHeadless();
18
- const { setPrevRole } = useMyMetadata();
20
+ const { updateMetaData } = useMyMetadata();
19
21
  const currentRole = useHMSStore(selectLocalPeerRoleName);
20
22
  const roleChangeRequest = useHMSStore(selectRoleChangeRequest);
21
23
  const name = useHMSStore(selectLocalPeerName);
24
+ const { sendEvent } = useCustomEvent({ type: ROLE_CHANGE_DECLINED });
22
25
 
23
26
  useEffect(() => {
24
- if (!roleChangeRequest?.role || isHeadless) {
27
+ if (!roleChangeRequest?.role) {
25
28
  return;
26
29
  }
30
+ (async () => {
31
+ await updateMetaData({ prevRole: currentRole });
32
+ await hmsActions.preview({ asRole: roleChangeRequest.role.name });
33
+ })();
34
+ }, [hmsActions, roleChangeRequest, currentRole, updateMetaData]);
27
35
 
28
- hmsActions.preview({ asRole: roleChangeRequest.role.name });
29
- }, [hmsActions, roleChangeRequest, isHeadless]);
30
-
31
- if (!roleChangeRequest?.role || isHeadless) {
36
+ if (!roleChangeRequest?.role) {
32
37
  return null;
33
38
  }
34
39
 
@@ -46,8 +51,8 @@ export const RoleChangeRequestModal = () => {
46
51
  mt: '$6',
47
52
  }}
48
53
  >
49
- <PreviewTile name={name} />
50
- <PreviewControls />
54
+ <PreviewTile name={name || ''} />
55
+ <PreviewControls hideSettings={true} />
51
56
  </Flex>
52
57
  </>
53
58
  );
@@ -58,27 +63,41 @@ export const RoleChangeRequestModal = () => {
58
63
  onOpenChange={async value => {
59
64
  if (!value) {
60
65
  await hmsActions.rejectChangeRole(roleChangeRequest);
61
- await hmsActions.sendDirectMessage('', roleChangeRequest.requestedBy?.id, ROLE_CHANGE_DECLINED);
66
+ sendEvent({ ...roleChangeRequest, peerName: name }, { peerId: roleChangeRequest.requestedBy?.id });
62
67
  await hmsActions.cancelMidCallPreview();
68
+ await updateMetaData({ isHandRaised: false });
63
69
  }
64
70
  }}
65
71
  body={body}
66
- onAction={() => {
67
- hmsActions.acceptChangeRole(roleChangeRequest);
68
- setPrevRole(currentRole);
72
+ onAction={async () => {
73
+ await hmsActions.acceptChangeRole(roleChangeRequest);
74
+ await updateMetaData({ isHandRaised: false });
69
75
  }}
70
76
  actionText="Accept"
71
77
  />
72
78
  );
73
79
  };
74
80
 
75
- const RequestDialog = ({ open = true, onOpenChange, title, body, actionText = 'Accept', onAction, Icon }) => (
81
+ const RequestDialog = ({
82
+ open = true,
83
+ onOpenChange,
84
+ title,
85
+ body,
86
+ actionText = 'Accept',
87
+ onAction,
88
+ }: {
89
+ open?: boolean;
90
+ onOpenChange: (value: boolean) => void;
91
+ title: string;
92
+ body: React.ReactNode;
93
+ actionText?: string;
94
+ onAction: () => void;
95
+ }) => (
76
96
  <Dialog.Root open={open} onOpenChange={onOpenChange}>
77
97
  <Dialog.Portal>
78
98
  <Dialog.Overlay />
79
99
  <Dialog.Content css={{ p: '$10' }}>
80
100
  <Dialog.Title css={{ p: 0, display: 'flex', flexDirection: 'row', gap: '$md', justifyContent: 'center' }}>
81
- {Icon ? Icon : null}
82
101
  <Text variant="h6">{title}</Text>
83
102
  </Dialog.Title>
84
103
  <Box css={{ mt: '$4', mb: '$10' }}>{body}</Box>
@@ -15,7 +15,7 @@ import { Video } from '../../Video';
15
15
  import { StyledVideoTile } from '../../VideoTile';
16
16
  import { getVideoTileLabel } from './peerTileUtils';
17
17
  import { ScreenshareDisplay } from './ScreenshareDisplay';
18
- import { useIsHeadless, useUISettings } from './AppData/useUISettings';
18
+ import { useUISettings } from './AppData/useUISettings';
19
19
  import { UI_SETTINGS } from '../common/constants';
20
20
 
21
21
  const labelStyles = {
@@ -24,7 +24,6 @@ const labelStyles = {
24
24
  textAlign: 'center',
25
25
  c: '$on_surface_high',
26
26
  transform: 'none',
27
- mt: '$2',
28
27
  flexShrink: 0,
29
28
  };
30
29
 
@@ -33,7 +32,6 @@ const Tile = ({ peerId, width = '100%', height = '100%' }) => {
33
32
  const track = useHMSStore(selectScreenShareByPeerID(peerId));
34
33
  const peer = useHMSStore(selectPeerByID(peerId));
35
34
  const isAudioOnly = useUISettings(UI_SETTINGS.isAudioOnly);
36
- const isHeadless = useIsHeadless();
37
35
  const [isMouseHovered, setIsMouseHovered] = useState(false);
38
36
  const showStatsOnTiles = useUISettings(UI_SETTINGS.showStatsOnTiles);
39
37
  const label = getVideoTileLabel({
@@ -59,11 +57,11 @@ const Tile = ({ peerId, width = '100%', height = '100%' }) => {
59
57
  return null;
60
58
  }
61
59
  return (
62
- <StyledVideoTile.Root css={{ width, height, p: 0, mb: '$4', minHeight: 0 }} data-testid="screenshare_tile">
60
+ <StyledVideoTile.Root css={{ width, height, p: 0, minHeight: 0 }} data-testid="screenshare_tile">
63
61
  <StyledVideoTile.Container
64
62
  transparentBg
65
63
  ref={fullscreenRef}
66
- css={{ flexDirection: 'column' }}
64
+ css={{ flexDirection: 'column', gap: '$2' }}
67
65
  onMouseEnter={() => setIsMouseHovered(true)}
68
66
  onMouseLeave={() => {
69
67
  setIsMouseHovered(false);
@@ -72,7 +70,7 @@ const Tile = ({ peerId, width = '100%', height = '100%' }) => {
72
70
  {showStatsOnTiles ? (
73
71
  <VideoTileStats audioTrackID={audioTrack?.id} videoTrackID={track?.id} peerID={peerId} isLocal={isLocal} />
74
72
  ) : null}
75
- {isFullScreenSupported && !isHeadless ? (
73
+ {isFullScreenSupported && isMouseHovered ? (
76
74
  <StyledVideoTile.FullScreenButton onClick={() => setFullscreen(!fullscreen)}>
77
75
  {isFullscreen ? <ShrinkIcon /> : <ExpandIcon />}
78
76
  </StyledVideoTile.FullScreenButton>
@@ -83,10 +81,11 @@ const Tile = ({ peerId, width = '100%', height = '100%' }) => {
83
81
  mirror={peer.isLocal && track?.source === 'regular'}
84
82
  attach={!isAudioOnly}
85
83
  trackId={track.id}
84
+ css={{ minHeight: 0 }}
86
85
  />
87
86
  ) : null}
88
87
  <StyledVideoTile.Info css={labelStyles}>{label}</StyledVideoTile.Info>
89
- {isMouseHovered && !isHeadless && !peer?.isLocal ? (
88
+ {isMouseHovered && !peer?.isLocal ? (
90
89
  <TileMenu isScreenshare peerID={peer?.id} audioTrackID={audioTrack?.id} videoTrackID={track?.id} />
91
90
  ) : null}
92
91
  </StyledVideoTile.Container>
@@ -6,7 +6,7 @@ import { config as cssConfig } from '../../Theme';
6
6
  import { Pagination } from './Pagination';
7
7
  import { usePagesWithTiles } from './hooks/useTileLayout';
8
8
 
9
- export const SecondaryTiles = ({ peers, onPageChange, onPageSize }: LayoutProps) => {
9
+ export const SecondaryTiles = ({ peers, onPageChange, onPageSize, edgeToEdge }: LayoutProps) => {
10
10
  const isMobile = useMedia(cssConfig.media.md);
11
11
  const maxTileCount = isMobile ? 2 : 4;
12
12
  const pagesWithTiles = usePagesWithTiles({ peers, maxTileCount });
@@ -20,15 +20,17 @@ export const SecondaryTiles = ({ peers, onPageChange, onPageSize }: LayoutProps)
20
20
  }, [pageSize, onPageSize]);
21
21
 
22
22
  return (
23
- <ProminenceLayout.SecondarySection tiles={pagesWithTiles[page]}>
24
- <Pagination
25
- page={page}
26
- onPageChange={page => {
27
- setPage(page);
28
- onPageChange?.(page);
29
- }}
30
- numPages={pagesWithTiles.length}
31
- />
23
+ <ProminenceLayout.SecondarySection tiles={pagesWithTiles[page]} edgeToEdge={edgeToEdge}>
24
+ {!edgeToEdge && (
25
+ <Pagination
26
+ page={page}
27
+ onPageChange={page => {
28
+ setPage(page);
29
+ onPageChange?.(page);
30
+ }}
31
+ numPages={pagesWithTiles.length}
32
+ />
33
+ )}
32
34
  </ProminenceLayout.SecondarySection>
33
35
  );
34
36
  };