diff --git a/frontend/src/documents/data/useDocumentsWorkspace.ts b/frontend/src/documents/data/useDocumentsWorkspace.ts index 637fb04..0a22f43 100644 --- a/frontend/src/documents/data/useDocumentsWorkspace.ts +++ b/frontend/src/documents/data/useDocumentsWorkspace.ts @@ -58,7 +58,7 @@ import { useApi } from '../../lib/context/ApiContext'; import { useWorkspaceSelection } from '../../app/useWorkspaceSelection'; import useDocumentPreview from '../../app/useDocumentPreview'; import type { DocumentId, FolderNodeId, Identifier } from '../../types/identifiers'; -import type { Document, Tag } from '../../types/documents'; +import type { Document } from '../../types/documents'; const EntryType = Object.freeze({ document: 'document', @@ -394,7 +394,6 @@ const useDocumentsWorkspace = ({ setActiveTagFilters, activeCorrespondentFilters, setActiveCorrespondentFilters, - isFilterActive, documentsFilterValue, } = useDocumentsSearch({ api: apiClient, @@ -484,57 +483,21 @@ const useDocumentsWorkspace = ({ selectionInitializedRef, }); - const tagsStateRaw = useTags({ + const tagsState = useTags({ tenantIdRef, tagManager, setActiveTagFilters, documentsManager, }); - useEffect(() => { - tagManager.ensureAll().catch((err) => console.warn('Failed to bootstrap tags', err)); - }, [tagManager]); - - const { - tags, - refreshTags, - handleTagCreate, - handleTagUpdate, - handleTagDelete, - } = tagsStateRaw; - - // tagLookupById is derived locally - useEffect(() => { - tenantIdRef.current = currentTenantId; - }, [currentTenantId, tenantIdRef]); - - const tagLookupById = new Map(); - tags.forEach((tag) => { - if (tag?.id) { - tagLookupById.set(tag.id, tag); - } - }); - - const tagsState = { - ...tagsStateRaw, - tags, - tagLookupById, - tagManager, - }; - - const correspondentsStateRaw = useCorrespondents({ + // Correspondents state + const correspondentsState = useCorrespondents({ correspondentManager, documentsManager, }); - const { - correspondents, - correspondentLookupById, - refreshCorrespondents, - handleCorrespondentCreate, - handleCorrespondentUpdate, - handleCorrespondentDelete, - } = correspondentsStateRaw; + const { refreshTags } = tagsState; + const { refreshCorrespondents } = correspondentsState; // Prefetch tags/correspondents when tenant changes useEffect(() => { @@ -542,16 +505,7 @@ const useDocumentsWorkspace = ({ refreshCorrespondents(); }, [refreshTags, refreshCorrespondents, currentTenantId]); - const { - passkeys, - passkeysSupported, - passkeysLoading, - registeringPasskey, - revokingPasskeyId, - refreshPasskeys, - registerPasskey, - revokePasskey, - } = usePasskeys({}); + const passkeys = usePasskeys({}); const resolveTargetDocumentIds = useCallback( (candidateIds) => { @@ -588,21 +542,14 @@ const useDocumentsWorkspace = ({ handleBulkTagRemoveFromDetail, handleBulkSelectionReanalyze, } = useDocumentTagActions({ - tags, + tags: tagsState.tags, tagManager, - refreshTags, + refreshTags: tagsState.refreshTags, resolveTargetDocumentIds, documentsManager, }); - const { - dropOverlayState, - handleFileDrop, - uploadQueue, - clearUploadQueue, - resetUploadsState, - handleFileSelection, - } = useDocumentUploads({ + const upload = useDocumentUploads({ selectedFolder, currentFolderName, refreshCurrentFolder: refreshFolderData, @@ -645,8 +592,8 @@ const useDocumentsWorkspace = ({ detailPanelControlRef.current.close(); assetManager.reset(); resetPreviewState(); - resetUploadsState(); - clearUploadQueue(); + upload.resetUploadsState(); + upload.clearUploadQueue(); detailFolderFetchRef.current = new Set(); bootstrapInitializedRef.current = false; @@ -671,8 +618,7 @@ const useDocumentsWorkspace = ({ setActiveCorrespondentFilters, setActivePreviewId, resetPreviewState, - resetUploadsState, - clearUploadQueue, + upload, ]); useEffect(() => { @@ -695,6 +641,22 @@ const useDocumentsWorkspace = ({ closeDocumentPreview, }; + const documentMutationsResult = useDocumentMutations({ + documentsState, + folderState, + selectionState, + tagsState: { + ...tagsState, + tagManager, + }, + correspondentsState: { + ...correspondentsState, + correspondentManager, + }, + actions: actionsState, + previewDocumentId, + }); + const { moveDocumentsToFolder, handleThumbnailRegeneration, @@ -708,20 +670,14 @@ const useDocumentsWorkspace = ({ handleDocumentCorrespondentDetach, handleDocumentCorrespondentAdd, correspondentLookupByName, - } = useDocumentMutations({ - documentsState, - folderState, - selectionState, - tagsState, - correspondentsState: { - correspondents, - correspondentLookupById, - refreshCorrespondents, - correspondentManager, - }, - actions: actionsState, - previewDocumentId, - }); + } = documentMutationsResult; + + const mutations = { + ...documentMutationsResult, + handleDocumentDragStart, + handleDocumentDragEnd, + draggedDocumentIds, + }; const dragState = { draggedDocumentIds, @@ -730,18 +686,11 @@ const useDocumentsWorkspace = ({ setDraggedFolderId, }; - const { - loadFolder, - selectFolder, - handleFolderRename, - handleFolderCreate, - handleFolderDelete, - folderClickHandlers, - } = useFolderTreeActions({ + const folderActions = useFolderTreeActions({ folderState, dragState, actions: { - handleFileDrop, + handleFileDrop: upload.handleFileDrop, moveDocumentsToFolder, }, utils: { @@ -750,8 +699,13 @@ const useDocumentsWorkspace = ({ }); const { - clearDocumentSelection, - } = useDocumentsSelection({ + loadFolder, + selectFolder, + handleFolderCreate, + handleFolderDelete, + } = folderActions; + + const selectionContext = useDocumentsSelection({ showingSearchResults, currentSubfolders: visibleSubfolders, visibleDocuments: viewDocuments, @@ -767,6 +721,7 @@ const useDocumentsWorkspace = ({ setFocusedEntryKey, focusedEntryKey, }); + const initializeAfterLogin = useCallback(async () => { await Promise.all([ refreshTags(), @@ -801,7 +756,6 @@ const useDocumentsWorkspace = ({ routeFolderId, routeDocumentId, selectedFolder, - isFilterActive, selectFolder, ]); @@ -849,12 +803,12 @@ const useDocumentsWorkspace = ({ } = useBulkDocumentActions({ resolveTargetDocumentIds, correspondentLookupByName, - handleCorrespondentCreate, + handleCorrespondentCreate: correspondentsState.handleCorrespondentCreate, selectedDocumentIds, selectedFolderIds, handleDocumentsDelete, handleFolderDelete, - clearDocumentSelection, + clearDocumentSelection: selectionContext.clearDocumentSelection, documentsManager, }); @@ -913,17 +867,17 @@ const useDocumentsWorkspace = ({ const { managementModals, openTagsModal, openCorrespondentsModal } = useManagementModals({ locationPathname: location.pathname, - tags, - refreshTags, - onTagCreate: handleTagCreate, - onTagUpdate: async (tagId: string, changes: any) => { await handleTagUpdate(tagId, changes); }, - onTagDelete: async (tagId: string) => { await handleTagDelete(tagId); }, - correspondents, - correspondentLookupById, - refreshCorrespondents, - onCorrespondentCreate: handleCorrespondentCreate, - onCorrespondentUpdate: handleCorrespondentUpdate, - onCorrespondentDelete: handleCorrespondentDelete, + tags: tagsState.tags, + refreshTags: tagsState.refreshTags, + onTagCreate: tagsState.handleTagCreate, + onTagUpdate: async (tagId: string, changes: any) => { await tagsState.handleTagUpdate(tagId, changes); }, + onTagDelete: async (tagId: string) => { await tagsState.handleTagDelete(tagId); }, + correspondents: correspondentsState.correspondents, + correspondentLookupById: correspondentsState.correspondentLookupById, + refreshCorrespondents: correspondentsState.refreshCorrespondents, + onCorrespondentCreate: correspondentsState.handleCorrespondentCreate, + onCorrespondentUpdate: correspondentsState.handleCorrespondentUpdate, + onCorrespondentDelete: correspondentsState.handleCorrespondentDelete, correspondentManager, }); @@ -971,13 +925,13 @@ const useDocumentsWorkspace = ({ handleDocumentTagDetach, ensureAssetUrl, getAsset: getDocumentAsset, - correspondents, + correspondents: correspondentsState.correspondents, handleCorrespondentAdd: handleDocumentCorrespondentAdd, handleCorrespondentRemove: handleDocumentCorrespondentDetach, selectFolder, - tags, - tagLookupById, - correspondentLookupById, + tags: tagsState.tags, + tagLookupById: tagsState.tagLookupById, + correspondentLookupById: correspondentsState.correspondentLookupById, }); const handleEntryPointerCore = useEntryPointerCore({ @@ -1009,7 +963,7 @@ const useDocumentsWorkspace = ({ handleDocumentsViewModeChange, }); - const sessionContext = { + const session = { token, appStatus, handleLogout, @@ -1019,7 +973,7 @@ const useDocumentsWorkspace = ({ handleTenantSelect, }; - const uiContext = { + const ui = { notifyApiError, settingsOpen, openSettings, @@ -1028,21 +982,11 @@ const useDocumentsWorkspace = ({ refreshCurrentFolder: handleManualRefresh, }; - const uploadContext = { - dropOverlayState, - uploadQueue, - clearUploadQueue, - handleFileSelection, - }; - - const tagsContext = { - tags, - refreshTags, - tagLookupById, + const tags = { + ...tagsState, + tagManager, activeTagFilters, - handleTagUpdate, - handleTagCreate, - handleTagDelete, + // Add derived/action handlers that were previously in tagsContext handleDocumentTagAttach, handleDocumentTagDetach, handleBulkTagAddFromDetail, @@ -1050,14 +994,10 @@ const useDocumentsWorkspace = ({ openTagsModal, }; - const correspondentsContext = { - correspondents, - correspondentLookupById, - refreshCorrespondents, + const correspondents = { + ...correspondentsState, activeCorrespondentFilters, - handleCorrespondentUpdate, - handleCorrespondentCreate, - handleCorrespondentDelete, + // Add derived/action handlers handleDocumentCorrespondentAttach, handleDocumentCorrespondentDetach, handleDocumentCorrespondentAdd, @@ -1066,18 +1006,7 @@ const useDocumentsWorkspace = ({ openCorrespondentsModal, }; - const passkeysContext = { - passkeys, - passkeysSupported, - passkeysLoading, - registeringPasskey, - revokingPasskeyId, - refreshPasskeys, - registerPasskey, - revokePasskey, - }; - - const previewContext = { + const preview = { previewActive, previewWorkspaceDocument, previewDocumentId, @@ -1087,13 +1016,13 @@ const useDocumentsWorkspace = ({ handleThumbnailRegeneration, }; - const detailPanelContext = { + const detailPanel = { detailPanelProps, detailPanelOpen, openDetailPanel, }; - const searchContext = { + const search = { searchQuery, documentsFilter, searchLoading, @@ -1107,18 +1036,18 @@ const useDocumentsWorkspace = ({ documents: viewDocuments, }; - const folderTreeContext = { + const folderTree = { foldersManager, selectedFolder, currentFolderName, folderOptions, handleBreadcrumbNavigate, resolveFolderPath, - selectFolder, + selectFolder: folderActions.selectFolder, moveDocumentsToFolder, - folderClickHandlers, - handleFolderRename, - handleFolderDelete, + folderClickHandlers: folderActions.folderClickHandlers, + handleFolderRename: folderActions.handleFolderRename, + handleFolderDelete: folderActions.handleFolderDelete, handleFolderDragStart, handleFolderDragEnd, draggedFolderId, @@ -1128,40 +1057,33 @@ const useDocumentsWorkspace = ({ breadcrumbs, }; - const selectionContext = { - clearDocumentSelection, + const selection = { + clearDocumentSelection: selectionContext.clearDocumentSelection, handleDeleteSelection, handleEntryPointerCore, handleBulkSelectionReanalyze, selectionValue: selectionState, }; - const documentMutations = { - handleDocumentTitleUpdate, - handleDocumentDragStart, - handleDocumentDragEnd, - draggedDocumentIds, - }; - const managers = { documentsManager, documentLookup, }; const contextValue = { - 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, + session, + ui, + upload, + tags, + correspondents, + passkeys, + preview, + detailPanel, + search, + folderTree, + selection, + mutations, + managers, }; // hook callers handle rendering / routing @@ -1169,7 +1091,7 @@ const useDocumentsWorkspace = ({ appStatus, location, shellRef, - dropOverlayState, + dropOverlayState: upload.dropOverlayState, managementModals, contextValue, settingsOpen, diff --git a/frontend/src/documents/data/useTags.ts b/frontend/src/documents/data/useTags.ts index 9181d69..97686e7 100644 --- a/frontend/src/documents/data/useTags.ts +++ b/frontend/src/documents/data/useTags.ts @@ -14,6 +14,7 @@ interface UseTagsOptions { interface UseTagsResult { tags: Tag[]; + tagLookupById: Map; refreshTags: () => Promise; handleTagUpdate: (tagId: TagId, changes: { label?: string; color?: string | null }) => Promise; handleTagCreate: (payload?: { label?: string; color?: string | null }) => Promise; @@ -130,6 +131,7 @@ const useTags = ({ return { tags, + tagLookupById: tagsSnapshot, refreshTags, handleTagUpdate, handleTagCreate,