Add sidecar download, setup screen, and auto-launch
On first launch, the app now prompts users to download the Python sidecar (CPU or CUDA variant) from Gitea releases, matching the voice-to-notes pattern. On subsequent launches, it auto-launches the sidecar and connects. New Rust module (src-tauri/src/sidecar/): - download_sidecar: streams download with progress events, extracts zip - check_sidecar: verifies installed sidecar binary exists - check_sidecar_update: compares local vs latest release version - SidecarManager: launches binary, waits for ready JSON, manages lifecycle - Dev mode: runs `python -m backend.main_headless` directly - start_sidecar/stop_sidecar/get_sidecar_port: Tauri commands New Svelte component (SidecarSetup.svelte): - First-time setup overlay with CPU/CUDA variant selection - Download progress bar with byte counter - Error state with retry, success state with auto-continue Updated App.svelte state machine: - checking -> needs_setup -> starting -> connected - Falls back to direct connection in browser dev mode Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -5,10 +5,14 @@
|
||||
import Controls from "$lib/components/Controls.svelte";
|
||||
import TranscriptionDisplay from "$lib/components/TranscriptionDisplay.svelte";
|
||||
import Settings from "$lib/components/Settings.svelte";
|
||||
import SidecarSetup from "$lib/components/SidecarSetup.svelte";
|
||||
import { backendStore } from "$lib/stores/backend";
|
||||
import { configStore } from "$lib/stores/config";
|
||||
|
||||
type SidecarState = "checking" | "needs_setup" | "starting" | "connected";
|
||||
|
||||
let showSettings = $state(false);
|
||||
let sidecarState = $state<SidecarState>("checking");
|
||||
|
||||
let obsDisplayUrl = $derived(backendStore.obsUrl);
|
||||
let syncDisplayUrl = $derived(backendStore.syncUrl);
|
||||
@@ -23,9 +27,55 @@
|
||||
showSettings = false;
|
||||
}
|
||||
|
||||
async function checkAndLaunchSidecar() {
|
||||
try {
|
||||
const { invoke } = await import("@tauri-apps/api/core");
|
||||
|
||||
// Check if sidecar is installed
|
||||
sidecarState = "checking";
|
||||
const installed = await invoke<boolean>("check_sidecar");
|
||||
|
||||
if (!installed) {
|
||||
sidecarState = "needs_setup";
|
||||
return;
|
||||
}
|
||||
|
||||
await launchSidecar();
|
||||
} catch {
|
||||
// Not running in Tauri (browser dev mode) - skip sidecar check
|
||||
// and connect directly to localhost:8081
|
||||
sidecarState = "starting";
|
||||
backendStore.setPort(8081);
|
||||
backendStore.connect();
|
||||
configStore.loadConfig();
|
||||
}
|
||||
}
|
||||
|
||||
async function launchSidecar() {
|
||||
try {
|
||||
const { invoke } = await import("@tauri-apps/api/core");
|
||||
|
||||
sidecarState = "starting";
|
||||
await invoke("start_sidecar");
|
||||
|
||||
const port = await invoke<number>("get_sidecar_port");
|
||||
backendStore.setPort(port);
|
||||
backendStore.connect();
|
||||
configStore.loadConfig();
|
||||
} catch {
|
||||
// If sidecar launch fails, still try connecting to default port
|
||||
sidecarState = "starting";
|
||||
backendStore.connect();
|
||||
configStore.loadConfig();
|
||||
}
|
||||
}
|
||||
|
||||
async function onSidecarReady() {
|
||||
await launchSidecar();
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
backendStore.connect();
|
||||
configStore.loadConfig();
|
||||
checkAndLaunchSidecar();
|
||||
|
||||
return () => {
|
||||
backendStore.disconnect();
|
||||
@@ -33,7 +83,21 @@
|
||||
});
|
||||
</script>
|
||||
|
||||
{#if !isConnected}
|
||||
{#if sidecarState === "checking"}
|
||||
<div class="connecting-overlay">
|
||||
<div class="connecting-content">
|
||||
<div class="connecting-icon">
|
||||
<div class="spinner"></div>
|
||||
</div>
|
||||
<h2>Local Transcription</h2>
|
||||
<p>Checking setup...</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{:else if sidecarState === "needs_setup"}
|
||||
<SidecarSetup onComplete={onSidecarReady} />
|
||||
|
||||
{:else if !isConnected}
|
||||
<div class="connecting-overlay">
|
||||
<div class="connecting-content">
|
||||
<div class="connecting-icon">
|
||||
@@ -57,6 +121,7 @@
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{:else}
|
||||
<div class="app-shell">
|
||||
<Header onSettingsClick={openSettings} />
|
||||
|
||||
Reference in New Issue
Block a user