@100mslive/roomkit-react 0.1.8-alpha.0 → 0.1.9-alpha.0

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 (142) hide show
  1. package/dist/{HLSView-IQRPLYNH.js → HLSView-U53QN3AC.js} +3 -3
  2. package/dist/Modal/Dialog.d.ts +402 -1706
  3. package/dist/Prebuilt/App.d.ts +6 -0
  4. package/dist/Prebuilt/AppContext.d.ts +2 -0
  5. package/dist/Prebuilt/AppStateContext.d.ts +16 -0
  6. package/dist/Prebuilt/components/ConferenceScreen.d.ts +2 -0
  7. package/dist/Prebuilt/components/Footer/PaginatedParticipants.d.ts +5 -0
  8. package/dist/Prebuilt/components/Footer/PollsToggle.d.ts +2 -0
  9. package/dist/Prebuilt/components/Footer/RoleAccordion.d.ts +10 -3
  10. package/dist/Prebuilt/components/LeaveScreen.d.ts +2 -0
  11. package/dist/Prebuilt/components/MwebLandscapePrompt.d.ts +2 -0
  12. package/dist/Prebuilt/components/Notifications/AutoplayBlockedModal.d.ts +2 -0
  13. package/dist/Prebuilt/components/Notifications/HLSFailureModal.d.ts +2 -0
  14. package/dist/Prebuilt/components/Notifications/InitErrorModal.d.ts +2 -0
  15. package/dist/Prebuilt/components/Notifications/Notifications.d.ts +2 -0
  16. package/dist/Prebuilt/components/Notifications/PeerNotifications.d.ts +1 -0
  17. package/dist/Prebuilt/components/Notifications/PermissionErrorModal.d.ts +2 -0
  18. package/dist/Prebuilt/components/Notifications/ReconnectNotifications.d.ts +2 -0
  19. package/dist/Prebuilt/components/Notifications/TrackBulkUnmuteModal.d.ts +2 -0
  20. package/dist/Prebuilt/components/Notifications/TrackNotifications.d.ts +1 -0
  21. package/dist/Prebuilt/components/Notifications/TrackUnmuteModal.d.ts +2 -0
  22. package/dist/Prebuilt/components/Polls/Polls.d.ts +2 -0
  23. package/dist/Prebuilt/components/Preview/PreviewJoin.d.ts +1 -2
  24. package/dist/Prebuilt/components/Preview/PreviewScreen.d.ts +2 -0
  25. package/dist/Prebuilt/components/hooks/useRedirectToLeave.d.ts +1 -1
  26. package/dist/{VirtualBackground-GP4ATXD3.js → VirtualBackground-PMLQPJB6.js} +3 -5
  27. package/dist/{VirtualBackground-GP4ATXD3.js.map → VirtualBackground-PMLQPJB6.js.map} +1 -1
  28. package/dist/chunk-ANQRGVIX.js +14441 -0
  29. package/dist/chunk-ANQRGVIX.js.map +7 -0
  30. package/dist/{chunk-Z3O2WGWV.js → chunk-XQ2NRKIW.js} +66 -3
  31. package/dist/chunk-XQ2NRKIW.js.map +7 -0
  32. package/dist/context/DialogContext.d.ts +6 -0
  33. package/dist/hooks/useDialogContainerSelector.d.ts +1 -0
  34. package/dist/index.cjs.js +10956 -9818
  35. package/dist/index.cjs.js.map +4 -4
  36. package/dist/index.d.ts +1 -0
  37. package/dist/index.js +6 -2
  38. package/dist/meta.cjs.json +4076 -3201
  39. package/dist/meta.esbuild.json +4391 -3623
  40. package/dist/utils/animations.d.ts +11 -0
  41. package/package.json +6 -7
  42. package/src/AudioLevel/AudioLevel.tsx +1 -1
  43. package/src/Modal/Dialog.tsx +31 -3
  44. package/src/Prebuilt/App.tsx +49 -97
  45. package/src/Prebuilt/AppContext.tsx +6 -0
  46. package/src/Prebuilt/AppStateContext.tsx +71 -0
  47. package/src/Prebuilt/common/constants.js +36 -1
  48. package/src/Prebuilt/common/utils.js +47 -0
  49. package/src/Prebuilt/components/AppData/AppData.jsx +6 -1
  50. package/src/Prebuilt/components/AppData/useSidepane.js +23 -1
  51. package/src/Prebuilt/components/AppData/useUISettings.js +49 -5
  52. package/src/Prebuilt/components/Chip.tsx +6 -2
  53. package/src/Prebuilt/components/{conference.jsx → ConferenceScreen.tsx} +34 -46
  54. package/src/Prebuilt/components/Footer/Footer.tsx +5 -0
  55. package/src/Prebuilt/components/Footer/PaginatedParticipants.tsx +125 -0
  56. package/src/Prebuilt/components/Footer/ParticipantList.jsx +55 -24
  57. package/src/Prebuilt/components/Footer/PollsToggle.tsx +22 -0
  58. package/src/Prebuilt/components/Footer/RoleAccordion.tsx +87 -85
  59. package/src/Prebuilt/components/Footer/RoleOptions.tsx +1 -1
  60. package/src/Prebuilt/components/Header/StreamActions.tsx +5 -3
  61. package/src/Prebuilt/components/Leave/DesktopLeaveRoom.tsx +4 -5
  62. package/src/Prebuilt/components/Leave/LeaveRoom.tsx +0 -4
  63. package/src/Prebuilt/components/{PostLeave.jsx → LeaveScreen.tsx} +6 -13
  64. package/src/Prebuilt/components/MoreSettings/ChangeNameModal.jsx +2 -3
  65. package/src/Prebuilt/components/MoreSettings/EmbedUrl.jsx +2 -3
  66. package/src/Prebuilt/components/MoreSettings/SplitComponents/MwebOptions.tsx +18 -1
  67. package/src/Prebuilt/components/{MwebLandscapePrompt.jsx → MwebLandscapePrompt.tsx} +10 -11
  68. package/src/Prebuilt/components/Notifications/{AutoplayBlockedModal.jsx → AutoplayBlockedModal.tsx} +2 -1
  69. package/src/Prebuilt/components/Notifications/{HLSFailureModal.jsx → HLSFailureModal.tsx} +10 -8
  70. package/src/Prebuilt/components/Notifications/{InitErrorModal.jsx → InitErrorModal.tsx} +5 -2
  71. package/src/Prebuilt/components/Notifications/{Notifications.jsx → Notifications.tsx} +41 -27
  72. package/src/Prebuilt/components/Notifications/{PeerNotifications.jsx → PeerNotifications.tsx} +3 -0
  73. package/src/Prebuilt/components/Notifications/{PermissionErrorModal.jsx → PermissionErrorModal.tsx} +6 -4
  74. package/src/Prebuilt/components/Notifications/{ReconnectNotifications.jsx → ReconnectNotifications.tsx} +11 -6
  75. package/src/Prebuilt/components/Notifications/{TrackBulkUnmuteModal.jsx → TrackBulkUnmuteModal.tsx} +9 -3
  76. package/src/Prebuilt/components/Notifications/{TrackUnmuteModal.jsx → TrackUnmuteModal.tsx} +9 -3
  77. package/src/Prebuilt/components/Notifications/index.tsx +1 -0
  78. package/src/Prebuilt/components/Polls/CreatePollQuiz/PollsQuizMenu.jsx +229 -0
  79. package/src/Prebuilt/components/Polls/CreatePollQuiz/Timer.jsx +71 -0
  80. package/src/Prebuilt/components/Polls/CreateQuestions/CreateQuestions.jsx +132 -0
  81. package/src/Prebuilt/components/Polls/CreateQuestions/DeleteQuestionModal.jsx +66 -0
  82. package/src/Prebuilt/components/Polls/CreateQuestions/QuestionForm.jsx +251 -0
  83. package/src/Prebuilt/components/Polls/CreateQuestions/SavedQuestion.jsx +57 -0
  84. package/src/Prebuilt/components/Polls/Polls.tsx +28 -0
  85. package/src/Prebuilt/components/Polls/Voting/PollResultSummary.jsx +125 -0
  86. package/src/Prebuilt/components/Polls/Voting/QuestionCard.jsx +249 -0
  87. package/src/Prebuilt/components/Polls/Voting/StandardVoting.jsx +40 -0
  88. package/src/Prebuilt/components/Polls/Voting/TimedVoting.jsx +36 -0
  89. package/src/Prebuilt/components/Polls/Voting/Voting.jsx +99 -0
  90. package/src/Prebuilt/components/Polls/common/MultipleChoiceOptions.jsx +101 -0
  91. package/src/Prebuilt/components/Polls/common/OptionInputWithDelete.jsx +25 -0
  92. package/src/Prebuilt/components/Polls/common/SingleChoiceOptions.jsx +125 -0
  93. package/src/Prebuilt/components/Polls/common/StatusIndicator.jsx +47 -0
  94. package/src/Prebuilt/components/Polls/common/VoteCount.jsx +28 -0
  95. package/src/Prebuilt/components/Polls/common/VoteProgress.jsx +17 -0
  96. package/src/Prebuilt/components/Polls/common/VoterList.jsx +22 -0
  97. package/src/Prebuilt/components/Polls/common/Votes.jsx +72 -0
  98. package/src/Prebuilt/components/Preview/PreviewForm.tsx +3 -2
  99. package/src/Prebuilt/components/Preview/PreviewJoin.tsx +29 -21
  100. package/src/Prebuilt/components/Preview/{PreviewContainer.tsx → PreviewScreen.tsx} +2 -19
  101. package/src/Prebuilt/components/RaiseHand.jsx +1 -1
  102. package/src/Prebuilt/components/RoleChangeModal.jsx +2 -3
  103. package/src/Prebuilt/components/RoleChangeRequest/RequestPrompt.tsx +2 -3
  104. package/src/Prebuilt/components/Settings/SettingsModal.jsx +2 -3
  105. package/src/Prebuilt/components/Settings/StartRecording.jsx +15 -4
  106. package/src/Prebuilt/components/SidePaneTabs.tsx +32 -6
  107. package/src/Prebuilt/components/StatsForNerds.jsx +2 -3
  108. package/src/Prebuilt/components/Streaming/Common.jsx +31 -21
  109. package/src/Prebuilt/components/VideoLayouts/ScreenshareLayout.tsx +8 -9
  110. package/src/Prebuilt/components/VideoTile.jsx +28 -39
  111. package/src/Prebuilt/components/hooks/useAutoStartStreaming.tsx +3 -3
  112. package/src/Prebuilt/components/hooks/useDropdownSelection.jsx +1 -1
  113. package/src/Prebuilt/components/hooks/useRedirectToLeave.tsx +9 -17
  114. package/src/Prebuilt/components/pdfAnnotator/pdfFileOptions.jsx +2 -3
  115. package/src/Prebuilt/components/pdfAnnotator/submitPdf.jsx +1 -1
  116. package/src/Prebuilt/components/pdfAnnotator/uploadedFile.jsx +2 -3
  117. package/src/Prebuilt/layouts/EmbedView.jsx +47 -60
  118. package/src/Prebuilt/layouts/PDFView.jsx +49 -99
  119. package/src/Prebuilt/layouts/SidePane.tsx +9 -4
  120. package/src/Prebuilt/layouts/VideoStreamingSection.tsx +2 -2
  121. package/src/Prebuilt/primitives/DialogContent.jsx +4 -5
  122. package/src/context/DialogContext.tsx +13 -0
  123. package/src/hooks/useDialogContainerSelector.tsx +7 -0
  124. package/src/index.ts +1 -0
  125. package/src/utils/animations.ts +6 -0
  126. package/dist/Prebuilt/components/PrebuiltDialogPortal.d.ts +0 -4
  127. package/dist/Prebuilt/components/Preview/PreviewContainer.d.ts +0 -3
  128. package/dist/chunk-2H5NIZB7.js +0 -70
  129. package/dist/chunk-2H5NIZB7.js.map +0 -7
  130. package/dist/chunk-GLYGPYNS.js +0 -7125
  131. package/dist/chunk-GLYGPYNS.js.map +0 -7
  132. package/dist/chunk-Z3O2WGWV.js.map +0 -7
  133. package/dist/conference-JD35TNH4.js +0 -6503
  134. package/dist/conference-JD35TNH4.js.map +0 -7
  135. package/src/Prebuilt/components/GoLiveButton.jsx +0 -42
  136. package/src/Prebuilt/components/PrebuiltDialogPortal.tsx +0 -6
  137. package/src/Prebuilt/components/Streaming/HLSStreaming.jsx +0 -220
  138. package/src/Prebuilt/components/Streaming/RTMPStreaming.jsx +0 -334
  139. package/src/Prebuilt/components/Streaming/StreamingLanding.jsx +0 -76
  140. /package/dist/{HLSView-IQRPLYNH.js.map → HLSView-U53QN3AC.js.map} +0 -0
  141. /package/{src/Prebuilt/components/Notifications/index.jsx → dist/Prebuilt/components/Notifications/index.d.ts} +0 -0
  142. /package/src/Prebuilt/components/Notifications/{TrackNotifications.jsx → TrackNotifications.tsx} +0 -0
