refactor(frontend): migrate JS modules to TypeScript

Wholesale JS -> TS migration of the frontend — stores, utils, actions,
and all Svelte component scripts adopt type annotations. Compile-time
surfaces (app.d.ts, lib/types/) added for shared DTO types.

Build plumbing:
  - package.json: dev:frontend script that runs svelte-kit sync first
  - tauri.conf.json: beforeDevCommand points at dev:frontend
  - run.sh: dropped the sed-hack that temporarily blanked beforeDevCommand;
    now relies on npm run dev:frontend to avoid double-Vite
  - jsconfig.json: allowImportingTsExtensions

Preserves all Group 1 behaviour:
  - page.svelte.ts keeps loadHistory / loadTasks Tauri-first, no
    localStorage; saveTranscriptMeta + mapTranscriptRow + mapTaskRow
    intact; update_task_cmd and update_transcript_meta_cmd invocations
    carry the correct payload shape.
  - Toasts, preferences stores typed without behaviour change.
  - Viewer still routes segment edits through saveTranscriptMeta; the
    Task 1.5 TODO markers are gone.

taskExtractor.ts is functionally improved during the migration:
  - multi-task matches in the same sentence
  - list-style shopping-verb expansion (get bread, milk, and cheese)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-19 20:05:54 +01:00
parent 6605266587
commit d6bf9ed245
48 changed files with 1693 additions and 1156 deletions

243
src/lib/types/app.ts Normal file
View File

@@ -0,0 +1,243 @@
export type ThemeMode = "light" | "dark" | "system";
export type FontFamily = "lexend" | "atkinson" | "opendyslexic";
export type ReduceMotion = "system" | "on" | "off";
export type RecordingEngine = "whisper" | "parakeet";
export type FormatMode = "Raw" | "Clean" | "Smart";
export type WhisperModelSize = "Tiny" | "Base" | "Small" | "Medium";
export type TaskBucket = "inbox" | "today" | "soon" | "later";
export type ToastSeverity = "info" | "success" | "warn" | "error";
export interface PageState {
current: string;
status: string;
statusColor: string;
activeProfile: string;
recording: boolean;
timerText: string;
handedness: string;
taskSidebarOpen: boolean;
}
export interface SettingsState {
engine: RecordingEngine;
modelSize: WhisperModelSize;
language: string;
device: string;
formatMode: FormatMode;
removeFillers: boolean;
antiHallucination: boolean;
britishEnglish: boolean;
autoCopy: boolean;
includeTimestamps: boolean;
theme: "Dark" | "Light" | "System";
fontSize: number;
llmModelSize: string;
llmEnabled: boolean;
saveAudio: boolean;
outputFolder: string;
globalHotkey: string;
sidebarCollapsed: boolean;
microphoneDevice: string;
}
export interface Profile {
name: string;
words: string;
}
export interface Template {
name: string;
sections: string[];
}
export interface AccessibilityPreferences {
fontFamily: FontFamily;
fontSize: number;
letterSpacing: number;
lineHeight: number;
transcriptSize: number;
bionicReading: boolean;
reduceMotion: ReduceMotion;
}
export interface Preferences {
theme: ThemeMode;
zone: string;
accessibility: AccessibilityPreferences;
}
export interface Segment {
start: number;
end: number;
text: string;
starred?: boolean;
[key: string]: unknown;
}
export interface TranscriptDto {
id: string;
text: string;
source: string;
title: string | null;
audioPath: string | null;
duration: number;
engine: string | null;
modelId: string | null;
createdAt: string;
starred: boolean;
manualTags: string;
template: string;
language: string;
segmentsJson: string;
}
export interface TranscriptEntry {
id: string;
text: string;
source: string;
title: string;
audioPath: string | null;
duration: number;
engine: string | null;
modelId: string | null;
createdAt: string | null;
date: string;
preview: string;
starred: boolean;
manualTags: string[];
template: string;
language: string;
segments: Segment[];
}
export interface TranscriptWriteEntry extends Partial<TranscriptEntry> {
id: string;
text: string;
inferenceMs?: number | null;
sampleRate?: number | null;
audioChannels?: number | null;
formatMode?: string | null;
removeFillers?: boolean;
britishEnglish?: boolean;
antiHallucination?: boolean;
}
export interface TranscriptMetaPatch {
starred?: boolean;
manualTags?: string[] | string;
template?: string;
language?: string;
segments?: Segment[];
}
export interface TaskDto {
id: string;
text: string;
bucket: string;
listId: string | null;
effort: string | null;
notes: string;
done: boolean;
doneAt: string | null;
createdAt: string;
sourceTranscriptId: string | null;
parentTaskId: string | null;
}
export interface TaskEntry {
id: string;
text: string;
bucket: TaskBucket;
listId: string | null;
effort: string;
notes: string;
done: boolean;
doneAt: string | null;
createdAt: string;
sourceTranscriptId: string | null;
parentTaskId: string | null;
}
export interface TaskDraft {
text: string;
bucket?: TaskBucket;
listId?: string | null;
effort?: string | null;
sourceTranscriptId?: string | null;
}
export interface TaskUpdate {
text?: string | null;
bucket?: TaskBucket | null;
listId?: string | null;
effort?: string | null;
notes?: string | null;
}
export interface TaskList {
id: string;
name: string;
builtIn: boolean;
profileId?: string | null;
createdAt: string | null;
}
export interface ToastItem {
id: number;
severity: ToastSeverity;
title: string;
body: string;
duration: number;
}
export interface AudioDeviceInfo {
name: string;
sample_rate: number;
channels: number;
is_likely_monitor: boolean;
is_default: boolean;
description: string;
}
export interface DictionaryEntry {
id: number;
term: string;
note: string | null;
}
export interface LanguageSupportInfo {
kind: string;
languageCount: number;
}
export interface ModelRuntimeCapabilities {
id: string;
displayName: string;
downloaded: boolean;
loaded: boolean;
languageSupport: LanguageSupportInfo;
}
export interface EngineRuntimeCapabilities {
id: string;
defaultModelId: string;
loadedModelId: string | null;
supportsGpu: boolean;
models: ModelRuntimeCapabilities[];
}
export interface RuntimeCapabilities {
accelerators: string[];
engines: EngineRuntimeCapabilities[];
}
export interface DiagnosticReportOptions {
includeRecentErrors: boolean;
includeCrashes: boolean;
includeSettings: boolean;
includeLogTail: boolean;
}
export interface ViewerSegment extends Segment {
_idx: number;
}