anc
Интерфейс: список встреч слева, заметка справа
- Боковая панель: «Записать», «Добавить аудио» (и перетаскивание файла),
«Новая заметка», список встреч.
- Экран встречи: название правится на месте, шаги «Расшифровать» и
команды ИИ с ходом работы, панель записи с уровнями и текстом
предупреждения для чата Zoom.
- Заметка: «Текст» / «Правка», автосохранение, «Копировать всё»,
«Как текст», копирование раздела, живые галочки задач.
- Сообщения внизу экрана вместо ошибок в тексте страницы.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
996ce52
30 сентября 2026 г.
state.ts
// Общее состояние интерфейса: идёт ли запись и сообщения об ошибках.
// Боковая панель и экран заметки подписываются на изменения.
import { api, errorText, type RecordingView } from "./api";
type Listener = () => void;
const listeners = new Set<Listener>();
export const state = {
recording: null as RecordingView | null,
};
export function onChange(cb: Listener): () => void {
listeners.add(cb);
return () => listeners.delete(cb);
}
export function changed(): void {
listeners.forEach((cb) => cb());
}
export async function refreshRecording(): Promise<void> {
state.recording = await api.recorderStatus();
changed();
}
/** Сообщение внизу экрана: ошибка или «Скопировано». Исчезает само. */
export function toast(message: unknown, kind: "error" | "ok" = "error"): void {
const el = document.getElementById("toast");
if (!el) return;
el.textContent = kind === "error" ? errorText(message) : String(message);
el.className = `toast is-${kind}`;
el.hidden = false;
window.clearTimeout(Number(el.dataset.timer));
el.dataset.timer = String(window.setTimeout(() => (el.hidden = true), kind === "error" ? 8000 : 2000));
}
export async function copy(text: string, what = "Скопировано"): Promise<void> {
try {
await navigator.clipboard.writeText(text);
toast(what, "ok");
} catch (e) {
toast(e);
}
}