diff --git a/frontend/src/app/DocumentsRoute.tsx b/frontend/src/app/DocumentsRoute.tsx index 34b7d8b..87ec466 100644 --- a/frontend/src/app/DocumentsRoute.tsx +++ b/frontend/src/app/DocumentsRoute.tsx @@ -4,7 +4,7 @@ import { useNavigate } from 'react-router-dom'; import { DocumentsFilterProvider, } from '../documents/context/DocumentsFilterContext'; -import { PreviewProvider, usePreviewContext } from '../viewer/PreviewContext'; +import { FullscreenPreviewProvider, useFullscreenPreviewContext } from '../viewer/FullscreenPreviewContext'; import { DocumentOpenProvider } from '../lib/context/DocumentOpenContext'; import { useWorkspaceSurface } from './useWorkspaceSurface'; import { SidebarProvider, useSidebarContext } from '../sidebar/SidebarContext'; @@ -16,7 +16,7 @@ const DocumentsInner: React.FC<{ surfaceConfig: any; onNavigate: (documentId: string) => void; }> = ({ surfaceConfig, onNavigate }) => { - const { openPreview } = usePreviewContext(); + const { openFullscreenPreview } = useFullscreenPreviewContext(); const { collapsed: sidebarCollapsed } = useSidebarContext(); const { sidebarSuppressed, @@ -68,7 +68,7 @@ const DocumentsInner: React.FC<{ return ( {renderSurface()} @@ -89,14 +89,14 @@ const DocumentsRouteContent: React.FC = () => { return ( - - + ); }; diff --git a/frontend/src/app/useDocumentPreview.ts b/frontend/src/app/useDocumentViewer.ts similarity index 62% rename from frontend/src/app/useDocumentPreview.ts rename to frontend/src/app/useDocumentViewer.ts index 98f1307..344cc20 100644 --- a/frontend/src/app/useDocumentPreview.ts +++ b/frontend/src/app/useDocumentViewer.ts @@ -12,7 +12,7 @@ type FolderId = DocumentId | 'root'; import type { Document } from '../types/documents'; import useNotifyApiError from '../hooks/useNotifyApiError'; -interface UseDocumentPreviewArgs { +interface UseDocumentViewerArgs { routeDocumentId?: DocumentId | null; documentsManager: { getById: (id: DocumentId) => Document | null; @@ -28,36 +28,36 @@ interface UseDocumentPreviewArgs { open?: (args?: { documentIds?: DocumentId[] }) => void; close?: () => void; } | null>; - setActivePreviewId: Dispatch>; + setActiveViewerId: Dispatch>; } -interface UseDocumentPreviewResult { - ensurePreviewData: (documentId: DocumentId) => Promise; - openDocumentPreview: (documentId: DocumentId, options?: { replace?: boolean }) => void; - closeDocumentPreview: (folderId?: FolderId) => void; - resetPreviewState: () => void; - previewWorkspaceDocument: Document | null; - previewActive: boolean; +interface UseDocumentViewerResult { + ensureViewerData: (documentId: DocumentId) => Promise; + openDocumentViewer: (documentId: DocumentId, options?: { replace?: boolean }) => void; + closeDocumentViewer: (folderId?: FolderId) => void; + resetViewerState: () => void; + viewerWorkspaceDocument: Document | null; + viewerActive: boolean; } -const useDocumentPreview = ({ +const useDocumentViewer = ({ routeDocumentId, documentsManager, selectedFolder, locationPathname, locationSearch, detailPanelControlRef, - setActivePreviewId, -}: UseDocumentPreviewArgs): UseDocumentPreviewResult => { - const previewReturnPathRef = useRef(null); + setActiveViewerId, +}: UseDocumentViewerArgs): UseDocumentViewerResult => { + const viewerReturnPathRef = useRef(null); const notifyApiError = useNotifyApiError(); const navigate = useNavigate(); - const resetPreviewState = useCallback(() => { - previewReturnPathRef.current = null; + const resetViewerState = useCallback(() => { + viewerReturnPathRef.current = null; }, []); - const ensurePreviewData = useCallback( + const ensureViewerData = useCallback( async (documentId: DocumentId): Promise => { if (!documentId) return null; @@ -67,35 +67,35 @@ const useDocumentPreview = ({ throw new Error('Document metadata unavailable.'); } - if (!previewReturnPathRef.current) { + if (!viewerReturnPathRef.current) { const fallbackFolderId = doc?.folder_id || 'root'; - previewReturnPathRef.current = + viewerReturnPathRef.current = fallbackFolderId === 'root' ? '/documents' : `/documents/folder/${fallbackFolderId}`; } - setActivePreviewId(documentId); + setActiveViewerId(documentId); return doc; }, [ documentsManager, - setActivePreviewId, + setActiveViewerId, ], ); - const openDocumentPreview = useCallback( + const openDocumentViewer = useCallback( (documentId: DocumentId, { replace = false }: { replace?: boolean } = {}) => { if (!documentId) return; detailPanelControlRef.current?.close?.(); - previewReturnPathRef.current = `${locationPathname}${locationSearch}`; + viewerReturnPathRef.current = `${locationPathname}${locationSearch}`; navigate(`/documents/${documentId}`, { replace }); }, [navigate, locationPathname, locationSearch, detailPanelControlRef], ); - const closeDocumentPreview = useCallback( + const closeDocumentViewer = useCallback( (folderId?: FolderId) => { - const fallbackPath = previewReturnPathRef.current; - previewReturnPathRef.current = null; + const fallbackPath = viewerReturnPathRef.current; + viewerReturnPathRef.current = null; if (fallbackPath) { navigate(fallbackPath, { replace: false }); @@ -116,36 +116,36 @@ const useDocumentPreview = ({ let cancelled = false; - ensurePreviewData(routeDocumentId).catch((error) => { + ensureViewerData(routeDocumentId).catch((error) => { if (cancelled) { return; } notifyApiError(error, 'Failed to open document preview.'); - closeDocumentPreview(); + closeDocumentViewer(); }); return () => { cancelled = true; }; - }, [routeDocumentId, ensurePreviewData, notifyApiError, closeDocumentPreview]); + }, [routeDocumentId, ensureViewerData, notifyApiError, closeDocumentViewer]); - const previewWorkspaceDocument = useMemo(() => { + const viewerWorkspaceDocument = useMemo(() => { if (!routeDocumentId) { return null; } return documentsManager.getById(routeDocumentId); }, [routeDocumentId, documentsManager]); - const previewActive = Boolean(routeDocumentId && previewWorkspaceDocument); + const viewerActive = Boolean(routeDocumentId && viewerWorkspaceDocument); return { - ensurePreviewData, - openDocumentPreview, - closeDocumentPreview, - resetPreviewState, - previewWorkspaceDocument, - previewActive, + ensureViewerData, + openDocumentViewer, + closeDocumentViewer, + resetViewerState, + viewerWorkspaceDocument, + viewerActive, }; }; -export default useDocumentPreview; +export default useDocumentViewer; diff --git a/frontend/src/app/useDocumentsShell.ts b/frontend/src/app/useDocumentsShell.ts index e8dedd1..743f36e 100644 --- a/frontend/src/app/useDocumentsShell.ts +++ b/frontend/src/app/useDocumentsShell.ts @@ -30,10 +30,10 @@ const useDocumentsShell = (): DocumentsShellView => { 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'], + viewerWorkspaceDocument: shell.preview?.viewerWorkspaceDocument, + viewerDocumentId: (shell.preview?.viewerDocumentId as Identifier) ?? null, + closeDocumentViewer: shell.preview?.closeDocumentViewer as WorkspaceSurfaceConfig['closeDocumentViewer'], + ensureViewerData: shell.preview?.ensureViewerData as WorkspaceSurfaceConfig['ensureViewerData'], ensureAssetUrl: shell.preview?.ensureAssetUrl as WorkspaceSurfaceConfig['ensureAssetUrl'], getDocumentAsset: shell.preview?.getDocumentAsset as WorkspaceSurfaceConfig['getDocumentAsset'], notifyApiError: shell.ui?.notifyApiError as WorkspaceSurfaceConfig['notifyApiError'], diff --git a/frontend/src/app/useWorkspaceSurface.tsx b/frontend/src/app/useWorkspaceSurface.tsx index c87e0a6..e4e8747 100644 --- a/frontend/src/app/useWorkspaceSurface.tsx +++ b/frontend/src/app/useWorkspaceSurface.tsx @@ -12,14 +12,14 @@ type EnsureAssetUrl = ( asset: unknown, options?: Record, ) => Promise | void; -type EnsurePreviewData = (docId: Identifier, options?: Record) => Promise; +type EnsureViewerData = (docId: Identifier, options?: Record) => Promise; type GetDocumentAsset = (document: unknown, assetType: string) => unknown; type NotifyApiError = (error: unknown, fallbackMessage?: string) => void; type DocumentsTableProps = ComponentProps | null; type DetailPanelProps = (ComponentProps & { onClose?: () => void; - onOpenPreview?: (args: { documentIds: Array }) => void; + onOpenViewer?: (args: { documentIds: Array }) => void; folderNodes?: Map; ensureFolderData?: ( folderId: Identifier | 'root', @@ -35,13 +35,13 @@ export interface UseWorkspaceSurfaceArgs { documentsTableProps?: DocumentsTableProps; detailPanelProps?: DetailPanelProps; detailPanelOpen?: boolean; - previewWorkspaceDocument?: unknown; - previewDocumentId?: Identifier | null; + viewerWorkspaceDocument?: unknown; + viewerDocumentId?: Identifier | null; ensureAssetUrl?: EnsureAssetUrl; - ensurePreviewData?: EnsurePreviewData; + ensureViewerData?: EnsureViewerData; getDocumentAsset?: GetDocumentAsset; notifyApiError?: NotifyApiError; - closeDocumentPreview?: () => void; + closeDocumentViewer?: () => void; } interface UseWorkspaceSurfaceResult { @@ -54,13 +54,13 @@ export const useWorkspaceSurface = ({ documentsTableProps, detailPanelProps, detailPanelOpen = false, - previewWorkspaceDocument, - previewDocumentId, + viewerWorkspaceDocument, + viewerDocumentId, ensureAssetUrl, - ensurePreviewData, + ensureViewerData, getDocumentAsset, notifyApiError, - closeDocumentPreview, + closeDocumentViewer, }: UseWorkspaceSurfaceArgs): UseWorkspaceSurfaceResult => { const { registerDetailCloseHandler, setDetailActive } = usePanelManager(); @@ -118,7 +118,7 @@ export const useWorkspaceSurface = ({ ? (() => { const { onClose, - onOpenPreview, + onOpenViewer, tags: tagOptions, folderNodes, ensureFolderData, @@ -129,7 +129,7 @@ export const useWorkspaceSurface = ({ variant="sidebar" sidebarMode={sidebarMode} onClose={onClose} - onMaximize={onOpenPreview} + onMaximize={onOpenViewer} tagOptions={tagOptions} {...restDetailProps} /> @@ -164,10 +164,10 @@ export const useWorkspaceSurface = ({ detailPanelProps, ]); - const showPreviewWorkspace = Boolean(previewDocumentId); + const showViewerWorkspace = Boolean(viewerDocumentId); - const previewSurface = useMemo(() => { - if (!showPreviewWorkspace) { + const viewerSurface = useMemo(() => { + if (!showViewerWorkspace) { return null; } @@ -191,8 +191,8 @@ export const useWorkspaceSurface = ({ const viewer = ( ); @@ -223,23 +223,23 @@ export const useWorkspaceSurface = ({ return { content, detail: null, detailMode: null }; }, [ - showPreviewWorkspace, - previewWorkspaceDocument, - ensurePreviewData, + showViewerWorkspace, + viewerWorkspaceDocument, + ensureViewerData, ensureAssetUrl, getDocumentAsset, notifyApiError, renderSidebarToggle, - closeDocumentPreview, + closeDocumentViewer, detailPanelProps, ]); const surface = useMemo(() => { - if (showPreviewWorkspace) { - return previewSurface; + if (showViewerWorkspace) { + return viewerSurface; } return documentsSurface; - }, [showPreviewWorkspace, previewSurface, documentsSurface]); + }, [showViewerWorkspace, viewerSurface, documentsSurface]); return { surface }; }; diff --git a/frontend/src/documents/data/useDocumentMutations.ts b/frontend/src/documents/data/useDocumentMutations.ts index 2038cc5..7ed1fe4 100644 --- a/frontend/src/documents/data/useDocumentMutations.ts +++ b/frontend/src/documents/data/useDocumentMutations.ts @@ -57,8 +57,8 @@ interface UseDocumentMutationsArgs { selectionState: SelectionState; tagsState: TagsState; correspondentsState: CorrespondentsState; - closeDocumentPreview: () => void; - previewDocumentId?: DocumentId | null; + closeDocumentViewer: () => void; + viewerDocumentId?: DocumentId | null; resolveTargetDocumentIds: (ids?: Identifier[] | null) => Identifier[]; } @@ -103,8 +103,8 @@ const useDocumentMutations = ({ selectionState, tagsState, correspondentsState, - closeDocumentPreview, - previewDocumentId, + closeDocumentViewer, + viewerDocumentId, resolveTargetDocumentIds, }: UseDocumentMutationsArgs): UseDocumentMutationsResult => { const { showToast } = useStatusToast(); @@ -140,14 +140,14 @@ const useDocumentMutations = ({ await queueDocumentReanalysis(documentId); showToast('Analysis queued.', 'info'); // Close preview if it's the current one to allow refresh? - if (previewDocumentId === documentId) { - closeDocumentPreview(); + if (viewerDocumentId === documentId) { + closeDocumentViewer(); } } catch (error) { notifyApiError(error, 'Failed to queue analysis.'); } }, - [closeDocumentPreview, notifyApiError, previewDocumentId, showToast], + [closeDocumentViewer, notifyApiError, viewerDocumentId, showToast], ); const handleDocumentsDelete = useCallback( diff --git a/frontend/src/documents/data/useDocumentsWorkspace.ts b/frontend/src/documents/data/useDocumentsWorkspace.ts index 9095387..3065f4f 100644 --- a/frontend/src/documents/data/useDocumentsWorkspace.ts +++ b/frontend/src/documents/data/useDocumentsWorkspace.ts @@ -55,7 +55,7 @@ import { useAppDispatch, useAppState } from '../../lib/store/appState'; import { listFolderContents } from '../../lib/api/apiClient'; import { useApi } from '../../lib/context/ApiContext'; import { useWorkspaceSelection } from '../../app/useWorkspaceSelection'; -import useDocumentPreview from '../../app/useDocumentPreview'; +import useDocumentViewer from '../../app/useDocumentViewer'; import type { DocumentId, FolderNodeId, Identifier } from '../../types/identifiers'; import type { Document } from '../../types/documents'; @@ -117,7 +117,7 @@ const useDocumentsWorkspace = ({ const docMatch = matchPath('/documents/:documentId', location.pathname); const routeFolderId = folderMatch?.params?.folderId || null; const routeDocumentId = docMatch?.params?.documentId || null; - const previewDocumentId = routeDocumentId; + const viewerDocumentId = routeDocumentId; const handleBreadcrumbNavigate = useCallback((crumb: { id?: Identifier | string } | null) => { if (!crumb || !crumb.id) { @@ -157,7 +157,7 @@ const useDocumentsWorkspace = ({ const [draggedDocumentIds, setDraggedDocumentIds] = useState([]); const [draggedFolderId, setDraggedFolderId] = useState(null); - const [activePreviewId, setActivePreviewId] = useState(routeDocumentId || null); + const [activeViewerId, setActiveViewerId] = useState(routeDocumentId || null); const shellRef = useRef(null); const assetManagerRef = useRef(null); if (!assetManagerRef.current) { @@ -402,7 +402,7 @@ const useDocumentsWorkspace = ({ documentsManager, }); - const documentsFilter = documentsSearch.documentsFilterValue; + const showingSearchResults = documentsSearch.searchResultIds !== null; // Live Filter: Ensure we only show documents that actually belong to the current folder. @@ -432,30 +432,30 @@ const useDocumentsWorkspace = ({ }); const { - openDocumentPreview, - closeDocumentPreview, - resetPreviewState, - previewWorkspaceDocument, - previewActive, - } = useDocumentPreview({ - routeDocumentId: previewDocumentId, + openDocumentViewer, + closeDocumentViewer, + resetViewerState, + viewerWorkspaceDocument, + viewerActive, + } = useDocumentViewer({ + routeDocumentId: viewerDocumentId, documentsManager, selectedFolder, locationPathname: location.pathname, locationSearch: location.search, detailPanelControlRef, - setActivePreviewId, + setActiveViewerId, }); - const openDocumentPreviewForDetail = useCallback( + const openDocumentViewerForDetail = useCallback( ({ documentIds }: { documentIds?: Identifier[] } = {}) => { const targetId = documentIds?.find((value): value is Identifier => value != null); if (targetId == null) { return; } - openDocumentPreview(targetId, { replace: true }); + openDocumentViewer(targetId, { replace: true }); }, - [openDocumentPreview], + [openDocumentViewer], ); const getDocumentAsset = useCallback((doc, type) => { @@ -475,8 +475,8 @@ const useDocumentsWorkspace = ({ selectionAnchorRef, setFocusedDocumentId, selectedDocumentIds, - activePreviewId, - setActivePreviewId, + activeViewerId, + setActiveViewerId, selectionInitializedRef, }); @@ -573,10 +573,10 @@ const useDocumentsWorkspace = ({ documentsSearch.setSearchQuery(''); documentsSearch.setActiveTagFilters([]); documentsSearch.setActiveCorrespondentFilters([]); - setActivePreviewId(null); + setActiveViewerId(null); detailPanelControlRef.current.close(); assetManager.reset(); - resetPreviewState(); + resetViewerState(); upload.resetUploadsState(); upload.clearUploadQueue(); @@ -598,8 +598,8 @@ const useDocumentsWorkspace = ({ setDraggedDocumentIds, setDraggedFolderId, documentsSearch, - setActivePreviewId, - resetPreviewState, + setActiveViewerId, + resetViewerState, upload, ]); @@ -631,8 +631,8 @@ const useDocumentsWorkspace = ({ ...correspondentsState, correspondentManager, }, - closeDocumentPreview, - previewDocumentId, + closeDocumentViewer, + viewerDocumentId, resolveTargetDocumentIds, }); @@ -693,7 +693,7 @@ const useDocumentsWorkspace = ({ selectionAnchorRef, promoteSelectionOrderRaw, setFocusedDocumentId, - setActivePreviewId, + setActiveViewerId, clearSelection, focusedDocumentId, setFocusedEntryKey, @@ -884,12 +884,12 @@ const useDocumentsWorkspace = ({ return () => window.removeEventListener('keydown', handleKeyDown); }, [settingsOpen]); - const detailPanel = useDetailWorkspace({ + const detailWorkspace = useDetailWorkspace({ documentLookup, folderNodes, detailPanelControlRef, detailFolderFetchRef, - openDocumentPreview: openDocumentPreviewForDetail, + openDocumentViewer: openDocumentViewerForDetail, handleDocumentTitleUpdate, handleDocumentIssuedUpdate, handleDocumentTagAdd, @@ -906,6 +906,8 @@ const useDocumentsWorkspace = ({ resolveFolderPath, }); + + const handleEntryPointerCore = useEntryPointerCore({ onSelectEntry: (entry, event, { rowKey, modifierClick, primaryClick }) => { const { type, id } = entry; @@ -979,17 +981,18 @@ const useDocumentsWorkspace = ({ }; const preview = { - previewActive, - previewWorkspaceDocument, - previewDocumentId, - closeDocumentPreview, + openDocumentViewerForDetail, + viewerActive, + viewerWorkspaceDocument, + viewerDocumentId, + closeDocumentViewer, + selectionContext, ensureAssetUrl, getDocumentAsset, }; const search = { searchQuery: documentsSearch.searchQuery, - documentsFilter, searchLoading: documentsSearch.searchLoading, documentsViewMode, handleDocumentsViewModeChange, @@ -999,6 +1002,7 @@ const useDocumentsWorkspace = ({ handleDocumentsSortDirectionToggle, searchResultIds: documentsSearch.searchResultIds, documents: viewDocuments, + documentsFilter: documentsSearch.documentsFilterValue, }; const folderTree = { @@ -1043,7 +1047,7 @@ const useDocumentsWorkspace = ({ correspondents, passkeys, preview, - detailPanel, + detailPanel: detailWorkspace, search, folderTree, selection, diff --git a/frontend/src/documents/features/selection/useDocumentsSelection.ts b/frontend/src/documents/features/selection/useDocumentsSelection.ts index 44f66cf..26af9f5 100644 --- a/frontend/src/documents/features/selection/useDocumentsSelection.ts +++ b/frontend/src/documents/features/selection/useDocumentsSelection.ts @@ -29,7 +29,7 @@ interface UseDocumentsSelectionOptions { selectionAnchorRef: { current: string | null }; promoteSelectionOrderRaw: (id: DocumentId) => void; setFocusedDocumentId: (id: DocumentId | null) => void; - setActivePreviewId: (id: DocumentId | null) => void; + setActiveViewerId: (id: DocumentId | null) => void; clearSelection: () => void; focusedDocumentId: DocumentId | null; setFocusedEntryKey: Dispatch>; @@ -46,7 +46,7 @@ const useDocumentsSelection = ({ selectionAnchorRef, promoteSelectionOrderRaw, setFocusedDocumentId, - setActivePreviewId, + setActiveViewerId, clearSelection, focusedDocumentId, setFocusedEntryKey, @@ -92,9 +92,9 @@ const useDocumentsSelection = ({ selectionAnchorRef.current = rowKey; } setFocusedDocumentId(docId); - setActivePreviewId(docId); + setActiveViewerId(docId); }, - [promoteSelectionOrderRaw, selectionAnchorRef, setFocusedDocumentId, setActivePreviewId], + [promoteSelectionOrderRaw, selectionAnchorRef, setFocusedDocumentId, setActiveViewerId], ); const clearDocumentSelection = useCallback(() => { diff --git a/frontend/src/documents/features/selection/useWorkspaceSelectionSync.ts b/frontend/src/documents/features/selection/useWorkspaceSelectionSync.ts index e67f5b5..5be3051 100644 --- a/frontend/src/documents/features/selection/useWorkspaceSelectionSync.ts +++ b/frontend/src/documents/features/selection/useWorkspaceSelectionSync.ts @@ -11,8 +11,8 @@ interface UseWorkspaceSelectionSyncArgs { selectionAnchorRef: MutableRefObject; setFocusedDocumentId: (id: Identifier | null) => void; selectedDocumentIds: Identifier[]; - activePreviewId: Identifier | null; - setActivePreviewId: (id: Identifier | null) => void; + activeViewerId: Identifier | null; + setActiveViewerId: (id: Identifier | null) => void; selectionInitializedRef: MutableRefObject; } @@ -25,8 +25,8 @@ const useWorkspaceSelectionSync = ({ selectionAnchorRef, setFocusedDocumentId, selectedDocumentIds, - activePreviewId, - setActivePreviewId, + activeViewerId, + setActiveViewerId, selectionInitializedRef, }: UseWorkspaceSelectionSyncArgs) => { useEffect(() => { @@ -52,11 +52,11 @@ const useWorkspaceSelectionSync = ({ if (!selectedDocumentIds.length) { return; } - if (!selectedDocumentIds.includes(activePreviewId as Identifier)) { - setActivePreviewId(selectedDocumentIds[selectedDocumentIds.length - 1]); + if (!selectedDocumentIds.includes(activeViewerId as Identifier)) { + setActiveViewerId(selectedDocumentIds[selectedDocumentIds.length - 1]); } selectionInitializedRef.current = true; - }, [selectedDocumentIds, activePreviewId, selectionInitializedRef, setActivePreviewId]); + }, [selectedDocumentIds, activeViewerId, selectionInitializedRef, setActiveViewerId]); }; export default useWorkspaceSelectionSync; diff --git a/frontend/src/lib/context/DocumentOpenContext.tsx b/frontend/src/lib/context/DocumentOpenContext.tsx index ba187b5..20670ac 100644 --- a/frontend/src/lib/context/DocumentOpenContext.tsx +++ b/frontend/src/lib/context/DocumentOpenContext.tsx @@ -14,14 +14,14 @@ const [DocumentOpenContext, useDocumentOpen] = createSafeContext void; - onOpenPreview?: (doc: Document) => void; + onOpenFullscreenPreview?: (doc: Document) => void; onOpenDetailPanel?: (docId: Identifier) => void; } export const DocumentOpenProvider: React.FC = ({ children, onOpenViewer, - onOpenPreview, + onOpenFullscreenPreview, onOpenDetailPanel, }) => { const openDocument = useCallback((doc: Document, intent: DocumentOpenIntent = 'preview') => { @@ -29,8 +29,8 @@ export const DocumentOpenProvider: React.FC = ({ switch (intent) { case 'preview': - if (onOpenPreview) { - onOpenPreview(doc); + if (onOpenFullscreenPreview) { + onOpenFullscreenPreview(doc); } break; case 'inspect': @@ -51,7 +51,7 @@ export const DocumentOpenProvider: React.FC = ({ } break; } - }, [onOpenPreview, onOpenDetailPanel, onOpenViewer]); + }, [onOpenFullscreenPreview, onOpenDetailPanel, onOpenViewer]); return ( diff --git a/frontend/src/styles/index.css b/frontend/src/styles/index.css index 9f3fefa..89367b9 100644 --- a/frontend/src/styles/index.css +++ b/frontend/src/styles/index.css @@ -2,7 +2,7 @@ @import './base/controls.css'; @import './layout/panel-header-controls.css'; @import './components/resize-handle.css'; -@import '../viewer/preview-zoom.css'; +@import '../viewer/fullscreen-preview.css'; @import './base/iconography.css'; @import '../documents/styles/controls.css'; @import './layout/structure.css'; @@ -21,4 +21,4 @@ @import '../login/login.css'; @import '../documents/styles/shared-snippets.css'; @import './uploads/overlay.css'; -@import './base/text-button.css'; +@import './base/text-button.css'; \ No newline at end of file diff --git a/frontend/src/viewer/DocumentViewerPanel.tsx b/frontend/src/viewer/DocumentViewerPanel.tsx index ce94a93..3facf06 100644 --- a/frontend/src/viewer/DocumentViewerPanel.tsx +++ b/frontend/src/viewer/DocumentViewerPanel.tsx @@ -16,7 +16,7 @@ import { sortCorrespondents, } from './components/DocumentSummarySection'; import DocumentDownloadLink from '../documents/components/DocumentDownloadLink'; -import { usePreviewContext } from './PreviewContext'; +import { useFullscreenPreviewContext } from './FullscreenPreviewContext'; import type { DocumentSummarySectionProps } from './components/DocumentSummarySection'; import { extractDocumentMetadataPayload } from './logic/documentSummary'; import { resolveDocumentAssetUrl } from '../lib/assets/AssetManager'; @@ -218,14 +218,14 @@ const DocumentViewerPanel: React.FC = ({ [hasOcr, loadOcrContent], ); - const { openPreview } = usePreviewContext(); + const { openFullscreenPreview } = useFullscreenPreviewContext(); const handleZoomOpen = useCallback(() => { if (!document) { return; } - openPreview(document); - }, [document, openPreview]); + openFullscreenPreview(document); + }, [document, openFullscreenPreview]); const panelRef = useRef(null); const isStackedLayout = useViewerLayoutMode(panelRef, document?.id); diff --git a/frontend/src/viewer/PreviewContext.tsx b/frontend/src/viewer/FullscreenPreviewContext.tsx similarity index 53% rename from frontend/src/viewer/PreviewContext.tsx rename to frontend/src/viewer/FullscreenPreviewContext.tsx index 9eee7fe..429d5b6 100644 --- a/frontend/src/viewer/PreviewContext.tsx +++ b/frontend/src/viewer/FullscreenPreviewContext.tsx @@ -1,33 +1,33 @@ import React, { useState, useCallback, useMemo, useRef } from 'react'; -import PreviewZoomOverlay from './components/PreviewZoomOverlay'; +import FullscreenPreviewOverlay from './components/FullscreenPreviewOverlay'; import type { Document } from '../types/documents'; import type { Identifier } from '../types/identifiers'; import { createSafeContext } from '../utils/createSafeContext'; -interface PreviewContextType { - openPreview: (doc: Document) => void; - closePreview: () => void; +interface FullscreenPreviewContextType { + openFullscreenPreview: (doc: Document) => void; + closeFullscreenPreview: () => void; } -const [PreviewContext, usePreviewContext] = createSafeContext('Preview'); +const [FullscreenPreviewContext, useFullscreenPreviewContext] = createSafeContext('FullscreenPreview'); -interface PreviewProviderProps { +interface FullscreenPreviewProviderProps { children: React.ReactNode; onNavigate?: (documentId: Identifier) => void; } -export const PreviewProvider: React.FC = ({ children, onNavigate }) => { +export const FullscreenPreviewProvider: React.FC = ({ children, onNavigate }) => { const [previewDoc, setPreviewDoc] = useState(null); const lastFocusedElement = useRef(null); - const openPreview = useCallback((doc: Document) => { + const openFullscreenPreview = useCallback((doc: Document) => { if (!lastFocusedElement.current) { lastFocusedElement.current = document.activeElement as HTMLElement; } setPreviewDoc(doc); }, []); - const closePreview = useCallback(() => { + const closeFullscreenPreview = useCallback(() => { setPreviewDoc(null); if (lastFocusedElement.current) { lastFocusedElement.current.focus(); @@ -38,26 +38,26 @@ export const PreviewProvider: React.FC = ({ children, onNa const handleMaximize = useCallback(() => { if (previewDoc && onNavigate) { onNavigate(previewDoc.id); - closePreview(); + closeFullscreenPreview(); } - }, [previewDoc, onNavigate, closePreview]); + }, [previewDoc, onNavigate, closeFullscreenPreview]); const value = useMemo(() => ({ - openPreview, - closePreview, - }), [openPreview, closePreview]); + openFullscreenPreview, + closeFullscreenPreview, + }), [openFullscreenPreview, closeFullscreenPreview]); return ( - + {children} - - + ); }; -export { usePreviewContext }; +export { useFullscreenPreviewContext }; diff --git a/frontend/src/viewer/components/PreviewZoomOverlay.tsx b/frontend/src/viewer/components/FullscreenPreviewOverlay.tsx similarity index 91% rename from frontend/src/viewer/components/PreviewZoomOverlay.tsx rename to frontend/src/viewer/components/FullscreenPreviewOverlay.tsx index 123549c..d30f335 100644 --- a/frontend/src/viewer/components/PreviewZoomOverlay.tsx +++ b/frontend/src/viewer/components/FullscreenPreviewOverlay.tsx @@ -7,14 +7,14 @@ import { IconX, FileInfoIcon } from '../../components/icons'; import type { Document } from '../../types/documents'; -interface PreviewZoomOverlayProps { +interface FullscreenPreviewOverlayProps { open?: boolean; onClose: () => void; onMaximize?: () => void; document?: Document | null; } -const PreviewZoomOverlay: React.FC = ({ +const FullscreenPreviewOverlay: React.FC = ({ open = false, onClose, onMaximize, @@ -81,12 +81,12 @@ const PreviewZoomOverlay: React.FC = ({ } }; - const stageClassName = 'preview-zoom__stage'; - const containerClassName = 'preview-zoom__scroll'; + const stageClassName = 'fullscreen-preview__stage'; + const containerClassName = 'fullscreen-preview__scroll'; const backdropClassName = [ - 'preview-zoom-backdrop', - isBackdropVisible ? 'preview-zoom-backdrop--visible' : '', + 'fullscreen-preview-backdrop', + isBackdropVisible ? 'fullscreen-preview-backdrop--visible' : '', ] .filter(Boolean) .join(' '); @@ -160,4 +160,4 @@ const PreviewZoomOverlay: React.FC = ({ ); }; -export default PreviewZoomOverlay; +export default FullscreenPreviewOverlay; diff --git a/frontend/src/viewer/preview-zoom.css b/frontend/src/viewer/fullscreen-preview.css similarity index 78% rename from frontend/src/viewer/preview-zoom.css rename to frontend/src/viewer/fullscreen-preview.css index bfdd51a..a891afd 100644 --- a/frontend/src/viewer/preview-zoom.css +++ b/frontend/src/viewer/fullscreen-preview.css @@ -1,4 +1,4 @@ -.preview-zoom-backdrop { +.fullscreen-preview-backdrop { position: fixed; inset: 0; background: var(--overlay-backdrop); @@ -14,13 +14,13 @@ -webkit-backdrop-filter: blur(8px); } -.preview-zoom-backdrop--visible { +.fullscreen-preview-backdrop--visible { opacity: 1; background: var(--overlay-backdrop); pointer-events: auto; } -.preview-zoom__stage { +.fullscreen-preview__stage { position: relative; display: flex; align-items: center; @@ -32,7 +32,7 @@ --header-clearance: calc(2.5rem + 0.5rem); } -.preview-zoom__scroll .document-viewer__object--image { +.fullscreen-preview__scroll .document-viewer__object--image { width: auto; height: auto; box-shadow: 0 32px 120px var(--shadow-deep); @@ -42,7 +42,7 @@ touch-action: manipulation; } -.preview-zoom__scroll { +.fullscreen-preview__scroll { display: flex; align-items: center; justify-content: center; @@ -55,21 +55,21 @@ --pdf-viewer-stack-padding: var(--preview-padding); } -.preview-zoom__scroll:focus { +.fullscreen-preview__scroll:focus { outline: none; } -.preview-zoom__scroll .document-viewer__object--pdf { +.fullscreen-preview__scroll .document-viewer__object--pdf { width: 100%; height: 100%; } -.preview-zoom__stage .pdf-viewer__page-wrapper { +.fullscreen-preview__stage .pdf-viewer__page-wrapper { position: relative; overflow: visible; } -.preview-zoom__stage .pdf-viewer__page-wrapper::after { +.fullscreen-preview__stage .pdf-viewer__page-wrapper::after { content: ''; position: absolute; inset: 0; @@ -80,7 +80,7 @@ } /* Header positioning for preview zoom overlay */ -.preview-zoom-backdrop .panel-header--dark { +.fullscreen-preview-backdrop .panel-header--dark { position: absolute; top: 0; left: 0; @@ -94,6 +94,6 @@ } /* Prevent header clicks from closing backdrop */ -.preview-zoom-backdrop .panel-header--dark * { +.fullscreen-preview-backdrop .panel-header--dark * { pointer-events: auto; } \ No newline at end of file diff --git a/frontend/src/viewer/logic/useDetailWorkspace.ts b/frontend/src/viewer/logic/useDetailWorkspace.ts index 3e9cec4..d34cd18 100644 --- a/frontend/src/viewer/logic/useDetailWorkspace.ts +++ b/frontend/src/viewer/logic/useDetailWorkspace.ts @@ -22,7 +22,7 @@ interface UseDetailWorkspaceArgs { folderNodes: Map; detailPanelControlRef: MutableRefObject<{ open?: (documentId: Identifier) => void; close?: () => void } | null>; detailFolderFetchRef: MutableRefObject>; - openDocumentPreview?: (args: { documentIds: Identifier[] }) => void; + openDocumentViewer?: (args: { documentIds: Identifier[] }) => void; handleDocumentTitleUpdate?: (docId: Identifier, title: string) => Promise | boolean; handleDocumentIssuedUpdate?: (docId: Identifier, issued: number | null) => Promise | boolean; handleDocumentTagAdd?: (doc: Document, value: string, context?: { option?: unknown }) => void; @@ -54,7 +54,7 @@ const useDetailWorkspace = ({ folderNodes, detailPanelControlRef, detailFolderFetchRef, - openDocumentPreview, + openDocumentViewer, handleDocumentTitleUpdate, handleDocumentIssuedUpdate, handleDocumentTagAdd, @@ -176,7 +176,7 @@ const useDetailWorkspace = ({ correspondentLookupById, onTagAdd: handleDetailTagAdd, onTagRemove: handleDetailTagRemove, - onOpenPreview: openDocumentPreview, + onOpenViewer: openDocumentViewer, onUpdateTitle: handleDocumentTitleUpdate, onUpdateIssued: handleDocumentIssuedUpdate, ensureAssetUrl,