feat: add manual save with Ctrl+S and suppress auto-save toasts

Changes:
- Modified handleSaveProject to accept showToast parameter (default: false)
- Auto-saves now run silently without toast notifications
- Added Ctrl+S / Cmd+S keyboard shortcut for manual save with toast
- Added "Save Project" and "Open Projects" to command palette
- Error toasts still shown for all save failures

This provides the best of both worlds:
- Automatic background saves don't interrupt the user
- Manual saves (Ctrl+S or command palette) provide confirmation
- Users can work without being constantly notified

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-11-19 10:10:32 +01:00
parent 31af08e9f7
commit bcf439ca5e

View File

@@ -887,7 +887,7 @@ export function AudioEditor() {
currentTimeRef.current = currentTime;
}, [currentTime]);
const handleSaveProject = React.useCallback(async () => {
const handleSaveProject = React.useCallback(async (showToast = false) => {
if (tracks.length === 0) return;
try {
@@ -920,14 +920,18 @@ export function AudioEditor() {
// Save last project ID to localStorage for auto-load on next visit
localStorage.setItem('audio-ui-last-project', projectId);
addToast({
title: 'Project Saved',
description: `"${currentProjectName}" saved successfully`,
variant: 'success',
duration: 2000,
});
// Only show toast for manual saves
if (showToast) {
addToast({
title: 'Project Saved',
description: `"${currentProjectName}" saved successfully`,
variant: 'success',
duration: 2000,
});
}
} catch (error) {
console.error('Failed to save project:', error);
// Always show error toasts
addToast({
title: 'Save Failed',
description: 'Could not save project',
@@ -1173,6 +1177,22 @@ export function AudioEditor() {
category: 'playback',
action: stop,
},
// Project
{
id: 'save-project',
label: 'Save Project',
description: 'Save current project',
shortcut: 'Ctrl+S',
category: 'file',
action: () => handleSaveProject(true),
},
{
id: 'open-projects',
label: 'Open Projects',
description: 'Open projects dialog',
category: 'file',
action: handleOpenProjectsDialog,
},
// View
{
id: 'zoom-in',
@@ -1219,7 +1239,7 @@ export function AudioEditor() {
},
];
return actions;
}, [play, pause, stop, handleZoomIn, handleZoomOut, handleFitToView, handleImportTracks, handleClearTracks, addTrack]);
}, [play, pause, stop, handleSaveProject, handleOpenProjectsDialog, handleZoomIn, handleZoomOut, handleFitToView, handleImportTracks, handleClearTracks, addTrack]);
// Keyboard shortcuts
React.useEffect(() => {
@@ -1275,6 +1295,13 @@ export function AudioEditor() {
return;
}
// Ctrl/Cmd+S: Save project (manual save with toast)
if ((e.ctrlKey || e.metaKey) && e.key === 's') {
e.preventDefault();
handleSaveProject(true); // Show toast for manual saves
return;
}
// Ctrl/Cmd+D: Duplicate
if ((e.ctrlKey || e.metaKey) && e.key === 'd') {
e.preventDefault();
@@ -1298,7 +1325,7 @@ export function AudioEditor() {
window.addEventListener('keydown', handleKeyDown);
return () => window.removeEventListener('keydown', handleKeyDown);
}, [togglePlayPause, canUndo, canRedo, undo, redo, handleCut, handleCopy, handlePaste, handleDelete, handleDuplicate]);
}, [togglePlayPause, canUndo, canRedo, undo, redo, handleCut, handleCopy, handlePaste, handleDelete, handleDuplicate, handleSaveProject]);
return (
<>