@100mslive/roomkit-react 0.1.15 → 0.1.17
Sign up to get free protection for your applications and to get access to all the features.
- package/dist/{HLSView-MXBOUQBG.js → HLSView-ADUOTLEX.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-NEXHITYN.js} +1882 -7116
- package/dist/chunk-NEXHITYN.js.map +7 -0
- package/dist/index.cjs.js +2479 -7668
- 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 +1 -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-ADUOTLEX.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.17",
|
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.26",
|
80
|
+
"@100mslive/hms-virtual-background": "1.11.26",
|
81
|
+
"@100mslive/react-icons": "0.8.26",
|
82
|
+
"@100mslive/react-sdk": "0.8.26",
|
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": "444a25f76180f142aa695a15df6f0bde06cb4a05"
|
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 (
|