Skip to content

Commit 3ae909b

Browse files
committed
fix: rapid move-node operations can cause view.save race condition
1 parent a7cc2b0 commit 3ae909b

2 files changed

Lines changed: 25 additions & 21 deletions

File tree

src/stores/view/subscriptions/on-document-state-update.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,8 +84,8 @@ export const onDocumentStateUpdate = (
8484
if (!container || !view.isViewOfFile) return;
8585

8686
if (e.content || structuralChange) {
87-
const maybeViewIsClosing = !view.isActive;
88-
view.saveDocument(maybeViewIsClosing);
87+
const debouncedSave = type === 'DOCUMENT/MOVE_NODE';
88+
view.saveDocument(debouncedSave);
8989
}
9090

9191
if (e.content || structuralChange) {

src/view/view.ts

Lines changed: 23 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,6 @@ import { MinimapStoreAction } from 'src/stores/minimap/minimap-store-actions';
4646
import { StyleRulesProcessor } from 'src/stores/view/subscriptions/effects/style-rules/style-rules-processor';
4747
import { AlignBranch } from 'src/stores/view/subscriptions/effects/align-branch/align-branch';
4848
import { lang } from 'src/lang/lang';
49-
import { logger } from 'src/helpers/logger';
5049
import { DebouncedMinimapEffects } from 'src/stores/minimap/subscriptions/effects/debounced-minimap-effects';
5150
import { updateFrontmatter } from 'src/stores/view/subscriptions/actions/document/update-frontmatter';
5251
import { loadFullDocument } from 'src/stores/view/subscriptions/actions/document/load-full-document';
@@ -71,7 +70,7 @@ export class LineageView extends TextFileView {
7170
id: string;
7271
zoomFactor: number;
7372
minimapDom: MinimapDomElements | null = null;
74-
73+
private hasDebouncedSave = false;
7574
private readonly onDestroyCallbacks: Set<Unsubscriber> = new Set();
7675
private activeFilePath: null | string;
7776
constructor(
@@ -120,27 +119,18 @@ export class LineageView extends TextFileView {
120119
if (!this.activeFilePath && this.file) {
121120
this.activeFilePath = this.file?.path;
122121
this.loadInitialData();
123-
} else if (this.file && data.trim().length === 0) {
124-
this.plugin.app.vault.adapter
125-
.read(this.file.path)
126-
.then((content) => {
127-
if (content.trim().length !== 0) {
128-
throw new Error(lang.error_set_empty_data);
129-
} else {
130-
this.data = data;
131-
this.debouncedLoadDocumentToStore();
132-
}
133-
})
134-
.catch((error) => {
135-
logger.error('Error reading file:', error);
136-
});
137122
} else {
138123
this.data = data;
139124
this.debouncedLoadDocumentToStore();
140125
}
141126
}
142127

143128
async onUnloadFile() {
129+
if (this.hasDebouncedSave && this.data.length) {
130+
this.save();
131+
this.hasDebouncedSave = false;
132+
}
133+
144134
if (this.component) {
145135
this.component.$destroy();
146136
}
@@ -201,7 +191,7 @@ export class LineageView extends TextFileView {
201191
onPluginError(error, location, action);
202192
};
203193

204-
saveDocument = async (immediate = false) => {
194+
saveDocument = async (debounced = false) => {
205195
invariant(this.file);
206196
const state = clone(this.documentStore.getValue());
207197
const data: string =
@@ -212,11 +202,25 @@ export class LineageView extends TextFileView {
212202
throw new Error(lang.error_save_empty_data);
213203
}
214204
this.data = data;
215-
if (immediate) await this.save();
216-
else this.requestSave();
205+
if (debounced) {
206+
this.debouncedSave();
207+
} else {
208+
this.requestSave();
209+
}
210+
this.hasDebouncedSave = debounced;
217211
}
218212
};
219213

214+
private debouncedSave = debounce(
215+
() => {
216+
if (!this.hasDebouncedSave) return;
217+
this.save();
218+
this.hasDebouncedSave = false;
219+
},
220+
8000,
221+
true,
222+
);
223+
220224
private loadInitialData = async () => {
221225
invariant(this.file);
222226

0 commit comments

Comments
 (0)