This commit is contained in:
Reece 2025-07-23 11:01:22 +01:00
parent 1192e3b5d5
commit f7cfccd391
3 changed files with 49 additions and 84 deletions

View File

@ -5,6 +5,7 @@ import { FileSelectionProvider, useFileSelection } from "../contexts/FileSelecti
import { useToolManagement } from "../hooks/useToolManagement"; import { useToolManagement } from "../hooks/useToolManagement";
import { Group, Box, Button, Container } from "@mantine/core"; import { Group, Box, Button, Container } from "@mantine/core";
import { useRainbowThemeContext } from "../components/shared/RainbowThemeProvider"; import { useRainbowThemeContext } from "../components/shared/RainbowThemeProvider";
import { PageEditorFunctions } from "../types/pageEditor";
import rainbowStyles from '../styles/rainbow.module.css'; import rainbowStyles from '../styles/rainbow.module.css';
import ToolPicker from "../components/tools/ToolPicker"; import ToolPicker from "../components/tools/ToolPicker";
@ -16,47 +17,26 @@ import Viewer from "../components/viewer/Viewer";
import FileUploadSelector from "../components/shared/FileUploadSelector"; import FileUploadSelector from "../components/shared/FileUploadSelector";
import ToolRenderer from "../components/tools/ToolRenderer"; import ToolRenderer from "../components/tools/ToolRenderer";
import QuickAccessBar from "../components/shared/QuickAccessBar"; import QuickAccessBar from "../components/shared/QuickAccessBar";
import { useMultipleEndpointsEnabled } from "../hooks/useEndpointConfig";
// Inner component that uses file selection context
function HomePageContent() { function HomePageContent() {
const { t } = useTranslation(); const { t } = useTranslation();
const { isRainbowMode } = useRainbowThemeContext(); const { isRainbowMode } = useRainbowThemeContext();
// Get file context
const fileContext = useFileContext(); const fileContext = useFileContext();
const { activeFiles, currentView, currentMode, setCurrentView, addFiles } = fileContext; const { activeFiles, currentView, currentMode, setCurrentView, addFiles } = fileContext;
// Get file selection context
const { setMaxFiles, setIsToolMode, setSelectedFiles } = useFileSelection(); const { setMaxFiles, setIsToolMode, setSelectedFiles } = useFileSelection();
const { const {
selectedToolKey, selectedToolKey,
selectedTool, selectedTool,
toolSelectedFileIds,
toolRegistry, toolRegistry,
selectTool, selectTool,
clearToolSelection, clearToolSelection,
setToolSelectedFileIds,
} = useToolManagement(); } = useToolManagement();
const [sidebarsVisible, setSidebarsVisible] = useState(true); const [sidebarsVisible, setSidebarsVisible] = useState(true);
const [leftPanelView, setLeftPanelView] = useState<'toolPicker' | 'toolContent'>('toolPicker'); const [leftPanelView, setLeftPanelView] = useState<'toolPicker' | 'toolContent'>('toolPicker');
const [readerMode, setReaderMode] = useState(false); const [readerMode, setReaderMode] = useState(false);
const [pageEditorFunctions, setPageEditorFunctions] = useState<{ const [pageEditorFunctions, setPageEditorFunctions] = useState<PageEditorFunctions | null>(null);
closePdf: () => void;
handleUndo: () => void;
handleRedo: () => void;
canUndo: boolean;
canRedo: boolean;
handleRotate: () => void;
handleDelete: () => void;
handleSplit: () => void;
onExportSelected: () => void;
onExportAll: () => void;
exportLoading: boolean;
selectionMode: boolean;
selectedPages: number[];
} | null>(null);
const [previewFile, setPreviewFile] = useState<File | null>(null); const [previewFile, setPreviewFile] = useState<File | null>(null);
// Update file selection context when tool changes // Update file selection context when tool changes
@ -65,9 +45,9 @@ function HomePageContent() {
setMaxFiles(selectedTool.maxFiles); setMaxFiles(selectedTool.maxFiles);
setIsToolMode(true); setIsToolMode(true);
} else { } else {
setMaxFiles(-1); // Unlimited when not in tool mode setMaxFiles(-1);
setIsToolMode(false); setIsToolMode(false);
setSelectedFiles([]); // Clear selection when exiting tool mode setSelectedFiles([]);
} }
}, [selectedTool, setMaxFiles, setIsToolMode, setSelectedFiles]); }, [selectedTool, setMaxFiles, setIsToolMode, setSelectedFiles]);
@ -220,24 +200,20 @@ function HomePageContent() {
maxRecentFiles={8} maxRecentFiles={8}
/> />
</Container> </Container>
) : currentView === "fileEditor" && selectedToolKey ? (
// Tool-specific FileEditor - for file selection with tools
<FileEditor
toolMode={true}
showUpload={true}
showBulkActions={false}
/>
) : currentView === "fileEditor" ? ( ) : currentView === "fileEditor" ? (
// Generic FileEditor - for general file management
<FileEditor <FileEditor
onOpenPageEditor={(file) => { toolMode={!!selectedToolKey}
handleViewChange("pageEditor"); showUpload={true}
}} showBulkActions={!selectedToolKey}
onMergeFiles={(filesToMerge) => { {...(!selectedToolKey && {
// Add merged files to active set onOpenPageEditor: (file) => {
filesToMerge.forEach(addToActiveFiles); handleViewChange("pageEditor");
handleViewChange("viewer"); },
}} onMergeFiles: (filesToMerge) => {
filesToMerge.forEach(addToActiveFiles);
handleViewChange("viewer");
}
})}
/> />
) : currentView === "viewer" ? ( ) : currentView === "viewer" ? (
<Viewer <Viewer

View File

@ -36,3 +36,19 @@ export interface UndoRedoState {
operations: PageOperation[]; operations: PageOperation[];
currentIndex: number; currentIndex: number;
} }
export interface PageEditorFunctions {
closePdf: () => void;
handleUndo: () => void;
handleRedo: () => void;
canUndo: boolean;
canRedo: boolean;
handleRotate: () => void;
handleDelete: () => void;
handleSplit: () => void;
onExportSelected: () => void;
onExportAll: () => void;
exportLoading: boolean;
selectionMode: boolean;
selectedPages: number[];
}

