@100mslive/roomkit-react 0.2.1-alpha.2 → 0.2.2-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 (33) hide show
  1. package/dist/{HLSView-S5JHEMWJ.js → HLSView-4TLGLPKO.js} +19 -4
  2. package/dist/HLSView-4TLGLPKO.js.map +7 -0
  3. package/dist/Prebuilt/components/Polls/Voting/LeaderboardEntry.d.ts +2 -1
  4. package/dist/Prebuilt/components/RoleChangeRequest/RequestPrompt.d.ts +2 -1
  5. package/dist/Prebuilt/components/VirtualBackground/VBHandler.d.ts +1 -0
  6. package/dist/{chunk-AWWYBQSE.js → chunk-ARSLHHAZ.js} +176 -159
  7. package/dist/{chunk-AWWYBQSE.js.map → chunk-ARSLHHAZ.js.map} +3 -3
  8. package/dist/index.cjs.js +159 -124
  9. package/dist/index.cjs.js.map +3 -3
  10. package/dist/index.js +1 -1
  11. package/dist/meta.cjs.json +40 -40
  12. package/dist/meta.esbuild.json +49 -49
  13. package/package.json +6 -6
  14. package/src/Button/Button.tsx +2 -2
  15. package/src/Prebuilt/components/Notifications/PermissionErrorModal.tsx +8 -1
  16. package/src/Prebuilt/components/Polls/Voting/LeaderboardEntry.tsx +17 -5
  17. package/src/Prebuilt/components/Polls/Voting/LeaderboardSummary.tsx +1 -0
  18. package/src/Prebuilt/components/Polls/Voting/PeerParticipationSummary.tsx +4 -2
  19. package/src/Prebuilt/components/Polls/Voting/QuestionCard.jsx +38 -81
  20. package/src/Prebuilt/components/Polls/Voting/StandardVoting.tsx +0 -1
  21. package/src/Prebuilt/components/Polls/Voting/TimedVoting.tsx +2 -3
  22. package/src/Prebuilt/components/Polls/Voting/Voting.tsx +3 -3
  23. package/src/Prebuilt/components/Polls/common/MultipleChoiceOptions.jsx +1 -2
  24. package/src/Prebuilt/components/Polls/common/SingleChoiceOptions.jsx +6 -4
  25. package/src/Prebuilt/components/Polls/common/StatusIndicator.tsx +1 -1
  26. package/src/Prebuilt/components/Preview/PreviewJoin.tsx +4 -14
  27. package/src/Prebuilt/components/RoleChangeRequest/RequestPrompt.tsx +15 -5
  28. package/src/Prebuilt/components/RoleChangeRequest/RoleChangeRequestModal.tsx +3 -0
  29. package/src/Prebuilt/components/VirtualBackground/VBHandler.tsx +11 -1
  30. package/src/Prebuilt/components/VirtualBackground/VBPicker.tsx +16 -2
  31. package/src/Prebuilt/layouts/HLSView.jsx +16 -1
  32. package/src/Sheet/Sheet.tsx +1 -1
  33. package/dist/HLSView-S5JHEMWJ.js.map +0 -7
package/package.json CHANGED
@@ -10,7 +10,7 @@
10
10
  "prebuilt",
11
11
  "roomkit"
12
12
  ],
13
- "version": "0.2.1-alpha.2",
13
+ "version": "0.2.2-alpha.0",
14
14
  "author": "100ms",
15
15
  "license": "MIT",
16
16
  "repository": {
@@ -82,10 +82,10 @@
82
82
  "react": ">=17.0.2 <19.0.0"
83
83
  },
84
84
  "dependencies": {
85
- "@100mslive/hls-player": "0.2.1-alpha.2",
86
- "@100mslive/hms-virtual-background": "1.12.1-alpha.2",
87
- "@100mslive/react-icons": "0.9.1-alpha.2",
88
- "@100mslive/react-sdk": "0.9.1-alpha.2",
85
+ "@100mslive/hls-player": "0.2.2-alpha.0",
86
+ "@100mslive/hms-virtual-background": "1.12.2-alpha.0",
87
+ "@100mslive/react-icons": "0.9.2-alpha.0",
88
+ "@100mslive/react-sdk": "0.9.2-alpha.0",
89
89
  "@100mslive/types-prebuilt": "0.12.5",
90
90
  "@emoji-mart/data": "^1.0.6",
91
91
  "@emoji-mart/react": "^1.0.1",
@@ -120,5 +120,5 @@
120
120
  "uuid": "^8.3.2",
121
121
  "worker-timers": "^7.0.40"
122
122
  },
