improved zone handling
This commit is contained in:
@ -3,7 +3,14 @@ import { useEditorStore } from '../store/editorStore';
|
||||
import { Virtuoso } from 'react-virtuoso';
|
||||
import { Scissors, VolumeX, SlidersHorizontal, RotateCcw } from 'lucide-react';
|
||||
|
||||
export default function TranscriptEditor() {
|
||||
interface TranscriptEditorProps {
|
||||
cutMode: boolean;
|
||||
muteMode: boolean;
|
||||
gainMode: boolean;
|
||||
gainModeDb: number;
|
||||
}
|
||||
|
||||
export default function TranscriptEditor({ cutMode, muteMode, gainMode, gainModeDb }: TranscriptEditorProps) {
|
||||
const words = useEditorStore((s) => s.words);
|
||||
const segments = useEditorStore((s) => s.segments);
|
||||
const deletedRanges = useEditorStore((s) => s.deletedRanges);
|
||||
@ -26,6 +33,8 @@ export default function TranscriptEditor() {
|
||||
const selectionStart = useRef<number | null>(null);
|
||||
const wasDragging = useRef(false);
|
||||
const virtuosoRef = useRef<any>(null);
|
||||
const zoneDragStart = useRef<number | null>(null);
|
||||
const [zoneDragRange, setZoneDragRange] = useState<{ start: number; end: number } | null>(null);
|
||||
|
||||
const deletedSet = useMemo(() => {
|
||||
const s = new Set<number>();
|
||||
@ -74,6 +83,14 @@ export default function TranscriptEditor() {
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (cutMode || muteMode || gainMode) {
|
||||
zoneDragStart.current = index;
|
||||
setZoneDragRange({ start: index, end: index });
|
||||
selectionStart.current = null;
|
||||
return;
|
||||
}
|
||||
|
||||
wasDragging.current = false;
|
||||
if (e.shiftKey && selectedWordIndices.length > 0) {
|
||||
const first = selectedWordIndices[0];
|
||||
@ -87,12 +104,19 @@ export default function TranscriptEditor() {
|
||||
setSelectedWordIndices([index]);
|
||||
}
|
||||
},
|
||||
[words, selectedWordIndices, setSelectedWordIndices],
|
||||
[words, selectedWordIndices, setSelectedWordIndices, cutMode, muteMode, gainMode],
|
||||
);
|
||||
|
||||
const handleWordMouseEnter = useCallback(
|
||||
(index: number) => {
|
||||
setHoveredWordIndex(index);
|
||||
if (zoneDragStart.current !== null) {
|
||||
setZoneDragRange({
|
||||
start: Math.min(zoneDragStart.current, index),
|
||||
end: Math.max(zoneDragStart.current, index),
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (selectionStart.current !== null) {
|
||||
wasDragging.current = true;
|
||||
const start = Math.min(selectionStart.current, index);
|
||||
@ -106,8 +130,19 @@ export default function TranscriptEditor() {
|
||||
);
|
||||
|
||||
const handleMouseUp = useCallback(() => {
|
||||
if (zoneDragStart.current !== null && zoneDragRange) {
|
||||
const startWord = words[zoneDragRange.start];
|
||||
const endWord = words[zoneDragRange.end];
|
||||
if (startWord && endWord) {
|
||||
if (cutMode) addCutRange(startWord.start, endWord.end);
|
||||
if (muteMode) addMuteRange(startWord.start, endWord.end);
|
||||
if (gainMode) addGainRange(startWord.start, endWord.end, gainModeDb);
|
||||
}
|
||||
}
|
||||
zoneDragStart.current = null;
|
||||
setZoneDragRange(null);
|
||||
selectionStart.current = null;
|
||||
}, []);
|
||||
}, [zoneDragRange, words, cutMode, muteMode, gainMode, gainModeDb, addCutRange, addMuteRange, addGainRange]);
|
||||
|
||||
const handleClickOutside = useCallback(
|
||||
(e: React.MouseEvent) => {
|
||||
@ -148,8 +183,8 @@ export default function TranscriptEditor() {
|
||||
const sorted = [...selectedWordIndices].sort((a, b) => a - b);
|
||||
const startTime = words[sorted[0]].start;
|
||||
const endTime = words[sorted[sorted.length - 1]].end;
|
||||
addGainRange(startTime, endTime, 3);
|
||||
}, [selectedWordIndices, words, addGainRange]);
|
||||
addGainRange(startTime, endTime, gainModeDb);
|
||||
}, [selectedWordIndices, words, addGainRange, gainModeDb]);
|
||||
|
||||
const getCutRangeForWord = useCallback(
|
||||
(wordIndex: number) => {
|
||||
@ -196,6 +231,9 @@ export default function TranscriptEditor() {
|
||||
const isSelected = selectedSet.has(globalIndex);
|
||||
const isActive = globalIndex === activeWordIndex;
|
||||
const isHovered = globalIndex === hoveredWordIndex;
|
||||
const isZoneDragSelected = zoneDragRange
|
||||
? globalIndex >= zoneDragRange.start && globalIndex <= zoneDragRange.end
|
||||
: false;
|
||||
const deletedRange = isDeleted ? getRangeForWord(globalIndex) : null;
|
||||
const cutRange = getCutRangeForWord(globalIndex);
|
||||
const muteRange = getMuteRangeForWord(globalIndex);
|
||||
@ -216,6 +254,9 @@ export default function TranscriptEditor() {
|
||||
${cutRange ? 'bg-red-500/20 text-red-100' : ''}
|
||||
${muteRange ? 'bg-blue-500/20 text-blue-100' : ''}
|
||||
${gainRange ? 'bg-amber-500/20 text-amber-100' : ''}
|
||||
${isZoneDragSelected && cutMode ? 'bg-red-500/30 ring-1 ring-red-400/60' : ''}
|
||||
${isZoneDragSelected && muteMode ? 'bg-blue-500/30 ring-1 ring-blue-400/60' : ''}
|
||||
${isZoneDragSelected && gainMode ? 'bg-amber-500/30 ring-1 ring-amber-400/60' : ''}
|
||||
${isSelected && !isDeleted && !cutRange && !muteRange && !gainRange ? 'bg-editor-word-selected text-white' : ''}
|
||||
${isActive && !isDeleted && !isSelected && !cutRange && !muteRange && !gainRange ? 'bg-editor-accent/20 text-editor-accent' : ''}
|
||||
${isHovered && !isDeleted && !isSelected && !isActive && !cutRange && !muteRange && !gainRange ? 'bg-editor-word-hover' : ''}
|
||||
@ -253,7 +294,7 @@ export default function TranscriptEditor() {
|
||||
</div>
|
||||
);
|
||||
},
|
||||
[segments, deletedSet, selectedSet, activeWordIndex, hoveredWordIndex, handleWordMouseDown, handleWordMouseEnter, setHoveredWordIndex, getRangeForWord, getCutRangeForWord, getMuteRangeForWord, getGainRangeForWord, restoreRange, removeCutRange, removeMuteRange, removeGainRange],
|
||||
[segments, deletedSet, selectedSet, activeWordIndex, hoveredWordIndex, handleWordMouseDown, handleWordMouseEnter, setHoveredWordIndex, getRangeForWord, getCutRangeForWord, getMuteRangeForWord, getGainRangeForWord, restoreRange, removeCutRange, removeMuteRange, removeGainRange, zoneDragRange, cutMode, muteMode, gainMode],
|
||||
);
|
||||
|
||||
return (
|
||||
@ -283,7 +324,7 @@ export default function TranscriptEditor() {
|
||||
className="flex items-center gap-1 px-2 py-1 text-xs bg-amber-500/20 text-amber-300 rounded hover:bg-amber-500/30 transition-colors"
|
||||
>
|
||||
<SlidersHorizontal className="w-3 h-3" />
|
||||
Gain (+3 dB)
|
||||
Gain ({gainModeDb > 0 ? '+' : ''}{gainModeDb.toFixed(1)} dB)
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user