Notebook reorder: commit drop on any release event and skip pointer capture on mouse, so it works in WebView2 (Windows)

This commit is contained in:
Yuri Karamian
2026-06-25 14:55:59 +02:00
parent 181b3eb6c2
commit 8eba4527af
+15 -20
View File
@@ -53,7 +53,7 @@
let dropTargetPath = $state<string | null>(null); let dropTargetPath = $state<string | null>(null);
let dropPosition = $state<'above' | 'into' | 'below' | null>(null); let dropPosition = $state<'above' | 'into' | 'below' | null>(null);
let draggedNotebookPath = $state<string | null>(null); let draggedNotebookPath = $state<string | null>(null);
let nbPointer: { id: number; src: string } | null = null; let nbPointer: { src: string } | null = null;
// Apply manual ordering recursively when in 'manual' sort mode. // Apply manual ordering recursively when in 'manual' sort mode.
// In 'alphabetical' mode the Rust scanner already sorts, so we pass through unchanged. // In 'alphabetical' mode the Rust scanner already sorts, so we pass through unchanged.
@@ -385,8 +385,9 @@
function nbStopDragListeners() { function nbStopDragListeners() {
window.removeEventListener('pointermove', nbPointerMove); window.removeEventListener('pointermove', nbPointerMove);
window.removeEventListener('pointerup', nbPointerUp); window.removeEventListener('pointerup', nbDragEnd);
window.removeEventListener('pointercancel', nbPointerCancel); window.removeEventListener('pointercancel', nbDragEnd);
window.removeEventListener('mouseup', nbDragEnd);
} }
function nbHandleDown(e: PointerEvent, nb: NotebookEntry) { function nbHandleDown(e: PointerEvent, nb: NotebookEntry) {
@@ -394,17 +395,20 @@
e.stopPropagation(); e.stopPropagation();
e.preventDefault(); e.preventDefault();
nbStopDragListeners(); nbStopDragListeners();
nbPointer = { id: e.pointerId, src: nb.path }; nbPointer = { src: nb.path };
draggedNotebookPath = nb.path; draggedNotebookPath = nb.path;
try { (e.currentTarget as HTMLElement).setPointerCapture(e.pointerId); } catch {} // Capture helps touch hold the gesture; on Windows mouse it makes WebView2 swallow the release, so skip it there.
// WebView2 doesn't reliably send pointermove to a captured element; track on window instead. if (e.pointerType === 'touch') {
try { (e.currentTarget as HTMLElement).setPointerCapture(e.pointerId); } catch {}
}
window.addEventListener('pointermove', nbPointerMove, { passive: false }); window.addEventListener('pointermove', nbPointerMove, { passive: false });
window.addEventListener('pointerup', nbPointerUp); window.addEventListener('pointerup', nbDragEnd);
window.addEventListener('pointercancel', nbPointerCancel); window.addEventListener('pointercancel', nbDragEnd);
window.addEventListener('mouseup', nbDragEnd);
} }
function nbPointerMove(e: PointerEvent) { function nbPointerMove(e: PointerEvent) {
if (!nbPointer || e.pointerId !== nbPointer.id) return; if (!nbPointer) return;
e.preventDefault(); e.preventDefault();
const el = document.elementFromPoint(e.clientX, e.clientY) as HTMLElement | null; const el = document.elementFromPoint(e.clientX, e.clientY) as HTMLElement | null;
if (el?.closest('[data-nb-root]')) { dropTargetPath = '__root__'; dropPosition = null; return; } if (el?.closest('[data-nb-root]')) { dropTargetPath = '__root__'; dropPosition = null; return; }
@@ -421,8 +425,8 @@
dropPosition = pos; dropPosition = pos;
} }
function nbPointerUp(e: PointerEvent) { function nbDragEnd() {
if (!nbPointer || e.pointerId !== nbPointer.id) return; if (!nbPointer) return;
nbStopDragListeners(); nbStopDragListeners();
const src = nbPointer.src; const src = nbPointer.src;
const target = dropTargetPath; const target = dropTargetPath;
@@ -442,15 +446,6 @@
} }
} }
function nbPointerCancel(e: PointerEvent) {
if (!nbPointer || e.pointerId !== nbPointer.id) return;
nbStopDragListeners();
nbPointer = null;
draggedNotebookPath = null;
dropTargetPath = null;
dropPosition = null;
}
function findSiblingsOfPath(tree: NotebookEntry[], parentPath: string, vaultRoot: string): NotebookEntry[] { function findSiblingsOfPath(tree: NotebookEntry[], parentPath: string, vaultRoot: string): NotebookEntry[] {
if (parentPath === vaultRoot) return tree; if (parentPath === vaultRoot) return tree;
for (const nb of tree) { for (const nb of tree) {