Page MenuHomePhorge

D15160.1765044706.diff
No OneTemporary

Size
11 KB
Referenced Files
None
Subscribers
None

D15160.1765044706.diff

diff --git a/lib/ops/dm-operations-store-ops.js b/lib/ops/dm-operations-store-ops.js
--- a/lib/ops/dm-operations-store-ops.js
+++ b/lib/ops/dm-operations-store-ops.js
@@ -322,6 +322,16 @@
item => !op.payload.ids.includes(item.id),
),
};
+ } else if (op.type === 'replace_dm_operation') {
+ if (op.payload.type === dmOperationUnshimmedType) {
+ processedStore = {
+ ...processedStore,
+ shimmedOperations: [
+ ...processedStore.shimmedOperations,
+ { operation: op.payload.operation, id: op.payload.id },
+ ],
+ };
+ }
}
}
@@ -435,6 +445,103 @@
},
};
+export function convertQueuedDMOperationsStoreToAddOps(
+ store: QueuedDMOperations,
+): $ReadOnlyArray<DMOperationStoreOperation> {
+ const operations: Array<DMOperationStoreOperation> = [];
+
+ // Convert thread queue operations
+ for (const [threadID, operationsQueue] of Object.entries(store.threadQueue)) {
+ for (const { operation, timestamp } of operationsQueue) {
+ operations.push({
+ type: 'add_queued_dm_operation',
+ payload: {
+ condition: {
+ type: queuedDMOperationConditionType.THREAD,
+ threadID,
+ },
+ operation,
+ timestamp,
+ },
+ });
+ }
+ }
+
+ // Convert message queue operations
+ for (const [messageID, operationsQueue] of Object.entries(
+ store.messageQueue,
+ )) {
+ for (const { operation, timestamp } of operationsQueue) {
+ operations.push({
+ type: 'add_queued_dm_operation',
+ payload: {
+ condition: {
+ type: queuedDMOperationConditionType.MESSAGE,
+ messageID,
+ },
+ operation,
+ timestamp,
+ },
+ });
+ }
+ }
+
+ // Convert entry queue operations
+ for (const [entryID, operationsQueue] of Object.entries(store.entryQueue)) {
+ for (const { operation, timestamp } of operationsQueue) {
+ operations.push({
+ type: 'add_queued_dm_operation',
+ payload: {
+ condition: {
+ type: queuedDMOperationConditionType.ENTRY,
+ entryID,
+ },
+ operation,
+ timestamp,
+ },
+ });
+ }
+ }
+
+ // Convert membership queue operations
+ for (const [threadID, threadMembershipQueue] of Object.entries(
+ store.membershipQueue,
+ )) {
+ for (const [userID, operationsQueue] of Object.entries(
+ threadMembershipQueue,
+ )) {
+ for (const { operation, timestamp } of operationsQueue) {
+ operations.push({
+ type: 'add_queued_dm_operation',
+ payload: {
+ condition: {
+ type: queuedDMOperationConditionType.MEMBERSHIP,
+ threadID,
+ userID,
+ },
+ operation,
+ timestamp,
+ },
+ });
+ }
+ }
+ }
+
+ // Convert shimmed operations
+ for (const shimmedOp of store.shimmedOperations) {
+ operations.push({
+ type: 'replace_dm_operation',
+ payload: {
+ id: shimmedOp.id,
+ type: dmOperationUnshimmedType,
+ operation: shimmedOp.operation,
+ },
+ });
+ }
+
+ return operations;
+}
+
export const dmOperationUnshimmedType = 'unshimmed_operation';
export {
diff --git a/lib/ops/dm-operations-store-ops.test.js b/lib/ops/dm-operations-store-ops.test.js
new file mode 100644
--- /dev/null
+++ b/lib/ops/dm-operations-store-ops.test.js
@@ -0,0 +1,170 @@
+// @flow
+
+import {
+ convertQueuedDMOperationsStoreToAddOps,
+ dmOperationsStoreOpsHandlers,
+} from './dm-operations-store-ops.js';
+import type { QueuedDMOperations } from '../types/dm-ops.js';
+
+describe('convertQueuedDMOperationsStoreToAddOps', () => {
+ // Shared mock operation for reuse
+ const mockOperation = {
+ type: 'send_text_message',
+ threadID: 'thread1',
+ creatorID: 'user123',
+ time: 1642500000000,
+ messageID: 'msg1',
+ text: 'Mock operation',
+ };
+
+ it('should convert complete store to operations and back', () => {
+ // Create mock store with data for all queue types
+ const originalStore: QueuedDMOperations = {
+ threadQueue: {
+ thread1: [
+ {
+ operation: mockOperation,
+ timestamp: 1642500000000,
+ },
+ {
+ operation: { ...mockOperation, messageID: 'msg1b' },
+ timestamp: 1642500001000,
+ },
+ ],
+ thread2: [
+ {
+ operation: {
+ ...mockOperation,
+ threadID: 'thread2',
+ messageID: 'msg2a',
+ },
+ timestamp: 1642500002000,
+ },
+ ],
+ },
+ messageQueue: {
+ msg3: [
+ {
+ operation: mockOperation,
+ timestamp: 1642500003000,
+ },
+ {
+ operation: { ...mockOperation, messageID: 'msg3b' },
+ timestamp: 1642500004000,
+ },
+ ],
+ msg4: [
+ {
+ operation: { ...mockOperation, messageID: 'msg4a' },
+ timestamp: 1642500005000,
+ },
+ ],
+ },
+ entryQueue: {
+ entry1: [
+ {
+ operation: mockOperation,
+ timestamp: 1642500006000,
+ },
+ {
+ operation: { ...mockOperation, messageID: 'entry1b' },
+ timestamp: 1642500007000,
+ },
+ ],
+ entry2: [
+ {
+ operation: { ...mockOperation, messageID: 'entry2a' },
+ timestamp: 1642500008000,
+ },
+ ],
+ },
+ membershipQueue: {
+ thread1: {
+ user123: [
+ {
+ operation: mockOperation,
+ timestamp: 1642500009000,
+ },
+ {
+ operation: { ...mockOperation, messageID: 'member1b' },
+ timestamp: 1642500010000,
+ },
+ ],
+ user456: [
+ {
+ operation: { ...mockOperation, messageID: 'member2a' },
+ timestamp: 1642500011000,
+ },
+ ],
+ },
+ thread2: {
+ user789: [
+ {
+ operation: {
+ ...mockOperation,
+ threadID: 'thread2',
+ messageID: 'member3a',
+ },
+ timestamp: 1642500012000,
+ },
+ ],
+ },
+ },
+ shimmedOperations: [
+ {
+ id: 'shimmed1',
+ operation: mockOperation,
+ },
+ {
+ id: 'shimmed2',
+ operation: mockOperation,
+ },
+ ],
+ };
+
+ // Convert store to operations
+ const operations = convertQueuedDMOperationsStoreToAddOps(originalStore);
+
+ // Verify we have the correct number of operations
+ // 3 thread + 3 message + 3 entry + 4 membership + 2 shimmed = 15 total
+ expect(operations).toHaveLength(15);
+
+ // Process operations back to store
+ const emptyStore = {
+ threadQueue: {},
+ messageQueue: {},
+ entryQueue: {},
+ membershipQueue: {},
+ shimmedOperations: [],
+ };
+
+ const reconstructedStore =
+ dmOperationsStoreOpsHandlers.processStoreOperations(
+ emptyStore,
+ operations,
+ );
+
+ // Verify reconstructed store matches original
+ expect(reconstructedStore).toEqual(originalStore);
+ });
+
+ it('should handle empty store', () => {
+ const emptyStore = {
+ threadQueue: {},
+ messageQueue: {},
+ entryQueue: {},
+ membershipQueue: {},
+ shimmedOperations: [],
+ };
+
+ const operations = convertQueuedDMOperationsStoreToAddOps(emptyStore);
+ expect(operations).toHaveLength(0);
+
+ const reconstructedStore =
+ dmOperationsStoreOpsHandlers.processStoreOperations(
+ emptyStore,
+ operations,
+ );
+ expect(reconstructedStore).toEqual(emptyStore);
+ });
+});
diff --git a/native/redux/handle-redux-migration-failure.js b/native/redux/handle-redux-migration-failure.js
--- a/native/redux/handle-redux-migration-failure.js
+++ b/native/redux/handle-redux-migration-failure.js
@@ -30,6 +30,7 @@
'globalThemeInfo',
'holderStore',
'threadActivityStore',
+ 'queuedDMOperations',
];
function handleReduxMigrationFailure(oldState: AppState): AppState {
diff --git a/native/redux/persist-constants.js b/native/redux/persist-constants.js
--- a/native/redux/persist-constants.js
+++ b/native/redux/persist-constants.js
@@ -5,6 +5,6 @@
// NOTE: renaming this constant requires updating
// `native/native_rust_library/build.rs` to correctly
// scrap Redux state version from this file.
-const storeVersion = 94;
+const storeVersion = 95;
export { rootKey, storeVersion };
diff --git a/native/redux/persist.js b/native/redux/persist.js
--- a/native/redux/persist.js
+++ b/native/redux/persist.js
@@ -17,6 +17,7 @@
convertConnectionInfoToNewIDSchema,
} from 'lib/_generated/migration-utils.js';
import { extractKeyserverIDFromID } from 'lib/keyserver-conn/keyserver-call-utils.js';
+import { convertQueuedDMOperationsStoreToAddOps } from 'lib/ops/dm-operations-store-ops.js';
import type {
ClientDBEntryStoreOperation,
ReplaceEntryOperation,
@@ -1690,6 +1691,17 @@
},
};
}: MigrationFunction<NavInfo, AppState>),
+ [95]: (async (state: AppState) => {
+ const queuedDMOperations = state.queuedDMOperations;
+
+ return {
+ state,
+ ops: {
+ dmOperationStoreOperations:
+ convertQueuedDMOperationsStoreToAddOps(queuedDMOperations),
+ },
+ };
+ }: MigrationFunction<NavInfo, AppState>),
});
const persistConfig = {
diff --git a/web/redux/handle-redux-migration-failure.js b/web/redux/handle-redux-migration-failure.js
--- a/web/redux/handle-redux-migration-failure.js
+++ b/web/redux/handle-redux-migration-failure.js
@@ -11,7 +11,6 @@
'customServer',
'messageStore',
'tunnelbrokerDeviceToken',
- 'queuedDMOperations',
'restoreBackupState',
];
diff --git a/web/redux/persist-constants.js b/web/redux/persist-constants.js
--- a/web/redux/persist-constants.js
+++ b/web/redux/persist-constants.js
@@ -3,6 +3,6 @@
const rootKey = 'root';
const rootKeyPrefix = 'persist:';
const completeRootKey = `${rootKeyPrefix}${rootKey}`;
-const storeVersion = 94;
+const storeVersion = 95;
export { rootKey, rootKeyPrefix, completeRootKey, storeVersion };
diff --git a/web/redux/persist.js b/web/redux/persist.js
--- a/web/redux/persist.js
+++ b/web/redux/persist.js
@@ -7,6 +7,7 @@
import type { PersistConfig } from 'redux-persist/src/types.js';
import { createReplaceThreadOperation } from 'lib/ops/create-replace-thread-operation.js';
+import { convertQueuedDMOperationsStoreToAddOps } from 'lib/ops/dm-operations-store-ops.js';
import {
type HolderStoreOperation,
createReplaceHoldersOperation,
@@ -904,6 +905,17 @@
},
};
}: MigrationFunction<WebNavInfo, AppState>),
+ [95]: (async (state: AppState) => {
+ const queuedDMOperations = state.queuedDMOperations;
+
+ return {
+ state,
+ ops: {
+ dmOperationStoreOperations:
+ convertQueuedDMOperationsStoreToAddOps(queuedDMOperations),
+ },
+ };
+ }: MigrationFunction<WebNavInfo, AppState>),
};
const persistConfig: PersistConfig = {

File Metadata

Mime Type
text/plain
Expires
Sat, Dec 6, 6:11 PM (18 h, 32 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
5839999
Default Alt Text
D15160.1765044706.diff (11 KB)

Event Timeline