From 6ead0cbacd831a8defeb21dac6f636a5173053a5 Mon Sep 17 00:00:00 2001 From: Heinz217 <2725411278@qq.com> Date: Tue, 4 Aug 2026 17:19:14 +0800 Subject: [PATCH] fix(local-replica): optionally sync external file changes --- package.json | 6 ++++++ package.nls.json | 3 ++- src/scm/localReplicaSCM.ts | 24 +++++++++++++----------- 3 files changed, 21 insertions(+), 12 deletions(-) diff --git a/package.json b/package.json index 9de7641..df9377e 100644 --- a/package.json +++ b/package.json @@ -430,6 +430,12 @@ "scope": "machine", "markdownDescription": "%configuration.compileOnSave.enabled.markdownDescription%" }, + "overleaf-workshop.localReplica.syncOnFileChange.enabled": { + "type": "boolean", + "default": false, + "scope": "machine", + "markdownDescription": "%configuration.localReplica.syncOnFileChange.enabled.markdownDescription%" + }, "overleaf-workshop.compileOutputFolderName": { "type": "string", "default": ".output", diff --git a/package.nls.json b/package.nls.json index 2838547..0008483 100644 --- a/package.nls.json +++ b/package.nls.json @@ -50,6 +50,7 @@ "commands.collaboration.jumpToUser.title": "Jump to Collaborator ...", "configuration.compileOnSave.enabled.markdownDescription": "Always update the compiled PDF when a file is saved.", + "configuration.localReplica.syncOnFileChange.enabled.markdownDescription": "Sync Local Replica changes made by external tools. (Take effect after restarting VSCode)", "configuration.compileOutputFolderName.markdownDescription": "The name of the folder where the compiled output files (e.g., `output.pdf`) is located. (Take effect after restarting VSCode)", "configuration.pdfViewer.themes.markdownDescription": "Configure the color themes used by the PDF viewer. (Take effect after restarting VSCode)", "configuration.pdfViewer.themes.theme.description": "The name of the theme.", @@ -69,4 +70,4 @@ "views.explorer.overleaf-workshop.chatWebview.contextualTitle": "Overleaf Chat", "customEditors.overleaf-workshop.pdfViewer.displayName": "Overleaf Workshop PDF Viewer" -} \ No newline at end of file +} diff --git a/src/scm/localReplicaSCM.ts b/src/scm/localReplicaSCM.ts index 7b77293..adef8c1 100644 --- a/src/scm/localReplicaSCM.ts +++ b/src/scm/localReplicaSCM.ts @@ -40,7 +40,6 @@ export class LocalReplicaSCMProvider extends BaseSCM { private baseCache: {[key:string]: Uint8Array} = {}; private vfsWatcher?: vscode.FileSystemWatcher; private localWatcher?: vscode.FileSystemWatcher; - private saveListener?: vscode.Disposable; private ignorePatterns: string[] = [ '**/.*', '**/.*/**', @@ -376,24 +375,27 @@ export class LocalReplicaSCMProvider extends BaseSCM { ); await this.overwrite(); - // Listen for explicit user saves (not file system changes) to push local edits. - // File system watchers would also fire for git operations, compilation outputs, - // and other external modifications, causing unwanted sync (issues #299, #323). - this.saveListener = vscode.workspace.onDidSaveTextDocument( - doc => this.onDocumentSaved(doc) - ); + const syncOnFileChange = vscode.workspace + .getConfiguration('overleaf-workshop.localReplica.syncOnFileChange') + .get('enabled', false); + + // By default, only explicit editor saves push file modifications. Users who + // rely on external tools can opt into file-system change events instead. + // Keep these listeners mutually exclusive so an editor save is not pushed twice. + const localChangeListener = syncOnFileChange + ? this.localWatcher.onDidChange(async uri => await this.syncToVFS(uri, 'update')) + : vscode.workspace.onDidSaveTextDocument(doc => this.onDocumentSaved(doc)); return [ // sync from vfs to local this.vfsWatcher.onDidChange(async uri => await this.syncFromVFS(uri, 'update')), this.vfsWatcher.onDidCreate(async uri => await this.syncFromVFS(uri, 'update')), this.vfsWatcher.onDidDelete(async uri => await this.syncFromVFS(uri, 'delete')), - // sync from local to vfs: file updates via editor saves (onDidSaveTextDocument above), - // file creation and deletion still via watcher (these are explicit user actions) + // sync from local to vfs: file updates use the configured listener above; + // file creation and deletion still always use the file-system watcher + localChangeListener, this.localWatcher.onDidCreate(async uri => await this.syncToVFS(uri, 'update')), this.localWatcher.onDidDelete(async uri => await this.syncToVFS(uri, 'delete')), - // include save listener for proper disposal - this.saveListener, ]; }