202 lines
6.6 KiB
JavaScript
202 lines
6.6 KiB
JavaScript
import React, { useState, useEffect } from 'react';
|
|
import PropTypes from 'prop-types';
|
|
import { Meteor } from 'meteor/meteor';
|
|
import { defineMessages, injectIntl } from 'react-intl';
|
|
import _ from 'lodash';
|
|
import AudioService from '/imports/ui/components/audio/service';
|
|
import ChatPushAlert from './push-alert/component';
|
|
import Service from '../service';
|
|
import { styles } from '../styles';
|
|
|
|
const CHAT_CONFIG = Meteor.settings.public.chat;
|
|
const PUBLIC_CHAT_CLEAR = CHAT_CONFIG.chat_clear;
|
|
const PUBLIC_CHAT_ID = CHAT_CONFIG.public_id;
|
|
|
|
const propTypes = {
|
|
pushAlertEnabled: PropTypes.bool.isRequired,
|
|
audioAlertEnabled: PropTypes.bool.isRequired,
|
|
unreadMessagesCountByChat: PropTypes.arrayOf(PropTypes.object),
|
|
unreadMessagesByChat: PropTypes.arrayOf(PropTypes.array),
|
|
idChatOpen: PropTypes.string.isRequired,
|
|
intl: PropTypes.shape({
|
|
formatMessage: PropTypes.func.isRequired,
|
|
}).isRequired,
|
|
};
|
|
|
|
const defaultProps = {
|
|
unreadMessagesCountByChat: null,
|
|
unreadMessagesByChat: null,
|
|
};
|
|
|
|
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 ALERT_INTERVAL = 5000; // 5 seconds
|
|
const ALERT_DURATION = 4000; // 4 seconds
|
|
|
|
const ChatAlert = (props) => {
|
|
const {
|
|
audioAlertEnabled,
|
|
pushAlertEnabled,
|
|
idChatOpen,
|
|
unreadMessagesCountByChat,
|
|
unreadMessagesByChat,
|
|
intl,
|
|
layoutContextDispatch,
|
|
} = props;
|
|
|
|
const [unreadMessagesCount, setUnreadMessagesCount] = useState(0);
|
|
const [unreadMessages, setUnreadMessages] = useState([]);
|
|
const [lastAlertTimestampByChat, setLastAlertTimestampByChat] = useState({});
|
|
const [alertEnabledTimestamp, setAlertEnabledTimestamp] = useState(null);
|
|
|
|
// audio alerts
|
|
useEffect(() => {
|
|
if (audioAlertEnabled) {
|
|
const unreadObject = unreadMessagesCountByChat;
|
|
|
|
const unreadCount = document.hidden
|
|
? unreadObject.reduce((a, b) => a + b.unreadCounter, 0)
|
|
: unreadObject.filter((chat) => chat.chatId !== idChatOpen)
|
|
.reduce((a, b) => a + b.unreadCounter, 0);
|
|
|
|
if (audioAlertEnabled && unreadCount > unreadMessagesCount) {
|
|
AudioService.playAlertSound(`${Meteor.settings.public.app.cdn
|
|
+ Meteor.settings.public.app.basename
|
|
+ Meteor.settings.public.app.instanceId}`
|
|
+ '/resources/sounds/notify.mp3');
|
|
}
|
|
|
|
setUnreadMessagesCount(unreadCount);
|
|
}
|
|
}, [unreadMessagesCountByChat]);
|
|
|
|
// push alerts
|
|
useEffect(() => {
|
|
if (pushAlertEnabled) {
|
|
setAlertEnabledTimestamp(new Date().getTime());
|
|
}
|
|
}, [pushAlertEnabled]);
|
|
|
|
useEffect(() => {
|
|
if (pushAlertEnabled) {
|
|
const alertsObject = unreadMessagesByChat;
|
|
|
|
let timewindowsToAlert = [];
|
|
let filteredTimewindows = [];
|
|
|
|
alertsObject.forEach((chat) => {
|
|
filteredTimewindows = filteredTimewindows.concat(
|
|
chat.filter((timeWindow) => timeWindow.timestamp > alertEnabledTimestamp),
|
|
);
|
|
});
|
|
|
|
filteredTimewindows.forEach((timeWindow) => {
|
|
const durationDiff = ALERT_DURATION - (new Date().getTime() - timeWindow.timestamp);
|
|
|
|
if ((timeWindow.lastTimestamp > timeWindow.timestamp && durationDiff > 0
|
|
&& timeWindow.lastTimestamp > (lastAlertTimestampByChat[timeWindow.chatId] || 0))
|
|
|| timeWindow.timestamp
|
|
> (lastAlertTimestampByChat[timeWindow.chatId] || 0) + ALERT_INTERVAL) {
|
|
timewindowsToAlert = timewindowsToAlert
|
|
.filter((item) => item.chatId !== timeWindow.chatId);
|
|
const newTimeWindow = { ...timeWindow };
|
|
newTimeWindow.durationDiff = durationDiff;
|
|
timewindowsToAlert.push(newTimeWindow);
|
|
|
|
const newLastAlertTimestampByChat = { ...lastAlertTimestampByChat };
|
|
if (timeWindow.timestamp > (lastAlertTimestampByChat[timeWindow.chatId] || 0)) {
|
|
newLastAlertTimestampByChat[timeWindow.chatId] = timeWindow.timestamp;
|
|
setLastAlertTimestampByChat(newLastAlertTimestampByChat);
|
|
}
|
|
}
|
|
});
|
|
setUnreadMessages(timewindowsToAlert);
|
|
}
|
|
}, [unreadMessagesByChat]);
|
|
|
|
const mapContentText = (message) => {
|
|
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 messages */
|
|
const tempDiv = document.createElement('div');
|
|
tempDiv.innerHTML = content.text;
|
|
const textWithoutTag = tempDiv.innerText;
|
|
return textWithoutTag;
|
|
});
|
|
|
|
return contentMessage;
|
|
};
|
|
|
|
const createMessage = (name, message) => (
|
|
<div className={styles.pushMessageContent}>
|
|
<h3 className={styles.userNameMessage}>{name}</h3>
|
|
<div className={styles.contentMessage}>
|
|
{
|
|
mapContentText(message)
|
|
.reduce((acc, text) => [...acc, (<br key={_.uniqueId('br_')} />), text], [])
|
|
}
|
|
</div>
|
|
</div>
|
|
);
|
|
|
|
return pushAlertEnabled
|
|
? unreadMessages.map((timeWindow) => {
|
|
const mappedMessage = Service.mapGroupMessage(timeWindow);
|
|
const content = mappedMessage
|
|
? createMessage(mappedMessage.sender.name, mappedMessage.content.slice(-5))
|
|
: null;
|
|
|
|
const messageChatId = mappedMessage.chatId === 'MAIN-PUBLIC-GROUP-CHAT' ? PUBLIC_CHAT_ID : mappedMessage.chatId;
|
|
|
|
const newUnreadMessages = unreadMessages
|
|
.filter((message) => message.key !== mappedMessage.key);
|
|
|
|
return content
|
|
? (
|
|
<ChatPushAlert
|
|
key={messageChatId}
|
|
chatId={messageChatId}
|
|
content={content}
|
|
title={
|
|
(mappedMessage.chatId === 'MAIN-PUBLIC-GROUP-CHAT')
|
|
? <span>{intl.formatMessage(intlMessages.appToastChatPublic)}</span>
|
|
: <span>{intl.formatMessage(intlMessages.appToastChatPrivate)}</span>
|
|
}
|
|
onOpen={
|
|
() => setUnreadMessages(newUnreadMessages)
|
|
}
|
|
onClose={
|
|
() => setUnreadMessages(newUnreadMessages)
|
|
}
|
|
alertDuration={timeWindow.durationDiff}
|
|
layoutContextDispatch={layoutContextDispatch}
|
|
/>
|
|
) : null;
|
|
})
|
|
: null;
|
|
};
|
|
ChatAlert.propTypes = propTypes;
|
|
ChatAlert.defaultProps = defaultProps;
|
|
|
|
export default injectIntl(ChatAlert);
|