Improves sound placement and preview logic
Refines the sound placement logic in the sequencer to ensure sounds are placed correctly within track boundaries. It restricts sound placement to the track duration, preventing sounds from being placed out of bounds. Enhances the drag preview by visually indicating invalid placement positions with a red border and "Invalid" label. Also extracts duration and size formatting into separate utility functions for better code organization.
This commit is contained in:
@@ -157,26 +157,38 @@ function TrackRow({ track, duration, zoom, isPlaying, currentTime, draggedItem,
|
||||
</div>
|
||||
|
||||
{/* Precise drag preview */}
|
||||
{draggedItem && dragOverInfo && dragOverInfo.trackId === track.id && (
|
||||
<div
|
||||
className="absolute top-2 bottom-2 border-2 border-dashed border-primary/60 bg-primary/10 rounded pointer-events-none z-10 flex items-center px-2"
|
||||
style={{
|
||||
left: `${dragOverInfo.x}px`,
|
||||
width: `${Math.max(60,
|
||||
draggedItem.type === 'sound'
|
||||
? (draggedItem.sound.duration / 1000) * zoom
|
||||
: draggedItem.duration * zoom
|
||||
)}px`,
|
||||
}}
|
||||
>
|
||||
<div className="text-xs text-primary/80 truncate font-medium">
|
||||
{draggedItem.type === 'sound'
|
||||
? (draggedItem.sound.name || draggedItem.sound.filename)
|
||||
: draggedItem.name
|
||||
}
|
||||
{draggedItem && dragOverInfo && dragOverInfo.trackId === track.id && (() => {
|
||||
const soundDuration = draggedItem.type === 'sound'
|
||||
? draggedItem.sound.duration / 1000 // Convert ms to seconds
|
||||
: draggedItem.duration
|
||||
const startTime = dragOverInfo.x / zoom
|
||||
const endTime = startTime + soundDuration
|
||||
const isValidPosition = startTime >= 0 && endTime <= duration
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`absolute top-2 bottom-2 border-2 border-dashed rounded pointer-events-none z-10 flex items-center px-2 ${
|
||||
isValidPosition
|
||||
? 'border-primary/60 bg-primary/10'
|
||||
: 'border-red-500/60 bg-red-500/10'
|
||||
}`}
|
||||
style={{
|
||||
left: `${Math.max(0, dragOverInfo.x)}px`,
|
||||
width: `${Math.max(60, soundDuration * zoom)}px`,
|
||||
}}
|
||||
>
|
||||
<div className={`text-xs truncate font-medium ${
|
||||
isValidPosition ? 'text-primary/80' : 'text-red-500/80'
|
||||
}`}>
|
||||
{draggedItem.type === 'sound'
|
||||
? (draggedItem.sound.name || draggedItem.sound.filename)
|
||||
: draggedItem.name
|
||||
}
|
||||
{!isValidPosition && ' (Invalid)'}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
)
|
||||
})()}
|
||||
|
||||
{/* Playhead */}
|
||||
{isPlaying && (
|
||||
|
||||
@@ -21,6 +21,8 @@ import {
|
||||
} from 'lucide-react'
|
||||
import { useCallback, useEffect, useState } from 'react'
|
||||
import { toast } from 'sonner'
|
||||
import { formatDuration } from '@/utils/format-duration'
|
||||
import { formatSize } from '@/utils/format-size'
|
||||
|
||||
interface DraggableSoundProps {
|
||||
sound: Sound
|
||||
@@ -43,18 +45,6 @@ function DraggableSound({ sound }: DraggableSoundProps) {
|
||||
// Don't apply transform to prevent layout shift - DragOverlay handles the visual feedback
|
||||
const style = undefined
|
||||
|
||||
const formatDuration = (ms: number): string => {
|
||||
const seconds = Math.floor(ms / 1000)
|
||||
const mins = Math.floor(seconds / 60)
|
||||
const secs = seconds % 60
|
||||
return `${mins}:${secs.toString().padStart(2, '0')}`
|
||||
}
|
||||
|
||||
const formatFileSize = (bytes: number): string => {
|
||||
const mb = bytes / (1024 * 1024)
|
||||
return `${mb.toFixed(1)}MB`
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
ref={setNodeRef}
|
||||
@@ -81,7 +71,7 @@ function DraggableSound({ sound }: DraggableSoundProps) {
|
||||
<div className="flex items-center gap-2 text-xs text-muted-foreground mt-1">
|
||||
<span>{formatDuration(sound.duration)}</span>
|
||||
<span>•</span>
|
||||
<span>{formatFileSize(sound.size)}</span>
|
||||
<span>{formatSize(sound.size)}</span>
|
||||
{sound.play_count > 0 && (
|
||||
<>
|
||||
<span>•</span>
|
||||
|
||||
Reference in New Issue
Block a user