removed electron
This commit is contained in:
@ -22,7 +22,7 @@ import {
|
||||
VolumeX,
|
||||
} from 'lucide-react';
|
||||
|
||||
const IS_ELECTRON = !!window.electronAPI;
|
||||
const IS_DESKTOP = !!window.desktopAPI;
|
||||
|
||||
type Panel = 'ai' | 'settings' | 'export' | 'silence' | null;
|
||||
|
||||
@ -66,8 +66,8 @@ export default function App() {
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (IS_ELECTRON) {
|
||||
window.electronAPI!.getBackendUrl().then(setBackendUrl);
|
||||
if (IS_DESKTOP) {
|
||||
window.desktopAPI!.getBackendUrl().then(setBackendUrl);
|
||||
}
|
||||
// In Tauri on Linux/WebKit2GTK the ipc:// custom protocol is blocked by
|
||||
// WebKit internals; postMessage fallback works but logs noisy warnings.
|
||||
@ -75,11 +75,11 @@ export default function App() {
|
||||
}, [setBackendUrl]);
|
||||
|
||||
const handleLoadProject = async () => {
|
||||
if (!IS_ELECTRON) return;
|
||||
if (!IS_DESKTOP) return;
|
||||
try {
|
||||
const projectPath = await window.electronAPI!.openProject();
|
||||
const projectPath = await window.desktopAPI!.openProject();
|
||||
if (!projectPath) return;
|
||||
const content = await window.electronAPI!.readFile(projectPath);
|
||||
const content = await window.desktopAPI!.readFile(projectPath);
|
||||
const data = JSON.parse(content);
|
||||
useEditorStore.getState().loadProject(data);
|
||||
} catch (err) {
|
||||
@ -89,13 +89,13 @@ export default function App() {
|
||||
};
|
||||
|
||||
const handleSaveProject = async () => {
|
||||
if (!IS_ELECTRON) return;
|
||||
if (!IS_DESKTOP) return;
|
||||
try {
|
||||
const savePath = await window.electronAPI!.saveProject();
|
||||
const savePath = await window.desktopAPI!.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));
|
||||
await window.desktopAPI!.writeFile(path, JSON.stringify(data, null, 2));
|
||||
} catch (err) {
|
||||
console.error('Failed to save project:', err);
|
||||
alert(`Failed to save project: ${err}`);
|
||||
@ -103,8 +103,8 @@ export default function App() {
|
||||
};
|
||||
|
||||
const handleOpenFile = async () => {
|
||||
if (IS_ELECTRON) {
|
||||
const path = await window.electronAPI!.openFile();
|
||||
if (IS_DESKTOP) {
|
||||
const path = await window.desktopAPI!.openFile();
|
||||
if (path) {
|
||||
loadVideo(path);
|
||||
await transcribeVideo(path);
|
||||
@ -130,7 +130,7 @@ export default function App() {
|
||||
const transcribeVideo = async (path: string) => {
|
||||
setTranscribing(true, 0, 'Checking model...');
|
||||
try {
|
||||
if (!window.electronAPI?.transcribe) {
|
||||
if (!window.desktopAPI?.transcribe) {
|
||||
throw new Error('Transcription not available');
|
||||
}
|
||||
// Step 1: ensure model is downloaded (may take a while on first run)
|
||||
@ -153,11 +153,11 @@ export default function App() {
|
||||
};
|
||||
const modelLabel = MODEL_SIZES[whisperModel] ?? 'unknown size';
|
||||
setTranscribing(true, 5, `Downloading ${whisperModel} model (${modelLabel})...`);
|
||||
await window.electronAPI.ensureModel(whisperModel);
|
||||
await window.desktopAPI.ensureModel(whisperModel);
|
||||
|
||||
// Step 2: run transcription
|
||||
setTranscribing(true, 20, 'Transcribing audio...');
|
||||
const data = await window.electronAPI.transcribe(path, whisperModel);
|
||||
const data = await window.desktopAPI.transcribe(path, whisperModel);
|
||||
setTranscription(data);
|
||||
} catch (err) {
|
||||
console.error('Transcription error:', err);
|
||||
@ -243,7 +243,7 @@ export default function App() {
|
||||
English-only models are ~10% faster and more accurate for English content.
|
||||
</p>
|
||||
|
||||
{IS_ELECTRON ? (
|
||||
{IS_DESKTOP ? (
|
||||
<div className="flex flex-col items-center gap-3">
|
||||
<button
|
||||
onClick={handleOpenFile}
|
||||
@ -313,9 +313,9 @@ export default function App() {
|
||||
<ToolbarButton
|
||||
icon={<FolderOpen className="w-4 h-4" />}
|
||||
label="Open"
|
||||
onClick={IS_ELECTRON ? handleOpenFile : () => useEditorStore.getState().reset()}
|
||||
onClick={IS_DESKTOP ? handleOpenFile : () => useEditorStore.getState().reset()}
|
||||
/>
|
||||
{IS_ELECTRON && (
|
||||
{IS_DESKTOP && (
|
||||
<ToolbarButton
|
||||
icon={<Save className="w-4 h-4" />}
|
||||
label="Save"
|
||||
@ -323,7 +323,7 @@ export default function App() {
|
||||
disabled={words.length === 0}
|
||||
/>
|
||||
)}
|
||||
{IS_ELECTRON && (
|
||||
{IS_DESKTOP && (
|
||||
<ToolbarButton
|
||||
icon={<FileInput className="w-4 h-4" />}
|
||||
label="Load"
|
||||
|
||||
@ -20,7 +20,7 @@ export default function ExportDialog() {
|
||||
const handleExport = useCallback(async () => {
|
||||
if (!videoPath) return;
|
||||
|
||||
const outputPath = await window.electronAPI?.saveFile({
|
||||
const outputPath = await window.desktopAPI?.saveFile({
|
||||
defaultPath: videoPath.replace(/\.[^.]+$/, '_edited.mp4'),
|
||||
filters: [
|
||||
{ name: 'MP4', extensions: ['mp4'] },
|
||||
|
||||
@ -167,14 +167,14 @@ async function saveProject() {
|
||||
modifiedAt: new Date().toISOString(),
|
||||
};
|
||||
|
||||
const outputPath = await window.electronAPI?.saveFile({
|
||||
const outputPath = await window.desktopAPI?.saveFile({
|
||||
defaultPath: state.videoPath.replace(/\.[^.]+$/, '.aive'),
|
||||
filters: [{ name: 'TalkEdit Project', extensions: ['aive'] }],
|
||||
});
|
||||
|
||||
if (outputPath) {
|
||||
if (window.electronAPI?.writeFile) {
|
||||
await window.electronAPI.writeFile(outputPath, JSON.stringify(projectData, null, 2));
|
||||
if (window.desktopAPI?.writeFile) {
|
||||
await window.desktopAPI.writeFile(outputPath, JSON.stringify(projectData, null, 2));
|
||||
} else {
|
||||
const blob = new Blob([JSON.stringify(projectData, null, 2)], { type: 'application/json' });
|
||||
const url = URL.createObjectURL(blob);
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
/**
|
||||
* tauri-bridge.ts
|
||||
*
|
||||
* Polyfills window.electronAPI with Tauri equivalents so all existing
|
||||
* call-sites in App.tsx, hooks, and stores continue to work unchanged.
|
||||
* Exposes window.desktopAPI using Tauri equivalents so UI code can stay
|
||||
* desktop-runtime agnostic.
|
||||
*
|
||||
* Imported once at the top of main.tsx.
|
||||
*/
|
||||
@ -25,7 +25,10 @@ const EXPORT_FILTERS = [
|
||||
{ name: 'Project Files', extensions: ['aive'] },
|
||||
];
|
||||
|
||||
window.electronAPI = {
|
||||
const BACKEND_PORT = import.meta.env.VITE_BACKEND_PORT || '8000';
|
||||
const BACKEND_URL = `http://127.0.0.1:${BACKEND_PORT}`;
|
||||
|
||||
window.desktopAPI = {
|
||||
openFile: async (_options?: Record<string, unknown>): Promise<string | null> => {
|
||||
const result = await open({
|
||||
multiple: false,
|
||||
@ -53,8 +56,8 @@ window.electronAPI = {
|
||||
},
|
||||
|
||||
getBackendUrl: (): Promise<string> => {
|
||||
// Backend URL is fixed; avoid invoke() which triggers ipc:// CSP errors on Linux/WebKit2GTK
|
||||
return Promise.resolve('http://127.0.0.1:8000');
|
||||
// Use env-driven backend URL and avoid invoke() to bypass ipc:// noise on Linux/WebKit2GTK.
|
||||
return Promise.resolve(BACKEND_URL);
|
||||
},
|
||||
|
||||
encryptString: (data: string): Promise<string> => {
|
||||
|
||||
@ -2,7 +2,7 @@ import React from 'react';
|
||||
import ReactDOM from 'react-dom/client';
|
||||
// Forward console.error/warn/log to backend in dev mode so we can tail webview.log
|
||||
import './lib/dev-logger';
|
||||
// Must be imported before App so window.electronAPI is patched before any component runs.
|
||||
// Must be imported before App so window.desktopAPI is patched before any component runs.
|
||||
import './lib/tauri-bridge';
|
||||
import App from './App';
|
||||
import './index.css';
|
||||
|
||||
@ -30,8 +30,8 @@ async function encryptAndStore(key: string, value: string): Promise<void> {
|
||||
localStorage.removeItem(ENCRYPTED_KEY_PREFIX + key);
|
||||
return;
|
||||
}
|
||||
if (window.electronAPI) {
|
||||
const encrypted = await window.electronAPI.encryptString(value);
|
||||
if (window.desktopAPI) {
|
||||
const encrypted = await window.desktopAPI.encryptString(value);
|
||||
localStorage.setItem(ENCRYPTED_KEY_PREFIX + key, encrypted);
|
||||
} else {
|
||||
localStorage.setItem(ENCRYPTED_KEY_PREFIX + key, btoa(value));
|
||||
@ -41,9 +41,9 @@ async function encryptAndStore(key: string, value: string): Promise<void> {
|
||||
async function loadAndDecrypt(key: string): Promise<string> {
|
||||
const stored = localStorage.getItem(ENCRYPTED_KEY_PREFIX + key);
|
||||
if (!stored) return '';
|
||||
if (window.electronAPI) {
|
||||
if (window.desktopAPI) {
|
||||
try {
|
||||
return await window.electronAPI.decryptString(stored);
|
||||
return await window.desktopAPI.decryptString(stored);
|
||||
} catch {
|
||||
return '';
|
||||
}
|
||||
|
||||
8
frontend/src/vite-env.d.ts
vendored
8
frontend/src/vite-env.d.ts
vendored
@ -1,6 +1,10 @@
|
||||
/// <reference types="vite/client" />
|
||||
|
||||
interface ElectronAPI {
|
||||
interface ImportMetaEnv {
|
||||
readonly VITE_BACKEND_PORT?: string;
|
||||
}
|
||||
|
||||
interface DesktopAPI {
|
||||
openFile: (options?: Record<string, unknown>) => Promise<string | null>;
|
||||
saveFile: (options?: Record<string, unknown>) => Promise<string | null>;
|
||||
openProject: () => Promise<string | null>;
|
||||
@ -15,5 +19,5 @@ interface ElectronAPI {
|
||||
}
|
||||
|
||||
interface Window {
|
||||
electronAPI?: ElectronAPI;
|
||||
desktopAPI?: DesktopAPI;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user