@100mslive/roomkit-react 0.1.15 → 0.1.16
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-MXBOUQBG.js → HLSView-EMUOLCTM.js} +2 -2
- package/dist/Prebuilt/common/PeersSorter.d.ts +1 -0
- package/dist/Prebuilt/common/constants.d.ts +7 -4
- package/dist/Prebuilt/common/hooks.d.ts +1 -0
- package/dist/Prebuilt/components/Footer/ParticipantList.d.ts +17 -0
- package/dist/Prebuilt/components/Footer/RoleAccordion.d.ts +3 -2
- package/dist/Prebuilt/components/Footer/WhiteboardToggle.d.ts +2 -0
- package/dist/Prebuilt/components/Notifications/HandRaisedNotifications.d.ts +1 -0
- package/dist/Prebuilt/components/PreviousRoleInMetadata.d.ts +1 -0
- package/dist/Prebuilt/components/RemoveParticipant.d.ts +5 -0
- package/dist/Prebuilt/components/hooks/useCloseScreenshareWhiteboard.d.ts +4 -0
- package/dist/Prebuilt/layouts/WhiteboardView.d.ts +2 -0
- package/dist/{chunk-HEOH5H43.js → chunk-ZYR4B4KQ.js} +1886 -7116
- package/dist/chunk-ZYR4B4KQ.js.map +7 -0
- package/dist/index.cjs.js +2477 -7662
- package/dist/index.cjs.js.map +4 -4
- package/dist/index.js +1 -1
- package/dist/meta.cjs.json +438 -161
- package/dist/meta.esbuild.json +443 -166
- package/package.json +7 -7
- package/src/Prebuilt/AppStateContext.tsx +1 -1
- package/src/Prebuilt/common/PeersSorter.ts +12 -5
- package/src/Prebuilt/common/constants.ts +5 -6
- package/src/Prebuilt/common/hooks.ts +16 -0
- package/src/Prebuilt/common/utils.js +5 -6
- package/src/Prebuilt/components/AppData/AppData.tsx +1 -16
- package/src/Prebuilt/components/Chat/Chat.jsx +7 -30
- package/src/Prebuilt/components/Chat/ChatBody.jsx +107 -66
- package/src/Prebuilt/components/Chat/ChatFooter.tsx +21 -12
- package/src/Prebuilt/components/Chat/ChatSelector.tsx +25 -25
- package/src/Prebuilt/components/Chat/ChatSelectorContainer.tsx +15 -16
- package/src/Prebuilt/components/Chat/PinnedMessage.tsx +7 -2
- package/src/Prebuilt/components/ConferenceScreen.tsx +2 -0
- package/src/Prebuilt/components/Footer/ChatToggle.tsx +30 -7
- package/src/Prebuilt/components/Footer/Footer.tsx +2 -1
- package/src/Prebuilt/components/Footer/PaginatedParticipants.tsx +0 -1
- package/src/Prebuilt/components/Footer/{ParticipantList.jsx → ParticipantList.tsx} +169 -127
- package/src/Prebuilt/components/Footer/RoleAccordion.tsx +23 -13
- package/src/Prebuilt/components/Footer/WhiteboardToggle.tsx +34 -0
- package/src/Prebuilt/components/Notifications/HandRaisedNotifications.tsx +35 -0
- package/src/Prebuilt/components/Notifications/Notifications.tsx +14 -12
- package/src/Prebuilt/components/Notifications/PeerNotifications.tsx +7 -2
- package/src/Prebuilt/components/Polls/Voting/QuestionCard.jsx +10 -2
- package/src/Prebuilt/components/PreviousRoleInMetadata.tsx +21 -0
- package/src/Prebuilt/components/RemoveParticipant.tsx +35 -0
- package/src/Prebuilt/components/RoleChangeModal.jsx +1 -1
- package/src/Prebuilt/components/SidePaneTabs.tsx +0 -1
- package/src/Prebuilt/components/TileMenu/TileMenuContent.tsx +1 -1
- package/src/Prebuilt/components/Toast/ToastConfig.jsx +15 -3
- package/src/Prebuilt/components/VideoLayouts/GridLayout.tsx +5 -2
- package/src/Prebuilt/components/hooks/useCloseScreenshareWhiteboard.tsx +24 -0
- package/src/Prebuilt/layouts/VideoStreamingSection.tsx +20 -3
- package/src/Prebuilt/layouts/WhiteboardView.tsx +66 -0
- package/dist/chunk-HEOH5H43.js.map +0 -7
- package/src/Prebuilt/components/AppData/useAppLayout.js +0 -6
- package/src/Prebuilt/components/init/initUtils.js +0 -67
- /package/dist/{HLSView-MXBOUQBG.js.map → HLSView-EMUOLCTM.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.16",
|
14
14
|
"author": "100ms",
|
15
15
|
"license": "MIT",
|
16
16
|
"files": [
|
@@ -76,11 +76,11 @@
|
|
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.
|
83
|
-
"@100mslive/types-prebuilt": "0.12.
|
79
|
+
"@100mslive/hls-player": "0.1.25",
|
80
|
+
"@100mslive/hms-virtual-background": "1.11.25",
|
81
|
+
"@100mslive/react-icons": "0.8.25",
|
82
|
+
"@100mslive/react-sdk": "0.8.25",
|
83
|
+
"@100mslive/types-prebuilt": "0.12.5",
|
84
84
|
"@emoji-mart/data": "^1.0.6",
|
85
85
|
"@emoji-mart/react": "^1.0.1",
|
86
86
|
"@radix-ui/react-accordion": "1.0.0",
|
@@ -115,5 +115,5 @@
|
|
115
115
|
"uuid": "^8.3.2",
|
116
116
|
"worker-timers": "^7.0.40"
|
117
117
|
},
|
118
|
-
"gitHead": "
|
118
|
+
"gitHead": "096d50e1ffbeb9f2ec895b630952d2ad9694dfee"
|
119
119
|
}
|
@@ -55,7 +55,7 @@ export const useAppStateManager = () => {
|
|
55
55
|
setActiveState(PrebuiltStates.MEETING);
|
56
56
|
} else if (
|
57
57
|
prevRoomState &&
|
58
|
-
[HMSRoomState.Reconnecting, HMSRoomState.Connected].includes(prevRoomState) &&
|
58
|
+
[HMSRoomState.Reconnecting, HMSRoomState.Connected, HMSRoomState.Connecting].includes(prevRoomState) &&
|
59
59
|
[HMSRoomState.Disconnecting, HMSRoomState.Disconnected].includes(roomState)
|
60
60
|
) {
|
61
61
|
const goTo = isPreviewScreenEnabled ? PrebuiltStates.PREVIEW : PrebuiltStates.MEETING;
|
@@ -53,6 +53,7 @@ class PeersSorter {
|
|
53
53
|
|
54
54
|
moveSpeakerToFront = (speaker?: HMSPeer) => {
|
55
55
|
if (!speaker) {
|
56
|
+
this.maintainLruSize(this.tilesPerPage);
|
56
57
|
this.updateListeners();
|
57
58
|
return;
|
58
59
|
}
|
@@ -62,11 +63,9 @@ class PeersSorter {
|
|
62
63
|
}
|
63
64
|
// delete to insert at beginning
|
64
65
|
this.lruPeers.delete(speaker.id);
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
}
|
69
|
-
this.lruPeers = new Set([speaker.id, ...lruPeerArray]);
|
66
|
+
// - 1 as we are going to insert the new speaker
|
67
|
+
this.maintainLruSize(this.tilesPerPage - 1);
|
68
|
+
this.lruPeers = new Set([speaker.id, ...this.lruPeers]);
|
70
69
|
this.updateListeners();
|
71
70
|
};
|
72
71
|
|
@@ -98,6 +97,14 @@ class PeersSorter {
|
|
98
97
|
});
|
99
98
|
this.listeners.forEach(listener => listener?.(orderedPeers));
|
100
99
|
};
|
100
|
+
|
101
|
+
private maintainLruSize = (size: number) => {
|
102
|
+
const lruPeerArray = Array.from(this.lruPeers);
|
103
|
+
while (lruPeerArray.length > size && lruPeerArray.length) {
|
104
|
+
lruPeerArray.pop();
|
105
|
+
}
|
106
|
+
this.lruPeers = new Set(lruPeerArray);
|
107
|
+
};
|
101
108
|
}
|
102
109
|
|
103
110
|
export default PeersSorter;
|
@@ -17,7 +17,7 @@ export const RTMP_RECORD_DEFAULT_RESOLUTION = {
|
|
17
17
|
export const EMOJI_REACTION_TYPE = 'EMOJI_REACTION';
|
18
18
|
|
19
19
|
export const CHAT_SELECTOR = {
|
20
|
-
|
20
|
+
PEER: 'peer',
|
21
21
|
ROLE: 'role',
|
22
22
|
EVERYONE: 'Everyone',
|
23
23
|
};
|
@@ -33,7 +33,6 @@ export const APP_DATA = {
|
|
33
33
|
waitingViewerRole: 'waitingViewerRole',
|
34
34
|
subscribedNotifications: 'subscribedNotifications',
|
35
35
|
logo: 'logo',
|
36
|
-
appLayout: 'appLayout',
|
37
36
|
hlsStarted: 'hlsStarted',
|
38
37
|
rtmpStarted: 'rtmpStarted',
|
39
38
|
recordingStarted: 'recordingStarted',
|
@@ -122,15 +121,15 @@ export enum INTERACTION_TYPE {
|
|
122
121
|
export enum QUESTION_TYPE_TITLE {
|
123
122
|
'single-choice' = 'Single Choice',
|
124
123
|
'multiple-choice' = 'Multiple Choice',
|
125
|
-
|
126
|
-
|
124
|
+
'short-answer' = 'Short Answer',
|
125
|
+
'long-answer' = 'Long Answer',
|
127
126
|
}
|
128
127
|
|
129
128
|
export enum QUESTION_TYPE {
|
130
129
|
SINGLE_CHOICE = 'single-choice',
|
131
130
|
MULTIPLE_CHOICE = 'multiple-choice',
|
132
|
-
|
133
|
-
|
131
|
+
SHORT_ANSWER = 'short-answer',
|
132
|
+
LONG_ANSWER = 'long-answer',
|
134
133
|
}
|
135
134
|
|
136
135
|
export const ROLE_CHANGE_DECLINED = 'role_change_declined';
|
@@ -12,6 +12,7 @@ import {
|
|
12
12
|
} from '@100mslive/react-sdk';
|
13
13
|
import { useRoomLayout } from '../provider/roomLayoutProvider';
|
14
14
|
import { useRoomLayoutConferencingScreen } from '../provider/roomLayoutProvider/hooks/useRoomLayoutScreen';
|
15
|
+
import { CHAT_SELECTOR } from './constants';
|
15
16
|
/**
|
16
17
|
* Hook to execute a callback when alone in room(after a certain 5d of time)
|
17
18
|
* @param {number} thresholdMs The threshold(in ms) after which the callback is executed,
|
@@ -55,6 +56,21 @@ export const useFilteredRoles = () => {
|
|
55
56
|
return elements?.chat?.roles_whitelist || [];
|
56
57
|
};
|
57
58
|
|
59
|
+
export const useDefaultChatSelection = () => {
|
60
|
+
const { elements } = useRoomLayoutConferencingScreen();
|
61
|
+
const roles = useFilteredRoles();
|
62
|
+
// default is everyone for public chat
|
63
|
+
if (elements?.chat?.public_chat_enabled) {
|
64
|
+
return CHAT_SELECTOR.EVERYONE;
|
65
|
+
}
|
66
|
+
// sending first role as default
|
67
|
+
if (roles.length > 0) {
|
68
|
+
return roles[0];
|
69
|
+
}
|
70
|
+
// sending empty
|
71
|
+
return '';
|
72
|
+
};
|
73
|
+
|
58
74
|
export const useShowStreamingUI = () => {
|
59
75
|
const layout = useRoomLayout();
|
60
76
|
const { join_form } = layout?.screens?.preview?.default?.elements || {};
|
@@ -1,4 +1,3 @@
|
|
1
|
-
import { isEqual } from 'lodash';
|
2
1
|
import { QUESTION_TYPE } from './constants';
|
3
2
|
|
4
3
|
// eslint-disable-next-line complexity
|
@@ -159,11 +158,11 @@ export const getPeerParticipationSummary = (poll, localPeerID, localCustomerUser
|
|
159
158
|
if (!peerResponse?.[0]) {
|
160
159
|
return;
|
161
160
|
}
|
162
|
-
const
|
163
|
-
|
164
|
-
|
165
|
-
questions[peerResponse[0].questionIndex - 1].
|
166
|
-
|
161
|
+
const isCorrect = checkCorrectAnswer(
|
162
|
+
questions[peerResponse[0].questionIndex - 1].answer,
|
163
|
+
peerResponse[0],
|
164
|
+
questions[peerResponse[0].questionIndex - 1].type,
|
165
|
+
);
|
167
166
|
if (isCorrect) {
|
168
167
|
score += questions[peerResponse[0].questionIndex - 1]?.weight || 0;
|
169
168
|
correctResponses++;
|
@@ -1,11 +1,8 @@
|
|
1
1
|
import React, { useEffect } from 'react';
|
2
2
|
import {
|
3
3
|
HMSRoomState,
|
4
|
-
selectAvailableRoleNames,
|
5
4
|
selectFullAppData,
|
6
5
|
selectHLSState,
|
7
|
-
selectLocalPeerRoleName,
|
8
|
-
selectRolesMap,
|
9
6
|
selectRoomState,
|
10
7
|
selectRTMPState,
|
11
8
|
useHMSActions,
|
@@ -13,8 +10,6 @@ import {
|
|
13
10
|
useRecordingStreaming,
|
14
11
|
} from '@100mslive/react-sdk';
|
15
12
|
//@ts-ignore
|
16
|
-
import { normalizeAppPolicyConfig } from '../init/initUtils';
|
17
|
-
//@ts-ignore
|
18
13
|
import { UserPreferencesKeys, useUserPreferences } from '../hooks/useUserPreferences';
|
19
14
|
// @ts-ignore
|
20
15
|
import { useIsSidepaneTypeOpen, useSidepaneToggle } from './useSidepane';
|
@@ -49,7 +44,7 @@ const initialAppData = {
|
|
49
44
|
[APP_DATA.chatOpen]: false,
|
50
45
|
[APP_DATA.chatSelector]: {
|
51
46
|
[CHAT_SELECTOR.ROLE]: '',
|
52
|
-
[CHAT_SELECTOR.
|
47
|
+
[CHAT_SELECTOR.PEER]: {},
|
53
48
|
},
|
54
49
|
[APP_DATA.chatDraft]: '',
|
55
50
|
[APP_DATA.sidePane]: '',
|
@@ -73,9 +68,6 @@ const initialAppData = {
|
|
73
68
|
export const AppData = React.memo(() => {
|
74
69
|
const hmsActions = useHMSActions();
|
75
70
|
const [preferences = {}] = useUserPreferences(UserPreferencesKeys.UI_SETTINGS);
|
76
|
-
const roleNames = useHMSStore(selectAvailableRoleNames);
|
77
|
-
const rolesMap = useHMSStore(selectRolesMap);
|
78
|
-
const localPeerRole = useHMSStore(selectLocalPeerRoleName);
|
79
71
|
const appData = useHMSStore(selectFullAppData);
|
80
72
|
|
81
73
|
useEffect(() => {
|
@@ -109,13 +101,6 @@ export const AppData = React.memo(() => {
|
|
109
101
|
hmsActions.setAppData(APP_DATA.subscribedNotifications, preferences.subscribedNotifications, true);
|
110
102
|
}, [preferences.subscribedNotifications, hmsActions]);
|
111
103
|
|
112
|
-
useEffect(() => {
|
113
|
-
if (localPeerRole) {
|
114
|
-
const config = normalizeAppPolicyConfig(roleNames, rolesMap);
|
115
|
-
hmsActions.setAppData(APP_DATA.appLayout, config[localPeerRole]);
|
116
|
-
}
|
117
|
-
}, [roleNames, rolesMap, localPeerRole, hmsActions]);
|
118
|
-
|
119
104
|
return <ResetStreamingStart />;
|
120
105
|
});
|
121
106
|
|
@@ -1,13 +1,7 @@
|
|
1
|
-
import React, { useCallback,
|
1
|
+
import React, { useCallback, useRef, useState } from 'react';
|
2
2
|
import { useMedia } from 'react-use';
|
3
|
-
import { selectLocalPeer,
|
4
|
-
import {
|
5
|
-
HMSNotificationTypes,
|
6
|
-
selectHMSMessagesCount,
|
7
|
-
useHMSActions,
|
8
|
-
useHMSNotifications,
|
9
|
-
useHMSStore,
|
10
|
-
} from '@100mslive/react-sdk';
|
3
|
+
import { selectLocalPeer, selectSessionStore, selectUnreadHMSMessagesCount } from '@100mslive/hms-video-store';
|
4
|
+
import { selectHMSMessagesCount, useHMSActions, useHMSStore } from '@100mslive/react-sdk';
|
11
5
|
import { ChevronDownIcon } from '@100mslive/react-icons';
|
12
6
|
import { Button } from '../../../Button';
|
13
7
|
import { Flex } from '../../../Layout';
|
@@ -17,33 +11,18 @@ import { ChatFooter } from './ChatFooter';
|
|
17
11
|
import { ChatBlocked, ChatPaused } from './ChatStates';
|
18
12
|
import { PinnedMessage } from './PinnedMessage';
|
19
13
|
import { useRoomLayoutConferencingScreen } from '../../provider/roomLayoutProvider/hooks/useRoomLayoutScreen';
|
20
|
-
import { useSetSubscribedChatSelector } from '../AppData/useUISettings';
|
21
14
|
import { useSetPinnedMessages } from '../hooks/useSetPinnedMessages';
|
22
|
-
import {
|
23
|
-
import { CHAT_SELECTOR, SESSION_STORE_KEY } from '../../common/constants';
|
15
|
+
import { SESSION_STORE_KEY } from '../../common/constants';
|
24
16
|
|
25
17
|
export const Chat = () => {
|
26
18
|
const { elements, screenType } = useRoomLayoutConferencingScreen();
|
27
|
-
const notification = useHMSNotifications(HMSNotificationTypes.PEER_LEFT);
|
28
|
-
const [selectedPeer, setPeerSelector] = useSetSubscribedChatSelector(CHAT_SELECTOR.PEER_ID);
|
29
|
-
const [selectedRole, setRoleSelector] = useSetSubscribedChatSelector(CHAT_SELECTOR.ROLE);
|
30
19
|
const localPeer = useHMSStore(selectLocalPeer);
|
31
20
|
const [isSelectorOpen] = useState(false);
|
32
21
|
const listRef = useRef(null);
|
33
22
|
const hmsActions = useHMSActions();
|
34
23
|
const { removePinnedMessage } = useSetPinnedMessages();
|
35
24
|
const pinnedMessages = useHMSStore(selectSessionStore(SESSION_STORE_KEY.PINNED_MESSAGES)) || [];
|
36
|
-
const isPeerPresent = !!useHMSStore(selectPeerByID(selectedPeer));
|
37
25
|
|
38
|
-
useEffect(() => {
|
39
|
-
if (notification && notification.data && selectedPeer === notification.data.id) {
|
40
|
-
setPeerSelector('');
|
41
|
-
setRoleSelector('');
|
42
|
-
}
|
43
|
-
if (selectedPeer && !isPeerPresent) {
|
44
|
-
setPeerSelector('');
|
45
|
-
}
|
46
|
-
}, [notification, selectedPeer, setPeerSelector, setRoleSelector, isPeerPresent]);
|
47
26
|
const blacklistedPeerIDs = useHMSStore(selectSessionStore(SESSION_STORE_KEY.CHAT_PEER_BLACKLIST)) || [];
|
48
27
|
const blacklistedPeerIDSet = new Set(blacklistedPeerIDs);
|
49
28
|
const isLocalPeerBlacklisted = blacklistedPeerIDSet.has(localPeer?.customerUserId);
|
@@ -97,17 +76,15 @@ export const Chat = () => {
|
|
97
76
|
|
98
77
|
{isChatEnabled && !isLocalPeerBlacklisted ? (
|
99
78
|
<ChatFooter onSend={() => scrollToBottom(1)} screenType={screenType}>
|
100
|
-
{!isSelectorOpen && !isScrolledToBottom &&
|
101
|
-
<NewMessageIndicator role={selectedRole} peerId={selectedPeer} scrollToBottom={scrollToBottom} />
|
102
|
-
)}
|
79
|
+
{!isSelectorOpen && !isScrolledToBottom && <NewMessageIndicator scrollToBottom={scrollToBottom} />}
|
103
80
|
</ChatFooter>
|
104
81
|
) : null}
|
105
82
|
</Flex>
|
106
83
|
);
|
107
84
|
};
|
108
85
|
|
109
|
-
const NewMessageIndicator = ({
|
110
|
-
const unreadCount =
|
86
|
+
const NewMessageIndicator = ({ scrollToBottom }) => {
|
87
|
+
const unreadCount = useHMSStore(selectUnreadHMSMessagesCount);
|
111
88
|
if (!unreadCount) {
|
112
89
|
return null;
|
113
90
|
}
|
@@ -7,10 +7,11 @@ import {
|
|
7
7
|
selectHMSMessages,
|
8
8
|
selectLocalPeerID,
|
9
9
|
selectLocalPeerName,
|
10
|
-
|
11
|
-
|
10
|
+
selectLocalPeerRoleName,
|
11
|
+
selectPeerNameByID,
|
12
12
|
selectPermissions,
|
13
13
|
selectSessionStore,
|
14
|
+
selectUnreadHMSMessagesCount,
|
14
15
|
useHMSActions,
|
15
16
|
useHMSStore,
|
16
17
|
} from '@100mslive/react-sdk';
|
@@ -19,6 +20,7 @@ import {
|
|
19
20
|
CrossCircleIcon,
|
20
21
|
CrossIcon,
|
21
22
|
EyeCloseIcon,
|
23
|
+
PeopleRemoveIcon,
|
22
24
|
PinIcon,
|
23
25
|
ReplyIcon,
|
24
26
|
VerticalMenuIcon,
|
@@ -34,10 +36,9 @@ import emptyChat from '../../images/empty-chat.svg';
|
|
34
36
|
import { ToastManager } from '../Toast/ToastManager';
|
35
37
|
import { MwebChatOption } from './MwebChatOption';
|
36
38
|
import { useRoomLayoutConferencingScreen } from '../../provider/roomLayoutProvider/hooks/useRoomLayoutScreen';
|
37
|
-
import { useSetSubscribedChatSelector
|
39
|
+
import { useSetSubscribedChatSelector } from '../AppData/useUISettings';
|
38
40
|
import { useChatBlacklist } from '../hooks/useChatBlacklist';
|
39
41
|
import { useSetPinnedMessages } from '../hooks/useSetPinnedMessages';
|
40
|
-
import { useUnreadCount } from './useUnreadCount';
|
41
42
|
import { CHAT_SELECTOR, SESSION_STORE_KEY } from '../../common/constants';
|
42
43
|
|
43
44
|
const iconStyle = { height: '1.125rem', width: '1.125rem' };
|
@@ -70,27 +71,28 @@ const MessageTypeContainer = ({ left, right }) => {
|
|
70
71
|
<Flex
|
71
72
|
align="center"
|
72
73
|
css={{
|
73
|
-
|
74
|
-
right: 0,
|
75
|
-
zIndex: 1,
|
74
|
+
ml: '$2',
|
76
75
|
mr: '$4',
|
77
|
-
|
78
|
-
border: '1px solid $border_bright',
|
79
|
-
r: '$0',
|
80
|
-
gap: '$3',
|
76
|
+
gap: '$space$2',
|
81
77
|
}}
|
82
|
-
className="message_type_container"
|
83
78
|
>
|
84
79
|
{left && (
|
85
|
-
<SenderName
|
80
|
+
<SenderName
|
81
|
+
variant="xs"
|
82
|
+
as="span"
|
83
|
+
css={{ color: '$on_surface_medium', textTransform: 'capitalize', fontWeight: '$regular' }}
|
84
|
+
>
|
86
85
|
{left}
|
87
86
|
</SenderName>
|
88
87
|
)}
|
89
88
|
{right && (
|
90
89
|
<SenderName
|
91
90
|
as="span"
|
92
|
-
variant="
|
93
|
-
css={{
|
91
|
+
variant="overline"
|
92
|
+
css={{
|
93
|
+
color: '$on_surface_medium',
|
94
|
+
fontWeight: '$regular',
|
95
|
+
}}
|
94
96
|
>
|
95
97
|
{right}
|
96
98
|
</SenderName>
|
@@ -99,13 +101,17 @@ const MessageTypeContainer = ({ left, right }) => {
|
|
99
101
|
);
|
100
102
|
};
|
101
103
|
|
102
|
-
const MessageType = ({ roles, receiver }) => {
|
104
|
+
const MessageType = ({ roles, hasCurrentUserSent, receiver }) => {
|
105
|
+
const peerName = useHMSStore(selectPeerNameByID(receiver));
|
106
|
+
const localPeerRoleName = useHMSStore(selectLocalPeerRoleName);
|
103
107
|
if (receiver) {
|
104
|
-
return
|
108
|
+
return (
|
109
|
+
<MessageTypeContainer left={hasCurrentUserSent ? `${peerName ? `to ${peerName}` : ''}` : 'to You'} right="(DM)" />
|
110
|
+
);
|
105
111
|
}
|
106
112
|
|
107
|
-
if (roles && roles.length
|
108
|
-
return <MessageTypeContainer left=
|
113
|
+
if (roles && roles.length) {
|
114
|
+
return <MessageTypeContainer left={`to ${hasCurrentUserSent ? roles[0] : localPeerRoleName}`} right="(Group)" />;
|
109
115
|
}
|
110
116
|
return null;
|
111
117
|
};
|
@@ -153,8 +159,8 @@ const getMessageType = ({ roles, receiver }) => {
|
|
153
159
|
const ChatActions = ({
|
154
160
|
onPin,
|
155
161
|
showPinAction,
|
156
|
-
|
157
|
-
|
162
|
+
onReply,
|
163
|
+
showReply,
|
158
164
|
message,
|
159
165
|
sentByLocalPeer,
|
160
166
|
isMobile,
|
@@ -167,6 +173,8 @@ const ChatActions = ({
|
|
167
173
|
can_block_user: false,
|
168
174
|
};
|
169
175
|
const [open, setOpen] = useState(false);
|
176
|
+
const actions = useHMSActions();
|
177
|
+
const canRemoveOthers = useHMSStore(selectPermissions)?.removeOthers;
|
170
178
|
const { blacklistItem: blacklistPeer } = useChatBlacklist(SESSION_STORE_KEY.CHAT_PEER_BLACKLIST);
|
171
179
|
|
172
180
|
const { blacklistItem: blacklistMessage, blacklistedIDs: blacklistedMessageIDs = [] } = useChatBlacklist(
|
@@ -199,11 +207,11 @@ const ChatActions = ({
|
|
199
207
|
|
200
208
|
const options = {
|
201
209
|
reply: {
|
202
|
-
text: 'Reply Privately',
|
203
|
-
tooltipText: 'Reply
|
210
|
+
text: message.recipientRoles?.length ? 'Reply to Group' : 'Reply Privately',
|
211
|
+
tooltipText: message.recipientRoles?.length ? 'Reply to Group' : 'Reply Privately',
|
204
212
|
icon: <ReplyIcon style={iconStyle} />,
|
205
|
-
onClick:
|
206
|
-
show:
|
213
|
+
onClick: onReply,
|
214
|
+
show: showReply,
|
207
215
|
},
|
208
216
|
pin: {
|
209
217
|
text: 'Pin message',
|
@@ -220,7 +228,7 @@ const ChatActions = ({
|
|
220
228
|
show: true,
|
221
229
|
},
|
222
230
|
hide: {
|
223
|
-
text: 'Hide for everyone',
|
231
|
+
text: message.recipientPeer ? 'Hide for both' : 'Hide for everyone',
|
224
232
|
icon: <EyeCloseIcon style={iconStyle} />,
|
225
233
|
onClick: async () => {
|
226
234
|
blacklistMessage(message.id);
|
@@ -235,6 +243,19 @@ const ChatActions = ({
|
|
235
243
|
color: '$alert_error_default',
|
236
244
|
show: can_block_user && !sentByLocalPeer,
|
237
245
|
},
|
246
|
+
remove: {
|
247
|
+
text: 'Remove Partipant',
|
248
|
+
icon: <PeopleRemoveIcon style={iconStyle} />,
|
249
|
+
color: '$alert_error_default',
|
250
|
+
show: canRemoveOthers && !sentByLocalPeer,
|
251
|
+
onClick: async () => {
|
252
|
+
try {
|
253
|
+
await actions.removePeer(message.sender, '');
|
254
|
+
} catch (error) {
|
255
|
+
ToastManager.addToast({ title: error.message, variant: 'error' });
|
256
|
+
}
|
257
|
+
},
|
258
|
+
},
|
238
259
|
};
|
239
260
|
|
240
261
|
if (isMobile) {
|
@@ -316,7 +337,7 @@ const ChatActions = ({
|
|
316
337
|
</Tooltip>
|
317
338
|
) : null}
|
318
339
|
|
319
|
-
{options.block.show || options.hide.show ? (
|
340
|
+
{options.block.show || options.hide.show || options.remove.show ? (
|
320
341
|
<Tooltip boxCss={tooltipBoxCSS} title="More actions">
|
321
342
|
<Dropdown.Trigger asChild>
|
322
343
|
<IconButton>
|
@@ -353,6 +374,18 @@ const ChatActions = ({
|
|
353
374
|
</Text>
|
354
375
|
</Dropdown.Item>
|
355
376
|
) : null}
|
377
|
+
{options.remove.show ? (
|
378
|
+
<Dropdown.Item
|
379
|
+
data-testid="remove_peer_btn"
|
380
|
+
onClick={options.remove.onClick}
|
381
|
+
css={{ color: options.remove.color }}
|
382
|
+
>
|
383
|
+
{options.remove.icon}
|
384
|
+
<Text variant="sm" css={{ ml: '$4', color: 'inherit', fontWeight: '$semiBold' }}>
|
385
|
+
{options.remove.text}
|
386
|
+
</Text>
|
387
|
+
</Dropdown.Item>
|
388
|
+
) : null}
|
356
389
|
</Dropdown.Content>
|
357
390
|
</Dropdown.Portal>
|
358
391
|
</Dropdown.Root>
|
@@ -363,7 +396,7 @@ const SenderName = styled(Text, {
|
|
363
396
|
overflow: 'hidden',
|
364
397
|
textOverflow: 'ellipsis',
|
365
398
|
whiteSpace: 'nowrap',
|
366
|
-
maxWidth: '
|
399
|
+
maxWidth: '14ch',
|
367
400
|
minWidth: 0,
|
368
401
|
color: '$on_surface_high',
|
369
402
|
fontWeight: '$semiBold',
|
@@ -381,20 +414,25 @@ const ChatMessage = React.memo(
|
|
381
414
|
}, [index, setRowHeight]);
|
382
415
|
const isMobile = useMedia(cssConfig.media.md);
|
383
416
|
const isPrivateChatEnabled = !!elements?.chat?.private_chat_enabled;
|
417
|
+
const roleWhiteList = elements?.chat?.roles_whitelist || [];
|
384
418
|
const isOverlay = elements?.chat?.is_overlay && isMobile;
|
385
419
|
const hmsActions = useHMSActions();
|
386
420
|
const localPeerId = useHMSStore(selectLocalPeerID);
|
387
|
-
const
|
388
|
-
const selectedPeer =
|
389
|
-
const selectedRole = useSubscribeChatSelector(CHAT_SELECTOR.ROLE);
|
390
|
-
const [, setPeerSelector] = useSetSubscribedChatSelector(CHAT_SELECTOR.PEER_ID);
|
421
|
+
const [selectedRole, setRoleSelector] = useSetSubscribedChatSelector(CHAT_SELECTOR.ROLE);
|
422
|
+
const [selectedPeer, setPeerSelector] = useSetSubscribedChatSelector(CHAT_SELECTOR.PEER);
|
391
423
|
const messageType = getMessageType({
|
392
424
|
roles: message.recipientRoles,
|
393
425
|
receiver: message.recipientPeer,
|
394
426
|
});
|
395
427
|
const [openSheet, setOpenSheet] = useState(false);
|
396
|
-
|
397
|
-
|
428
|
+
const showPinAction = !!elements?.chat?.allow_pinning_messages;
|
429
|
+
let showReply = false;
|
430
|
+
if (message.recipientRoles && roleWhiteList.includes(message.recipientRoles[0])) {
|
431
|
+
showReply = true;
|
432
|
+
} else if (message.sender !== selectedPeer.id && message.sender !== localPeerId && isPrivateChatEnabled) {
|
433
|
+
showReply = true;
|
434
|
+
}
|
435
|
+
|
398
436
|
useEffect(() => {
|
399
437
|
if (message.id && !message.read && inView) {
|
400
438
|
hmsActions.setMessageRead(true, message.id);
|
@@ -428,7 +466,7 @@ const ChatMessage = React.memo(
|
|
428
466
|
position: 'relative',
|
429
467
|
// Theme independent color, token should not be used for transparent chat
|
430
468
|
bg:
|
431
|
-
messageType && !(selectedPeer || selectedRole)
|
469
|
+
messageType && !(selectedPeer.id || selectedRole)
|
432
470
|
? isOverlay
|
433
471
|
? 'rgba(0, 0, 0, 0.64)'
|
434
472
|
: '$surface_default'
|
@@ -482,31 +520,45 @@ const ChatMessage = React.memo(
|
|
482
520
|
</SenderName>
|
483
521
|
</Tooltip>
|
484
522
|
)}
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
|
489
|
-
|
490
|
-
ml: '$2',
|
491
|
-
color: '$on_surface_medium',
|
492
|
-
flexShrink: 0,
|
493
|
-
}}
|
494
|
-
>
|
495
|
-
{formatTime(message.time)}
|
496
|
-
</Text>
|
497
|
-
) : null}
|
523
|
+
<MessageType
|
524
|
+
hasCurrentUserSent={message.sender === localPeerId}
|
525
|
+
receiver={message.recipientPeer}
|
526
|
+
roles={message.recipientRoles}
|
527
|
+
/>
|
498
528
|
</Flex>
|
499
|
-
{!(selectedPeer || selectedRole) && (
|
500
|
-
<MessageType receiver={message.recipientPeer} roles={message.recipientRoles} />
|
501
|
-
)}
|
502
529
|
|
530
|
+
{!isOverlay ? (
|
531
|
+
<Text
|
532
|
+
as="span"
|
533
|
+
variant="caption"
|
534
|
+
css={{
|
535
|
+
color: '$on_surface_medium',
|
536
|
+
flexShrink: 0,
|
537
|
+
position: 'absolute',
|
538
|
+
right: 0,
|
539
|
+
zIndex: 1,
|
540
|
+
mr: '$4',
|
541
|
+
p: '$2',
|
542
|
+
}}
|
543
|
+
>
|
544
|
+
{formatTime(message.time)}
|
545
|
+
</Text>
|
546
|
+
) : null}
|
503
547
|
<ChatActions
|
504
548
|
onPin={onPin}
|
505
549
|
showPinAction={showPinAction}
|
506
550
|
message={message}
|
507
551
|
sentByLocalPeer={message.sender === localPeerId}
|
508
|
-
|
509
|
-
|
552
|
+
onReply={() => {
|
553
|
+
if (message.recipientRoles?.length) {
|
554
|
+
setRoleSelector(message.recipientRoles[0]);
|
555
|
+
setPeerSelector({});
|
556
|
+
} else {
|
557
|
+
setRoleSelector('');
|
558
|
+
setPeerSelector({ id: message.sender, name: message.senderName });
|
559
|
+
}
|
560
|
+
}}
|
561
|
+
showReply={showReply}
|
510
562
|
isMobile={isMobile}
|
511
563
|
openSheet={openSheet}
|
512
564
|
setOpenSheet={setOpenSheet}
|
@@ -622,27 +674,16 @@ const VirtualizedChatMessages = React.forwardRef(({ messages, unreadCount = 0, s
|
|
622
674
|
});
|
623
675
|
|
624
676
|
export const ChatBody = React.forwardRef(({ scrollToBottom }, listRef) => {
|
625
|
-
|
626
|
-
const selectedRole = useSubscribeChatSelector(CHAT_SELECTOR.ROLE);
|
627
|
-
let storeMessageSelector;
|
628
|
-
if (selectedRole) {
|
629
|
-
storeMessageSelector = selectMessagesByRole(selectedRole);
|
630
|
-
} else if (selectedPeer) {
|
631
|
-
storeMessageSelector = selectMessagesByPeerID(selectedPeer);
|
632
|
-
} else {
|
633
|
-
storeMessageSelector = selectHMSMessages;
|
634
|
-
}
|
635
|
-
let messages = useHMSStore(storeMessageSelector) || [];
|
677
|
+
let messages = useHMSStore(selectHMSMessages);
|
636
678
|
const blacklistedMessageIDs = useHMSStore(selectSessionStore(SESSION_STORE_KEY.CHAT_MESSAGE_BLACKLIST)) || [];
|
637
679
|
const getFilteredMessages = () => {
|
638
680
|
const blacklistedMessageIDSet = new Set(blacklistedMessageIDs);
|
639
|
-
|
640
681
|
return messages?.filter(message => message.type === 'chat' && !blacklistedMessageIDSet.has(message.id)) || [];
|
641
682
|
};
|
642
683
|
|
643
684
|
const isMobile = useMedia(cssConfig.media.md);
|
644
685
|
const { elements } = useRoomLayoutConferencingScreen();
|
645
|
-
const unreadCount =
|
686
|
+
const unreadCount = useHMSStore(selectUnreadHMSMessagesCount);
|
646
687
|
|
647
688
|
if (messages.length === 0 && !(isMobile && elements?.chat?.is_overlay)) {
|
648
689
|
return (
|