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

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -1,19 +1,23 @@
1
1
  /* eslint-disable no-case-declarations */
2
2
  import React, { useCallback, useEffect } from 'react';
3
- import { useNavigate, useParams } from 'react-router-dom';
4
3
  import {
5
4
  HMSNotificationTypes,
5
+ HMSRoleChangeRequest,
6
6
  HMSRoomState,
7
7
  selectHasPeerHandRaised,
8
+ selectLocalPeerID,
9
+ selectPeerNameByID,
8
10
  selectRoomState,
9
11
  useCustomEvent,
10
12
  useHMSNotifications,
11
13
  useHMSStore,
12
14
  useHMSVanillaStore,
13
15
  } from '@100mslive/react-sdk';
14
- import { Button } from '../../../';
16
+ import { Button } from '../../..';
15
17
  import { useUpdateRoomLayout } from '../../provider/roomLayoutProvider';
18
+ // @ts-ignore: No implicit Any
16
19
  import { ToastBatcher } from '../Toast/ToastBatcher';
20
+ // @ts-ignore: No implicit Any
17
21
  import { ToastManager } from '../Toast/ToastManager';
18
22
  import { AutoplayBlockedModal } from './AutoplayBlockedModal';
19
23
  import { InitErrorModal } from './InitErrorModal';
@@ -23,22 +27,25 @@ import { ReconnectNotifications } from './ReconnectNotifications';
23
27
  import { TrackBulkUnmuteModal } from './TrackBulkUnmuteModal';
24
28
  import { TrackNotifications } from './TrackNotifications';
25
29
  import { TrackUnmuteModal } from './TrackUnmuteModal';
30
+ // @ts-ignore: No implicit Any
31
+ import { usePollViewToggle } from '../AppData/useSidepane';
32
+ // @ts-ignore: No implicit Any
26
33
  import { useIsNotificationDisabled, useSubscribedNotifications } from '../AppData/useUISettings';
27
- import { useRedirectToLeave } from '../hooks/useRedirectToLeave';
34
+ // @ts-ignore: No implicit Any
28
35
  import { getMetadata } from '../../common/utils';
36
+ // @ts-ignore: No implicit Any
29
37
  import { ROLE_CHANGE_DECLINED } from '../../common/constants';
