2017-10-28 03:29:48 +08:00
|
|
|
import React, { Component } from 'react';
|
|
|
|
import PropTypes from 'prop-types';
|
2018-05-30 00:43:11 +08:00
|
|
|
import { defineMessages, injectIntl } from 'react-intl';
|
|
|
|
import _ from 'lodash';
|
|
|
|
import UnreadMessages from '/imports/ui/services/unread-messages';
|
2017-10-28 03:29:48 +08:00
|
|
|
import ChatAudioNotification from './audio-notification/component';
|
|
|
|
import ChatPushNotification from './push-notification/component';
|
2018-05-30 00:43:11 +08:00
|
|
|
import Service from '../service';
|
|
|
|
import { styles } from '../styles';
|
2017-10-28 03:29:48 +08:00
|
|
|
|
|
|
|
const propTypes = {
|
|
|
|
disableNotify: PropTypes.bool.isRequired,
|
2017-11-03 00:47:49 +08:00
|
|
|
openChats: PropTypes.arrayOf(PropTypes.object).isRequired,
|
2017-10-28 03:29:48 +08:00
|
|
|
disableAudio: PropTypes.bool.isRequired,
|
|
|
|
};
|
|
|
|
|
2018-05-30 00:43:11 +08:00
|
|
|
const intlMessages = defineMessages({
|
|
|
|
appToastChatPublic: {
|
|
|
|
id: 'app.toast.chat.public',
|
|
|
|
description: 'when entry various message',
|
|
|
|
},
|
2018-06-13 01:21:31 +08:00
|
|
|
appToastChatPrivate: {
|
|
|
|
id: 'app.toast.chat.private',
|
|
|
|
description: 'when entry various message',
|
|
|
|
},
|
2018-05-30 00:43:11 +08:00
|
|
|
appToastChatSystem: {
|
|
|
|
id: 'app.toast.chat.system',
|
|
|
|
description: 'system for use',
|
|
|
|
},
|
|
|
|
publicChatClear: {
|
|
|
|
id: 'app.chat.clearPublicChatMessage',
|
|
|
|
description: 'message of when clear the public chat',
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
|
|
|
const PUBLIC_KEY = 'public';
|
|
|
|
const PRIVATE_KEY = 'private';
|
|
|
|
|
2017-10-28 03:29:48 +08:00
|
|
|
class ChatNotification extends Component {
|
|
|
|
constructor(props) {
|
|
|
|
super(props);
|
2018-05-30 00:43:11 +08:00
|
|
|
this.state = {
|
|
|
|
notified: Service.getNotified(PRIVATE_KEY),
|
|
|
|
publicNotified: Service.getNotified(PUBLIC_KEY),
|
|
|
|
};
|
2017-10-28 03:29:48 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
componentWillReceiveProps(nextProps) {
|
|
|
|
const {
|
|
|
|
openChats,
|
|
|
|
disableNotify,
|
|
|
|
} = this.props;
|
|
|
|
|
|
|
|
if (nextProps.disableNotify === false && disableNotify === true) {
|
|
|
|
const loadMessages = {};
|
|
|
|
openChats
|
|
|
|
.forEach((c) => {
|
|
|
|
loadMessages[c.id] = c.unreadCounter;
|
|
|
|
});
|
|
|
|
this.setState({ notified: loadMessages });
|
2017-11-03 00:47:49 +08:00
|
|
|
return;
|
2017-10-28 03:29:48 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
const notifiedToClear = {};
|
|
|
|
openChats
|
2017-11-17 18:11:46 +08:00
|
|
|
.filter(c => c.unreadCounter === 0)
|
|
|
|
.forEach((c) => {
|
|
|
|
notifiedToClear[c.id] = 0;
|
|
|
|
});
|
2017-10-28 03:29:48 +08:00
|
|
|
|
|
|
|
this.setState(({ notified }) => ({
|
|
|
|
notified: {
|
|
|
|
...notified,
|
|
|
|
...notifiedToClear,
|
|
|
|
},
|
2018-05-30 00:43:11 +08:00
|
|
|
}), () => {
|
|
|
|
Service.setNotified(PRIVATE_KEY, this.state.notified);
|
|
|
|
});
|
2017-10-28 03:29:48 +08:00
|
|
|
}
|
|
|
|
|
2018-06-13 01:21:31 +08:00
|
|
|
mapContentText(message) {
|
2018-05-30 00:43:11 +08:00
|
|
|
const {
|
|
|
|
intl,
|
|
|
|
} = this.props;
|
|
|
|
const contentMessage = message
|
2018-06-13 01:21:31 +08:00
|
|
|
.map((content) => {
|
|
|
|
if (content.text === 'PUBLIC_CHAT_CLEAR') return intl.formatMessage(intlMessages.publicChatClear);
|
|
|
|
/* this code is to remove html tags that come in the server's messangens */
|
|
|
|
const tempDiv = document.createElement('div');
|
|
|
|
tempDiv.innerHTML = content.text;
|
|
|
|
const textWithoutTag = tempDiv.innerText;
|
|
|
|
return textWithoutTag;
|
|
|
|
});
|
2018-05-30 00:43:11 +08:00
|
|
|
return contentMessage;
|
|
|
|
}
|
|
|
|
|
2018-06-13 01:21:31 +08:00
|
|
|
createMessage(name, message) {
|
|
|
|
return (
|
|
|
|
<div className={styles.pushMessageContent}>
|
|
|
|
<h3 className={styles.userNameMessage}>{name}</h3>
|
|
|
|
<div className={styles.contentMessage}>
|
|
|
|
{
|
|
|
|
this.mapContentText(message)
|
|
|
|
.reduce((acc, text) => [...acc, (<br />), text], []).splice(1)
|
|
|
|
}
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2018-05-30 00:43:11 +08:00
|
|
|
notifyPrivateChat() {
|
2017-10-28 03:29:48 +08:00
|
|
|
const {
|
|
|
|
disableNotify,
|
|
|
|
openChats,
|
2018-05-30 00:43:11 +08:00
|
|
|
intl,
|
2018-07-06 22:23:47 +08:00
|
|
|
currentChatID,
|
2017-10-28 03:29:48 +08:00
|
|
|
} = this.props;
|
|
|
|
|
2018-07-06 22:23:47 +08:00
|
|
|
if (disableNotify) return;
|
|
|
|
|
|
|
|
const hasUnread = ({ unreadCounter }) => unreadCounter > 0;
|
|
|
|
const isNotNotified = ({ id, unreadCounter }) => unreadCounter !== this.state.notified[id];
|
|
|
|
const isPrivate = ({ id }) => id !== PUBLIC_KEY;
|
|
|
|
const thisChatClosed = ({ id }) => id !== currentChatID;
|
|
|
|
|
2017-10-28 03:29:48 +08:00
|
|
|
const chatsNotify = openChats
|
2018-07-06 22:23:47 +08:00
|
|
|
.filter(hasUnread)
|
|
|
|
.filter(isNotNotified)
|
|
|
|
.filter(isPrivate)
|
|
|
|
.filter(thisChatClosed)
|
2018-05-30 00:43:11 +08:00
|
|
|
.map(({
|
|
|
|
id,
|
|
|
|
name,
|
|
|
|
unreadCounter,
|
|
|
|
...rest
|
|
|
|
}) => ({
|
|
|
|
...rest,
|
|
|
|
name,
|
|
|
|
unreadCounter,
|
|
|
|
id,
|
2018-06-13 01:21:31 +08:00
|
|
|
message: intl.formatMessage(intlMessages.appToastChatPrivate),
|
2018-05-30 00:43:11 +08:00
|
|
|
}));
|
2017-10-28 03:29:48 +08:00
|
|
|
|
|
|
|
return (
|
|
|
|
<span>
|
|
|
|
{
|
2018-06-13 01:21:31 +08:00
|
|
|
chatsNotify.map(({ id, message, name }) => {
|
|
|
|
const getChatmessages = UnreadMessages.getUnreadMessages(id)
|
|
|
|
.filter(({ fromTime, fromUserId }) => fromTime > (this.state.notified[fromUserId] || 0));
|
|
|
|
|
|
|
|
const reduceMessages = Service
|
|
|
|
.reduceAndMapMessages(getChatmessages);
|
|
|
|
|
|
|
|
if (!reduceMessages.length) return null;
|
|
|
|
|
2018-05-30 00:43:11 +08:00
|
|
|
const flatMessages = _.flatten(reduceMessages
|
2018-06-13 01:21:31 +08:00
|
|
|
.map(msg => this.createMessage(name, msg.content)));
|
|
|
|
const limitingMessages = flatMessages;
|
2018-05-30 00:43:11 +08:00
|
|
|
|
|
|
|
return (<ChatPushNotification
|
|
|
|
key={id}
|
|
|
|
chatId={id}
|
|
|
|
content={limitingMessages}
|
2018-06-13 01:21:31 +08:00
|
|
|
message={<span >{message}</span>}
|
2018-05-30 00:43:11 +08:00
|
|
|
onOpen={() => {
|
|
|
|
this.setState(({ notified }) => ({
|
|
|
|
notified: {
|
|
|
|
...notified,
|
2018-06-13 01:21:31 +08:00
|
|
|
[id]: new Date().getTime(),
|
2018-05-30 00:43:11 +08:00
|
|
|
},
|
|
|
|
}), () => {
|
|
|
|
Service.setNotified(PRIVATE_KEY, this.state.notified);
|
|
|
|
});
|
|
|
|
}}
|
|
|
|
/>);
|
|
|
|
})
|
|
|
|
}
|
|
|
|
</span>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
notifyPublicChat() {
|
|
|
|
const {
|
|
|
|
publicUserId,
|
|
|
|
intl,
|
|
|
|
disableNotify,
|
2018-07-06 22:23:47 +08:00
|
|
|
currentChatID,
|
2018-05-30 00:43:11 +08:00
|
|
|
} = this.props;
|
|
|
|
|
|
|
|
const publicUnread = UnreadMessages.getUnreadMessages(publicUserId);
|
|
|
|
const publicUnreadReduced = Service.reduceAndMapMessages(publicUnread);
|
2018-07-06 22:23:47 +08:00
|
|
|
|
|
|
|
if (disableNotify) return;
|
|
|
|
if (!Service.hasUnreadMessages(publicUserId)) return;
|
|
|
|
if (currentChatID === PUBLIC_KEY) return;
|
|
|
|
|
|
|
|
const checkIfBeenNotified = ({ sender, time }) =>
|
|
|
|
time > (this.state.publicNotified[sender.id] || 0);
|
|
|
|
|
2018-05-30 00:43:11 +08:00
|
|
|
const chatsNotify = publicUnreadReduced
|
|
|
|
.map(msg => ({
|
|
|
|
...msg,
|
|
|
|
sender: {
|
|
|
|
name: msg.sender ? msg.sender.name : intl.formatMessage(intlMessages.appToastChatSystem),
|
|
|
|
...msg.sender,
|
|
|
|
},
|
|
|
|
}))
|
2018-07-06 22:23:47 +08:00
|
|
|
.filter(checkIfBeenNotified);
|
2018-05-30 00:43:11 +08:00
|
|
|
return (
|
|
|
|
<span>
|
|
|
|
{
|
|
|
|
chatsNotify.map(({ sender, time, content }) =>
|
2017-10-28 03:29:48 +08:00
|
|
|
(<ChatPushNotification
|
2018-05-30 00:43:11 +08:00
|
|
|
key={time}
|
|
|
|
chatId={PUBLIC_KEY}
|
|
|
|
name={sender.name}
|
|
|
|
message={
|
2018-06-13 01:21:31 +08:00
|
|
|
<span >
|
|
|
|
{ intl.formatMessage(intlMessages.appToastChatPublic) }
|
2018-05-30 00:43:11 +08:00
|
|
|
</span>
|
|
|
|
}
|
2018-06-13 01:21:31 +08:00
|
|
|
content={this.createMessage(sender.name, content)}
|
2017-10-28 03:29:48 +08:00
|
|
|
onOpen={() => {
|
2018-05-30 00:43:11 +08:00
|
|
|
this.setState(({ notified, publicNotified }) => ({
|
|
|
|
...notified,
|
|
|
|
publicNotified: {
|
|
|
|
...publicNotified,
|
2018-06-13 01:21:31 +08:00
|
|
|
[sender.id]: time,
|
2017-10-28 03:29:48 +08:00
|
|
|
},
|
2018-05-30 00:43:11 +08:00
|
|
|
}), () => {
|
|
|
|
Service.setNotified(PUBLIC_KEY, this.state.publicNotified);
|
|
|
|
});
|
2017-10-28 03:29:48 +08:00
|
|
|
}}
|
2017-11-17 18:11:46 +08:00
|
|
|
/>))
|
2017-10-28 03:29:48 +08:00
|
|
|
}
|
|
|
|
</span>
|
|
|
|
);
|
|
|
|
}
|
2018-05-30 00:43:11 +08:00
|
|
|
|
|
|
|
render() {
|
|
|
|
const {
|
|
|
|
openChats,
|
|
|
|
disableAudio,
|
|
|
|
} = this.props;
|
|
|
|
const unreadMessagesCount = openChats
|
|
|
|
.map(chat => chat.unreadCounter)
|
|
|
|
.reduce((a, b) => a + b, 0);
|
|
|
|
const shouldPlayAudio = !disableAudio && unreadMessagesCount > 0;
|
|
|
|
|
|
|
|
return (
|
|
|
|
<span>
|
|
|
|
<ChatAudioNotification play={shouldPlayAudio} count={unreadMessagesCount} />
|
|
|
|
{ this.notifyPublicChat() }
|
|
|
|
{ this.notifyPrivateChat() }
|
|
|
|
</span>
|
|
|
|
);
|
|
|
|
}
|
2017-10-28 03:29:48 +08:00
|
|
|
}
|
|
|
|
ChatNotification.propTypes = propTypes;
|
|
|
|
|
2018-05-30 00:43:11 +08:00
|
|
|
export default injectIntl(ChatNotification);
|