This commit is contained in:
2025-11-04 11:37:01 +01:00
parent f523e5651b
commit dd378b3ad8
6 changed files with 216 additions and 112 deletions
+63 -70
View File
@@ -20,8 +20,8 @@ import DropOverlay from './DropOverlay';
import { useManagementModals } from './useManagementModals';
import { api, useAppDispatch, useAppState } from './appState';
import { useDetailPanel } from './useDetailPanel';
import { useDocumentSelection } from './useDocumentSelection';
import { useEntryPointerHandler } from '../documents/useEntryPointer';
import useWorkspaceSelection from './useWorkspaceSelection';
import { useEntryPointerHandler as useEntryPointerCore } from '../documents/useEntryPointer';
import { isTagTransferEvent } from '../documents/tagTransfer';
const ASSET_PRESIGN_TTL_MS = 240 * 1000; // backend issues 5 min tokens; refresh slightly early
@@ -218,7 +218,6 @@ const AppLayout = () => {
setDeskHelpOpen(false);
}
}, [documentsViewMode, deskHelpOpen]);
const initialRowSelection = [];
const tokenRef = useRef(token);
const refreshPromiseRef = useRef(null);
const breadcrumbFetchRef = useRef(new Set());
@@ -358,8 +357,18 @@ const AppLayout = () => {
}
const tagManager = tagManagerRef.current;
const selection = useWorkspaceSelection({
resolveDocumentRowKey,
resolveFolderRowKey,
isDocumentRowKey,
isFolderRowKey,
getRowId,
});
const {
selectedEntries,
selectedDocumentIds,
selectedFolderIds,
setSelectedEntries,
selectionOrder,
setSelectionOrder,
@@ -371,18 +380,11 @@ const AppLayout = () => {
focusedRowKey,
setFocusedRowKey,
applySelection,
clearSelection: clearSelectionInternal,
handleEntrySelection: handleEntrySelectionInternal,
promoteSelectionOrder: promoteSelectionOrderInternal,
clearSelection,
handleEntrySelection,
promoteSelectionOrder: promoteSelectionOrderRaw,
configureSelectionEnvironment,
} = useDocumentSelection({
resolveDocumentRowKey,
resolveFolderRowKey,
isDocumentRowKey,
isFolderRowKey,
getRowId,
initialEntries: initialRowSelection,
});
} = selection;
const getDocumentAsset = useCallback((doc, type) => {
if (!doc || !type) return null;
@@ -393,24 +395,6 @@ const AppLayout = () => {
const dragCounterRef = useRef(0);
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 rootNode = createRootNode();
@@ -922,17 +906,10 @@ const AppLayout = () => {
});
}, [configureSelectionEnvironment, visibleRowKeySet, navigableRowKeys]);
const handleEntrySelection = useCallback(
(rowKey, event) => {
handleEntrySelectionInternal(rowKey, event);
},
[handleEntrySelectionInternal],
);
const promoteSelectionOrder = useCallback(
(docId) => {
if (!docId) return;
promoteSelectionOrderInternal(docId);
promoteSelectionOrderRaw(docId);
const rowKey = resolveDocumentRowKey(docId);
if (rowKey) {
selectionAnchorRef.current = rowKey;
@@ -941,7 +918,7 @@ const AppLayout = () => {
setActivePreviewId(docId);
},
[
promoteSelectionOrderInternal,
promoteSelectionOrderRaw,
selectionAnchorRef,
setFocusedDocumentId,
setActivePreviewId,
@@ -949,8 +926,8 @@ const AppLayout = () => {
);
const clearDocumentSelection = useCallback(() => {
clearSelectionInternal();
}, [clearSelectionInternal]);
clearSelection();
}, [clearSelection]);
const prevFocusedDocIdRef = useRef(focusedDocumentId);
useEffect(() => {
@@ -4225,17 +4202,14 @@ const AppLayout = () => {
close: closeDetailPanel,
};
const handleEntryPointer = useEntryPointerHandler({
const handleEntryPointerCore = useEntryPointerCore({
resolveDocumentRowKey,
resolveFolderRowKey,
onSelectDocument: (documentId, event, { modifierClick, primaryClick, rowKey }) => {
onSelectDocument: (documentId, event, { rowKey }) => {
const key = rowKey || resolveDocumentRowKey(documentId);
if (key) {
handleEntrySelection(key, event);
}
if (!modifierClick && primaryClick) {
openDetailPanel({ documentIds: [documentId] });
}
},
onSelectFolder: (folderId, event, { modifierClick, primaryClick, rowKey }) => {
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 chain = [];
const seen = new Set();
@@ -4580,7 +4564,8 @@ const AppLayout = () => {
onViewModeChange: handleDocumentsViewModeChange,
onClearSelection: clearDocumentSelection,
onDeleteSelection: handleDeleteSelection,
onEntryPointer: handleEntryPointer,
onEntryPointer: handleEntryPointerCore,
onInspectDocument: inspectDocument,
onEntrySelection: handleEntrySelection,
tags,
correspondents,
@@ -4611,7 +4596,8 @@ const AppLayout = () => {
handleFolderDragEnd,
handleFolderDragStart,
handleFolderRename,
handleEntryPointer,
handleEntryPointerCore,
inspectDocument,
handleEntrySelection,
handleDeleteSelection,
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(
(docIds) => {
if (!Array.isArray(docIds) || docIds.length === 0) {
@@ -4822,6 +4794,28 @@ const AppLayout = () => {
[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(() => {
setDeskHelpOpen(true);
}, []);
@@ -4857,9 +4851,9 @@ const AppLayout = () => {
onViewModeChange: handleDocumentsViewModeChange,
onExit: handleDeskExit,
onRefresh: refreshCurrentFolder,
onDocumentOpen: openDocumentPreview,
onInspectDocument: handleDeskInspectDocument,
onEntryPointer: handleEntryPointer,
onDocumentOpen: handleDeskDocumentOpen,
onInspectDocument: null,
onEntryPointer: handleEntryPointerCore,
onDocumentStackSelect: handleDeskDocumentStackSelect,
onPromoteSelection: promoteSelectionOrder,
onOpenHelp: handleDeskHelpOpen,
@@ -4898,10 +4892,8 @@ const AppLayout = () => {
handleDocumentsViewModeChange,
handleDeskExit,
refreshCurrentFolder,
openDocumentPreview,
handleDeskInspectDocument,
handleDeskDocumentStackSelect,
handleEntryPointer,
handleEntryPointerCore,
promoteSelectionOrder,
handleDeskHelpOpen,
handleDeskHelpClose,
@@ -4913,6 +4905,7 @@ const AppLayout = () => {
clearDocumentSelection,
detailPanelOpen,
handleDetailPanelClose,
handleDeskDocumentOpen,
resolveThumbnailUrlForDoc,
handleDocumentTagAttach,
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;