151 lines
3.5 KiB
JavaScript
151 lines
3.5 KiB
JavaScript
|
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
|