@100mslive/roomkit-react 0.3.19-alpha.2 → 0.3.19-alpha.20

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. package/dist/{HLSView-BRZ2FW7O.js → HLSView-I7EHD7WK.js} +2 -2
  2. package/dist/{HLSView-UXA322ED.css → HLSView-LUYYWC2J.css} +3 -3
  3. package/dist/{HLSView-UXA322ED.css.map → HLSView-LUYYWC2J.css.map} +1 -1
  4. package/dist/Modal/Dialog.d.ts +3 -1
  5. package/dist/Prebuilt/components/EndCallFeedback/Feedback.d.ts +2 -0
  6. package/dist/Prebuilt/components/EndCallFeedback/FeedbackForm.d.ts +28 -0
  7. package/dist/Prebuilt/components/EndCallFeedback/ThankyouView.d.ts +2 -0
  8. package/dist/Prebuilt/components/VirtualBackground/VBCollection.d.ts +1 -1
  9. package/dist/Prebuilt/components/VirtualBackground/VBHandler.d.ts +6 -6
  10. package/dist/Prebuilt/provider/roomLayoutProvider/hooks/useRoomLayoutScreen.d.ts +1 -0
  11. package/dist/{chunk-KR2DZJO5.js → chunk-RJ3RESWY.js} +1363 -831
  12. package/dist/chunk-RJ3RESWY.js.map +7 -0
  13. package/dist/index.cjs.css +2 -2
  14. package/dist/index.cjs.css.map +1 -1
  15. package/dist/index.cjs.js +1849 -1291
  16. package/dist/index.cjs.js.map +4 -4
  17. package/dist/index.css +2 -2
  18. package/dist/index.css.map +1 -1
  19. package/dist/index.js +1 -1
  20. package/dist/meta.cjs.json +323 -90
  21. package/dist/meta.esbuild.json +334 -101
  22. package/package.json +8 -8
  23. package/src/Modal/Dialog.tsx +13 -2
  24. package/src/Prebuilt/App.tsx +3 -0
  25. package/src/Prebuilt/AppStateContext.tsx +1 -2
  26. package/src/Prebuilt/Prebuilt.stories.tsx +1 -0
  27. package/src/Prebuilt/common/PeersSorter.ts +2 -1
  28. package/src/Prebuilt/components/EndCallFeedback/Feedback.tsx +71 -0
  29. package/src/Prebuilt/components/EndCallFeedback/FeedbackForm.tsx +381 -0
  30. package/src/Prebuilt/components/EndCallFeedback/ThankyouView.tsx +44 -0
  31. package/src/Prebuilt/components/LeaveScreen.tsx +2 -0
  32. package/src/Prebuilt/components/PIP/PIPChat.tsx +11 -4
  33. package/src/Prebuilt/components/VideoLayouts/RoleProminence.tsx +2 -9
  34. package/src/Prebuilt/components/VirtualBackground/VBCollection.tsx +3 -1
  35. package/src/Prebuilt/components/VirtualBackground/VBHandler.tsx +26 -4
  36. package/src/Prebuilt/components/VirtualBackground/VBPicker.tsx +58 -38
  37. package/src/Prebuilt/components/VirtualBackground/VBToggle.tsx +2 -1
  38. package/src/Prebuilt/plugins/CaptionsViewer.tsx +4 -1
  39. package/src/Prebuilt/provider/roomLayoutProvider/hooks/useRoomLayoutScreen.ts +1 -0
  40. package/dist/Prebuilt/components/VirtualBackground/util.d.ts +0 -1
  41. package/dist/chunk-KR2DZJO5.js.map +0 -7
  42. package/src/Prebuilt/components/VirtualBackground/util.tsx +0 -13
  43. /package/dist/{HLSView-BRZ2FW7O.js.map → HLSView-I7EHD7WK.js.map} +0 -0
package/package.json CHANGED
@@ -10,7 +10,7 @@
10
10
  "prebuilt",
