UNPKG

podchat-browser

Version:

Javascript SDK to use POD's Chat Service - Browser Only

250 lines (224 loc) 9.6 kB
/** * * @param {number} threadId * @param {Object} params * @param {Array} list * @returns {Object} * @constructor */ function HistoryItem(threadId, params, list) { let config = { threadId, list, hasMore: (params.count <= list.length), hasNext: true, }; return { threadId, get() { return config.list; }, findMessageIdByFromTime(time) { const message = config.list.filter(item => item.timeMiliSeconds === time); if (message.length === 0) { return 0 } return message[0].id || 0; }, findMessagePreviousIdByToTime(time) { const message = config.list.filter(item => item.timeMiliSeconds === time); if (message.length === 0) { return 0 } return message[0].previousId || 0; }, hasNextMessage() { }, hasNoPrevious(cacheData) { if (cacheData.length > 0) { return cacheData[cacheData.length - 1]?.previousId == undefined } return true; }, isCacheValid(cachedData, count, previousId) { return cachedData.length === count || this.hasNoPrevious(cachedData); }, matchesPreviousId(cachedData, previousId) { return cachedData[0]?.previousId === previousId; }, checkSequence(cachedData) { for (let i = 1; i < cachedData.length; i++) { if (cachedData[i].id !== cachedData[i - 1].previousId) { return false; } } return true; }, getRangeCacheData(params) { let resCachedData = []; const cacheData = [...config.list]; const {size, messageId} = params if (size && messageId) { const message = config.list.find(item => item.id === messageId); if (message.timeMiliSeconds) { const fromTimeIndex = cacheData.findIndex(x => x.timeMiliSeconds === message.timeMiliSeconds) if (fromTimeIndex >= size) { resCachedData = cacheData.slice((fromTimeIndex - size), fromTimeIndex + size + 1); if (!this.checkSequence(resCachedData)) { return [] } } } } return resCachedData; }, getCacheData(params, lastMessageTime = 0) { const {count, fromTime, toTime, order} = params const cacheData = [...config.list]; let resCachedData = []; if (fromTime) { const fromTimeIndex = cacheData.findIndex(x => x.timeMiliSeconds === fromTime) const start = fromTimeIndex >= count ? (fromTimeIndex) - count : 0 resCachedData = cacheData.slice(start, fromTimeIndex); if (cacheData[fromTimeIndex]?.id !== resCachedData[resCachedData.length - 1]?.previousId) { if(!(lastMessageTime === fromTime && count === resCachedData.length)) { return [] } } if (!this.checkSequence(resCachedData)) { return [] } return resCachedData; } else if (toTime) { const toTimeIndex = cacheData.findIndex(x => x.timeMiliSeconds === toTime) if (toTimeIndex > -1) { resCachedData = cacheData.slice(toTimeIndex, toTimeIndex + count); if (cacheData[toTimeIndex - 1]?.previousId !== resCachedData[0].id) { if(!(lastMessageTime === toTime && count === resCachedData.length)) { return [] } } if (!this.checkSequence(resCachedData)) { return [] } } } else { resCachedData = config.list.slice(0, count); if(lastMessageTime!==resCachedData[0]?.timeMiliSeconds){ return [] } if (!this.checkSequence(resCachedData)) { return [] } } if (order && order === 'desc') { return Array.from(resCachedData).reverse(); } return resCachedData; }, cacheHasEnoughData(params, lastMessageItem) { // handle range history cache if (params.size && params.messageId) { return this.getRangeCacheData(params).length === (params.size * 2) + 1 } const {id: lastMessageId, timeMiliSeconds} = lastMessageItem const cacheData = this.getCacheData(params, timeMiliSeconds); const oneOrLessThanCountItemCondition = cacheData.length > 0 && cacheData.length < params.count; if (oneOrLessThanCountItemCondition) { const index = params.order === 'desc' ? cacheData.length - 1 : 0; // prevent request when scroll top. (toTime) if (params?.toTime) { return [cacheData[index]?.previousId, cacheData[0]?.previousId].includes(undefined); } // handle request params.fromTime if (params?.fromTime) { return cacheData[index].id === lastMessageId } // if threads history items less than count value and request with count and offset parameter (not fromTime or To Time) if (cacheData[index]?.id === lastMessageId && (cacheData[cacheData.length - 1]?.previousId ==undefined || cacheData[0]?.previousId ==undefined)){ return true; } // if receive event with number 2 code from server when client is offline and data is less than count and fromTime and endTime not exit => data is invalid return false; } // check has more data if fromTime parameter exist on request and cacheData is empty if (cacheData.length === 0 && params?.fromTime === timeMiliSeconds && timeMiliSeconds!==undefined) { return true; } return cacheData.length == params.count; }, pushAtEnd(message) { config.list.push(message); }, mergeArray(messages) { config.list = config.list.concat(messages) .filter((item, index, self) => index === self.findIndex(t => t.id === item.id) ); }, sortDesc() { config.list.sort((a, b) => b.time - a.time); }, putAtBegin(message) { config.list.unshift(message) }, binaryInsert(message) { let left = 0; let right = config.list.length; // جستجوی دودویی برای پیدا کردن مکان مناسب while (left < right) { let mid = Math.floor((left + right) / 2); if (message.time > config.list[mid].time) { right = mid; } else { left = mid + 1; } } // درج شیء در مکان پیدا شده config.list.splice(left, 0, message); }, updateOrPushEndMessage(message) { let foundIndex = config.list.findIndex(item => item.id == message.id); if (foundIndex > -1) config.list[foundIndex] = message; else { const indexScrollDown = config.list.findIndex(item => item.id === message.previousId); const indexScrollUp = config.list.findIndex(item => item.previousId === message.id); if (indexScrollDown > -1) { config.list.splice(indexScrollDown, 0, message) } else { // config.list.push(null) config.list.push(message) } // config.list.push(message) } }, updateMessage(message) { let foundIndex = config.list.findIndex(item => item.id == message.id); if (foundIndex > -1) config.list[foundIndex] = message; }, hasMore() { return config.hasMore }, messageExists(messageId) { return config.list.findIndex(item => item.id == messageId) > -1; }, remove(messageId) { config.list = config.list.filter(item => !item || item && item.id != messageId); }, removeReplyInfoVO(messageId) { for (let i in config.list) { if (config.list[i].id == messageId) { config.list[i].replyInfo && (config.list[i].replyInfo.deleted = true); } } }, updateSeenItem(messageId) { let foundIndex = config.list.findIndex(item => item.id == messageId); if (foundIndex > -1) config.list[foundIndex]['seen'] = true; } } } export {HistoryItem}