@100mslive/roomkit-react 0.1.7-alpha.0 → 0.1.8-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/AudioLevel/AudioLevel.d.ts +5 -8
- package/dist/AudioLevel/index.d.ts +2 -1
- package/dist/AudioLevel/useBorderAudioLevel.d.ts +8 -0
- package/dist/{HLSView-F5BDZVT2.js → HLSView-IQRPLYNH.js} +8 -6
- package/dist/{HLSView-F5BDZVT2.js.map → HLSView-IQRPLYNH.js.map} +2 -2
- package/dist/Prebuilt/components/Chip.d.ts +12 -0
- package/dist/Prebuilt/components/PrebuiltDialogPortal.d.ts +4 -0
- package/dist/Prebuilt/components/RoleChangeRequest/RequestPrompt.d.ts +9 -0
- package/dist/VideoTile/StyledVideoTile.d.ts +445 -3
- package/dist/{VirtualBackground-THDRYDRA.js → VirtualBackground-GP4ATXD3.js} +3 -3
- package/dist/{chunk-JSH7SKEH.js → chunk-2H5NIZB7.js} +2 -2
- package/dist/{chunk-CDYRVICT.js → chunk-GLYGPYNS.js} +574 -1196
- package/dist/chunk-GLYGPYNS.js.map +7 -0
- package/dist/{chunk-U3G743OY.js → chunk-Z3O2WGWV.js} +2 -2
- package/dist/{chunk-U3G743OY.js.map → chunk-Z3O2WGWV.js.map} +1 -1
- package/dist/{conference-6IVZHILI.js → conference-JD35TNH4.js} +1545 -840
- package/dist/conference-JD35TNH4.js.map +7 -0
- package/dist/index.cjs.js +5975 -5849
- package/dist/index.cjs.js.map +4 -4
- package/dist/index.js +4 -2
- package/dist/meta.cjs.json +1633 -1399
- package/dist/meta.esbuild.json +1689 -1454
- package/package.json +6 -6
- package/src/AudioLevel/AudioLevel.tsx +79 -30
- package/src/AudioLevel/audio-level.png +0 -0
- package/src/AudioLevel/index.ts +2 -1
- package/src/AudioLevel/useBorderAudioLevel.tsx +34 -0
- package/src/Input/Input.tsx +1 -1
- package/src/Prebuilt/App.tsx +1 -0
- package/src/Prebuilt/components/Chat/ChatBody.jsx +125 -106
- package/src/Prebuilt/components/{Chip.jsx → Chip.tsx} +13 -2
- package/src/Prebuilt/components/Footer/ParticipantList.jsx +24 -13
- package/src/Prebuilt/components/Footer/RoleAccordion.tsx +43 -3
- package/src/Prebuilt/components/Leave/DesktopLeaveRoom.tsx +41 -46
- package/src/Prebuilt/components/Leave/MwebLeaveRoom.tsx +23 -35
- package/src/Prebuilt/components/MoreSettings/ChangeNameModal.jsx +3 -2
- package/src/Prebuilt/components/MoreSettings/EmbedUrl.jsx +3 -2
- package/src/Prebuilt/components/MwebLandscapePrompt.jsx +58 -0
- package/src/Prebuilt/components/Notifications/HLSFailureModal.jsx +3 -2
- package/src/Prebuilt/components/Notifications/PermissionErrorModal.jsx +3 -2
- package/src/Prebuilt/components/PrebuiltDialogPortal.tsx +6 -0
- package/src/Prebuilt/components/Preview/PreviewJoin.tsx +9 -6
- package/src/Prebuilt/components/RaiseHand.jsx +4 -11
- package/src/Prebuilt/components/RoleChangeModal.jsx +3 -2
- package/src/Prebuilt/components/RoleChangeRequest/RequestPrompt.tsx +67 -0
- package/src/Prebuilt/components/{RoleChangeRequestModal.tsx → RoleChangeRequest/RoleChangeRequestModal.tsx} +18 -50
- package/src/Prebuilt/components/Settings/SettingsModal.jsx +3 -2
- package/src/Prebuilt/components/Settings/StartRecording.jsx +3 -2
- package/src/Prebuilt/components/StatsForNerds.jsx +3 -2
- package/src/Prebuilt/components/VideoTile.jsx +34 -75
- package/src/Prebuilt/components/conference.jsx +1 -1
- package/src/Prebuilt/components/hooks/useMetadata.jsx +2 -1
- package/src/Prebuilt/components/pdfAnnotator/pdfFileOptions.jsx +3 -2
- package/src/Prebuilt/components/pdfAnnotator/shareScreenOptions.jsx +4 -29
- package/src/Prebuilt/components/pdfAnnotator/uploadedFile.jsx +3 -2
- package/src/Prebuilt/layouts/HLSView.jsx +4 -2
- package/src/Prebuilt/layouts/SidePane.tsx +0 -1
- package/src/Prebuilt/primitives/DialogContent.jsx +5 -4
- package/src/VideoTile/StyledVideoTile.tsx +10 -14
- package/dist/chunk-CDYRVICT.js.map +0 -7
- package/dist/conference-6IVZHILI.js.map +0 -7
- /package/dist/Prebuilt/components/{RoleChangeRequestModal.d.ts → RoleChangeRequest/RoleChangeRequestModal.d.ts} +0 -0
- /package/dist/{VirtualBackground-THDRYDRA.js.map → VirtualBackground-GP4ATXD3.js.map} +0 -0
- /package/dist/{chunk-JSH7SKEH.js.map → chunk-2H5NIZB7.js.map} +0 -0
package/package.json
CHANGED
@@ -10,7 +10,7 @@
|
|
10
10
|
"prebuilt",
|
11
11
|
"roomkit"
|
12
12
|
],
|
13
|
-
"version": "0.1.
|
13
|
+
"version": "0.1.8-alpha.0",
|
14
14
|
"author": "100ms",
|
15
15
|
"license": "MIT",
|
16
16
|
"files": [
|
@@ -76,10 +76,10 @@
|
|
76
76
|
"react": ">=17.0.2 <19.0.0"
|
77
77
|
},
|
78
78
|
"dependencies": {
|
79
|
-
"@100mslive/hls-player": "0.1.
|
80
|
-
"@100mslive/hms-virtual-background": "1.11.
|
81
|
-
"@100mslive/react-icons": "0.8.
|
82
|
-
"@100mslive/react-sdk": "0.8.
|
79
|
+
"@100mslive/hls-player": "0.1.17-alpha.0",
|
80
|
+
"@100mslive/hms-virtual-background": "1.11.17-alpha.0",
|
81
|
+
"@100mslive/react-icons": "0.8.17-alpha.0",
|
82
|
+
"@100mslive/react-sdk": "0.8.17-alpha.0",
|
83
83
|
"@100mslive/types-prebuilt": "0.12.0",
|
84
84
|
"@emoji-mart/data": "^1.0.6",
|
85
85
|
"@emoji-mart/react": "^1.0.1",
|
@@ -115,5 +115,5 @@
|
|
115
115
|
"uuid": "^8.3.2",
|
116
116
|
"worker-timers": "^7.0.40"
|
117
117
|
},
|
118
|
-
"gitHead": "
|
118
|
+
"gitHead": "d6e072de081b508a297ebc1684a33a8e9db048ef"
|
119
119
|
}
|
@@ -1,34 +1,83 @@
|
|
1
|
-
import {
|
2
|
-
import {
|
3
|
-
import {
|
4
|
-
import {
|
1
|
+
import React, { useEffect, useRef } from 'react';
|
2
|
+
import { selectTrackAudioByID, useHMSVanillaStore } from '@100mslive/react-sdk';
|
3
|
+
import { Box, Flex } from '../Layout';
|
4
|
+
import { keyframes } from '../Theme';
|
5
|
+
//@ts-ignore
|
6
|
+
import bg from './audio-level.png';
|
5
7
|
|
6
|
-
|
7
|
-
|
8
|
-
*
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
8
|
+
// keep the calculated values before hand to avoid recalcuation everytime
|
9
|
+
const positionValues = new Array(101).fill(0).reduce((acc, _, index) => {
|
10
|
+
acc[index] = Math.round((index / 100) * 4) / 4; // convert to 0.25 multiples
|
11
|
+
return acc;
|
12
|
+
}, {});
|
13
|
+
|
14
|
+
const barAnimation = keyframes({
|
15
|
+
from: {
|
16
|
+
maskSize: '4em .8em',
|
17
|
+
'-webkit-mask-position-y': '.1em',
|
18
|
+
maskPosition: 'initial .1em',
|
19
|
+
},
|
20
|
+
|
21
|
+
'50%': {
|
22
|
+
maskSize: '4em 1em',
|
23
|
+
'-webkit-mask-position-y': 0,
|
24
|
+
maskPosition: 'initial 0',
|
25
|
+
},
|
26
|
+
|
27
|
+
to: {
|
28
|
+
maskSize: '4em .8em',
|
29
|
+
'-webkit-mask-position-y': '.1em',
|
30
|
+
maskPosition: 'initial 0',
|
31
|
+
},
|
32
|
+
});
|
33
|
+
|
34
|
+
const AudioBar = () => {
|
35
|
+
return (
|
36
|
+
<Box
|
37
|
+
css={{
|
38
|
+
width: '.25em',
|
39
|
+
height: '1em',
|
40
|
+
maskImage: `url(${bg})`,
|
41
|
+
'-webkit-mask-repeat': 'no-repeat',
|
42
|
+
backgroundColor: '$on_primary_high',
|
43
|
+
maskSize: '4em 1em',
|
44
|
+
}}
|
45
|
+
/>
|
22
46
|
);
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
});
|
29
|
-
return ref;
|
30
|
-
}
|
47
|
+
};
|
48
|
+
|
49
|
+
export const AudioLevel = ({ trackId, size }: { trackId?: string; size?: 'small' | 'medium' }) => {
|
50
|
+
const ref = useRef<HTMLDivElement | null>(null);
|
51
|
+
const vanillaStore = useHMSVanillaStore();
|
31
52
|
|
32
|
-
|
33
|
-
|
53
|
+
useEffect(() => {
|
54
|
+
const unsubscribe = vanillaStore.subscribe(audioLevel => {
|
55
|
+
if (ref.current) {
|
56
|
+
let index = 0;
|
57
|
+
//@ts-ignore
|
58
|
+
for (const child of ref.current.children) {
|
59
|
+
const positionX = `-${positionValues[audioLevel] * (index === 1 ? 2.5 : 1.25)}em`;
|
60
|
+
child.style['-webkit-mask-position-x'] = positionX;
|
61
|
+
child.style['mask-position'] = `${positionX} 0`;
|
62
|
+
child.style['animation'] =
|
63
|
+
positionValues[audioLevel] > 0 ? `${barAnimation} 0.6s steps(3,jump-none) 0s infinite` : 'none';
|
64
|
+
index++;
|
65
|
+
}
|
66
|
+
}
|
67
|
+
}, selectTrackAudioByID(trackId));
|
68
|
+
return unsubscribe;
|
69
|
+
}, [vanillaStore, trackId]);
|
70
|
+
return (
|
71
|
+
<Flex
|
72
|
+
ref={ref}
|
73
|
+
css={{
|
74
|
+
fontSize: size === 'small' ? '0.75rem' : '1rem',
|
75
|
+
gap: size === 'small' ? '$1' : '$2',
|
76
|
+
}}
|
77
|
+
>
|
78
|
+
<AudioBar />
|
79
|
+
<AudioBar />
|
80
|
+
<AudioBar />
|
81
|
+
</Flex>
|
82
|
+
);
|
34
83
|
};
|
Binary file
|
package/src/AudioLevel/index.ts
CHANGED
@@ -1 +1,2 @@
|
|
1
|
-
export { useBorderAudioLevel } from './
|
1
|
+
export { useBorderAudioLevel } from './useBorderAudioLevel';
|
2
|
+
export { AudioLevel } from './AudioLevel';
|
@@ -0,0 +1,34 @@
|
|
1
|
+
import { useCallback, useRef } from 'react';
|
2
|
+
import { HMSTrackID } from '@100mslive/hms-video-store';
|
3
|
+
import { useAudioLevelStyles } from '@100mslive/react-sdk';
|
4
|
+
import { useTheme } from '../Theme';
|
5
|
+
|
6
|
+
/**
|
7
|
+
* pass in a track id and get a ref. That ref can be attached to an element which will have border
|
8
|
+
* as per audio level post that.
|
9
|
+
*/
|
10
|
+
export function useBorderAudioLevel(audioTrackId?: HMSTrackID) {
|
11
|
+
const { theme } = useTheme();
|
12
|
+
const color = theme.colors.primary_default.value;
|
13
|
+
const getStyle = useCallback(
|
14
|
+
(level: number) => {
|
15
|
+
const style: Record<string, string> = {
|
16
|
+
transition: 'outline 0.4s ease-in-out',
|
17
|
+
};
|
18
|
+
style['outline'] = level ? `${sigmoid(level) * 4}px solid ${color}` : '0px solid transparent';
|
19
|
+
return style;
|
20
|
+
},
|
21
|
+
[color],
|
22
|
+
);
|
23
|
+
const ref = useRef(null);
|
24
|
+
useAudioLevelStyles({
|
25
|
+
trackId: audioTrackId,
|
26
|
+
getStyle,
|
27
|
+
ref,
|
28
|
+
});
|
29
|
+
return ref;
|
30
|
+
}
|
31
|
+
|
32
|
+
export const sigmoid = (z: number) => {
|
33
|
+
return 1 / (1 + Math.exp(-z));
|
34
|
+
};
|
package/src/Input/Input.tsx
CHANGED
package/src/Prebuilt/App.tsx
CHANGED
@@ -218,6 +218,7 @@ export const HMSPrebuilt = React.forwardRef<HMSPrebuiltRefType, HMSPrebuiltProps
|
|
218
218
|
<AppData appDetails={metadata} tokenEndpoint={tokenByRoomIdRoleEndpoint} />
|
219
219
|
<Init />
|
220
220
|
<Box
|
221
|
+
id="prebuilt-container"
|
221
222
|
css={{
|
222
223
|
bg: '$background_dim',
|
223
224
|
size: '100%',
|
@@ -24,6 +24,7 @@ import { Tooltip } from '../../../Tooltip';
|
|
24
24
|
import emptyChat from '../../images/empty-chat.svg';
|
25
25
|
import { useRoomLayoutConferencingScreen } from '../../provider/roomLayoutProvider/hooks/useRoomLayoutScreen';
|
26
26
|
import { useSetPinnedMessage } from '../hooks/useSetPinnedMessage';
|
27
|
+
import { useUnreadCount } from './useUnreadCount';
|
27
28
|
|
28
29
|
const formatTime = date => {
|
29
30
|
if (!(date instanceof Date)) {
|
@@ -192,119 +193,127 @@ const SenderName = styled(Text, {
|
|
192
193
|
fontWeight: '$semiBold',
|
193
194
|
});
|
194
195
|
|
195
|
-
const ChatMessage = React.memo(
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
196
|
+
const ChatMessage = React.memo(
|
197
|
+
({ index, style = {}, message, setRowHeight, isLast = false, unreadCount = 0, scrollToBottom, onPin }) => {
|
198
|
+
const { ref, inView } = useInView({ threshold: 0.5, triggerOnce: true });
|
199
|
+
const rowRef = useRef(null);
|
200
|
+
useEffect(() => {
|
201
|
+
if (rowRef.current) {
|
202
|
+
setRowHeight(index, rowRef.current.clientHeight);
|
203
|
+
}
|
204
|
+
}, [index, setRowHeight]);
|
205
|
+
const isMobile = useMedia(cssConfig.media.md);
|
206
|
+
const { elements } = useRoomLayoutConferencingScreen();
|
207
|
+
const isOverlay = elements?.chat?.is_overlay && isMobile;
|
208
|
+
const hmsActions = useHMSActions();
|
209
|
+
const localPeerId = useHMSStore(selectLocalPeerID);
|
210
|
+
const permissions = useHMSStore(selectPermissions);
|
211
|
+
const messageType = getMessageType({
|
212
|
+
roles: message.recipientRoles,
|
213
|
+
receiver: message.recipientPeer,
|
214
|
+
});
|
215
|
+
// show pin action only if peer has remove others permission and the message is of broadcast type
|
216
|
+
const showPinAction = permissions.removeOthers && !messageType && elements?.chat?.allow_pinning_messages;
|
215
217
|
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
218
|
+
useEffect(() => {
|
219
|
+
if (message.id && !message.read && inView) {
|
220
|
+
hmsActions.setMessageRead(true, message.id);
|
221
|
+
}
|
222
|
+
}, [message.read, hmsActions, inView, message.id]);
|
221
223
|
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
<
|
230
|
-
ref={
|
231
|
-
|
232
|
-
css={{
|
233
|
-
|
234
|
-
// Theme independent color, token should not be used for transparent chat
|
235
|
-
bg: messageType ? (isOverlay ? 'rgba(0, 0, 0, 0.64)' : '$surface_default') : undefined,
|
236
|
-
r: messageType ? '$1' : undefined,
|
237
|
-
px: messageType ? '$4' : '$2',
|
238
|
-
py: messageType ? '$4' : 0,
|
239
|
-
userSelect: 'none',
|
240
|
-
}}
|
241
|
-
key={message.time}
|
242
|
-
data-testid="chat_msg"
|
224
|
+
useEffect(() => {
|
225
|
+
if (isLast && inView && unreadCount >= 1) {
|
226
|
+
scrollToBottom(1);
|
227
|
+
}
|
228
|
+
}, [inView, isLast, scrollToBottom, unreadCount]);
|
229
|
+
|
230
|
+
return (
|
231
|
+
<Box
|
232
|
+
ref={ref}
|
233
|
+
as="div"
|
234
|
+
css={{ mb: '$10', pr: '$10', mt: '$8', '&:hover .chat_actions': { opacity: 1 } }}
|
235
|
+
style={style}
|
243
236
|
>
|
244
|
-
<
|
237
|
+
<Flex
|
238
|
+
ref={rowRef}
|
239
|
+
align="center"
|
245
240
|
css={{
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
241
|
+
flexWrap: 'wrap',
|
242
|
+
// Theme independent color, token should not be used for transparent chat
|
243
|
+
bg: messageType ? (isOverlay ? 'rgba(0, 0, 0, 0.64)' : '$surface_default') : undefined,
|
244
|
+
r: messageType ? '$1' : undefined,
|
245
|
+
px: messageType ? '$4' : '$2',
|
246
|
+
py: messageType ? '$4' : 0,
|
247
|
+
userSelect: 'none',
|
252
248
|
}}
|
253
|
-
|
249
|
+
key={message.time}
|
250
|
+
data-testid="chat_msg"
|
254
251
|
>
|
255
|
-
<
|
256
|
-
{
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
252
|
+
<Text
|
253
|
+
css={{
|
254
|
+
color: isOverlay ? '#FFF' : '$on_surface_high',
|
255
|
+
fontWeight: '$semiBold',
|
256
|
+
display: 'inline-flex',
|
257
|
+
alignItems: 'center',
|
258
|
+
justifyContent: 'space-between',
|
259
|
+
width: '100%',
|
260
|
+
}}
|
261
|
+
as="div"
|
262
|
+
>
|
263
|
+
<Flex align="baseline">
|
264
|
+
{message.senderName === 'You' || !message.senderName ? (
|
262
265
|
<SenderName as="span" variant="sm" css={{ color: isOverlay ? '#FFF' : '$on_surface_high' }}>
|
263
|
-
{message.senderName}
|
266
|
+
{message.senderName || 'Anonymous'}
|
264
267
|
</SenderName>
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
}
|
268
|
+
) : (
|
269
|
+
<Tooltip title={message.senderName} side="top" align="start">
|
270
|
+
<SenderName as="span" variant="sm" css={{ color: isOverlay ? '#FFF' : '$on_surface_high' }}>
|
271
|
+
{message.senderName}
|
272
|
+
</SenderName>
|
273
|
+
</Tooltip>
|
274
|
+
)}
|
275
|
+
{!isOverlay ? (
|
276
|
+
<Text
|
277
|
+
as="span"
|
278
|
+
variant="xs"
|
279
|
+
css={{
|
280
|
+
ml: '$4',
|
281
|
+
color: '$on_surface_medium',
|
282
|
+
flexShrink: 0,
|
283
|
+
}}
|
284
|
+
>
|
285
|
+
{formatTime(message.time)}
|
286
|
+
</Text>
|
287
|
+
) : null}
|
288
|
+
</Flex>
|
289
|
+
<MessageType
|
290
|
+
hasCurrentUserSent={message.sender === localPeerId}
|
291
|
+
receiver={message.recipientPeer}
|
292
|
+
roles={message.recipientRoles}
|
293
|
+
/>
|
294
|
+
{!isOverlay ? <ChatActions onPin={onPin} showPinAction={showPinAction} /> : null}
|
295
|
+
</Text>
|
296
|
+
<Text
|
297
|
+
variant="sm"
|
298
|
+
css={{
|
299
|
+
w: '100%',
|
300
|
+
mt: '$2',
|
301
|
+
wordBreak: 'break-word',
|
302
|
+
whiteSpace: 'pre-wrap',
|
303
|
+
userSelect: 'all',
|
304
|
+
color: isOverlay ? '#FFF' : '$on_surface_high',
|
305
|
+
}}
|
306
|
+
onClick={e => e.stopPropagation()}
|
307
|
+
>
|
308
|
+
<AnnotisedMessage message={message.message} />
|
309
|
+
</Text>
|
310
|
+
</Flex>
|
311
|
+
</Box>
|
312
|
+
);
|
313
|
+
},
|
314
|
+
);
|
306
315
|
const ChatList = React.forwardRef(
|
307
|
-
({ width, height, setRowHeight, getRowHeight, messages, scrollToBottom }, listRef) => {
|
316
|
+
({ width, height, setRowHeight, getRowHeight, messages, unreadCount = 0, scrollToBottom }, listRef) => {
|
308
317
|
const { setPinnedMessage } = useSetPinnedMessage();
|
309
318
|
useLayoutEffect(() => {
|
310
319
|
if (listRef.current && listRef.current.scrollToItem) {
|
@@ -331,6 +340,9 @@ const ChatList = React.forwardRef(
|
|
331
340
|
key={messages[index].id}
|
332
341
|
message={messages[index]}
|
333
342
|
setRowHeight={setRowHeight}
|
343
|
+
unreadCount={unreadCount}
|
344
|
+
isLast={index >= messages.length - 2}
|
345
|
+
scrollToBottom={scrollToBottom}
|
334
346
|
onPin={() => setPinnedMessage(messages[index])}
|
335
347
|
/>
|
336
348
|
)}
|
@@ -338,7 +350,7 @@ const ChatList = React.forwardRef(
|
|
338
350
|
);
|
339
351
|
},
|
340
352
|
);
|
341
|
-
const VirtualizedChatMessages = React.forwardRef(({ messages, scrollToBottom }, listRef) => {
|
353
|
+
const VirtualizedChatMessages = React.forwardRef(({ messages, unreadCount = 0, scrollToBottom }, listRef) => {
|
342
354
|
const rowHeights = useRef({});
|
343
355
|
|
344
356
|
function getRowHeight(index) {
|
@@ -377,6 +389,7 @@ const VirtualizedChatMessages = React.forwardRef(({ messages, scrollToBottom },
|
|
377
389
|
getRowHeight={getRowHeight}
|
378
390
|
scrollToBottom={scrollToBottom}
|
379
391
|
ref={listRef}
|
392
|
+
unreadCount={unreadCount}
|
380
393
|
/>
|
381
394
|
)}
|
382
395
|
</AutoSizer>
|
@@ -394,6 +407,7 @@ export const ChatBody = React.forwardRef(({ role, peerId, scrollToBottom }, list
|
|
394
407
|
messages = useMemo(() => messages?.filter(message => message.type === 'chat') || [], [messages]);
|
395
408
|
const isMobile = useMedia(cssConfig.media.md);
|
396
409
|
const { elements } = useRoomLayoutConferencingScreen();
|
410
|
+
const unreadCount = useUnreadCount({ role, peerId });
|
397
411
|
|
398
412
|
if (messages.length === 0 && !(isMobile && elements?.chat?.is_overlay)) {
|
399
413
|
return (
|
@@ -425,7 +439,12 @@ export const ChatBody = React.forwardRef(({ role, peerId, scrollToBottom }, list
|
|
425
439
|
|
426
440
|
return (
|
427
441
|
<Fragment>
|
428
|
-
<VirtualizedChatMessages
|
442
|
+
<VirtualizedChatMessages
|
443
|
+
messages={messages}
|
444
|
+
scrollToBottom={scrollToBottom}
|
445
|
+
unreadCount={unreadCount}
|
446
|
+
ref={listRef}
|
447
|
+
/>
|
429
448
|
</Fragment>
|
430
449
|
);
|
431
450
|
});
|
@@ -1,6 +1,7 @@
|
|
1
1
|
import React from 'react';
|
2
2
|
import { Flex } from '../../Layout';
|
3
3
|
import { Text } from '../../Text';
|
4
|
+
import { CSS } from '../../Theme';
|
4
5
|
|
5
6
|
const Chip = ({
|
6
7
|
icon = <></>,
|
@@ -8,12 +9,22 @@ const Chip = ({
|
|
8
9
|
backgroundColor = '$surface_default',
|
9
10
|
textColor = '$on_surface_high',
|
10
11
|
hideIfNoContent = false,
|
12
|
+
onClick,
|
13
|
+
css = {},
|
14
|
+
}: {
|
15
|
+
icon?: React.JSX.Element;
|
16
|
+
content: string;
|
17
|
+
backgroundColor?: string;
|
18
|
+
textColor?: string;
|
19
|
+
hideIfNoContent?: boolean;
|
20
|
+
onClick?: () => void | Promise<void>;
|
21
|
+
css?: CSS;
|
11
22
|
}) => {
|
12
23
|
if (hideIfNoContent && !content) {
|
13
|
-
return;
|
24
|
+
return null;
|
14
25
|
}
|
15
26
|
return (
|
16
|
-
<Flex align="center" css={{ backgroundColor, p: '$4 $6', borderRadius: '$4' }}>
|
27
|
+
<Flex align="center" css={{ backgroundColor, p: '$4 $6', borderRadius: '$4', ...css }} onClick={() => onClick?.()}>
|
17
28
|
{icon}
|
18
29
|
<Text variant="sm" css={{ fontWeight: '$semiBold', color: textColor, ml: '$2' }}>
|
19
30
|
{content}
|
@@ -127,13 +127,15 @@ const VirtualizedParticipants = ({ peersOrderedByRoles = {}, isConnected, filter
|
|
127
127
|
flex: '1 1 0',
|
128
128
|
}}
|
129
129
|
>
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
130
|
+
{handRaisedList.length > 0 ? (
|
131
|
+
<RoleAccordion
|
132
|
+
peerList={handRaisedList}
|
133
|
+
roleName="Hand Raised"
|
134
|
+
filter={filter}
|
135
|
+
isConnected={isConnected}
|
136
|
+
isHandRaisedAccordion
|
137
|
+
/>
|
138
|
+
) : null}
|
137
139
|
{Object.keys(peersOrderedByRoles).map(role => (
|
138
140
|
<RoleAccordion
|
139
141
|
key={role}
|
@@ -179,7 +181,10 @@ export const Participant = ({ peer, isConnected }) => {
|
|
179
181
|
const ParticipantActions = React.memo(({ peerId, role, isLocal }) => {
|
180
182
|
const isHandRaised = useHMSStore(selectHasPeerHandRaised(peerId));
|
181
183
|
const canChangeRole = useHMSStore(selectPermissions)?.changeRole;
|
182
|
-
const
|
184
|
+
const canRemoveOthers = useHMSStore(selectPermissions)?.removeOthers;
|
185
|
+
const { elements } = useRoomLayoutConferencingScreen();
|
186
|
+
const { on_stage_exp } = elements || {};
|
187
|
+
const shouldShowMoreActions = (on_stage_exp && canChangeRole) || canRemoveOthers;
|
183
188
|
const isAudioMuted = !useHMSStore(selectIsPeerAudioEnabled(peerId));
|
184
189
|
|
185
190
|
return (
|
@@ -210,15 +215,21 @@ const ParticipantActions = React.memo(({ peerId, role, isLocal }) => {
|
|
210
215
|
</Flex>
|
211
216
|
) : null}
|
212
217
|
|
213
|
-
{shouldShowMoreActions && !isLocal ?
|
218
|
+
{shouldShowMoreActions && !isLocal ? (
|
219
|
+
<ParticipantMoreActions
|
220
|
+
peerId={peerId}
|
221
|
+
role={role}
|
222
|
+
elements={elements}
|
223
|
+
canChangeRole={canChangeRole}
|
224
|
+
canRemoveOthers={canRemoveOthers}
|
225
|
+
/>
|
226
|
+
) : null}
|
214
227
|
</Flex>
|
215
228
|
);
|
216
229
|
});
|
217
230
|
|
218
|
-
const ParticipantMoreActions = ({ peerId, role }) => {
|
231
|
+
const ParticipantMoreActions = ({ peerId, role, elements, canChangeRole, canRemoveOthers }) => {
|
219
232
|
const hmsActions = useHMSActions();
|
220
|
-
const { changeRole: canChangeRole, removeOthers: canRemoveOthers } = useHMSStore(selectPermissions);
|
221
|
-
const { elements } = useRoomLayoutConferencingScreen();
|
222
233
|
const {
|
223
234
|
bring_to_stage_label,
|
224
235
|
remove_from_stage_label,
|
@@ -327,7 +338,7 @@ export const ParticipantSearch = ({ onSearch, placeholder, inSidePane = false })
|
|
327
338
|
<Input
|
328
339
|
type="text"
|
329
340
|
placeholder={placeholder || 'Search for participants'}
|
330
|
-
css={{ w: '100%', p: '$6', pl: '$
|
341
|
+
css={{ w: '100%', p: '$6', pl: '$16', mr: '$4', bg: inSidePane ? '$surface_default' : '$surface_dim' }}
|
331
342
|
value={value}
|
332
343
|
onKeyDown={event => {
|
333
344
|
event.stopPropagation();
|