bigbluebutton-Github/bigbluebutton-html5/imports/ui/components/chat/container.jsx

270 lines
8.7 KiB
React
Raw Normal View History

import React, { useEffect, useContext, useState } from 'react';
2016-06-14 01:00:38 +08:00
import { defineMessages, injectIntl } from 'react-intl';
import { withTracker } from 'meteor/react-meteor-data';
import { throttle } from '/imports/utils/throttle';
import Auth from '/imports/ui/services/auth';
import Storage from '/imports/ui/services/storage/session';
import { meetingIsBreakout } from '/imports/ui/components/app/service';
import { ChatContext, getLoginTime } from '../components-data/chat-context/context';
import { GroupChatContext } from '../components-data/group-chat-context/context';
import { UsersContext } from '../components-data/users-context/context';
import ChatLogger from '/imports/ui/components/chat/chat-logger/ChatLogger';
import lockContextContainer from '/imports/ui/components/lock-viewers/context/container';
2021-05-18 04:25:07 +08:00
import Chat from '/imports/ui/components/chat/component';
2017-07-13 00:47:58 +08:00
import ChatService from './service';
2021-09-11 04:48:52 +08:00
import { layoutSelect, layoutDispatch } from '../layout/context';
import { escapeHtml } from '/imports/utils/string-utils';
2016-04-29 03:02:51 +08:00
const CHAT_CONFIG = Meteor.settings.public.chat;
const PUBLIC_CHAT_KEY = CHAT_CONFIG.public_id;
const PUBLIC_GROUP_CHAT_KEY = CHAT_CONFIG.public_group_id;
const CHAT_CLEAR = CHAT_CONFIG.system_messages_keys.chat_clear;
const SYSTEM_CHAT_TYPE = CHAT_CONFIG.type_system;
const ROLE_MODERATOR = Meteor.settings.public.user.role_moderator;
2021-02-04 04:49:58 +08:00
const DEBOUNCE_TIME = 1000;
2016-06-02 00:33:19 +08:00
const sysMessagesIds = {
welcomeId: `${SYSTEM_CHAT_TYPE}-welcome-msg`,
2021-03-10 04:52:20 +08:00
moderatorId: `${SYSTEM_CHAT_TYPE}-moderator-msg`,
2021-05-18 04:25:07 +08:00
syncId: `${SYSTEM_CHAT_TYPE}-sync-msg`,
2021-02-13 01:43:04 +08:00
};
2016-06-14 01:00:38 +08:00
const intlMessages = defineMessages({
[CHAT_CLEAR]: {
2017-11-23 21:00:41 +08:00
id: 'app.chat.clearPublicChatMessage',
description: 'message of when clear the public chat',
},
2016-06-14 01:00:38 +08:00
titlePublic: {
id: 'app.chat.titlePublic',
description: 'Public chat title',
},
titlePrivate: {
id: 'app.chat.titlePrivate',
description: 'Private chat title',
},
partnerDisconnected: {
id: 'app.chat.partnerDisconnected',
description: 'System chat message when the private chat partnet disconnect from the meeting',
},
2021-03-10 04:52:20 +08:00
loading: {
id: 'app.chat.loading',
description: 'loading message',
},
2016-06-14 01:00:38 +08:00
});
let previousChatId = null;
2021-03-10 04:52:20 +08:00
let prevSync = false;
let prevPartnerIsLoggedOut = false;
2021-03-10 04:52:20 +08:00
2021-05-18 04:25:07 +08:00
let globalAppplyStateToProps = () => { };
2021-02-04 04:49:58 +08:00
const throttledFunc = throttle(() => {
2021-02-04 04:49:58 +08:00
globalAppplyStateToProps();
2021-02-13 01:43:04 +08:00
}, DEBOUNCE_TIME, { trailing: true, leading: true });
2021-02-04 04:49:58 +08:00
const ChatContainer = (props) => {
const {
children,
loginTime,
intl,
userLocks,
lockSettings,
isChatLockedPublic,
isChatLockedPrivate,
users: propUsers,
...restProps
} = props;
2021-09-11 04:48:52 +08:00
const idChatOpen = layoutSelect((i) => i.idChatOpen);
const layoutContextDispatch = layoutDispatch();
2021-05-18 04:25:07 +08:00
const isPublicChat = idChatOpen === PUBLIC_CHAT_KEY;
const chatID = idChatOpen;
if (!chatID) return null;
useEffect(() => {
ChatService.removeFromClosedChatsSession();
}, []);
const modOnlyMessage = Storage.getItem('ModeratorOnlyMessage');
const { welcomeProp } = ChatService.getWelcomeProp();
2021-03-10 04:52:20 +08:00
ChatLogger.debug('ChatContainer::render::props', props);
const systemMessages = {
2021-02-13 01:43:04 +08:00
[sysMessagesIds.welcomeId]: {
id: sysMessagesIds.welcomeId,
content: [{
id: sysMessagesIds.welcomeId,
text: welcomeProp.welcomeMsg,
time: loginTime,
}],
key: sysMessagesIds.welcomeId,
time: loginTime,
sender: null,
},
[sysMessagesIds.moderatorId]: {
id: sysMessagesIds.moderatorId,
content: [{
id: sysMessagesIds.moderatorId,
text: modOnlyMessage,
2021-02-13 01:43:04 +08:00
time: loginTime + 1,
}],
key: sysMessagesIds.moderatorId,
2021-02-13 01:43:04 +08:00
time: loginTime + 1,
sender: null,
2021-05-18 04:25:07 +08:00
},
};
const usingUsersContext = useContext(UsersContext);
const { users } = usingUsersContext;
2021-04-15 20:12:21 +08:00
const currentUser = users[Auth.meetingID][Auth.userID];
const amIModerator = currentUser.role === ROLE_MODERATOR;
2021-05-18 04:25:07 +08:00
const systemMessagesIds = [
sysMessagesIds.welcomeId,
amIModerator && modOnlyMessage && sysMessagesIds.moderatorId,
].filter((i) => i);
const usingChatContext = useContext(ChatContext);
const usingGroupChatContext = useContext(GroupChatContext);
const [stateLastMsg, setLastMsg] = useState(null);
2021-05-18 04:25:07 +08:00
const [
stateTimeWindows, setTimeWindows,
] = useState(isPublicChat ? [...systemMessagesIds.map((item) => systemMessages[item])] : []);
const [lastTimeWindowValuesBuild, setLastTimeWindowValuesBuild] = useState(0);
2021-05-18 04:25:07 +08:00
const { groupChat } = usingGroupChatContext;
2021-05-18 04:25:07 +08:00
const participants = groupChat[idChatOpen]?.participants;
2021-02-13 01:43:04 +08:00
const chatName = participants?.filter((user) => user.id !== Auth.userID)[0]?.name;
2021-05-18 04:25:07 +08:00
const title = chatName
? intl.formatMessage(intlMessages.titlePrivate, { 0: chatName })
: intl.formatMessage(intlMessages.titlePublic);
2021-02-13 03:13:21 +08:00
let partnerIsLoggedOut = false;
let isChatLocked;
2021-05-18 04:25:07 +08:00
if (!isPublicChat) {
const idUser = participants?.filter((user) => user.id !== Auth.userID)[0]?.id;
2021-05-18 04:25:07 +08:00
partnerIsLoggedOut = !!(users[Auth.meetingID][idUser]?.loggedOut
|| users[Auth.meetingID][idUser]?.ejected);
2021-04-19 21:35:00 +08:00
isChatLocked = isChatLockedPrivate && !(users[Auth.meetingID][idUser]?.role === ROLE_MODERATOR);
} else {
isChatLocked = isChatLockedPublic;
}
const contextChat = usingChatContext?.chats[isPublicChat ? PUBLIC_GROUP_CHAT_KEY : chatID];
const lastTimeWindow = contextChat?.lastTimewindow;
2021-02-13 01:43:04 +08:00
const lastMsg = contextChat && (isPublicChat
2021-03-18 01:49:44 +08:00
? contextChat?.preJoinMessages[lastTimeWindow] || contextChat?.posJoinMessages[lastTimeWindow]
: contextChat?.messageGroups[lastTimeWindow]);
2021-05-18 04:25:07 +08:00
ChatLogger.debug('ChatContainer::render::chatData', contextChat);
const applyPropsToState = () => {
ChatLogger.debug('ChatContainer::applyPropsToState::chatData', lastMsg, stateLastMsg, contextChat?.syncing);
2021-03-10 04:52:20 +08:00
if (
(lastMsg?.lastTimestamp !== stateLastMsg?.lastTimestamp)
2021-05-18 04:25:07 +08:00
|| (previousChatId !== idChatOpen)
2021-03-10 04:52:20 +08:00
|| (prevSync !== contextChat?.syncing)
|| (prevPartnerIsLoggedOut !== partnerIsLoggedOut)
2021-05-18 04:25:07 +08:00
) {
2021-03-10 04:52:20 +08:00
prevSync = contextChat?.syncing;
prevPartnerIsLoggedOut = partnerIsLoggedOut;
2021-02-13 01:43:04 +08:00
const timeWindowsValues = isPublicChat
2021-03-10 04:52:20 +08:00
? [
...(
!contextChat?.syncing ? Object.values(contextChat?.preJoinMessages || {}) : [
{
id: sysMessagesIds.syncId,
content: [{
id: 'synced',
2021-05-18 04:25:07 +08:00
text: intl.formatMessage(intlMessages.loading, { 0: contextChat?.syncedPercent }),
2021-03-10 04:52:20 +08:00
time: loginTime + 1,
}],
key: sysMessagesIds.syncId,
time: loginTime + 1,
sender: null,
2021-05-18 04:25:07 +08:00
},
2021-03-10 04:52:20 +08:00
]
2021-05-18 04:25:07 +08:00
), ...systemMessagesIds.map((item) => systemMessages[item]),
...Object.values(contextChat?.posJoinMessages || {})]
2021-02-13 01:43:04 +08:00
: [...Object.values(contextChat?.messageGroups || {})];
2021-05-18 04:25:07 +08:00
if (previousChatId !== idChatOpen) {
previousChatId = idChatOpen;
2021-02-13 01:43:04 +08:00
}
if (partnerIsLoggedOut) {
const time = Date.now();
const id = `partner-disconnected-${time}`;
const messagePartnerLoggedOut = {
id,
content: [{
id,
text: escapeHtml(intl.formatMessage(intlMessages.partnerDisconnected, { 0: chatName })),
time,
}],
time,
sender: null,
};
timeWindowsValues.push(messagePartnerLoggedOut);
}
2021-02-13 01:43:04 +08:00
setLastMsg(lastMsg ? { ...lastMsg } : lastMsg);
setTimeWindows(timeWindowsValues);
setLastTimeWindowValuesBuild(Date.now());
}
2021-05-18 04:25:07 +08:00
};
2021-02-13 01:43:04 +08:00
globalAppplyStateToProps = applyPropsToState;
throttledFunc();
ChatService.removePackagedClassAttribute(
2021-05-18 04:25:07 +08:00
['ReactVirtualized__Grid', 'ReactVirtualized__Grid__innerScrollContainer'],
'role',
);
return (
2021-02-13 01:43:04 +08:00
<Chat {...{
2021-05-18 04:25:07 +08:00
idChatOpen,
isChatLocked,
2021-05-18 04:25:07 +08:00
...restProps,
2021-02-13 01:43:04 +08:00
chatID,
amIModerator,
count: (contextChat?.unreadTimeWindows.size || 0),
timeWindowsValues: stateTimeWindows,
dispatch: usingChatContext?.dispatch,
title,
2021-03-10 04:52:20 +08:00
syncing: contextChat?.syncing,
syncedPercent: contextChat?.syncedPercent,
2021-02-13 01:43:04 +08:00
chatName,
2021-05-18 04:25:07 +08:00
contextChat,
2021-08-05 19:03:24 +08:00
layoutContextDispatch,
lastTimeWindowValuesBuild,
2021-05-18 04:25:07 +08:00
partnerIsLoggedOut,
}}
>
{children}
</Chat>
);
};
2016-04-29 03:02:51 +08:00
export default lockContextContainer(injectIntl(withTracker(({ intl, userLocks }) => {
const isChatLockedPublic = userLocks.userPublicChat;
const isChatLockedPrivate = userLocks.userPrivateChat;
2019-06-27 00:29:34 +08:00
const { connected: isMeteorConnected } = Meteor.status();
2016-06-02 00:33:19 +08:00
return {
intl,
isChatLockedPublic,
isChatLockedPrivate,
2019-06-27 00:29:34 +08:00
isMeteorConnected,
meetingIsBreakout: meetingIsBreakout(),
loginTime: getLoginTime(),
2016-06-03 02:40:27 +08:00
actions: {
handleClosePrivateChat: ChatService.closePrivateChat,
2016-06-03 02:40:27 +08:00
},
2016-06-02 00:33:19 +08:00
};
})(ChatContainer)));