@100mslive/roomkit-react 0.3.10-alpha.16 → 0.3.10-alpha.18
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-WF5O5RAH.css → HLSView-LNCDKSKQ.css} +3 -3
- package/dist/{HLSView-WF5O5RAH.css.map → HLSView-LNCDKSKQ.css.map} +1 -1
- package/dist/{HLSView-GCQTTWZN.js → HLSView-SJJ2GAYJ.js} +18 -3
- package/dist/HLSView-SJJ2GAYJ.js.map +7 -0
- package/dist/Prebuilt/common/constants.d.ts +0 -2
- package/dist/Prebuilt/common/hooks.d.ts +8 -1
- package/dist/Prebuilt/components/Polls/Voting/StandardVoting.d.ts +4 -2
- package/dist/Prebuilt/components/Polls/Voting/TimedVoting.d.ts +4 -2
- package/dist/Prebuilt/layouts/WaitingView.d.ts +6 -0
- package/dist/{chunk-FFWLNZPI.js → chunk-FMGGXDNB.js} +901 -788
- package/dist/chunk-FMGGXDNB.js.map +7 -0
- package/dist/index.cjs.css +2 -2
- package/dist/index.cjs.css.map +1 -1
- package/dist/index.cjs.js +1063 -941
- package/dist/index.cjs.js.map +4 -4
- package/dist/index.css +2 -2
- package/dist/index.css.map +1 -1
- package/dist/index.js +1 -1
- package/dist/meta.cjs.json +138 -108
- package/dist/meta.esbuild.json +154 -123
- package/package.json +7 -7
- package/src/Prebuilt/common/constants.ts +0 -2
- package/src/Prebuilt/common/hooks.ts +34 -1
- package/src/Prebuilt/common/utils.js +11 -11
- package/src/Prebuilt/components/AppData/AppData.tsx +0 -2
- package/src/Prebuilt/components/AppData/useUISettings.js +0 -3
- package/src/Prebuilt/components/Chat/Chat.tsx +26 -6
- package/src/Prebuilt/components/Chat/ChatFooter.tsx +18 -2
- package/src/Prebuilt/components/Chat/ChatStates.tsx +1 -1
- package/src/Prebuilt/components/Footer/ChatToggle.tsx +5 -1
- package/src/Prebuilt/components/Footer/ParticipantList.tsx +4 -2
- package/src/Prebuilt/components/Footer/PollsToggle.tsx +1 -1
- package/src/Prebuilt/components/Polls/CreatePollQuiz/PollsQuizMenu.tsx +2 -15
- package/src/Prebuilt/components/Polls/Voting/LeaderboardSummary.tsx +71 -66
- package/src/Prebuilt/components/Polls/Voting/QuestionCard.jsx +39 -40
- package/src/Prebuilt/components/Polls/Voting/StandardVoting.tsx +12 -6
- package/src/Prebuilt/components/Polls/Voting/TimedVoting.tsx +21 -10
- package/src/Prebuilt/components/Polls/Voting/Voting.tsx +44 -2
- package/src/Prebuilt/components/VideoLayouts/EqualProminence.tsx +13 -17
- package/src/Prebuilt/layouts/HLSView.jsx +14 -11
- package/src/Prebuilt/layouts/VideoStreamingSection.tsx +44 -9
- package/src/Prebuilt/layouts/WaitingView.tsx +52 -0
- package/dist/HLSView-GCQTTWZN.js.map +0 -7
- package/dist/chunk-FFWLNZPI.js.map +0 -7
- package/src/Prebuilt/layouts/NonPublisherView.jsx +0 -51
- package/src/Prebuilt/layouts/WaitingView.jsx +0 -51
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// @ts-check
|
|
2
|
-
import React, { useCallback, useMemo, useRef, useState } from 'react';
|
|
2
|
+
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
3
3
|
import { match } from 'ts-pattern';
|
|
4
4
|
import { selectLocalPeer, selectLocalPeerRoleName, useHMSActions, useHMSStore } from '@100mslive/react-sdk';
|
|
5
5
|
import { CheckCircleIcon, ChevronDownIcon, CrossCircleIcon } from '@100mslive/react-icons';
|
|
@@ -21,15 +21,12 @@ export const QuestionCard = ({
|
|
|
21
21
|
text,
|
|
22
22
|
options = [],
|
|
23
23
|
answer,
|
|
24
|
-
|
|
25
|
-
|
|
24
|
+
localPeerResponse,
|
|
25
|
+
updateSavedResponses,
|
|
26
26
|
rolesThatCanViewResponses,
|
|
27
27
|
}) => {
|
|
28
28
|
const actions = useHMSActions();
|
|
29
29
|
const localPeer = useHMSStore(selectLocalPeer);
|
|
30
|
-
const localPeerResponse = responses?.find(
|
|
31
|
-
response => response.peer?.peerid === localPeer?.id || response.peer?.userid === localPeer?.customerUserId,
|
|
32
|
-
);
|
|
33
30
|
|
|
34
31
|
const isLocalPeerCreator = localPeer?.id === startedBy;
|
|
35
32
|
const localPeerRoleName = useHMSStore(selectLocalPeerRoleName);
|
|
@@ -37,20 +34,26 @@ export const QuestionCard = ({
|
|
|
37
34
|
!rolesThatCanViewResponses ||
|
|
38
35
|
rolesThatCanViewResponses.length === 0 ||
|
|
39
36
|
rolesThatCanViewResponses.includes(localPeerRoleName || '');
|
|
37
|
+
const [localPeerChoice, setLocalPeerChoice] = useState(localPeerResponse);
|
|
38
|
+
|
|
39
|
+
useEffect(() => {
|
|
40
|
+
setLocalPeerChoice(localPeerResponse);
|
|
41
|
+
}, [localPeerResponse]);
|
|
42
|
+
|
|
40
43
|
const showVoteCount =
|
|
41
|
-
roleCanViewResponse && (
|
|
44
|
+
roleCanViewResponse && (localPeerChoice || (isLocalPeerCreator && pollState === 'stopped')) && !isQuiz;
|
|
42
45
|
|
|
43
46
|
const isLive = pollState === 'started';
|
|
44
47
|
const pollEnded = pollState === 'stopped';
|
|
45
|
-
const canRespond = isLive && !
|
|
48
|
+
const canRespond = isLive && !localPeerChoice;
|
|
46
49
|
const startTime = useRef(Date.now());
|
|
47
|
-
const isCorrectAnswer = checkCorrectAnswer(answer,
|
|
50
|
+
const isCorrectAnswer = checkCorrectAnswer(answer, localPeerChoice, type);
|
|
48
51
|
|
|
49
52
|
const [singleOptionAnswer, setSingleOptionAnswer] = useState();
|
|
50
53
|
const [multipleOptionAnswer, setMultipleOptionAnswer] = useState(new Set());
|
|
51
54
|
const [showOptions, setShowOptions] = useState(true);
|
|
52
55
|
|
|
53
|
-
const respondedToQuiz = isQuiz &&
|
|
56
|
+
const respondedToQuiz = isQuiz && localPeerChoice && !localPeerChoice.skipped;
|
|
54
57
|
|
|
55
58
|
const isValidVote = useMemo(() => {
|
|
56
59
|
if (type === QUESTION_TYPE.SINGLE_CHOICE) {
|
|
@@ -64,17 +67,28 @@ export const QuestionCard = ({
|
|
|
64
67
|
if (!isValidVote) {
|
|
65
68
|
return;
|
|
66
69
|
}
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
70
|
+
const submittedResponse = {
|
|
71
|
+
questionIndex: index,
|
|
72
|
+
option: singleOptionAnswer,
|
|
73
|
+
options: Array.from(multipleOptionAnswer),
|
|
74
|
+
duration: Date.now() - startTime.current,
|
|
75
|
+
};
|
|
76
|
+
await actions.interactivityCenter.addResponsesToPoll(pollID, [submittedResponse]);
|
|
77
|
+
updateSavedResponses(prev => {
|
|
78
|
+
const prevCopy = { ...prev };
|
|
79
|
+
prevCopy[index] = { option: singleOptionAnswer, options: Array.from(multipleOptionAnswer) };
|
|
80
|
+
return prevCopy;
|
|
81
|
+
});
|
|
76
82
|
startTime.current = Date.now();
|
|
77
|
-
}, [
|
|
83
|
+
}, [
|
|
84
|
+
isValidVote,
|
|
85
|
+
index,
|
|
86
|
+
singleOptionAnswer,
|
|
87
|
+
multipleOptionAnswer,
|
|
88
|
+
actions.interactivityCenter,
|
|
89
|
+
pollID,
|
|
90
|
+
updateSavedResponses,
|
|
91
|
+
]);
|
|
78
92
|
|
|
79
93
|
return (
|
|
80
94
|
<Box
|
|
@@ -147,7 +161,7 @@ export const QuestionCard = ({
|
|
|
147
161
|
setAnswer={setSingleOptionAnswer}
|
|
148
162
|
totalResponses={result?.totalResponses}
|
|
149
163
|
showVoteCount={showVoteCount}
|
|
150
|
-
localPeerResponse={
|
|
164
|
+
localPeerResponse={localPeerChoice}
|
|
151
165
|
isStopped={pollState === 'stopped'}
|
|
152
166
|
/>
|
|
153
167
|
) : null}
|
|
@@ -163,27 +177,19 @@ export const QuestionCard = ({
|
|
|
163
177
|
setSelectedOptions={setMultipleOptionAnswer}
|
|
164
178
|
totalResponses={result?.totalResponses}
|
|
165
179
|
showVoteCount={showVoteCount}
|
|
166
|
-
localPeerResponse={
|
|
180
|
+
localPeerResponse={localPeerChoice}
|
|
167
181
|
isStopped={pollState === 'stopped'}
|
|
168
182
|
/>
|
|
169
183
|
) : null}
|
|
170
184
|
</Box>
|
|
171
185
|
{isLive && (
|
|
172
|
-
<QuestionActions
|
|
173
|
-
isValidVote={isValidVote}
|
|
174
|
-
onVote={handleVote}
|
|
175
|
-
response={localPeerResponse}
|
|
176
|
-
isQuiz={isQuiz}
|
|
177
|
-
incrementIndex={() => {
|
|
178
|
-
setCurrentIndex(curr => Math.min(totalQuestions, curr + 1));
|
|
179
|
-
}}
|
|
180
|
-
/>
|
|
186
|
+
<QuestionActions isValidVote={isValidVote} onVote={handleVote} response={localPeerChoice} isQuiz={isQuiz} />
|
|
181
187
|
)}
|
|
182
188
|
</Box>
|
|
183
189
|
);
|
|
184
190
|
};
|
|
185
191
|
|
|
186
|
-
const QuestionActions = ({ isValidVote, response, isQuiz, onVote
|
|
192
|
+
const QuestionActions = ({ isValidVote, response, isQuiz, onVote }) => {
|
|
187
193
|
return (
|
|
188
194
|
<Flex align="center" justify="end" css={{ gap: '$4', w: '100%' }}>
|
|
189
195
|
{response ? (
|
|
@@ -193,14 +199,7 @@ const QuestionActions = ({ isValidVote, response, isQuiz, onVote, incrementIndex
|
|
|
193
199
|
{!isQuiz && !response.skipped ? 'Voted' : null}
|
|
194
200
|
</Text>
|
|
195
201
|
) : (
|
|
196
|
-
<Button
|
|
197
|
-
css={{ p: '$xs $10', fontWeight: '$semiBold' }}
|
|
198
|
-
disabled={!isValidVote}
|
|
199
|
-
onClick={() => {
|
|
200
|
-
onVote();
|
|
201
|
-
incrementIndex();
|
|
202
|
-
}}
|
|
203
|
-
>
|
|
202
|
+
<Button css={{ p: '$xs $10', fontWeight: '$semiBold' }} disabled={!isValidVote} onClick={onVote}>
|
|
204
203
|
{isQuiz ? 'Answer' : 'Vote'}
|
|
205
204
|
</Button>
|
|
206
205
|
)}
|
|
@@ -1,10 +1,18 @@
|
|
|
1
|
-
import React from 'react';
|
|
1
|
+
import React, { Dispatch, SetStateAction } from 'react';
|
|
2
2
|
import { HMSPoll } from '@100mslive/react-sdk';
|
|
3
3
|
import { PeerParticipationSummary } from './PeerParticipationSummary';
|
|
4
4
|
// @ts-ignore
|
|
5
5
|
import { QuestionCard } from './QuestionCard';
|
|
6
6
|
|
|
7
|
-
export const StandardView = ({
|
|
7
|
+
export const StandardView = ({
|
|
8
|
+
poll,
|
|
9
|
+
localPeerResponses,
|
|
10
|
+
updateSavedResponses,
|
|
11
|
+
}: {
|
|
12
|
+
poll: HMSPoll;
|
|
13
|
+
localPeerResponses: Record<number, number | number[] | undefined>;
|
|
14
|
+
updateSavedResponses: Dispatch<SetStateAction<Record<any, any>>>;
|
|
15
|
+
}) => {
|
|
8
16
|
if (!poll?.questions) {
|
|
9
17
|
return null;
|
|
10
18
|
}
|
|
@@ -28,11 +36,9 @@ export const StandardView = ({ poll }: { poll: HMSPoll }) => {
|
|
|
28
36
|
result={question.result}
|
|
29
37
|
totalQuestions={poll.questions?.length || 0}
|
|
30
38
|
options={question.options}
|
|
31
|
-
|
|
39
|
+
localPeerResponse={localPeerResponses?.[question.index]}
|
|
32
40
|
answer={question.answer}
|
|
33
|
-
|
|
34
|
-
return;
|
|
35
|
-
}}
|
|
41
|
+
updateSavedResponses={updateSavedResponses}
|
|
36
42
|
rolesThatCanViewResponses={poll.rolesThatCanViewResponses}
|
|
37
43
|
/>
|
|
38
44
|
))}
|
|
@@ -1,16 +1,27 @@
|
|
|
1
|
-
import React, { useState } from 'react';
|
|
2
|
-
import { HMSPoll
|
|
1
|
+
import React, { Dispatch, SetStateAction, useEffect, useState } from 'react';
|
|
2
|
+
import { HMSPoll } from '@100mslive/react-sdk';
|
|
3
3
|
// @ts-ignore
|
|
4
4
|
import { QuestionCard } from './QuestionCard';
|
|
5
5
|
// @ts-ignore
|
|
6
|
-
import {
|
|
6
|
+
import { getIndexToShow } from '../../../common/utils';
|
|
7
7
|
|
|
8
|
-
export const TimedView = ({
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
8
|
+
export const TimedView = ({
|
|
9
|
+
poll,
|
|
10
|
+
localPeerResponses,
|
|
11
|
+
updateSavedResponses,
|
|
12
|
+
}: {
|
|
13
|
+
poll: HMSPoll;
|
|
14
|
+
localPeerResponses?: Record<number, number | number[] | undefined>;
|
|
15
|
+
updateSavedResponses: Dispatch<SetStateAction<Record<any, any>>>;
|
|
16
|
+
}) => {
|
|
17
|
+
const [currentIndex, setCurrentIndex] = useState(getIndexToShow(localPeerResponses));
|
|
12
18
|
const activeQuestion = poll.questions?.find(question => question.index === currentIndex);
|
|
13
|
-
const attemptedAll = poll.questions?.length
|
|
19
|
+
const attemptedAll = (poll.questions?.length || 0) < currentIndex;
|
|
20
|
+
|
|
21
|
+
// Handles increments so only one question is shown at a time in quiz
|
|
22
|
+
useEffect(() => {
|
|
23
|
+
setCurrentIndex(getIndexToShow(localPeerResponses));
|
|
24
|
+
}, [localPeerResponses]);
|
|
14
25
|
|
|
15
26
|
if ((!activeQuestion && !attemptedAll) || !poll.questions?.length) {
|
|
16
27
|
return null;
|
|
@@ -32,10 +43,10 @@ export const TimedView = ({ poll }: { poll: HMSPoll }) => {
|
|
|
32
43
|
result={question?.result}
|
|
33
44
|
totalQuestions={poll.questions?.length || 0}
|
|
34
45
|
options={question.options}
|
|
35
|
-
|
|
46
|
+
localPeerResponse={localPeerResponses?.[question.index]}
|
|
36
47
|
answer={question.answer}
|
|
37
|
-
setCurrentIndex={setCurrentIndex}
|
|
38
48
|
rolesThatCanViewResponses={poll.rolesThatCanViewResponses}
|
|
49
|
+
updateSavedResponses={updateSavedResponses}
|
|
39
50
|
/>
|
|
40
51
|
) : null;
|
|
41
52
|
})}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import React from 'react';
|
|
1
|
+
import React, { useEffect, useRef, useState } from 'react';
|
|
2
2
|
import {
|
|
3
|
+
selectLocalPeerID,
|
|
3
4
|
selectPeerNameByID,
|
|
4
5
|
selectPermissions,
|
|
5
6
|
selectPollByID,
|
|
@@ -14,6 +15,8 @@ import { StandardView } from './StandardVoting';
|
|
|
14
15
|
import { TimedView } from './TimedVoting';
|
|
15
16
|
// @ts-ignore
|
|
16
17
|
import { usePollViewState } from '../../AppData/useUISettings';
|
|
18
|
+
// @ts-ignore
|
|
19
|
+
import { getPeerResponses } from '../../../common/utils';
|
|
17
20
|
import { StatusIndicator } from '../common/StatusIndicator';
|
|
18
21
|
import { POLL_VIEWS } from '../../../common/constants';
|
|
19
22
|
|
|
@@ -26,6 +29,41 @@ export const Voting = ({ id, toggleVoting }: { id: string; toggleVoting: () => v
|
|
|
26
29
|
const { setPollView } = usePollViewState();
|
|
27
30
|
// Sets view - linear or vertical, toggles timer indicator
|
|
28
31
|
const showSingleView = poll?.type === 'quiz' && poll.state === 'started';
|
|
32
|
+
const fetchedInitialResponses = useRef(false);
|
|
33
|
+
const [savedResponses, setSavedResponses] = useState<Record<any, any>>({});
|
|
34
|
+
const localPeerId = useHMSStore(selectLocalPeerID);
|
|
35
|
+
|
|
36
|
+
// To reset whenever a different poll is opened
|
|
37
|
+
useEffect(() => {
|
|
38
|
+
fetchedInitialResponses.current = false;
|
|
39
|
+
setSavedResponses({});
|
|
40
|
+
}, [id, setSavedResponses]);
|
|
41
|
+
|
|
42
|
+
useEffect(() => {
|
|
43
|
+
const getResponses = async () => {
|
|
44
|
+
if (poll && actions.interactivityCenter && !fetchedInitialResponses.current) {
|
|
45
|
+
await actions.interactivityCenter.getPollResponses(poll, true);
|
|
46
|
+
fetchedInitialResponses.current = true;
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
getResponses();
|
|
50
|
+
}, [poll, actions.interactivityCenter]);
|
|
51
|
+
|
|
52
|
+
useEffect(() => {
|
|
53
|
+
if (poll?.questions) {
|
|
54
|
+
const localPeerResponses = getPeerResponses(poll.questions, localPeerId);
|
|
55
|
+
// @ts-ignore
|
|
56
|
+
localPeerResponses?.forEach(response => {
|
|
57
|
+
if (response) {
|
|
58
|
+
setSavedResponses(prev => {
|
|
59
|
+
const prevCopy = { ...prev };
|
|
60
|
+
prevCopy[response[0]?.questionIndex] = { option: response[0]?.option, options: response[0]?.options };
|
|
61
|
+
return prevCopy;
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
}, [localPeerId, poll?.questions, id]);
|
|
29
67
|
|
|
30
68
|
if (!poll) {
|
|
31
69
|
return null;
|
|
@@ -74,7 +112,11 @@ export const Voting = ({ id, toggleVoting }: { id: string; toggleVoting: () => v
|
|
|
74
112
|
</Text>
|
|
75
113
|
) : null}
|
|
76
114
|
|
|
77
|
-
{showSingleView ?
|
|
115
|
+
{showSingleView ? (
|
|
116
|
+
<TimedView poll={poll} localPeerResponses={savedResponses} updateSavedResponses={setSavedResponses} />
|
|
117
|
+
) : (
|
|
118
|
+
<StandardView poll={poll} localPeerResponses={savedResponses} updateSavedResponses={setSavedResponses} />
|
|
119
|
+
)}
|
|
78
120
|
</Flex>
|
|
79
121
|
<Flex
|
|
80
122
|
css={{ w: '100%', justifyContent: 'end', alignItems: 'center', p: '$8', borderTop: '1px solid $border_bright' }}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import React, { useEffect,
|
|
1
|
+
import React, { useEffect, useState } from 'react';
|
|
2
2
|
import { useMedia } from 'react-use';
|
|
3
|
-
import {
|
|
3
|
+
import { PeopleAddIcon } from '@100mslive/react-icons';
|
|
4
4
|
import { Flex } from '../../../Layout';
|
|
5
5
|
import { config as cssConfig } from '../../../Theme';
|
|
6
|
+
import { WaitingView } from '../../layouts/WaitingView';
|
|
6
7
|
import { InsetTile } from '../InsetTile';
|
|
7
8
|
import { Pagination } from '../Pagination';
|
|
8
9
|
import { Grid } from './Grid';
|
|
@@ -13,26 +14,14 @@ import { usePagesWithTiles, useTileLayout } from '../hooks/useTileLayout';
|
|
|
13
14
|
import { UI_SETTINGS } from '../../common/constants';
|
|
14
15
|
|
|
15
16
|
export function EqualProminence({ isInsetEnabled = false, peers, onPageChange, onPageSize, edgeToEdge }: LayoutProps) {
|
|
16
|
-
const localPeer = useHMSStore(selectLocalPeer);
|
|
17
17
|
const isMobile = useMedia(cssConfig.media.md);
|
|
18
18
|
let maxTileCount = useUISettings(UI_SETTINGS.maxTileCount);
|
|
19
19
|
maxTileCount = isMobile ? Math.min(maxTileCount, 6) : maxTileCount;
|
|
20
|
-
|
|
20
|
+
const pageList = usePagesWithTiles({
|
|
21
21
|
peers,
|
|
22
22
|
maxTileCount,
|
|
23
23
|
});
|
|
24
|
-
|
|
25
|
-
const inputPeers = useMemo(() => {
|
|
26
|
-
if (pageList.length === 0) {
|
|
27
|
-
return localPeer ? [localPeer] : [];
|
|
28
|
-
}
|
|
29
|
-
return peers;
|
|
30
|
-
}, [pageList.length, peers, localPeer]);
|
|
31
|
-
// Pass local peer to main grid if no other peer has tiles
|
|
32
|
-
pageList = usePagesWithTiles({
|
|
33
|
-
peers: inputPeers,
|
|
34
|
-
maxTileCount,
|
|
35
|
-
});
|
|
24
|
+
|
|
36
25
|
const { ref, pagesWithTiles } = useTileLayout({
|
|
37
26
|
pageList,
|
|
38
27
|
maxTileCount,
|
|
@@ -60,7 +49,14 @@ export function EqualProminence({ isInsetEnabled = false, peers, onPageChange, o
|
|
|
60
49
|
numPages={pagesWithTiles.length}
|
|
61
50
|
/>
|
|
62
51
|
)}
|
|
63
|
-
{
|
|
52
|
+
{pageList.length === 0 ? (
|
|
53
|
+
<WaitingView
|
|
54
|
+
title="Waiting for Host to join"
|
|
55
|
+
subtitle="Sit back and relax till others join"
|
|
56
|
+
icon={<PeopleAddIcon width="56px" height="56px" style={{ color: 'white' }} />}
|
|
57
|
+
/>
|
|
58
|
+
) : null}
|
|
59
|
+
{isInsetEnabled && <InsetTile />}
|
|
64
60
|
</Flex>
|
|
65
61
|
);
|
|
66
62
|
}
|
|
@@ -34,6 +34,7 @@ import { Loading } from '../../Loading';
|
|
|
34
34
|
import { Text } from '../../Text';
|
|
35
35
|
import { config, theme, useTheme } from '../../Theme';
|
|
36
36
|
import { Tooltip } from '../../Tooltip';
|
|
37
|
+
import { WaitingView } from './WaitingView';
|
|
37
38
|
import { useSidepaneToggle } from '../components/AppData/useSidepane';
|
|
38
39
|
import { useRoomLayoutConferencingScreen } from '../provider/roomLayoutProvider/hooks/useRoomLayoutScreen';
|
|
39
40
|
import { useIsLandscape, useKeyboardHandler } from '../common/hooks';
|
|
@@ -457,17 +458,19 @@ const HLSView = () => {
|
|
|
457
458
|
flex: isLandscape ? '2 1 0' : '1 1 0',
|
|
458
459
|
}}
|
|
459
460
|
>
|
|
460
|
-
|
|
461
|
-
<
|
|
462
|
-
{
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
<
|
|
468
|
-
{
|
|
469
|
-
|
|
470
|
-
|
|
461
|
+
{streamEnded ? (
|
|
462
|
+
<WaitingView
|
|
463
|
+
icon={<ColoredHandIcon height={56} width={56} />}
|
|
464
|
+
title="Stream has ended"
|
|
465
|
+
subtitle="Have a nice day!"
|
|
466
|
+
/>
|
|
467
|
+
) : (
|
|
468
|
+
<WaitingView
|
|
469
|
+
icon={<GoLiveIcon height={56} width={56} style={{ color: 'white' }} />}
|
|
470
|
+
title="Stream yet to start"
|
|
471
|
+
subtitle="Sit back and relax"
|
|
472
|
+
/>
|
|
473
|
+
)}
|
|
471
474
|
</Flex>
|
|
472
475
|
</>
|
|
473
476
|
);
|
|
@@ -5,7 +5,14 @@ import {
|
|
|
5
5
|
HLSLiveStreamingScreen_Elements,
|
|
6
6
|
} from '@100mslive/types-prebuilt';
|
|
7
7
|
import { match } from 'ts-pattern';
|
|
8
|
-
import {
|
|
8
|
+
import {
|
|
9
|
+
selectIsConnectedToRoom,
|
|
10
|
+
selectIsLocalScreenShared,
|
|
11
|
+
selectLocalPeerRoleName,
|
|
12
|
+
useHMSActions,
|
|
13
|
+
useHMSStore,
|
|
14
|
+
} from '@100mslive/react-sdk';
|
|
15
|
+
import { PeopleAddIcon, ShareScreenIcon } from '@100mslive/react-icons';
|
|
9
16
|
import FullPageProgress from '../components/FullPageProgress';
|
|
10
17
|
import { GridLayout } from '../components/VideoLayouts/GridLayout';
|
|
11
18
|
import { Box, Flex } from '../../Layout';
|
|
@@ -21,11 +28,10 @@ import { CaptionsViewer } from '../plugins/CaptionsViewer';
|
|
|
21
28
|
import {
|
|
22
29
|
usePDFConfig,
|
|
23
30
|
useUrlToEmbed,
|
|
24
|
-
useWaitingViewerRole,
|
|
25
31
|
// @ts-ignore: No implicit Any
|
|
26
32
|
} from '../components/AppData/useUISettings';
|
|
27
33
|
import { useCloseScreenshareWhiteboard } from '../components/hooks/useCloseScreenshareWhiteboard';
|
|
28
|
-
import { useLandscapeHLSStream, useMobileHLSStream } from '../common/hooks';
|
|
34
|
+
import { useLandscapeHLSStream, useMobileHLSStream, useWaitingRoomInfo } from '../common/hooks';
|
|
29
35
|
import { SESSION_STORE_KEY } from '../common/constants';
|
|
30
36
|
// @ts-ignore: No implicit Any
|
|
31
37
|
const HLSView = React.lazy(() => import('./HLSView'));
|
|
@@ -39,17 +45,20 @@ export const VideoStreamingSection = ({
|
|
|
39
45
|
elements: DefaultConferencingScreen_Elements | HLSLiveStreamingScreen_Elements;
|
|
40
46
|
hideControls: boolean;
|
|
41
47
|
}) => {
|
|
42
|
-
const
|
|
48
|
+
const localPeerRoleName = useHMSStore(selectLocalPeerRoleName);
|
|
43
49
|
const isConnected = useHMSStore(selectIsConnectedToRoom);
|
|
50
|
+
const isSharingScreen = useHMSStore(selectIsLocalScreenShared);
|
|
44
51
|
|
|
45
52
|
const hmsActions = useHMSActions();
|
|
46
|
-
const waitingViewerRole = useWaitingViewerRole();
|
|
47
53
|
const urlToIframe = useUrlToEmbed();
|
|
48
54
|
const pdfAnnotatorActive = usePDFConfig();
|
|
49
55
|
const isMobileHLSStream = useMobileHLSStream();
|
|
50
56
|
const isLandscapeHLSStream = useLandscapeHLSStream();
|
|
51
57
|
useCloseScreenshareWhiteboard();
|
|
52
58
|
|
|
59
|
+
const { isNotAllowedToPublish, isScreenOnlyPublishParams, hasSubscribedRolePublishing } = useWaitingRoomInfo();
|
|
60
|
+
|
|
61
|
+
console.log('pring ', isNotAllowedToPublish, isScreenOnlyPublishParams, hasSubscribedRolePublishing);
|
|
53
62
|
useEffect(() => {
|
|
54
63
|
if (!isConnected) {
|
|
55
64
|
return;
|
|
@@ -64,7 +73,7 @@ export const VideoStreamingSection = ({
|
|
|
64
73
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
65
74
|
}, [isConnected, hmsActions]);
|
|
66
75
|
|
|
67
|
-
if (!
|
|
76
|
+
if (!localPeerRoleName) {
|
|
68
77
|
// we don't know the role yet to decide how to render UI
|
|
69
78
|
return null;
|
|
70
79
|
}
|
|
@@ -82,7 +91,15 @@ export const VideoStreamingSection = ({
|
|
|
82
91
|
.with({ isMobileHLSStream: true }, () => 'column')
|
|
83
92
|
.otherwise(() => 'row')}
|
|
84
93
|
>
|
|
85
|
-
{match({
|
|
94
|
+
{match({
|
|
95
|
+
screenType,
|
|
96
|
+
isNotAllowedToPublish,
|
|
97
|
+
isScreenOnlyPublishParams,
|
|
98
|
+
hasSubscribedRolePublishing,
|
|
99
|
+
isSharingScreen,
|
|
100
|
+
pdfAnnotatorActive,
|
|
101
|
+
urlToIframe,
|
|
102
|
+
})
|
|
86
103
|
.with(
|
|
87
104
|
{
|
|
88
105
|
screenType: 'hls_live_streaming',
|
|
@@ -90,8 +107,26 @@ export const VideoStreamingSection = ({
|
|
|
90
107
|
() => <HLSView />,
|
|
91
108
|
)
|
|
92
109
|
.when(
|
|
93
|
-
({
|
|
94
|
-
|
|
110
|
+
({ isNotAllowedToPublish, hasSubscribedRolePublishing }) =>
|
|
111
|
+
isNotAllowedToPublish && !hasSubscribedRolePublishing,
|
|
112
|
+
() => (
|
|
113
|
+
<WaitingView
|
|
114
|
+
title="Waiting for Host to join"
|
|
115
|
+
subtitle="Sit back and relax"
|
|
116
|
+
icon={<PeopleAddIcon width="56px" height="56px" style={{ color: 'white' }} />}
|
|
117
|
+
/>
|
|
118
|
+
),
|
|
119
|
+
)
|
|
120
|
+
.when(
|
|
121
|
+
({ isScreenOnlyPublishParams, isSharingScreen, hasSubscribedRolePublishing }) =>
|
|
122
|
+
isScreenOnlyPublishParams && !isSharingScreen && !hasSubscribedRolePublishing,
|
|
123
|
+
() => (
|
|
124
|
+
<WaitingView
|
|
125
|
+
title="Ready to present"
|
|
126
|
+
subtitle="Select the Screenshare button to start presenting"
|
|
127
|
+
icon={<ShareScreenIcon width="56px" height="56px" style={{ color: 'white' }} />}
|
|
128
|
+
/>
|
|
129
|
+
),
|
|
95
130
|
)
|
|
96
131
|
.when(
|
|
97
132
|
({ pdfAnnotatorActive }) => !!pdfAnnotatorActive,
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Box, Flex } from '../../Layout';
|
|
3
|
+
import { Text } from '../../Text';
|
|
4
|
+
|
|
5
|
+
export const WaitingView = React.memo(
|
|
6
|
+
({ icon, title, subtitle }: { icon: React.ReactNode; title: string; subtitle: string }) => {
|
|
7
|
+
return (
|
|
8
|
+
<Flex
|
|
9
|
+
align="center"
|
|
10
|
+
direction="column"
|
|
11
|
+
css={{
|
|
12
|
+
textAlign: 'center',
|
|
13
|
+
margin: 'auto',
|
|
14
|
+
h: '100%',
|
|
15
|
+
justifyContent: 'center',
|
|
16
|
+
gap: '$8',
|
|
17
|
+
}}
|
|
18
|
+
>
|
|
19
|
+
<Box
|
|
20
|
+
css={{
|
|
21
|
+
backgroundColor: '$surface_default',
|
|
22
|
+
display: 'flex',
|
|
23
|
+
alignItems: 'center',
|
|
24
|
+
gap: '$4',
|
|
25
|
+
size: '$20',
|
|
26
|
+
r: '$round',
|
|
27
|
+
justifyContent: 'center',
|
|
28
|
+
}}
|
|
29
|
+
>
|
|
30
|
+
{icon}
|
|
31
|
+
</Box>
|
|
32
|
+
<Flex
|
|
33
|
+
direction="column"
|
|
34
|
+
css={{
|
|
35
|
+
p: '$1',
|
|
36
|
+
gap: '$4',
|
|
37
|
+
}}
|
|
38
|
+
>
|
|
39
|
+
<Text variant="h4" css={{ '@md': { fontSize: '$md', color: '$on_surface_high' } }}>
|
|
40
|
+
{title}
|
|
41
|
+
</Text>
|
|
42
|
+
<Text
|
|
43
|
+
variant="body1"
|
|
44
|
+
css={{ fontWeight: '$regular', color: '$on_surface_medium', '@md': { fontSize: '$sm' } }}
|
|
45
|
+
>
|
|
46
|
+
{subtitle}
|
|
47
|
+
</Text>
|
|
48
|
+
</Flex>
|
|
49
|
+
</Flex>
|
|
50
|
+
);
|
|
51
|
+
},
|
|
52
|
+
);
|