import React, { PureComponent } from 'react'; import PropTypes from 'prop-types'; import { defineMessages, injectIntl } from 'react-intl'; import { Session } from 'meteor/session'; import _ from 'lodash'; import UnreadMessages from '/imports/ui/services/unread-messages'; import ChatAudioAlert from './audio-alert/component'; import ChatPushAlert from './push-alert/component'; import Service from '../service'; import { styles } from '../styles'; const propTypes = { disableNotify: PropTypes.bool.isRequired, openChats: PropTypes.arrayOf(PropTypes.object).isRequired, disableAudio: PropTypes.bool.isRequired, }; const intlMessages = defineMessages({ appToastChatPublic: { id: 'app.toast.chat.public', description: 'when entry various message', }, appToastChatPrivate: { id: 'app.toast.chat.private', description: 'when entry various message', }, 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'; class ChatAlert extends PureComponent { constructor(props) { super(props); this.state = { notified: Service.getNotified(PRIVATE_KEY), publicNotified: Service.getNotified(PUBLIC_KEY), }; } 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 }); return; } const notifiedToClear = {}; openChats .filter(c => c.unreadCounter === 0) .forEach((c) => { notifiedToClear[c.id] = 0; }); this.setState(({ notified }) => ({ notified: { ...notified, ...notifiedToClear, }, }), () => { Service.setNotified(PRIVATE_KEY, this.state.notified); }); } mapContentText(message) { const { intl, } = this.props; const contentMessage = message .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; }); return contentMessage; } createMessage(name, message) { return (

{name}

{ this.mapContentText(message) .reduce((acc, text) => [...acc, (
), text], []).splice(1) }
); } notifyPrivateChat() { const { disableNotify, openChats, intl, } = this.props; 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 }) => !Session.equals('idChatOpen', id); const chatsNotify = openChats .filter(hasUnread) .filter(isNotNotified) .filter(isPrivate) .filter(thisChatClosed) .map(({ id, name, unreadCounter, ...rest }) => ({ ...rest, name, unreadCounter, id, message: intl.formatMessage(intlMessages.appToastChatPrivate), })); return ( { chatsNotify.map(({ id, message, name }) => { const getChatmessages = UnreadMessages.getUnreadMessages(id) .filter(({ fromTime, fromUserId }) => fromTime > (this.state.notified[fromUserId] || 0)); const reduceMessages = Service .reduceAndMapGroupMessages(getChatmessages); if (!reduceMessages.length) return null; const flatMessages = _.flatten(reduceMessages .map(msg => this.createMessage(name, msg.content))); const limitingMessages = flatMessages; return ({message}} onOpen={() => { this.setState(({ notified }) => ({ notified: { ...notified, [id]: new Date().getTime(), }, }), () => { Service.setNotified(PRIVATE_KEY, this.state.notified); }); }} />); }) } ); } notifyPublicChat() { const { publicUserId, intl, disableNotify, } = this.props; const publicUnread = UnreadMessages.getUnreadMessages(publicUserId); const publicUnreadReduced = Service.reduceAndMapGroupMessages(publicUnread); if (disableNotify) return; if (!Service.hasUnreadMessages(publicUserId)) return; if (Session.equals('idChatOpen', PUBLIC_KEY)) return; const checkIfBeenNotified = ({ sender, time }) => time > (this.state.publicNotified[sender.id] || 0); const chatsNotify = publicUnreadReduced .map(msg => ({ ...msg, sender: { name: msg.sender ? msg.sender.name : intl.formatMessage(intlMessages.appToastChatSystem), ...msg.sender, }, })) .filter(checkIfBeenNotified); return ( { chatsNotify.map(({ sender, time, content }) => ( { intl.formatMessage(intlMessages.appToastChatPublic) } } content={this.createMessage(sender.name, content)} onOpen={() => { this.setState(({ notified, publicNotified }) => ({ ...notified, publicNotified: { ...publicNotified, [sender.id]: time, }, }), () => { Service.setNotified(PUBLIC_KEY, this.state.publicNotified); }); }} />)) } ); } 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 ( { this.notifyPublicChat() } { this.notifyPrivateChat() } ); } } ChatAlert.propTypes = propTypes; export default injectIntl(ChatAlert);