fix(slideover): double-click on Save no longer creates a duplicate entry
soSave had no re-entrancy guard: a second click while the first run awaited encryption/POST ran the whole save again -> two POSTs, two entries. Wrapped in a soSaving latch (same class as the sync-button guard); body moved to soSaveInner so every early validation return releases the latch via finally. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -4713,7 +4713,17 @@ function soDirtyCheck() {
|
|||||||
if (btn) btn.style.display = isSoDirty() ? '' : 'none';
|
if (btn) btn.style.display = isSoDirty() ? '' : 'none';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Re-entrancy latch: a double-click on Save (or Enter+click) while the first
|
||||||
|
// run awaits encryption/POST would fire a SECOND full save → duplicate entry.
|
||||||
|
// Same async-race class as the sync-button guard.
|
||||||
|
let soSaving = false;
|
||||||
async function soSave() {
|
async function soSave() {
|
||||||
|
if (soSaving) return;
|
||||||
|
soSaving = true;
|
||||||
|
try { await soSaveInner(); } finally { soSaving = false; }
|
||||||
|
}
|
||||||
|
|
||||||
|
async function soSaveInner() {
|
||||||
if (!soState) return;
|
if (!soState) return;
|
||||||
// Flush any uncommitted tag text — user may have typed in the chip
|
// Flush any uncommitted tag text — user may have typed in the chip
|
||||||
// input without pressing Enter / comma before clicking Save.
|
// input without pressing Enter / comma before clicking Save.
|
||||||
|
|||||||
Reference in New Issue
Block a user