Fix: vault events during sync cause pulled files to re-appear in pendingOps

writeLocal()/modifyBinary() fires Obsidian vault modify/create events
asynchronously. These events fire AFTER the pendingOps cleanup, so
result.pulled files get re-added to pendingOps on the next tick.

Fix: skip handleModify/handleCreate entirely while this.syncing is true.
Events during sync are caused by the sync itself (writeLocal), not by
real user edits. Real offline edits are caught by mergeOfflineDiff on
next startup.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
ml2310 2026-04-14 09:45:47 +08:00
parent 12df4f84a5
commit ef2016edab
2 changed files with 4 additions and 0 deletions

View file

@ -830,6 +830,7 @@ var NeoGDSync = class extends import_obsidian4.Plugin {
return false;
}
handleCreate(f) {
if (this.syncing) return; // sync itself calls writeLocal which fires create events
if (this.exclude(f.path)) return;
if (!(f instanceof import_obsidian4.TFile)) return; // skip folders
const cur = this.pendingOps[f.path];
@ -842,6 +843,7 @@ var NeoGDSync = class extends import_obsidian4.Plugin {
this.debouncedSave();
}
handleModify(f) {
if (this.syncing) return; // sync itself calls writeLocal/modifyBinary which fires modify events
if (this.exclude(f.path) || !(f instanceof import_obsidian4.TFile)) return;
// Skip if file matches snapshot (Obsidian fires modify events on startup for all files)
const snap = this.snapshot.get(f.path);

View file

@ -94,6 +94,7 @@ export default class NeoGDSync extends Plugin {
}
private handleCreate(f: TAbstractFile) {
if (this.syncing) return; // sync itself calls writeLocal which fires create events
if (this.exclude(f.path)) return;
if (!(f instanceof TFile)) return; // skip folders
const cur = this.pendingOps[f.path];
@ -107,6 +108,7 @@ export default class NeoGDSync extends Plugin {
}
private handleModify(f: TAbstractFile) {
if (this.syncing) return; // sync itself calls writeLocal/modifyBinary which fires modify events
if (this.exclude(f.path) || !(f instanceof TFile)) return;
// Skip if file matches snapshot (avoids false positives on startup events)
const snap = this.snapshot.get(f.path);