View File

@ -1,37 +1,16 @@
import React from 'react'; import React from 'react';
// Type definitions for better type safety export type MaxFiles = number; // 1=single, >1=limited, -1=unlimited
export type MaxFiles = number; // 1 = single file, >1 = limited multi-file, -1 = unlimited
export type ToolCategory = 'manipulation' | 'conversion' | 'analysis' | 'utility' | 'optimization' | 'security'; export type ToolCategory = 'manipulation' | 'conversion' | 'analysis' | 'utility' | 'optimization' | 'security';
/**
* Tool definition without name - used for base definitions before translation
*/
export type ToolDefinition = Omit<Tool, 'name'>; export type ToolDefinition = Omit<Tool, 'name'>;
export type ToolStepType = 'files' | 'settings' | 'results';
/**
* Standard interface that all modern tools should implement
* This ensures consistent behavior and makes adding new tools trivial
*/
export interface BaseToolProps { export interface BaseToolProps {
// Tool results callback - called when tool completes successfully
onComplete?: (results: File[]) => void; onComplete?: (results: File[]) => void;
// Error handling callback
onError?: (error: string) => void; onError?: (error: string) => void;
// Preview functionality for result files
onPreviewFile?: (file: File | null) => void; onPreviewFile?: (file: File | null) => void;
} }
/**
* Tool step types for standardized UI
*/
export type ToolStepType = 'files' | 'settings' | 'results';
/**
* Tool step configuration
*/
export interface ToolStepConfig { export interface ToolStepConfig {
type: ToolStepType; type: ToolStepType;
title: string; title: string;
@ -42,9 +21,12 @@ export interface ToolStepConfig {
onCollapsedClick?: () => void; onCollapsedClick?: () => void;
} }
/** export interface ToolValidationResult {
* Tool operation result valid: boolean;
*/ errors?: string[];
warnings?: string[];
}
export interface ToolResult { export interface ToolResult {
success: boolean; success: boolean;
files?: File[]; files?: File[];
@ -53,30 +35,21 @@ export interface ToolResult {
metadata?: Record<string, any>; metadata?: Record<string, any>;
} }
/**
* Complete tool definition - single interface for all tool needs
*/
export interface Tool { export interface Tool {
id: string; id: string;
name: string; // Always required - added via translation name: string;
icon: React.ReactNode; // Always required - for UI display icon: React.ReactNode;
component: React.ComponentType<BaseToolProps>; // Lazy-loaded tool component component: React.ComponentType<BaseToolProps>;
maxFiles: MaxFiles; // File selection limit: 1=single, 5=limited, -1=unlimited maxFiles: MaxFiles;
category?: ToolCategory; // Tool grouping for organization category?: ToolCategory;
description?: string; // Help text for users description?: string;
endpoints?: string[]; // Backend endpoints this tool uses endpoints?: string[];
supportedFormats?: string[]; // File types this tool accepts supportedFormats?: string[];
validation?: (files: File[]) => { valid: boolean; message?: string }; // File validation logic validation?: (files: File[]) => ToolValidationResult;
} }
/**
* Tool registry type - tools indexed by key
*/
export type ToolRegistry = Record<string, Tool>; export type ToolRegistry = Record<string, Tool>;
/**
* File selection context interfaces for type safety
*/
export interface FileSelectionState { export interface FileSelectionState {
selectedFiles: File[]; selectedFiles: File[];
maxFiles: MaxFiles; maxFiles: MaxFiles;