feat: integrate ImportDialog into file upload flow
Now when users upload an audio file, they see the ImportDialog with options: **User Flow:** 1. User selects audio file (click or drag-drop) 2. File is pre-decoded to extract metadata (sample rate, channels) 3. ImportDialog shows with file info and import options: - Convert to Mono (if stereo/multi-channel) - Resample Audio (44.1kHz - 192kHz) - Normalize on Import 4. User clicks Import (or Cancel) 5. File is imported with selected transformations applied 6. Track name auto-updates to filename **Track.tsx Changes:** - Added import dialog state (showImportDialog, pendingFile, fileMetadata) - Updated handleFileChange to show dialog instead of direct import - Added handleImport to process file with user-selected options - Added handleImportCancel to dismiss dialog - Renders ImportDialog when showImportDialog is true - Logs imported audio metadata to console Now users can see and control all import transformations! 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -15,6 +15,8 @@ import { createAutomationPoint } from '@/lib/audio/automation/utils';
|
||||
import { createAutomationLane } from '@/lib/audio/automation-utils';
|
||||
import { EffectDevice } from '@/components/effects/EffectDevice';
|
||||
import { EffectBrowser } from '@/components/effects/EffectBrowser';
|
||||
import { ImportDialog } from '@/components/dialogs/ImportDialog';
|
||||
import { importAudioFile, type ImportOptions } from '@/lib/audio/decoder';
|
||||
|
||||
export interface TrackProps {
|
||||
track: TrackType;
|
||||
@@ -86,6 +88,11 @@ export function Track({
|
||||
const resizeStartRef = React.useRef({ y: 0, height: 0 });
|
||||
const [effectBrowserOpen, setEffectBrowserOpen] = React.useState(false);
|
||||
|
||||
// Import dialog state
|
||||
const [showImportDialog, setShowImportDialog] = React.useState(false);
|
||||
const [pendingFile, setPendingFile] = React.useState<File | null>(null);
|
||||
const [fileMetadata, setFileMetadata] = React.useState<{ sampleRate?: number; channels?: number }>({});
|
||||
|
||||
// Selection state
|
||||
const [isSelecting, setIsSelecting] = React.useState(false);
|
||||
const [selectionStart, setSelectionStart] = React.useState<number | null>(null);
|
||||
@@ -452,24 +459,55 @@ export function Track({
|
||||
if (!file || !onLoadAudio) return;
|
||||
|
||||
try {
|
||||
// Decode to get basic metadata before showing dialog
|
||||
const arrayBuffer = await file.arrayBuffer();
|
||||
const audioContext = new AudioContext();
|
||||
const audioBuffer = await audioContext.decodeAudioData(arrayBuffer);
|
||||
onLoadAudio(audioBuffer);
|
||||
const tempBuffer = await audioContext.decodeAudioData(arrayBuffer);
|
||||
|
||||
// Update track name to filename if it's still default
|
||||
if (track.name === 'New Track' || track.name === 'Untitled Track') {
|
||||
const fileName = file.name.replace(/\.[^/.]+$/, '');
|
||||
onNameChange(fileName);
|
||||
}
|
||||
// Set metadata and show import dialog
|
||||
setFileMetadata({
|
||||
sampleRate: tempBuffer.sampleRate,
|
||||
channels: tempBuffer.numberOfChannels,
|
||||
});
|
||||
setPendingFile(file);
|
||||
setShowImportDialog(true);
|
||||
} catch (error) {
|
||||
console.error('Failed to load audio file:', error);
|
||||
console.error('Failed to read audio file metadata:', error);
|
||||
}
|
||||
|
||||
// Reset input
|
||||
e.target.value = '';
|
||||
};
|
||||
|
||||
const handleImport = async (options: ImportOptions) => {
|
||||
if (!pendingFile || !onLoadAudio) return;
|
||||
|
||||
try {
|
||||
setShowImportDialog(false);
|
||||
const { buffer, metadata } = await importAudioFile(pendingFile, options);
|
||||
onLoadAudio(buffer);
|
||||
|
||||
// Update track name to filename if it's still default
|
||||
if (track.name === 'New Track' || track.name === 'Untitled Track') {
|
||||
const fileName = metadata.fileName.replace(/\.[^/.]+$/, '');
|
||||
onNameChange(fileName);
|
||||
}
|
||||
|
||||
console.log('Audio imported:', metadata);
|
||||
} catch (error) {
|
||||
console.error('Failed to import audio file:', error);
|
||||
} finally {
|
||||
setPendingFile(null);
|
||||
setFileMetadata({});
|
||||
}
|
||||
};
|
||||
|
||||
const handleImportCancel = () => {
|
||||
setShowImportDialog(false);
|
||||
setPendingFile(null);
|
||||
setFileMetadata({});
|
||||
};
|
||||
|
||||
const handleLoadAudioClick = () => {
|
||||
fileInputRef.current?.click();
|
||||
};
|
||||
@@ -1005,6 +1043,17 @@ export function Track({
|
||||
<div className="absolute inset-x-0 bottom-0 h-px bg-border group-hover:bg-primary transition-colors duration-200" />
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Import Dialog */}
|
||||
{showImportDialog && pendingFile && (
|
||||
<ImportDialog
|
||||
fileName={pendingFile.name}
|
||||
originalSampleRate={fileMetadata.sampleRate}
|
||||
originalChannels={fileMetadata.channels}
|
||||
onImport={handleImport}
|
||||
onCancel={handleImportCancel}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user