/** * Transcriptions store - manages the list of transcription items * received from the backend via WebSocket. */ export interface TranscriptionItem { id: string; text: string; userName: string; timestamp: string; isPreview: boolean; } let items = $state([]); let nextId = 0; function generateId(): string { return `t-${Date.now()}-${nextId++}`; } function addTranscription(data: { text?: string; user_name?: string; timestamp?: string; }) { // When a final transcription arrives, remove any existing preview const previewIndex = items.findIndex((item) => item.isPreview); if (previewIndex !== -1) { items.splice(previewIndex, 1); } items.push({ id: generateId(), text: data.text ?? "", userName: data.user_name ?? "", timestamp: data.timestamp ?? "", isPreview: false, }); // Keep a reasonable limit if (items.length > 500) { items.splice(0, items.length - 500); } } function setPreview(data: { text?: string; user_name?: string; timestamp?: string; }) { const existingIndex = items.findIndex((item) => item.isPreview); const previewItem: TranscriptionItem = { id: existingIndex !== -1 ? items[existingIndex].id : generateId(), text: data.text ?? "", userName: data.user_name ?? "", timestamp: data.timestamp ?? "", isPreview: true, }; if (existingIndex !== -1) { items[existingIndex] = previewItem; } else { items.push(previewItem); } } function clearAll() { items.length = 0; } function getPlainText(): string { return items .filter((item) => !item.isPreview) .map((item) => { let line = ""; if (item.timestamp) line += `[${item.timestamp}] `; if (item.userName) line += `${item.userName}: `; line += item.text; return line; }) .join("\n"); } // Listen for backend events if (typeof window !== "undefined") { window.addEventListener("backend:transcription", ((e: CustomEvent) => { addTranscription(e.detail); }) as EventListener); window.addEventListener("backend:preview", ((e: CustomEvent) => { setPreview(e.detail); }) as EventListener); } export const transcriptionStore = { get items() { return items; }, get currentPreview(): TranscriptionItem | null { return items.find((item) => item.isPreview) ?? null; }, get transcriptions(): TranscriptionItem[] { return items.filter((item) => !item.isPreview); }, addTranscription, setPreview, clearAll, getPlainText, };