From f0b58317b91a857b91fa38b55b154afe463dedfa Mon Sep 17 00:00:00 2001 From: Nils Schneider Date: Wed, 10 Dec 2025 01:48:46 +0100 Subject: [PATCH] refactor: restructure `useAppShell` context into nested objects --- frontend/src/app/SettingsRoute.tsx | 8 +- frontend/src/app/useDocumentsShell.ts | 32 ++--- .../documents/data/useDocumentsWorkspace.ts | 28 ++--- .../selection/SelectionFloatingActions.tsx | 4 +- .../documents/logic/useDocumentsPanelProps.ts | 115 ++++++++++-------- frontend/src/index.tsx | 4 +- frontend/src/sidebar/Sidebar.tsx | 22 +++- .../sidebar/components/SidebarFolderList.tsx | 3 +- 8 files changed, 123 insertions(+), 93 deletions(-) diff --git a/frontend/src/app/SettingsRoute.tsx b/frontend/src/app/SettingsRoute.tsx index ee15126..43ca189 100644 --- a/frontend/src/app/SettingsRoute.tsx +++ b/frontend/src/app/SettingsRoute.tsx @@ -11,10 +11,10 @@ interface SettingsRouteProps { } const SettingsRoute: React.FC = ({ open = true, onClose }) => { + const shell = useAppShell() as any; + const { token } = shell.session || {}; + const { notifyApiError, setStatusMessage } = shell.ui || {}; const { - token, - notifyApiError, - setStatusMessage, passkeys, passkeysSupported, passkeysLoading, @@ -23,7 +23,7 @@ const SettingsRoute: React.FC = ({ open = true, onClose }) = refreshPasskeys, registerPasskey, revokePasskey, - } = useAppShell() as Record; + } = shell.passkeys || {}; const { tokens, diff --git a/frontend/src/app/useDocumentsShell.ts b/frontend/src/app/useDocumentsShell.ts index 33fe411..e8dedd1 100644 --- a/frontend/src/app/useDocumentsShell.ts +++ b/frontend/src/app/useDocumentsShell.ts @@ -20,31 +20,31 @@ interface DocumentsShellView { } const useDocumentsShell = (): DocumentsShellView => { - const shell = useAppShell(); + const shell = useAppShell() as any; const documentsPanelProps = useDocumentsPanelProps(shell as any); return useMemo(() => { const surfaceConfig: WorkspaceSurfaceConfig = { documentsTableProps: documentsPanelProps, - detailPanelProps: (shell.detailPanelProps ?? null) as WorkspaceSurfaceConfig['detailPanelProps'], - detailPanelOpen: Boolean(shell.detailPanelOpen), - openDetailPanel: shell.openDetailPanel as WorkspaceSurfaceConfig['openDetailPanel'], - closeDetailPanel: shell.closeDetailPanel as WorkspaceSurfaceConfig['closeDetailPanel'], - previewWorkspaceDocument: shell.previewWorkspaceDocument, - previewDocumentId: (shell.previewDocumentId as Identifier) ?? null, - closeDocumentPreview: shell.closeDocumentPreview as WorkspaceSurfaceConfig['closeDocumentPreview'], - ensurePreviewData: shell.ensurePreviewData as WorkspaceSurfaceConfig['ensurePreviewData'], - ensureAssetUrl: shell.ensureAssetUrl as WorkspaceSurfaceConfig['ensureAssetUrl'], - getDocumentAsset: shell.getDocumentAsset as WorkspaceSurfaceConfig['getDocumentAsset'], - notifyApiError: shell.notifyApiError as WorkspaceSurfaceConfig['notifyApiError'], - handleBreadcrumbNavigate: shell.handleBreadcrumbNavigate as WorkspaceSurfaceConfig['handleBreadcrumbNavigate'], + detailPanelProps: (shell.detailPanel?.detailPanelProps ?? null) as WorkspaceSurfaceConfig['detailPanelProps'], + detailPanelOpen: Boolean(shell.detailPanel?.detailPanelOpen), + openDetailPanel: shell.detailPanel?.openDetailPanel as WorkspaceSurfaceConfig['openDetailPanel'], + closeDetailPanel: shell.detailPanel?.closeDetailPanel as WorkspaceSurfaceConfig['closeDetailPanel'], + previewWorkspaceDocument: shell.preview?.previewWorkspaceDocument, + previewDocumentId: (shell.preview?.previewDocumentId as Identifier) ?? null, + closeDocumentPreview: shell.preview?.closeDocumentPreview as WorkspaceSurfaceConfig['closeDocumentPreview'], + ensurePreviewData: shell.preview?.ensurePreviewData as WorkspaceSurfaceConfig['ensurePreviewData'], + ensureAssetUrl: shell.preview?.ensureAssetUrl as WorkspaceSurfaceConfig['ensureAssetUrl'], + getDocumentAsset: shell.preview?.getDocumentAsset as WorkspaceSurfaceConfig['getDocumentAsset'], + notifyApiError: shell.ui?.notifyApiError as WorkspaceSurfaceConfig['notifyApiError'], + handleBreadcrumbNavigate: shell.folderTree?.handleBreadcrumbNavigate as WorkspaceSurfaceConfig['handleBreadcrumbNavigate'], }; return { surfaceConfig, - documentsFilter: shell.documentsFilter as DocumentsFilterValue, - documentsManager: shell.documentsManager, - foldersManager: shell.foldersManager, + documentsFilter: shell.search?.documentsFilter as DocumentsFilterValue, + documentsManager: shell.managers?.documentsManager, + foldersManager: shell.folderTree?.foldersManager, }; }, [shell, documentsPanelProps]); }; diff --git a/frontend/src/documents/data/useDocumentsWorkspace.ts b/frontend/src/documents/data/useDocumentsWorkspace.ts index d385e90..637fb04 100644 --- a/frontend/src/documents/data/useDocumentsWorkspace.ts +++ b/frontend/src/documents/data/useDocumentsWorkspace.ts @@ -949,8 +949,6 @@ const useDocumentsWorkspace = ({ return () => window.removeEventListener('keydown', handleKeyDown); }, [settingsOpen]); - - const { detailPanelProps, detailPanelOpen, @@ -1151,19 +1149,19 @@ const useDocumentsWorkspace = ({ }; const contextValue = { - ...sessionContext, - ...uiContext, - ...uploadContext, - ...tagsContext, - ...correspondentsContext, - ...passkeysContext, - ...previewContext, - ...detailPanelContext, - ...searchContext, - ...folderTreeContext, - ...selectionContext, - ...documentMutations, - ...managers, + session: sessionContext, + ui: uiContext, + upload: uploadContext, + tags: tagsContext, + correspondents: correspondentsContext, + passkeys: passkeysContext, + preview: previewContext, + detailPanel: detailPanelContext, + search: searchContext, + folderTree: folderTreeContext, + selection: selectionContext, + mutations: documentMutations, + managers: managers, }; // hook callers handle rendering / routing diff --git a/frontend/src/documents/features/selection/SelectionFloatingActions.tsx b/frontend/src/documents/features/selection/SelectionFloatingActions.tsx index 8e0a4c2..f570e33 100644 --- a/frontend/src/documents/features/selection/SelectionFloatingActions.tsx +++ b/frontend/src/documents/features/selection/SelectionFloatingActions.tsx @@ -235,8 +235,8 @@ const SelectionFloatingActions: React.FC = ({ ), [documentLookup]); const tagLookupMap = tagLookupById instanceof Map ? tagLookupById : null; - const shell = useAppShell(); - const foldersManager = shell.foldersManager as FoldersManager; + const shell = useAppShell() as any; + const foldersManager = shell.folderTree?.foldersManager as FoldersManager; const [remoteFolderTree, setRemoteFolderTree] = useState([]); diff --git a/frontend/src/documents/logic/useDocumentsPanelProps.ts b/frontend/src/documents/logic/useDocumentsPanelProps.ts index 5389fb6..2adf457 100644 --- a/frontend/src/documents/logic/useDocumentsPanelProps.ts +++ b/frontend/src/documents/logic/useDocumentsPanelProps.ts @@ -67,54 +67,73 @@ interface UseDocumentsPanelPropsArgs { const useDocumentsPanelProps = (props: UseDocumentsPanelPropsArgs) => { const { - currentFolderName, - breadcrumbs, - refreshCurrentFolder, - currentSubfolders, - documents, - searchQuery, - searchResultIds, - folderClickHandlers, - selectedFolder, - selectFolder, - handleFolderDragStart, - handleFolderDragEnd, - draggedFolderId, - handleFolderRename, - handleDocumentTitleUpdate, - focusedRowKey, - draggedDocumentIds, - handleDocumentDragStart, - handleDocumentDragEnd, - searchLoading, - tagLookupById, - activeTagFilters, - activeCorrespondentFilters, - ensureAssetUrl, - getDocumentAsset, - handleDocumentTagAttach, - handleDocumentTagDetach, - documentsViewMode, - documentsSortField, - documentsSortDirection, - handleDocumentsSortFieldChange, - handleDocumentsSortDirectionToggle, - handleDocumentsViewModeChange, - handleDeleteSelection, - handleEntryPointerCore, - tags, - correspondents, - correspondentLookupById, - documentLookup, - handleBulkTagAddFromDetail, - handleBulkTagRemoveFromDetail, - handleBulkCorrespondentAdd, - handleBulkCorrespondentRemove, - handleBulkSelectionReanalyze, - folderOptions, - moveDocumentsToFolder, - selectionValue, - } = props; + folderTree: { + currentFolderName, + breadcrumbs, + currentSubfolders, + folderClickHandlers, + selectedFolder, + selectFolder, + handleFolderDragStart, + handleFolderDragEnd, + draggedFolderId, + handleFolderRename, + folderOptions, + moveDocumentsToFolder, + } = {}, + search: { + documents, + searchQuery, + searchResultIds, + searchLoading, + documentsViewMode, + documentsSortField, + documentsSortDirection, + handleDocumentsSortFieldChange, + handleDocumentsSortDirectionToggle, + handleDocumentsViewModeChange, + } = {}, + ui: { + refreshCurrentFolder, + } = {}, + mutations: { + handleDocumentTitleUpdate, + draggedDocumentIds, + handleDocumentDragStart, + handleDocumentDragEnd, + } = {}, + selection: { + selectionValue, + handleDeleteSelection, + handleEntryPointerCore, + handleBulkSelectionReanalyze, + } = {}, + tags: { + tagLookupById, + activeTagFilters, + tags, + handleDocumentTagAttach, + handleDocumentTagDetach, + handleBulkTagAddFromDetail, + handleBulkTagRemoveFromDetail, + } = {}, + correspondents: { + activeCorrespondentFilters, + correspondents, + correspondentLookupById, + handleBulkCorrespondentAdd, + handleBulkCorrespondentRemove, + } = {}, + preview: { + ensureAssetUrl, + getDocumentAsset, + } = {}, + managers: { + documentLookup, + } = {}, + } = props as any; + + const focusedRowKey = selectionValue?.focusedEntryKey || null; return { currentFolderName, diff --git a/frontend/src/index.tsx b/frontend/src/index.tsx index 165eb52..40ed57a 100644 --- a/frontend/src/index.tsx +++ b/frontend/src/index.tsx @@ -63,8 +63,8 @@ const AppLayout: React.FC = () => { folderName={dropOverlayState.folderName} /> diff --git a/frontend/src/sidebar/Sidebar.tsx b/frontend/src/sidebar/Sidebar.tsx index e43e44e..07eeabf 100644 --- a/frontend/src/sidebar/Sidebar.tsx +++ b/frontend/src/sidebar/Sidebar.tsx @@ -9,21 +9,31 @@ import SidebarHeader from './components/SidebarHeader'; import SidebarSearch from './components/SidebarSearch'; const Sidebar: React.FC = () => { + const shell = useAppShell() as any; const { - sidebarSuppressed, openTagsModal, - openCorrespondentsModal, handleTagCreate, - handleCorrespondentCreate, - handleLogout, tags = [], + } = shell.tags || {}; + const { + openCorrespondentsModal, + handleCorrespondentCreate, correspondents = [], + } = shell.correspondents || {}; + const { + handleLogout, tenant, tenants, tenantOptions, handleTenantSelect, + } = shell.session || {}; + const { openSettings, + } = shell.ui || {}; + const { handleFileSelection, + } = shell.upload || {}; + const { folderClickHandlers = {}, handleFolderDelete, handleFolderRename, @@ -33,7 +43,9 @@ const Sidebar: React.FC = () => { draggedFolderId = null, handlePromptCreateFolder, creatingFolder = false, - } = useAppShell() as any; + } = shell.folderTree || {}; + + const sidebarSuppressed = shell.ui?.sidebarSuppressed; const onSelect = folderClickHandlers.onSelect; const onDrop = folderClickHandlers.onDrop; diff --git a/frontend/src/sidebar/components/SidebarFolderList.tsx b/frontend/src/sidebar/components/SidebarFolderList.tsx index 0c97a93..c690785 100644 --- a/frontend/src/sidebar/components/SidebarFolderList.tsx +++ b/frontend/src/sidebar/components/SidebarFolderList.tsx @@ -37,7 +37,8 @@ const SidebarFolderList: React.FC = ({ onCreateFolder, creatingFolder, }) => { - const { foldersManager } = useAppShell(); + const shell = useAppShell() as any; + const foldersManager = shell.folderTree?.foldersManager; const getTreeSnapshot = useCallback(() => { if (!foldersManager) return [];