2016-06-02 00:33:19 +08:00
|
|
|
import Chats from '/imports/api/chat';
|
|
|
|
import Users from '/imports/api/users';
|
2016-06-14 01:00:38 +08:00
|
|
|
import Meetings from '/imports/api/meetings';
|
|
|
|
|
2016-06-02 21:46:35 +08:00
|
|
|
import Auth from '/imports/ui/services/auth';
|
2016-07-05 02:53:47 +08:00
|
|
|
import UnreadMessages from '/imports/ui/services/unread-messages';
|
2016-06-02 21:00:57 +08:00
|
|
|
|
2016-06-03 02:40:27 +08:00
|
|
|
import { callServer } from '/imports/ui/services/api';
|
2016-06-02 21:00:57 +08:00
|
|
|
|
|
|
|
const GROUPING_MESSAGES_WINDOW = 60000;
|
2016-06-02 00:33:19 +08:00
|
|
|
|
|
|
|
const SYSTEM_CHAT_TYPE = 'SYSTEM_MESSAGE';
|
|
|
|
const PUBLIC_CHAT_TYPE = 'PUBLIC_CHAT';
|
|
|
|
const PRIVATE_CHAT_TYPE = 'PRIVATE_CHAT';
|
|
|
|
|
2016-06-03 02:40:27 +08:00
|
|
|
const PUBLIC_CHAT_ID = 'public';
|
2016-07-05 02:53:47 +08:00
|
|
|
const PUBLIC_CHAT_USERID = 'public_chat_userid';
|
|
|
|
const PUBLIC_CHAT_USERNAME = 'public_chat_username';
|
2016-06-02 21:00:57 +08:00
|
|
|
|
2016-07-01 01:10:36 +08:00
|
|
|
const ScrollCollection = new Mongo.Collection(null);
|
|
|
|
|
2016-06-02 21:00:57 +08:00
|
|
|
/* TODO: Same map is done in the user-list/service we should share this someway */
|
|
|
|
|
|
|
|
const mapUser = (user) => ({
|
|
|
|
id: user.userid,
|
|
|
|
name: user.name,
|
|
|
|
isPresenter: user.presenter,
|
|
|
|
isModerator: user.role === 'MODERATOR',
|
2016-07-11 21:45:24 +08:00
|
|
|
isCurrent: user.userid === Auth.userID,
|
2016-06-02 21:00:57 +08:00
|
|
|
isVoiceUser: user.voiceUser.joined,
|
|
|
|
isMuted: user.voiceUser.muted,
|
|
|
|
isListenOnly: user.listenOnly,
|
|
|
|
isSharingWebcam: user.webcam_stream.length,
|
2016-06-14 01:00:38 +08:00
|
|
|
isLocked: user.locked,
|
2016-06-02 21:00:57 +08:00
|
|
|
});
|
|
|
|
|
2016-07-11 20:34:58 +08:00
|
|
|
const mapMessage = (messagePayload, isPublic = false) => {
|
|
|
|
const { message } = messagePayload;
|
|
|
|
|
2016-06-02 21:00:57 +08:00
|
|
|
let mappedMessage = {
|
2016-07-11 20:34:58 +08:00
|
|
|
id: messagePayload._id,
|
2016-07-08 00:51:55 +08:00
|
|
|
content: [
|
|
|
|
{
|
2016-07-11 20:34:58 +08:00
|
|
|
id: messagePayload._id,
|
2016-07-08 00:51:55 +08:00
|
|
|
text: message.message,
|
|
|
|
time: message.from_time,
|
2016-07-11 20:34:58 +08:00
|
|
|
unread: message.from_time > UnreadMessages.get(isPublic ? PUBLIC_CHAT_USERID : message.from_userid),
|
2016-07-08 00:51:55 +08:00
|
|
|
},
|
|
|
|
],
|
|
|
|
time: message.from_time, //+ message.from_tz_offset,
|
2016-06-02 21:00:57 +08:00
|
|
|
sender: null,
|
|
|
|
};
|
|
|
|
|
2016-06-03 02:40:27 +08:00
|
|
|
if (message.chat_type !== SYSTEM_CHAT_TYPE) {
|
|
|
|
mappedMessage.sender = getUser(message.from_userid);
|
2016-06-02 00:33:19 +08:00
|
|
|
}
|
2016-06-02 21:00:57 +08:00
|
|
|
|
|
|
|
return mappedMessage;
|
|
|
|
};
|
|
|
|
|
|
|
|
const reduceMessages = (previous, current, index, array) => {
|
|
|
|
let lastMessage = previous[previous.length - 1];
|
|
|
|
|
|
|
|
if (!lastMessage || !lastMessage.sender || !current.sender) { // Skip system messages
|
|
|
|
return previous.concat(current);
|
|
|
|
}
|
|
|
|
|
|
|
|
// 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
|
|
|
|
|
|
|
|
if (lastMessage.sender.id === current.sender.id
|
|
|
|
&& (current.time - lastMessage.time) <= GROUPING_MESSAGES_WINDOW) {
|
2016-07-08 00:51:55 +08:00
|
|
|
lastMessage.content.push(current.content.pop());
|
2016-07-05 02:53:47 +08:00
|
|
|
lastMessage.timeLastMessage = current.time;
|
2016-06-02 21:00:57 +08:00
|
|
|
return previous;
|
|
|
|
} else {
|
|
|
|
return previous.concat(current);
|
|
|
|
}
|
|
|
|
};
|
2016-06-02 00:33:19 +08:00
|
|
|
|
2016-06-03 02:40:27 +08:00
|
|
|
const getUser = (userID) => {
|
|
|
|
const user = Users.findOne({ userId: userID });
|
|
|
|
if (user) {
|
|
|
|
return mapUser(user.user);
|
|
|
|
} else {
|
2016-06-14 01:00:38 +08:00
|
|
|
return null;
|
2016-06-03 02:40:27 +08:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2016-06-02 00:33:19 +08:00
|
|
|
const getPublicMessages = () => {
|
2016-06-02 21:00:57 +08:00
|
|
|
let publicMessages = Chats.find({
|
|
|
|
'message.chat_type': { $in: [PUBLIC_CHAT_TYPE, SYSTEM_CHAT_TYPE] },
|
|
|
|
}, {
|
|
|
|
sort: ['message.from_time'],
|
|
|
|
})
|
|
|
|
.fetch();
|
|
|
|
|
|
|
|
let systemMessage = Chats.findOne({ 'message.chat_type': SYSTEM_CHAT_TYPE });
|
2016-06-02 00:33:19 +08:00
|
|
|
|
2016-06-02 21:00:57 +08:00
|
|
|
return publicMessages
|
2016-07-11 20:34:58 +08:00
|
|
|
.map(mapMessage, true)
|
2016-06-02 21:00:57 +08:00
|
|
|
.reduce(reduceMessages, []);
|
2016-06-02 00:33:19 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
const getPrivateMessages = (userID) => {
|
|
|
|
let messages = Chats.find({
|
2016-06-02 21:00:57 +08:00
|
|
|
'message.chat_type': PRIVATE_CHAT_TYPE,
|
|
|
|
$or: [
|
|
|
|
{ 'message.to_userid': userID },
|
|
|
|
{ 'message.from_userid': userID },
|
|
|
|
],
|
|
|
|
}, {
|
|
|
|
sort: ['message.from_time'],
|
|
|
|
}).fetch();
|
2016-06-02 00:33:19 +08:00
|
|
|
|
2016-06-02 21:00:57 +08:00
|
|
|
return messages
|
|
|
|
.map(mapMessage)
|
|
|
|
.reduce(reduceMessages, []);
|
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;
|
2016-07-11 21:45:24 +08:00
|
|
|
const currentUser = getUser(Auth.userID);
|
2016-06-14 01:00:38 +08:00
|
|
|
const meeting = Meetings.findOne({});
|
|
|
|
|
|
|
|
const lockSettings = meeting.roomLockSettings || {
|
|
|
|
disablePublicChat: false,
|
|
|
|
disablePrivateChat: false,
|
|
|
|
};
|
|
|
|
|
|
|
|
if (!currentUser.isLocked || currentUser.isPresenter) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return isPublic ? lockSettings.disablePublicChat : lockSettings.disablePrivateChat;
|
|
|
|
};
|
|
|
|
|
2016-07-05 02:53:47 +08:00
|
|
|
const hasUnreadMessages = (receiverID) => {
|
|
|
|
const isPublic = receiverID === PUBLIC_CHAT_ID;
|
|
|
|
receiverID = isPublic ? PUBLIC_CHAT_USERID : receiverID;
|
|
|
|
|
|
|
|
return UnreadMessages.count(receiverID) > 0;
|
|
|
|
};
|
|
|
|
|
2016-06-03 02:40:27 +08:00
|
|
|
const sendMessage = (receiverID, message) => {
|
|
|
|
const isPublic = receiverID === PUBLIC_CHAT_ID;
|
|
|
|
|
2016-07-11 21:45:24 +08:00
|
|
|
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
|
|
|
|
*/
|
|
|
|
|
|
|
|
let messagePayload = {
|
|
|
|
message: message,
|
|
|
|
chat_type: isPublic ? PUBLIC_CHAT_TYPE : PRIVATE_CHAT_TYPE,
|
|
|
|
from_userid: sender.id,
|
|
|
|
from_username: sender.name,
|
|
|
|
from_tz_offset: (new Date()).getTimezoneOffset(),
|
|
|
|
to_username: receiver.name,
|
|
|
|
to_userid: receiver.id,
|
|
|
|
from_lang: window.navigator.userLanguage || window.navigator.language,
|
|
|
|
from_time: Date.now(),
|
|
|
|
from_color: 0,
|
|
|
|
};
|
2016-06-02 00:33:19 +08:00
|
|
|
|
2016-07-06 00:47:40 +08:00
|
|
|
callServer('sendChatMessagetoServer', messagePayload);
|
|
|
|
|
|
|
|
return messagePayload;
|
2016-06-02 00:33:19 +08:00
|
|
|
};
|
|
|
|
|
2016-07-01 01:10:36 +08:00
|
|
|
const getScrollPosition = (receiverID) => {
|
|
|
|
let scroll = ScrollCollection.findOne({ receiver: receiverID }) || { position: null };
|
|
|
|
return scroll.position;
|
|
|
|
};
|
|
|
|
|
2016-07-05 02:53:47 +08:00
|
|
|
const updateScrollPosition =
|
|
|
|
(receiverID, position) => ScrollCollection.upsert(
|
|
|
|
{ receiver: receiverID },
|
|
|
|
{ $set: { position: position } },
|
|
|
|
);
|
|
|
|
|
|
|
|
const updateUnreadMessage = (receiverID, timestamp) => {
|
|
|
|
const isPublic = receiverID === PUBLIC_CHAT_ID;
|
|
|
|
receiverID = isPublic ? PUBLIC_CHAT_USERID : receiverID;
|
|
|
|
return UnreadMessages.update(receiverID, timestamp);
|
2016-07-01 01:10:36 +08:00
|
|
|
};
|
|
|
|
|
2016-06-02 00:33:19 +08:00
|
|
|
export default {
|
|
|
|
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-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,
|
|
|
|
};
|