feat: add comprehensive conversion options and enhanced UI
This major update adds powerful format-specific controls, quality presets, file metadata display, and enhanced progress feedback to significantly improve the user experience. New Components: - ConversionOptionsPanel: Format-specific controls with collapsible advanced options - Video options: codec selection (H.264, H.265, VP8, VP9), bitrate, resolution, FPS - Audio options: codec selection, bitrate, sample rate, channels - Image options: quality slider, width/height controls - Quality Presets: One-click presets (High Quality, Balanced, Small File, Web Optimized) - FileInfo: Displays file metadata including size, duration, dimensions - Slider: Reusable slider component for quality/bitrate controls - Select: Reusable dropdown component for codec/format selection Enhanced Features: - ConversionPreview improvements: - Real-time elapsed time display - Estimated time remaining calculation - File size comparison (input vs output with % reduction/increase) - Better visual status indicators with icons - Enhanced loading states with detailed progress - FileConverter integration: - Passes conversion options to converter services - Manages conversion options state - Resets options on file reset UI/UX Improvements: - Format-specific option panels that adapt to selected output format - Visual preset buttons with icons and descriptions - Collapsible advanced options to reduce clutter - Better progress feedback with time estimates - File size comparison badges showing compression results - Smooth animations and transitions (existing animations already in place) - Responsive design for all new components Technical Details: - Options are properly typed and integrated with ConversionOptions interface - All components support disabled states during conversion - Preview component calculates speed and estimates remaining time - Metadata extraction for video/audio/image files using browser APIs - Proper cleanup of object URLs and timers User Benefits: - Power users can fine-tune codec, bitrate, resolution settings - Beginners can use quality presets with confidence - Better understanding of conversion progress and file size impact - Informed decisions with file metadata display - Professional-grade control over output quality 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -7,6 +7,8 @@ import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/com
|
||||
import { FileUpload } from './FileUpload';
|
||||
import { FormatSelector } from './FormatSelector';
|
||||
import { ConversionPreview } from './ConversionPreview';
|
||||
import { ConversionOptionsPanel } from './ConversionOptions';
|
||||
import { FileInfo } from './FileInfo';
|
||||
import { useToast } from '@/components/ui/Toast';
|
||||
import {
|
||||
SUPPORTED_FORMATS,
|
||||
@@ -17,7 +19,7 @@ import {
|
||||
import { convertWithFFmpeg } from '@/lib/converters/ffmpegService';
|
||||
import { convertWithImageMagick } from '@/lib/converters/imagemagickService';
|
||||
import { addToHistory } from '@/lib/storage/history';
|
||||
import type { ConversionJob, ConversionFormat } from '@/types/conversion';
|
||||
import type { ConversionJob, ConversionFormat, ConversionOptions } from '@/types/conversion';
|
||||
|
||||
export function FileConverter() {
|
||||
const { addToast } = useToast();
|
||||
@@ -27,6 +29,7 @@ export function FileConverter() {
|
||||
const [outputFormat, setOutputFormat] = React.useState<ConversionFormat | undefined>();
|
||||
const [compatibleFormats, setCompatibleFormats] = React.useState<ConversionFormat[]>([]);
|
||||
const [conversionJob, setConversionJob] = React.useState<ConversionJob | undefined>();
|
||||
const [conversionOptions, setConversionOptions] = React.useState<ConversionOptions>({});
|
||||
|
||||
// Detect input format when file is selected
|
||||
React.useEffect(() => {
|
||||
@@ -77,7 +80,7 @@ export function FileConverter() {
|
||||
inputFile: selectedFile,
|
||||
inputFormat,
|
||||
outputFormat,
|
||||
options: {},
|
||||
options: conversionOptions,
|
||||
status: 'loading',
|
||||
progress: 0,
|
||||
startTime: Date.now(),
|
||||
@@ -94,7 +97,7 @@ export function FileConverter() {
|
||||
|
||||
switch (outputFormat.converter) {
|
||||
case 'ffmpeg':
|
||||
result = await convertWithFFmpeg(selectedFile, outputFormat.extension, {}, (progress) => {
|
||||
result = await convertWithFFmpeg(selectedFile, outputFormat.extension, conversionOptions, (progress) => {
|
||||
setConversionJob((prev) => prev && { ...prev, progress });
|
||||
});
|
||||
break;
|
||||
@@ -103,7 +106,7 @@ export function FileConverter() {
|
||||
result = await convertWithImageMagick(
|
||||
selectedFile,
|
||||
outputFormat.extension,
|
||||
{},
|
||||
conversionOptions,
|
||||
(progress) => {
|
||||
setConversionJob((prev) => prev && { ...prev, progress });
|
||||
}
|
||||
@@ -165,6 +168,7 @@ export function FileConverter() {
|
||||
setOutputFormat(undefined);
|
||||
setCompatibleFormats([]);
|
||||
setConversionJob(undefined);
|
||||
setConversionOptions({});
|
||||
};
|
||||
|
||||
const isConvertDisabled =
|
||||
@@ -189,6 +193,11 @@ export function FileConverter() {
|
||||
disabled={conversionJob?.status === 'processing' || conversionJob?.status === 'loading'}
|
||||
/>
|
||||
|
||||
{/* File Info */}
|
||||
{selectedFile && inputFormat && (
|
||||
<FileInfo file={selectedFile} format={inputFormat} />
|
||||
)}
|
||||
|
||||
{/* Format selection */}
|
||||
{inputFormat && compatibleFormats.length > 0 && (
|
||||
<div className="grid grid-cols-1 md:grid-cols-[1fr_auto_1fr] gap-4 items-start">
|
||||
@@ -217,6 +226,17 @@ export function FileConverter() {
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Conversion Options */}
|
||||
{inputFormat && outputFormat && (
|
||||
<ConversionOptionsPanel
|
||||
inputFormat={inputFormat}
|
||||
outputFormat={outputFormat}
|
||||
options={conversionOptions}
|
||||
onOptionsChange={setConversionOptions}
|
||||
disabled={conversionJob?.status === 'processing' || conversionJob?.status === 'loading'}
|
||||
/>
|
||||
)}
|
||||
|
||||
{/* Convert button */}
|
||||
{inputFormat && outputFormat && (
|
||||
<div className="flex gap-3">
|
||||
|
||||
Reference in New Issue
Block a user