30
38
  export function Notifications() {
39
+ const localPeerID = useHMSStore(selectLocalPeerID);
31
40
  const notification = useHMSNotifications();
32
- const navigate = useNavigate();
33
- const params = useParams();
34
41
  const subscribedNotifications = useSubscribedNotifications() || {};
35
42
  const roomState = useHMSStore(selectRoomState);
36
43
  const updateRoomLayoutForRole = useUpdateRoomLayout();
37
44
  const isNotificationDisabled = useIsNotificationDisabled();
38
- const { redirectToLeave } = useRedirectToLeave();
39
45
  const vanillaStore = useHMSVanillaStore();
46
+ const togglePollView = usePollViewToggle();
40
47
 
41
- const handleRoleChangeDenied = useCallback(request => {
48
+ const handleRoleChangeDenied = useCallback((request: HMSRoleChangeRequest & { peerName: string }) => {
42
49
  ToastManager.addToast({
43
50
  title: `${request.peerName} denied your request to join the ${request.role.name} role`,
44
51
  variant: 'error',
@@ -85,28 +92,13 @@ export function Notifications() {
85
92
  title: `Error: ${notification.data?.message}`,
86
93
  });
87
94
  } else {
88
- // show button action when the error is terminal
89
- const toastId = ToastManager.addToast({
95
+ ToastManager.addToast({
90
96
  title:
91
97
  notification.data?.message ||
92
98
  'We couldn’t reconnect you. When you’re back online, try joining the room.',
93
- inlineAction: true,
94
- action: (
95
- <Button
96
- onClick={() => {
97
- ToastManager.removeToast(toastId);
98
- navigate(`/${params.roomId}${params.role ? `/${params.role}` : ''}`);
99
- }}
100
- >
101
- Rejoin
102
- </Button>
103
- ),
104
99
  close: false,
105
100
  });
106
101
  }
107
- // goto leave for terminal if any action is not performed within 2secs
108
- // if network is still unavailable going to preview will throw an error
109
- redirectToLeave(1000);
110
102
  return;
111
103
  }
112
104
  // Autoplay error or user denied screen share (cancelled browser pop-up)
@@ -122,11 +114,11 @@ export function Notifications() {
122
114
  });
123
115
  break;
124
116
  case HMSNotificationTypes.ROLE_UPDATED: {
125
- if (notification.data?.isLocal) {
117
+ if (notification.data?.isLocal && notification.data?.roleName) {
126
118
  ToastManager.addToast({
127
119
  title: `You are now a ${notification.data.roleName}`,
128
120
  });
129
- updateRoomLayoutForRole(notification.data.roleName);
121
+ updateRoomLayoutForRole?.(notification.data.roleName);
130
122
  }
131
123
  break;
132
124
  }
@@ -145,13 +137,35 @@ export function Notifications() {
145
137
  title: `${notification.message}.
146
138
  ${notification.data.reason && `Reason: ${notification.data.reason}`}`,
147
139
  });
148
- redirectToLeave(1000);
149
140
  break;
150
141
  case HMSNotificationTypes.DEVICE_CHANGE_UPDATE:
151
142
  ToastManager.addToast({
152
143
  title: notification.message,
153
144
  });
154
145
  break;
146
+
147
+ case HMSNotificationTypes.POLL_STARTED:
148
+ if (notification.data.startedBy !== localPeerID) {
149
+ const pollStartedBy = vanillaStore.getState(selectPeerNameByID(notification.data.startedBy));
150
+ ToastManager.addToast({
151
+ title: `${pollStartedBy} started a ${notification.data.type}: ${notification.data.title}`,
152
+ action: (
153
+ <Button
154
+ onClick={() => togglePollView(notification.data.id)}
155
+ variant="standard"
156
+ css={{
157
+ backgroundColor: '$surface_bright',
158
+ fontWeight: '$semiBold',
159
+ color: '$on_surface_high',
160
+ p: '$xs $md',
161
+ }}
162
+ >
163
+ Vote
164
+ </Button>
165
+ ),
166
+ });
167
+ }
168
+ break;
155
169
  default:
156
170
  break;
157
171
  }
@@ -171,7 +185,7 @@ export function Notifications() {
171
185
  <ReconnectNotifications />
172
186
  <AutoplayBlockedModal />
173
187
  <PermissionErrorModal />
174
- <InitErrorModal notification={notification} />
188
+ <InitErrorModal />
175
189
  </>
176
190
  );
177
191
  }
@@ -1,7 +1,10 @@
1
1
  import { useEffect } from 'react';
2
2
  import { HMSNotificationTypes, useHMSNotifications } from '@100mslive/react-sdk';
3
+ // @ts-ignore: No implicit Any
3
4
  import { ToastBatcher } from '../Toast/ToastBatcher';
5
+ // @ts-ignore: No implicit Any
4
6
  import { useSubscribedNotifications } from '../AppData/useUISettings';
7
+ // @ts-ignore: No implicit Any
5
8
  import { SUBSCRIBED_NOTIFICATIONS } from '../../common/constants';
6
9
 
7
10
  const notificationTypes = [
@@ -1,10 +1,12 @@
1
1
  import React, { useEffect, useState } from 'react';
2
2
  import { useMedia } from 'react-use';
3
3
  import { HMSNotificationTypes, useHMSNotifications } from '@100mslive/react-sdk';
4
- import { Button, config as cssConfig, Dialog, Flex, Text } from '../../../';
4
+ import { Button, config as cssConfig, Dialog, Flex, Text } from '../../..';
5
+ // @ts-ignore: No implicit Any
5
6
  import androidPermissionAlert from '../../images/android-perm-1.png';
7
+ // @ts-ignore: No implicit Any
6
8
  import iosPermissions from '../../images/ios-perm-0.png';
7
- import { PrebuiltDialogPortal } from '../PrebuiltDialogPortal';
9
+ // @ts-ignore: No implicit Any
8
10
  import { isAndroid, isIOS } from '../../common/constants';
9
11
 
10
12
  export function PermissionErrorModal() {
@@ -40,7 +42,7 @@ export function PermissionErrorModal() {
40
42
 
41
43
  return deviceType ? (
42
44
  <Dialog.Root open={!!deviceType}>
43
- <PrebuiltDialogPortal>
45
+ <Dialog.Portal>
44
46
  <Dialog.Overlay />
45
47
  <Dialog.Content css={{ w: 'min(380px, 90%)', p: '$8' }}>
46
48
  <Dialog.Title
@@ -119,7 +121,7 @@ export function PermissionErrorModal() {
119
121
  </Flex>
120
122
  ) : null}
121
123
  </Dialog.Content>
122
- </PrebuiltDialogPortal>
124
+ </Dialog.Portal>
123
125
  </Dialog.Root>
124
126
  ) : null;
125
127
  }
@@ -1,7 +1,9 @@
1
1
  import React, { useEffect, useState } from 'react';
2
2
  import { HMSNotificationTypes, useHMSNotifications } from '@100mslive/react-sdk';
3
- import { Dialog, Flex, Loading, Text } from '../../../';
3
+ import { Dialog, Flex, Loading, Text } from '../../..';
4
+ // @ts-ignore: No implicit Any
4
5
  import { ToastConfig } from '../Toast/ToastConfig';
6
+ // @ts-ignore: No implicit Any
5
7
  import { ToastManager } from '../Toast/ToastManager';
6
8
 
7
9
  const notificationTypes = [
@@ -9,21 +11,24 @@ const notificationTypes = [
9
11
  HMSNotificationTypes.RECONNECTING,
10
12
  HMSNotificationTypes.ERROR,
11
13
  ];
12
- let notificationId = null;
14
+ let notificationId: string | null = null;
13
15
 
14
16
  export const ReconnectNotifications = () => {
15
17
  const notification = useHMSNotifications(notificationTypes);
16
18
  const [open, setOpen] = useState(false);
17
19
  useEffect(() => {
18
- if (notification?.type === HMSNotificationTypes.ERROR && notification?.data?.isTerminal) {
20
+ if (!notification) {
21
+ return;
22
+ }
23
+ if (notification.type === HMSNotificationTypes.ERROR && notification.data?.isTerminal) {
19
24
  setOpen(false);
20
- } else if (notification?.type === HMSNotificationTypes.RECONNECTED) {
25
+ } else if (notification.type === HMSNotificationTypes.RECONNECTED) {
21
26
  notificationId = ToastManager.replaceToast(notificationId, ToastConfig.RECONNECTED.single());
22
27
  setOpen(false);
23
- } else if (notification?.type === HMSNotificationTypes.RECONNECTING) {
28
+ } else if (notification.type === HMSNotificationTypes.RECONNECTING) {
24
29
  notificationId = ToastManager.replaceToast(
25
30
  notificationId,
26
- ToastConfig.RECONNECTING.single(notification.data.message),
31
+ ToastConfig.RECONNECTING.single(notification.data?.message),
27
32
  );
28
33
  }
29
34
  }, [notification]);
@@ -1,11 +1,17 @@
1
1
  import React, { useEffect, useState } from 'react';
2
- import { HMSNotificationTypes, useHMSActions, useHMSNotifications } from '@100mslive/react-sdk';
2
+ import {
3
+ HMSChangeMultiTrackStateRequest,
4
+ HMSNotificationTypes,
5
+ useHMSActions,
6
+ useHMSNotifications,
7
+ } from '@100mslive/react-sdk';
3
8
  import { MicOnIcon } from '@100mslive/react-icons';
9
+ // @ts-ignore: No implicit Any
4
10
  import { RequestDialog } from '../../primitives/DialogContent';
5
11
 
6
12
  export const TrackBulkUnmuteModal = () => {
7
13
  const hmsActions = useHMSActions();
8
- const [muteNotification, setMuteNotification] = useState(null);
14
+ const [muteNotification, setMuteNotification] = useState<HMSChangeMultiTrackStateRequest | null>(null);
9
15
  const notification = useHMSNotifications([
10
16
  HMSNotificationTypes.CHANGE_MULTI_TRACK_STATE_REQUEST,
11
17
  HMSNotificationTypes.ROOM_ENDED,
@@ -38,7 +44,7 @@ export const TrackBulkUnmuteModal = () => {
38
44
  <RequestDialog
39
45
  title="Track Unmute Request"
40
46
  body={`${peer?.name} has requested you to unmute your tracks.`}
41
- onOpenChange={value => !value && setMuteNotification(null)}
47
+ onOpenChange={(value: boolean) => !value && setMuteNotification(null)}
42
48
  onAction={() => {
43
49
  tracks.forEach(track => {
44
50
  hmsActions.setEnabledTrack(track.id, enabled);
@@ -1,6 +1,12 @@
1
1
  import React, { useEffect, useState } from 'react';
2
- import { HMSNotificationTypes, useHMSActions, useHMSNotifications } from '@100mslive/react-sdk';
2
+ import {
3
+ HMSChangeTrackStateRequest,
4
+ HMSNotificationTypes,
5
+ useHMSActions,
6
+ useHMSNotifications,
7
+ } from '@100mslive/react-sdk';
3
8
  import { MicOnIcon } from '@100mslive/react-icons';
9
+ // @ts-ignore: No implicit Any
4
10
  import { RequestDialog } from '../../primitives/DialogContent';
5
11
 
6
12
  export const TrackUnmuteModal = () => {
@@ -10,7 +16,7 @@ export const TrackUnmuteModal = () => {
10
16
  HMSNotificationTypes.ROOM_ENDED,
11
17
  HMSNotificationTypes.REMOVED_FROM_ROOM,
12
18
  ]);
13
- const [muteNotification, setMuteNotification] = useState(null);
19
+ const [muteNotification, setMuteNotification] = useState<HMSChangeTrackStateRequest | null>(null);
14
20
 
15
21
  useEffect(() => {
16
22
  switch (notification?.type) {
@@ -37,7 +43,7 @@ export const TrackUnmuteModal = () => {
37
43
  return (
38
44
  <RequestDialog
39
45
  title="Track Unmute Request"
40
- onOpenChange={value => !value && setMuteNotification(null)}
46
+ onOpenChange={(value: boolean) => !value && setMuteNotification(null)}
41
47
  body={`${peer?.name} has requested you to unmute your ${track?.source} ${track?.type}.`}
42
48
  onAction={() => {
43
49
  hmsActions.setEnabledTrack(track.id, enabled);
@@ -0,0 +1 @@
1
+ export { Notifications } from './Notifications';
@@ -0,0 +1,229 @@
1
+ // @ts-check
2
+ import React, { useMemo, useState } from 'react';
3
+ import {
4
+ selectLocalPeerRoleName,
5
+ selectPermissions,
6
+ selectPolls,
7
+ useHMSActions,
8
+ useHMSStore,
9
+ } from '@100mslive/react-sdk';
10
+ import { QuestionIcon, StatsIcon } from '@100mslive/react-icons';
11
+ import { Button, Flex, Input, Switch, Text } from '../../../../';
12
+ import { Container, ContentHeader, ErrorText } from '../../Streaming/Common';
13
+ import { usePollViewToggle } from '../../AppData/useSidepane';
14
+ import { usePollViewState } from '../../AppData/useUISettings';
15
+ import { isValidTextInput } from '../../../common/utils';
16
+ import { StatusIndicator } from '../common/StatusIndicator';
17
+ import { INTERACTION_TYPE, POLL_STATE, POLL_VIEWS } from '../../../common/constants';
18
+
19
+ export const PollsQuizMenu = () => {
20
+ const togglePollView = usePollViewToggle();
21
+ const permissions = useHMSStore(selectPermissions);
22
+
23
+ return (
24
+ <Container rounded>
25
+ <ContentHeader content="Polls and Quizzes" onClose={togglePollView} />
26
+ <Flex direction="column" css={{ px: '$10', pb: '$10', overflowY: 'auto' }}>
27
+ {permissions?.pollWrite && <AddMenu />}
28
+ <PrevMenu />
29
+ </Flex>
30
+ </Container>
31
+ );
32
+ };
33
+
34
+ function InteractionSelectionCard({ title, icon, active, onClick }) {
35
+ const activeBorderStyle = active ? '$space$px solid $primary_default' : '$space$px solid $border_bright';
36
+ return (
37
+ <Flex
38
+ onClick={onClick}
39
+ css={{
40
+ border: activeBorderStyle,
41
+ p: '$4',
42
+ r: '$2',
43
+ w: '100%',
44
+ cursor: 'pointer',
45
+ }}
46
+ align="center"
47
+ >
48
+ <Flex
49
+ css={{
50
+ border: activeBorderStyle,
51
+ p: '$4',
52
+ bg: '$surface_bright',
53
+ c: '$on_surface_high',
54
+ r: '$0',
55
+ }}
56
+ >
57
+ {icon}
58
+ </Flex>
59
+ <Text variant="sub1" css={{ ml: '$md' }}>
60
+ {title}
61
+ </Text>
62
+ </Flex>
63
+ );
64
+ }
65
+
66
+ const AddMenu = () => {
67
+ const actions = useHMSActions();
68
+ const [title, setTitle] = useState('');
69
+ const localPeerRoleName = useHMSStore(selectLocalPeerRoleName);
70
+ const [anonymous, setAnonymous] = useState(false);
71
+ const [hideVoteCount, setHideVoteCount] = useState(false);
72
+ const [error, setError] = useState();
73
+ const [titleError, setTitleError] = useState('');
74
+ const { setPollState } = usePollViewState();
75
+ const [interactionType, setInteractionType] = useState(INTERACTION_TYPE.POLL);
76
+
77
+ const handleCreate = id => {
78
+ setPollState({
79
+ [POLL_STATE.pollInView]: id,
80
+ [POLL_STATE.view]: POLL_VIEWS.CREATE_QUESTIONS,
81
+ });
82
+ };
83
+
84
+ const validateTitle = useMemo(() => {
85
+ if (!isValidTextInput(title)) {
86
+ if (title) {
87
+ setTitleError('The title should have between 2-100 characters');
88
+ }
89
+ return true;
90
+ } else {
91
+ setTitleError('');
92
+ return false;
93
+ }
94
+ }, [title]);
95
+ // const [timer, setTimer] = useState(10);
96
+ // const [showTimerDropDown, setShowTimerDropDown] = useState(false);
97
+
98
+ return (
99
+ <>
100
+ <Text variant="caption" css={{ c: '$on_surface_medium', mb: '$md' }}>
101
+ Select the type you want to continue with
102
+ </Text>
103
+ <Flex css={{ w: '100%', gap: '$10', mb: '$md' }}>
104
+ <InteractionSelectionCard
105
+ title={INTERACTION_TYPE.POLL}
106
+ icon={<StatsIcon width={32} height={32} />}
107
+ onClick={() => setInteractionType(INTERACTION_TYPE.POLL)}
108
+ active={interactionType === INTERACTION_TYPE.POLL}
109
+ />
110
+ <InteractionSelectionCard
111
+ title={INTERACTION_TYPE.QUIZ}
112
+ icon={<QuestionIcon width={32} height={32} />}
113
+ onClick={() => setInteractionType(INTERACTION_TYPE.QUIZ)}
114
+ active={interactionType === INTERACTION_TYPE.QUIZ}
115
+ />
116
+ </Flex>
117
+ <Flex direction="column">
118
+ <Text variant="body2" css={{ mb: '$4' }}>{`Name this ${interactionType.toLowerCase()}`}</Text>
119
+ <Input
120
+ type="text"
121
+ value={title}
122
+ onChange={event => setTitle(event.target.value)}
123
+ css={{
124
+ backgroundColor: '$surface_bright',
125
+ border: '1px solid $border_default',
126
+ }}
127
+ />
128
+ <Flex align="center" css={{ mt: '$10' }}>
129
+ <Switch onCheckedChange={value => setHideVoteCount(value)} css={{ mr: '$6' }} />
130
+ <Text variant="body2" css={{ c: '$on_surface_medium' }}>
131
+ Hide Vote Count
132
+ </Text>
133
+ </Flex>
134
+ <Flex align="center" css={{ mt: '$10' }}>
135
+ <Switch onCheckedChange={value => setAnonymous(value)} css={{ mr: '$6' }} />
136
+ <Text variant="body2" css={{ c: '$on_surface_medium' }}>
137
+ Make Results Anonymous
138
+ </Text>
139
+ </Flex>
140
+ {/* <Timer
141
+ timer={timer}
142
+ setTimer={setTimer}
143
+ showTimerDropDown={showTimerDropDown}
144
+ setShowTimerDropDown={setShowTimerDropDown}
145
+ /> */}
146
+
147
+ <Button
148
+ variant="primary"
149
+ disabled={validateTitle}
150
+ css={{ mt: '$10' }}
151
+ onClick={async () => {
152
+ const id = Date.now().toString();
153
+ await actions.interactivityCenter
154
+ .createPoll({
155
+ id,
156
+ title,
157
+ anonymous,
158
+ rolesThatCanViewResponses: hideVoteCount && localPeerRoleName ? [localPeerRoleName] : undefined,
159
+ type: interactionType.toLowerCase(),
160
+ // duration: showTimerDropDown ? timer : undefined,
161
+ })
162
+ .then(() => handleCreate(id))
163
+ .catch(err => setError(err.message));
164
+ }}
165
+ >
166
+ Create {interactionType}
167
+ </Button>
168
+ <ErrorText error={error || titleError} />
169
+ </Flex>
170
+ </>
171
+ );
172
+ };
173
+
174
+ const PrevMenu = () => {
175
+ const polls = useHMSStore(selectPolls)?.filter(poll => poll.state === 'started' || poll.state === 'stopped');
176
+ return polls?.length ? (
177
+ <Flex
178
+ css={{
179
+ borderTop: '$space$px solid $border_bright',
180
+ mt: '$10',
181
+ pt: '$10',
182
+ }}
183
+ >
184
+ <Flex direction="column" css={{ w: '100%' }}>
185
+ <Text variant="h6" css={{ c: '$on_surface_high' }}>
186
+ Previous Polls and Quizzes
187
+ </Text>
188
+ <Flex direction="column" css={{ gap: '$10', mt: '$8' }}>
189
+ {polls.map(poll => (
190
+ <InteractionCard
191
+ key={poll.id}
192
+ id={poll.id}
193
+ title={poll.title}
194
+ isLive={poll.state === 'started'}
195
+ isTimed={(poll.duration || 0) > 0}
196
+ />
197
+ ))}
198
+ </Flex>
199
+ </Flex>
200
+ </Flex>
201
+ ) : null;
202
+ };
203
+
204
+ const InteractionCard = ({ id, title, isLive, isTimed }) => {
205
+ const { setPollState } = usePollViewState();
206
+
207
+ const goToVote = id => {
208
+ setPollState({
209
+ [POLL_STATE.pollInView]: id,
210
+ [POLL_STATE.view]: POLL_VIEWS.VOTE,
211
+ });
212
+ };
213
+
214
+ return (
215
+ <Flex direction="column" css={{ backgroundColor: '$surface_bright', borderRadius: '$1', p: '$8' }}>
216
+ <Flex css={{ w: '100%', justifyContent: 'space-between', mb: '$sm' }}>
217
+ <Text variant="sub1" css={{ c: '$on_surface_high', fontWeight: '$semiBold' }}>
218
+ {title}
219
+ </Text>
220
+ <StatusIndicator isLive={isLive} shouldShowTimer={isLive && isTimed} />
221
+ </Flex>
222
+ <Flex css={{ w: '100%', gap: '$4' }} justify="end">
223
+ <Button variant="primary" onClick={() => goToVote(id)}>
224
+ View
225
+ </Button>
226
+ </Flex>
227
+ </Flex>
228
+ );
229
+ };
@@ -0,0 +1,71 @@
1
+ // @ts-check
2
+ import React, { useRef, useState } from 'react';
3
+ import { Dropdown, Flex, Switch, Text } from '../../../../';
4
+ import { DialogDropdownTrigger } from '../../../primitives/DropdownTrigger';
5
+ import { useDropdownSelection } from '../../hooks/useDropdownSelection';
6
+
7
+ const timerSettings = {
8
+ 10: '10 secs',
9
+ 15: '15 secs',
10
+ 20: '20 secs',
11
+ 25: '25 secs',
12
+ 30: '30 secs',
13
+ 60: '1 min',
14
+ 120: '2 mins',
15
+ 300: '5 mins',
16
+ };
17
+
18
+ export const Timer = ({ timer, setTimer, showTimerDropDown, setShowTimerDropDown }) => {
19
+ const selectionBg = useDropdownSelection();
20
+ const [timerDropdownToggle, setTimerDropdownToggle] = useState(false);
21
+ const timerDropdownRef = useRef();
22
+
23
+ return (
24
+ <Flex justify="between" align="center" css={{ mt: '$10' }}>
25
+ <Flex align="center">
26
+ <Switch checked={showTimerDropDown} onCheckedChange={setShowTimerDropDown} css={{ mr: '$6' }} />
27
+ <Text variant="body2" css={{ c: '$on_surface_medium' }}>
28
+ Timer
29
+ </Text>
30
+ </Flex>
31
+ <Flex align="center">
32
+ {showTimerDropDown ? (
33
+ <Dropdown.Root open={timerDropdownToggle} onOpenChange={setTimerDropdownToggle}>
34
+ <DialogDropdownTrigger
35
+ ref={timerDropdownRef}
36
+ title={timerSettings[timer]}
37
+ open={timerDropdownToggle}
38
+ titleCss={{ c: '$on_surface_high', ml: '$md' }}
39
+ />
40
+ <Dropdown.Portal>
41
+ <Dropdown.Content
42
+ align="start"
43
+ sideOffset={8}
44
+ css={{
45
+ w: timerDropdownRef.current?.clientWidth,
46
+ zIndex: 1000,
47
+ }}
48
+ >
49
+ {Object.keys(timerSettings).map(value => {
50
+ const val = parseInt(value);
51
+ return (
52
+ <Dropdown.Item
53
+ key={value}
54
+ onSelect={() => setTimer(val)}
55
+ css={{
56
+ px: '$9',
57
+ bg: timer === val ? selectionBg : undefined,
58
+ }}
59
+ >
60
+ {timerSettings[val]}
61
+ </Dropdown.Item>
62
+ );
63
+ })}
64
+ </Dropdown.Content>
65
+ </Dropdown.Portal>
66
+ </Dropdown.Root>
67
+ ) : null}
68
+ </Flex>
69
+ </Flex>
70
+ );
71
+ };