Files
local-transcription/src/lib/components/Controls.svelte
Developer 4c519a109a Add missing Svelte components and stores, fix .gitignore lib/ pattern
The src/lib/ directory was being excluded by a Python .gitignore rule
for lib/ (meant for Python's build output). Changed to /lib/ so it
only matches root-level lib/ and doesn't block src/lib/.

Adds 8 files that were created but missed in the initial commit:
- 5 Svelte components (Header, StatusBar, Controls, TranscriptionDisplay, Settings)
- 3 TypeScript stores (backend, config, transcriptions)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 13:42:31 -07:00

117 lines
3.1 KiB
Svelte

<script lang="ts">
import { backendStore } from "$lib/stores/backend";
import { transcriptionStore } from "$lib/stores/transcriptions";
let isTranscribing = $derived(backendStore.appState === "transcribing");
let isReady = $derived(
backendStore.appState === "ready" || backendStore.appState === "transcribing"
);
let isLoading = $state(false);
async function toggleTranscription() {
if (isLoading) return;
isLoading = true;
try {
if (isTranscribing) {
await backendStore.apiPost("/api/stop");
} else {
await backendStore.apiPost("/api/start");
}
} catch (err) {
console.error("Failed to toggle transcription:", err);
} finally {
isLoading = false;
}
}
async function clearTranscriptions() {
try {
await backendStore.apiPost("/api/clear");
transcriptionStore.clearAll();
} catch (err) {
console.error("Failed to clear:", err);
}
}
async function saveTranscriptions() {
try {
// Get transcription text from backend or local store
let text: string;
try {
const data = await backendStore.apiGet<{ text: string }>("/api/transcriptions");
text = data.text || transcriptionStore.getPlainText();
} catch {
text = transcriptionStore.getPlainText();
}
if (!text.trim()) {
console.warn("No transcriptions to save");
return;
}
// Try Tauri dialog for native save, fall back to browser download
try {
const { save } = await import("@tauri-apps/plugin-dialog");
const filePath = await save({
defaultPath: "transcription.txt",
filters: [
{ name: "Text Files", extensions: ["txt"] },
{ name: "All Files", extensions: ["*"] },
],
});
if (filePath) {
// Write via backend API
await backendStore.apiPost("/api/save-file", { path: filePath, text });
}
} catch {
// Fallback: browser-style download
const blob = new Blob([text], { type: "text/plain" });
const url = URL.createObjectURL(blob);
const a = document.createElement("a");
a.href = url;
a.download = "transcription.txt";
a.click();
URL.revokeObjectURL(url);
}
} catch (err) {
console.error("Failed to save:", err);
}
}
</script>
<div class="controls">
<button
class={isTranscribing ? "danger" : "primary"}
onclick={toggleTranscription}
disabled={!isReady || isLoading}
>
{#if isLoading}
...
{:else if isTranscribing}
Stop Transcription
{:else}
Start Transcription
{/if}
</button>
<button onclick={clearTranscriptions} disabled={!backendStore.connected}>
Clear
</button>
<button onclick={saveTranscriptions} disabled={!backendStore.connected}>
Save
</button>
</div>
<style>
.controls {
display: flex;
align-items: center;
gap: 8px;
padding: 10px 20px;
background-color: var(--bg-secondary);
border-top: 1px solid var(--border-color);
flex-shrink: 0;
}
</style>