11
11
  "roomkit"
12
12
  ],
13
- "version": "0.3.19-alpha.2",
13
+ "version": "0.3.19-alpha.20",
14
14
  "author": "100ms",
15
15
  "license": "MIT",
16
16
  "repository": {
@@ -75,13 +75,13 @@
75
75
  "react": ">=17.0.2 <19.0.0"
76
76
  },
77
77
  "dependencies": {
78
- "@100mslive/hls-player": "0.3.19-alpha.2",
78
+ "@100mslive/hls-player": "0.3.19-alpha.20",
79
79
  "@100mslive/hms-noise-cancellation": "0.0.1",
80
- "@100mslive/hms-virtual-background": "1.13.19-alpha.2",
81
- "@100mslive/hms-whiteboard": "0.0.9-alpha.2",
82
- "@100mslive/react-icons": "0.10.19-alpha.2",
83
- "@100mslive/react-sdk": "0.10.19-alpha.2",
84
- "@100mslive/types-prebuilt": "0.12.11",
80
+ "@100mslive/hms-virtual-background": "1.13.19-alpha.20",
81
+ "@100mslive/hms-whiteboard": "0.0.9-alpha.20",
82
+ "@100mslive/react-icons": "0.10.19-alpha.20",
83
+ "@100mslive/react-sdk": "0.10.19-alpha.20",
84
+ "@100mslive/types-prebuilt": "0.12.12",
85
85
  "@emoji-mart/data": "^1.0.6",
86
86
  "@emoji-mart/react": "^1.0.1",
87
87
  "@radix-ui/react-accordion": "1.0.0",
@@ -117,5 +117,5 @@
117
117
  "uuid": "^8.3.2",
118
118
  "worker-timers": "^7.0.40"
119
119
  },
120
- "gitHead": "88c8ac68235961d5352322c7be3efedad27f6d92"
120
+ "gitHead": "c9675947ac0d32c0381fc04effd2149a8d938501"
121
121
  }
@@ -1,4 +1,4 @@
1
- import React, { ReactNode, useRef } from 'react';
1
+ import React, { ReactNode, useEffect, useRef } from 'react';
2
2
  import { Root } from '@radix-ui/react-dialog';
3
3
  import { styled } from '@stitches/react';
4
4
  import {
@@ -15,6 +15,17 @@ import { useDialogContainerSelector } from '../hooks/useDialogContainerSelector'
15
15
 
16
16
  const StyledDialog = styled(Root, {});
17
17
 
18
+ // Handles race conditions when multiple elements with dismissable layer are present
19
+ // https://github.com/radix-ui/primitives/issues/2122
20
+ const DialogRoot = <T extends React.ComponentProps<typeof StyledDialog>>(props: T) => {
21
+ useEffect(() => {
22
+ return () => {
23
+ if (document) setTimeout(() => (document.body.style.pointerEvents = 'auto'), 0);
24
+ };
25
+ }, []);
26
+ return <StyledDialog {...(props as object)} />;
27
+ };
28
+
18
29
  const CustomDialogPortal = ({ children, container }: { children: ReactNode; container?: HTMLElement | null }) => {
19
30
  const dialogContainerSelector = useDialogContainerSelector();
20
31
  const containerRef = useRef<HTMLElement | null>(null);
@@ -34,7 +45,7 @@ const CustomDialogPortal = ({ children, container }: { children: ReactNode; cont
34
45
  };
35
46
 
36
47
  export const Dialog = {
37
- Root: StyledDialog,
48
+ Root: DialogRoot,
38
49
  Trigger: StyledDialogTrigger,
39
50
  Overlay: CustomDialogOverlay,
40
51
  Content: CustomDialogContent,
@@ -140,10 +140,12 @@ export const HMSPrebuilt = React.forwardRef<HMSPrebuiltRefType, HMSPrebuiltProps
140
140
  init: string;
141
141
  tokenByRoomCode: string;
142
142
  roomLayout: string;
143
+ event: string;
143
144
  }
144
145
  | undefined;
145
146
  const tokenByRoomCodeEndpoint: string = endpointsObj?.tokenByRoomCode || '';
146
147
  const initEndpoint: string = endpointsObj?.init || '';
148
+ const eventEndpoint: string = endpointsObj?.event || '';
147
149
  const roomLayoutEndpoint: string = endpointsObj?.roomLayout || '';
148
150
 
149
151
  const overrideLayout: Partial<Layout> = {
@@ -182,6 +184,7 @@ export const HMSPrebuilt = React.forwardRef<HMSPrebuiltRefType, HMSPrebuiltProps
182
184
  tokenByRoomCode: tokenByRoomCodeEndpoint,
183
185
  init: initEndpoint,
184
186
  roomLayout: roomLayoutEndpoint,
187
+ event: eventEndpoint,
185
188
  },
186
189
  }}
187
190
  >
@@ -84,7 +84,6 @@ export const useAppStateManager = () => {
84
84
  .otherwise(() => {
85
85
  // do nothing
86
86
  });
87
- }, [roomLayout, roomState, isLeaveScreenEnabled, isPreviewScreenEnabled, prevRoomState, redirectToLeave, hmsActions]);
88
-
87
+ }, [roomLayout, roomState, isLeaveScreenEnabled, isPreviewScreenEnabled, prevRoomState, redirectToLeave]);
89
88
  return { activeState, rejoin };
