2016-05-20 02:22:56 +08:00
|
|
|
import Users from '/imports/api/users';
|
2016-06-30 22:45:19 +08:00
|
|
|
import Chat from '/imports/api/chat';
|
2016-07-07 20:50:32 +08:00
|
|
|
import Auth from '/imports/ui/services/auth';
|
2016-07-11 20:34:58 +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';
|
2016-09-27 04:29:44 +08:00
|
|
|
import { EMOJI_STATUSES } from '/imports/utils/statuses.js';
|
2016-06-28 21:10:20 +08:00
|
|
|
|
|
|
|
import { callServer } from '/imports/ui/services/api';
|
2017-03-22 05:52:10 +08:00
|
|
|
import _ from 'lodash';
|
2016-06-07 00:45:30 +08:00
|
|
|
|
2016-08-17 23:48:03 +08:00
|
|
|
const CHAT_CONFIG = Meteor.settings.public.chat;
|
|
|
|
const USER_CONFIG = Meteor.settings.public.user;
|
|
|
|
const ROLE_MODERATOR = USER_CONFIG.role_moderator;
|
|
|
|
const PRIVATE_CHAT_TYPE = CHAT_CONFIG.type_private;
|
2016-06-07 00:45:30 +08:00
|
|
|
|
2017-03-17 23:27:37 +08:00
|
|
|
// session for closed chat list
|
|
|
|
const CLOSED_CHAT_LIST_KEY = 'closedChatList';
|
|
|
|
|
2016-06-07 00:45:30 +08:00
|
|
|
/* TODO: Same map is done in the chat/service we should share this someway */
|
|
|
|
|
2016-06-28 21:10:20 +08:00
|
|
|
const mapUser = user => ({
|
2016-06-07 00:45:30 +08:00
|
|
|
id: user.userid,
|
|
|
|
name: user.name,
|
2016-06-08 00:46:24 +08:00
|
|
|
emoji: {
|
|
|
|
status: user.emoji_status,
|
|
|
|
changedAt: user.set_emoji_time,
|
|
|
|
},
|
2016-06-07 00:45:30 +08:00
|
|
|
isPresenter: user.presenter,
|
|
|
|
isModerator: user.role === ROLE_MODERATOR,
|
2016-07-11 21:45:24 +08:00
|
|
|
isCurrent: user.userid === Auth.userID,
|
2016-06-07 00:45:30 +08:00
|
|
|
isVoiceUser: user.voiceUser.joined,
|
|
|
|
isMuted: user.voiceUser.muted,
|
2016-11-22 23:06:54 +08:00
|
|
|
isTalking: user.voiceUser.talking,
|
2016-06-07 00:45:30 +08:00
|
|
|
isListenOnly: user.listenOnly,
|
|
|
|
isSharingWebcam: user.webcam_stream.length,
|
2016-06-07 21:58:51 +08:00
|
|
|
isPhoneUser: user.phone_user,
|
2017-04-12 03:46:51 +08:00
|
|
|
isOnline:true
|
2016-06-07 00:45:30 +08:00
|
|
|
});
|
|
|
|
|
2016-06-28 21:10:20 +08:00
|
|
|
const mapOpenChats = chat => {
|
2016-07-11 21:45:24 +08:00
|
|
|
let currentUserId = Auth.userID;
|
|
|
|
return chat.message.from_userid !== Auth.userID
|
2016-06-28 21:10:20 +08:00
|
|
|
? chat.message.from_userid
|
|
|
|
: chat.message.to_userid;
|
|
|
|
};
|
|
|
|
|
2016-06-07 21:58:51 +08:00
|
|
|
const sortUsersByName = (a, b) => {
|
|
|
|
if (a.name.toLowerCase() < b.name.toLowerCase()) {
|
2016-06-07 00:45:30 +08:00
|
|
|
return -1;
|
2016-06-07 21:58:51 +08:00
|
|
|
} else if (a.name.toLowerCase() > b.name.toLowerCase()) {
|
2016-06-07 00:45:30 +08:00
|
|
|
return 1;
|
2016-06-07 21:58:51 +08:00
|
|
|
} else if (a.id.toLowerCase() > b.id.toLowerCase()) {
|
2016-06-07 00:45:30 +08:00
|
|
|
return -1;
|
2016-06-07 21:58:51 +08:00
|
|
|
} else if (a.id.toLowerCase() < b.id.toLowerCase()) {
|
2016-06-07 00:45:30 +08:00
|
|
|
return 1;
|
2016-06-07 21:58:51 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
};
|
|
|
|
|
|
|
|
const sortUsersByEmoji = (a, b) => {
|
2016-06-08 00:46:24 +08:00
|
|
|
if ((EMOJI_STATUSES.indexOf(a.emoji.status) > -1)
|
|
|
|
&& (EMOJI_STATUSES.indexOf(b.emoji.status) > -1)) {
|
|
|
|
if (a.emoji.changedAt < b.emoji.changedAt) {
|
|
|
|
return -1;
|
|
|
|
} else if (a.emoji.changedAt > b.emoji.changedAt) {
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2016-06-07 21:58:51 +08:00
|
|
|
return sortUsersByName(a, b);
|
2016-06-08 00:46:24 +08:00
|
|
|
} else if (EMOJI_STATUSES.indexOf(a.emoji.status) > -1) {
|
2016-06-07 00:45:30 +08:00
|
|
|
return -1;
|
2016-06-08 00:46:24 +08:00
|
|
|
} else if (EMOJI_STATUSES.indexOf(b.emoji.status) > -1) {
|
2016-06-07 00:45:30 +08:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2016-06-07 21:58:51 +08:00
|
|
|
return 0;
|
|
|
|
};
|
|
|
|
|
|
|
|
const sortUsersByModerator = (a, b) => {
|
|
|
|
if (a.isModerator && b.isModerator) {
|
2016-10-07 04:42:37 +08:00
|
|
|
return sortUsersByEmoji(a, b);
|
2016-06-07 21:58:51 +08:00
|
|
|
} else if (a.isModerator) {
|
2016-06-07 00:45:30 +08:00
|
|
|
return -1;
|
2016-06-07 21:58:51 +08:00
|
|
|
} else if (b.isModerator) {
|
2016-06-07 00:45:30 +08:00
|
|
|
return 1;
|
2016-06-07 21:58:51 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
};
|
|
|
|
|
|
|
|
const sortUsersByPhoneUser = (a, b) => {
|
2016-06-08 00:46:24 +08:00
|
|
|
if (!a.isPhoneUser && !b.isPhoneUser) {
|
2016-06-07 21:58:51 +08:00
|
|
|
return sortUsersByName(a, b);
|
2016-06-08 00:46:24 +08:00
|
|
|
} else if (!a.isPhoneUser) {
|
2016-06-07 00:45:30 +08:00
|
|
|
return -1;
|
2016-06-08 00:46:24 +08:00
|
|
|
} else if (!b.isPhoneUser) {
|
2016-06-07 00:45:30 +08:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
};
|
|
|
|
|
2016-06-07 21:58:51 +08:00
|
|
|
const sortUsers = (a, b) => {
|
2016-10-07 04:42:37 +08:00
|
|
|
let sort = sortUsersByModerator(a, b);
|
2016-06-07 21:58:51 +08:00
|
|
|
|
|
|
|
if (sort === 0) {
|
2016-10-07 04:42:37 +08:00
|
|
|
sort = sortUsersByEmoji(a, b);
|
2016-06-07 21:58:51 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (sort === 0) {
|
|
|
|
sort = sortUsersByPhoneUser(a, b);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sort === 0) {
|
|
|
|
sort = sortUsersByName(a, b);
|
|
|
|
}
|
|
|
|
|
|
|
|
return sort;
|
|
|
|
};
|
|
|
|
|
2016-06-28 21:10:20 +08:00
|
|
|
const sortChatsByName = (a, b) => {
|
|
|
|
if (a.name.toLowerCase() < b.name.toLowerCase()) {
|
|
|
|
return -1;
|
|
|
|
} else if (a.name.toLowerCase() > b.name.toLowerCase()) {
|
|
|
|
return 1;
|
|
|
|
} else if (a.id.toLowerCase() > b.id.toLowerCase()) {
|
|
|
|
return -1;
|
|
|
|
} else if (a.id.toLowerCase() < b.id.toLowerCase()) {
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
};
|
|
|
|
|
|
|
|
const sortChatsByIcon = (a, b) => {
|
|
|
|
if (a.icon && b.icon) {
|
|
|
|
return sortChatsByName(a, b);
|
|
|
|
} else if (a.icon) {
|
|
|
|
return -1;
|
|
|
|
} else if (b.icon) {
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
};
|
|
|
|
|
|
|
|
const sortChats = (a, b) => {
|
|
|
|
let sort = sortChatsByIcon(a, b);
|
|
|
|
|
|
|
|
if (sort === 0) {
|
|
|
|
sort = sortChatsByName(a, b);
|
|
|
|
}
|
|
|
|
|
|
|
|
return sort;
|
|
|
|
};
|
|
|
|
|
|
|
|
const userFindSorting = {
|
|
|
|
'user.set_emoji_time': 1,
|
|
|
|
'user.role': 1,
|
|
|
|
'user.phone_user': 1,
|
|
|
|
'user._sort_name': 1,
|
|
|
|
'user.userid': 1,
|
|
|
|
};
|
|
|
|
|
2016-06-07 00:45:30 +08:00
|
|
|
const getUsers = () => {
|
|
|
|
let users = Users
|
2017-04-12 03:46:51 +08:00
|
|
|
.find({ "user.connection_status": 'online' }, userFindSorting)
|
2016-06-07 00:45:30 +08:00
|
|
|
.fetch();
|
|
|
|
|
|
|
|
return users
|
2017-03-03 05:42:39 +08:00
|
|
|
.map(u => u.user)
|
|
|
|
.map(mapUser)
|
|
|
|
.sort(sortUsers);
|
2016-05-31 19:29:38 +08:00
|
|
|
};
|
2016-05-20 02:22:56 +08:00
|
|
|
|
2016-06-30 22:45:19 +08:00
|
|
|
const getOpenChats = chatID => {
|
2017-03-01 06:40:16 +08:00
|
|
|
|
2016-06-28 21:10:20 +08:00
|
|
|
let openChats = Chat
|
2017-03-03 05:42:39 +08:00
|
|
|
.find({ 'message.chat_type': PRIVATE_CHAT_TYPE })
|
|
|
|
.fetch()
|
|
|
|
.map(mapOpenChats);
|
2016-06-28 21:10:20 +08:00
|
|
|
|
2016-07-11 21:45:24 +08:00
|
|
|
let currentUserId = Auth.userID;
|
2017-03-01 06:40:16 +08:00
|
|
|
|
2016-06-30 22:45:19 +08:00
|
|
|
if (chatID) {
|
|
|
|
openChats.push(chatID);
|
2016-06-28 21:10:20 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
openChats = _.uniq(openChats);
|
|
|
|
|
|
|
|
openChats = Users
|
2017-03-03 05:42:39 +08:00
|
|
|
.find({ 'user.userid': { $in: openChats } })
|
|
|
|
.map(u => u.user)
|
|
|
|
.map(mapUser)
|
|
|
|
.map(op => {
|
|
|
|
op.unreadCounter = UnreadMessages.count(op.id);
|
|
|
|
return op;
|
|
|
|
});
|
2017-03-01 06:40:16 +08:00
|
|
|
|
2017-03-17 23:27:37 +08:00
|
|
|
let currentClosedChats = Storage.getItem(CLOSED_CHAT_LIST_KEY) || [];
|
2017-03-03 04:33:49 +08:00
|
|
|
let filteredChatList = [];
|
2017-03-01 06:55:00 +08:00
|
|
|
|
2017-03-03 04:33:49 +08:00
|
|
|
openChats.forEach((op) => {
|
2017-03-03 05:42:39 +08:00
|
|
|
|
2017-03-07 01:25:35 +08:00
|
|
|
// When a new private chat message is received, ensure the conversation view is restored.
|
2017-03-03 04:33:49 +08:00
|
|
|
if (op.unreadCounter > 0) {
|
2017-03-22 05:52:10 +08:00
|
|
|
if (_.indexOf(currentClosedChats, op.id) > -1) {
|
2017-03-17 23:27:37 +08:00
|
|
|
Storage.setItem(CLOSED_CHAT_LIST_KEY, _.without(currentClosedChats, op.id));
|
2017-03-02 05:27:05 +08:00
|
|
|
}
|
2017-03-03 04:33:49 +08:00
|
|
|
}
|
2017-03-01 06:40:16 +08:00
|
|
|
|
2017-03-03 05:42:39 +08:00
|
|
|
// Compare openChats with session and push it into filteredChatList
|
|
|
|
// if one of the openChat is not in session.
|
|
|
|
// It will pass to openChats.
|
2017-03-22 05:52:10 +08:00
|
|
|
if (_.indexOf(currentClosedChats, op.id) < 0) {
|
2017-03-03 04:33:49 +08:00
|
|
|
filteredChatList.push(op);
|
2017-03-01 06:40:16 +08:00
|
|
|
}
|
2017-03-03 04:33:49 +08:00
|
|
|
});
|
|
|
|
|
|
|
|
openChats = filteredChatList;
|
2016-06-28 21:10:20 +08:00
|
|
|
|
|
|
|
openChats.push({
|
|
|
|
id: 'public',
|
|
|
|
name: 'Public Chat',
|
2017-03-02 09:03:02 +08:00
|
|
|
icon: 'group_chat',
|
2016-07-11 20:34:58 +08:00
|
|
|
unreadCounter: UnreadMessages.count('public_chat_userid'),
|
2016-06-28 21:10:20 +08:00
|
|
|
});
|
|
|
|
|
|
|
|
return openChats
|
|
|
|
.sort(sortChats);
|
|
|
|
};
|
|
|
|
|
|
|
|
getCurrentUser = () => {
|
2016-07-11 21:45:24 +08:00
|
|
|
let currentUserId = Auth.userID;
|
2016-07-06 00:54:45 +08:00
|
|
|
let currentUser = Users.findOne({ 'user.userid': currentUserId });
|
2016-06-28 21:10:20 +08:00
|
|
|
|
2016-07-06 00:54:45 +08:00
|
|
|
return (currentUser) ? mapUser(currentUser.user) : null;
|
2016-06-28 21:10:20 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
const userActions = {
|
2016-06-30 21:01:02 +08:00
|
|
|
openChat: {
|
|
|
|
label: 'Chat',
|
|
|
|
handler: (router, user) => router.push(`/users/chat/${user.id}`),
|
|
|
|
icon: 'chat',
|
|
|
|
},
|
|
|
|
clearStatus: {
|
|
|
|
label: 'Clear Status',
|
2017-02-22 21:11:47 +08:00
|
|
|
handler: user => callServer('setEmojiStatus', user.id, 'none'),
|
2017-03-02 09:03:02 +08:00
|
|
|
icon: 'clear_status',
|
2016-06-30 21:01:02 +08:00
|
|
|
},
|
|
|
|
setPresenter: {
|
|
|
|
label: 'Make Presenter',
|
2017-02-22 20:56:32 +08:00
|
|
|
handler: user => callServer('assignPresenter', user.id),
|
2016-06-30 21:01:02 +08:00
|
|
|
icon: 'presentation',
|
|
|
|
},
|
|
|
|
kick: {
|
|
|
|
label: 'Kick User',
|
2017-02-02 00:47:39 +08:00
|
|
|
handler: user => callServer('kickUser', user.id),
|
2017-03-02 09:03:02 +08:00
|
|
|
icon: 'circle_close',
|
2016-06-30 21:01:02 +08:00
|
|
|
},
|
2016-12-21 07:39:11 +08:00
|
|
|
mute: {
|
|
|
|
label: 'Mute Audio',
|
2017-02-02 03:14:32 +08:00
|
|
|
handler: user=> callServer('muteUser', user.id),
|
2017-03-02 09:03:02 +08:00
|
|
|
icon: 'audio_off',
|
2016-12-21 07:39:11 +08:00
|
|
|
},
|
|
|
|
unmute: {
|
|
|
|
label: 'Unmute Audio',
|
2017-02-02 03:14:32 +08:00
|
|
|
handler: user=> callServer('unmuteUser', user.id),
|
2017-03-02 09:03:02 +08:00
|
|
|
icon: 'audio_on',
|
2016-12-21 07:39:11 +08:00
|
|
|
},
|
2016-06-28 21:10:20 +08:00
|
|
|
};
|
|
|
|
|
2016-06-01 04:25:42 +08:00
|
|
|
export default {
|
2016-06-07 00:45:30 +08:00
|
|
|
getUsers,
|
2016-06-28 21:10:20 +08:00
|
|
|
getOpenChats,
|
|
|
|
getCurrentUser,
|
|
|
|
userActions,
|
2016-06-01 04:25:42 +08:00
|
|
|
};
|