@100mslive/roomkit-react 0.3.16-alpha.1 → 0.3.16-alpha.11
Sign up to get free protection for your applications and to get access to all the features.
- package/dist/{HLSView-ERPYXVOY.js → HLSView-CTSCXXFA.js} +2 -2
- package/dist/{HLSView-T2PXKR6I.css → HLSView-Y2452RZU.css} +3 -3
- package/dist/{HLSView-T2PXKR6I.css.map → HLSView-Y2452RZU.css.map} +1 -1
- package/dist/Prebuilt/components/IconButtonWithOptions/IconButtonWithOptions.d.ts +2 -1
- package/dist/{chunk-NKC36NL4.js → chunk-I7DPNCT4.js} +1066 -968
- package/dist/chunk-I7DPNCT4.js.map +7 -0
- package/dist/index.cjs.css +2 -2
- package/dist/index.cjs.css.map +1 -1
- package/dist/index.cjs.js +1480 -1384
- 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 +110 -80
- package/dist/meta.esbuild.json +123 -93
- package/package.json +7 -7
- package/src/Prebuilt/App.tsx +21 -18
- package/src/Prebuilt/components/AudioVideoToggle.tsx +6 -12
- package/src/Prebuilt/components/ConferenceScreen.tsx +13 -1
- package/src/Prebuilt/components/Footer/ParticipantList.tsx +1 -4
- package/src/Prebuilt/components/IconButtonWithOptions/IconButtonWithOptions.tsx +9 -1
- package/src/Prebuilt/components/MoreSettings/MoreSettings.tsx +1 -4
- package/src/Prebuilt/components/MoreSettings/SplitComponents/DesktopOptions.tsx +12 -2
- package/src/Prebuilt/components/Notifications/HandRaisedNotifications.tsx +33 -0
- package/src/Prebuilt/components/Notifications/Notifications.tsx +3 -1
- package/src/Prebuilt/components/PIP/PIPChat.tsx +62 -14
- package/src/Prebuilt/components/PIP/PIPWindow.tsx +1 -1
- package/src/Prebuilt/components/PIP/usePIPChat.tsx +2 -0
- package/src/Prebuilt/components/Preview/PreviewJoin.tsx +3 -1
- package/src/Prebuilt/components/Toast/ToastConfig.jsx +2 -2
- package/src/Prebuilt/components/VirtualBackground/VBOption.tsx +1 -1
- package/dist/chunk-NKC36NL4.js.map +0 -7
- /package/dist/{HLSView-ERPYXVOY.js.map → HLSView-CTSCXXFA.js.map} +0 -0
package/src/Prebuilt/App.tsx
CHANGED
@@ -23,6 +23,7 @@ import { KeyboardHandler } from './components/Input/KeyboardInputManager';
|
|
23
23
|
import { LeaveScreen } from './components/LeaveScreen';
|
24
24
|
import { MwebLandscapePrompt } from './components/MwebLandscapePrompt';
|
25
25
|
import { Notifications } from './components/Notifications';
|
26
|
+
import { PIPProvider } from './components/PIP/PIPProvider';
|
26
27
|
import { PreviewScreen } from './components/Preview/PreviewScreen';
|
27
28
|
// @ts-ignore: No implicit Any
|
28
29
|
import { ToastContainer } from './components/Toast/ToastContainer';
|
@@ -218,24 +219,26 @@ export const HMSPrebuilt = React.forwardRef<HMSPrebuiltRefType, HMSPrebuiltProps
|
|
218
219
|
},
|
219
220
|
}}
|
220
221
|
>
|
221
|
-
<
|
222
|
-
|
223
|
-
<
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
222
|
+
<PIPProvider>
|
223
|
+
<Init />
|
224
|
+
<DialogContainerProvider dialogContainerSelector={containerSelector}>
|
225
|
+
<Box
|
226
|
+
className={DEFAULT_PORTAL_CONTAINER.slice(1)} // Skips the '.' in the selector
|
227
|
+
css={{
|
228
|
+
bg: '$background_dim',
|
229
|
+
size: '100%',
|
230
|
+
lineHeight: '1.5',
|
231
|
+
'-webkit-text-size-adjust': '100%',
|
232
|
+
position: 'relative',
|
233
|
+
}}
|
234
|
+
>
|
235
|
+
<AppRoutes
|
236
|
+
authTokenByRoomCodeEndpoint={tokenByRoomCodeEndpoint}
|
237
|
+
defaultAuthToken={authToken}
|
238
|
+
/>
|
239
|
+
</Box>
|
240
|
+
</DialogContainerProvider>
|
241
|
+
</PIPProvider>
|
239
242
|
</HMSThemeProvider>
|
240
243
|
);
|
241
244
|
}}
|
@@ -44,7 +44,7 @@ import { useRoomLayoutConferencingScreen } from '../provider/roomLayoutProvider/
|
|
44
44
|
// @ts-ignore: No implicit Any
|
45
45
|
import { useIsNoiseCancellationEnabled, useSetNoiseCancellation } from './AppData/useUISettings';
|
46
46
|
import { useAudioOutputTest } from './hooks/useAudioOutputTest';
|
47
|
-
import { isMacOS, TEST_AUDIO_URL } from '../common/constants';
|
47
|
+
import { isAndroid, isIOS, isMacOS, TEST_AUDIO_URL } from '../common/constants';
|
48
48
|
|
49
49
|
const krispPlugin = new HMSKrispPlugin();
|
50
50
|
// const optionsCSS = { fontWeight: '$semiBold', color: '$on_surface_high', w: '100%' };
|
@@ -310,10 +310,9 @@ export const AudioVideoToggle = ({ hideOptions = false }: { hideOptions?: boolea
|
|
310
310
|
disabled={!toggleAudio}
|
311
311
|
hideOptions={hideOptions || !hasAudioDevices}
|
312
312
|
onDisabledClick={toggleAudio}
|
313
|
+
testid="audio_toggle_btn"
|
313
314
|
tooltipMessage={`Turn ${isLocalAudioEnabled ? 'off' : 'on'} audio (${isMacOS ? '⌘' : 'ctrl'} + d)`}
|
314
|
-
icon={
|
315
|
-
!isLocalAudioEnabled ? <MicOffIcon data-testid="audio_off_btn" /> : <MicOnIcon data-testid="audio_on_btn" />
|
316
|
-
}
|
315
|
+
icon={!isLocalAudioEnabled ? <MicOffIcon /> : <MicOnIcon />}
|
317
316
|
active={isLocalAudioEnabled}
|
318
317
|
onClick={toggleAudio}
|
319
318
|
key="toggleAudio"
|
@@ -353,13 +352,8 @@ export const AudioVideoToggle = ({ hideOptions = false }: { hideOptions?: boolea
|
|
353
352
|
hideOptions={hideOptions || !hasVideoDevices}
|
354
353
|
onDisabledClick={toggleVideo}
|
355
354
|
tooltipMessage={`Turn ${isLocalVideoEnabled ? 'off' : 'on'} video (${isMacOS ? '⌘' : 'ctrl'} + e)`}
|
356
|
-
|
357
|
-
|
358
|
-
<VideoOffIcon data-testid="video_off_btn" />
|
359
|
-
) : (
|
360
|
-
<VideoOnIcon data-testid="video_on_btn" />
|
361
|
-
)
|
362
|
-
}
|
355
|
+
testid="video_toggle_btn"
|
356
|
+
icon={!isLocalVideoEnabled ? <VideoOffIcon /> : <VideoOnIcon />}
|
363
357
|
key="toggleVideo"
|
364
358
|
active={isLocalVideoEnabled}
|
365
359
|
onClick={toggleVideo}
|
@@ -372,7 +366,7 @@ export const AudioVideoToggle = ({ hideOptions = false }: { hideOptions?: boolea
|
|
372
366
|
</IconButtonWithOptions>
|
373
367
|
) : null}
|
374
368
|
|
375
|
-
{localVideoTrack?.facingMode && roomState === HMSRoomState.Preview ? (
|
369
|
+
{localVideoTrack?.facingMode && roomState === HMSRoomState.Preview && (isIOS || isAndroid) ? (
|
376
370
|
<Tooltip title="Switch Camera" key="switchCamera">
|
377
371
|
<IconButton
|
378
372
|
onClick={async () => {
|
@@ -6,6 +6,7 @@ import {
|
|
6
6
|
selectAppData,
|
7
7
|
selectIsConnectedToRoom,
|
8
8
|
selectRoomState,
|
9
|
+
useAwayNotifications,
|
9
10
|
useHMSActions,
|
10
11
|
useHMSStore,
|
11
12
|
} from '@100mslive/react-sdk';
|
@@ -50,6 +51,7 @@ export const ConferenceScreen = () => {
|
|
50
51
|
const isMobileDevice = isAndroid || isIOS || isIPadOS;
|
51
52
|
const dropdownListRef = useRef<string[]>();
|
52
53
|
const [isHLSStarted] = useSetAppDataByKey(APP_DATA.hlsStarted);
|
54
|
+
const { requestPermission } = useAwayNotifications();
|
53
55
|
|
54
56
|
// using it in hls stream to show action button when chat is disabled
|
55
57
|
const showChat = !!screenProps.elements?.chat;
|
@@ -99,10 +101,20 @@ export const ConferenceScreen = () => {
|
|
99
101
|
speakerAutoSelectionBlacklist: ['Yeti Stereo Microphone'],
|
100
102
|
},
|
101
103
|
})
|
104
|
+
.then(() => requestPermission())
|
102
105
|
.catch(console.error);
|
103
106
|
autoRoomJoined.current = true;
|
104
107
|
}
|
105
|
-
}, [
|
108
|
+
}, [
|
109
|
+
authTokenInAppData,
|
110
|
+
endpoints?.init,
|
111
|
+
hmsActions,
|
112
|
+
isConnectedToRoom,
|
113
|
+
isPreviewScreenEnabled,
|
114
|
+
roomState,
|
115
|
+
userName,
|
116
|
+
requestPermission,
|
117
|
+
]);
|
106
118
|
|
107
119
|
useEffect(() => {
|
108
120
|
onJoinFunc?.();
|
@@ -194,7 +194,6 @@ export const Participant = ({
|
|
194
194
|
<ParticipantActions
|
195
195
|
peerId={peer.id}
|
196
196
|
peerType={peer.type}
|
197
|
-
isLocal={peer.id === localPeerId}
|
198
197
|
role={peer.roleName}
|
199
198
|
isHandRaisedAccordion={isHandRaisedAccordion}
|
200
199
|
/>
|
@@ -273,12 +272,10 @@ const ParticipantActions = React.memo(
|
|
273
272
|
peerId,
|
274
273
|
peerType,
|
275
274
|
role,
|
276
|
-
isLocal,
|
277
275
|
isHandRaisedAccordion,
|
278
276
|
}: {
|
279
277
|
peerId: string;
|
280
278
|
role: string;
|
281
|
-
isLocal: boolean;
|
282
279
|
isHandRaisedAccordion?: boolean;
|
283
280
|
peerType: HMSPeerType;
|
284
281
|
}) => {
|
@@ -331,7 +328,7 @@ const ParticipantActions = React.memo(
|
|
331
328
|
</Flex>
|
332
329
|
) : null}
|
333
330
|
|
334
|
-
{shouldShowMoreActions
|
331
|
+
{shouldShowMoreActions ? <ParticipantMoreActions peerId={peerId} role={role} /> : null}
|
335
332
|
</>
|
336
333
|
)}
|
337
334
|
</Flex>
|
@@ -90,6 +90,7 @@ export const IconButtonWithOptions = ({
|
|
90
90
|
onDisabledClick = () => {
|
91
91
|
return;
|
92
92
|
},
|
93
|
+
testid = '',
|
93
94
|
tooltipMessage = '',
|
94
95
|
icon,
|
95
96
|
children,
|
@@ -103,6 +104,7 @@ export const IconButtonWithOptions = ({
|
|
103
104
|
onDisabledClick: () => void;
|
104
105
|
icon: React.ReactNode;
|
105
106
|
children: React.ReactNode;
|
107
|
+
testid?: string;
|
106
108
|
hideOptions?: boolean;
|
107
109
|
active: boolean;
|
108
110
|
disabled?: boolean;
|
@@ -111,7 +113,13 @@ export const IconButtonWithOptions = ({
|
|
111
113
|
const commonProps = { disabled, active };
|
112
114
|
return (
|
113
115
|
<Flex>
|
114
|
-
<IconSection
|
116
|
+
<IconSection
|
117
|
+
data-testid={testid}
|
118
|
+
{...commonProps}
|
119
|
+
onClick={onClick}
|
120
|
+
hideOptions={hideOptions}
|
121
|
+
className="__cancel-drag-event"
|
122
|
+
>
|
115
123
|
<Tooltip disabled={!tooltipMessage} title={tooltipMessage}>
|
116
124
|
<Icon {...commonProps}>{icon}</Icon>
|
117
125
|
</Tooltip>
|
@@ -10,7 +10,6 @@ import { DesktopOptions } from './SplitComponents/DesktopOptions';
|
|
10
10
|
// @ts-ignore: No implicit Any
|
11
11
|
import { MwebOptions } from './SplitComponents/MwebOptions';
|
12
12
|
import { config as cssConfig } from '../../..';
|
13
|
-
import { PIPProvider } from '../PIP/PIPProvider';
|
14
13
|
import { useLandscapeHLSStream } from '../../common/hooks';
|
15
14
|
|
16
15
|
export const MoreSettings = ({
|
@@ -25,8 +24,6 @@ export const MoreSettings = ({
|
|
25
24
|
return isMobile || isLandscapeHLSStream ? (
|
26
25
|
<MwebOptions elements={elements} screenType={screenType} />
|
27
26
|
) : (
|
28
|
-
<
|
29
|
-
<DesktopOptions elements={elements} screenType={screenType} />
|
30
|
-
</PIPProvider>
|
27
|
+
<DesktopOptions elements={elements} screenType={screenType} />
|
31
28
|
);
|
32
29
|
};
|
@@ -48,12 +48,14 @@ import { CaptionModal } from '../CaptionModal';
|
|
48
48
|
import { FullScreenItem } from '../FullScreenItem';
|
49
49
|
import { MuteAllModal } from '../MuteAllModal';
|
50
50
|
// @ts-ignore: No implicit any
|
51
|
+
import { useIsSidepaneTypeOpen, useSidepaneToggle } from '../../AppData/useSidepane';
|
52
|
+
// @ts-ignore: No implicit any
|
51
53
|
import { useDropdownList } from '../../hooks/useDropdownList';
|
52
54
|
import { useMyMetadata } from '../../hooks/useMetadata';
|
53
55
|
// @ts-ignore: No implicit any
|
54
56
|
import { usePIPChat } from '../../PIP/usePIPChat';
|
55
57
|
// @ts-ignore: No implicit any
|
56
|
-
import { APP_DATA, isMacOS } from '../../../common/constants';
|
58
|
+
import { APP_DATA, isMacOS, SIDE_PANE_OPTIONS } from '../../../common/constants';
|
57
59
|
|
58
60
|
const MODALS = {
|
59
61
|
CHANGE_NAME: 'changeName',
|
@@ -85,6 +87,8 @@ export const DesktopOptions = ({
|
|
85
87
|
const isTranscriptionAllowed = useHMSStore(selectIsTranscriptionAllowedByMode(HMSTranscriptionMode.CAPTION));
|
86
88
|
const isTranscriptionEnabled = useHMSStore(selectIsTranscriptionEnabled);
|
87
89
|
const { isSupported, pipWindow, requestPipWindow } = usePIPChat();
|
90
|
+
const isChatOpen = useIsSidepaneTypeOpen(SIDE_PANE_OPTIONS.CHAT);
|
91
|
+
const toggleChat = useSidepaneToggle(SIDE_PANE_OPTIONS.CHAT);
|
88
92
|
const showPipChatOption = !!elements?.chat && isSupported;
|
89
93
|
|
90
94
|
useDropdownList({ open: openModals.size > 0, name: 'MoreSettings' });
|
@@ -180,7 +184,13 @@ export const DesktopOptions = ({
|
|
180
184
|
</Dropdown.Item>
|
181
185
|
) : null}
|
182
186
|
|
183
|
-
<PIPChatOption
|
187
|
+
<PIPChatOption
|
188
|
+
showPIPChat={showPipChatOption}
|
189
|
+
openChat={async () => {
|
190
|
+
isChatOpen && toggleChat();
|
191
|
+
await requestPipWindow(350, 500);
|
192
|
+
}}
|
193
|
+
/>
|
184
194
|
<FullScreenItem />
|
185
195
|
<Dropdown.ItemSeparator css={{ mx: 0 }} />
|
186
196
|
<Dropdown.Item onClick={() => updateState(MODALS.DEVICE_SETTINGS, true)} data-testid="device_settings_btn">
|
@@ -1,14 +1,19 @@
|
|
1
1
|
import { useEffect } from 'react';
|
2
|
+
import { useDebounce } from 'react-use';
|
2
3
|
import {
|
3
4
|
HMSNotificationTypes,
|
4
5
|
HMSRoomState,
|
6
|
+
selectHandRaisedPeers,
|
5
7
|
selectHasPeerHandRaised,
|
8
|
+
selectIsLocalScreenShared,
|
6
9
|
selectPeerByID,
|
7
10
|
selectRoomState,
|
11
|
+
useAwayNotifications,
|
8
12
|
useHMSNotifications,
|
9
13
|
useHMSStore,
|
10
14
|
useHMSVanillaStore,
|
11
15
|
} from '@100mslive/react-sdk';
|
16
|
+
import { useRoomLayout } from '../../provider/roomLayoutProvider';
|
12
17
|
// @ts-ignore: No implicit Any
|
13
18
|
import { ToastBatcher } from '../Toast/ToastBatcher';
|
14
19
|
import { useRoomLayoutConferencingScreen } from '../../provider/roomLayoutProvider/hooks/useRoomLayoutScreen';
|
@@ -22,6 +27,9 @@ export const HandRaisedNotifications = () => {
|
|
22
27
|
const vanillaStore = useHMSVanillaStore();
|
23
28
|
const { on_stage_exp } = useRoomLayoutConferencingScreen().elements || {};
|
24
29
|
const isSubscribing = !!useSubscribedNotifications(SUBSCRIBED_NOTIFICATIONS.METADATA_UPDATED);
|
30
|
+
const amIScreenSharing = useHMSStore(selectIsLocalScreenShared);
|
31
|
+
const { showNotification } = useAwayNotifications();
|
32
|
+
const logoURL = useRoomLayout()?.logo?.url;
|
25
33
|
|
26
34
|
useEffect(() => {
|
27
35
|
if (!notification?.data) {
|
@@ -32,6 +40,7 @@ export const HandRaisedNotifications = () => {
|
|
32
40
|
if (roomState !== HMSRoomState.Connected || notification.data.isLocal || !isSubscribing) {
|
33
41
|
return;
|
34
42
|
}
|
43
|
+
|
35
44
|
const hasPeerHandRaised = vanillaStore.getState(selectHasPeerHandRaised(notification.data.id));
|
36
45
|
const peer = vanillaStore.getState(selectPeerByID(notification.data.id));
|
37
46
|
if (hasPeerHandRaised) {
|
@@ -41,5 +50,29 @@ export const HandRaisedNotifications = () => {
|
|
41
50
|
}
|
42
51
|
}, [isSubscribing, notification, on_stage_exp, roomState, vanillaStore]);
|
43
52
|
|
53
|
+
useDebounce(
|
54
|
+
() => {
|
55
|
+
if (!notification?.data) {
|
56
|
+
return;
|
57
|
+
}
|
58
|
+
|
59
|
+
// Don't show toast message in case of local peer.
|
60
|
+
if (roomState !== HMSRoomState.Connected || notification.data.isLocal || !isSubscribing) {
|
61
|
+
return;
|
62
|
+
}
|
63
|
+
|
64
|
+
const hasPeerHandRaised = vanillaStore.getState(selectHasPeerHandRaised(notification.data.id));
|
65
|
+
const peer = vanillaStore.getState(selectPeerByID(notification.data.id));
|
66
|
+
const handRaisedPeers = vanillaStore.getState(selectHandRaisedPeers);
|
67
|
+
if (amIScreenSharing && hasPeerHandRaised) {
|
68
|
+
const title = `${peer?.name} ${
|
69
|
+
handRaisedPeers.length > 1 ? `and ${handRaisedPeers.length - 1} others` : ''
|
70
|
+
} raised hand`;
|
71
|
+
showNotification(title, { icon: logoURL });
|
72
|
+
}
|
73
|
+
},
|
74
|
+
1000,
|
75
|
+
[isSubscribing, notification, roomState, vanillaStore, amIScreenSharing],
|
76
|
+
);
|
44
77
|
return null;
|
45
78
|
};
|
@@ -35,6 +35,7 @@ import { useRoomLayoutConferencingScreen } from '../../provider/roomLayoutProvid
|
|
35
35
|
import { usePollViewToggle } from '../AppData/useSidepane';
|
36
36
|
// @ts-ignore: No implicit Any
|
37
37
|
import { useIsNotificationDisabled, useSubscribedNotifications } from '../AppData/useUISettings';
|
38
|
+
import { usePIPWindow } from '../PIP/usePIPWindow';
|
38
39
|
import { ROLE_CHANGE_DECLINED } from '../../common/constants';
|
39
40
|
|
40
41
|
const pollToastKey: Record<string, string> = {};
|
@@ -52,6 +53,7 @@ export function Notifications() {
|
|
52
53
|
const { showNotification } = useAwayNotifications();
|
53
54
|
const amIScreenSharing = useHMSStore(selectIsLocalScreenShared);
|
54
55
|
const logoURL = useRoomLayout()?.logo?.url;
|
56
|
+
const { pipWindow } = usePIPWindow();
|
55
57
|
|
56
58
|
const handleRoleChangeDenied = useCallback((request: HMSRoleChangeRequest & { peerName: string }) => {
|
57
59
|
ToastManager.addToast({
|
@@ -172,7 +174,7 @@ export function Notifications() {
|
|
172
174
|
}
|
173
175
|
break;
|
174
176
|
case HMSNotificationTypes.NEW_MESSAGE:
|
175
|
-
if (amIScreenSharing && !notification.data?.ignored) {
|
177
|
+
if (amIScreenSharing && !notification.data?.ignored && !pipWindow) {
|
176
178
|
showNotification(`New message from ${notification.data.senderName}`, {
|
177
179
|
body: notification.data.message,
|
178
180
|
icon: logoURL,
|
@@ -2,6 +2,7 @@ import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
|
2
2
|
import {
|
3
3
|
selectHMSMessages,
|
4
4
|
selectLocalPeerID,
|
5
|
+
selectPeerNameByID,
|
5
6
|
selectSessionStore,
|
6
7
|
selectUnreadHMSMessagesCount,
|
7
8
|
useHMSStore,
|
@@ -14,6 +15,7 @@ import { Tooltip } from '../../../Tooltip';
|
|
14
15
|
import IconButton from '../../IconButton';
|
15
16
|
import { AnnotisedMessage } from '../Chat/ChatBody';
|
16
17
|
import { useRoomLayoutConferencingScreen } from '../../provider/roomLayoutProvider/hooks/useRoomLayoutScreen';
|
18
|
+
import { useIsPeerBlacklisted } from '../hooks/useChatBlacklist';
|
17
19
|
import { CHAT_MESSAGE_LIMIT, formatTime } from '../Chat/utils';
|
18
20
|
import { SESSION_STORE_KEY } from '../../common/constants';
|
19
21
|
|
@@ -43,10 +45,29 @@ export const PIPChat = () => {
|
|
43
45
|
const blacklistedMessageIDSet = new Set(blacklistedMessageIDs || []);
|
44
46
|
return messages?.filter(message => message.type === 'chat' && !blacklistedMessageIDSet.has(message.id)) || [];
|
45
47
|
}, [blacklistedMessageIDs, messages]);
|
48
|
+
const { enabled: isChatEnabled = true, updatedBy: chatStateUpdatedBy = '' } =
|
49
|
+
useHMSStore(selectSessionStore(SESSION_STORE_KEY.CHAT_STATE)) || {};
|
50
|
+
const isLocalPeerBlacklisted = useIsPeerBlacklisted({ local: true });
|
46
51
|
const { elements } = useRoomLayoutConferencingScreen();
|
47
52
|
const message_placeholder = elements?.chat?.message_placeholder || 'Send a message';
|
48
53
|
const canSendChatMessages = !!elements?.chat?.public_chat_enabled || !!elements?.chat?.roles_whitelist?.length;
|
49
54
|
|
55
|
+
const getChatStatus = useCallback(() => {
|
56
|
+
if (isLocalPeerBlacklisted) return "You've been blocked from sending messages";
|
57
|
+
if (!isChatEnabled)
|
58
|
+
return `Chat has been paused by ${
|
59
|
+
chatStateUpdatedBy.peerId === localPeerID ? 'you' : chatStateUpdatedBy?.userName
|
60
|
+
}`;
|
61
|
+
return message_placeholder;
|
62
|
+
}, [
|
63
|
+
chatStateUpdatedBy.peerId,
|
64
|
+
chatStateUpdatedBy?.userName,
|
65
|
+
isChatEnabled,
|
66
|
+
isLocalPeerBlacklisted,
|
67
|
+
localPeerID,
|
68
|
+
message_placeholder,
|
69
|
+
]);
|
70
|
+
|
50
71
|
return (
|
51
72
|
<div style={{ height: '100%' }}>
|
52
73
|
<Box
|
@@ -55,7 +76,7 @@ export const PIPChat = () => {
|
|
55
76
|
bg: '$surface_dim',
|
56
77
|
overflowY: 'auto',
|
57
78
|
// Subtracting height of footer
|
58
|
-
h: canSendChatMessages ? 'calc(100% -
|
79
|
+
h: canSendChatMessages ? 'calc(100% - 87px)' : '100%',
|
59
80
|
position: 'relative',
|
60
81
|
}}
|
61
82
|
>
|
@@ -108,16 +129,11 @@ export const PIPChat = () => {
|
|
108
129
|
</Text>
|
109
130
|
</Tooltip>
|
110
131
|
)}
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
{message.recipientPeer ? (
|
117
|
-
<Text as="span" variant="sub2" css={{ color: '$on_surface_high', fontWeight: '$semiBold' }}>
|
118
|
-
(DM)
|
119
|
-
</Text>
|
120
|
-
) : null}
|
132
|
+
<MessageTitle
|
133
|
+
localPeerID={localPeerID}
|
134
|
+
recipientPeer={message.recipientPeer}
|
135
|
+
recipientRoles={message.recipientRoles}
|
136
|
+
/>
|
121
137
|
</Flex>
|
122
138
|
|
123
139
|
<Text
|
@@ -193,13 +209,16 @@ export const PIPChat = () => {
|
|
193
209
|
<TextArea
|
194
210
|
id="chat-input"
|
195
211
|
maxLength={CHAT_MESSAGE_LIMIT}
|
196
|
-
|
212
|
+
disabled={!isChatEnabled || isLocalPeerBlacklisted}
|
213
|
+
rows={1}
|
197
214
|
css={{
|
198
215
|
w: '100%',
|
199
216
|
c: '$on_surface_high',
|
200
|
-
|
217
|
+
p: '0.75rem 0.75rem !important',
|
218
|
+
border: 'none',
|
219
|
+
resize: 'none',
|
201
220
|
}}
|
202
|
-
placeholder={
|
221
|
+
placeholder={getChatStatus()}
|
203
222
|
required
|
204
223
|
autoComplete="off"
|
205
224
|
aria-autocomplete="none"
|
@@ -207,6 +226,8 @@ export const PIPChat = () => {
|
|
207
226
|
|
208
227
|
<IconButton
|
209
228
|
id="send-btn"
|
229
|
+
disabled={!isChatEnabled || isLocalPeerBlacklisted}
|
230
|
+
title={getChatStatus()}
|
210
231
|
css={{
|
211
232
|
ml: 'auto',
|
212
233
|
height: 'max-content',
|
@@ -223,3 +244,30 @@ export const PIPChat = () => {
|
|
223
244
|
</div>
|
224
245
|
);
|
225
246
|
};
|
247
|
+
|
248
|
+
const MessageTitle = ({
|
249
|
+
recipientPeer,
|
250
|
+
recipientRoles,
|
251
|
+
localPeerID,
|
252
|
+
}: {
|
253
|
+
recipientPeer?: string;
|
254
|
+
recipientRoles?: string[];
|
255
|
+
localPeerID: string;
|
256
|
+
}) => {
|
257
|
+
const peerName = useHMSStore(selectPeerNameByID(recipientPeer));
|
258
|
+
|
259
|
+
return (
|
260
|
+
<>
|
261
|
+
{recipientRoles ? (
|
262
|
+
<Text as="span" variant="sub2" css={{ color: '$on_surface_high', fontWeight: '$semiBold' }}>
|
263
|
+
to {recipientRoles} (Group)
|
264
|
+
</Text>
|
265
|
+
) : null}
|
266
|
+
{recipientPeer ? (
|
267
|
+
<Text as="span" variant="sub2" css={{ color: '$on_surface_high', fontWeight: '$semiBold' }}>
|
268
|
+
to {recipientPeer === localPeerID ? 'You' : peerName} (DM)
|
269
|
+
</Text>
|
270
|
+
) : null}
|
271
|
+
</>
|
272
|
+
);
|
273
|
+
};
|
@@ -8,6 +8,6 @@ type PIPWindowProps = {
|
|
8
8
|
|
9
9
|
export const PIPWindow = ({ pipWindow, children }: PIPWindowProps) => {
|
10
10
|
pipWindow.document.body.style.margin = '0';
|
11
|
-
pipWindow.document.body.style.
|
11
|
+
pipWindow.document.body.style.overflow = 'clip';
|
12
12
|
return createPortal(children, pipWindow.document.body);
|
13
13
|
};
|
@@ -25,6 +25,8 @@ export const usePIPChat = () => {
|
|
25
25
|
const pipChatInput = pipWindow.document.getElementById('chat-input') as HTMLTextAreaElement;
|
26
26
|
const marker = pipWindow.document.getElementById('marker');
|
27
27
|
|
28
|
+
marker?.scrollIntoView({ block: 'end' });
|
29
|
+
|
28
30
|
const observer = new IntersectionObserver(
|
29
31
|
entries => {
|
30
32
|
entries.forEach(entry => {
|
@@ -8,6 +8,7 @@ import {
|
|
8
8
|
selectRoomState,
|
9
9
|
selectVideoTrackByID,
|
10
10
|
useAVToggle,
|
11
|
+
useAwayNotifications,
|
11
12
|
useHMSStore,
|
12
13
|
useParticipants,
|
13
14
|
usePreviewJoin,
|
@@ -100,6 +101,7 @@ const PreviewJoin = ({
|
|
100
101
|
},
|
101
102
|
asRole,
|
102
103
|
});
|
104
|
+
const { requestPermission } = useAwayNotifications();
|
103
105
|
const roomState = useHMSStore(selectRoomState);
|
104
106
|
const savePreferenceAndJoin = useCallback(() => {
|
105
107
|
setPreviewPreference({
|
@@ -115,7 +117,7 @@ const PreviewJoin = ({
|
|
115
117
|
if (skipPreview) {
|
116
118
|
savePreferenceAndJoin();
|
117
119
|
} else {
|
118
|
-
preview();
|
120
|
+
preview().then(() => requestPermission());
|
119
121
|
}
|
120
122
|
}
|
121
123
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
@@ -111,7 +111,7 @@ export const ToastConfig = {
|
|
111
111
|
const count = new Set(notifications.map(notification => notification.data?.id)).size;
|
112
112
|
return {
|
113
113
|
title: `${notifications[notifications.length - 1].data?.name} ${
|
114
|
-
count > 1 ?
|
114
|
+
count > 1 ? `and ${count} others` : ''
|
115
115
|
} raised hand`,
|
116
116
|
icon: <HandIcon />,
|
117
117
|
};
|
@@ -129,7 +129,7 @@ export const ToastConfig = {
|
|
129
129
|
const count = new Set(notifications.map(notification => notification.data?.id)).size;
|
130
130
|
return {
|
131
131
|
title: `${notifications[notifications.length - 1].data?.name} ${
|
132
|
-
count > 1 ?
|
132
|
+
count > 1 ? `and ${count} others` : ''
|
133
133
|
} raised hand`,
|
134
134
|
icon: <HandIcon />,
|
135
135
|
action: <HandRaiseAction isSingleHandRaise={false} />,
|
@@ -26,7 +26,7 @@ const Root = ({
|
|
26
26
|
border: `4px solid ${isActive ? '$primary_default' : '$surface_dim'}`,
|
27
27
|
cursor: 'pointer',
|
28
28
|
'&:hover': { border: '4px solid $primary_dim' },
|
29
|
-
...(mediaURL ? { height: '$20', backgroundImage: `url(${mediaURL})`, backgroundSize: 'cover' } : {}),
|
29
|
+
...(mediaURL ? { height: '$20', backgroundImage: `url("${mediaURL}")`, backgroundSize: 'cover' } : {}),
|
30
30
|
}}
|
31
31
|
onClick={async () => {
|
32
32
|
await onClick?.();
|