anc
Интерфейс: список встреч слева, заметка справа
- Боковая панель: «Записать», «Добавить аудио» (и перетаскивание файла),
«Новая заметка», список встреч.
- Экран встречи: название правится на месте, шаги «Расшифровать» и
команды ИИ с ходом работы, панель записи с уровнями и текстом
предупреждения для чата Zoom.
- Заметка: «Текст» / «Правка», автосохранение, «Копировать всё»,
«Как текст», копирование раздела, живые галочки задач.
- Сообщения внизу экрана вместо ошибок в тексте страницы.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
996ce52
30 сентября 2026 г.
main.ts
// Оболочка: боковая панель со встречами слева, экран справа.
// Маршруты: #/ — начало, #/m/<id> — встреча, #/settings — настройки.
import { renderNote } from "./views/note";
import { renderSettings } from "./views/settings";
import { renderStart } from "./views/start";
import { mountSidebar } from "./views/sidebar";
import { errorText } from "./api";
import { esc } from "./dom";
import { Scope } from "./scope";
const main = document.getElementById("app")!;
let scope = new Scope();
async function route(): Promise<void> {
scope.dispose();
scope = new Scope();
const [section, id] = location.hash.replace(/^#\/?/, "").split("/");
const settingsLink = document.querySelector("[data-nav=settings]");
if (section === "settings") settingsLink?.setAttribute("aria-current", "page");
else settingsLink?.removeAttribute("aria-current");
try {
if (section === "m" && id) await renderNote(main, scope, decodeURIComponent(id));
else if (section === "settings") await renderSettings(main);
else await renderStart(main);
} catch (e) {
main.innerHTML = `<p class="error">${esc(errorText(e))}</p>`;
}
}
mountSidebar(document.getElementById("sidebar")!).catch((e) => {
document.getElementById("sidebar")!.innerHTML = `<p class="error">${esc(errorText(e))}</p>`;
});
window.addEventListener("hashchange", route);
route();