Dev #4

Merged
sandrodach merged 12 commits from dev into main 2026-10-25 21:09:45 +01:00
Showing only changes of commit 0008e9c420 - Show all commits
@@ -198,6 +198,7 @@ export const WorkspaceView: React.FC<WorkspaceViewProps> = ({
const idleUnlockTimerRef = useRef<any>(null); const idleUnlockTimerRef = useRef<any>(null);
const currentDocIdRef = useRef<string | null>(null); const currentDocIdRef = useRef<string | null>(null);
const isEditorFocusedRef = useRef(false); const isEditorFocusedRef = useRef(false);
const isDraggingBlockRef = useRef(false);
const blockInputRefs = useRef<Record<string, HTMLTextAreaElement | HTMLInputElement | null>>({}); const blockInputRefs = useRef<Record<string, HTMLTextAreaElement | HTMLInputElement | null>>({});
@@ -339,8 +340,15 @@ export const WorkspaceView: React.FC<WorkspaceViewProps> = ({
pendingSaveDocRef.current = null; pendingSaveDocRef.current = null;
setSaveState('saved'); setSaveState('saved');
} }
if (!isEditorFocusedRef.current && holdsLockRef.current) { if (!isEditorFocusedRef.current && !isDraggingBlockRef.current && holdsLockRef.current) {
releaseMyLock(); if (idleUnlockTimerRef.current) {
clearTimeout(idleUnlockTimerRef.current);
}
idleUnlockTimerRef.current = setTimeout(async () => {
if (!isEditorFocusedRef.current && !isDraggingBlockRef.current && holdsLockRef.current) {
await releaseMyLock();
}
}, 2000);
} }
} }
}; };
@@ -1940,6 +1948,18 @@ export const WorkspaceView: React.FC<WorkspaceViewProps> = ({
// Drag & Drop Handlers on the Bullet row / Grip / Dot // Drag & Drop Handlers on the Bullet row / Grip / Dot
const handleBlockDragStart = (e: React.DragEvent, blockId: string) => { const handleBlockDragStart = (e: React.DragEvent, blockId: string) => {
e.stopPropagation(); e.stopPropagation();
if (isReadOnly) {
e.preventDefault();
return;
}
isDraggingBlockRef.current = true;
if (idleUnlockTimerRef.current) {
clearTimeout(idleUnlockTimerRef.current);
idleUnlockTimerRef.current = null;
}
// Activate write lock immediately upon dragging
ensureLock();
e.dataTransfer.setData('application/mindsift-block-id', blockId); e.dataTransfer.setData('application/mindsift-block-id', blockId);
e.dataTransfer.setData('text/plain', blockId); e.dataTransfer.setData('text/plain', blockId);
e.dataTransfer.effectAllowed = 'move'; e.dataTransfer.effectAllowed = 'move';
@@ -1990,6 +2010,7 @@ export const WorkspaceView: React.FC<WorkspaceViewProps> = ({
draggingBlockId; draggingBlockId;
const position = explicitPosition || dragOverBlockTarget?.position || 'after'; const position = explicitPosition || dragOverBlockTarget?.position || 'after';
isDraggingBlockRef.current = false;
setDraggingBlockId(null); setDraggingBlockId(null);
setDragOverBlockTarget(null); setDragOverBlockTarget(null);
@@ -2054,6 +2075,16 @@ export const WorkspaceView: React.FC<WorkspaceViewProps> = ({
} }
persistDocument({ ...selectedDoc, blocks }, true); persistDocument({ ...selectedDoc, blocks }, true);
if (idleUnlockTimerRef.current) {
clearTimeout(idleUnlockTimerRef.current);
}
idleUnlockTimerRef.current = setTimeout(async () => {
if (!isEditorFocusedRef.current && !isDraggingBlockRef.current && holdsLockRef.current) {
await flushPendingSave();
await releaseMyLock();
}
}, 2500);
}; };
// Export full document as portable Logseq-indented Markdown // Export full document as portable Logseq-indented Markdown
@@ -3559,10 +3590,30 @@ export const WorkspaceView: React.FC<WorkspaceViewProps> = ({
{/* Drag Handle on hover - tightened spacing to the bullet */} {/* Drag Handle on hover - tightened spacing to the bullet */}
<div <div
draggable={!isReadOnly} draggable={!isReadOnly}
onMouseDown={() => {
if (!isReadOnly) {
if (idleUnlockTimerRef.current) {
clearTimeout(idleUnlockTimerRef.current);
idleUnlockTimerRef.current = null;
}
isDraggingBlockRef.current = true;
ensureLock();
}
}}
onDragStart={(e) => !isReadOnly && handleBlockDragStart(e, block.id)} onDragStart={(e) => !isReadOnly && handleBlockDragStart(e, block.id)}
onDragEnd={() => { onDragEnd={() => {
isDraggingBlockRef.current = false;
setDraggingBlockId(null); setDraggingBlockId(null);
setDragOverBlockTarget(null); setDragOverBlockTarget(null);
if (idleUnlockTimerRef.current) {
clearTimeout(idleUnlockTimerRef.current);
}
idleUnlockTimerRef.current = setTimeout(async () => {
if (!isEditorFocusedRef.current && !isDraggingBlockRef.current && holdsLockRef.current) {
await flushPendingSave();
await releaseMyLock();
}
}, 2500);
}} }}
className="opacity-0 group-hover:opacity-100 flex items-center pt-1 text-faint hover:text-accent cursor-grab active:cursor-grabbing flex-shrink-0 -ml-1 mr-0.5" className="opacity-0 group-hover:opacity-100 flex items-center pt-1 text-faint hover:text-accent cursor-grab active:cursor-grabbing flex-shrink-0 -ml-1 mr-0.5"
title="Ziehen zum Verschieben" title="Ziehen zum Verschieben"
@@ -3591,10 +3642,30 @@ export const WorkspaceView: React.FC<WorkspaceViewProps> = ({
{/* Interactive Bullet Dot (Click: Zoom-in! Drag: Reorder! Drop on it: Nest as child!) */} {/* Interactive Bullet Dot (Click: Zoom-in! Drag: Reorder! Drop on it: Nest as child!) */}
<div <div
draggable={!isReadOnly} draggable={!isReadOnly}
onMouseDown={() => {
if (!isReadOnly) {
if (idleUnlockTimerRef.current) {
clearTimeout(idleUnlockTimerRef.current);
idleUnlockTimerRef.current = null;
}
isDraggingBlockRef.current = true;
ensureLock();
}
}}
onDragStart={(e) => !isReadOnly && handleBlockDragStart(e, block.id)} onDragStart={(e) => !isReadOnly && handleBlockDragStart(e, block.id)}
onDragEnd={() => { onDragEnd={() => {
isDraggingBlockRef.current = false;
setDraggingBlockId(null); setDraggingBlockId(null);
setDragOverBlockTarget(null); setDragOverBlockTarget(null);
if (idleUnlockTimerRef.current) {
clearTimeout(idleUnlockTimerRef.current);
}
idleUnlockTimerRef.current = setTimeout(async () => {
if (!isEditorFocusedRef.current && !isDraggingBlockRef.current && holdsLockRef.current) {
await flushPendingSave();
await releaseMyLock();
}
}, 2500);
}} }}
onDragOver={(e) => { onDragOver={(e) => {
if (!isReadOnly && draggingBlockId && draggingBlockId !== block.id) { if (!isReadOnly && draggingBlockId && draggingBlockId !== block.id) {