123
- "gitHead": "28ace828c5944beff16c169195c807e4750e817e"
123
+ "gitHead": "8d716a49dfb9bfed4ee6863e9e55490b39b49ed5"
124
124
  }
@@ -143,8 +143,8 @@ const StyledButton = styled('button', {
143
143
  '$secondary_bright',
144
144
  '$secondary_dim',
145
145
  '$secondary_disabled',
146
- '$on_surface_high',
147
- '$on_surface_low',
146
+ '$on_secondary_high',
147
+ '$on_secondary_low',
148
148
  ),
149
149
  danger: getButtonVariants(
150
150
  '$alert_error_default',
@@ -44,7 +44,14 @@ export function PermissionErrorModal() {
44
44
  <Dialog.Root open={!!deviceType}>
45
45
  <Dialog.Portal>
46
46
  <Dialog.Overlay />
47
- <Dialog.Content css={{ w: 'min(380px, 90%)', p: '$8' }}>
47
+ <Dialog.Content
48
+ css={{
49
+ w: 'min(380px, 90%)',
50
+ p: '$8',
51
+ // overlay over Sheet.tsx
52
+ zIndex: 23,
53
+ }}
54
+ >
48
55
  <Dialog.Title
49
56
  css={{
50
57
  borderBottom: '1px solid $border_default',
@@ -1,5 +1,5 @@
1
1
  import React from 'react';
2
- import { CheckCircleIcon, TrophyFilledIcon } from '@100mslive/react-icons';
2
+ import { CheckCircleIcon, ClockIcon, TrophyFilledIcon } from '@100mslive/react-icons';
3
3
  import { Box, Flex } from '../../../../Layout';
4
4
  import { Text } from '../../../../Text';
5
5
 
@@ -12,6 +12,7 @@ export const LeaderboardEntry = ({
12
12
  correctResponses,
13
13
  userName,
14
14
  maxPossibleScore,
15
+ duration,
15
16
  }: {
16
17
  position: number;
17
18
  score: number;
@@ -19,6 +20,7 @@ export const LeaderboardEntry = ({
19
20
  correctResponses: number;
20
21
  userName: string;
21
22
  maxPossibleScore: number;
23
+ duration: number;
22
24
  }) => {
23
25
  return (
24
26
  <Flex align="center" justify="between" css={{ my: '$4' }}>
@@ -49,13 +51,23 @@ export const LeaderboardEntry = ({
49
51
  </Text>
50
52
  </Box>
51
53
  </Flex>
54
+
52
55
  <Flex align="center" css={{ gap: '$4', color: '$on_surface_medium' }}>
53
56
  {position === 1 ? <TrophyFilledIcon height={16} width={16} /> : null}
54
- <CheckCircleIcon height={16} width={16} />
55
57
  {questionCount ? (
56
- <Text variant="xs">
57
- {correctResponses} / {questionCount}
58
- </Text>
58
+ <>
59
+ <CheckCircleIcon height={16} width={16} />
60
+ <Text variant="xs">
61
+ {correctResponses}/{questionCount}
62
+ </Text>
63
+ </>
64
+ ) : null}
65
+
66
+ {duration ? (
67
+ <Flex align="center" css={{ gap: '$2', color: '$on_surface_medium' }}>
68
+ <ClockIcon height={16} width={16} />
69
+ <Text variant="xs">{(duration / 1000).toFixed(3)}s</Text>
70
+ </Flex>
59
71
  ) : null}
60
72
  </Flex>
61
73
  </Flex>
@@ -86,6 +86,7 @@ export const LeaderboardSummary = ({ pollID }: { pollID: string }) => {
86
86
  correctResponses={question.correctResponses}
87
87
  userName={question.peer.username || ''}
88
88
  maxPossibleScore={maxPossibleScore}
89
+ duration={question.duration}
89
90
  />
90
91
  ))}
91
92
  {quizLeaderboard?.entries?.length > 5 && !viewAllEntries ? (
@@ -28,7 +28,8 @@ export const PeerParticipationSummary = ({ quiz }: { quiz: HMSPoll }) => {
28
28
  summary.correctUsers
29
29
  }/${summary.totalUsers})`,
30
30
  },
31
- { title: 'Avg. Time Taken', value: summary.avgTime },
31
+ // Time in ms
32
+ { title: 'Avg. Time Taken', value: `${(summary.avgTime / 1000).toFixed(3)}s` },
32
33
  {
33
34
  title: 'Avg. Score',
34
35
  value: Number.isInteger(summary.avgScore) ? summary.avgScore : summary.avgScore.toFixed(2),
@@ -37,7 +38,8 @@ export const PeerParticipationSummary = ({ quiz }: { quiz: HMSPoll }) => {
37
38
  : [
38
39
  { title: 'Your rank', value: peerEntry?.position ? `${peerEntry.position}/${summary.totalUsers}` : '-' },
39
40
  { title: 'Points', value: peerEntry?.score },
40
- { title: 'Time Taken', value: peerEntry?.duration },
41
+ // Time in ms
42
+ { title: 'Time Taken', value: `${((peerEntry?.duration || 0) / 1000).toFixed(3)}s` },
41
43
  {
42
44
  title: 'Correct Answers',
43
45
  value: peerEntry?.totalResponses ? `${peerEntry?.correctResponses}/${peerEntry.totalResponses}` : '-',
@@ -1,14 +1,8 @@
1
1
  // @ts-check
2
- import React, { useCallback, useMemo, useState } from 'react';
2
+ import React, { useCallback, useMemo, useRef, useState } from 'react';
3
3
  import { selectLocalPeer, selectLocalPeerRoleName, useHMSActions, useHMSStore } from '@100mslive/react-sdk';
4
- import {
5
- CheckCircleIcon,
6
- ChevronDownIcon,
7
- ChevronLeftIcon,
8
- ChevronRightIcon,
9
- CrossCircleIcon,
10
- } from '@100mslive/react-icons';
11
- import { Box, Button, Flex, IconButton, Text } from '../../../../';
4
+ import { CheckCircleIcon, ChevronDownIcon, CrossCircleIcon } from '@100mslive/react-icons';
5
+ import { Box, Button, Flex, Text } from '../../../../';
12
6
  import { checkCorrectAnswer } from '../../../common/utils';
13
7
  import { MultipleChoiceOptions } from '../common/MultipleChoiceOptions';
14
8
  import { SingleChoiceOptions } from '../common/SingleChoiceOptions';
@@ -27,9 +21,7 @@ export const QuestionCard = ({
27
21
  options = [],
28
22
  answer,
29
23
  setCurrentIndex,
30
- skippable = false,
31
24
  responses = [],
32
- isTimed = false,
33
25
  rolesThatCanViewResponses,
34
26
  }) => {
35
27
  const actions = useHMSActions();
@@ -37,6 +29,7 @@ export const QuestionCard = ({
37
29
  const localPeerResponse = responses?.find(
38
30
  response => response.peer?.peerid === localPeer?.id || response.peer?.userid === localPeer?.customerUserId,
39
31
  );
32
+
40
33
  const isLocalPeerCreator = localPeer?.id === startedBy;
41
34
  const localPeerRoleName = useHMSStore(selectLocalPeerRoleName);
42
35
  const roleCanViewResponse =
@@ -48,27 +41,13 @@ export const QuestionCard = ({
48
41
 
49
42
  const isLive = pollState === 'started';
50
43
  const canRespond = isLive && !localPeerResponse;
51
-
44
+ const startTime = useRef(Date.now());
52
45
  const isCorrectAnswer = checkCorrectAnswer(answer, localPeerResponse, type);
53
46
 
54
- const prev = index !== 1;
55
- const next = index !== totalQuestions && (skippable || localPeerResponse);
56
-
57
- const moveNext = useCallback(() => {
58
- setCurrentIndex(curr => Math.min(totalQuestions, curr + 1));
59
- }, [setCurrentIndex, totalQuestions]);
60
-
61
- const movePrev = () => {
62
- setCurrentIndex(curr => Math.max(1, curr - 1));
63
- };
64
-
65
- // const [textAnswer, setTextAnswer] = useState('');
66
47
  const [singleOptionAnswer, setSingleOptionAnswer] = useState();
67
48
  const [multipleOptionAnswer, setMultipleOptionAnswer] = useState(new Set());
68
49
  const [showOptions, setShowOptions] = useState(true);
69
50
 
70
- // const stringAnswerExpected = [QUESTION_TYPE.LONG_ANSWER, QUESTION_TYPE.SHORT_ANSWER].includes(type);
71
-
72
51
  const respondedToQuiz = isQuiz && localPeerResponse && !localPeerResponse.skipped;
73
52
 
74
53
  const isValidVote = useMemo(() => {
@@ -83,24 +62,31 @@ export const QuestionCard = ({
83
62
  if (!isValidVote) {
84
63
  return;
85
64
  }
65
+
86
66
  await actions.interactivityCenter.addResponsesToPoll(pollID, [
87
67
  {
88
68
  questionIndex: index,
89
69
  option: singleOptionAnswer,
90
70
  options: Array.from(multipleOptionAnswer),
71
+ duration: Date.now() - startTime.current,
91
72
  },
92
73
  ]);
93
- }, [actions, index, pollID, isValidVote, singleOptionAnswer, multipleOptionAnswer]);
74
+ startTime.current = Date.now();
94
75
 
95
- const handleSkip = useCallback(async () => {
96
- await actions.interactivityCenter.addResponsesToPoll(pollID, [
97
- {
98
- questionIndex: index,
99
- skipped: true,
100
- },
101
- ]);
102
- moveNext();
103
- }, [actions, index, pollID, moveNext]);
76
+ if (isQuiz && index !== totalQuestions) {
77
+ setSingleOptionAnswer(undefined);
78
+ setMultipleOptionAnswer(new Set());
79
+ }
80
+ }, [
81
+ isValidVote,
82
+ actions.interactivityCenter,
83
+ pollID,
84
+ index,
85
+ singleOptionAnswer,
86
+ multipleOptionAnswer,
87
+ totalQuestions,
88
+ isQuiz,
89
+ ]);
104
90
 
105
91
  return (
106
92
  <Box
@@ -135,39 +121,6 @@ export const QuestionCard = ({
135
121
  {respondedToQuiz && !isCorrectAnswer ? <CrossCircleIcon height={20} width={20} /> : null}
136
122
  QUESTION {index} OF {totalQuestions}: {type.toUpperCase()}
137
123
  </Text>
138
-
139
- {isTimed ? (
140
- <Flex align="center" css={{ gap: '$4' }}>
141
- <IconButton
142
- disabled={!prev}
143
- onClick={movePrev}
144
- css={
145
- prev
146
- ? { color: '$on_surface_high', cursor: 'pointer' }
147
- : {
148
- color: '$on_surface_low',
149
- cursor: 'not-allowed',
150
- }
151
- }
152
- >
153
- <ChevronLeftIcon height={16} width={16} />
154
- </IconButton>
155
- <IconButton
156
- disabled={!next}
157
- onClick={moveNext}
158
- css={
159
- next
160
- ? { color: '$on_surface_high', cursor: 'pointer' }
161
- : {
162
- color: '$on_surface_low',
163
- cursor: 'not-allowed',
164
- }
165
- }
166
- >
167
- <ChevronRightIcon height={16} width={16} />
168
- </IconButton>
169
- </Flex>
170
- ) : null}
171
124
  </Flex>
172
125
 
173
126
  <Flex justify="between" css={{ my: '$md' }}>
@@ -185,10 +138,10 @@ export const QuestionCard = ({
185
138
  <Box css={{ maxHeight: showOptions ? '$80' : '0', transition: 'max-height 0.3s ease', overflowY: 'hidden' }}>
186
139
  {type === QUESTION_TYPE.SINGLE_CHOICE ? (
187
140
  <SingleChoiceOptions
141
+ key={index}
188
142
  questionIndex={index}
189
143
  isQuiz={isQuiz}
190
144
  canRespond={canRespond}
191
- response={localPeerResponse}
192
145
  correctOptionIndex={answer?.option}
193
146
  options={options}
194
147
  setAnswer={setSingleOptionAnswer}
@@ -196,14 +149,15 @@ export const QuestionCard = ({
196
149
  showVoteCount={showVoteCount}
197
150
  localPeerResponse={localPeerResponse}
198
151
  isStopped={pollState === 'stopped'}
152
+ answer={singleOptionAnswer}
199
153
  />
200
154
  ) : null}
155
+
201
156
  {type === QUESTION_TYPE.MULTIPLE_CHOICE ? (
202
157
  <MultipleChoiceOptions
203
158
  questionIndex={index}
204
159
  isQuiz={isQuiz}
205
160
  canRespond={canRespond}
206
- response={localPeerResponse}
207
161
  correctOptionIndexes={answer?.options}
208
162
  options={options}
209
163
  selectedOptions={multipleOptionAnswer}
@@ -214,14 +168,16 @@ export const QuestionCard = ({
214
168
  isStopped={pollState === 'stopped'}
215
169
  />
216
170
  ) : null}
171
+
217
172
  {isLive && (
218
173
  <QuestionActions
219
174
  isValidVote={isValidVote}
220
- skippable={skippable}
221
- onSkip={handleSkip}
222
175
  onVote={handleVote}
223
176
  response={localPeerResponse}
224
177
  isQuiz={isQuiz}
178
+ incrementIndex={() => {
179
+ setCurrentIndex(curr => Math.min(totalQuestions, curr + 1));
180
+ }}
225
181
  />
226
182
  )}
227
183
  </Box>
@@ -229,15 +185,9 @@ export const QuestionCard = ({
229
185
  );
230
186
  };
231
187
 
232
- const QuestionActions = ({ isValidVote, skippable, response, isQuiz, onVote, onSkip }) => {
188
+ const QuestionActions = ({ isValidVote, response, isQuiz, onVote, incrementIndex }) => {
233
189
  return (
234
190
  <Flex align="center" justify="end" css={{ gap: '$4', w: '100%' }}>
235
- {skippable && !response ? (
236
- <Button variant="standard" onClick={onSkip} css={{ p: '$xs $10', fontWeight: '$semiBold' }}>
237
- Skip
238
- </Button>
239
- ) : null}
240
-
241
191
  {response ? (
242
192
  <Text css={{ fontWeight: '$semiBold', color: '$on_surface_medium' }}>
243
193
  {response.skipped ? 'Skipped' : null}
@@ -245,7 +195,14 @@ const QuestionActions = ({ isValidVote, skippable, response, isQuiz, onVote, onS
245
195
  {!isQuiz && !response.skipped ? 'Voted' : null}
246
196
  </Text>
247
197
  ) : (
248
- <Button css={{ p: '$xs $10', fontWeight: '$semiBold' }} disabled={!isValidVote} onClick={onVote}>
198
+ <Button
199
+ css={{ p: '$xs $10', fontWeight: '$semiBold' }}
200
+ disabled={!isValidVote}
201
+ onClick={() => {
202
+ onVote();
203
+ incrementIndex();
204
+ }}
205
+ >
249
206
  {isQuiz ? 'Answer' : 'Vote'}
250
207
  </Button>
251
208
  )}
@@ -28,7 +28,6 @@ export const StandardView = ({ poll }: { poll: HMSPoll }) => {
28
28
  result={question.result}
29
29
  totalQuestions={poll.questions?.length || 0}
30
30
  options={question.options}
31
- skippable={question.skippable}
32
31
  responses={question.responses}
33
32
  answer={question.answer}
34
33
  setCurrentIndex={() => {
@@ -4,9 +4,10 @@ import { HMSPoll } from '@100mslive/react-sdk';
4
4
  import { QuestionCard } from './QuestionCard';
5
5
 
6
6
  export const TimedView = ({ poll }: { poll: HMSPoll }) => {
7
- // backend question index starts at 1
7
+ // Backend question index starts at 1
8
8
  const [currentIndex, setCurrentIndex] = useState(1);
9
9
  const activeQuestion = poll.questions?.find(question => question.index === currentIndex);
10
+
10
11
  if (!activeQuestion) {
11
12
  return null;
12
13
  }
@@ -23,12 +24,10 @@ export const TimedView = ({ poll }: { poll: HMSPoll }) => {
23
24
  result={activeQuestion?.result}
24
25
  totalQuestions={poll.questions?.length || 0}
25
26
  options={activeQuestion.options}
26
- skippable={activeQuestion.skippable || false}
27
27
  responses={activeQuestion.responses}
28
28
  answer={activeQuestion.answer}
29
29
  setCurrentIndex={setCurrentIndex}
30
30
  rolesThatCanViewResponses={poll.rolesThatCanViewResponses}
31
- isTimed
32
31
  />
33
32
  );
34
33
  };
@@ -23,6 +23,8 @@ export const Voting = ({ id, toggleVoting }: { id: string; toggleVoting: () => v
23
23
  const pollCreatorName = useHMSStore(selectPeerNameByID(poll?.createdBy));
24
24
  const isLocalPeerCreator = useHMSStore(selectLocalPeerID) === poll?.createdBy;
25
25
  const { setPollView } = usePollViewState();
26
+ // Sets view - linear or vertical, toggles timer indicator
27
+ const showSingleView = poll?.type === 'quiz' && poll.state === 'started';
26
28
 
27
29
  if (!poll) {
28
30
  return null;
@@ -30,8 +32,6 @@ export const Voting = ({ id, toggleVoting }: { id: string; toggleVoting: () => v
30
32
 
31
33
  const canViewLeaderboard = poll.type === 'quiz' && poll.state === 'stopped' && !poll.anonymous;
32
34
 
33
- // Sets view - linear or vertical, toggles timer indicator
34
- const isTimed = (poll.duration || 0) > 0;
35
35
  const isLive = poll.state === 'started';
36
36
 
37
37
  return (
@@ -74,7 +74,7 @@ export const Voting = ({ id, toggleVoting }: { id: string; toggleVoting: () => v
74
74
  </Text>
75
75
  ) : null}
76
76
 
77
- {isTimed ? <TimedView poll={poll} /> : <StandardView poll={poll} />}
77
+ {showSingleView ? <TimedView poll={poll} /> : <StandardView poll={poll} />}
78
78
 
79
79
  {poll.state === 'started' && isLocalPeerCreator && (
80
80
  <Button
@@ -10,7 +10,6 @@ export const MultipleChoiceOptions = ({
10
10
  questionIndex,
11
11
  options,
12
12
  canRespond,
13
- response,
14
13
  totalResponses,
15
14
  selectedOptions,
16
15
  setSelectedOptions,
@@ -39,7 +38,7 @@ export const MultipleChoiceOptions = ({
39
38
  <Checkbox.Root
40
39
  id={`${questionIndex}-${option.index}`}
41
40
  disabled={!canRespond}
42
- checked={response?.options?.includes(option.index)}
41
+ checked={localPeerResponse?.options?.includes(option.index)}
43
42
  onCheckedChange={checked => handleCheckedChange(checked, option.index)}
44
43
  css={{
45
44
  cursor: canRespond ? 'pointer' : 'not-allowed',
@@ -9,7 +9,6 @@ import { VoteProgress } from './VoteProgress';
9
9
  export const SingleChoiceOptions = ({
10
10
  questionIndex,
11
11
  options,
12
- response,
13
12
  canRespond,
14
13
  setAnswer,
15
14
  totalResponses,
@@ -18,9 +17,10 @@ export const SingleChoiceOptions = ({
18
17
  isStopped,
19
18
  isQuiz,
20
19
  localPeerResponse,
20
+ answer,
21
21
  }) => {
22
22
  return (
23
- <RadioGroup.Root value={response?.option} onValueChange={value => setAnswer(value)}>
23
+ <RadioGroup.Root value={answer || null} onValueChange={value => setAnswer(value)}>
24
24
  <Flex direction="column" css={{ gap: '$md', w: '100%', mb: '$md' }}>
25
25
  {options.map(option => {
26
26
  return (
@@ -65,8 +65,10 @@ export const SingleChoiceOptions = ({
65
65
 
66
66
  <Flex direction="column" css={{ flexGrow: '1' }}>
67
67
  <Flex css={{ w: '100%' }}>
68
- <Text css={{ display: 'flex', flexGrow: '1' }}>
69
- <Label htmlFor={`${questionIndex}-${option.index}`}>{option.text}</Label>
68
+ <Text css={{ display: 'flex', flexGrow: '1', color: '$on_surface_high' }}>
69
+ <Label style={{ color: 'inherit' }} htmlFor={`${questionIndex}-${option.index}`}>
70
+ {option.text}
71
+ </Label>
70
72
  </Text>
71
73
  {showVoteCount && <VoteCount voteCount={option.voteCount} />}
72
74
  </Flex>
@@ -15,7 +15,7 @@ export const StatusIndicator = ({ isLive }: { isLive: boolean }) => {
15
15
  variant="caption"
16
16
  css={{
17
17
  fontWeight: '$semiBold',
18
- color: '$on_surface_high',
18
+ color: '$on_primary_high',
19
19
  }}
20
20
  >
21
21
  {isLive ? 'LIVE' : 'ENDED'}
@@ -160,20 +160,7 @@ const PreviewJoin = ({
160
160
  <Chip content={getParticipantChipContent(peerCount)} hideIfNoContent />
161
161
  </Flex>
162
162
  </Flex>
163
- {toggleVideo ? (
164
- <Flex
165
- align="center"
166
- justify="center"
167
- css={{
168
- mt: '$14',
169
- '@md': { mt: 0 },
170
- '@sm': { width: '100%' },
171
- flexDirection: 'column',
172
- }}
173
- >
174
- <PreviewTile name={name} error={previewError} />
175
- </Flex>
176
- ) : null}
163
+ {toggleVideo ? <PreviewTile name={name} error={previewError} /> : null}
177
164
  <Box css={{ w: '100%', maxWidth: `${Math.max(aspectRatio, 1) * 360}px` }}>
178
165
  <PreviewControls hideSettings={!toggleVideo && !toggleAudio} vbEnabled={!!virtual_background} />
179
166
  <PreviewForm
@@ -225,9 +212,12 @@ export const PreviewTile = ({ name, error }: { name: string; error?: boolean })
225
212
  bg: '$surface_default',
226
213
  aspectRatio,
227
214
  height: 'min(360px, 70vh)',
215
+ width: 'auto',
228
216
  maxWidth: '640px',
229
217
  overflow: 'clip',
218
+ mt: '$14',
230
219
  '@md': {
220
+ mt: 0,
231
221
  width: 'min(220px, 70vw)',
232
222
  maxWidth: '100%',
233
223
  my: '$4',
@@ -10,6 +10,7 @@ export const RequestPrompt = ({
10
10
  body,
11
11
  actionText = 'Accept',
12
12
  onAction,
13
+ disableActions = false,
13
14
  }: {
14
15
  open?: boolean;
15
16
  onOpenChange: (value: boolean) => void;
@@ -17,6 +18,7 @@ export const RequestPrompt = ({
17
18
  body: React.ReactNode;
18
19
  actionText?: string;
19
20
  onAction: () => void;
21
+ disableActions?: boolean;
20
22
  }) => {
21
23
  const isMobile = useMedia(cssConfig.media.md);
22
24
 
@@ -26,7 +28,7 @@ export const RequestPrompt = ({
26
28
  <Sheet.Content css={{ py: '$8' }}>
27
29
  <Text css={{ fontWeight: '$semiBold', c: '$on_surface_high', '@md': { px: '$8' } }}>{title}</Text>
28
30
  {body}
29
- <RequestActions actionText={actionText} onAction={onAction} />
31
+ <RequestActions actionText={actionText} onAction={onAction} disabled={disableActions} />
30
32
  </Sheet.Content>
31
33
  </Sheet.Root>
32
34
  );
@@ -40,24 +42,32 @@ export const RequestPrompt = ({
40
42
  <Text variant="h6">{title}</Text>
41
43
  </Dialog.Title>
42
44
  <Box css={{ mt: '$4', mb: '$10' }}>{body}</Box>
43
- <RequestActions actionText={actionText} onAction={onAction} />
45
+ <RequestActions actionText={actionText} onAction={onAction} disabled={disableActions} />
44
46
  </Dialog.Content>
45
47
  </Dialog.Portal>
46
48
  </Dialog.Root>
47
49
  );
48
50
  };
49
51
 
50
- const RequestActions = ({ onAction, actionText }: { actionText?: string; onAction: () => void }) => (
52
+ const RequestActions = ({
53
+ onAction,
54
+ actionText,
55
+ disabled = false,
56
+ }: {
57
+ actionText?: string;
58
+ onAction: () => void;
59
+ disabled?: boolean;
60
+ }) => (
51
61
  <Flex justify="center" align="center" css={{ width: '100%', gap: '$md', '@md': { mt: '$8', px: '$8' } }}>
52
62
  <Box css={{ width: '50%' }}>
53
63
  <Dialog.Close css={{ width: '100%' }}>
54
- <Button variant="standard" outlined css={{ width: '100%' }}>
64
+ <Button variant="standard" outlined css={{ width: '100%' }} disabled={disabled}>
55
65
  Decline
56
66
  </Button>
57
67
  </Dialog.Close>
58
68
  </Box>
59
69
  <Box css={{ width: '50%' }}>
60
- <Button variant="primary" css={{ width: '100%' }} onClick={onAction}>
70
+ <Button variant="primary" css={{ width: '100%' }} onClick={onAction} disabled={disabled}>
61
71
  {actionText}
62
72
  </Button>
63
73
  </Box>
@@ -1,5 +1,6 @@
1
1
  import React, { useEffect } from 'react';
2
2
  import {
3
+ selectIsInPreview,
3
4
  selectLocalPeerName,
4
5
  selectLocalPeerRoleName,
5
6
  selectRoleChangeRequest,
@@ -20,6 +21,7 @@ import { ROLE_CHANGE_DECLINED } from '../../common/constants';
20
21
  export const RoleChangeRequestModal = () => {
21
22
  const hmsActions = useHMSActions();
22
23
  const { updateMetaData } = useMyMetadata();
24
+ const isPreview = useHMSStore(selectIsInPreview);
23
25
  const currentRole = useHMSStore(selectLocalPeerRoleName);
24
26
  const roleChangeRequest = useHMSStore(selectRoleChangeRequest);
25
27
  const name = useHMSStore(selectLocalPeerName);
@@ -87,6 +89,7 @@ export const RoleChangeRequestModal = () => {
87
89
  await hmsActions.lowerLocalPeerHand();
88
90
  }}
89
91
  actionText="Accept"
92
+ disableActions={!isPreview}
90
93
  />
91
94
  );
92
95
  };
@@ -19,8 +19,18 @@ export class VBPlugin {
19
19
  if (this.effectsPlugin) {
20
20
  return this.effectsPlugin?.getBackground();
21
21
  } else {
22
+ const background = this.hmsPlugin?.getBackground();
22
23
  // @ts-ignore
23
- return this.hmsPlugin?.background?.src || this.hmsPlugin?.background;
24
+ return background?.src || background;
25
+ }
26
+ };
27
+
28
+ getBlurAmount = () => {
29
+ if (this.effectsPlugin) {
30
+ return this.effectsPlugin.getBlurAmount();
31
+ } else {
32
+ // Treating HMS VB intensity as a fixed value
33
+ return this.hmsPlugin?.getBackground() === HMSVirtualBackgroundTypes.BLUR ? 1 : 0;
24
34
  }
25
35
  };
26
36