desktop
This commit is contained in:
@@ -32,6 +32,12 @@
|
|||||||
position: relative;
|
position: relative;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.desk-canvas:focus,
|
||||||
|
.desk-canvas:focus-visible {
|
||||||
|
outline: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.desk-empty {
|
.desk-empty {
|
||||||
|
|||||||
@@ -1966,6 +1966,7 @@ const DesktopWorkspaceView = () => {
|
|||||||
useDocumentDrag();
|
useDocumentDrag();
|
||||||
|
|
||||||
const deferredSelectionRef = useRef(null);
|
const deferredSelectionRef = useRef(null);
|
||||||
|
const pointerIntentRef = useRef(null);
|
||||||
const pointerStartRef = useRef({ x: 0, y: 0 });
|
const pointerStartRef = useRef({ x: 0, y: 0 });
|
||||||
const pointerMovedRef = useRef(false);
|
const pointerMovedRef = useRef(false);
|
||||||
|
|
||||||
@@ -2103,19 +2104,14 @@ const DesktopWorkspaceView = () => {
|
|||||||
|
|
||||||
const allSizesReady = items.every((doc) => ensureDocumentSize(doc));
|
const allSizesReady = items.every((doc) => ensureDocumentSize(doc));
|
||||||
|
|
||||||
useEffect(() => {
|
const handleShellKeyDown = useCallback(
|
||||||
if (typeof window === 'undefined' || typeof onClearSelection !== 'function') {
|
(event) => {
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleKeyDown = (event) => {
|
|
||||||
if (!event || event.defaultPrevented) {
|
if (!event || event.defaultPrevented) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const key = event.key;
|
const { key } = event;
|
||||||
const spacePressed = key === ' ' || key === 'Space' || key === 'Spacebar';
|
if (key !== ' ' && key !== 'Space' && key !== 'Spacebar') {
|
||||||
if (!spacePressed) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2133,10 +2129,9 @@ const DesktopWorkspaceView = () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const hasSelection = Array.isArray(selectedDocumentIds) && selectedDocumentIds.length > 0;
|
if (Array.isArray(selectedDocumentIds) && selectedDocumentIds.length > 0) {
|
||||||
if (hasSelection) {
|
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
onClearSelection();
|
onClearSelection?.();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2144,22 +2139,18 @@ const DesktopWorkspaceView = () => {
|
|||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
onCloseDetailPanel();
|
onCloseDetailPanel();
|
||||||
}
|
}
|
||||||
};
|
},
|
||||||
|
[
|
||||||
window.addEventListener('keydown', handleKeyDown, true);
|
|
||||||
return () => window.removeEventListener('keydown', handleKeyDown, true);
|
|
||||||
}, [
|
|
||||||
onClearSelection,
|
|
||||||
selectedDocumentIds,
|
|
||||||
detailPanelOpen,
|
detailPanelOpen,
|
||||||
|
onClearSelection,
|
||||||
onCloseDetailPanel,
|
onCloseDetailPanel,
|
||||||
]);
|
selectedDocumentIds,
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div
|
<div className="desk-shell" onPointerDown={(event) => {
|
||||||
className="desk-shell"
|
|
||||||
onPointerDown={(event) => {
|
|
||||||
if (event.target === event.currentTarget && typeof onClearSelection === 'function') {
|
if (event.target === event.currentTarget && typeof onClearSelection === 'function') {
|
||||||
onClearSelection();
|
onClearSelection();
|
||||||
}
|
}
|
||||||
@@ -2168,6 +2159,8 @@ const DesktopWorkspaceView = () => {
|
|||||||
<div
|
<div
|
||||||
className="desk-canvas"
|
className="desk-canvas"
|
||||||
ref={containerRef}
|
ref={containerRef}
|
||||||
|
tabIndex={0}
|
||||||
|
onKeyDown={handleShellKeyDown}
|
||||||
onDragOver={handleCanvasDragOver}
|
onDragOver={handleCanvasDragOver}
|
||||||
onDragLeave={handleCanvasDragLeave}
|
onDragLeave={handleCanvasDragLeave}
|
||||||
onDrop={handleCanvasDrop}
|
onDrop={handleCanvasDrop}
|
||||||
@@ -2259,6 +2252,9 @@ const DesktopWorkspaceView = () => {
|
|||||||
y: Number.isFinite(event.clientY) ? event.clientY : 0,
|
y: Number.isFinite(event.clientY) ? event.clientY : 0,
|
||||||
};
|
};
|
||||||
pointerMovedRef.current = false;
|
pointerMovedRef.current = false;
|
||||||
|
const selectionCountAtDown = Array.isArray(selectedDocumentIds)
|
||||||
|
? selectedDocumentIds.length
|
||||||
|
: 0;
|
||||||
const alreadySelected = selectedDocumentIds.includes(doc.id);
|
const alreadySelected = selectedDocumentIds.includes(doc.id);
|
||||||
const metaOrCtrlOnly =
|
const metaOrCtrlOnly =
|
||||||
(event.metaKey || event.ctrlKey) && !event.shiftKey && !event.altKey;
|
(event.metaKey || event.ctrlKey) && !event.shiftKey && !event.altKey;
|
||||||
@@ -2285,6 +2281,20 @@ const DesktopWorkspaceView = () => {
|
|||||||
|
|
||||||
const modifierActive =
|
const modifierActive =
|
||||||
Boolean(event.metaKey || event.ctrlKey || event.shiftKey || event.altKey);
|
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,
|
||||||
|
selectionCountAtDown,
|
||||||
|
modifierActive,
|
||||||
|
pointerButton,
|
||||||
|
openDetailOnRelease:
|
||||||
|
!modifierActive
|
||||||
|
&& alreadySelected
|
||||||
|
&& pointerButton === 0
|
||||||
|
&& typeof onDocumentOpen === 'function',
|
||||||
|
};
|
||||||
|
|
||||||
const deferSelection =
|
const deferSelection =
|
||||||
!modifierActive
|
!modifierActive
|
||||||
&& alreadySelected
|
&& alreadySelected
|
||||||
@@ -2302,9 +2312,8 @@ const DesktopWorkspaceView = () => {
|
|||||||
deferredSelectionRef.current = null;
|
deferredSelectionRef.current = null;
|
||||||
} else if (deferSelection) {
|
} else if (deferSelection) {
|
||||||
deferredSelectionRef.current = {
|
deferredSelectionRef.current = {
|
||||||
type: 'document',
|
entry: { type: 'document', id: doc.id, key: `document:${doc.id}` },
|
||||||
id: doc.id,
|
applySelection: false,
|
||||||
key: `document:${doc.id}`,
|
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
deferredSelectionRef.current = null;
|
deferredSelectionRef.current = null;
|
||||||
@@ -2319,6 +2328,8 @@ const DesktopWorkspaceView = () => {
|
|||||||
handlePointerDown(event, doc.id, {
|
handlePointerDown(event, doc.id, {
|
||||||
stackDocIds,
|
stackDocIds,
|
||||||
stackSelectionApplied: appliedStackSelection,
|
stackSelectionApplied: appliedStackSelection,
|
||||||
|
wasSelected: alreadySelected,
|
||||||
|
modifierActive,
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
onPointerMove={(event) => {
|
onPointerMove={(event) => {
|
||||||
@@ -2331,21 +2342,50 @@ const DesktopWorkspaceView = () => {
|
|||||||
handlePointerMove(event);
|
handlePointerMove(event);
|
||||||
}}
|
}}
|
||||||
onPointerUp={(event) => {
|
onPointerUp={(event) => {
|
||||||
const deferredEntry = deferredSelectionRef.current;
|
const deferredInfo = deferredSelectionRef.current;
|
||||||
|
const pointerState = pointerIntentRef.current;
|
||||||
const pointerMoved = pointerMovedRef.current;
|
const pointerMoved = pointerMovedRef.current;
|
||||||
|
|
||||||
handlePointerUp(event);
|
handlePointerUp(event);
|
||||||
|
|
||||||
if (!pointerMoved && deferredEntry && typeof onEntryPointer === 'function') {
|
if (!pointerMoved && deferredInfo && typeof onEntryPointer === 'function') {
|
||||||
onEntryPointer(deferredEntry, event);
|
const entry = deferredInfo.entry || deferredInfo;
|
||||||
|
const applySelection = deferredInfo.applySelection !== false;
|
||||||
|
if (applySelection && entry) {
|
||||||
|
onEntryPointer(entry, event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
!pointerMoved
|
||||||
|
&& pointerState
|
||||||
|
&& pointerState.docId === doc.id
|
||||||
|
&& pointerState.openDetailOnRelease
|
||||||
|
&& typeof onDocumentOpen === 'function'
|
||||||
|
) {
|
||||||
|
const expectedButton =
|
||||||
|
typeof pointerState.pointerButton === 'number'
|
||||||
|
? pointerState.pointerButton
|
||||||
|
: 0;
|
||||||
|
const releasedButton = typeof event.button === 'number' ? event.button : expectedButton;
|
||||||
|
const isPrimaryRelease = expectedButton === 0 && releasedButton === 0;
|
||||||
|
const stillSelected = Array.isArray(selectedDocumentIds)
|
||||||
|
&& selectedDocumentIds.includes(doc.id);
|
||||||
|
if (isPrimaryRelease && stillSelected) {
|
||||||
|
const useSelection =
|
||||||
|
pointerState.selectedAtDown && pointerState.selectionCountAtDown > 0;
|
||||||
|
onDocumentOpen(doc.id, { useSelection });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
deferredSelectionRef.current = null;
|
deferredSelectionRef.current = null;
|
||||||
|
pointerIntentRef.current = null;
|
||||||
pointerMovedRef.current = false;
|
pointerMovedRef.current = false;
|
||||||
}}
|
}}
|
||||||
onPointerCancel={(event) => {
|
onPointerCancel={(event) => {
|
||||||
deferredSelectionRef.current = null;
|
deferredSelectionRef.current = null;
|
||||||
pointerMovedRef.current = false;
|
pointerMovedRef.current = false;
|
||||||
|
pointerIntentRef.current = null;
|
||||||
handlePointerCancel(event);
|
handlePointerCancel(event);
|
||||||
}}
|
}}
|
||||||
onDragEnter={(event) => handleTagDragEnterDoc(event, doc.id)}
|
onDragEnter={(event) => handleTagDragEnterDoc(event, doc.id)}
|
||||||
|
|||||||
@@ -20,8 +20,8 @@ import DropOverlay from './DropOverlay';
|
|||||||
import { useManagementModals } from './useManagementModals';
|
import { useManagementModals } from './useManagementModals';
|
||||||
import { api, useAppDispatch, useAppState } from './appState';
|
import { api, useAppDispatch, useAppState } from './appState';
|
||||||
import { useDetailPanel } from './useDetailPanel';
|
import { useDetailPanel } from './useDetailPanel';
|
||||||
import { useDocumentSelection } from './useDocumentSelection';
|
import useWorkspaceSelection from './useWorkspaceSelection';
|
||||||
import { useEntryPointerHandler } from '../documents/useEntryPointer';
|
import { useEntryPointerHandler as useEntryPointerCore } from '../documents/useEntryPointer';
|
||||||
import { isTagTransferEvent } from '../documents/tagTransfer';
|
import { isTagTransferEvent } from '../documents/tagTransfer';
|
||||||
|
|
||||||
const ASSET_PRESIGN_TTL_MS = 240 * 1000; // backend issues 5 min tokens; refresh slightly early
|
const ASSET_PRESIGN_TTL_MS = 240 * 1000; // backend issues 5 min tokens; refresh slightly early
|
||||||
@@ -218,7 +218,6 @@ const AppLayout = () => {
|
|||||||
setDeskHelpOpen(false);
|
setDeskHelpOpen(false);
|
||||||
}
|
}
|
||||||
}, [documentsViewMode, deskHelpOpen]);
|
}, [documentsViewMode, deskHelpOpen]);
|
||||||
const initialRowSelection = [];
|
|
||||||
const tokenRef = useRef(token);
|
const tokenRef = useRef(token);
|
||||||
const refreshPromiseRef = useRef(null);
|
const refreshPromiseRef = useRef(null);
|
||||||
const breadcrumbFetchRef = useRef(new Set());
|
const breadcrumbFetchRef = useRef(new Set());
|
||||||
@@ -358,8 +357,18 @@ const AppLayout = () => {
|
|||||||
}
|
}
|
||||||
const tagManager = tagManagerRef.current;
|
const tagManager = tagManagerRef.current;
|
||||||
|
|
||||||
|
const selection = useWorkspaceSelection({
|
||||||
|
resolveDocumentRowKey,
|
||||||
|
resolveFolderRowKey,
|
||||||
|
isDocumentRowKey,
|
||||||
|
isFolderRowKey,
|
||||||
|
getRowId,
|
||||||
|
});
|
||||||
|
|
||||||
const {
|
const {
|
||||||
selectedEntries,
|
selectedEntries,
|
||||||
|
selectedDocumentIds,
|
||||||
|
selectedFolderIds,
|
||||||
setSelectedEntries,
|
setSelectedEntries,
|
||||||
selectionOrder,
|
selectionOrder,
|
||||||
setSelectionOrder,
|
setSelectionOrder,
|
||||||
@@ -371,18 +380,11 @@ const AppLayout = () => {
|
|||||||
focusedRowKey,
|
focusedRowKey,
|
||||||
setFocusedRowKey,
|
setFocusedRowKey,
|
||||||
applySelection,
|
applySelection,
|
||||||
clearSelection: clearSelectionInternal,
|
clearSelection,
|
||||||
handleEntrySelection: handleEntrySelectionInternal,
|
handleEntrySelection,
|
||||||
promoteSelectionOrder: promoteSelectionOrderInternal,
|
promoteSelectionOrder: promoteSelectionOrderRaw,
|
||||||
configureSelectionEnvironment,
|
configureSelectionEnvironment,
|
||||||
} = useDocumentSelection({
|
} = selection;
|
||||||
resolveDocumentRowKey,
|
|
||||||
resolveFolderRowKey,
|
|
||||||
isDocumentRowKey,
|
|
||||||
isFolderRowKey,
|
|
||||||
getRowId,
|
|
||||||
initialEntries: initialRowSelection,
|
|
||||||
});
|
|
||||||
|
|
||||||
const getDocumentAsset = useCallback((doc, type) => {
|
const getDocumentAsset = useCallback((doc, type) => {
|
||||||
if (!doc || !type) return null;
|
if (!doc || !type) return null;
|
||||||
@@ -393,24 +395,6 @@ const AppLayout = () => {
|
|||||||
const dragCounterRef = useRef(0);
|
const dragCounterRef = useRef(0);
|
||||||
const detailFolderFetchRef = useRef(new Set());
|
const detailFolderFetchRef = useRef(new Set());
|
||||||
|
|
||||||
const selectedDocumentIds = useMemo(
|
|
||||||
() =>
|
|
||||||
selectedEntries
|
|
||||||
.filter(isDocumentRowKey)
|
|
||||||
.map((key) => getRowId(key))
|
|
||||||
.filter(Boolean),
|
|
||||||
[selectedEntries],
|
|
||||||
);
|
|
||||||
|
|
||||||
const selectedFolderIds = useMemo(
|
|
||||||
() =>
|
|
||||||
selectedEntries
|
|
||||||
.filter(isFolderRowKey)
|
|
||||||
.map((key) => getRowId(key))
|
|
||||||
.filter(Boolean),
|
|
||||||
[selectedEntries],
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
const resetWorkspaceState = useCallback(() => {
|
const resetWorkspaceState = useCallback(() => {
|
||||||
const rootNode = createRootNode();
|
const rootNode = createRootNode();
|
||||||
@@ -922,17 +906,10 @@ const AppLayout = () => {
|
|||||||
});
|
});
|
||||||
}, [configureSelectionEnvironment, visibleRowKeySet, navigableRowKeys]);
|
}, [configureSelectionEnvironment, visibleRowKeySet, navigableRowKeys]);
|
||||||
|
|
||||||
const handleEntrySelection = useCallback(
|
|
||||||
(rowKey, event) => {
|
|
||||||
handleEntrySelectionInternal(rowKey, event);
|
|
||||||
},
|
|
||||||
[handleEntrySelectionInternal],
|
|
||||||
);
|
|
||||||
|
|
||||||
const promoteSelectionOrder = useCallback(
|
const promoteSelectionOrder = useCallback(
|
||||||
(docId) => {
|
(docId) => {
|
||||||
if (!docId) return;
|
if (!docId) return;
|
||||||
promoteSelectionOrderInternal(docId);
|
promoteSelectionOrderRaw(docId);
|
||||||
const rowKey = resolveDocumentRowKey(docId);
|
const rowKey = resolveDocumentRowKey(docId);
|
||||||
if (rowKey) {
|
if (rowKey) {
|
||||||
selectionAnchorRef.current = rowKey;
|
selectionAnchorRef.current = rowKey;
|
||||||
@@ -941,7 +918,7 @@ const AppLayout = () => {
|
|||||||
setActivePreviewId(docId);
|
setActivePreviewId(docId);
|
||||||
},
|
},
|
||||||
[
|
[
|
||||||
promoteSelectionOrderInternal,
|
promoteSelectionOrderRaw,
|
||||||
selectionAnchorRef,
|
selectionAnchorRef,
|
||||||
setFocusedDocumentId,
|
setFocusedDocumentId,
|
||||||
setActivePreviewId,
|
setActivePreviewId,
|
||||||
@@ -949,8 +926,8 @@ const AppLayout = () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
const clearDocumentSelection = useCallback(() => {
|
const clearDocumentSelection = useCallback(() => {
|
||||||
clearSelectionInternal();
|
clearSelection();
|
||||||
}, [clearSelectionInternal]);
|
}, [clearSelection]);
|
||||||
|
|
||||||
const prevFocusedDocIdRef = useRef(focusedDocumentId);
|
const prevFocusedDocIdRef = useRef(focusedDocumentId);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -4225,17 +4202,14 @@ const AppLayout = () => {
|
|||||||
close: closeDetailPanel,
|
close: closeDetailPanel,
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleEntryPointer = useEntryPointerHandler({
|
const handleEntryPointerCore = useEntryPointerCore({
|
||||||
resolveDocumentRowKey,
|
resolveDocumentRowKey,
|
||||||
resolveFolderRowKey,
|
resolveFolderRowKey,
|
||||||
onSelectDocument: (documentId, event, { modifierClick, primaryClick, rowKey }) => {
|
onSelectDocument: (documentId, event, { rowKey }) => {
|
||||||
const key = rowKey || resolveDocumentRowKey(documentId);
|
const key = rowKey || resolveDocumentRowKey(documentId);
|
||||||
if (key) {
|
if (key) {
|
||||||
handleEntrySelection(key, event);
|
handleEntrySelection(key, event);
|
||||||
}
|
}
|
||||||
if (!modifierClick && primaryClick) {
|
|
||||||
openDetailPanel({ documentIds: [documentId] });
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
onSelectFolder: (folderId, event, { modifierClick, primaryClick, rowKey }) => {
|
onSelectFolder: (folderId, event, { modifierClick, primaryClick, rowKey }) => {
|
||||||
const key = rowKey || resolveFolderRowKey(folderId);
|
const key = rowKey || resolveFolderRowKey(folderId);
|
||||||
@@ -4248,6 +4222,16 @@ const AppLayout = () => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const inspectDocument = useCallback(
|
||||||
|
(documentId) => {
|
||||||
|
if (!documentId) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
openDetailPanel({ documentIds: [documentId] });
|
||||||
|
},
|
||||||
|
[openDetailPanel],
|
||||||
|
);
|
||||||
|
|
||||||
const { breadcrumbs, missingBreadcrumbAncestors } = useMemo(() => {
|
const { breadcrumbs, missingBreadcrumbAncestors } = useMemo(() => {
|
||||||
const chain = [];
|
const chain = [];
|
||||||
const seen = new Set();
|
const seen = new Set();
|
||||||
@@ -4580,7 +4564,8 @@ const AppLayout = () => {
|
|||||||
onViewModeChange: handleDocumentsViewModeChange,
|
onViewModeChange: handleDocumentsViewModeChange,
|
||||||
onClearSelection: clearDocumentSelection,
|
onClearSelection: clearDocumentSelection,
|
||||||
onDeleteSelection: handleDeleteSelection,
|
onDeleteSelection: handleDeleteSelection,
|
||||||
onEntryPointer: handleEntryPointer,
|
onEntryPointer: handleEntryPointerCore,
|
||||||
|
onInspectDocument: inspectDocument,
|
||||||
onEntrySelection: handleEntrySelection,
|
onEntrySelection: handleEntrySelection,
|
||||||
tags,
|
tags,
|
||||||
correspondents,
|
correspondents,
|
||||||
@@ -4611,7 +4596,8 @@ const AppLayout = () => {
|
|||||||
handleFolderDragEnd,
|
handleFolderDragEnd,
|
||||||
handleFolderDragStart,
|
handleFolderDragStart,
|
||||||
handleFolderRename,
|
handleFolderRename,
|
||||||
handleEntryPointer,
|
handleEntryPointerCore,
|
||||||
|
inspectDocument,
|
||||||
handleEntrySelection,
|
handleEntrySelection,
|
||||||
handleDeleteSelection,
|
handleDeleteSelection,
|
||||||
isFilterActive,
|
isFilterActive,
|
||||||
@@ -4777,20 +4763,6 @@ const AppLayout = () => {
|
|||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleDeskInspectDocument = useCallback(
|
|
||||||
(docId) => {
|
|
||||||
if (!docId) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const rowKey = resolveDocumentRowKey(docId);
|
|
||||||
if (rowKey) {
|
|
||||||
applySelection([rowKey], { anchor: rowKey, interactedKeys: [rowKey] });
|
|
||||||
}
|
|
||||||
openDetailPanel({ documentIds: [docId] });
|
|
||||||
},
|
|
||||||
[applySelection, openDetailPanel],
|
|
||||||
);
|
|
||||||
|
|
||||||
const handleDeskDocumentStackSelect = useCallback(
|
const handleDeskDocumentStackSelect = useCallback(
|
||||||
(docIds) => {
|
(docIds) => {
|
||||||
if (!Array.isArray(docIds) || docIds.length === 0) {
|
if (!Array.isArray(docIds) || docIds.length === 0) {
|
||||||
@@ -4822,6 +4794,28 @@ const AppLayout = () => {
|
|||||||
[applySelection, selectedEntries, selectionAnchorRef],
|
[applySelection, selectedEntries, selectionAnchorRef],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const handleDeskDocumentOpen = useCallback(
|
||||||
|
(docId, { useSelection = false } = {}) => {
|
||||||
|
const selectionDocIds = Array.isArray(selectedDocumentIds) ? selectedDocumentIds : [];
|
||||||
|
let targetIds = [];
|
||||||
|
|
||||||
|
if ((useSelection || selectionDocIds.includes(docId)) && selectionDocIds.length) {
|
||||||
|
targetIds = selectionDocIds;
|
||||||
|
} else if (selectionDocIds.length) {
|
||||||
|
targetIds = selectionDocIds;
|
||||||
|
} else if (docId) {
|
||||||
|
targetIds = [docId];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!targetIds.length) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
openDetailPanel({ documentIds: targetIds });
|
||||||
|
},
|
||||||
|
[openDetailPanel, selectedDocumentIds],
|
||||||
|
);
|
||||||
|
|
||||||
const handleDeskHelpOpen = useCallback(() => {
|
const handleDeskHelpOpen = useCallback(() => {
|
||||||
setDeskHelpOpen(true);
|
setDeskHelpOpen(true);
|
||||||
}, []);
|
}, []);
|
||||||
@@ -4857,9 +4851,9 @@ const AppLayout = () => {
|
|||||||
onViewModeChange: handleDocumentsViewModeChange,
|
onViewModeChange: handleDocumentsViewModeChange,
|
||||||
onExit: handleDeskExit,
|
onExit: handleDeskExit,
|
||||||
onRefresh: refreshCurrentFolder,
|
onRefresh: refreshCurrentFolder,
|
||||||
onDocumentOpen: openDocumentPreview,
|
onDocumentOpen: handleDeskDocumentOpen,
|
||||||
onInspectDocument: handleDeskInspectDocument,
|
onInspectDocument: null,
|
||||||
onEntryPointer: handleEntryPointer,
|
onEntryPointer: handleEntryPointerCore,
|
||||||
onDocumentStackSelect: handleDeskDocumentStackSelect,
|
onDocumentStackSelect: handleDeskDocumentStackSelect,
|
||||||
onPromoteSelection: promoteSelectionOrder,
|
onPromoteSelection: promoteSelectionOrder,
|
||||||
onOpenHelp: handleDeskHelpOpen,
|
onOpenHelp: handleDeskHelpOpen,
|
||||||
@@ -4898,10 +4892,8 @@ const AppLayout = () => {
|
|||||||
handleDocumentsViewModeChange,
|
handleDocumentsViewModeChange,
|
||||||
handleDeskExit,
|
handleDeskExit,
|
||||||
refreshCurrentFolder,
|
refreshCurrentFolder,
|
||||||
openDocumentPreview,
|
|
||||||
handleDeskInspectDocument,
|
|
||||||
handleDeskDocumentStackSelect,
|
handleDeskDocumentStackSelect,
|
||||||
handleEntryPointer,
|
handleEntryPointerCore,
|
||||||
promoteSelectionOrder,
|
promoteSelectionOrder,
|
||||||
handleDeskHelpOpen,
|
handleDeskHelpOpen,
|
||||||
handleDeskHelpClose,
|
handleDeskHelpClose,
|
||||||
@@ -4913,6 +4905,7 @@ const AppLayout = () => {
|
|||||||
clearDocumentSelection,
|
clearDocumentSelection,
|
||||||
detailPanelOpen,
|
detailPanelOpen,
|
||||||
handleDetailPanelClose,
|
handleDetailPanelClose,
|
||||||
|
handleDeskDocumentOpen,
|
||||||
resolveThumbnailUrlForDoc,
|
resolveThumbnailUrlForDoc,
|
||||||
handleDocumentTagAttach,
|
handleDocumentTagAttach,
|
||||||
handleTagRemove,
|
handleTagRemove,
|
||||||
|
|||||||
@@ -0,0 +1,48 @@
|
|||||||
|
import { useCallback } from 'react';
|
||||||
|
import { useEntryPointerHandler as useEntryPointerCore, isPointerModifierEvent, isPrimaryPointerEvent } from '../documents/useEntryPointer';
|
||||||
|
|
||||||
|
export const useEntryPointer = ({
|
||||||
|
resolveDocumentRowKey,
|
||||||
|
resolveFolderRowKey,
|
||||||
|
onSelectDocument,
|
||||||
|
onInspectDocument,
|
||||||
|
onSelectFolder,
|
||||||
|
}) => {
|
||||||
|
const coreHandler = useEntryPointerCore({
|
||||||
|
resolveDocumentRowKey,
|
||||||
|
resolveFolderRowKey,
|
||||||
|
onSelectDocument: (documentId, event, meta) => {
|
||||||
|
const { modifierClick, primaryClick, rowKey } = meta;
|
||||||
|
onSelectDocument(documentId, event, { modifierClick, primaryClick, rowKey });
|
||||||
|
if (!modifierClick && primaryClick && typeof onInspectDocument === 'function') {
|
||||||
|
onInspectDocument(documentId, meta);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onSelectFolder,
|
||||||
|
});
|
||||||
|
|
||||||
|
return useCallback((entry, event) => {
|
||||||
|
if (!entry) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (entry.type !== 'document') {
|
||||||
|
coreHandler(entry, event);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const modifierClick = isPointerModifierEvent(event);
|
||||||
|
const primaryClick = isPrimaryPointerEvent(event);
|
||||||
|
|
||||||
|
onSelectDocument(entry.id, event, {
|
||||||
|
modifierClick,
|
||||||
|
primaryClick,
|
||||||
|
rowKey: entry.key,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!modifierClick && primaryClick) {
|
||||||
|
onInspectDocument?.(entry.id, { modifierClick, primaryClick, rowKey: entry.key });
|
||||||
|
}
|
||||||
|
}, [coreHandler, onInspectDocument, onSelectDocument]);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default useEntryPointer;
|
||||||
@@ -24,7 +24,6 @@ const useDocumentDrag = () => {
|
|||||||
recalcVisibleDocIds,
|
recalcVisibleDocIds,
|
||||||
settings,
|
settings,
|
||||||
containerRef,
|
containerRef,
|
||||||
onDocumentOpen,
|
|
||||||
onInspectDocument,
|
onInspectDocument,
|
||||||
onDocumentStackSelect,
|
onDocumentStackSelect,
|
||||||
selectedDocumentIds,
|
selectedDocumentIds,
|
||||||
@@ -76,9 +75,7 @@ const useDocumentDrag = () => {
|
|||||||
}
|
}
|
||||||
if (typeof onInspectDocument === 'function') {
|
if (typeof onInspectDocument === 'function') {
|
||||||
onInspectDocument(data.docId);
|
onInspectDocument(data.docId);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
onDocumentOpen?.(data.docId);
|
|
||||||
},
|
},
|
||||||
onDouble: ({ data, event }) => {
|
onDouble: ({ data, event }) => {
|
||||||
if (!data || !data.docId) {
|
if (!data || !data.docId) {
|
||||||
@@ -146,17 +143,26 @@ const useDocumentDrag = () => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const stackDocIdsOption = Array.isArray(options?.stackDocIds)
|
const stackDocIdsOptionRaw = options?.stackDocIds;
|
||||||
? options.stackDocIds
|
const stackDocIdsOption = Array.isArray(stackDocIdsOptionRaw)
|
||||||
|
? stackDocIdsOptionRaw
|
||||||
.map((value) => (value != null ? String(value) : null))
|
.map((value) => (value != null ? String(value) : null))
|
||||||
.filter(Boolean)
|
.filter(Boolean)
|
||||||
: null;
|
: null;
|
||||||
const stackSelectionAppliedInitial = Boolean(options?.stackSelectionApplied);
|
const stackSelectionAppliedInitial = Boolean(options?.stackSelectionApplied);
|
||||||
|
const wasSelectedAtPointerDown = Boolean(options?.wasSelected);
|
||||||
|
const pointerModifierActive = typeof options?.modifierActive === 'boolean'
|
||||||
|
? options.modifierActive
|
||||||
|
: Boolean(event.metaKey || event.ctrlKey || event.shiftKey || event.altKey);
|
||||||
|
|
||||||
let selectionIds = Array.isArray(selectedDocumentIds)
|
let selectionIds = Array.isArray(selectedDocumentIds)
|
||||||
? selectedDocumentIds.map((id) => String(id))
|
? selectedDocumentIds.map((id) => String(id))
|
||||||
: [];
|
: [];
|
||||||
|
|
||||||
|
if (!stackDocIdsOption && !pointerModifierActive && !wasSelectedAtPointerDown) {
|
||||||
|
selectionIds = [];
|
||||||
|
}
|
||||||
|
|
||||||
if (stackDocIdsOption && stackDocIdsOption.length) {
|
if (stackDocIdsOption && stackDocIdsOption.length) {
|
||||||
const selectionSet = new Set(selectionIds);
|
const selectionSet = new Set(selectionIds);
|
||||||
stackDocIdsOption.forEach((value) => {
|
stackDocIdsOption.forEach((value) => {
|
||||||
@@ -204,7 +210,7 @@ const useDocumentDrag = () => {
|
|||||||
const centerX = typeof entry?.centerX === 'number' ? entry.centerX : defaultCenterX;
|
const centerX = typeof entry?.centerX === 'number' ? entry.centerX : defaultCenterX;
|
||||||
const centerY = typeof entry?.centerY === 'number' ? entry.centerY : defaultCenterY;
|
const centerY = typeof entry?.centerY === 'number' ? entry.centerY : defaultCenterY;
|
||||||
|
|
||||||
const modifierPressed = event.metaKey || event.ctrlKey || event.shiftKey || event.altKey;
|
const modifierPressed = pointerModifierActive;
|
||||||
if (!modifierPressed) {
|
if (!modifierPressed) {
|
||||||
if (isGroupDrag) {
|
if (isGroupDrag) {
|
||||||
const layout = layoutRef.current;
|
const layout = layoutRef.current;
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ const DocumentsPanel = ({
|
|||||||
onDocumentRename,
|
onDocumentRename,
|
||||||
onEntryPointer = null,
|
onEntryPointer = null,
|
||||||
onEntrySelection = null,
|
onEntrySelection = null,
|
||||||
|
onInspectDocument = null,
|
||||||
tagLookupById,
|
tagLookupById,
|
||||||
activeCorrespondentIds = [],
|
activeCorrespondentIds = [],
|
||||||
onFocusedRowChange,
|
onFocusedRowChange,
|
||||||
@@ -300,6 +301,7 @@ const DocumentsPanel = ({
|
|||||||
const entry = getEntryByKey(activeRow.key);
|
const entry = getEntryByKey(activeRow.key);
|
||||||
if (entry?.document) {
|
if (entry?.document) {
|
||||||
handleDocumentActivate(entry.document, event);
|
handleDocumentActivate(entry.document, event);
|
||||||
|
onInspectDocument?.(entry.document.id, event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -341,6 +343,7 @@ const DocumentsPanel = ({
|
|||||||
onEntrySelection,
|
onEntrySelection,
|
||||||
onFocusedRowChange,
|
onFocusedRowChange,
|
||||||
onFolderSelect,
|
onFolderSelect,
|
||||||
|
onInspectDocument,
|
||||||
selectedEntries,
|
selectedEntries,
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
@@ -479,8 +482,16 @@ const DocumentsPanel = ({
|
|||||||
event,
|
event,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
typeof onInspectDocument === 'function'
|
||||||
|
&& !isPointerModifierEvent(event)
|
||||||
|
&& isPrimaryPointerEvent(event)
|
||||||
|
) {
|
||||||
|
onInspectDocument(doc.id, event);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
[onEntryPointer],
|
[onEntryPointer, onInspectDocument],
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleFolderClick = useCallback(
|
const handleFolderClick = useCallback(
|
||||||
|
|||||||
Reference in New Issue
Block a user