90
89
  };
@@ -28,6 +28,7 @@ const endpoints: HMSPrebuiltOptions['endpoints'] = {
28
28
  roomLayout: process.env.STORYBOOK_ROOM_LAYOUT_ENDPOINT,
29
29
  tokenByRoomCode: process.env.STORYBOOK_TOKEN_BY_ROOM_CODE_ENDPOINT,
30
30
  init: process.env.STORYBOOK_INIT_API_ENDPOINT,
31
+ event: process.env.STORYBOOK_EVENT_API_ENDPOINT,
31
32
  };
32
33
 
33
34
  const hasEndpoints = Object.values(endpoints).some(val => !!val);
@@ -7,13 +7,14 @@ class PeersSorter {
7
7
  lruPeers: Set<HMSPeerID>;
8
8
  tilesPerPage!: number;
9
9
  speaker?: HMSPeer;
10
- listeners: Set<(peers: HMSPeer[]) => void> = new Set();
10
+ listeners: Set<(peers: HMSPeer[]) => void>;
11
11
 
12
12
  constructor(store: IStoreReadOnly<any>) {
13
13
  this.store = store;
14
14
  this.peers = new Map();
15
15
  this.lruPeers = new Set();
16
16
  this.speaker = undefined;
17
+ this.listeners = new Set();
17
18
  }
18
19
 
19
20
  setPeersAndTilesPerPage = ({ peers, tilesPerPage }: { peers: HMSPeer[]; tilesPerPage: number }) => {
@@ -0,0 +1,71 @@
1
+ import React, { useState } from 'react';
2
+ import { useMedia } from 'react-use';
3
+ import { Flex } from '../../../Layout';
4
+ import { config as cssConfig } from '../../../Theme';
5
+ import { FEEBACK_INDEX, FeedbackHeader, FeedbackModal } from './FeedbackForm';
6
+ import { ThankyouView } from './ThankyouView';
7
+ import { useRoomLayoutLeaveScreen } from '../../provider/roomLayoutProvider/hooks/useRoomLayoutScreen';
8
+
9
+ export const Feedback = () => {
10
+ const { feedback } = useRoomLayoutLeaveScreen();
11
+ const [index, setIndex] = useState(FEEBACK_INDEX.INIT);
12
+ const isMobile = useMedia(cssConfig.media.md);
13
+
14
+ if (!feedback) {
15
+ return null;
16
+ }
17
+ const { ratings } = feedback;
18
+ if (!ratings) {
19
+ return null;
20
+ }
21
+ ratings.sort((a, b) => {
22
+ if (!a.value || !b.value) {
23
+ return 0;
24
+ }
25
+ return a.value - b.value;
26
+ });
27
+ // TO show thank ypu page
28
+ if (index === FEEBACK_INDEX.THANK_YOU) {
29
+ return (
30
+ <Flex
31
+ justify="center"
32
+ css={{
33
+ pt: '$16',
34
+ }}
35
+ >
36
+ <ThankyouView />
37
+ </Flex>
38
+ );
39
+ }
40
+ return (
41
+ <Flex
42
+ justify="center"
43
+ css={{
44
+ pt: '$16',
45
+ w: '528px',
46
+ }}
47
+ >
48
+ {index === FEEBACK_INDEX.INIT ? (
49
+ <Flex
50
+ css={{
51
+ p: isMobile ? '$10' : '$12',
52
+ border: '1px solid $border_default',
53
+ bg: '$surface_dim',
54
+ borderRadius: !isMobile ? '$3' : '$3 $3 0 0',
55
+ gap: '$10',
56
+ '@md': {
57
+ position: 'absolute',
58
+ bottom: '0',
59
+ w: '100%',
60
+ },
61
+ }}
62
+ direction="column"
63
+ >
64
+ <FeedbackHeader ratings={ratings} onEmojiClicked={setIndex} />
65
+ </Flex>
66
+ ) : (
67
+ <FeedbackModal ratings={ratings} index={index} setIndex={setIndex} />
68
+ )}
69
+ </Flex>
70
+ );
71
+ };
@@ -0,0 +1,381 @@
1
+ import React, { useState } from 'react';
2
+ import { useMedia } from 'react-use';
3
+ import { Rating } from '@100mslive/types-prebuilt/elements/feedback';
4
+ import { useHMSActions } from '@100mslive/react-sdk';
5
+ import { CheckIcon, CrossIcon } from '@100mslive/react-icons';
6
+ import { Button } from '../../../Button';
7
+ import { Checkbox } from '../../../Checkbox';
8
+ import { Label } from '../../../Label';
9
+ import { Flex } from '../../../Layout';
10
+ import { Dialog } from '../../../Modal';
11
+ import { Sheet } from '../../../Sheet';
12
+ import { Text } from '../../../Text';
13
+ import { TextArea } from '../../../TextArea';
14
+ import { config as cssConfig } from '../../../Theme';
15
+ import { useHMSPrebuiltContext } from '../../AppContext';
16
+ import { useRoomLayoutLeaveScreen } from '../../provider/roomLayoutProvider/hooks/useRoomLayoutScreen';
17
+
18
+ export const FEEBACK_INDEX = {
19
+ THANK_YOU: -10,
20
+ INIT: -1,
21
+ };
22
+ export const FeedbackModal = ({
23
+ ratings,
24
+ index,
25
+ setIndex,
26
+ }: {
27
+ ratings: Rating[];
28
+ index: number;
29
+ setIndex: (index: number) => void;
30
+ }) => {
31
+ const isMobile = useMedia(cssConfig.media.md);
32
+ const onOpenChange = () => {
33
+ setIndex(FEEBACK_INDEX.INIT);
34
+ };
35
+ const avoidDefaultDomBehavior = (e: Event) => {
36
+ e.preventDefault();
37
+ };
38
+ if (isMobile) {
39
+ return (
40
+ <Sheet.Root open={index !== FEEBACK_INDEX.INIT} onOpenChange={onOpenChange}>
41
+ <Sheet.Content
42
+ css={{ bg: '$surface_dim', p: '$10' }}
43
+ onPointerDownOutside={avoidDefaultDomBehavior}
44
+ onInteractOutside={avoidDefaultDomBehavior}
45
+ >
46
+ <FeedbackContent ratings={ratings} indexSelected={index} setIndex={setIndex} />
47
+ </Sheet.Content>
48
+ </Sheet.Root>
49
+ );
50
+ }
51
+ return (
52
+ <Dialog.Root open={index !== FEEBACK_INDEX.INIT} onOpenChange={onOpenChange}>
53
+ <Dialog.Portal>
54
+ <Dialog.Overlay />
55
+ <Dialog.Content
56
+ css={{ bg: '$surface_dim', width: '528px', p: '$12' }}
57
+ onPointerDownOutside={avoidDefaultDomBehavior}
58
+ onInteractOutside={avoidDefaultDomBehavior}
59
+ >
60
+ <FeedbackContent ratings={ratings} indexSelected={index} setIndex={setIndex} />
61
+ </Dialog.Content>
62
+ </Dialog.Portal>
63
+ </Dialog.Root>
64
+ );
65
+ };
66
+
67
+ export const FeedbackContent = ({
68
+ ratings,
69
+ indexSelected,
70
+ setIndex,
71
+ }: {
72
+ ratings: Rating[];
73
+ indexSelected: number;
74
+ setIndex: (index: number) => void;
75
+ }) => {
76
+ const { feedback } = useRoomLayoutLeaveScreen();
77
+ const { endpoints } = useHMSPrebuiltContext();
78
+ const isMobile = useMedia(cssConfig.media.md);
79
+ const hmsActions = useHMSActions();
80
+ const [comment, setComment] = useState('');
81
+ const [selectedReasons, setSelectedReasons] = useState(new Set<number>());
82
+ const handleCheckedChange = (checked: boolean | string, index: number) => {
83
+ const newSelected = new Set(selectedReasons);
84
+ if (checked) {
85
+ newSelected.add(index);
86
+ } else {
87
+ newSelected.delete(index);
88
+ }
89
+ setSelectedReasons(newSelected);
90
+ };
91
+ const submitFeedback = async () => {
92
+ if (indexSelected < 0 || ratings.length <= indexSelected) {
93
+ return;
94
+ }
95
+ try {
96
+ const reasons = [...selectedReasons].map((value: number) => ratings[indexSelected]?.reasons?.[value] || '');
97
+ await hmsActions.submitSessionFeedback(
98
+ {
99
+ question: `${feedback?.title} | ${ratings[indexSelected].question || ''}`,
100
+ rating: ratings[indexSelected].value || 1,
101
+ min_rating: 1,
102
+ max_rating: ratings.length,
103
+ reasons: selectedReasons.size === 0 ? [] : reasons,
104
+ comment: comment,
105
+ },
106
+ endpoints?.event,
107
+ );
108
+ } catch (e) {
109
+ console.error(e);
110
+ }
111
+ // always submit and take it to thankyou page
112
+ setIndex(FEEBACK_INDEX.THANK_YOU);
113
+ };
114
+ return (
115
+ <Flex
116
+ css={{
117
+ p: indexSelected === FEEBACK_INDEX.INIT ? '$12 !important' : '0',
118
+ bg: '$surface_dim',
119
+ r: '$3',
120
+ gap: '$10',
121
+ }}
122
+ direction="column"
123
+ >
124
+ <FeedbackHeader
125
+ ratings={ratings}
126
+ indexSelected={indexSelected}
127
+ onEmojiClicked={(value: number) => {
128
+ setSelectedReasons(new Set<number>());
129
+ setIndex(value);
130
+ }}
131
+ />
132
+ <FeedbackForm
133
+ rating={ratings[indexSelected]}
134
+ comment={comment}
135
+ setComment={setComment}
136
+ selectedReasons={selectedReasons}
137
+ handleCheckedChange={handleCheckedChange}
138
+ />
139
+ <Button
140
+ type="submit"
141
+ icon
142
+ css={{
143
+ alignSelf: isMobile ? '' : 'end',
144
+ }}
145
+ onClick={submitFeedback}
146
+ >
147
+ {feedback?.submit_btn_label || 'Submit Feedback'}
148
+ </Button>
149
+ </Flex>
150
+ );
151
+ };
152
+ export const FeedbackHeader = ({
153
+ onEmojiClicked,
154
+ ratings,
155
+ indexSelected = FEEBACK_INDEX.INIT,
156
+ }: {
157
+ onEmojiClicked: (index: number) => void;
158
+ ratings: Rating[];
159
+ indexSelected?: number;
160
+ }) => {
161
+ const isMobile = useMedia(cssConfig.media.md);
162
+ const { feedback } = useRoomLayoutLeaveScreen();
163
+ return (
164
+ <>
165
+ <Flex align="center">
166
+ <Flex
167
+ direction="column"
168
+ css={{
169
+ flex: '1 1 0',
170
+ }}
171
+ >
172
+ <Text
173
+ variant={isMobile ? 'h6' : 'h5'}
174
+ css={{
175
+ c: '$on_surface_high',
176
+ fontStyle: 'normal',
177
+ }}
178
+ >
179
+ {feedback?.title || 'How was your experience?'}
180
+ </Text>
181
+ <Text
182
+ variant={isMobile ? 'body2' : 'body1'}
183
+ css={{
184
+ c: '$on_surface_medium',
185
+ opacity: 0.9,
186
+ fontWeight: '$regular',
187
+ }}
188
+ >
189
+ {feedback?.sub_title || 'Your answers help us improve the quality.'}
190
+ </Text>
191
+ </Flex>
192
+ {indexSelected !== FEEBACK_INDEX.INIT ? (
193
+ <CrossIcon width="24px" height="24px" color="white" onClick={() => onEmojiClicked(FEEBACK_INDEX.INIT)} />
194
+ ) : null}
195
+ </Flex>
196
+ <Flex
197
+ justify="between"
198
+ css={{
199
+ gap: '$17',
200
+ c: '$on_surface_high',
201
+ '@md': {
202
+ gap: '0',
203
+ },
204
+ }}
205
+ >
206
+ {ratings.map((element, index) => {
207
+ return (
208
+ <Flex
209
+ align="center"
210
+ direction="column"
211
+ css={{
212
+ c:
213
+ indexSelected === index || indexSelected === FEEBACK_INDEX.INIT
214
+ ? '$on_surface_high'
215
+ : '$on_surface_default',
216
+ gap: '$4',
217
+ }}
218
+ onClick={() => onEmojiClicked(index)}
219
+ key={`${index}`}
220
+ >
221
+ <Text
222
+ css={{
223
+ fontWeight: '$semiBold',
224
+ fontSize: '$h4',
225
+ pb: '$1',
226
+ cursor: 'pointer',
227
+ opacity: indexSelected === index || indexSelected === FEEBACK_INDEX.INIT ? 1 : 0.2,
228
+ '@md': {
229
+ fontSize: '$h5',
230
+ },
231
+ }}
232
+ >
233
+ {element.emoji}
234
+ </Text>
235
+ <Text
236
+ variant={isMobile ? 'body2' : 'body1'}
237
+ css={{
238
+ c:
239
+ indexSelected === index || indexSelected === FEEBACK_INDEX.INIT
240
+ ? '$on_surface_medium'
241
+ : '$on_surface_low',
242
+ fontWeight: '$regular',
243
+ }}
244
+ >
245
+ {element.label}
246
+ </Text>
247
+ </Flex>
248
+ );
249
+ })}
250
+ </Flex>
251
+ </>
252
+ );
253
+ };
254
+ export const FeedbackForm = ({
255
+ rating,
256
+ comment,
257
+ setComment,
258
+ selectedReasons,
259
+ handleCheckedChange,
260
+ }: {
261
+ rating: Rating;
262
+ comment: string;
263
+ setComment: (value: string) => void;
264
+ selectedReasons: Set<number>;
265
+ handleCheckedChange: (checked: string | boolean, index: number) => void;
266
+ }) => {
267
+ const { feedback } = useRoomLayoutLeaveScreen();
268
+ return (
269
+ <>
270
+ {rating.reasons && rating.reasons.length > 0 && (
271
+ <Flex
272
+ direction="column"
273
+ css={{
274
+ gap: '$4',
275
+ }}
276
+ >
277
+ <Text
278
+ variant="sub2"
279
+ css={{
280
+ c: '$on_surface_high',
281
+ fontWeight: '$semiBold',
282
+ fontSize: '$sm',
283
+ px: '$2',
284
+ }}
285
+ >
286
+ {rating.question || 'What do you like/dislike here?'}
287
+ </Text>
288
+ <Flex
289
+ css={{
290
+ alignItems: 'flex-start',
291
+ alignSelf: 'stretch',
292
+ flexWrap: 'wrap',
293
+ gap: '$6',
294
+ flex: '1 1 calc(25% - 12px)',
295
+ '@md': {
296
+ flex: '1 1 calc(50% - 12px)',
297
+ },
298
+ '@sm': {
299
+ flex: '1 1 100%',
300
+ },
301
+ }}
302
+ >
303
+ {rating.reasons.map((option: string, index: number) => {
304
+ return (
305
+ <Flex
306
+ align="center"
307
+ gap="2"
308
+ key={index}
309
+ css={{
310
+ border: '1px solid $border_bright',
311
+ r: '$1',
312
+ p: '$6',
313
+ }}
314
+ >
315
+ <Checkbox.Root
316
+ id={`${option}-${index}`}
317
+ checked={selectedReasons.has(index)}
318
+ onCheckedChange={checked => handleCheckedChange(checked, index)}
319
+ css={{
320
+ cursor: 'pointer',
321
+ flexShrink: 0,
322
+ bg: '$on_secondary_low',
323
+ border: '1px solid $border_bright',
324
+ }}
325
+ >
326
+ <Checkbox.Indicator>
327
+ <CheckIcon width={12} height={12} />
328
+ </Checkbox.Indicator>
329
+ </Checkbox.Root>
330
+ <Label
331
+ htmlFor={`${option}-${index}`}
332
+ css={{
333
+ color: '$on_surface_high',
334
+ fontSize: '$sm',
335
+ fontWeight: '$regular',
336
+ lineHeight: '20px' /* 142.857% */,
337
+ }}
338
+ >
339
+ {option}
340
+ </Label>
341
+ </Flex>
342
+ );
343
+ })}
344
+ </Flex>
345
+ </Flex>
346
+ )}
347
+ {feedback?.comment && (
348
+ <Flex
349
+ direction="column"
350
+ css={{
351
+ gap: '$4',
352
+ }}
353
+ >
354
+ <Text
355
+ variant="body2"
356
+ css={{
357
+ c: '$on_surface_high',
358
+ fontWeight: '$regular',
359
+ fontSize: '$sm',
360
+ }}
361
+ >
362
+ {feedback?.comment.label || 'Additional comments (optional)'}
363
+ </Text>
364
+ <TextArea
365
+ maxLength={1024}
366
+ placeholder={feedback?.comment.placeholder || 'Tell us more...'}
367
+ css={{
368
+ backgroundColor: '$surface_bright',
369
+ border: '1px solid $border_bright',
370
+ resize: 'none',
371
+ height: '$36',
372
+ display: 'flex',
373
+ }}
374
+ value={comment}
375
+ onChange={event => setComment(event.target.value.trimStart())}
376
+ />
377
+ </Flex>
378
+ )}
379
+ </>
380
+ );
381
+ };
@@ -0,0 +1,44 @@
1
+ import React from 'react';
2
+ import { useMedia } from 'react-use';
3
+ import { UserMusicIcon } from '@100mslive/react-icons';
4
+ import { Flex } from '../../../Layout';
5
+ import { Text } from '../../../Text';
6
+ import { config as cssConfig } from '../../../Theme';
7
+
8
+ export const ThankyouView = () => {
9
+ const isMobile = useMedia(cssConfig.media.md);
10
+ return (
11
+ <Flex
12
+ direction={isMobile ? 'column' : 'row'}
13
+ align="center"
14
+ css={{
15
+ gap: '$10',
16
+ border: '1px solid $border_default',
17
+ borderRadius: !isMobile ? '$3' : '$3 $3 0 0',
18
+ bg: '$surface_dim',
19
+ w: !isMobile ? '528px' : '410px',
20
+ p: '$12',
21
+ pb: isMobile ? '$16' : '$12',
22
+ '@md': {
23
+ position: 'absolute',
24
+ bottom: '0',
25
+ },
26
+ }}
27
+ >
28
+ <UserMusicIcon width="64px" height="64px" />
29
+ <Flex direction="column" align={isMobile ? 'center' : 'start'}>
30
+ <Text variant="h5">Thank you for your feedback</Text>
31
+ <Text
32
+ variant="body1"
33
+ css={{
34
+ fontWeight: '$regular',
35
+ fontSize: '$md',
36
+ opacity: '0.9',
37
+ }}
38
+ >
39
+ Your answers help us improve.
40
+ </Text>
41
+ </Flex>
42
+ </Flex>
43
+ );
44
+ };
@@ -1,5 +1,6 @@
1
1
  import React from 'react';
2
2
  import { ExitIcon } from '@100mslive/react-icons';
3
+ import { Feedback } from './EndCallFeedback/Feedback';
3
4
  // @ts-ignore: No implicit Any
4
5
  import { ToastManager } from './Toast/ToastManager';
5
6
  import { Button } from '../../Button';
@@ -63,6 +64,7 @@ export const LeaveScreen = () => {
63
64
  <Text css={{ ml: '$3', fontWeight: '$semiBold', color: 'inherit' }}>Rejoin</Text>
64
65
  </Button>
65
66
  </Flex>
67
+ <Feedback />
66
68
  </Flex>
67
69
  </Flex>
68
70
  );
@@ -50,7 +50,10 @@ export const PIPChat = () => {
50
50
  const isLocalPeerBlacklisted = useIsPeerBlacklisted({ local: true });
51
51
  const { elements } = useRoomLayoutConferencingScreen();
52
52
  const message_placeholder = elements?.chat?.message_placeholder || 'Send a message';
53
- const canSendChatMessages = !!elements?.chat?.public_chat_enabled || !!elements?.chat?.roles_whitelist?.length;
53
+ const canSendChatMessages =
54
+ !!elements?.chat?.public_chat_enabled ||
55
+ !!elements?.chat?.roles_whitelist?.length ||
56
+ !!elements?.chat?.private_chat_enabled;
54
57
 
55
58
  const getChatStatus = useCallback(() => {
56
59
  if (isLocalPeerBlacklisted) return "You've been blocked from sending messages";
@@ -114,9 +117,13 @@ export const PIPChat = () => {
114
117
  <Text variant="h5" css={{ mt: '$8', c: '$on_surface_high' }}>
115
118
  {canSendChatMessages ? 'Start a conversation' : 'No messages yet'}
116
119
  </Text>
117
- <Text variant="sm" style={{ maxWidth: '80%', textAlign: 'center', marginTop: '4px' }}>
118
- There are no messages here yet. Start a conversation by sending a message.
119
- </Text>
120
+ {canSendChatMessages ? (
121
+ <Text variant="sm" style={{ maxWidth: '80%', textAlign: 'center', marginTop: '4px' }}>
122
+ There are no messages here yet. Start a conversation by sending a message.
123
+ </Text>
124
+ ) : (
125
+ ''
126
+ )}
120
127
  </div>
121
128
  ) : (
122
129
  filteredMessages.map(message => (