From 213a9e18fb292e916e3b866eb03053429983d2bf Mon Sep 17 00:00:00 2001 From: Andras Schmelczer Date: Sun, 23 Nov 2025 14:20:03 +0000 Subject: [PATCH] Use new WS api --- .../sync-client/src/sync-operations/syncer.ts | 62 ++++++++++++++++++- 1 file changed, 60 insertions(+), 2 deletions(-) diff --git a/frontend/sync-client/src/sync-operations/syncer.ts b/frontend/sync-client/src/sync-operations/syncer.ts index d1aa5faf..ddfde46c 100644 --- a/frontend/sync-client/src/sync-operations/syncer.ts +++ b/frontend/sync-client/src/sync-operations/syncer.ts @@ -17,7 +17,9 @@ import { createPromise } from "../utils/create-promise"; import { SyncResetError } from "../services/sync-reset-error"; import { Locks } from "../utils/data-structures/locks"; import type { DocumentVersionWithoutContent } from "../services/types/DocumentVersionWithoutContent"; -import type { FixedSizeDocumentCache } from "../utils/data-structures/fix-sized-cache"; +import { WebSocketVaultUpdate } from "../services/types/WebSocketVaultUpdate"; +import { WebSocketManager } from "../services/websocket-manager"; +import { WebSocketClientMessage } from "../services/types/WebSocketClientMessage"; export class Syncer { private readonly remoteDocumentsLock: Locks; @@ -26,13 +28,17 @@ export class Syncer { ) => unknown)[] = []; private readonly syncQueue: PQueue; + private _isFirstSyncComplete = false; + private runningScheduleSyncForOfflineChanges: Promise | undefined; public constructor( + private readonly deviceId: string, private readonly logger: Logger, private readonly database: Database, - settings: Settings, + private readonly settings: Settings, private readonly syncService: SyncService, + private readonly webSocketManager: WebSocketManager, private readonly operations: FileOperations, private readonly internalSyncer: UnrestrictedSyncer ) { @@ -53,6 +59,22 @@ export class Syncer { listener(this.syncQueue.size); }); }); + + this.webSocketManager.addWebSocketStatusChangeListener( + (isConnected) => { + if (isConnected) { + // The JS WebSocket API doesn't support setting headers, so we have to send the token as a message + this.sendHandshakeMessage(); + } + } + ); + this.webSocketManager.addRemoteVaultUpdateListener( + this.syncRemotelyUpdatedFile.bind(this) + ); + } + + public get isFirstSyncComplete(): boolean { + return this._isFirstSyncComplete; } public addRemainingOperationsListener( @@ -263,6 +285,42 @@ export class Syncer { } public async syncRemotelyUpdatedFile( + message: WebSocketVaultUpdate + ): Promise { + try { + const handlerPromise = Promise.allSettled( + message.documents.map(async (document) => + this.internalSyncRemotelyUpdatedFile(document) + ) + ); + + await handlerPromise; + + if (message.isInitialSync && message.documents.length > 0) { + this.database.setLastSeenUpdateId( + message.documents + .map((document) => document.vaultUpdateId) + .reduce((a, b) => Math.max(a, b)) + ); + } + + this._isFirstSyncComplete = true; + } catch (e) { + this.logger.error(`Failed to sync remotely updated file: ${e}`); + } + } + + private sendHandshakeMessage(): void { + const message: WebSocketClientMessage = { + type: "handshake", + deviceId: this.deviceId, + token: this.settings.getSettings().token, + lastSeenVaultUpdateId: this.database.getLastSeenUpdateId() + }; + this.webSocketManager.sendHandshakeMessage(message); + } + + private async internalSyncRemotelyUpdatedFile( remoteVersion: DocumentVersionWithoutContent ): Promise { let document = this.database.getDocumentByDocumentId(