diff --git a/lib/reducers/entry-reducer.js b/lib/reducers/entry-reducer.js --- a/lib/reducers/entry-reducer.js +++ b/lib/reducers/entry-reducer.js @@ -119,15 +119,15 @@ )(oldDaysToEntries); } -function mergeNewEntryInfos( +function mergeNewEntryInfosOps( currentEntryInfos: { +[id: string]: RawEntryInfo }, currentDaysToEntries: ?{ +[day: string]: string[] }, newEntryInfos: $ReadOnlyArray, threadInfos: RawThreadInfos, -) { +): $ReadOnlyArray { const mergedEntryInfos: { [string]: RawEntryInfo } = {}; - let someEntryUpdated = false; + const ops: Array = []; for (const rawEntryInfo of newEntryInfos) { const serverID = rawEntryInfo.id; invariant(serverID, 'new entryInfos should have serverID'); @@ -165,8 +165,14 @@ if (_isEqual(currentEntryInfo)(newEntryInfo)) { mergedEntryInfos[serverID] = currentEntryInfo; } else { + ops.push({ + type: 'replace_entry', + payload: { + id: serverID, + entry: newEntryInfo, + }, + }); mergedEntryInfos[serverID] = newEntryInfo; - someEntryUpdated = true; } } @@ -177,20 +183,19 @@ } } - for (const id in mergedEntryInfos) { - const entryInfo = mergedEntryInfos[id]; - if (!threadInFilterList(threadInfos[entryInfo.threadID])) { - someEntryUpdated = true; - delete mergedEntryInfos[id]; - } + const entriesFromOutsideFilterList = Object.entries(mergedEntryInfos) + .filter(([, entry]) => !threadInFilterList(threadInfos[entry.threadID])) + .map(([id]) => id); + if (entriesFromOutsideFilterList.length > 0) { + ops.push({ + type: 'remove_entries', + payload: { + ids: entriesFromOutsideFilterList, + }, + }); } - const daysToEntries = - !currentDaysToEntries || someEntryUpdated - ? daysToEntriesFromEntryInfos(values(mergedEntryInfos)) - : currentDaysToEntries; - const entryInfos = someEntryUpdated ? mergedEntryInfos : currentEntryInfos; - return [entryInfos, daysToEntries]; + return ops; } function reduceEntryInfos( @@ -280,19 +285,15 @@ reportCreationRequests: [], }; } else if (action.type === fetchEntriesActionTypes.success) { - const [updatedEntryInfos, updatedDaysToEntries] = mergeNewEntryInfos( + const ops = mergeNewEntryInfosOps( entryInfos, daysToEntries, action.payload.rawEntryInfos, newThreadInfos, ); return { - entryStore: { - entryInfos: updatedEntryInfos, - daysToEntries: updatedDaysToEntries, - lastUserInteractionCalendar, - }, - entryStoreOperations: [], + entryStore: entryStoreOpsHandlers.processStoreOperations(entryStore, ops), + entryStoreOperations: ops, reportCreationRequests: [], }; } else if ( @@ -313,23 +314,27 @@ const newLastUserInteractionCalendar = action.payload.calendarQuery ? Date.now() : lastUserInteractionCalendar; - const [updatedEntryInfos, updatedDaysToEntries] = mergeNewEntryInfos( + const mergeEntriesOps = mergeNewEntryInfosOps( entryInfos, daysToEntries, action.payload.rawEntryInfos, newThreadInfos, ); - const deletionMarkedEntryInfos = markDeletedEntries( + const updatedEntryInfos = entryStoreOpsHandlers.processStoreOperations( + entryStore, + mergeEntriesOps, + ).entryInfos; + const markAsDeletedOps = markDeletedEntries( updatedEntryInfos, action.payload.deletedEntryIDs, ); + const ops = [...mergeEntriesOps, ...markAsDeletedOps]; return { entryStore: { - entryInfos: deletionMarkedEntryInfos, - daysToEntries: updatedDaysToEntries, + ...entryStoreOpsHandlers.processStoreOperations(entryStore, ops), lastUserInteractionCalendar: newLastUserInteractionCalendar, }, - entryStoreOperations: [], + entryStoreOperations: ops, reportCreationRequests: [], }; } else if (action.type === createLocalEntryActionType) { @@ -385,7 +390,7 @@ }; } - const [updatedEntryInfos, updatedDaysToEntries] = mergeNewEntryInfos( + const ops = mergeNewEntryInfosOps( rekeyedEntryInfos, null, mergeUpdateEntryInfos([], action.payload.updatesResult.viewerUpdates), @@ -393,11 +398,10 @@ ); return { entryStore: { - entryInfos: updatedEntryInfos, - daysToEntries: updatedDaysToEntries, + ...entryStoreOpsHandlers.processStoreOperations(entryStore, ops), lastUserInteractionCalendar: Date.now(), }, - entryStoreOperations: [], + entryStoreOperations: ops, reportCreationRequests: [], }; } else if (action.type === saveEntryActionTypes.success) { @@ -414,7 +418,7 @@ }; } - const [updatedEntryInfos, updatedDaysToEntries] = mergeNewEntryInfos( + const ops = mergeNewEntryInfosOps( entryInfos, daysToEntries, mergeUpdateEntryInfos([], action.payload.updatesResult.viewerUpdates), @@ -423,11 +427,10 @@ return { entryStore: { - entryInfos: updatedEntryInfos, - daysToEntries: updatedDaysToEntries, + ...entryStoreOpsHandlers.processStoreOperations(entryStore, ops), lastUserInteractionCalendar: Date.now(), }, - entryStoreOperations: [], + entryStoreOperations: ops, reportCreationRequests: [], }; } else if (action.type === concurrentModificationResetActionType) { @@ -485,19 +488,18 @@ } else if (action.type === deleteEntryActionTypes.success) { const { payload } = action; if (payload) { - const [updatedEntryInfos, updatedDaysToEntries] = mergeNewEntryInfos( + const ops = mergeNewEntryInfosOps( entryInfos, daysToEntries, mergeUpdateEntryInfos([], payload.updatesResult.viewerUpdates), newThreadInfos, ); return { - entryStore: { - entryInfos: updatedEntryInfos, - daysToEntries: updatedDaysToEntries, - lastUserInteractionCalendar, - }, - entryStoreOperations: [], + entryStore: entryStoreOpsHandlers.processStoreOperations( + entryStore, + ops, + ), + entryStoreOperations: ops, reportCreationRequests: [], }; } @@ -533,7 +535,7 @@ reportCreationRequests: [], }; } else if (action.type === restoreEntryActionTypes.success) { - const [updatedEntryInfos, updatedDaysToEntries] = mergeNewEntryInfos( + const ops = mergeNewEntryInfosOps( entryInfos, daysToEntries, mergeUpdateEntryInfos([], action.payload.updatesResult.viewerUpdates), @@ -541,11 +543,10 @@ ); return { entryStore: { - entryInfos: updatedEntryInfos, - daysToEntries: updatedDaysToEntries, + ...entryStoreOpsHandlers.processStoreOperations(entryStore, ops), lastUserInteractionCalendar: Date.now(), }, - entryStoreOperations: [], + entryStoreOperations: ops, reportCreationRequests: [], }; } else if ( @@ -555,24 +556,23 @@ ) { const { calendarResult } = action.payload; if (calendarResult) { - const [updatedEntryInfos, updatedDaysToEntries] = mergeNewEntryInfos( + const ops = mergeNewEntryInfosOps( entryInfos, daysToEntries, calendarResult.rawEntryInfos, newThreadInfos, ); return { - entryStore: { - entryInfos: updatedEntryInfos, - daysToEntries: updatedDaysToEntries, - lastUserInteractionCalendar, - }, - entryStoreOperations: [], + entryStore: entryStoreOpsHandlers.processStoreOperations( + entryStore, + ops, + ), + entryStoreOperations: ops, reportCreationRequests: [], }; } } else if (action.type === incrementalStateSyncActionType) { - const [updatedEntryInfos, updatedDaysToEntries] = mergeNewEntryInfos( + const mergeEntriesOps = mergeNewEntryInfosOps( entryInfos, daysToEntries, mergeUpdateEntryInfos( @@ -581,17 +581,18 @@ ), newThreadInfos, ); - const deletionMarkedEntryInfos = markDeletedEntries( + const updatedEntryInfos = entryStoreOpsHandlers.processStoreOperations( + entryStore, + mergeEntriesOps, + ).entryInfos; + const markAsDeletedOps = markDeletedEntries( updatedEntryInfos, action.payload.deletedEntryIDs, ); + const ops = [...mergeEntriesOps, ...markAsDeletedOps]; return { - entryStore: { - entryInfos: deletionMarkedEntryInfos, - daysToEntries: updatedDaysToEntries, - lastUserInteractionCalendar, - }, - entryStoreOperations: [], + entryStore: entryStoreOpsHandlers.processStoreOperations(entryStore, ops), + entryStoreOperations: ops, reportCreationRequests: [], }; } else if ( @@ -599,35 +600,27 @@ action.type === joinThreadActionTypes.success || action.type === newThreadActionTypes.success ) { - const [updatedEntryInfos, updatedDaysToEntries] = mergeNewEntryInfos( + const ops = mergeNewEntryInfosOps( entryInfos, daysToEntries, mergeUpdateEntryInfos([], action.payload.updatesResult.newUpdates), newThreadInfos, ); return { - entryStore: { - entryInfos: updatedEntryInfos, - daysToEntries: updatedDaysToEntries, - lastUserInteractionCalendar, - }, - entryStoreOperations: [], + entryStore: entryStoreOpsHandlers.processStoreOperations(entryStore, ops), + entryStoreOperations: ops, reportCreationRequests: [], }; } else if (action.type === fullStateSyncActionType) { - const [updatedEntryInfos, updatedDaysToEntries] = mergeNewEntryInfos( + const ops = mergeNewEntryInfosOps( entryInfos, daysToEntries, action.payload.rawEntryInfos, newThreadInfos, ); return { - entryStore: { - entryInfos: updatedEntryInfos, - daysToEntries: updatedDaysToEntries, - lastUserInteractionCalendar, - }, - entryStoreOperations: [], + entryStore: entryStoreOpsHandlers.processStoreOperations(entryStore, ops), + entryStoreOperations: ops, reportCreationRequests: [], }; } else if ( @@ -679,42 +672,45 @@ }; } - const updatedEntryInfos: { [string]: RawEntryInfo } = { ...entryInfos }; + const ops: Array = []; + let updatedEntryInfos = entryInfos; if (deleteEntryIDs) { - for (const deleteEntryID of deleteEntryIDs) { - delete updatedEntryInfos[deleteEntryID]; - } + ops.push({ + type: 'remove_entries', + payload: { + ids: deleteEntryIDs, + }, + }); + updatedEntryInfos = entryStoreOpsHandlers.processStoreOperations( + entryStore, + ops, + ).entryInfos; } - let mergedEntryInfos: { +[string]: RawEntryInfo }; - let mergedDaysToEntries; if (rawEntryInfos) { - [mergedEntryInfos, mergedDaysToEntries] = mergeNewEntryInfos( - updatedEntryInfos, - null, - rawEntryInfos, - newThreadInfos, - ); - } else { - mergedEntryInfos = updatedEntryInfos; - mergedDaysToEntries = daysToEntriesFromEntryInfos( - values(updatedEntryInfos), + ops.push( + ...mergeNewEntryInfosOps( + updatedEntryInfos, + null, + rawEntryInfos, + newThreadInfos, + ), ); } + const newStore = entryStoreOpsHandlers.processStoreOperations( + entryStore, + ops, + ); const newInconsistencies = stateSyncSpecs.entries.findStoreInconsistencies( action, entryInfos, - mergedEntryInfos, + newStore.entryInfos, ); return { - entryStore: { - entryInfos: mergedEntryInfos, - daysToEntries: mergedDaysToEntries, - lastUserInteractionCalendar, - }, - entryStoreOperations: [], + entryStore: newStore, + entryStoreOperations: ops, reportCreationRequests: newInconsistencies, }; } else if (action.type === setClientDBStoreActionType) { @@ -766,22 +762,25 @@ function markDeletedEntries( entryInfos: { +[id: string]: RawEntryInfo }, deletedEntryIDs: $ReadOnlyArray, -): { +[id: string]: RawEntryInfo } { - let result = entryInfos; +): $ReadOnlyArray { + const ops = []; for (const deletedEntryID of deletedEntryIDs) { const entryInfo = entryInfos[deletedEntryID]; if (!entryInfo || entryInfo.deleted) { continue; } - result = { - ...result, - [deletedEntryID]: { - ...entryInfo, - deleted: true, + ops.push({ + type: 'replace_entry', + payload: { + id: deletedEntryID, + entry: { + ...entryInfo, + deleted: true, + }, }, - }; + }); } - return result; + return ops; } export { daysToEntriesFromEntryInfos, reduceEntryInfos };