From 4bc7357e41613a70ad759192055afaafd11c5486 Mon Sep 17 00:00:00 2001 From: Nils Schneider Date: Fri, 7 Nov 2025 23:48:25 +0100 Subject: [PATCH] ux --- frontend/src/app/AppLayout.jsx | 3 +- frontend/src/desktop/DesktopWorkspace.jsx | 24 +++++++++++-- frontend/src/desktop/pointer/pointerUtils.js | 2 +- .../src/desktop/pointer/useDeskPointer.js | 21 ++++++++--- frontend/src/desktop/useDocumentDrag.js | 19 ++++------ frontend/src/documents/DocumentsPanel.jsx | 36 ++++++++++--------- frontend/src/ui/icons.js | 10 ++++++ 7 files changed, 77 insertions(+), 38 deletions(-) diff --git a/frontend/src/app/AppLayout.jsx b/frontend/src/app/AppLayout.jsx index cda9ee9..c2560e6 100644 --- a/frontend/src/app/AppLayout.jsx +++ b/frontend/src/app/AppLayout.jsx @@ -5030,7 +5030,7 @@ const AppLayout = () => { onExit: handleDeskExit, onRefresh: refreshCurrentFolder, onDocumentOpen: handleDeskDocumentOpen, - onInspectDocument: null, + onInspectDocument: inspectDocument, onEntryPointer: handleEntryPointerCore, onDocumentStackSelect: handleDeskDocumentStackSelect, onPromoteSelection: promoteSelectionOrder, @@ -5088,6 +5088,7 @@ const AppLayout = () => { detailPanelOpen, handleDetailPanelClose, handleDeskDocumentOpen, + inspectDocument, resolveThumbnailUrlForDoc, handleDocumentTagDrop, handleTagRemove, diff --git a/frontend/src/desktop/DesktopWorkspace.jsx b/frontend/src/desktop/DesktopWorkspace.jsx index 86b952a..ad65cd2 100644 --- a/frontend/src/desktop/DesktopWorkspace.jsx +++ b/frontend/src/desktop/DesktopWorkspace.jsx @@ -703,7 +703,6 @@ const DesktopWorkspace = ({ onDocumentOpen, onDocumentStackSelect, onEntryPointer, - onInspectDocument, onPromoteSelection, openOverlayForDoc, overlayDisplay, @@ -717,6 +716,7 @@ const DesktopWorkspace = ({ setDraggingId, selectedDocumentIds, detailPanelOpen, + onInspectDocument, markLayoutDirty, tagDropTargetId, visibleDocIds, @@ -804,7 +804,7 @@ const DesktopWorkspaceView = ({ markLayoutDirty, }); - const { getCardPointerHandlers, handleShellKeyDown } = useDeskPointer({ + const { getCardPointerHandlers, handleShellKeyDown, focusShell } = useDeskPointer({ containerRef, items, layoutRef, @@ -819,11 +819,27 @@ const DesktopWorkspaceView = ({ onPromoteSelection, onDocumentOpen, selectedDocumentIds, - onClearSelection, detailPanelOpen, onCloseDetailPanel, + openOverlayForDoc, }); + useEffect(() => { + focusShell(); + }, [focusShell]); + + useEffect(() => { + if (selectedDocumentIds.length) { + focusShell(); + } + }, [focusShell, selectedDocumentIds.length]); + + useEffect(() => { + if (!detailPanelOpen) { + focusShell(); + } + }, [detailPanelOpen, focusShell]); + const allSizesReady = items.every((doc) => ensureDocumentSize(doc)); @@ -834,6 +850,7 @@ const DesktopWorkspaceView = ({ if (event.target === event.currentTarget && typeof onClearSelection === 'function') { onClearSelection(); } + focusShell(); }} >
{!allSizesReady ? ( diff --git a/frontend/src/desktop/pointer/pointerUtils.js b/frontend/src/desktop/pointer/pointerUtils.js index e6603c1..160d78a 100644 --- a/frontend/src/desktop/pointer/pointerUtils.js +++ b/frontend/src/desktop/pointer/pointerUtils.js @@ -40,7 +40,7 @@ export const createPointerIntent = ({ clickAction = CLICK_ACTIONS.addStack; dragAction = DRAG_ACTIONS.dragSelectStack; } else if (alreadySelected) { - clickAction = CLICK_ACTIONS.openDetail; + clickAction = CLICK_ACTIONS.selectSingle; dragAction = selectionCount > 1 ? DRAG_ACTIONS.dragSelection : DRAG_ACTIONS.dragSelectSingle; } else { clickAction = CLICK_ACTIONS.selectSingle; diff --git a/frontend/src/desktop/pointer/useDeskPointer.js b/frontend/src/desktop/pointer/useDeskPointer.js index 0206a1c..855f955 100644 --- a/frontend/src/desktop/pointer/useDeskPointer.js +++ b/frontend/src/desktop/pointer/useDeskPointer.js @@ -37,9 +37,9 @@ export const useDeskPointer = ({ onPromoteSelection, onDocumentOpen, selectedDocumentIds, - onClearSelection, detailPanelOpen, onCloseDetailPanel, + openOverlayForDoc = null, }) => { const pointerIntentRef = useRef(null); const pointerStartRef = useRef({ x: 0, y: 0 }); @@ -401,9 +401,16 @@ export const useDeskPointer = ({ } } - if (Array.isArray(selectedDocumentIds) && selectedDocumentIds.length > 0) { + if ( + typeof openOverlayForDoc === 'function' + && Array.isArray(selectedDocumentIds) + && selectedDocumentIds.length > 0 + ) { event.preventDefault(); - onClearSelection?.(); + const targetId = selectedDocumentIds[selectedDocumentIds.length - 1]; + if (targetId) { + openOverlayForDoc(targetId); + } return; } @@ -412,12 +419,18 @@ export const useDeskPointer = ({ safeInvoke(onCloseDetailPanel); } }, - [detailPanelOpen, onClearSelection, onCloseDetailPanel, selectedDocumentIds], + [detailPanelOpen, onCloseDetailPanel, openOverlayForDoc, selectedDocumentIds], ); return { getCardPointerHandlers, handleShellKeyDown, + focusShell: () => { + const shell = containerRef.current; + if (shell && typeof shell.focus === 'function') { + shell.focus({ preventScroll: true }); + } + }, }; }; diff --git a/frontend/src/desktop/useDocumentDrag.js b/frontend/src/desktop/useDocumentDrag.js index 0a73d49..354e20c 100644 --- a/frontend/src/desktop/useDocumentDrag.js +++ b/frontend/src/desktop/useDocumentDrag.js @@ -54,25 +54,18 @@ const useDocumentDrag = (options = {}) => { const tapHandler = usePointerTap({ delay: 220, - onSingle: ({ data, event }) => { - if (!data || !data.docId) { - return; - } - if (event && (event.metaKey || event.ctrlKey || event.shiftKey || event.altKey)) { - return; - } - if (typeof onInspectDocument === 'function') { - onInspectDocument(data.docId); - } - }, + onSingle: () => {}, onDouble: ({ data, event }) => { if (!data || !data.docId) { return; } - if (event && (event.metaKey || event.ctrlKey || event.shiftKey || event.altKey)) { + if (event?.altKey) { + openOverlayForDoc(data.docId, data.originInfo); return; } - openOverlayForDoc(data.docId, data.originInfo); + if (typeof onInspectDocument === 'function') { + onInspectDocument(data.docId, event); + } }, }); const dragStateRef = useRef(null); diff --git a/frontend/src/documents/DocumentsPanel.jsx b/frontend/src/documents/DocumentsPanel.jsx index 9e1d759..740b423 100644 --- a/frontend/src/documents/DocumentsPanel.jsx +++ b/frontend/src/documents/DocumentsPanel.jsx @@ -204,6 +204,9 @@ const DocumentsPanel = ({ const handleDocumentActivate = useCallback( (doc, event) => { + if (!doc) { + return; + } if (event) { if (typeof event.preventDefault === 'function') { event.preventDefault(); @@ -212,9 +215,13 @@ const DocumentsPanel = ({ event.stopPropagation(); } } - handleDocumentPreviewZoom(doc); + if (event?.altKey) { + handleDocumentPreviewZoom(doc); + return; + } + onInspectDocument?.(doc.id, event); }, - [handleDocumentPreviewZoom], + [handleDocumentPreviewZoom, onInspectDocument], ); const selectedRowKeySet = useMemo(() => new Set(selectedEntries || []), [selectedEntries]); @@ -318,8 +325,7 @@ const DocumentsPanel = ({ } else { const entry = getEntryByKey(activeRow.key); if (entry?.document) { - handleDocumentActivate(entry.document, event); - onInspectDocument?.(entry.document.id, event); + handleDocumentPreviewZoom(entry.document); } } } @@ -355,14 +361,13 @@ const DocumentsPanel = ({ [ focusedRowKey, getEntryByKey, - handleDocumentActivate, navigableRowKeys, navigableRows, onEntrySelection, onFocusedRowChange, onFolderSelect, - onInspectDocument, selectedEntries, + handleDocumentPreviewZoom, ], ); @@ -500,16 +505,8 @@ const DocumentsPanel = ({ event, ); } - - if ( - typeof onInspectDocument === 'function' - && !isPointerModifierEvent(event) - && isPrimaryPointerEvent(event) - ) { - onInspectDocument(doc.id, event); - } }, - [onEntryPointer, onInspectDocument], + [onEntryPointer], ); const handleFolderClick = useCallback( @@ -980,6 +977,7 @@ export const createDocumentsSurface = ({ onMoveDocumentsToFolder, searchIncludeDescendants, onToggleSearchIncludeDescendants, + onInspectDocument, } = tableProps; const title = Array.isArray(searchResults) ? 'Search results' : currentFolderName; @@ -1044,7 +1042,13 @@ export const createDocumentsSurface = ({ breadcrumbs, selectionLabel: null, floatingActions, - content: , + content: ( + + ), detail, }); diff --git a/frontend/src/ui/icons.js b/frontend/src/ui/icons.js index 1e85254..6b4cb25 100644 --- a/frontend/src/ui/icons.js +++ b/frontend/src/ui/icons.js @@ -38,6 +38,7 @@ import { IconLoader, IconSortAscendingLetters, IconSortDescendingLetters, + IconFileInfo, } from '@tabler/icons-react'; import FolderSvg from '../assets/folder.svg'; @@ -176,6 +177,15 @@ export const InfoIcon = ({ className, size = '1em', stroke = 1.6, ...rest }) => /> ); +export const FileInfoIcon = ({ className, size = '1em', stroke = 1.6, ...rest }) => ( + +); + export const DetailPanelCollapseIcon = ({ className, size = '1em', stroke = 1.6, ...rest }) => (