diff --git a/lib/ops/create-replace-thread-operation.js b/lib/ops/create-replace-thread-operation.js new file mode 100644 --- /dev/null +++ b/lib/ops/create-replace-thread-operation.js @@ -0,0 +1,20 @@ +// @flow + +import type { ReplaceThreadOperation } from './thread-store-ops.js'; +import { threadSpecs } from '../shared/threads/thread-specs.js'; +import type { RawThreadInfo } from '../types/minimally-encoded-thread-permissions-types.js'; + +function createReplaceThreadOperation( + id: string, + threadInfo: RawThreadInfo, +): ReplaceThreadOperation { + return { + type: 'replace', + payload: { + id, + threadInfo, + isBackedUp: threadSpecs[threadInfo.type].protocol.dataIsBackedUp, + }, + }; +} +export { createReplaceThreadOperation }; diff --git a/lib/ops/thread-store-ops.js b/lib/ops/thread-store-ops.js --- a/lib/ops/thread-store-ops.js +++ b/lib/ops/thread-store-ops.js @@ -23,7 +23,7 @@ export type ReplaceThreadOperation = { +type: 'replace', - +payload: { +id: string, +threadInfo: RawThreadInfo }, + +payload: { +id: string, +threadInfo: RawThreadInfo, +isBackedUp: boolean }, }; export type ThreadStoreOperation = diff --git a/lib/permissions/minimally-encoded-thread-permissions.js b/lib/permissions/minimally-encoded-thread-permissions.js --- a/lib/permissions/minimally-encoded-thread-permissions.js +++ b/lib/permissions/minimally-encoded-thread-permissions.js @@ -15,6 +15,7 @@ makePermissionsBlob, makePermissionsForChildrenBlob, } from './thread-permissions.js'; +import { createReplaceThreadOperation } from '../ops/create-replace-thread-operation.js'; import type { ThreadStoreOperation } from '../ops/thread-store-ops.js'; import { getChildThreads } from '../selectors/thread-selectors.js'; import type { @@ -458,13 +459,7 @@ .filter( updatedThread => !_isEqual(updatedThread, threads[updatedThread.id]), ) - .map(thread => ({ - type: 'replace', - payload: { - id: thread.id, - threadInfo: thread, - }, - })); + .map(thread => createReplaceThreadOperation(thread.id, thread)); return { operations, diff --git a/lib/reducers/integrity-reducer.test.js b/lib/reducers/integrity-reducer.test.js --- a/lib/reducers/integrity-reducer.test.js +++ b/lib/reducers/integrity-reducer.test.js @@ -2,6 +2,7 @@ import { reduceIntegrityStore } from './integrity-reducer.js'; import { updateIntegrityStoreActionType } from '../actions/integrity-actions.js'; +import { createReplaceThreadOperation } from '../ops/create-replace-thread-operation.js'; import type { ThreadStoreOperation } from '../ops/thread-store-ops'; import { type ThreadHashes } from '../types/integrity-types.js'; import type { RawThreadInfo } from '../types/minimally-encoded-thread-permissions-types.js'; @@ -120,13 +121,10 @@ }; const threadStoreOperations: Array = [ - { - type: 'replace', - payload: { - id: threadIDToUpdate, - threadInfo: threadInfos[threadIDToUpdate], - }, - }, + createReplaceThreadOperation( + threadIDToUpdate, + threadInfos[threadIDToUpdate], + ), ]; expect( @@ -200,13 +198,10 @@ { type: 'remove_all', }, - { - type: 'replace', - payload: { - id: threadIDToUpdate, - threadInfo: threadInfos[threadIDToUpdate], - }, - }, + createReplaceThreadOperation( + threadIDToUpdate, + threadInfos[threadIDToUpdate], + ), ]; expect( diff --git a/lib/reducers/thread-reducer.js b/lib/reducers/thread-reducer.js --- a/lib/reducers/thread-reducer.js +++ b/lib/reducers/thread-reducer.js @@ -34,6 +34,7 @@ extractKeyserverIDFromIDOptional, } from '../keyserver-conn/keyserver-call-utils.js'; import { setNewSessionActionType } from '../keyserver-conn/keyserver-conn-types.js'; +import { createReplaceThreadOperation } from '../ops/create-replace-thread-operation.js'; import { type ThreadStoreOperation, threadStoreOpsHandlers, @@ -106,10 +107,9 @@ type: 'remove', payload: { ids: threadsToRemove }, }, - ...Object.keys(newThreadInfos).map((id: string) => ({ - type: 'replace', - payload: { id, threadInfo: newThreadInfos[id] }, - })), + ...Object.keys(newThreadInfos).map((id: string) => + createReplaceThreadOperation(id, newThreadInfos[id]), + ), ]; const updatedThreadStore = processThreadStoreOperations( state, @@ -148,10 +148,9 @@ { type: 'remove_all', }, - ...Object.keys(newThreadInfos).map((id: string) => ({ - type: 'replace', - payload: { id, threadInfo: newThreadInfos[id] }, - })), + ...Object.keys(newThreadInfos).map((id: string) => + createReplaceThreadOperation(id, newThreadInfos[id]), + ), ]; const updatedThreadStore = processThreadStoreOperations( state, @@ -175,10 +174,9 @@ type: 'remove', payload: { ids: threadIDsToRemove }, }, - ...Object.keys(newThreadInfos).map((id: string) => ({ - type: 'replace', - payload: { id, threadInfo: newThreadInfos[id] }, - })), + ...Object.keys(newThreadInfos).map((id: string) => + createReplaceThreadOperation(id, newThreadInfos[id]), + ), ]; const updatedThreadStore = processThreadStoreOperations( state, @@ -318,13 +316,7 @@ }, }; const threadStoreOperations = [ - { - type: 'replace', - payload: { - id: threadID, - threadInfo: newThreadInfo, - }, - }, + createReplaceThreadOperation(threadID, newThreadInfo), ]; const updatedThreadStore = processThreadStoreOperations( state, @@ -392,13 +384,9 @@ }; } if (Object.keys(changedThreadInfos).length !== 0) { - const threadStoreOperations = Object.keys(changedThreadInfos).map(id => ({ - type: 'replace', - payload: { - id, - threadInfo: changedThreadInfos[id], - }, - })); + const threadStoreOperations = Object.keys(changedThreadInfos).map(id => + createReplaceThreadOperation(id, changedThreadInfos[id]), + ); const updatedThreadStore = processThreadStoreOperations( state, threadStoreOperations, @@ -432,13 +420,9 @@ const threadStoreOperations: ThreadStoreOperation[] = []; if (rawThreadInfos) { for (const rawThreadInfo of rawThreadInfos) { - threadStoreOperations.push({ - type: 'replace', - payload: { - id: rawThreadInfo.id, - threadInfo: rawThreadInfo, - }, - }); + threadStoreOperations.push( + createReplaceThreadOperation(rawThreadInfo.id, rawThreadInfo), + ); } } if (deleteThreadIDs) { @@ -488,13 +472,9 @@ threadStoreOperations: [], }; } - const threadStoreOperations = Object.keys(updatedThreadInfos).map(id => ({ - type: 'replace', - payload: { - id, - threadInfo: updatedThreadInfos[id], - }, - })); + const threadStoreOperations = Object.keys(updatedThreadInfos).map(id => + createReplaceThreadOperation(id, updatedThreadInfos[id]), + ); const updatedThreadStore = processThreadStoreOperations( state, threadStoreOperations, @@ -515,13 +495,7 @@ }, }; const threadStoreOperations = [ - { - type: 'replace', - payload: { - id: threadID, - threadInfo: updatedThreadInfo, - }, - }, + createReplaceThreadOperation(threadID, updatedThreadInfo), ]; const updatedThreadStore = processThreadStoreOperations( state, @@ -550,13 +524,7 @@ currentUser: { ...currentUser, unread: true }, }; const threadStoreOperations = [ - { - type: 'replace', - payload: { - id: threadID, - threadInfo: updatedThread, - }, - }, + createReplaceThreadOperation(threadID, updatedThread), ]; const updatedThreadStore = processThreadStoreOperations( state, diff --git a/lib/shared/redux/client-db-utils.js b/lib/shared/redux/client-db-utils.js --- a/lib/shared/redux/client-db-utils.js +++ b/lib/shared/redux/client-db-utils.js @@ -4,6 +4,7 @@ import { auxUserStoreOpsHandlers } from '../../ops/aux-user-store-ops.js'; import { communityStoreOpsHandlers } from '../../ops/community-store-ops.js'; +import { createReplaceThreadOperation } from '../../ops/create-replace-thread-operation.js'; import { convertDMOperationOpsToClientDBOps } from '../../ops/dm-operations-store-ops.js'; import { entryStoreOpsHandlers } from '../../ops/entries-store-ops.js'; import { integrityStoreOpsHandlers } from '../../ops/integrity-store-ops.js'; @@ -45,14 +46,8 @@ const updatedKeyedRawThreadInfosArray = values(updatedKeyedRawThreadInfos); // 5. Construct `replace` `ThreadStoreOperation`s. - const replaceThreadOperations = updatedKeyedRawThreadInfosArray.map( - thread => ({ - type: 'replace', - payload: { - id: thread.id, - threadInfo: thread, - }, - }), + const replaceThreadOperations = updatedKeyedRawThreadInfosArray.map(thread => + createReplaceThreadOperation(thread.id, thread), ); // 6. Prepend `replaceThreadOperations` with `remove_all` op and return. diff --git a/lib/shared/updates/delete-account-spec.js b/lib/shared/updates/delete-account-spec.js --- a/lib/shared/updates/delete-account-spec.js +++ b/lib/shared/updates/delete-account-spec.js @@ -3,6 +3,7 @@ import t from 'tcomb'; import type { UpdateSpec } from './update-spec.js'; +import { createReplaceThreadOperation } from '../../ops/create-replace-thread-operation.js'; import type { RawThreadInfos } from '../../types/thread-types.js'; import { updateTypes } from '../../types/update-types-enum.js'; import type { @@ -48,13 +49,9 @@ } } if (replacedThreadInfo) { - operations.push({ - type: 'replace', - payload: { - id: threadInfo.id, - threadInfo: replacedThreadInfo, - }, - }); + operations.push( + createReplaceThreadOperation(threadInfo.id, replacedThreadInfo), + ); } } return operations; diff --git a/lib/shared/updates/join-thread-spec.js b/lib/shared/updates/join-thread-spec.js --- a/lib/shared/updates/join-thread-spec.js +++ b/lib/shared/updates/join-thread-spec.js @@ -5,6 +5,7 @@ import t from 'tcomb'; import type { UpdateInfoFromRawInfoParams, UpdateSpec } from './update-spec.js'; +import { createReplaceThreadOperation } from '../../ops/create-replace-thread-operation.js'; import { mixedThinRawThreadInfoValidator } from '../../permissions/minimally-encoded-raw-thread-info-validators.js'; import { type RawEntryInfo, @@ -46,13 +47,7 @@ 'update threadInfo must be minimallyEncoded', ); return [ - { - type: 'replace', - payload: { - id: update.threadInfo.id, - threadInfo: update.threadInfo, - }, - }, + createReplaceThreadOperation(update.threadInfo.id, update.threadInfo), ]; }, mergeEntryInfos( diff --git a/lib/shared/updates/update-thread-read-status-spec.js b/lib/shared/updates/update-thread-read-status-spec.js --- a/lib/shared/updates/update-thread-read-status-spec.js +++ b/lib/shared/updates/update-thread-read-status-spec.js @@ -3,6 +3,7 @@ import t from 'tcomb'; import type { UpdateSpec } from './update-spec.js'; +import { createReplaceThreadOperation } from '../../ops/create-replace-thread-operation.js'; import type { RawThreadInfo } from '../../types/minimally-encoded-thread-permissions-types.js'; import type { LegacyRawThreadInfo, @@ -66,15 +67,7 @@ }, }; } - return [ - { - type: 'replace', - payload: { - id: update.threadID, - threadInfo: updatedThread, - }, - }, - ]; + return [createReplaceThreadOperation(update.threadID, updatedThread)]; }, rawUpdateInfoFromRow(row: Object) { const { threadID, unread } = JSON.parse(row.content); diff --git a/lib/shared/updates/update-thread-spec.js b/lib/shared/updates/update-thread-spec.js --- a/lib/shared/updates/update-thread-spec.js +++ b/lib/shared/updates/update-thread-spec.js @@ -5,6 +5,7 @@ import t from 'tcomb'; import type { UpdateInfoFromRawInfoParams, UpdateSpec } from './update-spec.js'; +import { createReplaceThreadOperation } from '../../ops/create-replace-thread-operation.js'; import { mixedThinRawThreadInfoValidator } from '../../permissions/minimally-encoded-raw-thread-info-validators.js'; import type { RawThreadInfos } from '../../types/thread-types.js'; import { updateTypes } from '../../types/update-types-enum.js'; @@ -33,13 +34,7 @@ 'update threadInfo must be minimallyEncoded', ); return [ - { - type: 'replace', - payload: { - id: update.threadInfo.id, - threadInfo: update.threadInfo, - }, - }, + createReplaceThreadOperation(update.threadInfo.id, update.threadInfo), ]; }, reduceCalendarThreadFilters( diff --git a/native/redux/persist.js b/native/redux/persist.js --- a/native/redux/persist.js +++ b/native/redux/persist.js @@ -489,7 +489,11 @@ }, ...Object.keys(threadInfos).map((id: string) => ({ type: 'replace', - payload: { id, threadInfo: threadInfos[id] }, + // Adding `isBackedUp` only to support types, when this migration was + // implemented, backup was not yet supported, because of that, + // this migration should maintain the default behaviour. + // Migrating DM threads to be supported by backup is added later. + payload: { id, threadInfo: threadInfos[id], isBackedUp: false }, })), ]; try { diff --git a/native/redux/redux-setup.js b/native/redux/redux-setup.js --- a/native/redux/redux-setup.js +++ b/native/redux/redux-setup.js @@ -14,6 +14,7 @@ deleteKeyserverAccountActionTypes, } from 'lib/actions/user-actions.js'; import { setNewSessionActionType } from 'lib/keyserver-conn/keyserver-conn-types.js'; +import { createReplaceThreadOperation } from 'lib/ops/create-replace-thread-operation.js'; import type { ThreadStoreOperation } from 'lib/ops/thread-store-ops.js'; import { threadStoreOpsHandlers } from 'lib/ops/thread-store-ops.js'; import { reduceBackupStore } from 'lib/reducers/backup-reducer.js'; @@ -392,15 +393,8 @@ unread: false, }, }; - const threadStoreOperations = [ - { - type: 'replace', - payload: { - id: activeThread, - threadInfo: updatedActiveThreadInfo, - }, - }, + createReplaceThreadOperation(activeThread, updatedActiveThreadInfo), ]; const updatedThreadStore = threadStoreOpsHandlers.processStoreOperations( diff --git a/web/redux/initial-state-gate.js b/web/redux/initial-state-gate.js --- a/web/redux/initial-state-gate.js +++ b/web/redux/initial-state-gate.js @@ -156,6 +156,10 @@ payload: { id, threadInfo, + // This code is responsible for migrating keyserver threads to + // SQLite, which means this data shouldn't be included in the + // backup because it is owned by keyserver. + isBackedUp: false, }, }), ); diff --git a/web/redux/persist.js b/web/redux/persist.js --- a/web/redux/persist.js +++ b/web/redux/persist.js @@ -6,6 +6,7 @@ import storage from 'redux-persist/es/storage/index.js'; import type { PersistConfig } from 'redux-persist/src/types.js'; +import { createReplaceThreadOperation } from 'lib/ops/create-replace-thread-operation.js'; import { type ClientDBKeyserverStoreOperation, keyserverStoreOpsHandlers, @@ -713,10 +714,9 @@ // 5. Construct `ThreadStoreOperation`s. const threadOperations: ThreadStoreOperation[] = [{ type: 'remove_all' }]; for (const rawThreadInfo of updatedKeyedRawThreadInfosArray) { - threadOperations.push({ - type: 'replace', - payload: { id: rawThreadInfo.id, threadInfo: rawThreadInfo }, - }); + threadOperations.push( + createReplaceThreadOperation(rawThreadInfo.id, rawThreadInfo), + ); } const operations: StoreOperations = { diff --git a/web/redux/redux-setup.js b/web/redux/redux-setup.js --- a/web/redux/redux-setup.js +++ b/web/redux/redux-setup.js @@ -11,6 +11,7 @@ keyserverAuthActionTypes, } from 'lib/actions/user-actions.js'; import { setNewSessionActionType } from 'lib/keyserver-conn/keyserver-conn-types.js'; +import { createReplaceThreadOperation } from 'lib/ops/create-replace-thread-operation.js'; import { type ReplaceKeyserverOperation, keyserverStoreOpsHandlers, @@ -476,19 +477,16 @@ ) { // Makes sure a currently focused thread is never unread const activeThreadInfo = state.threadStore.threadInfos[activeThread]; - updateActiveThreadOps.push({ - type: 'replace', - payload: { - id: activeThread, - threadInfo: { - ...activeThreadInfo, - currentUser: { - ...activeThreadInfo.currentUser, - unread: false, - }, - }, + const updatedActiveThreadInfo = { + ...activeThreadInfo, + currentUser: { + ...activeThreadInfo.currentUser, + unread: false, }, - }); + }; + updateActiveThreadOps.push( + createReplaceThreadOperation(activeThread, updatedActiveThreadInfo), + ); } const oldActiveThread = activeThreadSelector(oldState);