@@ -37,36 +37,46 @@ export const StreamCard = ({ title, subtitle, Icon, imgSrc = '', css = {}, onCli
37
37
  );
38
38
  };
39
39
 
40
- export const ContentHeader = ({ onBack, title, content }) => {
40
+ export const ContentHeader = ({ onBack, onClose, title = '', content }) => {
41
41
  return (
42
- <Flex css={{ w: '100%', py: '$8', px: '$10', cursor: 'pointer' }}>
43
- <Text
44
- css={{ p: '$2', bg: '$surface_bright', r: '$round', alignSelf: 'center' }}
45
- onClick={onBack}
46
- data-testid="go_back"
47
- >
48
- <ChevronLeftIcon width={16} height={16} />
49
- </Text>
50
- <Box css={{ flex: '1 1 0', mx: '$8' }}>
42
+ <Flex
43
+ css={{ w: '100%', py: '$8', px: '$10', cursor: 'pointer', borderBottom: '1px solid $border_bright', mb: '$8' }}
44
+ >
45
+ {onBack ? (
51
46
  <Text
52
- variant="tiny"
53
47
  css={{
54
- textTransform: 'uppercase',
55
- fontWeight: '$semiBold',
56
- color: '$on_surface_medium',
48
+ alignSelf: 'center',
49
+ mr: '$8',
57
50
  }}
51
+ onClick={onBack}
52
+ data-testid="go_back"
58
53
  >
59
- {title}
54
+ <ChevronLeftIcon />
60
55
  </Text>
56
+ ) : null}
57
+ <Box css={{ flex: '1 1 0' }}>
58
+ {title ? (
59
+ <Text
60
+ variant="tiny"
61
+ css={{
62
+ textTransform: 'uppercase',
63
+ fontWeight: '$semiBold',
64
+ color: '$on_surface_medium',
65
+ }}
66
+ >
67
+ {title}
68
+ </Text>
69
+ ) : null}
61
70
  <Text variant="h6">{content}</Text>
62
71
  </Box>
63
- <IconButton onClick={onBack} css={{ alignSelf: 'flex-start' }} data-testid="close_stream_section">
64
- <CrossIcon width={16} height={16} />
65
- </IconButton>
72
+ {onClose ? (
73
+ <IconButton onClick={onClose} css={{ alignSelf: 'flex-start' }} data-testid="close_stream_section">
74
+ <CrossIcon />
75
+ </IconButton>
76
+ ) : null}
66
77
  </Flex>
67
78
  );
68
79
  };
69
-
70
80
  export const Container = ({ children, rounded = false }) => {
71
81
  return (
72
82
  <Box
@@ -76,7 +86,7 @@ export const Container = ({ children, rounded = false }) => {
76
86
  position: 'absolute',
77
87
  top: 0,
78
88
  left: 0,
79
- bg: '$surface_default',
89
+ bg: '$surface_dim',
80
90
  transform: 'translateX(10%)',
81
91
  animation: `${slideLeftAndFade('10%')} 100ms ease-out forwards`,
82
92
  display: 'flex',
@@ -125,7 +135,7 @@ export const ErrorText = ({ error }) => {
125
135
  return null;
126
136
  }
127
137
  return (
128
- <Text variant="sm" css={{ mb: '$8', color: '$alert_error_default' }}>
138
+ <Text variant="sm" css={{ my: '$4', color: '$alert_error_default' }}>
129
139
  {error}
130
140
  </Text>
131
141
  );
@@ -19,15 +19,14 @@ export const ScreenshareLayout = ({ peers, onPageChange, onPageSize, edgeToEdge
19
19
  const [page, setPage] = useState(0);
20
20
  const activeSharePeer = peersSharing[page];
21
21
  const isMobile = useMedia(cssConfig.media.md);
22
- const secondaryPeers = useMemo(
23
- () =>
24
- isMobile
25
- ? activeSharePeer
26
- ? [activeSharePeer, ...peers.filter(p => p.id !== activeSharePeer?.id)]
27
- : peers //keep active sharing peer as first tile
28
- : peers.filter(p => p.id !== activeSharePeer?.id),
29
- [activeSharePeer, peers, isMobile],
30
- );
22
+ const secondaryPeers = useMemo(() => {
23
+ if (isMobile) {
24
+ return activeSharePeer
25
+ ? [activeSharePeer, ...peers.filter(p => p.id !== activeSharePeer?.id)] //keep active sharing peer as first tile
26
+ : peers;
27
+ }
28
+ return peers.filter(p => p.id !== activeSharePeer?.id);
29
+ }, [activeSharePeer, peers, isMobile]);
31
30
  useEffect(() => {
32
31
  setActiveScreenSharePeer(isMobile ? '' : activeSharePeer?.id);
33
32
  return () => {
@@ -1,5 +1,5 @@
1
- import React, { Fragment, useCallback, useMemo, useRef, useState } from 'react';
2
- import { useMedia } from 'react-use';
1
+ import React, { Fragment, useCallback, useMemo, useState } from 'react';
2
+ import { useMeasure, useMedia } from 'react-use';
3
3
  import {
4
4
  selectAudioTrackByPeerID,
5
5
  selectHasPeerHandRaised,
@@ -23,6 +23,7 @@ import { Video } from '../../Video';
23
23
  import { StyledVideoTile } from '../../VideoTile';
24
24
  import { getVideoTileLabel } from './peerTileUtils';
25
25
  import { useSetAppDataByKey, useUISettings } from './AppData/useUISettings';
26
+ import { calculateAvatarAndAttribBoxSize } from '../common/utils';
26
27
  import { APP_DATA, SESSION_STORE_KEY, UI_SETTINGS } from '../common/constants';
27
28
 
28
29
  const Tile = ({
@@ -71,29 +72,14 @@ const Tile = ({
71
72
  setIsMouseHovered(event.type === 'mouseenter');
72
73
  }, []);
73
74
 
74
- const ref = useRef(null);
75
- const calculatedHeight = ref.current?.clientHeight || '';
76
- const calculatedWidth = ref.current?.clientWidth || '';
75
+ const [ref, { width: calculatedWidth, height: calculatedHeight }] = useMeasure();
77
76
 
78
77
  const isTileBigEnoughToShowStats = calculatedHeight >= 180 && calculatedWidth >= 180;
79
78
 
80
- const [avatarSize, attribBoxSize] = useMemo(() => {
81
- if (!calculatedWidth || !calculatedHeight) {
82
- return [undefined, undefined];
83
- }
84
- let avatarSize = 'large';
85
- if (calculatedWidth <= 150 || calculatedHeight <= 150) {
86
- avatarSize = 'small';
87
- } else if (calculatedWidth <= 300 || calculatedHeight <= 300) {
88
- avatarSize = 'medium';
89
- }
90
- let attribBoxSize = 'medium';
91
- if (calculatedWidth <= 180 || calculatedHeight <= 180) {
92
- attribBoxSize = 'small';
93
- }
94
-
95
- return [avatarSize, attribBoxSize];
96
- }, [calculatedWidth, calculatedHeight]);
79
+ const [avatarSize, attribBoxSize] = useMemo(
80
+ () => calculateAvatarAndAttribBoxSize(calculatedWidth, calculatedHeight),
81
+ [calculatedWidth, calculatedHeight],
82
+ );
97
83
 
98
84
  return (
99
85
  <StyledVideoTile.Root
@@ -133,23 +119,27 @@ const Tile = ({
133
119
  bg: 'transparent',
134
120
  }}
135
121
  />
122
+ {calculatedWidth > 0 && calculatedHeight > 0 ? (
123
+ <>
124
+ {isVideoMuted || (!isLocal && isAudioOnly) ? (
125
+ <StyledVideoTile.AvatarContainer>
126
+ <Avatar name={peerName || ''} data-testid="participant_avatar_icon" size={avatarSize} />
127
+ </StyledVideoTile.AvatarContainer>
128
+ ) : null}
136
129
 
137
- {isVideoMuted || (!isLocal && isAudioOnly) ? (
138
- <StyledVideoTile.AvatarContainer>
139
- <Avatar name={peerName || ''} data-testid="participant_avatar_icon" size={avatarSize} />
140
- </StyledVideoTile.AvatarContainer>
141
- ) : null}
142
-
143
- {!hideAudioMuteOnTile ? (
144
- isAudioMuted ? (
145
- <StyledVideoTile.AudioIndicator data-testid="participant_audio_mute_icon" size={attribBoxSize}>
146
- <MicOffIcon />
147
- </StyledVideoTile.AudioIndicator>
148
- ) : (
149
- <StyledVideoTile.AudioIndicator size={attribBoxSize}>
150
- <AudioLevel trackId={audioTrack?.id} size={attribBoxSize} />
151
- </StyledVideoTile.AudioIndicator>
152
- )
130
+ {!hideAudioMuteOnTile ? (
131
+ isAudioMuted ? (
132
+ <StyledVideoTile.AudioIndicator data-testid="participant_audio_mute_icon" size={attribBoxSize}>
133
+ <MicOffIcon />
134
+ </StyledVideoTile.AudioIndicator>
135
+ ) : (
136
+ <StyledVideoTile.AudioIndicator size={attribBoxSize}>
137
+ <AudioLevel trackId={audioTrack?.id} size={attribBoxSize} />
138
+ </StyledVideoTile.AudioIndicator>
139
+ )
140
+ ) : null}
141
+ {!hideMetadataOnTile && <PeerMetadata peerId={peerId} size={attribBoxSize} />}
142
+ </>
153
143
  ) : null}
154
144
  {isMouseHovered || (isDragabble && isMobile) ? (
155
145
  <TileMenu
@@ -160,7 +150,6 @@ const Tile = ({
160
150
  enableSpotlightingPeer={enableSpotlightingPeer}
161
151
  />
162
152
  ) : null}
163
- {!hideMetadataOnTile && <PeerMetadata peerId={peerId} size={attribBoxSize} />}
164
153
 
165
154
  <TileConnection
166
155
  hideLabel={hideParticipantNameOnTile}
@@ -20,12 +20,12 @@ export const useAutoStartStreaming = () => {
20
20
  const showStreamingUI = useShowStreamingUI();
21
21
  const hmsActions = useHMSActions();
22
22
  const isConnected = useHMSStore(selectIsConnectedToRoom);
23
- const { isHLSRunning } = useRecordingStreaming();
23
+ const { isHLSRunning, isRTMPRunning } = useRecordingStreaming();
24
24
  const streamStartedRef = useRef(false);
25
25
 
26
26
  const startHLS = useCallback(async () => {
27
27
  try {
28
- if (isHLSStarted || !showStreamingUI || isHLSRunning) {
28
+ if (isHLSStarted || !showStreamingUI || isHLSRunning || isRTMPRunning) {
29
29
  return;
30
30
  }
31
31
  setHLSStarted(true);
@@ -38,7 +38,7 @@ export const useAutoStartStreaming = () => {
38
38
  streamStartedRef.current = false;
39
39
  setHLSStarted(false);
40
40
  }
41
- }, [hmsActions, isHLSRunning, isHLSStarted, setHLSStarted, showStreamingUI]);
41
+ }, [hmsActions, isHLSRunning, isHLSStarted, setHLSStarted, showStreamingUI, isRTMPRunning]);
42
42
 
43
43
  useEffect(() => {
44
44
  if (!isHLSStarted && !isHLSRunning) {
@@ -1,3 +1,3 @@
1
1
  export const useDropdownSelection = () => {
2
- return '$primary_dim';
2
+ return '$surface_bright';
3
3
  };
@@ -1,33 +1,25 @@
1
1
  import { useCallback } from 'react';
2
- import { useNavigate, useParams } from 'react-router-dom';
3
2
  import { useHMSPrebuiltContext } from '../../AppContext';
4
3
  // @ts-ignore: No implicit Any
5
4
  import { PictureInPicture } from '../PIP/PIPManager';
6
5
  // @ts-ignore: No implicit Any
7
6
  import { ToastManager } from '../Toast/ToastManager';
8
- import { useRoomLayoutLeaveScreen } from '../../provider/roomLayoutProvider/hooks/useRoomLayoutScreen';
9
7
 
10
8
  export const useRedirectToLeave = () => {
11
- const { isLeaveScreenEnabled } = useRoomLayoutLeaveScreen();
12
9
  const { onLeave } = useHMSPrebuiltContext();
13
- const params = useParams();
14
- const navigate = useNavigate();
15
10
 
16
11
  const redirect = useCallback(
17
12
  (timeout = 0) => {
18
- setTimeout(() => {
19
- const prefix = isLeaveScreenEnabled ? '/leave/' : '/';
20
- if (params.role) {
21
- navigate(prefix + params.roomId + '/' + params.role);
22
- } else {
23
- navigate(prefix + params.roomId);
24
- }
25
- PictureInPicture.stop().catch(() => console.error('stopping pip'));
26
- ToastManager.clearAllToast();
27
- onLeave?.();
28
- }, timeout);
13
+ return new Promise<void>(resolve => {
14
+ setTimeout(() => {
15
+ PictureInPicture.stop().catch(() => console.error('stopping pip'));
16
+ ToastManager.clearAllToast();
17
+ onLeave?.();
18
+ resolve();
19
+ }, timeout);
20
+ });
29
21
  },
30
- [isLeaveScreenEnabled, navigate, onLeave, params.role, params.roomId],
22
+ [onLeave],
31
23
  );
32
24
 
33
25
  return { redirectToLeave: redirect };
@@ -1,7 +1,6 @@
1
1
  import React, { useState } from 'react';
2
2
  import { Dialog, Flex } from '../../../';
3
3
  import { DialogInputFile } from '../../primitives/DialogContent';
4
- import { PrebuiltDialogPortal } from '../PrebuiltDialogPortal';
5
4
  import { PDFHeader } from './pdfHeader';
6
5
  import { SubmitPDF } from './submitPdf';
7
6
  import { UploadedFile } from './uploadedFile';
@@ -11,7 +10,7 @@ export function PDFFileOptions({ onOpenChange }) {
11
10
 
12
11
  return !pdfFile ? (
13
12
  <Dialog.Root defaultOpen onOpenChange={onOpenChange}>
14
- <PrebuiltDialogPortal>
13
+ <Dialog.Portal>
15
14
  <Dialog.Overlay />
16
15
  <Dialog.Content
17
16
  css={{
@@ -35,7 +34,7 @@ export function PDFFileOptions({ onOpenChange }) {
35
34
  <SubmitPDF pdfFile={pdfFile} onOpenChange={onOpenChange} />
36
35
  </Flex>
37
36
  </Dialog.Content>
38
- </PrebuiltDialogPortal>
37
+ </Dialog.Portal>
39
38
  </Dialog.Root>
40
39
  ) : (
41
40
  <UploadedFile pdfFile={pdfFile} setPDFFile={setPDFFile} onOpenChange={onOpenChange} />
@@ -31,7 +31,7 @@ export const SubmitPDF = ({ pdfFile, onOpenChange }) => {
31
31
  type="submit"
32
32
  onClick={() => {
33
33
  if (pdfFile) {
34
- setPDFConfig({ state: true, file: pdfFile });
34
+ setPDFConfig(pdfFile);
35
35
  onOpenChange(false);
36
36
  }
37
37
  }}
@@ -2,7 +2,6 @@ import React from 'react';
2
2
  import { TrashIcon } from '@100mslive/react-icons';
3
3
  import { Dialog, Flex, Text } from '../../../';
4
4
  import { DialogRow } from '../../primitives/DialogContent';
5
- import { PrebuiltDialogPortal } from '../PrebuiltDialogPortal';
6
5
  import { PDFHeader } from './pdfHeader';
7
6
  import { PDFInfo } from './pdfInfo';
8
7
  import { SubmitPDF } from './submitPdf';
@@ -11,7 +10,7 @@ export const UploadedFile = ({ pdfFile, setPDFFile, onOpenChange }) => {
11
10
  const [fileName, ext] = pdfFile.name.split('.');
12
11
  return (
13
12
  <Dialog.Root defaultOpen onOpenChange={onOpenChange}>
14
- <PrebuiltDialogPortal>
13
+ <Dialog.Portal>
15
14
  <Dialog.Overlay />
16
15
  <Dialog.Content
17
16
  css={{
@@ -66,7 +65,7 @@ export const UploadedFile = ({ pdfFile, setPDFFile, onOpenChange }) => {
66
65
  <SubmitPDF pdfFile={pdfFile} onOpenChange={onOpenChange} />
67
66
  </Flex>
68
67
  </Dialog.Content>
69
- </PrebuiltDialogPortal>
68
+ </Dialog.Portal>
70
69
  </Dialog.Root>
71
70
  );
72
71
  };
@@ -1,26 +1,21 @@
1
- import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
2
- import {
3
- selectPeers,
4
- selectPeerScreenSharing,
5
- throwErrorHandler,
6
- useHMSStore,
7
- useScreenShare,
8
- } from '@100mslive/react-sdk';
1
+ import React, { useEffect, useMemo } from 'react';
2
+ import { selectAppData, selectPeers, selectPeerScreenSharing, useEmbedShare, useHMSStore } from '@100mslive/react-sdk';
9
3
  import { SecondaryTiles } from '../components/SecondaryTiles';
4
+ import { ToastManager } from '../components/Toast/ToastManager';
10
5
  import { ProminenceLayout } from '../components/VideoLayouts/ProminenceLayout';
11
6
  import { Box } from '../../Layout';
12
- import { useSetAppDataByKey } from '../components/AppData/useUISettings';
7
+ import { useResetEmbedConfig, useSetAppDataByKey } from '../components/AppData/useUISettings';
13
8
  import { APP_DATA } from '../common/constants';
14
9
 
15
10
  export const EmbedView = () => {
16
11
  return (
17
- <EmbebScreenShareView>
12
+ <EmbedScreenShareView>
18
13
  <EmbedComponent />
19
- </EmbebScreenShareView>
14
+ </EmbedScreenShareView>
20
15
  );
21
16
  };
22
17
 
23
- export const EmbebScreenShareView = ({ children }) => {
18
+ export const EmbedScreenShareView = ({ children }) => {
24
19
  const peers = useHMSStore(selectPeers);
25
20
 
26
21
  const peerPresenting = useHMSStore(selectPeerScreenSharing);
@@ -44,62 +39,54 @@ export const EmbebScreenShareView = ({ children }) => {
44
39
  </ProminenceLayout.Root>
45
40
  );
46
41
  };
47
-
42
+ /**
43
+ * EmbedView is responsible for rendering the iframe and managing the screen sharing functionality.
44
+ */
48
45
  const EmbedComponent = () => {
49
- const { amIScreenSharing, toggleScreenShare } = useScreenShare(throwErrorHandler);
50
- const [embedConfig, setEmbedConfig] = useSetAppDataByKey(APP_DATA.embedConfig);
51
- const [wasScreenShared, setWasScreenShared] = useState(false);
52
- // to handle - https://github.com/facebook/react/issues/24502
53
- const screenShareAttemptInProgress = useRef(false);
54
- const src = embedConfig.url;
55
- const iframeRef = useRef();
56
-
57
- const resetEmbedConfig = useCallback(() => {
58
- if (src) {
59
- setEmbedConfig({ url: '' });
60
- }
61
- }, [src, setEmbedConfig]);
46
+ const embedConfig = useHMSStore(selectAppData(APP_DATA.embedConfig));
47
+ const resetConfig = useResetEmbedConfig();
62
48
 
63
- useEffect(() => {
64
- if (embedConfig.shareScreen && !amIScreenSharing && !wasScreenShared && !screenShareAttemptInProgress.current) {
65
- screenShareAttemptInProgress.current = true;
66
- // start screenshare on load for others in the room to see
67
- toggleScreenShare({
68
- forceCurrentTab: true,
69
- cropElement: iframeRef.current,
70
- })
71
- .then(() => {
72
- setWasScreenShared(true);
73
- })
74
- .catch(resetEmbedConfig)
75
- .finally(() => {
76
- screenShareAttemptInProgress.current = false;
77
- });
78
- }
79
- // eslint-disable-next-line react-hooks/exhaustive-deps
80
- }, []);
49
+ // need to send resetConfig to clear configuration, if stop screenshare occurs.
50
+ const { iframeRef, startEmbedShare, isEmbedShareInProgress } = useEmbedShare(resetConfig);
81
51
 
82
52
  useEffect(() => {
83
- // reset embed when screenshare is closed from anywhere
84
- if (wasScreenShared && !amIScreenSharing) {
85
- resetEmbedConfig();
86
- }
87
- return () => {
88
- // close screenshare when this component is being unmounted
89
- if (wasScreenShared && amIScreenSharing) {
90
- resetEmbedConfig();
91
- toggleScreenShare(); // stop
53
+ (async () => {
54
+ if (embedConfig && !isEmbedShareInProgress) {
55
+ try {
56
+ await startEmbedShare(embedConfig);
57
+ } catch (err) {
58
+ resetConfig();
59
+ ToastManager.addToast({
60
+ title: `Error while sharing embed url ${err.message || ''}`,
61
+ variant: 'error',
62
+ });
63
+ }
92
64
  }
93
- };
94
- }, [wasScreenShared, amIScreenSharing, resetEmbedConfig, toggleScreenShare]);
65
+ })();
66
+ }, [isEmbedShareInProgress, embedConfig, startEmbedShare, resetConfig]);
95
67
 
96
68
  return (
97
- <Box ref={iframeRef} css={{ size: '100%' }}>
69
+ <Box
70
+ css={{
71
+ mx: '$8',
72
+ flex: '3 1 0',
73
+ '@lg': {
74
+ flex: '2 1 0',
75
+ display: 'flex',
76
+ alignItems: 'center',
77
+ },
78
+ }}
79
+ >
98
80
  <iframe
99
- src={src}
100
- title={src}
101
- style={{ width: '100%', height: '100%', border: 0 }}
102
- allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture fullscreen"
81
+ title="Embed View"
82
+ ref={iframeRef}
83
+ style={{
84
+ width: '100%',
85
+ height: '100%',
86
+ border: 0,
87
+ borderRadius: '0.75rem',
88
+ }}
89
+ allow="autoplay; clipboard-write;"
103
90
  referrerPolicy="no-referrer"
104
91
  />
105
92
  </Box>
@@ -1,111 +1,61 @@
1
- import React, { useCallback, useEffect, useRef, useState } from 'react';
2
- import { throwErrorHandler, useScreenShare } from '@100mslive/react-sdk';
1
+ import React, { useEffect } from 'react';
2
+ import { usePDFShare } from '@100mslive/react-sdk';
3
+ import { ToastManager } from '../components/Toast/ToastManager';
3
4
  import { Box } from '../../Layout';
4
- import { ThemeTypes, useTheme } from '../../Theme';
5
- import { EmbebScreenShareView } from './EmbedView';
6
- import { useSetAppDataByKey } from '../components/AppData/useUISettings';
7
- import { APP_DATA, isChrome } from '../common/constants';
5
+ import { EmbedScreenShareView } from './EmbedView';
6
+ import { usePDFConfig, useResetPDFConfig } from '../components/AppData/useUISettings';
8
7
 
8
+ /**
9
+ * PDFView is responsible for rendering the PDF iframe and managing the screen sharing functionality.
10
+ */
9
11
  export const PDFView = () => {
10
- return (
11
- <EmbebScreenShareView>
12
- <PDFEmbedComponent />
13
- </EmbebScreenShareView>
14
- );
15
- };
12
+ const pdfConfig = usePDFConfig();
13
+ const resetConfig = useResetPDFConfig();
16
14
 
17
- export const PDFEmbedComponent = () => {
18
- const ref = useRef();
19
- const themeType = useTheme().themeType;
20
- const [isPDFLoaded, setIsPDFLoaded] = useState(false);
21
- let pdfJSURL = process.env.REACT_APP_PDFJS_IFRAME_URL;
22
- const { amIScreenSharing, toggleScreenShare } = useScreenShare(throwErrorHandler);
23
- const [pdfConfig, setPDFConfig] = useSetAppDataByKey(APP_DATA.pdfConfig);
24
- if (pdfConfig.url && !pdfConfig.file) {
25
- pdfJSURL = pdfJSURL + '?file=' + encodeURIComponent(pdfConfig.url);
26
- }
27
- const [wasScreenShared, setWasScreenShared] = useState(false);
28
- // to handle - https://github.com/facebook/react/issues/24502
29
- const screenShareAttemptInProgress = useRef(false);
30
- const iframeRef = useRef();
15
+ // need to send resetConfig to clear configuration, if stop screenshare occurs.
16
+ const { iframeRef, startPDFShare, isPDFShareInProgress } = usePDFShare(resetConfig);
31
17
 
32
- const resetEmbedConfig = useCallback(() => {
33
- setPDFConfig({ state: false });
34
- }, [setPDFConfig]);
35
- useEffect(() => {
36
- if (isPDFLoaded && ref.current) {
37
- ref.current.contentWindow.postMessage(
38
- {
39
- theme: themeType === ThemeTypes.dark ? 2 : 1,
40
- },
41
- '*',
42
- );
43
- }
44
- }, [isPDFLoaded, themeType]);
45
18
  useEffect(() => {
46
- if (!amIScreenSharing && !wasScreenShared && !screenShareAttemptInProgress.current) {
47
- screenShareAttemptInProgress.current = true;
48
- // start screenshare on load for others in the room to see
49
- toggleScreenShare({
50
- forceCurrentTab: isChrome,
51
- cropElement: iframeRef.current,
52
- preferCurrentTab: isChrome,
53
- })
54
- .then(() => {
55
- setWasScreenShared(true);
56
- })
57
- .catch(resetEmbedConfig)
58
- .finally(() => {
59
- screenShareAttemptInProgress.current = false;
19
+ (async () => {
20
+ try {
21
+ if (!isPDFShareInProgress && pdfConfig) {
22
+ await startPDFShare(pdfConfig);
23
+ }
24
+ } catch (err) {
25
+ resetConfig();
26
+ ToastManager.addToast({
27
+ title: `Error while sharing annotator ${err.message || ''}`,
28
+ variant: 'error',
60
29
  });
61
- }
62
- // eslint-disable-next-line react-hooks/exhaustive-deps
63
- }, []);
64
-
65
- useEffect(() => {
66
- // reset embed when screenshare is closed from anywhere
67
- if (wasScreenShared && !amIScreenSharing) {
68
- resetEmbedConfig();
69
- }
70
- return () => {
71
- // close screenshare when this component is being unmounted
72
- if (wasScreenShared && amIScreenSharing) {
73
- resetEmbedConfig();
74
- toggleScreenShare(); // stop
75
30
  }
76
- };
77
- }, [wasScreenShared, amIScreenSharing, resetEmbedConfig, toggleScreenShare]);
78
-
31
+ })();
32
+ }, [isPDFShareInProgress, pdfConfig, resetConfig, startPDFShare]);
79
33
  return (
80
- <Box ref={iframeRef} css={{ size: '100%' }}>
81
- <iframe
82
- src={pdfJSURL}
83
- title="PDF Annotator"
84
- ref={ref}
85
- style={{
86
- width: '100%',
87
- height: '100%',
88
- border: 0,
89
- borderRadius: '0.75rem',
90
- }}
91
- allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture fullscreen"
92
- referrerPolicy="no-referrer"
93
- onLoad={() => {
94
- if (ref.current && pdfConfig.file) {
95
- // setting theme dark -> 2 and light -> 1
96
- requestAnimationFrame(() => {
97
- ref.current.contentWindow.postMessage(
98
- {
99
- file: pdfConfig.file,
100
- theme: themeType === ThemeTypes.dark ? 2 : 1,
101
- },
102
- '*',
103
- );
104
- setIsPDFLoaded(true);
105
- }, 1000);
106
- }
34
+ <EmbedScreenShareView>
35
+ <Box
36
+ css={{
37
+ mx: '$8',
38
+ flex: '3 1 0',
39
+ '@lg': {
40
+ flex: '2 1 0',
41
+ display: 'flex',
42
+ alignItems: 'center',
43
+ },
107
44
  }}
108
- />
109
- </Box>
45
+ >
46
+ <iframe
47
+ title="Embed View"
48
+ ref={iframeRef}
49
+ style={{
50
+ width: '100%',
51
+ height: '100%',
52
+ border: 0,
53
+ borderRadius: '0.75rem',
54
+ }}
55
+ allow="autoplay; clipboard-write;"
56
+ referrerPolicy="no-referrer"
57
+ />
58
+ </Box>
59
+ </EmbedScreenShareView>
110
60
  );
111
61
  };