mirror of
https://github.com/Stirling-Tools/Stirling-PDF.git
synced 2025-08-02 18:45:21 +00:00
Supported files & single file auto label
This commit is contained in:
parent
bbf92afa36
commit
695b3766ac
@ -12,6 +12,7 @@ import { FileOperation } from '../../types/fileContext';
|
|||||||
import { fileStorage } from '../../services/fileStorage';
|
import { fileStorage } from '../../services/fileStorage';
|
||||||
import { generateThumbnailForFile } from '../../utils/thumbnailUtils';
|
import { generateThumbnailForFile } from '../../utils/thumbnailUtils';
|
||||||
import { zipFileService } from '../../services/zipFileService';
|
import { zipFileService } from '../../services/zipFileService';
|
||||||
|
import { detectFileExtension } from '../../utils/fileUtils';
|
||||||
import styles from '../pageEditor/PageEditor.module.css';
|
import styles from '../pageEditor/PageEditor.module.css';
|
||||||
import FileThumbnail from '../pageEditor/FileThumbnail';
|
import FileThumbnail from '../pageEditor/FileThumbnail';
|
||||||
import DragDropGrid from '../pageEditor/DragDropGrid';
|
import DragDropGrid from '../pageEditor/DragDropGrid';
|
||||||
@ -34,6 +35,7 @@ interface FileEditorProps {
|
|||||||
toolMode?: boolean;
|
toolMode?: boolean;
|
||||||
showUpload?: boolean;
|
showUpload?: boolean;
|
||||||
showBulkActions?: boolean;
|
showBulkActions?: boolean;
|
||||||
|
supportedExtensions?: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
const FileEditor = ({
|
const FileEditor = ({
|
||||||
@ -41,10 +43,17 @@ const FileEditor = ({
|
|||||||
onMergeFiles,
|
onMergeFiles,
|
||||||
toolMode = false,
|
toolMode = false,
|
||||||
showUpload = true,
|
showUpload = true,
|
||||||
showBulkActions = true
|
showBulkActions = true,
|
||||||
|
supportedExtensions = ["pdf"]
|
||||||
}: FileEditorProps) => {
|
}: FileEditorProps) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
// Utility function to check if a file extension is supported
|
||||||
|
const isFileSupported = useCallback((fileName: string): boolean => {
|
||||||
|
const extension = detectFileExtension(fileName);
|
||||||
|
return extension ? supportedExtensions.includes(extension) : false;
|
||||||
|
}, [supportedExtensions]);
|
||||||
|
|
||||||
// Get file context
|
// Get file context
|
||||||
const fileContext = useFileContext();
|
const fileContext = useFileContext();
|
||||||
const {
|
const {
|
||||||
@ -807,6 +816,7 @@ const FileEditor = ({
|
|||||||
onSplitFile={handleSplitFile}
|
onSplitFile={handleSplitFile}
|
||||||
onSetStatus={setStatus}
|
onSetStatus={setStatus}
|
||||||
toolMode={toolMode}
|
toolMode={toolMode}
|
||||||
|
isSupported={isFileSupported(file.name)}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
renderSplitMarker={(file, index) => (
|
renderSplitMarker={(file, index) => (
|
||||||
|
@ -18,9 +18,10 @@ interface FileCardProps {
|
|||||||
onEdit?: () => void;
|
onEdit?: () => void;
|
||||||
isSelected?: boolean;
|
isSelected?: boolean;
|
||||||
onSelect?: () => void;
|
onSelect?: () => void;
|
||||||
|
isSupported?: boolean; // Whether the file format is supported by the current tool
|
||||||
}
|
}
|
||||||
|
|
||||||
const FileCard = ({ file, onRemove, onDoubleClick, onView, onEdit, isSelected, onSelect }: FileCardProps) => {
|
const FileCard = ({ file, onRemove, onDoubleClick, onView, onEdit, isSelected, onSelect, isSupported = true }: FileCardProps) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { thumbnail: thumb, isGenerating } = useIndexedDBThumbnail(file);
|
const { thumbnail: thumb, isGenerating } = useIndexedDBThumbnail(file);
|
||||||
const [isHovered, setIsHovered] = useState(false);
|
const [isHovered, setIsHovered] = useState(false);
|
||||||
@ -35,10 +36,12 @@ const FileCard = ({ file, onRemove, onDoubleClick, onView, onEdit, isSelected, o
|
|||||||
width: 225,
|
width: 225,
|
||||||
minWidth: 180,
|
minWidth: 180,
|
||||||
maxWidth: 260,
|
maxWidth: 260,
|
||||||
cursor: onDoubleClick ? "pointer" : undefined,
|
cursor: onDoubleClick && isSupported ? "pointer" : undefined,
|
||||||
position: 'relative',
|
position: 'relative',
|
||||||
border: isSelected ? '2px solid var(--mantine-color-blue-6)' : undefined,
|
border: isSelected ? '2px solid var(--mantine-color-blue-6)' : undefined,
|
||||||
backgroundColor: isSelected ? 'var(--mantine-color-blue-0)' : undefined
|
backgroundColor: isSelected ? 'var(--mantine-color-blue-0)' : undefined,
|
||||||
|
opacity: isSupported ? 1 : 0.5,
|
||||||
|
filter: isSupported ? 'none' : 'grayscale(50%)'
|
||||||
}}
|
}}
|
||||||
onDoubleClick={onDoubleClick}
|
onDoubleClick={onDoubleClick}
|
||||||
onMouseEnter={() => setIsHovered(true)}
|
onMouseEnter={() => setIsHovered(true)}
|
||||||
@ -180,6 +183,11 @@ const FileCard = ({ file, onRemove, onDoubleClick, onView, onEdit, isSelected, o
|
|||||||
DB
|
DB
|
||||||
</Badge>
|
</Badge>
|
||||||
)}
|
)}
|
||||||
|
{!isSupported && (
|
||||||
|
<Badge color="orange" variant="filled" size="sm">
|
||||||
|
{t("fileManager.unsupported", "Unsupported")}
|
||||||
|
</Badge>
|
||||||
|
)}
|
||||||
</Group>
|
</Group>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import { Text, Checkbox, Tooltip, ActionIcon, Badge, Modal } from '@mantine/core';
|
import { Text, Checkbox, Tooltip, ActionIcon, Badge, Modal } from '@mantine/core';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
import CloseIcon from '@mui/icons-material/Close';
|
import CloseIcon from '@mui/icons-material/Close';
|
||||||
import VisibilityIcon from '@mui/icons-material/Visibility';
|
import VisibilityIcon from '@mui/icons-material/Visibility';
|
||||||
import HistoryIcon from '@mui/icons-material/History';
|
import HistoryIcon from '@mui/icons-material/History';
|
||||||
@ -37,6 +38,7 @@ interface FileThumbnailProps {
|
|||||||
onViewFile: (fileId: string) => void;
|
onViewFile: (fileId: string) => void;
|
||||||
onSetStatus: (status: string) => void;
|
onSetStatus: (status: string) => void;
|
||||||
toolMode?: boolean;
|
toolMode?: boolean;
|
||||||
|
isSupported?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const FileThumbnail = ({
|
const FileThumbnail = ({
|
||||||
@ -60,7 +62,9 @@ const FileThumbnail = ({
|
|||||||
onViewFile,
|
onViewFile,
|
||||||
onSetStatus,
|
onSetStatus,
|
||||||
toolMode = false,
|
toolMode = false,
|
||||||
|
isSupported = true,
|
||||||
}: FileThumbnailProps) => {
|
}: FileThumbnailProps) => {
|
||||||
|
const { t } = useTranslation();
|
||||||
const [showHistory, setShowHistory] = useState(false);
|
const [showHistory, setShowHistory] = useState(false);
|
||||||
|
|
||||||
const formatFileSize = (bytes: number) => {
|
const formatFileSize = (bytes: number) => {
|
||||||
@ -107,7 +111,9 @@ const FileThumbnail = ({
|
|||||||
}
|
}
|
||||||
return 'translateX(0)';
|
return 'translateX(0)';
|
||||||
})(),
|
})(),
|
||||||
transition: isAnimating ? 'none' : 'transform 0.2s ease-in-out'
|
transition: isAnimating ? 'none' : 'transform 0.2s ease-in-out',
|
||||||
|
opacity: isSupported ? 1 : 0.5,
|
||||||
|
filter: isSupported ? 'none' : 'grayscale(50%)'
|
||||||
}}
|
}}
|
||||||
draggable
|
draggable
|
||||||
onDragStart={() => onDragStart(file.id)}
|
onDragStart={() => onDragStart(file.id)}
|
||||||
@ -142,9 +148,12 @@ const FileThumbnail = ({
|
|||||||
checked={selectedFiles.includes(file.id)}
|
checked={selectedFiles.includes(file.id)}
|
||||||
onChange={(event) => {
|
onChange={(event) => {
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
onToggleFile(file.id);
|
if (isSupported) {
|
||||||
|
onToggleFile(file.id);
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
onClick={(e) => e.stopPropagation()}
|
onClick={(e) => e.stopPropagation()}
|
||||||
|
disabled={!isSupported}
|
||||||
size="sm"
|
size="sm"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@ -195,6 +204,23 @@ const FileThumbnail = ({
|
|||||||
{file.pageCount} pages
|
{file.pageCount} pages
|
||||||
</Badge>
|
</Badge>
|
||||||
|
|
||||||
|
{/* Unsupported badge */}
|
||||||
|
{!isSupported && (
|
||||||
|
<Badge
|
||||||
|
size="sm"
|
||||||
|
variant="filled"
|
||||||
|
color="orange"
|
||||||
|
style={{
|
||||||
|
position: 'absolute',
|
||||||
|
top: 8,
|
||||||
|
right: selectionMode ? 48 : 8, // Avoid overlap with checkbox
|
||||||
|
zIndex: 3,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{t("fileManager.unsupported", "Unsupported")}
|
||||||
|
</Badge>
|
||||||
|
)}
|
||||||
|
|
||||||
{/* File name overlay */}
|
{/* File name overlay */}
|
||||||
<Text
|
<Text
|
||||||
className={styles.pageNumber}
|
className={styles.pageNumber}
|
||||||
@ -240,7 +266,7 @@ const FileThumbnail = ({
|
|||||||
whiteSpace: 'nowrap'
|
whiteSpace: 'nowrap'
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{!toolMode && (
|
{!toolMode && isSupported && (
|
||||||
<>
|
<>
|
||||||
<Tooltip label="View File">
|
<Tooltip label="View File">
|
||||||
<ActionIcon
|
<ActionIcon
|
||||||
|
@ -20,6 +20,7 @@ interface FileGridProps {
|
|||||||
onShowAll?: () => void;
|
onShowAll?: () => void;
|
||||||
showingAll?: boolean;
|
showingAll?: boolean;
|
||||||
onDeleteAll?: () => void;
|
onDeleteAll?: () => void;
|
||||||
|
isFileSupported?: (fileName: string) => boolean; // Function to check if file is supported
|
||||||
}
|
}
|
||||||
|
|
||||||
type SortOption = 'date' | 'name' | 'size';
|
type SortOption = 'date' | 'name' | 'size';
|
||||||
@ -37,7 +38,8 @@ const FileGrid = ({
|
|||||||
maxDisplay,
|
maxDisplay,
|
||||||
onShowAll,
|
onShowAll,
|
||||||
showingAll = false,
|
showingAll = false,
|
||||||
onDeleteAll
|
onDeleteAll,
|
||||||
|
isFileSupported
|
||||||
}: FileGridProps) => {
|
}: FileGridProps) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const [searchTerm, setSearchTerm] = useState("");
|
const [searchTerm, setSearchTerm] = useState("");
|
||||||
@ -123,16 +125,18 @@ const FileGrid = ({
|
|||||||
{displayFiles.map((file, idx) => {
|
{displayFiles.map((file, idx) => {
|
||||||
const fileId = file.id || file.name;
|
const fileId = file.id || file.name;
|
||||||
const originalIdx = files.findIndex(f => (f.id || f.name) === fileId);
|
const originalIdx = files.findIndex(f => (f.id || f.name) === fileId);
|
||||||
|
const supported = isFileSupported ? isFileSupported(file.name) : true;
|
||||||
return (
|
return (
|
||||||
<FileCard
|
<FileCard
|
||||||
key={fileId + idx}
|
key={fileId + idx}
|
||||||
file={file}
|
file={file}
|
||||||
onRemove={onRemove ? () => onRemove(originalIdx) : undefined}
|
onRemove={onRemove ? () => onRemove(originalIdx) : undefined}
|
||||||
onDoubleClick={onDoubleClick ? () => onDoubleClick(file) : undefined}
|
onDoubleClick={onDoubleClick && supported ? () => onDoubleClick(file) : undefined}
|
||||||
onView={onView ? () => onView(file) : undefined}
|
onView={onView && supported ? () => onView(file) : undefined}
|
||||||
onEdit={onEdit ? () => onEdit(file) : undefined}
|
onEdit={onEdit && supported ? () => onEdit(file) : undefined}
|
||||||
isSelected={selectedFiles.includes(fileId)}
|
isSelected={selectedFiles.includes(fileId)}
|
||||||
onSelect={onSelect ? () => onSelect(fileId) : undefined}
|
onSelect={onSelect && supported ? () => onSelect(fileId) : undefined}
|
||||||
|
isSupported={supported}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
|
@ -5,6 +5,7 @@ import UploadFileIcon from '@mui/icons-material/UploadFile';
|
|||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { fileStorage } from '../../services/fileStorage';
|
import { fileStorage } from '../../services/fileStorage';
|
||||||
import { FileWithUrl } from '../../types/file';
|
import { FileWithUrl } from '../../types/file';
|
||||||
|
import { detectFileExtension } from '../../utils/fileUtils';
|
||||||
import FileGrid from './FileGrid';
|
import FileGrid from './FileGrid';
|
||||||
import MultiSelectControls from './MultiSelectControls';
|
import MultiSelectControls from './MultiSelectControls';
|
||||||
import { useFileManager } from '../../hooks/useFileManager';
|
import { useFileManager } from '../../hooks/useFileManager';
|
||||||
@ -20,6 +21,7 @@ interface FileUploadSelectorProps {
|
|||||||
onFileSelect?: (file: File) => void;
|
onFileSelect?: (file: File) => void;
|
||||||
onFilesSelect: (files: File[]) => void;
|
onFilesSelect: (files: File[]) => void;
|
||||||
accept?: string[];
|
accept?: string[];
|
||||||
|
supportedExtensions?: string[]; // Extensions this tool supports (e.g., ['pdf', 'jpg', 'png'])
|
||||||
|
|
||||||
// Loading state
|
// Loading state
|
||||||
loading?: boolean;
|
loading?: boolean;
|
||||||
@ -38,6 +40,7 @@ const FileUploadSelector = ({
|
|||||||
onFileSelect,
|
onFileSelect,
|
||||||
onFilesSelect,
|
onFilesSelect,
|
||||||
accept = ["application/pdf", "application/zip", "application/x-zip-compressed"],
|
accept = ["application/pdf", "application/zip", "application/x-zip-compressed"],
|
||||||
|
supportedExtensions = ["pdf"], // Default to PDF only for most tools
|
||||||
loading = false,
|
loading = false,
|
||||||
disabled = false,
|
disabled = false,
|
||||||
showRecentFiles = true,
|
showRecentFiles = true,
|
||||||
@ -51,6 +54,12 @@ const FileUploadSelector = ({
|
|||||||
|
|
||||||
const { loadRecentFiles, handleRemoveFile, storeFile, convertToFile, createFileSelectionHandlers } = useFileManager();
|
const { loadRecentFiles, handleRemoveFile, storeFile, convertToFile, createFileSelectionHandlers } = useFileManager();
|
||||||
|
|
||||||
|
// Utility function to check if a file extension is supported
|
||||||
|
const isFileSupported = useCallback((fileName: string): boolean => {
|
||||||
|
const extension = detectFileExtension(fileName);
|
||||||
|
return extension ? supportedExtensions.includes(extension) : false;
|
||||||
|
}, [supportedExtensions]);
|
||||||
|
|
||||||
const refreshRecentFiles = useCallback(async () => {
|
const refreshRecentFiles = useCallback(async () => {
|
||||||
const files = await loadRecentFiles();
|
const files = await loadRecentFiles();
|
||||||
setRecentFiles(files);
|
setRecentFiles(files);
|
||||||
@ -227,6 +236,7 @@ const FileUploadSelector = ({
|
|||||||
selectedFiles={selectedFiles}
|
selectedFiles={selectedFiles}
|
||||||
showSearch={true}
|
showSearch={true}
|
||||||
showSort={true}
|
showSort={true}
|
||||||
|
isFileSupported={isFileSupported}
|
||||||
onDeleteAll={async () => {
|
onDeleteAll={async () => {
|
||||||
await Promise.all(recentFiles.map(async (file) => {
|
await Promise.all(recentFiles.map(async (file) => {
|
||||||
await fileStorage.deleteFile(file.id || file.name);
|
await fileStorage.deleteFile(file.id || file.name);
|
||||||
|
@ -64,20 +64,35 @@ const ConvertSettings = ({
|
|||||||
|
|
||||||
// Enhanced FROM options with endpoint availability
|
// Enhanced FROM options with endpoint availability
|
||||||
const enhancedFromOptions = useMemo(() => {
|
const enhancedFromOptions = useMemo(() => {
|
||||||
return FROM_FORMAT_OPTIONS.map(option => {
|
const baseOptions = FROM_FORMAT_OPTIONS.map(option => {
|
||||||
// Check if this source format has any available conversions
|
// Check if this source format has any available conversions
|
||||||
const availableConversions = getAvailableToExtensions(option.value) || [];
|
const availableConversions = getAvailableToExtensions(option.value) || [];
|
||||||
const hasAvailableConversions = availableConversions.some(targetOption =>
|
const hasAvailableConversions = availableConversions.some(targetOption =>
|
||||||
isConversionAvailable(option.value, targetOption.value)
|
isConversionAvailable(option.value, targetOption.value)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...option,
|
...option,
|
||||||
enabled: hasAvailableConversions
|
enabled: hasAvailableConversions
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
}, [getAvailableToExtensions, endpointStatus]);
|
|
||||||
|
// Add dynamic format option if current selection is a file-<extension> format
|
||||||
|
if (parameters.fromExtension && parameters.fromExtension.startsWith('file-')) {
|
||||||
|
const extension = parameters.fromExtension.replace('file-', '');
|
||||||
|
const dynamicOption = {
|
||||||
|
value: parameters.fromExtension,
|
||||||
|
label: extension.toUpperCase(),
|
||||||
|
group: 'File',
|
||||||
|
enabled: true
|
||||||
|
};
|
||||||
|
|
||||||
|
// Add the dynamic option at the beginning
|
||||||
|
return [dynamicOption, ...baseOptions];
|
||||||
|
}
|
||||||
|
|
||||||
|
return baseOptions;
|
||||||
|
}, [getAvailableToExtensions, endpointStatus, parameters.fromExtension]);
|
||||||
|
|
||||||
// Enhanced TO options with endpoint availability
|
// Enhanced TO options with endpoint availability
|
||||||
const enhancedToOptions = useMemo(() => {
|
const enhancedToOptions = useMemo(() => {
|
||||||
|
@ -93,15 +93,18 @@ export const useConvertParameters = (): ConvertParametersHook => {
|
|||||||
|
|
||||||
if (!fromExtension || !toExtension) return false;
|
if (!fromExtension || !toExtension) return false;
|
||||||
|
|
||||||
// Check if conversion is supported
|
// Handle dynamic format identifiers (file-<extension>)
|
||||||
const supportedToExtensions = CONVERSION_MATRIX[fromExtension];
|
let supportedToExtensions: string[] = [];
|
||||||
if (!supportedToExtensions || !supportedToExtensions.includes(toExtension)) {
|
if (fromExtension.startsWith('file-')) {
|
||||||
return false;
|
// Dynamic format - use 'any' conversion options
|
||||||
|
supportedToExtensions = CONVERSION_MATRIX['any'] || [];
|
||||||
|
} else {
|
||||||
|
// Regular format - check conversion matrix
|
||||||
|
supportedToExtensions = CONVERSION_MATRIX[fromExtension] || [];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Additional validation for image conversions
|
if (!supportedToExtensions.includes(toExtension)) {
|
||||||
if (['png', 'jpg'].includes(toExtension)) {
|
return false;
|
||||||
return parameters.imageOptions.dpi >= 72 && parameters.imageOptions.dpi <= 600;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -123,6 +126,12 @@ export const useConvertParameters = (): ConvertParametersHook => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Handle dynamic format identifiers (file-<extension>)
|
||||||
|
if (fromExtension.startsWith('file-')) {
|
||||||
|
// Dynamic format - use file-to-pdf endpoint
|
||||||
|
return 'file-to-pdf';
|
||||||
|
}
|
||||||
|
|
||||||
return getEndpointNameUtil(fromExtension, toExtension);
|
return getEndpointNameUtil(fromExtension, toExtension);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -142,12 +151,27 @@ export const useConvertParameters = (): ConvertParametersHook => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Handle dynamic format identifiers (file-<extension>)
|
||||||
|
if (fromExtension.startsWith('file-')) {
|
||||||
|
// Dynamic format - use file-to-pdf endpoint
|
||||||
|
return '/api/v1/convert/file/pdf';
|
||||||
|
}
|
||||||
|
|
||||||
return getEndpointUrl(fromExtension, toExtension);
|
return getEndpointUrl(fromExtension, toExtension);
|
||||||
};
|
};
|
||||||
|
|
||||||
const getAvailableToExtensions = (fromExtension: string) => {
|
const getAvailableToExtensions = (fromExtension: string) => {
|
||||||
if (!fromExtension) return [];
|
if (!fromExtension) return [];
|
||||||
|
|
||||||
|
// Handle dynamic format identifiers (file-<extension>)
|
||||||
|
if (fromExtension.startsWith('file-')) {
|
||||||
|
// Dynamic format - use 'any' conversion options (file-to-pdf)
|
||||||
|
const supportedExtensions = CONVERSION_MATRIX['any'] || [];
|
||||||
|
return TO_FORMAT_OPTIONS.filter(option =>
|
||||||
|
supportedExtensions.includes(option.value)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
let supportedExtensions = CONVERSION_MATRIX[fromExtension] || [];
|
let supportedExtensions = CONVERSION_MATRIX[fromExtension] || [];
|
||||||
|
|
||||||
// If no explicit conversion exists, but file-to-pdf might be available,
|
// If no explicit conversion exists, but file-to-pdf might be available,
|
||||||
@ -180,9 +204,13 @@ export const useConvertParameters = (): ConvertParametersHook => {
|
|||||||
let fromExt = detectedExt;
|
let fromExt = detectedExt;
|
||||||
let availableTargets = detectedExt ? CONVERSION_MATRIX[detectedExt] || [] : [];
|
let availableTargets = detectedExt ? CONVERSION_MATRIX[detectedExt] || [] : [];
|
||||||
|
|
||||||
// If no explicit conversion exists for this file type, fall back to 'any'
|
// If no explicit conversion exists for this file type, create a dynamic format entry
|
||||||
// which will attempt file-to-pdf conversion if available
|
// and fall back to 'any' conversion logic for the actual endpoint
|
||||||
if (availableTargets.length === 0) {
|
if (availableTargets.length === 0 && detectedExt) {
|
||||||
|
fromExt = `file-${detectedExt}`; // Create dynamic format identifier
|
||||||
|
availableTargets = CONVERSION_MATRIX['any'] || [];
|
||||||
|
} else if (availableTargets.length === 0) {
|
||||||
|
// No extension detected - fall back to 'any'
|
||||||
fromExt = 'any';
|
fromExt = 'any';
|
||||||
availableTargets = CONVERSION_MATRIX['any'] || [];
|
availableTargets = CONVERSION_MATRIX['any'] || [];
|
||||||
}
|
}
|
||||||
|
@ -35,7 +35,25 @@ const toolDefinitions: Record<string, ToolDefinition> = {
|
|||||||
maxFiles: -1,
|
maxFiles: -1,
|
||||||
category: "manipulation",
|
category: "manipulation",
|
||||||
description: "Change to and from PDF and other formats",
|
description: "Change to and from PDF and other formats",
|
||||||
endpoints: ["pdf-to-img", "img-to-pdf", "pdf-to-word", "pdf-to-presentation", "pdf-to-text", "pdf-to-html", "pdf-to-xml", "html-to-pdf", "markdown-to-pdf", "file-to-pdf"]
|
endpoints: ["pdf-to-img", "img-to-pdf", "pdf-to-word", "pdf-to-presentation", "pdf-to-text", "pdf-to-html", "pdf-to-xml", "html-to-pdf", "markdown-to-pdf", "file-to-pdf"],
|
||||||
|
supportedFormats: [
|
||||||
|
// Microsoft Office
|
||||||
|
"doc", "docx", "dot", "dotx", "csv", "xls", "xlsx", "xlt", "xltx", "slk", "dif", "ppt", "pptx",
|
||||||
|
// OpenDocument
|
||||||
|
"odt", "ott", "ods", "ots", "odp", "otp", "odg", "otg",
|
||||||
|
// Text formats
|
||||||
|
"txt", "text", "xml", "rtf", "html", "lwp", "md",
|
||||||
|
// Images
|
||||||
|
"bmp", "gif", "jpeg", "jpg", "png", "tif", "tiff", "pbm", "pgm", "ppm", "ras", "xbm", "xpm", "svg", "svm", "wmf", "webp",
|
||||||
|
// StarOffice
|
||||||
|
"sda", "sdc", "sdd", "sdw", "stc", "std", "sti", "stw", "sxd", "sxg", "sxi", "sxw",
|
||||||
|
// Email formats
|
||||||
|
"eml",
|
||||||
|
// Archive formats
|
||||||
|
"zip",
|
||||||
|
// Other
|
||||||
|
"dbf", "fods", "vsd", "vor", "vor3", "vor4", "uop", "pct", "ps", "pdf"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
swagger: {
|
swagger: {
|
||||||
id: "swagger",
|
id: "swagger",
|
||||||
|
@ -197,6 +197,7 @@ function HomePageContent() {
|
|||||||
files.forEach(addToActiveFiles);
|
files.forEach(addToActiveFiles);
|
||||||
}}
|
}}
|
||||||
accept={["*/*"]}
|
accept={["*/*"]}
|
||||||
|
supportedExtensions={selectedTool?.supportedFormats || ["pdf"]}
|
||||||
loading={false}
|
loading={false}
|
||||||
showRecentFiles={true}
|
showRecentFiles={true}
|
||||||
maxRecentFiles={8}
|
maxRecentFiles={8}
|
||||||
@ -207,6 +208,7 @@ function HomePageContent() {
|
|||||||
toolMode={!!selectedToolKey}
|
toolMode={!!selectedToolKey}
|
||||||
showUpload={true}
|
showUpload={true}
|
||||||
showBulkActions={!selectedToolKey}
|
showBulkActions={!selectedToolKey}
|
||||||
|
supportedExtensions={selectedTool?.supportedFormats || ["pdf"]}
|
||||||
{...(!selectedToolKey && {
|
{...(!selectedToolKey && {
|
||||||
onOpenPageEditor: (file) => {
|
onOpenPageEditor: (file) => {
|
||||||
handleViewChange("pageEditor");
|
handleViewChange("pageEditor");
|
||||||
@ -287,6 +289,7 @@ function HomePageContent() {
|
|||||||
files.forEach(addToActiveFiles);
|
files.forEach(addToActiveFiles);
|
||||||
}}
|
}}
|
||||||
accept={["*/*"]}
|
accept={["*/*"]}
|
||||||
|
supportedExtensions={selectedTool?.supportedFormats || ["pdf"]}
|
||||||
loading={false}
|
loading={false}
|
||||||
showRecentFiles={true}
|
showRecentFiles={true}
|
||||||
maxRecentFiles={8}
|
maxRecentFiles={8}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user