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