added cut and mute zones
This commit is contained in:
@ -17,6 +17,8 @@ import {
|
||||
FolderSearch,
|
||||
FileInput,
|
||||
Save,
|
||||
Scissors,
|
||||
VolumeX,
|
||||
} from 'lucide-react';
|
||||
|
||||
const IS_ELECTRON = !!window.electronAPI;
|
||||
@ -35,15 +37,33 @@ export default function App() {
|
||||
setTranscription,
|
||||
setTranscribing,
|
||||
backendUrl,
|
||||
selectedWordIndices,
|
||||
addCutRange,
|
||||
addMuteRange,
|
||||
} = useEditorStore();
|
||||
|
||||
const [activePanel, setActivePanel] = useState<Panel>(null);
|
||||
const [manualPath, setManualPath] = useState('');
|
||||
const [whisperModel, setWhisperModel] = useState('base');
|
||||
const [cutMode, setCutMode] = useState(false);
|
||||
const [muteMode, setMuteMode] = useState(false);
|
||||
const fileInputRef = useRef<HTMLInputElement>(null);
|
||||
|
||||
useKeyboardShortcuts();
|
||||
|
||||
// Handle Escape key to exit cut/mute modes
|
||||
useEffect(() => {
|
||||
const handleKeyDown = (e: KeyboardEvent) => {
|
||||
if (e.key === 'Escape') {
|
||||
setCutMode(false);
|
||||
setMuteMode(false);
|
||||
}
|
||||
};
|
||||
|
||||
window.addEventListener('keydown', handleKeyDown);
|
||||
return () => window.removeEventListener('keydown', handleKeyDown);
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (IS_ELECTRON) {
|
||||
window.electronAPI!.getBackendUrl().then(setBackendUrl);
|
||||
@ -146,8 +166,33 @@ export default function App() {
|
||||
}
|
||||
};
|
||||
|
||||
const togglePanel = (panel: Panel) =>
|
||||
setActivePanel((prev) => (prev === panel ? null : panel));
|
||||
const handleCut = () => {
|
||||
if (selectedWordIndices.length > 0) {
|
||||
// If words are selected, apply cut immediately
|
||||
const sorted = [...selectedWordIndices].sort((a, b) => a - b);
|
||||
const startTime = words[sorted[0]].start;
|
||||
const endTime = words[sorted[sorted.length - 1]].end;
|
||||
addCutRange(startTime, endTime);
|
||||
} else {
|
||||
// Toggle cut mode
|
||||
setCutMode(!cutMode);
|
||||
setMuteMode(false); // Exit mute mode
|
||||
}
|
||||
};
|
||||
|
||||
const handleMute = () => {
|
||||
if (selectedWordIndices.length > 0) {
|
||||
// If words are selected, apply mute immediately
|
||||
const sorted = [...selectedWordIndices].sort((a, b) => a - b);
|
||||
const startTime = words[sorted[0]].start;
|
||||
const endTime = words[sorted[sorted.length - 1]].end;
|
||||
addMuteRange(startTime, endTime);
|
||||
} else {
|
||||
// Toggle mute mode
|
||||
setMuteMode(!muteMode);
|
||||
setCutMode(false); // Exit cut mode
|
||||
}
|
||||
};
|
||||
|
||||
if (!videoPath) {
|
||||
return (
|
||||
@ -280,6 +325,18 @@ export default function App() {
|
||||
onClick={handleLoadProject}
|
||||
/>
|
||||
)}
|
||||
<ToolbarButton
|
||||
icon={<Scissors className="w-4 h-4" />}
|
||||
label="Cut"
|
||||
onClick={handleCut}
|
||||
active={cutMode}
|
||||
/>
|
||||
<ToolbarButton
|
||||
icon={<VolumeX className="w-4 h-4" />}
|
||||
label="Mute"
|
||||
onClick={handleMute}
|
||||
active={muteMode}
|
||||
/>
|
||||
<ToolbarButton
|
||||
icon={<Sparkles className="w-4 h-4" />}
|
||||
label="AI"
|
||||
@ -347,7 +404,7 @@ export default function App() {
|
||||
|
||||
{/* Waveform timeline */}
|
||||
<div className="h-32 border-t border-editor-border shrink-0">
|
||||
<WaveformTimeline />
|
||||
<WaveformTimeline cutMode={cutMode} muteMode={muteMode} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user