refactor: restructure useAppShell context into nested objects

This commit is contained in:
2025-12-10 01:48:46 +01:00
parent 82dcd6d33c
commit f0b58317b9
8 changed files with 123 additions and 93 deletions
+4 -4
View File
@@ -11,10 +11,10 @@ interface SettingsRouteProps {
} }
const SettingsRoute: React.FC<SettingsRouteProps> = ({ open = true, onClose }) => { const SettingsRoute: React.FC<SettingsRouteProps> = ({ open = true, onClose }) => {
const shell = useAppShell() as any;
const { token } = shell.session || {};
const { notifyApiError, setStatusMessage } = shell.ui || {};
const { const {
token,
notifyApiError,
setStatusMessage,
passkeys, passkeys,
passkeysSupported, passkeysSupported,
passkeysLoading, passkeysLoading,
@@ -23,7 +23,7 @@ const SettingsRoute: React.FC<SettingsRouteProps> = ({ open = true, onClose }) =
refreshPasskeys, refreshPasskeys,
registerPasskey, registerPasskey,
revokePasskey, revokePasskey,
} = useAppShell() as Record<string, any>; } = shell.passkeys || {};
const { const {
tokens, tokens,
+16 -16
View File
@@ -20,31 +20,31 @@ interface DocumentsShellView {
} }
const useDocumentsShell = (): DocumentsShellView => { const useDocumentsShell = (): DocumentsShellView => {
const shell = useAppShell(); const shell = useAppShell() as any;
const documentsPanelProps = useDocumentsPanelProps(shell as any); const documentsPanelProps = useDocumentsPanelProps(shell as any);
return useMemo(() => { return useMemo(() => {
const surfaceConfig: WorkspaceSurfaceConfig = { const surfaceConfig: WorkspaceSurfaceConfig = {
documentsTableProps: documentsPanelProps, documentsTableProps: documentsPanelProps,
detailPanelProps: (shell.detailPanelProps ?? null) as WorkspaceSurfaceConfig['detailPanelProps'], detailPanelProps: (shell.detailPanel?.detailPanelProps ?? null) as WorkspaceSurfaceConfig['detailPanelProps'],
detailPanelOpen: Boolean(shell.detailPanelOpen), detailPanelOpen: Boolean(shell.detailPanel?.detailPanelOpen),
openDetailPanel: shell.openDetailPanel as WorkspaceSurfaceConfig['openDetailPanel'], openDetailPanel: shell.detailPanel?.openDetailPanel as WorkspaceSurfaceConfig['openDetailPanel'],
closeDetailPanel: shell.closeDetailPanel as WorkspaceSurfaceConfig['closeDetailPanel'], closeDetailPanel: shell.detailPanel?.closeDetailPanel as WorkspaceSurfaceConfig['closeDetailPanel'],
previewWorkspaceDocument: shell.previewWorkspaceDocument, previewWorkspaceDocument: shell.preview?.previewWorkspaceDocument,
previewDocumentId: (shell.previewDocumentId as Identifier) ?? null, previewDocumentId: (shell.preview?.previewDocumentId as Identifier) ?? null,
closeDocumentPreview: shell.closeDocumentPreview as WorkspaceSurfaceConfig['closeDocumentPreview'], closeDocumentPreview: shell.preview?.closeDocumentPreview as WorkspaceSurfaceConfig['closeDocumentPreview'],
ensurePreviewData: shell.ensurePreviewData as WorkspaceSurfaceConfig['ensurePreviewData'], ensurePreviewData: shell.preview?.ensurePreviewData as WorkspaceSurfaceConfig['ensurePreviewData'],
ensureAssetUrl: shell.ensureAssetUrl as WorkspaceSurfaceConfig['ensureAssetUrl'], ensureAssetUrl: shell.preview?.ensureAssetUrl as WorkspaceSurfaceConfig['ensureAssetUrl'],
getDocumentAsset: shell.getDocumentAsset as WorkspaceSurfaceConfig['getDocumentAsset'], getDocumentAsset: shell.preview?.getDocumentAsset as WorkspaceSurfaceConfig['getDocumentAsset'],
notifyApiError: shell.notifyApiError as WorkspaceSurfaceConfig['notifyApiError'], notifyApiError: shell.ui?.notifyApiError as WorkspaceSurfaceConfig['notifyApiError'],
handleBreadcrumbNavigate: shell.handleBreadcrumbNavigate as WorkspaceSurfaceConfig['handleBreadcrumbNavigate'], handleBreadcrumbNavigate: shell.folderTree?.handleBreadcrumbNavigate as WorkspaceSurfaceConfig['handleBreadcrumbNavigate'],
}; };
return { return {
surfaceConfig, surfaceConfig,
documentsFilter: shell.documentsFilter as DocumentsFilterValue, documentsFilter: shell.search?.documentsFilter as DocumentsFilterValue,
documentsManager: shell.documentsManager, documentsManager: shell.managers?.documentsManager,
foldersManager: shell.foldersManager, foldersManager: shell.folderTree?.foldersManager,
}; };
}, [shell, documentsPanelProps]); }, [shell, documentsPanelProps]);
}; };
@@ -949,8 +949,6 @@ const useDocumentsWorkspace = ({
return () => window.removeEventListener('keydown', handleKeyDown); return () => window.removeEventListener('keydown', handleKeyDown);
}, [settingsOpen]); }, [settingsOpen]);
const { const {
detailPanelProps, detailPanelProps,
detailPanelOpen, detailPanelOpen,
@@ -1151,19 +1149,19 @@ const useDocumentsWorkspace = ({
}; };
const contextValue = { const contextValue = {
...sessionContext, session: sessionContext,
...uiContext, ui: uiContext,
...uploadContext, upload: uploadContext,
...tagsContext, tags: tagsContext,
...correspondentsContext, correspondents: correspondentsContext,
...passkeysContext, passkeys: passkeysContext,
...previewContext, preview: previewContext,
...detailPanelContext, detailPanel: detailPanelContext,
...searchContext, search: searchContext,
...folderTreeContext, folderTree: folderTreeContext,
...selectionContext, selection: selectionContext,
...documentMutations, mutations: documentMutations,
...managers, managers: managers,
}; };
// hook callers handle rendering / routing // hook callers handle rendering / routing
@@ -235,8 +235,8 @@ const SelectionFloatingActions: React.FC<SelectionFloatingActionsProps> = ({
), [documentLookup]); ), [documentLookup]);
const tagLookupMap = tagLookupById instanceof Map ? tagLookupById : null; const tagLookupMap = tagLookupById instanceof Map ? tagLookupById : null;
const shell = useAppShell(); const shell = useAppShell() as any;
const foldersManager = shell.foldersManager as FoldersManager; const foldersManager = shell.folderTree?.foldersManager as FoldersManager;
const [remoteFolderTree, setRemoteFolderTree] = useState<FolderTreeNode[]>([]); const [remoteFolderTree, setRemoteFolderTree] = useState<FolderTreeNode[]>([]);
@@ -67,54 +67,73 @@ interface UseDocumentsPanelPropsArgs {
const useDocumentsPanelProps = (props: UseDocumentsPanelPropsArgs) => { const useDocumentsPanelProps = (props: UseDocumentsPanelPropsArgs) => {
const { const {
currentFolderName, folderTree: {
breadcrumbs, currentFolderName,
refreshCurrentFolder, breadcrumbs,
currentSubfolders, currentSubfolders,
documents, folderClickHandlers,
searchQuery, selectedFolder,
searchResultIds, selectFolder,
folderClickHandlers, handleFolderDragStart,
selectedFolder, handleFolderDragEnd,
selectFolder, draggedFolderId,
handleFolderDragStart, handleFolderRename,
handleFolderDragEnd, folderOptions,
draggedFolderId, moveDocumentsToFolder,
handleFolderRename, } = {},
handleDocumentTitleUpdate, search: {
focusedRowKey, documents,
draggedDocumentIds, searchQuery,
handleDocumentDragStart, searchResultIds,
handleDocumentDragEnd, searchLoading,
searchLoading, documentsViewMode,
tagLookupById, documentsSortField,
activeTagFilters, documentsSortDirection,
activeCorrespondentFilters, handleDocumentsSortFieldChange,
ensureAssetUrl, handleDocumentsSortDirectionToggle,
getDocumentAsset, handleDocumentsViewModeChange,
handleDocumentTagAttach, } = {},
handleDocumentTagDetach, ui: {
documentsViewMode, refreshCurrentFolder,
documentsSortField, } = {},
documentsSortDirection, mutations: {
handleDocumentsSortFieldChange, handleDocumentTitleUpdate,
handleDocumentsSortDirectionToggle, draggedDocumentIds,
handleDocumentsViewModeChange, handleDocumentDragStart,
handleDeleteSelection, handleDocumentDragEnd,
handleEntryPointerCore, } = {},
tags, selection: {
correspondents, selectionValue,
correspondentLookupById, handleDeleteSelection,
documentLookup, handleEntryPointerCore,
handleBulkTagAddFromDetail, handleBulkSelectionReanalyze,
handleBulkTagRemoveFromDetail, } = {},
handleBulkCorrespondentAdd, tags: {
handleBulkCorrespondentRemove, tagLookupById,
handleBulkSelectionReanalyze, activeTagFilters,
folderOptions, tags,
moveDocumentsToFolder, handleDocumentTagAttach,
selectionValue, handleDocumentTagDetach,
} = props; handleBulkTagAddFromDetail,
handleBulkTagRemoveFromDetail,
} = {},
correspondents: {
activeCorrespondentFilters,
correspondents,
correspondentLookupById,
handleBulkCorrespondentAdd,
handleBulkCorrespondentRemove,
} = {},
preview: {
ensureAssetUrl,
getDocumentAsset,
} = {},
managers: {
documentLookup,
} = {},
} = props as any;
const focusedRowKey = selectionValue?.focusedEntryKey || null;
return { return {
currentFolderName, currentFolderName,
+2 -2
View File
@@ -63,8 +63,8 @@ const AppLayout: React.FC = () => {
folderName={dropOverlayState.folderName} folderName={dropOverlayState.folderName}
/> />
<UploadQueueOverlay <UploadQueueOverlay
queue={contextValue.uploadQueue || []} queue={contextValue.upload.uploadQueue || []}
onClearQueue={contextValue.clearUploadQueue} onClearQueue={contextValue.upload.clearUploadQueue}
/> />
<StatusToastOverlay /> <StatusToastOverlay />
<Outlet /> <Outlet />
+17 -5
View File
@@ -9,21 +9,31 @@ import SidebarHeader from './components/SidebarHeader';
import SidebarSearch from './components/SidebarSearch'; import SidebarSearch from './components/SidebarSearch';
const Sidebar: React.FC = () => { const Sidebar: React.FC = () => {
const shell = useAppShell() as any;
const { const {
sidebarSuppressed,
openTagsModal, openTagsModal,
openCorrespondentsModal,
handleTagCreate, handleTagCreate,
handleCorrespondentCreate,
handleLogout,
tags = [], tags = [],
} = shell.tags || {};
const {
openCorrespondentsModal,
handleCorrespondentCreate,
correspondents = [], correspondents = [],
} = shell.correspondents || {};
const {
handleLogout,
tenant, tenant,
tenants, tenants,
tenantOptions, tenantOptions,
handleTenantSelect, handleTenantSelect,
} = shell.session || {};
const {
openSettings, openSettings,
} = shell.ui || {};
const {
handleFileSelection, handleFileSelection,
} = shell.upload || {};
const {
folderClickHandlers = {}, folderClickHandlers = {},
handleFolderDelete, handleFolderDelete,
handleFolderRename, handleFolderRename,
@@ -33,7 +43,9 @@ const Sidebar: React.FC = () => {
draggedFolderId = null, draggedFolderId = null,
handlePromptCreateFolder, handlePromptCreateFolder,
creatingFolder = false, creatingFolder = false,
} = useAppShell() as any; } = shell.folderTree || {};
const sidebarSuppressed = shell.ui?.sidebarSuppressed;
const onSelect = folderClickHandlers.onSelect; const onSelect = folderClickHandlers.onSelect;
const onDrop = folderClickHandlers.onDrop; const onDrop = folderClickHandlers.onDrop;
@@ -37,7 +37,8 @@ const SidebarFolderList: React.FC<SidebarFolderListProps> = ({
onCreateFolder, onCreateFolder,
creatingFolder, creatingFolder,
}) => { }) => {
const { foldersManager } = useAppShell(); const shell = useAppShell() as any;
const foldersManager = shell.folderTree?.foldersManager;
const getTreeSnapshot = useCallback(() => { const getTreeSnapshot = useCallback(() => {
if (!foldersManager) return []; if (!foldersManager) return [];