import _ from 'lodash' const empty = (chatId) => { return { idIndex: {}, messages: [], newMessageCount: 0, lastSeenTimestamp: 0, chatId: chatId, minId: undefined, lastMessage: undefined } } const clear = (storage) => { storage.idIndex = {} storage.messages.splice(0, storage.messages.length) storage.newMessageCount = 0 storage.lastSeenTimestamp = 0 storage.minId = undefined storage.lastMessage = undefined } const deleteMessage = (storage, messageId) => { if (!storage) { return } storage.messages = storage.messages.filter(m => m.id !== messageId) delete storage.idIndex[messageId] if (storage.lastMessage && (storage.lastMessage.id === messageId)) { storage.lastMessage = _.maxBy(storage.messages, 'id') } if (storage.minId === messageId) { storage.minId = _.minBy(storage.messages, 'id') } } const add = (storage, { messages: newMessages }) => { if (!storage) { return } for (let i = 0; i < newMessages.length; i++) { const message = newMessages[i] // sanity check if (message.chat_id !== storage.chatId) { return } if (!storage.minId || message.id < storage.minId) { storage.minId = message.id } if (!storage.lastMessage || message.id > storage.lastMessage.id) { storage.lastMessage = message } if (!storage.idIndex[message.id]) { if (storage.lastSeenTimestamp < message.created_at) { storage.newMessageCount++ } storage.messages.push(message) storage.idIndex[message.id] = message } } } const resetNewMessageCount = (storage) => { if (!storage) { return } storage.newMessageCount = 0 storage.lastSeenTimestamp = new Date() } // Inserts date separators and marks the head and tail if it's the chain of messages made by the same user const getView = (storage) => { if (!storage) { return [] } const result = [] const messages = _.sortBy(storage.messages, ['id', 'desc']) const firstMessages = messages[0] let prev = messages[messages.length - 1] let currentMessageChainId if (firstMessages) { const date = new Date(firstMessages.created_at) date.setHours(0, 0, 0, 0) result.push({ type: 'date', date, id: date.getTime().toString() }) } let afterDate = false for (let i = 0; i < messages.length; i++) { const message = messages[i] const nextMessage = messages[i + 1] const date = new Date(message.created_at) date.setHours(0, 0, 0, 0) // insert date separator and start a new message chain if (prev && prev.date < date) { result.push({ type: 'date', date, id: date.getTime().toString() }) prev['isTail'] = true currentMessageChainId = undefined afterDate = true } const object = { type: 'message', data: message, date, id: message.id, messageChainId: currentMessageChainId } // end a message chian if ((nextMessage && nextMessage.account_id) !== message.account_id) { object['isTail'] = true currentMessageChainId = undefined } // start a new message chain if ((prev && prev.data && prev.data.account_id) !== message.account_id || afterDate) { currentMessageChainId = _.uniqueId() object['isHead'] = true object['messageChainId'] = currentMessageChainId } result.push(object) prev = object afterDate = false } return result } const ChatService = { add, empty, getView, deleteMessage, resetNewMessageCount, clear } export default ChatService