diff --git a/frontend/src/core/contexts/FilesModalContext.tsx b/frontend/src/core/contexts/FilesModalContext.tsx index 1096eee11..468609f7d 100644 --- a/frontend/src/core/contexts/FilesModalContext.tsx +++ b/frontend/src/core/contexts/FilesModalContext.tsx @@ -2,10 +2,11 @@ import React, { createContext, useContext, useState, useCallback, useMemo } from import { useFileHandler } from '@app/hooks/useFileHandler'; import { useFileActions } from '@app/contexts/FileContext'; import { StirlingFileStub } from '@app/types/fileContext'; +import { fileStorage } from '@app/services/fileStorage'; interface FilesModalContextType { isFilesModalOpen: boolean; - openFilesModal: (options?: { insertAfterPage?: number; customHandler?: (files: File[] | StirlingFileStub[], insertAfterPage?: number, isFromStorage?: boolean) => void }) => void; + openFilesModal: (options?: { insertAfterPage?: number; customHandler?: (files: File[], insertAfterPage?: number) => void }) => void; closeFilesModal: () => void; onFileUpload: (files: File[]) => void; onRecentFileSelect: (stirlingFileStubs: StirlingFileStub[]) => void; @@ -21,9 +22,9 @@ export const FilesModalProvider: React.FC<{ children: React.ReactNode }> = ({ ch const [isFilesModalOpen, setIsFilesModalOpen] = useState(false); const [onModalClose, setOnModalClose] = useState<(() => void) | undefined>(); const [insertAfterPage, setInsertAfterPage] = useState(); - const [customHandler, setCustomHandler] = useState<((files: File[] | StirlingFileStub[], insertAfterPage?: number, isFromStorage?: boolean) => void) | undefined>(); + const [customHandler, setCustomHandler] = useState<((files: File[], insertAfterPage?: number) => void) | undefined>(); - const openFilesModal = useCallback((options?: { insertAfterPage?: number; customHandler?: (files: File[] | StirlingFileStub[], insertAfterPage?: number, isFromStorage?: boolean) => void }) => { + const openFilesModal = useCallback((options?: { insertAfterPage?: number; customHandler?: (files: File[], insertAfterPage?: number) => void }) => { setInsertAfterPage(options?.insertAfterPage); setCustomHandler(() => options?.customHandler); setIsFilesModalOpen(true); @@ -49,8 +50,22 @@ export const FilesModalProvider: React.FC<{ children: React.ReactNode }> = ({ ch const handleRecentFileSelect = useCallback(async (stirlingFileStubs: StirlingFileStub[]) => { if (customHandler) { - // Pass stubs directly to custom handler with flag indicating they're from storage - customHandler(stirlingFileStubs, insertAfterPage, true); + // Load the actual files from storage for custom handler + try { + const loadedFiles: File[] = []; + for (const stub of stirlingFileStubs) { + const stirlingFile = await fileStorage.getStirlingFile(stub.id); + if (stirlingFile) { + loadedFiles.push(stirlingFile); + } + } + + if (loadedFiles.length > 0) { + customHandler(loadedFiles, insertAfterPage); + } + } catch (error) { + console.error('Failed to load files for custom handler:', error); + } } else { // Normal case - use addStirlingFileStubs to preserve metadata if (actions.addStirlingFileStubs) { diff --git a/frontend/src/core/contexts/PreferencesContext.tsx b/frontend/src/core/contexts/PreferencesContext.tsx index 482e0fed0..b28d1b35b 100644 --- a/frontend/src/core/contexts/PreferencesContext.tsx +++ b/frontend/src/core/contexts/PreferencesContext.tsx @@ -34,14 +34,14 @@ export const PreferencesProvider: React.FC<{ children: React.ReactNode }> = ({ c setPreferences(preferencesService.getAllPreferences()); }, []); - const value = React.useMemo(() => ({ - preferences, - updatePreference, - resetPreferences, - }), [preferences, updatePreference, resetPreferences]); - return ( - + {children} ); diff --git a/frontend/src/core/contexts/ViewerContext.tsx b/frontend/src/core/contexts/ViewerContext.tsx index 8afc1a9ea..8e0bea44a 100644 --- a/frontend/src/core/contexts/ViewerContext.tsx +++ b/frontend/src/core/contexts/ViewerContext.tsx @@ -1,4 +1,4 @@ -import React, { createContext, useContext, useState, ReactNode, useRef, useMemo, useCallback } from 'react'; +import React, { createContext, useContext, useState, ReactNode, useRef } from 'react'; import { SpreadMode } from '@embedpdf/plugin-spread/react'; import { useNavigation } from '@app/contexts/NavigationContext'; @@ -280,21 +280,21 @@ export const ViewerProvider: React.FC = ({ children }) => { } }; - const toggleThumbnailSidebar = useCallback(() => { + const toggleThumbnailSidebar = () => { setIsThumbnailSidebarVisible(prev => !prev); - }, []); + }; - const toggleAnnotationsVisibility = useCallback(() => { + const toggleAnnotationsVisibility = () => { setIsAnnotationsVisible(prev => !prev); - }, []); + }; - const setAnnotationMode = useCallback((enabled: boolean) => { + const setAnnotationMode = (enabled: boolean) => { setIsAnnotationModeState(enabled); - }, []); + }; - const toggleAnnotationMode = useCallback(() => { + const toggleAnnotationMode = () => { setIsAnnotationModeState(prev => !prev); - }, []); + }; // State getters - read from bridge refs const getScrollState = (): ScrollState => { @@ -334,7 +334,7 @@ export const ViewerProvider: React.FC = ({ children }) => { }; // Action handlers - call APIs directly - const scrollActions = useMemo(() => ({ + const scrollActions = { scrollToPage: (page: number) => { const api = bridgeRefs.current.scroll?.api; if (api?.scrollToPage) { @@ -366,9 +366,9 @@ export const ViewerProvider: React.FC = ({ children }) => { api.scrollToPage({ pageNumber: scrollState.totalPages }); } } - }), []); + }; - const zoomActions = useMemo(() => ({ + const zoomActions = { zoomIn: () => { const api = bridgeRefs.current.zoom?.api; if (api?.zoomIn) { @@ -405,9 +405,9 @@ export const ViewerProvider: React.FC = ({ children }) => { api.requestZoom(level); } } - }), []); + }; - const panActions = useMemo(() => ({ + const panActions = { enablePan: () => { const api = bridgeRefs.current.pan?.api; if (api?.enable) { @@ -426,9 +426,9 @@ export const ViewerProvider: React.FC = ({ children }) => { api.toggle(); } } - }), []); + }; - const selectionActions = useMemo(() => ({ + const selectionActions = { copyToClipboard: () => { const api = bridgeRefs.current.selection?.api; if (api?.copyToClipboard) { @@ -449,9 +449,9 @@ export const ViewerProvider: React.FC = ({ children }) => { } return null; } - }), []); + }; - const spreadActions = useMemo(() => ({ + const spreadActions = { setSpreadMode: (mode: SpreadMode) => { const api = bridgeRefs.current.spread?.api; if (api?.setSpreadMode) { @@ -471,9 +471,9 @@ export const ViewerProvider: React.FC = ({ children }) => { api.toggleSpreadMode(); } } - }), []); + }; - const rotationActions = useMemo(() => ({ + const rotationActions = { rotateForward: () => { const api = bridgeRefs.current.rotation?.api; if (api?.rotateForward) { @@ -499,9 +499,9 @@ export const ViewerProvider: React.FC = ({ children }) => { } return 0; } - }), []); + }; - const searchActions = useMemo(() => ({ + const searchActions = { search: async (query: string) => { const api = bridgeRefs.current.search?.api; if (api?.search) { @@ -526,9 +526,9 @@ export const ViewerProvider: React.FC = ({ children }) => { api.clear(); } } - }), []); + }; - const exportActions = useMemo(() => ({ + const exportActions = { download: () => { const api = bridgeRefs.current.export?.api; if (api?.download) { @@ -548,29 +548,29 @@ export const ViewerProvider: React.FC = ({ children }) => { } return null; } - }), []); + }; - const registerImmediateZoomUpdate = useCallback((callback: (percent: number) => void) => { + const registerImmediateZoomUpdate = (callback: (percent: number) => void) => { immediateZoomUpdateCallback.current = callback; - }, []); + }; - const registerImmediateScrollUpdate = useCallback((callback: (currentPage: number, totalPages: number) => void) => { + const registerImmediateScrollUpdate = (callback: (currentPage: number, totalPages: number) => void) => { immediateScrollUpdateCallback.current = callback; - }, []); + }; - const triggerImmediateScrollUpdate = useCallback((currentPage: number, totalPages: number) => { + const triggerImmediateScrollUpdate = (currentPage: number, totalPages: number) => { if (immediateScrollUpdateCallback.current) { immediateScrollUpdateCallback.current(currentPage, totalPages); } - }, []); + }; - const triggerImmediateZoomUpdate = useCallback((zoomPercent: number) => { + const triggerImmediateZoomUpdate = (zoomPercent: number) => { if (immediateZoomUpdateCallback.current) { immediateZoomUpdateCallback.current(zoomPercent); } - }, []); + }; - const value = useMemo(() => ({ + const value: ViewerContextType = { // UI state isThumbnailSidebarVisible, toggleThumbnailSidebar, @@ -615,20 +615,7 @@ export const ViewerProvider: React.FC = ({ children }) => { // Bridge registration registerBridge, - }), [ - isThumbnailSidebarVisible, - isAnnotationsVisible, - isAnnotationMode, - activeFileIndex, - scrollActions, - zoomActions, - panActions, - selectionActions, - spreadActions, - rotationActions, - searchActions, - exportActions, - ]); + }; return (