diff --git a/lib/ops/message-store-ops.js b/lib/ops/message-store-ops.js --- a/lib/ops/message-store-ops.js +++ b/lib/ops/message-store-ops.js @@ -1,11 +1,18 @@ // @flow +import { type BaseStoreOpsHandlers } from './base-ops.js'; import type { ClientDBMessageInfo, ClientDBThreadMessageInfo, + MessageStore, MessageStoreThreads, RawMessageInfo, } from '../types/message-types.js'; +import { + translateClientDBMessageInfoToRawMessageInfo, + translateRawMessageInfoToClientDBMessageInfo, + translateThreadMessageInfoToClientDBThreadMessageInfo, +} from '../utils/message-ops-utils.js'; // MessageStore messages ops export type RemoveMessageOperation = { @@ -76,3 +83,114 @@ | ClientDBReplaceThreadsOperation | RemoveMessageStoreThreadsOperation | RemoveMessageStoreAllThreadsOperation; + +export const messageStoreOpsHandlers: BaseStoreOpsHandlers< + MessageStore, + MessageStoreOperation, + ClientDBMessageStoreOperation, + { +[id: string]: RawMessageInfo }, + ClientDBMessageInfo, +> = { + processStoreOperations( + store: MessageStore, + ops: $ReadOnlyArray, + ): MessageStore { + if (ops.length === 0) { + return store; + } + let processedMessages = { ...store.messages }; + let processedThreads = { ...store.threads }; + for (const operation of ops) { + if (operation.type === 'replace') { + processedMessages[operation.payload.id] = operation.payload.messageInfo; + } else if (operation.type === 'remove') { + for (const id of operation.payload.ids) { + delete processedMessages[id]; + } + } else if (operation.type === 'remove_messages_for_threads') { + for (const msgID in processedMessages) { + if ( + operation.payload.threadIDs.includes( + processedMessages[msgID].threadID, + ) + ) { + delete processedMessages[msgID]; + } + } + } else if (operation.type === 'rekey') { + processedMessages[operation.payload.to] = + processedMessages[operation.payload.from]; + delete processedMessages[operation.payload.from]; + } else if (operation.type === 'remove_all') { + processedMessages = {}; + } else if (operation.type === 'replace_threads') { + for (const threadID in operation.payload.threads) { + processedThreads[threadID] = operation.payload.threads[threadID]; + } + } else if (operation.type === 'remove_threads') { + for (const id of operation.payload.ids) { + delete processedThreads[id]; + } + } else if (operation.type === 'remove_all_threads') { + processedThreads = {}; + } + } + return { + ...store, + threads: processedThreads, + messages: processedMessages, + }; + }, + + convertOpsToClientDBOps( + ops: $ReadOnlyArray, + ): $ReadOnlyArray { + const convertedOperations = ops.map(messageStoreOperation => { + if (messageStoreOperation.type === 'replace') { + return { + type: 'replace', + payload: translateRawMessageInfoToClientDBMessageInfo( + messageStoreOperation.payload.messageInfo, + ), + }; + } + + if (messageStoreOperation.type !== 'replace_threads') { + return messageStoreOperation; + } + + const threadMessageInfo: MessageStoreThreads = + messageStoreOperation.payload.threads; + const dbThreadMessageInfos: ClientDBThreadMessageInfo[] = []; + for (const threadID in threadMessageInfo) { + dbThreadMessageInfos.push( + translateThreadMessageInfoToClientDBThreadMessageInfo( + threadID, + threadMessageInfo[threadID], + ), + ); + } + if (dbThreadMessageInfos.length === 0) { + return undefined; + } + return { + type: 'replace_threads', + payload: { + threads: dbThreadMessageInfos, + }, + }; + }); + return convertedOperations.filter(Boolean); + }, + + translateClientDBData(data: $ReadOnlyArray): { + +[id: string]: RawMessageInfo, + } { + return Object.fromEntries( + data.map((dbMessageInfo: ClientDBMessageInfo) => [ + dbMessageInfo.id, + translateClientDBMessageInfoToRawMessageInfo(dbMessageInfo), + ]), + ); + }, +}; diff --git a/lib/reducers/message-reducer.js b/lib/reducers/message-reducer.js --- a/lib/reducers/message-reducer.js +++ b/lib/reducers/message-reducer.js @@ -53,9 +53,10 @@ logInActionTypes, registerActionTypes, } from '../actions/user-actions.js'; -import type { - MessageStoreOperation, - ReplaceMessageOperation, +import { + messageStoreOpsHandlers, + type MessageStoreOperation, + type ReplaceMessageOperation, } from '../ops/message-store-ops.js'; import { pendingToRealizedThreadIDsSelector } from '../selectors/thread-selectors.js'; import { @@ -101,10 +102,7 @@ } from '../types/update-types.js'; import { setNewSessionActionType } from '../utils/action-utils.js'; import { isDev } from '../utils/dev-utils.js'; -import { - translateClientDBMessageInfosToRawMessageInfos, - translateClientDBThreadMessageInfos, -} from '../utils/message-ops-utils.js'; +import { translateClientDBThreadMessageInfos } from '../utils/message-ops-utils.js'; import { assertObjectsAreEqual } from '../utils/objects.js'; const PROCESSED_MSG_STORE_INVARIANTS_DISABLED = !isDev; @@ -740,56 +738,8 @@ : payload; } -function processMessageStoreOperations( - messageStore: MessageStore, - messageStoreOperations: $ReadOnlyArray, -): MessageStore { - if (messageStoreOperations.length === 0) { - return messageStore; - } - let processedMessages = { ...messageStore.messages }; - let processedThreads = { ...messageStore.threads }; - for (const operation of messageStoreOperations) { - if (operation.type === 'replace') { - processedMessages[operation.payload.id] = operation.payload.messageInfo; - } else if (operation.type === 'remove') { - for (const id of operation.payload.ids) { - delete processedMessages[id]; - } - } else if (operation.type === 'remove_messages_for_threads') { - for (const msgID in processedMessages) { - if ( - operation.payload.threadIDs.includes( - processedMessages[msgID].threadID, - ) - ) { - delete processedMessages[msgID]; - } - } - } else if (operation.type === 'rekey') { - processedMessages[operation.payload.to] = - processedMessages[operation.payload.from]; - delete processedMessages[operation.payload.from]; - } else if (operation.type === 'remove_all') { - processedMessages = {}; - } else if (operation.type === 'replace_threads') { - for (const threadID in operation.payload.threads) { - processedThreads[threadID] = operation.payload.threads[threadID]; - } - } else if (operation.type === 'remove_threads') { - for (const id of operation.payload.ids) { - delete processedThreads[id]; - } - } else if (operation.type === 'remove_all_threads') { - processedThreads = {}; - } - } - return { - ...messageStore, - threads: processedThreads, - messages: processedMessages, - }; -} +const { processStoreOperations: processMessageStoreOperations } = + messageStoreOpsHandlers; type ReduceMessageStoreResult = { +messageStoreOperations: $ReadOnlyArray, @@ -1705,7 +1655,7 @@ } const threadsNeedMsgIDsResorting = new Set(); const actionPayloadMessages = - translateClientDBMessageInfosToRawMessageInfos(payloadMessages); + messageStoreOpsHandlers.translateClientDBData(payloadMessages); // When starting the app on native, we filter out any local-only multimedia // messages because the relevant context is no longer available diff --git a/lib/utils/message-ops-utils.js b/lib/utils/message-ops-utils.js --- a/lib/utils/message-ops-utils.js +++ b/lib/utils/message-ops-utils.js @@ -7,10 +7,6 @@ encryptedMediaBlobURI, encryptedVideoThumbnailBlobURI, } from '../media/media-utils.js'; -import type { - ClientDBMessageStoreOperation, - MessageStoreOperation, -} from '../ops/message-store-ops.js'; import { messageID } from '../shared/message-utils.js'; import { messageSpecs } from '../shared/messages/message-specs.js'; import type { @@ -29,7 +25,6 @@ type RawMessageInfo, type ClientDBThreadMessageInfo, type ThreadMessageInfo, - type MessageStoreThreads, } from '../types/message-types.js'; import type { MediaMessageServerDBContent } from '../types/messages/media.js'; @@ -246,17 +241,6 @@ ].rawMessageInfoFromClientDB(clientDBMessageInfo); } -function translateClientDBMessageInfosToRawMessageInfos( - clientDBMessageInfos: $ReadOnlyArray, -): { +[id: string]: RawMessageInfo } { - return Object.fromEntries( - clientDBMessageInfos.map((dbMessageInfo: ClientDBMessageInfo) => [ - dbMessageInfo.id, - translateClientDBMessageInfoToRawMessageInfo(dbMessageInfo), - ]), - ); -} - type TranslatedThreadMessageInfo = { +startReached: boolean, +lastNavigatedTo: number, @@ -295,49 +279,6 @@ }; } -function convertMessageStoreOperationsToClientDBOperations( - messageStoreOperations: $ReadOnlyArray, -): $ReadOnlyArray { - const convertedOperations = messageStoreOperations.map( - messageStoreOperation => { - if (messageStoreOperation.type === 'replace') { - return { - type: 'replace', - payload: translateRawMessageInfoToClientDBMessageInfo( - messageStoreOperation.payload.messageInfo, - ), - }; - } - - if (messageStoreOperation.type !== 'replace_threads') { - return messageStoreOperation; - } - - const threadMessageInfo: MessageStoreThreads = - messageStoreOperation.payload.threads; - const dbThreadMessageInfos: ClientDBThreadMessageInfo[] = []; - for (const threadID in threadMessageInfo) { - dbThreadMessageInfos.push( - translateThreadMessageInfoToClientDBThreadMessageInfo( - threadID, - threadMessageInfo[threadID], - ), - ); - } - if (dbThreadMessageInfos.length === 0) { - return undefined; - } - return { - type: 'replace_threads', - payload: { - threads: dbThreadMessageInfos, - }, - }; - }, - ); - return convertedOperations.filter(Boolean); -} - function getPinnedContentFromClientDBMessageInfo( clientDBMessageInfo: ClientDBMessageInfo, ): string { @@ -357,8 +298,6 @@ translateClientDBMediaInfoToImage, translateRawMessageInfoToClientDBMessageInfo, translateClientDBMessageInfoToRawMessageInfo, - translateClientDBMessageInfosToRawMessageInfos, - convertMessageStoreOperationsToClientDBOperations, translateClientDBMediaInfosToMedia, getPinnedContentFromClientDBMessageInfo, translateClientDBThreadMessageInfos, diff --git a/native/redux/persist.js b/native/redux/persist.js --- a/native/redux/persist.js +++ b/native/redux/persist.js @@ -15,7 +15,10 @@ convertCalendarFilterToNewIDSchema, convertConnectionInfoToNewIDSchema, } from 'lib/_generated/migration-utils.js'; -import type { ClientDBMessageStoreOperation } from 'lib/ops/message-store-ops.js'; +import { + type ClientDBMessageStoreOperation, + messageStoreOpsHandlers, +} from 'lib/ops/message-store-ops.js'; import { type ReportStoreOperation, type ClientDBReportStoreOperation, @@ -49,7 +52,6 @@ import { defaultConnectionInfo } from 'lib/types/socket-types.js'; import type { ClientDBThreadInfo } from 'lib/types/thread-types.js'; import { - convertMessageStoreOperationsToClientDBOperations, translateClientDBMessageInfoToRawMessageInfo, translateRawMessageInfoToClientDBMessageInfo, } from 'lib/utils/message-ops-utils.js'; @@ -537,7 +539,7 @@ return state; }, [37]: state => { - const operations = convertMessageStoreOperationsToClientDBOperations([ + const operations = messageStoreOpsHandlers.convertOpsToClientDBOps([ { type: 'remove_all_threads', }, diff --git a/native/redux/redux-utils.js b/native/redux/redux-utils.js --- a/native/redux/redux-utils.js +++ b/native/redux/redux-utils.js @@ -2,10 +2,10 @@ import { useSelector as reactReduxUseSelector } from 'react-redux'; +import { messageStoreOpsHandlers } from 'lib/ops/message-store-ops.js'; import { reportStoreOpsHandlers } from 'lib/ops/report-store-ops.js'; import { threadStoreOpsHandlers } from 'lib/ops/thread-store-ops.js'; import type { StoreOperations } from 'lib/types/store-ops-types.js'; -import { convertMessageStoreOperationsToClientDBOperations } from 'lib/utils/message-ops-utils.js'; import type { AppState } from './state-types.js'; import { commCoreModule } from '../native-modules.js'; @@ -31,7 +31,7 @@ const convertedThreadStoreOperations = threadStoreOpsHandlers.convertOpsToClientDBOps(threadStoreOperations); const convertedMessageStoreOperations = - convertMessageStoreOperationsToClientDBOperations(messageStoreOperations); + messageStoreOpsHandlers.convertOpsToClientDBOps(messageStoreOperations); const convertedReportStoreOperations = reportStoreOpsHandlers.convertOpsToClientDBOps(reportStoreOperations);