feat: implement drag & drop for audio loading and decrease upload icon
Changes: - Reduced upload icon size from h-8 w-8 to h-6 w-6 (smaller, cleaner) - Implemented full drag & drop functionality for audio files - Shows visual feedback when dragging: blue border, primary color highlight - Changes text to "Drop audio file here" when dragging over - Validates dropped file is audio type before processing - Updated message from "coming soon" to active "or drag & drop" 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -192,6 +192,50 @@ export function Track({
|
||||
fileInputRef.current?.click();
|
||||
};
|
||||
|
||||
const [isDragging, setIsDragging] = React.useState(false);
|
||||
|
||||
const handleDragOver = (e: React.DragEvent) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
setIsDragging(true);
|
||||
};
|
||||
|
||||
const handleDragLeave = (e: React.DragEvent) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
setIsDragging(false);
|
||||
};
|
||||
|
||||
const handleDrop = async (e: React.DragEvent) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
setIsDragging(false);
|
||||
|
||||
const file = e.dataTransfer.files?.[0];
|
||||
if (!file || !onLoadAudio) return;
|
||||
|
||||
// Check if it's an audio file
|
||||
if (!file.type.startsWith('audio/')) {
|
||||
console.warn('Dropped file is not an audio file');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const arrayBuffer = await file.arrayBuffer();
|
||||
const audioContext = new AudioContext();
|
||||
const audioBuffer = await audioContext.decodeAudioData(arrayBuffer);
|
||||
onLoadAudio(audioBuffer);
|
||||
|
||||
// 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);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to load audio file:', error);
|
||||
}
|
||||
};
|
||||
|
||||
const trackHeight = track.collapsed ? 48 : track.height;
|
||||
|
||||
return (
|
||||
@@ -354,15 +398,21 @@ export function Track({
|
||||
) : (
|
||||
<>
|
||||
<div
|
||||
className="absolute inset-0 flex flex-col items-center justify-center text-sm text-muted-foreground hover:text-foreground hover:bg-accent/50 transition-colors cursor-pointer group"
|
||||
className={cn(
|
||||
"absolute inset-0 flex flex-col items-center justify-center text-sm text-muted-foreground hover:text-foreground transition-colors cursor-pointer group",
|
||||
isDragging ? "bg-primary/20 text-primary border-2 border-primary border-dashed" : "hover:bg-accent/50"
|
||||
)}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
handleLoadAudioClick();
|
||||
}}
|
||||
onDragOver={handleDragOver}
|
||||
onDragLeave={handleDragLeave}
|
||||
onDrop={handleDrop}
|
||||
>
|
||||
<Upload className="h-8 w-8 mb-2 opacity-50 group-hover:opacity-100" />
|
||||
<p>Click to load audio file</p>
|
||||
<p className="text-xs opacity-75 mt-1">or drag & drop (coming soon)</p>
|
||||
<Upload className="h-6 w-6 mb-2 opacity-50 group-hover:opacity-100" />
|
||||
<p>{isDragging ? 'Drop audio file here' : 'Click to load audio file'}</p>
|
||||
<p className="text-xs opacity-75 mt-1">or drag & drop</p>
|
||||
</div>
|
||||
<input
|
||||
ref={fileInputRef}
|
||||
|
||||
Reference in New Issue
Block a user