feat: debounced caret-only saves without broadcast
This commit is contained in:
parent
6db41de485
commit
79a552f620
2 changed files with 48 additions and 1 deletions
|
|
@ -8,7 +8,7 @@
|
||||||
## 2. Caret persistence in the side panel
|
## 2. Caret persistence in the side panel
|
||||||
|
|
||||||
- [x] 2.1 In `sidepanel/sidepanel.js`, pass current caret (`selectionStart`/`selectionEnd`) and `scrollTop` to `saveNote` in the existing autosave (`doSave`)
|
- [x] 2.1 In `sidepanel/sidepanel.js`, pass current caret (`selectionStart`/`selectionEnd`) and `scrollTop` to `saveNote` in the existing autosave (`doSave`)
|
||||||
- [ ] 2.2 Track caret-only movement via `document` `selectionchange` (filtered to the editor) and editor `scroll`; debounce ~800ms into a caret-only save that calls `saveNote` without broadcasting; skip it while a content autosave is pending
|
- [x] 2.2 Track caret-only movement via `document` `selectionchange` (filtered to the editor) and editor `scroll`; debounce ~800ms into a caret-only save that calls `saveNote` without broadcasting; skip it while a content autosave is pending
|
||||||
- [ ] 2.3 Flush any pending caret-only save on editor `blur` and on `visibilitychange` → hidden
|
- [ ] 2.3 Flush any pending caret-only save on editor `blur` and on `visibilitychange` → hidden
|
||||||
|
|
||||||
## 3. Focus and caret/scroll restore
|
## 3. Focus and caret/scroll restore
|
||||||
|
|
|
||||||
|
|
@ -221,6 +221,53 @@ editor.addEventListener('blur', () => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Caret-only persistence
|
||||||
|
//
|
||||||
|
// Caret moves (selectionchange / scroll) without content edits are saved on
|
||||||
|
// a debounce. These saves never broadcast: a remote caret update must not
|
||||||
|
// make other panels reload and lose their own caret.
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
let caretTimer = null;
|
||||||
|
const CARET_DEBOUNCE_MS = 800;
|
||||||
|
|
||||||
|
function scheduleCaretSave() {
|
||||||
|
if (!currentKey || isLoadingContent) return;
|
||||||
|
// A pending content autosave will capture the caret anyway.
|
||||||
|
if (saveTimer) return;
|
||||||
|
if (caretTimer) clearTimeout(caretTimer);
|
||||||
|
caretTimer = setTimeout(doCaretSave, CARET_DEBOUNCE_MS);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function doCaretSave() {
|
||||||
|
caretTimer = null;
|
||||||
|
if (!currentKey || currentTabId == null) return;
|
||||||
|
// A content save got scheduled meanwhile — it captures the caret.
|
||||||
|
if (saveTimer) return;
|
||||||
|
// A remote content change is waiting for blur; our content is stale and
|
||||||
|
// must not be written back over it.
|
||||||
|
if (deferredReload) return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const saved = await saveNote(currentKey, editor.value, {}, {
|
||||||
|
caretStart: editor.selectionStart,
|
||||||
|
caretEnd: editor.selectionEnd,
|
||||||
|
scrollTop: editor.scrollTop,
|
||||||
|
});
|
||||||
|
currentNote = saved;
|
||||||
|
} catch (err) {
|
||||||
|
console.error('Side Notes: caret save failed', err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
document.addEventListener('selectionchange', () => {
|
||||||
|
if (document.activeElement === editor) {
|
||||||
|
scheduleCaretSave();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
editor.addEventListener('scroll', scheduleCaretSave);
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// In-panel Find
|
// In-panel Find
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue