bigbluebutton-Github/bigbluebutton-html5/imports/ui/components/chat/service.js

233 lines
6.5 KiB
JavaScript
Raw Normal View History

2017-07-12 20:42:16 +08:00
import Chats from '/imports/api/2.0/chat';
import Users from '/imports/api/2.0/users';
2017-09-01 05:29:18 +08:00
import Meetings from '/imports/api/2.0/meetings';
import Auth from '/imports/ui/services/auth';
2016-07-05 02:53:47 +08:00
import UnreadMessages from '/imports/ui/services/unread-messages';
2017-03-01 06:40:16 +08:00
import Storage from '/imports/ui/services/storage/session';
2017-08-01 21:10:12 +08:00
import mapUser from '/imports/ui/services/user/mapUser';
2017-04-26 21:47:44 +08:00
import { makeCall } from '/imports/ui/services/api';
2017-03-22 05:52:10 +08:00
import _ from 'lodash';
const CHAT_CONFIG = Meteor.settings.public.chat;
const GROUPING_MESSAGES_WINDOW = CHAT_CONFIG.grouping_messages_window;
2016-06-02 00:33:19 +08:00
const SYSTEM_CHAT_TYPE = CHAT_CONFIG.type_system;
2017-08-05 01:58:55 +08:00
const PUBLIC_CHAT_TYPE = CHAT_CONFIG.type_public;
2016-06-02 00:33:19 +08:00
const PUBLIC_CHAT_ID = CHAT_CONFIG.public_id;
const PUBLIC_CHAT_USERID = CHAT_CONFIG.public_userid;
const PUBLIC_CHAT_USERNAME = CHAT_CONFIG.public_username;
2016-07-01 01:10:36 +08:00
const ScrollCollection = new Mongo.Collection(null);
// session for closed chat list
const CLOSED_CHAT_LIST_KEY = 'closedChatList';
2017-08-05 01:58:55 +08:00
const getUser = (userId) => {
const user = Users.findOne({ userId });
2017-07-12 21:18:26 +08:00
if (!user) {
return null;
}
2017-07-26 22:09:07 +08:00
return mapUser(user);
2017-07-12 21:18:26 +08:00
};
2017-08-05 01:58:55 +08:00
const mapMessage = (message) => {
2017-06-03 03:25:02 +08:00
const mappedMessage = {
2017-08-05 01:58:55 +08:00
id: message._id,
content: message.content,
2017-07-12 21:18:26 +08:00
time: message.fromTime, // + message.from_tz_offset,
sender: null,
};
2017-08-05 01:58:55 +08:00
if (message.type !== SYSTEM_CHAT_TYPE) {
mappedMessage.sender = getUser(message.fromUserId);
2016-06-02 00:33:19 +08:00
}
return mappedMessage;
};
2017-07-12 21:18:26 +08:00
const reduceMessages = (previous, current) => {
2017-06-03 03:25:02 +08:00
const lastMessage = previous[previous.length - 1];
2017-08-05 01:58:55 +08:00
const currentMessage = current;
2017-07-12 21:18:26 +08:00
2017-08-05 01:58:55 +08:00
currentMessage.content = [{
2016-07-12 04:10:55 +08:00
id: current._id,
2017-08-05 01:58:55 +08:00
text: current.message,
time: current.fromTime,
}];
2017-08-05 01:58:55 +08:00
if (!lastMessage || !currentMessage.type === SYSTEM_CHAT_TYPE) {
return previous.concat(currentMessage);
}
// Check if the last message is from the same user and time discrepancy
// between the two messages exceeds window and then group current message
// with the last one
2017-08-05 01:58:55 +08:00
if (lastMessage.fromUserId === currentMessage.fromUserId
&& (currentMessage.fromTime - lastMessage.fromTime) <= GROUPING_MESSAGES_WINDOW) {
lastMessage.content.push(currentMessage.content.pop());
return previous;
}
2017-08-05 01:58:55 +08:00
return previous.concat(currentMessage);
2016-06-03 02:40:27 +08:00
};
const reduceAndMapMessages = messages =>
(messages.reduce(reduceMessages, []).map(mapMessage));
2016-06-02 00:33:19 +08:00
const getPublicMessages = () => {
2017-06-03 03:25:02 +08:00
const publicMessages = Chats.find({
2017-08-05 01:58:55 +08:00
type: { $in: [PUBLIC_CHAT_TYPE, SYSTEM_CHAT_TYPE] },
}, {
2017-08-05 01:58:55 +08:00
sort: ['fromTime'],
2017-07-12 21:54:54 +08:00
}).fetch();
return publicMessages;
2016-06-02 00:33:19 +08:00
};
const getPrivateMessages = (userID) => {
2017-06-03 03:25:02 +08:00
const messages = Chats.find({
2017-08-05 01:58:55 +08:00
toUsername: { $ne: PUBLIC_CHAT_USERNAME },
$or: [
2017-08-05 01:58:55 +08:00
{ toUserId: userID },
{ fromUserId: userID },
],
}, {
2017-08-05 01:58:55 +08:00
sort: ['fromTime'],
2017-06-03 03:25:02 +08:00
}).fetch();
2016-06-02 00:33:19 +08:00
return reduceAndMapMessages(messages);
2016-06-02 00:33:19 +08:00
};
2016-06-14 01:00:38 +08:00
const isChatLocked = (receiverID) => {
const isPublic = receiverID === PUBLIC_CHAT_ID;
2017-09-01 05:29:18 +08:00
const meeting = Meetings.findOne({});
2017-09-07 01:50:48 +08:00
const user = Users.findOne({});
2017-09-07 02:13:24 +08:00
if (meeting.lockSettingsProp === 'undefined'){
2017-09-07 01:50:48 +08:00
return false;
}
2017-09-01 05:29:18 +08:00
const isPubChatLocked = meeting.lockSettingsProp.disablePubChat;
const isPrivChatLocked = meeting.lockSettingsProp.disablePrivChat;
2017-09-01 05:49:13 +08:00
const isViewer = user.role === "VIEWER";
2017-09-07 03:53:07 +08:00
return ((isPublic && isPubChatLocked && isViewer && user.locked) || (!isPublic && isPrivChatLocked && isViewer && user.locked));
2016-06-14 01:00:38 +08:00
};
2016-07-05 02:53:47 +08:00
const hasUnreadMessages = (receiverID) => {
const isPublic = receiverID === PUBLIC_CHAT_ID;
2017-07-12 21:18:26 +08:00
const chatType = isPublic ? PUBLIC_CHAT_USERID : receiverID;
2016-07-05 02:53:47 +08:00
2017-07-12 21:18:26 +08:00
return UnreadMessages.count(chatType) > 0;
2016-07-05 02:53:47 +08:00
};
2016-07-12 03:42:54 +08:00
const lastReadMessageTime = (receiverID) => {
const isPublic = receiverID === PUBLIC_CHAT_ID;
2017-07-12 21:18:26 +08:00
const chatType = isPublic ? PUBLIC_CHAT_USERID : receiverID;
2016-07-12 03:42:54 +08:00
2017-07-12 21:18:26 +08:00
return UnreadMessages.get(chatType);
2016-07-12 03:42:54 +08:00
};
2016-06-03 02:40:27 +08:00
const sendMessage = (receiverID, message) => {
const isPublic = receiverID === PUBLIC_CHAT_ID;
const sender = getUser(Auth.userID);
2016-06-03 02:40:27 +08:00
const receiver = !isPublic ? getUser(receiverID) : {
2016-07-05 02:53:47 +08:00
id: PUBLIC_CHAT_USERID,
name: PUBLIC_CHAT_USERNAME,
2016-06-03 02:40:27 +08:00
};
/* FIX: Why we need all this payload to send a message?
* The server only really needs the message, from_userid, to_userid and from_lang
*/
2017-06-03 03:25:02 +08:00
const messagePayload = {
message,
2017-07-12 20:42:16 +08:00
fromUserId: sender.id,
fromUsername: sender.name,
fromTimezoneOffset: (new Date()).getTimezoneOffset(),
toUsername: receiver.name,
toUserId: receiver.id,
fromTime: Date.now(),
fromColor: 0,
2016-06-03 02:40:27 +08:00
};
2016-06-02 00:33:19 +08:00
2017-06-03 03:25:02 +08:00
const currentClosedChats = Storage.getItem(CLOSED_CHAT_LIST_KEY);
2017-03-03 05:42:39 +08:00
// Remove the chat that user send messages from the session.
2017-03-22 05:52:10 +08:00
if (_.indexOf(currentClosedChats, receiver.id) > -1) {
Storage.setItem(CLOSED_CHAT_LIST_KEY, _.without(currentClosedChats, receiver.id));
2017-03-01 06:40:16 +08:00
}
return makeCall('sendChat', messagePayload);
2016-06-02 00:33:19 +08:00
};
2016-07-01 01:10:36 +08:00
const getScrollPosition = (receiverID) => {
2017-06-03 03:25:02 +08:00
const scroll = ScrollCollection.findOne({ receiver: receiverID }) || { position: null };
2016-07-01 01:10:36 +08:00
return scroll.position;
};
2016-07-05 02:53:47 +08:00
const updateScrollPosition =
(receiverID, position) => ScrollCollection.upsert(
{ receiver: receiverID },
2017-06-03 03:25:02 +08:00
{ $set: { position } },
2016-07-05 02:53:47 +08:00
);
const updateUnreadMessage = (receiverID, timestamp) => {
const isPublic = receiverID === PUBLIC_CHAT_ID;
2017-07-12 21:18:26 +08:00
const chatType = isPublic ? PUBLIC_CHAT_USERID : receiverID;
return UnreadMessages.update(chatType, timestamp);
2016-07-01 01:10:36 +08:00
};
2017-08-03 01:05:20 +08:00
const clearPublicChatHistory = () => (makeCall('clearPublicChatHistory'));
const closePrivateChat = (chatID) => {
2017-06-03 03:25:02 +08:00
const currentClosedChats = Storage.getItem(CLOSED_CHAT_LIST_KEY) || [];
2017-03-03 04:33:49 +08:00
2017-03-22 05:52:10 +08:00
if (_.indexOf(currentClosedChats, chatID) < 0) {
2017-03-03 04:33:49 +08:00
currentClosedChats.push(chatID);
Storage.setItem(CLOSED_CHAT_LIST_KEY, currentClosedChats);
}
2017-03-03 04:33:49 +08:00
};
// We decode to prevent HTML5 escaped characters.
const htmlDecode = (input) => {
const e = document.createElement('div');
e.innerHTML = input;
return e.childNodes[0].nodeValue;
};
// Export the chat as [Hour:Min] user: message
const exportChat = messageList => (
messageList.map((message) => {
const date = new Date(message.fromTime);
const hour = date.getHours().toString().padStart(2, 0);
const min = date.getMinutes().toString().padStart(2, 0);
const hourMin = `[${hour}:${min}]`;
if (message.type === SYSTEM_CHAT_TYPE) {
return `${hourMin} ${message.message}`;
}
return `${hourMin} ${message.fromUsername}: ${htmlDecode(message.message)}`;
2017-08-03 22:10:05 +08:00
}).join('\n')
);
2016-06-02 00:33:19 +08:00
export default {
reduceAndMapMessages,
2016-06-02 00:33:19 +08:00
getPublicMessages,
getPrivateMessages,
2016-06-07 22:19:19 +08:00
getUser,
2016-07-01 01:10:36 +08:00
getScrollPosition,
2016-07-05 02:53:47 +08:00
hasUnreadMessages,
2016-07-12 03:42:54 +08:00
lastReadMessageTime,
2016-06-14 01:00:38 +08:00
isChatLocked,
2016-07-05 02:53:47 +08:00
updateScrollPosition,
updateUnreadMessage,
2016-06-02 00:33:19 +08:00
sendMessage,
closePrivateChat,
exportChat,
2017-08-03 01:05:20 +08:00
clearPublicChatHistory,
2017-09-07 01:50:48 +08:00
};