@ -3,6 +3,7 @@ import _ from 'lodash'
const empty = ( chatId ) => {
return {
idIndex : { } ,
idempotencyKeyIndex : { } ,
messages : [ ] ,
newMessageCount : 0 ,
lastSeenTimestamp : 0 ,
@ -13,8 +14,18 @@ const empty = (chatId) => {
}
const clear = ( storage ) => {
storage . idIndex = { }
storage . messages . splice ( 0 , storage . messages . length )
const failedMessageIds = [ ]
for ( const message of storage . messages ) {
if ( message . error ) {
failedMessageIds . push ( message . id )
} else {
delete storage . idIndex [ message . id ]
delete storage . idempotencyKeyIndex [ message . id ]
}
}
storage . messages = storage . messages . filter ( m => failedMessageIds . includes ( m . id ) )
storage . newMessageCount = 0
storage . lastSeenTimestamp = 0
storage . minId = undefined
@ -37,6 +48,25 @@ const deleteMessage = (storage, messageId) => {
}
}
const handleMessageError = ( storage , fakeId , isRetry ) => {
if ( ! storage ) { return }
const fakeMessage = storage . idIndex [ fakeId ]
if ( fakeMessage ) {
fakeMessage . error = true
fakeMessage . pending = false
if ( ! isRetry ) {
// Ensure the failed message doesn't stay at the bottom of the list.
const lastPersistedMessage = _ . orderBy ( storage . messages , [ 'pending' , 'id' ] , [ 'asc' , 'desc' ] ) [ 0 ]
if ( lastPersistedMessage ) {
const oldId = fakeMessage . id
fakeMessage . id = ` ${ lastPersistedMessage . id } - ${ new Date ( ) . getTime ( ) } `
storage . idIndex [ fakeMessage . id ] = fakeMessage
delete storage . idIndex [ oldId ]
}
}
}
}
const add = ( storage , { messages : newMessages , updateMaxId = true } ) => {
if ( ! storage ) { return }
for ( let i = 0 ; i < newMessages . length ; i ++ ) {
@ -45,7 +75,19 @@ const add = (storage, { messages: newMessages, updateMaxId = true }) => {
// sanity check
if ( message . chat _id !== storage . chatId ) { return }
if ( ! storage . minId || message . id < storage . minId ) {
if ( message . fakeId ) {
const fakeMessage = storage . idIndex [ message . fakeId ]
if ( fakeMessage ) {
Object . assign ( fakeMessage , message , { error : false } )
delete fakeMessage [ 'fakeId' ]
storage . idIndex [ fakeMessage . id ] = fakeMessage
delete storage . idIndex [ message . fakeId ]
return
}
}
if ( ! storage . minId || ( ! message . pending && message . id < storage . minId ) ) {
storage . minId = message . id
}
@ -55,16 +97,22 @@ const add = (storage, { messages: newMessages, updateMaxId = true }) => {
}
}
if ( ! storage . idIndex [ message . id ] ) {
if ( ! storage . idIndex [ message . id ] && ! isConfirmation ( storage , message ) ) {
if ( storage . lastSeenTimestamp < message . created _at ) {
storage . newMessageCount ++
}
storage . messages . push ( message )
storage . idIndex [ message . id ] = message
storage . messages . push ( storage . idIndex [ message . id ] )
storage . idempotencyKeyIndex [ message . idempotency _key ] = true
}
}
}
const isConfirmation = ( storage , message ) => {
if ( ! message . idempotency _key ) return
return storage . idempotencyKeyIndex [ message . idempotency _key ]
}
const resetNewMessageCount = ( storage ) => {
if ( ! storage ) { return }
storage . newMessageCount = 0
@ -76,7 +124,7 @@ const getView = (storage) => {
if ( ! storage ) { return [ ] }
const result = [ ]
const messages = _ . sortBy( storage . messages , [ 'id' , 'de sc'] )
const messages = _ . orderBy( storage . messages , [ 'pending' , 'id' ] , [ 'asc' , 'a sc'] )
const firstMessage = messages [ 0 ]
let previousMessage = messages [ messages . length - 1 ]
let currentMessageChainId
@ -148,7 +196,8 @@ const ChatService = {
getView ,
deleteMessage ,
resetNewMessageCount ,
clear
clear ,
handleMessageError
}
export default ChatService