diff --git a/PLAN.md b/PLAN.md index bdc7372..cc89498 100644 --- a/PLAN.md +++ b/PLAN.md @@ -2,7 +2,7 @@ ## Progress Overview -**Current Status**: Phase 12 Complete (Project Management: Save/load, auto-save, project list) - Ready for Phase 13 +**Current Status**: Phase 13 Complete (Keyboard Shortcuts: Full suite of shortcuts for navigation, editing, and view control) - Ready for Phase 14 ### Completed Phases - ✅ **Phase 1**: Project Setup & Core Infrastructure (95% complete) @@ -796,35 +796,37 @@ audio-ui/ - [x] Project name/description - [x] Created/updated timestamps -### Phase 13: Keyboard Shortcuts +### Phase 13: Keyboard Shortcuts ✅ -#### 13.1 Playback Shortcuts -- [ ] Spacebar - Play/Pause -- [ ] Home - Go to start -- [ ] End - Go to end -- [ ] Left/Right Arrow - Move cursor -- [ ] Ctrl+Left/Right - Move by larger increment +#### 13.1 Playback Shortcuts ✅ +- [x] Spacebar - Play/Pause +- [x] Home - Go to start +- [x] End - Go to end +- [x] Left/Right Arrow - Seek ±1 second +- [x] Ctrl+Left/Right - Seek ±5 seconds -#### 13.2 Editing Shortcuts -- [ ] Ctrl+Z - Undo -- [ ] Ctrl+Y / Ctrl+Shift+Z - Redo -- [ ] Ctrl+X - Cut -- [ ] Ctrl+C - Copy -- [ ] Ctrl+V - Paste -- [ ] Delete - Delete selection -- [ ] Ctrl+A - Select All -- [ ] Escape - Clear selection +#### 13.2 Editing Shortcuts ✅ +- [x] Ctrl+Z - Undo +- [x] Ctrl+Y / Ctrl+Shift+Z - Redo +- [x] Ctrl+X - Cut +- [x] Ctrl+C - Copy +- [x] Ctrl+V - Paste +- [x] Ctrl+S - Save project +- [x] Ctrl+D - Duplicate selection +- [x] Delete/Backspace - Delete selection +- [x] Ctrl+A - Select All (on current track) +- [x] Escape - Clear selection -#### 13.3 View Shortcuts -- [ ] Ctrl+Plus - Zoom in -- [ ] Ctrl+Minus - Zoom out -- [ ] Ctrl+0 - Fit to window -- [ ] F - Toggle fullscreen (optional) +#### 13.3 View Shortcuts ✅ +- [x] Ctrl+Plus/Equals - Zoom in +- [x] Ctrl+Minus - Zoom out +- [x] Ctrl+0 - Fit to window +- [ ] F - Toggle fullscreen (browser native) #### 13.4 Custom Shortcuts -- [ ] Keyboard shortcuts manager -- [ ] User-configurable shortcuts -- [ ] Shortcut conflict detection +- [ ] Keyboard shortcuts manager (future enhancement) +- [ ] User-configurable shortcuts (future enhancement) +- [ ] Shortcut conflict detection (future enhancement) ### Phase 14: Settings & Preferences diff --git a/components/editor/AudioEditor.tsx b/components/editor/AudioEditor.tsx index ee195fc..ec98a52 100644 --- a/components/editor/AudioEditor.tsx +++ b/components/editor/AudioEditor.tsx @@ -1386,12 +1386,90 @@ export function AudioEditor() { if (e.key === 'Escape') { e.preventDefault(); setSelectedTrackId(null); + return; + } + + // Home: Go to start + if (e.key === 'Home') { + e.preventDefault(); + seek(0); + return; + } + + // End: Go to end + if (e.key === 'End') { + e.preventDefault(); + seek(duration); + return; + } + + // Left Arrow: Seek backward 1 second + if (e.key === 'ArrowLeft' && !e.ctrlKey && !e.metaKey) { + e.preventDefault(); + seek(Math.max(0, currentTime - 1)); + return; + } + + // Right Arrow: Seek forward 1 second + if (e.key === 'ArrowRight' && !e.ctrlKey && !e.metaKey) { + e.preventDefault(); + seek(Math.min(duration, currentTime + 1)); + return; + } + + // Ctrl+Left Arrow: Seek backward 5 seconds + if (e.key === 'ArrowLeft' && (e.ctrlKey || e.metaKey)) { + e.preventDefault(); + seek(Math.max(0, currentTime - 5)); + return; + } + + // Ctrl+Right Arrow: Seek forward 5 seconds + if (e.key === 'ArrowRight' && (e.ctrlKey || e.metaKey)) { + e.preventDefault(); + seek(Math.min(duration, currentTime + 5)); + return; + } + + // Ctrl+A: Select All (select all content on current track) + if ((e.ctrlKey || e.metaKey) && e.key === 'a') { + e.preventDefault(); + if (selectedTrackId) { + const track = tracks.find(t => t.id === selectedTrackId); + if (track?.audioBuffer) { + updateTrack(selectedTrackId, { + selection: { start: 0, end: track.audioBuffer.duration } + }); + } + } + return; + } + + // Ctrl+Plus/Equals: Zoom in + if ((e.ctrlKey || e.metaKey) && (e.key === '+' || e.key === '=')) { + e.preventDefault(); + handleZoomIn(); + return; + } + + // Ctrl+Minus: Zoom out + if ((e.ctrlKey || e.metaKey) && e.key === '-') { + e.preventDefault(); + handleZoomOut(); + return; + } + + // Ctrl+0: Fit to view + if ((e.ctrlKey || e.metaKey) && e.key === '0') { + e.preventDefault(); + handleFitToView(); + return; } }; window.addEventListener('keydown', handleKeyDown); return () => window.removeEventListener('keydown', handleKeyDown); - }, [togglePlayPause, canUndo, canRedo, undo, redo, handleCut, handleCopy, handlePaste, handleDelete, handleDuplicate, handleSaveProject]); + }, [togglePlayPause, canUndo, canRedo, undo, redo, handleCut, handleCopy, handlePaste, handleDelete, handleDuplicate, handleSaveProject, seek, duration, currentTime, selectedTrackId, tracks, updateTrack, handleZoomIn, handleZoomOut, handleFitToView]); return ( <>