@100mslive/roomkit-react 0.2.1 → 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.
- package/dist/{HLSView-U7FQ2YLK.js → HLSView-4TLGLPKO.js} +19 -4
- package/dist/HLSView-4TLGLPKO.js.map +7 -0
- package/dist/Prebuilt/components/Polls/Voting/LeaderboardEntry.d.ts +2 -1
- package/dist/Prebuilt/components/RoleChangeRequest/RequestPrompt.d.ts +2 -1
- package/dist/Prebuilt/components/VirtualBackground/VBHandler.d.ts +1 -0
- package/dist/{chunk-GNQAOG73.js → chunk-ARSLHHAZ.js} +176 -159
- package/dist/{chunk-GNQAOG73.js.map → chunk-ARSLHHAZ.js.map} +3 -3
- package/dist/index.cjs.js +159 -124
- package/dist/index.cjs.js.map +3 -3
- package/dist/index.js +1 -1
- package/dist/meta.cjs.json +41 -41
- package/dist/meta.esbuild.json +50 -50
- package/package.json +6 -6
- package/src/Button/Button.tsx +2 -2
- package/src/Prebuilt/components/Notifications/PermissionErrorModal.tsx +8 -1
- package/src/Prebuilt/components/Polls/Voting/LeaderboardEntry.tsx +17 -5
- package/src/Prebuilt/components/Polls/Voting/LeaderboardSummary.tsx +1 -0
- package/src/Prebuilt/components/Polls/Voting/PeerParticipationSummary.tsx +4 -2
- package/src/Prebuilt/components/Polls/Voting/QuestionCard.jsx +38 -81
- package/src/Prebuilt/components/Polls/Voting/StandardVoting.tsx +0 -1
- package/src/Prebuilt/components/Polls/Voting/TimedVoting.tsx +2 -3
- package/src/Prebuilt/components/Polls/Voting/Voting.tsx +3 -3
- package/src/Prebuilt/components/Polls/common/MultipleChoiceOptions.jsx +1 -2
- package/src/Prebuilt/components/Polls/common/SingleChoiceOptions.jsx +6 -4
- package/src/Prebuilt/components/Polls/common/StatusIndicator.tsx +1 -1
- package/src/Prebuilt/components/Preview/PreviewJoin.tsx +4 -14
- package/src/Prebuilt/components/RoleChangeRequest/RequestPrompt.tsx +15 -5
- package/src/Prebuilt/components/RoleChangeRequest/RoleChangeRequestModal.tsx +3 -0
- package/src/Prebuilt/components/VirtualBackground/VBHandler.tsx +11 -1
- package/src/Prebuilt/components/VirtualBackground/VBPicker.tsx +16 -2
- package/src/Prebuilt/layouts/HLSView.jsx +16 -1
- package/src/Sheet/Sheet.tsx +1 -1
- package/dist/HLSView-U7FQ2YLK.js.map +0 -7
|
@@ -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
|
-
|
|
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
|
-
|
|
74
|
+
startTime.current = Date.now();
|
|
94
75
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
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,
|
|
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
|
|
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
|
-
//
|
|
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
|
-
{
|
|
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={
|
|
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={
|
|
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}`}>
|
|
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>
|
|
@@ -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 = ({
|
|
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
|
|
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
|
|
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
useHMSStore,
|
|
15
15
|
} from '@100mslive/react-sdk';
|
|
16
16
|
import { BlurPersonHighIcon, CloseIcon, CrossCircleIcon } from '@100mslive/react-icons';
|
|
17
|
-
import { Box, Flex, Video } from '../../../index';
|
|
17
|
+
import { Box, Flex, Slider, Video } from '../../../index';
|
|
18
18
|
import { Text } from '../../../Text';
|
|
19
19
|
import { VBCollection } from './VBCollection';
|
|
20
20
|
import { VBHandler } from './VBHandler';
|
|
@@ -36,6 +36,7 @@ export const VBPicker = ({ backgroundMedia = [] }: { backgroundMedia: VirtualBac
|
|
|
36
36
|
const mirrorLocalVideo = useUISettings(UI_SETTINGS.mirrorLocalVideo);
|
|
37
37
|
const trackSelector = selectVideoTrackByID(localPeer?.videoTrack);
|
|
38
38
|
const track = useHMSStore(trackSelector);
|
|
39
|
+
const [blurAmount, setBlurAmount] = useState(VBHandler.getBlurAmount() || 0.5);
|
|
39
40
|
const roomState = useHMSStore(selectRoomState);
|
|
40
41
|
const isLargeRoom = useHMSStore(selectIsLargeRoom);
|
|
41
42
|
const isEffectsEnabled = useHMSStore(selectIsEffectsEnabled);
|
|
@@ -127,7 +128,7 @@ export const VBPicker = ({ backgroundMedia = [] }: { backgroundMedia: VirtualBac
|
|
|
127
128
|
icon: <BlurPersonHighIcon style={iconDims} />,
|
|
128
129
|
value: HMSVirtualBackgroundTypes.BLUR,
|
|
129
130
|
onClick: async () => {
|
|
130
|
-
await VBHandler?.setBlur(
|
|
131
|
+
await VBHandler?.setBlur(blurAmount);
|
|
131
132
|
setActiveBackground(HMSVirtualBackgroundTypes.BLUR);
|
|
132
133
|
},
|
|
133
134
|
},
|
|
@@ -135,6 +136,19 @@ export const VBPicker = ({ backgroundMedia = [] }: { backgroundMedia: VirtualBac
|
|
|
135
136
|
activeBackground={activeBackground}
|
|
136
137
|
/>
|
|
137
138
|
|
|
139
|
+
{activeBackground === HMSVirtualBackgroundTypes.BLUR ? (
|
|
140
|
+
<Slider
|
|
141
|
+
value={[blurAmount]}
|
|
142
|
+
onValueChange={async e => {
|
|
143
|
+
setBlurAmount(e[0]);
|
|
144
|
+
await VBHandler.setBlur(e[0]);
|
|
145
|
+
}}
|
|
146
|
+
step={0.1}
|
|
147
|
+
min={0.1}
|
|
148
|
+
max={1}
|
|
149
|
+
/>
|
|
150
|
+
) : null}
|
|
151
|
+
|
|
138
152
|
<VBCollection
|
|
139
153
|
title="Backgrounds"
|
|
140
154
|
options={mediaList.map(mediaURL => ({
|
|
@@ -3,11 +3,13 @@ import { useFullscreen, useMedia, usePrevious, useToggle } from 'react-use';
|
|
|
3
3
|
import { HLSPlaybackState, HMSHLSPlayer, HMSHLSPlayerEvents } from '@100mslive/hls-player';
|
|
4
4
|
import screenfull from 'screenfull';
|
|
5
5
|
import {
|
|
6
|
+
HMSNotificationTypes,
|
|
6
7
|
selectAppData,
|
|
7
8
|
selectHLSState,
|
|
8
9
|
selectPeerNameByID,
|
|
9
10
|
selectPollByID,
|
|
10
11
|
useHMSActions,
|
|
12
|
+
useHMSNotifications,
|
|
11
13
|
useHMSStore,
|
|
12
14
|
useHMSVanillaStore,
|
|
13
15
|
} from '@100mslive/react-sdk';
|
|
@@ -30,12 +32,14 @@ import { usePollViewToggle } from '../components/AppData/useSidepane';
|
|
|
30
32
|
import { APP_DATA, EMOJI_REACTION_TYPE } from '../common/constants';
|
|
31
33
|
|
|
32
34
|
let hlsPlayer;
|
|
35
|
+
const toastMap = {};
|
|
33
36
|
|
|
34
37
|
const HLSView = () => {
|
|
35
38
|
const videoRef = useRef(null);
|
|
36
39
|
const hlsViewRef = useRef(null);
|
|
37
40
|
const hlsState = useHMSStore(selectHLSState);
|
|
38
41
|
const enablHlsStats = useHMSStore(selectAppData(APP_DATA.hlsStats));
|
|
42
|
+
const notification = useHMSNotifications(HMSNotificationTypes.POLL_STOPPED);
|
|
39
43
|
const hmsActions = useHMSActions();
|
|
40
44
|
const { themeType, theme } = useTheme();
|
|
41
45
|
const [streamEnded, setStreamEnded] = useState(false);
|
|
@@ -85,6 +89,15 @@ const HLSView = () => {
|
|
|
85
89
|
}
|
|
86
90
|
}, [hlsUrl, streamEnded, lastHlsUrl]);
|
|
87
91
|
|
|
92
|
+
useEffect(() => {
|
|
93
|
+
if (!notification) return;
|
|
94
|
+
const toastID = toastMap?.[notification.data.id];
|
|
95
|
+
if (toastID) {
|
|
96
|
+
ToastManager.removeToast(toastMap[notification.data.id]);
|
|
97
|
+
delete toastMap[notification.data.id];
|
|
98
|
+
}
|
|
99
|
+
}, [notification]);
|
|
100
|
+
|
|
88
101
|
useEffect(() => {
|
|
89
102
|
const videoElem = videoRef.current;
|
|
90
103
|
const setStreamEndedCallback = () => {
|
|
@@ -126,7 +139,7 @@ const HLSView = () => {
|
|
|
126
139
|
const poll = vanillaStore.getState(selectPollByID(pollId));
|
|
127
140
|
const pollStartedBy = vanillaStore.getState(selectPeerNameByID(poll.startedBy)) || 'Participant';
|
|
128
141
|
// launch poll
|
|
129
|
-
ToastManager.addToast({
|
|
142
|
+
const toastID = ToastManager.addToast({
|
|
130
143
|
title: `${pollStartedBy} started a ${poll.type}: ${poll.title}`,
|
|
131
144
|
action: (
|
|
132
145
|
<Button
|
|
@@ -142,7 +155,9 @@ const HLSView = () => {
|
|
|
142
155
|
{poll.type === 'quiz' ? 'Answer' : 'Vote'}
|
|
143
156
|
</Button>
|
|
144
157
|
),
|
|
158
|
+
duration: Infinity,
|
|
145
159
|
});
|
|
160
|
+
toastMap[pollId] = toastID;
|
|
146
161
|
return;
|
|
147
162
|
}
|
|
148
163
|
switch (parsedPayload.type) {
|
package/src/Sheet/Sheet.tsx
CHANGED