This commit is contained in:
Reece 2025-10-28 23:08:03 +00:00
parent f95249ee63
commit 0bbd40eba7
3 changed files with 62 additions and 60 deletions

View File

@ -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<number | undefined>();
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) {

View File

@ -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 (
<PreferencesContext.Provider value={value}>
<PreferencesContext.Provider
value={{
preferences,
updatePreference,
resetPreferences,
}}
>
{children}
</PreferencesContext.Provider>
);

View File

@ -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<ViewerProviderProps> = ({ 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<ViewerProviderProps> = ({ 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<ViewerProviderProps> = ({ 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<ViewerProviderProps> = ({ 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<ViewerProviderProps> = ({ 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<ViewerProviderProps> = ({ 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<ViewerProviderProps> = ({ 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<ViewerProviderProps> = ({ 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<ViewerProviderProps> = ({ 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<ViewerProviderProps> = ({ 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<ViewerContextType>(() => ({
const value: ViewerContextType = {
// UI state
isThumbnailSidebarVisible,
toggleThumbnailSidebar,
@ -615,20 +615,7 @@ export const ViewerProvider: React.FC<ViewerProviderProps> = ({ children }) => {
// Bridge registration
registerBridge,
}), [
isThumbnailSidebarVisible,
isAnnotationsVisible,
isAnnotationMode,
activeFileIndex,
scrollActions,
zoomActions,
panActions,
selectionActions,
spreadActions,
rotationActions,
searchActions,
exportActions,
]);
};
return (
<ViewerContext.Provider value={value}>