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 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<SettingsRouteProps> = ({ open = true, onClose }) =
refreshPasskeys,
registerPasskey,
revokePasskey,
} = useAppShell() as Record<string, any>;
} = shell.passkeys || {};
const {
tokens,
+16 -16
View File
@@ -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]);
};
@@ -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
@@ -235,8 +235,8 @@ const SelectionFloatingActions: React.FC<SelectionFloatingActionsProps> = ({
), [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<FolderTreeNode[]>([]);
@@ -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,
+2 -2
View File
@@ -63,8 +63,8 @@ const AppLayout: React.FC = () => {
folderName={dropOverlayState.folderName}
/>
<UploadQueueOverlay
queue={contextValue.uploadQueue || []}
onClearQueue={contextValue.clearUploadQueue}
queue={contextValue.upload.uploadQueue || []}
onClearQueue={contextValue.upload.clearUploadQueue}
/>
<StatusToastOverlay />
<Outlet />
+17 -5
View File
@@ -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;
@@ -37,7 +37,8 @@ const SidebarFolderList: React.FC<SidebarFolderListProps> = ({
onCreateFolder,
creatingFolder,
}) => {
const { foldersManager } = useAppShell();
const shell = useAppShell() as any;
const foldersManager = shell.folderTree?.foldersManager;
const getTreeSnapshot = useCallback(() => {
if (!foldersManager) return [];