This commit is contained in:
2025-11-04 14:18:41 +01:00
parent dd378b3ad8
commit 82b33a4d50
4 changed files with 100 additions and 35 deletions
+76 -31
View File
@@ -44,6 +44,47 @@ const DEBUG_DRAG = false;
const DEBUG_FOCUS = true;
const DEBUG_DROP = true;
const resolveDeskPointerIntent = ({
alreadySelected = false,
selectedCount = 0,
stackDocIds = null,
metaOrCtrl = false,
pointerButton = 0,
}) => {
const stackList = Array.isArray(stackDocIds) && stackDocIds.length > 0 ? [...stackDocIds] : null;
if (!metaOrCtrl) {
return {
callEntryPointer: true,
skipSelection: false,
stackDragDocIds: null,
stackClickDocIds: null,
stackReplace: false,
openDetailOnRelease: alreadySelected && pointerButton === 0 && selectedCount > 0,
};
}
if (alreadySelected) {
return {
callEntryPointer: false,
skipSelection: true,
stackDragDocIds: stackList,
stackClickDocIds: stackList,
stackReplace: Boolean(stackList),
openDetailOnRelease: false,
};
}
return {
callEntryPointer: true,
skipSelection: false,
stackDragDocIds: stackList,
stackClickDocIds: null,
stackReplace: Boolean(stackList),
openDetailOnRelease: false,
};
};
const signedDistance = (ax, ay, bx, by, px, py) => (bx - ax) * (py - ay) - (by - ay) * (px - ax);
const clipPolygonWithEdge = (subject, edgeStart, edgeEnd) => {
@@ -2259,29 +2300,24 @@ const DesktopWorkspaceView = () => {
const metaOrCtrlOnly =
(event.metaKey || event.ctrlKey) && !event.shiftKey && !event.altKey;
let stackDocIds = null;
let appliedStackSelection = false;
const modifierActive =
Boolean(event.metaKey || event.ctrlKey || event.shiftKey || event.altKey);
const pointerButton = typeof event.button === 'number' ? event.button : 0;
const stackHits = metaOrCtrlOnly ? resolveStackDocIds(event, doc.id) : null;
const pointerIntent = resolveDeskPointerIntent({
alreadySelected,
selectedCount: selectionCountAtDown,
stackDocIds: stackHits,
metaOrCtrl: metaOrCtrlOnly,
pointerButton,
});
if (metaOrCtrlOnly) {
const hits = resolveStackDocIds(event, doc.id);
if (Array.isArray(hits) && hits.length > 0) {
stackDocIds = hits;
const hasStack = hits.length > 1;
if (hasStack && alreadySelected && typeof onDocumentStackSelect === 'function') {
onDocumentStackSelect(hits, event);
appliedStackSelection = true;
deferredSelectionRef.current = null;
}
}
}
const stackDragDocIds = pointerIntent.stackDragDocIds;
const stackClickDocIds = pointerIntent.stackClickDocIds;
if (alreadySelected && typeof onPromoteSelection === 'function') {
onPromoteSelection(doc.id, event);
}
const modifierActive =
Boolean(event.metaKey || event.ctrlKey || event.shiftKey || event.altKey);
const pointerButton = typeof event.button === 'number' ? event.button : 0;
pointerIntentRef.current = {
docId: doc.id,
selectedAtDown: alreadySelected,
@@ -2289,10 +2325,10 @@ const DesktopWorkspaceView = () => {
modifierActive,
pointerButton,
openDetailOnRelease:
!modifierActive
&& alreadySelected
&& pointerButton === 0
&& typeof onDocumentOpen === 'function',
pointerIntent.openDetailOnRelease && typeof onDocumentOpen === 'function',
stackDragDocIds,
stackClickDocIds,
stackClickApplied: false,
};
const deferSelection =
@@ -2301,12 +2337,7 @@ const DesktopWorkspaceView = () => {
&& Array.isArray(selectedDocumentIds)
&& selectedDocumentIds.length > 1;
const skipPointerSelection =
appliedStackSelection
|| (metaOrCtrlOnly
&& alreadySelected
&& Array.isArray(stackDocIds)
&& stackDocIds.length > 1);
const skipPointerSelection = pointerIntent.skipSelection;
if (skipPointerSelection) {
deferredSelectionRef.current = null;
@@ -2317,7 +2348,7 @@ const DesktopWorkspaceView = () => {
};
} else {
deferredSelectionRef.current = null;
if (typeof onEntryPointer === 'function') {
if (pointerIntent.callEntryPointer && typeof onEntryPointer === 'function') {
onEntryPointer(
{ type: 'document', id: doc.id, key: `document:${doc.id}` },
event,
@@ -2326,10 +2357,11 @@ const DesktopWorkspaceView = () => {
}
handlePointerDown(event, doc.id, {
stackDocIds,
stackSelectionApplied: appliedStackSelection,
stackDocIds: stackDragDocIds,
stackSelectionApplied: false,
wasSelected: alreadySelected,
modifierActive,
stackReplace: pointerIntent.stackReplace,
});
}}
onPointerMove={(event) => {
@@ -2356,6 +2388,19 @@ const DesktopWorkspaceView = () => {
}
}
if (
!pointerMoved
&& pointerState
&& pointerState.selectedAtDown
&& Array.isArray(pointerState.stackClickDocIds)
&& pointerState.stackClickDocIds.length > 0
&& !pointerState.stackClickApplied
&& typeof onDocumentStackSelect === 'function'
) {
onDocumentStackSelect(pointerState.stackClickDocIds, event, { replace: false });
pointerState.stackClickApplied = true;
}
if (
!pointerMoved
&& pointerState
+8 -1
View File
@@ -1,4 +1,4 @@
import React, { useCallback, useMemo } from 'react';
import React, { useCallback, useEffect, useMemo } from 'react';
import { useNavigate } from 'react-router-dom';
import { useAppShell } from '../appShellContext';
import DocumentsLayout from './DocumentsLayout';
@@ -88,6 +88,13 @@ const DocumentsRouteContent = () => {
onNavigateParent: handleNavigateParent,
});
useEffect(() => {
document.body.classList.add('has-main-content');
return () => {
document.body.classList.remove('has-main-content');
};
}, []);
if (!surface) {
return (
<DocumentsLayout sidebarProps={sidebarPropsWithActions}>
+4 -2
View File
@@ -154,6 +154,7 @@ const useDocumentDrag = () => {
const pointerModifierActive = typeof options?.modifierActive === 'boolean'
? options.modifierActive
: Boolean(event.metaKey || event.ctrlKey || event.shiftKey || event.altKey);
const stackReplace = Boolean(options?.stackReplace);
let selectionIds = Array.isArray(selectedDocumentIds)
? selectedDocumentIds.map((id) => String(id))
@@ -330,6 +331,7 @@ const useDocumentDrag = () => {
groupElevated: !isGroupDrag,
stackDocIds: hasStackSource ? stackDocIdsOption : null,
stackSelectionApplied: stackSelectionAppliedInitial || !hasStackSource,
stackReplace,
};
setDraggingId(docId);
@@ -412,10 +414,10 @@ const useDocumentDrag = () => {
state.isGroup
&& !state.stackSelectionApplied
&& Array.isArray(state.stackDocIds)
&& state.stackDocIds.length > 1
&& state.stackDocIds.length > 0
) {
if (typeof onDocumentStackSelect === 'function') {
onDocumentStackSelect(state.stackDocIds);
onDocumentStackSelect(state.stackDocIds, event, { replace: state.stackReplace });
}
state.stackSelectionApplied = true;
}
+12 -1
View File
@@ -266,6 +266,10 @@ body {
overflow: hidden;
}
body.has-main-content {
background: var(--surface);
}
a {
color: var(--accent);
text-decoration: underline;
@@ -1524,6 +1528,10 @@ button.danger:hover:not([disabled]) {
width: 20em;
max-width: 20em;
flex: 0 0 20em;
background: var(--bg);
border-top: 1px solid var(--border);
border-bottom: 1px solid var(--border);
padding-top: -1px;
}
.sidebar__body {
@@ -2715,9 +2723,12 @@ button.danger:hover:not([disabled]) {
min-height: 100vh;
height: 100%;
height: 100%;
background: var(--surface);
background: var(--bg);
box-shadow: 0 0 24px var(--shadow-soft);
border-left: 1px solid var(--border);
border-top: 1px solid var(--border);
border-bottom: 1px solid var(--border);
padding-top: -1px;
display: flex;
flex-direction: column;
z-index: 1000000;