feat(workspace): activate write lock immediately on bullet drag-and-drop start
MindSift CI & Docker Release / Build, Test in Container & Push (push) Successful in 58s
MindSift CI & Docker Release / Build, Test in Container & Push (push) Successful in 58s
This commit is contained in:
1 parent
09725611b5
commit
0008e9c420
1 file changed
+73
-2
@@ -198,6 +198,7 @@ export const WorkspaceView: React.FC<WorkspaceViewProps> = ({
|
||||
const idleUnlockTimerRef = useRef<any>(null);
|
||||
const currentDocIdRef = useRef<string | null>(null);
|
||||
const isEditorFocusedRef = useRef(false);
|
||||
const isDraggingBlockRef = useRef(false);
|
||||
|
||||
const blockInputRefs = useRef<Record<string, HTMLTextAreaElement | HTMLInputElement | null>>({});
|
||||
|
||||
@@ -339,8 +340,15 @@ export const WorkspaceView: React.FC<WorkspaceViewProps> = ({
|
||||
pendingSaveDocRef.current = null;
|
||||
setSaveState('saved');
|
||||
}
|
||||
if (!isEditorFocusedRef.current && holdsLockRef.current) {
|
||||
releaseMyLock();
|
||||
if (!isEditorFocusedRef.current && !isDraggingBlockRef.current && holdsLockRef.current) {
|
||||
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
|
||||
const handleBlockDragStart = (e: React.DragEvent, blockId: string) => {
|
||||
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('text/plain', blockId);
|
||||
e.dataTransfer.effectAllowed = 'move';
|
||||
@@ -1990,6 +2010,7 @@ export const WorkspaceView: React.FC<WorkspaceViewProps> = ({
|
||||
draggingBlockId;
|
||||
|
||||
const position = explicitPosition || dragOverBlockTarget?.position || 'after';
|
||||
isDraggingBlockRef.current = false;
|
||||
setDraggingBlockId(null);
|
||||
setDragOverBlockTarget(null);
|
||||
|
||||
@@ -2054,6 +2075,16 @@ export const WorkspaceView: React.FC<WorkspaceViewProps> = ({
|
||||
}
|
||||
|
||||
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
|
||||
@@ -3559,10 +3590,30 @@ export const WorkspaceView: React.FC<WorkspaceViewProps> = ({
|
||||
{/* Drag Handle on hover - tightened spacing to the bullet */}
|
||||
<div
|
||||
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)}
|
||||
onDragEnd={() => {
|
||||
isDraggingBlockRef.current = false;
|
||||
setDraggingBlockId(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"
|
||||
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!) */}
|
||||
<div
|
||||
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)}
|
||||
onDragEnd={() => {
|
||||
isDraggingBlockRef.current = false;
|
||||
setDraggingBlockId(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) => {
|
||||
if (!isReadOnly && draggingBlockId && draggingBlockId !== block.id) {
|
||||
|
||||
Reference in new issue
Block a user