added cut and mute zones

This commit is contained in:
2026-04-03 11:14:31 -06:00
parent d7bc6ea74d
commit 585262c3e7
13 changed files with 554 additions and 117 deletions

View File

@ -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>