mirror of
https://github.com/Frooodle/Stirling-PDF.git
synced 2025-11-16 01:21:16 +01:00
Overview Replaced scattered file inputs with a unified modal-based upload system. Users now upload files via a global Files button with intelligent tool-aware filtering. Key Changes 🔄 New Upload Flow - Before: Direct file inputs throughout the UI - After: Single Files button → Modal → Tool filters files automatically 🎯 Smart File Filtering - Modal shows only supported file types based on selected tool - Visual indicators for unsupported files (grayed out + badges) - Automatic duplicate detection ✨ Enhanced UX - Files button shows active state when modal is open - Consistent upload experience across all tools - Professional modal workflow Architecture New Components FilesModalProvider → FileUploadModal → Tool-aware filtering Button System Redesign type: 'navigation' | 'modal' | 'action' // Only navigation buttons stay active // Modal buttons show active when modal open Files Changed - ✅ QuickAccessBar.tsx - Added Files button - ✅ FileUploadModal.tsx - New tool-aware modal - ✅ HomePage.tsx - Integrated modal system - ✅ ConvertE2E.spec.ts - Updated tests for modal workflow Benefits - Unified UX: One place to upload files - Smart Filtering: Only see relevant file types - Better Architecture: Clean separation of concerns - Improved Testing: Reliable test automation Migration: File uploads now go through Files button → modal instead of direct inputs. All existing functionality preserved. --------- Co-authored-by: Connor Yoh <connor@stirlingpdf.com>
57 lines
1.5 KiB
TypeScript
57 lines
1.5 KiB
TypeScript
import { useState, useCallback } from 'react';
|
|
|
|
export interface UseFilesModalReturn {
|
|
isFilesModalOpen: boolean;
|
|
openFilesModal: () => void;
|
|
closeFilesModal: () => void;
|
|
onFileSelect?: (file: File) => void;
|
|
onFilesSelect?: (files: File[]) => void;
|
|
onModalClose?: () => void;
|
|
setOnModalClose: (callback: () => void) => void;
|
|
}
|
|
|
|
interface UseFilesModalProps {
|
|
onFileSelect?: (file: File) => void;
|
|
onFilesSelect?: (files: File[]) => void;
|
|
}
|
|
|
|
export const useFilesModal = ({
|
|
onFileSelect,
|
|
onFilesSelect
|
|
}: UseFilesModalProps = {}): UseFilesModalReturn => {
|
|
const [isFilesModalOpen, setIsFilesModalOpen] = useState(false);
|
|
const [onModalClose, setOnModalClose] = useState<(() => void) | undefined>();
|
|
|
|
const openFilesModal = useCallback(() => {
|
|
setIsFilesModalOpen(true);
|
|
}, []);
|
|
|
|
const closeFilesModal = useCallback(() => {
|
|
setIsFilesModalOpen(false);
|
|
onModalClose?.();
|
|
}, [onModalClose]);
|
|
|
|
const handleFileSelect = useCallback((file: File) => {
|
|
onFileSelect?.(file);
|
|
closeFilesModal();
|
|
}, [onFileSelect, closeFilesModal]);
|
|
|
|
const handleFilesSelect = useCallback((files: File[]) => {
|
|
onFilesSelect?.(files);
|
|
closeFilesModal();
|
|
}, [onFilesSelect, closeFilesModal]);
|
|
|
|
const setModalCloseCallback = useCallback((callback: () => void) => {
|
|
setOnModalClose(() => callback);
|
|
}, []);
|
|
|
|
return {
|
|
isFilesModalOpen,
|
|
openFilesModal,
|
|
closeFilesModal,
|
|
onFileSelect: handleFileSelect,
|
|
onFilesSelect: handleFilesSelect,
|
|
onModalClose,
|
|
setOnModalClose: setModalCloseCallback,
|
|
};
|
|
}; |