close sh;able to save/load projects
This commit is contained in:
@ -1,5 +1,4 @@
|
||||
import { useEffect, useState, useRef } from 'react';
|
||||
import { invoke } from '@tauri-apps/api/core';
|
||||
import { useEditorStore } from './store/editorStore';
|
||||
import VideoPlayer from './components/VideoPlayer';
|
||||
import TranscriptEditor from './components/TranscriptEditor';
|
||||
@ -7,6 +6,7 @@ import WaveformTimeline from './components/WaveformTimeline';
|
||||
import AIPanel from './components/AIPanel';
|
||||
import ExportDialog from './components/ExportDialog';
|
||||
import SettingsPanel from './components/SettingsPanel';
|
||||
import DevPanel from './components/DevPanel';
|
||||
import { useKeyboardShortcuts } from './hooks/useKeyboardShortcuts';
|
||||
import {
|
||||
Film,
|
||||
@ -16,10 +16,10 @@ import {
|
||||
Download,
|
||||
FolderSearch,
|
||||
FileInput,
|
||||
Save,
|
||||
} from 'lucide-react';
|
||||
|
||||
const IS_ELECTRON = !!window.electronAPI;
|
||||
const IS_TAURI = !IS_ELECTRON && '__TAURI_INTERNALS__' in window;
|
||||
|
||||
type Panel = 'ai' | 'settings' | 'export' | null;
|
||||
|
||||
@ -47,9 +47,10 @@ export default function App() {
|
||||
useEffect(() => {
|
||||
if (IS_ELECTRON) {
|
||||
window.electronAPI!.getBackendUrl().then(setBackendUrl);
|
||||
} else if (IS_TAURI) {
|
||||
invoke<string>('get_backend_url').then(setBackendUrl).catch(console.error);
|
||||
}
|
||||
// In Tauri on Linux/WebKit2GTK the ipc:// custom protocol is blocked by
|
||||
// WebKit internals; postMessage fallback works but logs noisy warnings.
|
||||
// The backend URL is fixed at 127.0.0.1:8000 so we rely on the store default.
|
||||
}, [setBackendUrl]);
|
||||
|
||||
const handleLoadProject = async () => {
|
||||
@ -66,6 +67,20 @@ export default function App() {
|
||||
}
|
||||
};
|
||||
|
||||
const handleSaveProject = async () => {
|
||||
if (!IS_ELECTRON) return;
|
||||
try {
|
||||
const savePath = await window.electronAPI!.saveProject();
|
||||
if (!savePath) return;
|
||||
const data = useEditorStore.getState().saveProject();
|
||||
const path = savePath.endsWith('.aive') ? savePath : `${savePath}.aive`;
|
||||
await window.electronAPI!.writeFile(path, JSON.stringify(data, null, 2));
|
||||
} catch (err) {
|
||||
console.error('Failed to save project:', err);
|
||||
alert(`Failed to save project: ${err}`);
|
||||
}
|
||||
};
|
||||
|
||||
const handleOpenFile = async () => {
|
||||
if (IS_ELECTRON) {
|
||||
const path = await window.electronAPI!.openFile();
|
||||
@ -216,6 +231,21 @@ export default function App() {
|
||||
label="Open"
|
||||
onClick={IS_ELECTRON ? handleOpenFile : () => useEditorStore.getState().reset()}
|
||||
/>
|
||||
{IS_ELECTRON && (
|
||||
<ToolbarButton
|
||||
icon={<Save className="w-4 h-4" />}
|
||||
label="Save"
|
||||
onClick={handleSaveProject}
|
||||
disabled={words.length === 0}
|
||||
/>
|
||||
)}
|
||||
{IS_ELECTRON && (
|
||||
<ToolbarButton
|
||||
icon={<FileInput className="w-4 h-4" />}
|
||||
label="Load"
|
||||
onClick={handleLoadProject}
|
||||
/>
|
||||
)}
|
||||
<ToolbarButton
|
||||
icon={<Sparkles className="w-4 h-4" />}
|
||||
label="AI"
|
||||
@ -296,6 +326,7 @@ export default function App() {
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
{import.meta.env.DEV && <DevPanel />}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user