function createConversationPager({ loadPage }) { let state = { comments: [], page: 1, older_page: null, total: 0 }; let olderRequest = null; const validComments = comments => Array.isArray(comments) ? comments.filter(comment => comment && Number.isInteger(comment.id)) : []; const unique = comments => { const seen = new Set(); return comments.filter(comment => { if (seen.has(comment.id)) return false; seen.add(comment.id); return true; }).sort((left, right) => { const leftTime = Date.parse(left.created_at || ''); const rightTime = Date.parse(right.created_at || ''); if (Number.isFinite(leftTime) && Number.isFinite(rightTime) && leftTime !== rightTime) { return leftTime - rightTime; } return left.id - right.id; }); }; const snapshot = () => ({ ...state, comments: state.comments.map(comment => ({ ...comment })) }); return { reset(page) { const comments = unique(validComments(page?.comments)); state = { comments, page: Number.isInteger(page?.page) ? page.page : 1, older_page: Number.isInteger(page?.older_page) ? page.older_page : null, total: Number.isInteger(page?.total) ? Math.max(page.total, comments.length) : comments.length, }; olderRequest = null; return snapshot(); }, snapshot, loadOlder() { if (olderRequest) return olderRequest; if (!Number.isInteger(state.older_page)) return Promise.resolve(snapshot()); const requestedPage = state.older_page; olderRequest = Promise.resolve(loadPage(requestedPage)).then(page => { state = { comments: unique(validComments(page?.comments).concat(state.comments)), page: Number.isInteger(page?.page) ? page.page : requestedPage, older_page: Number.isInteger(page?.older_page) ? page.older_page : null, total: Number.isInteger(page?.total) ? Math.max(page.total, state.comments.length) : state.total, }; return snapshot(); }).finally(() => { olderRequest = null; }); return olderRequest; }, append(comment) { if (!comment || !Number.isInteger(comment.id)) return snapshot(); if (!state.comments.some(existing => existing.id === comment.id)) { state = { ...state, comments: state.comments.concat(comment), total: Math.max(state.total + 1, state.comments.length + 1), }; } return snapshot(); }, replace(comment) { if (!comment || !Number.isInteger(comment.id)) return snapshot(); state = { ...state, comments: state.comments.map(existing => existing.id === comment.id ? { ...comment } : existing), }; return snapshot(); }, remove(commentId) { const comments = state.comments.filter(comment => comment.id !== commentId); if (comments.length !== state.comments.length) { state = { ...state, comments, total: Math.max(0, state.total - 1) }; } return snapshot(); }, }; } if (typeof module !== 'undefined' && module.exports) module.exports = createConversationPager;