Files
notes-qpid-pro/TODO.md
T

203 lines
19 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 📋 Задачи проекта: study.qpid.pro (Backlog & Execution Queue)
Список задач для последовательной реализации в рамках принципов **Ponytail** (максимальная надёжность, нативные средства платформы, zero-dependency, высокая скорость).
---
## 🚀 Очередь реализации (Пошаговый план)
### 1. 📑 Полноценный рендеринг Markdown (.md) в читалке
- [x] **Блоки кода (Fenced Code Blocks ```` ```language ````)**:
- Выделение блоков кода в контейнер `<pre><code class="language-...">`.
- Моноширинный шрифт (`JetBrains Mono`, `Consolas`), сохранение отступов и табуляции (`white-space: pre`).
- Тёмная подложка, горизонтальный скролл при переполнении, отключение красной строки (`text-indent: 0`).
- Кнопка «Копировать код» в шапке блока.
- Отключение создания интерактивных словарных спанов `<span class="reader-word">` для кода, чтобы синтаксис не ломал форматирование.
- [x] **Инлайн-код (`` `variable` ``)**:
- Оборачивание в нативный тег `<code class="reader-inline-code">` с бейджик-стилем.
- [x] **Списки и цитаты**:
- Преобразование маркированных (`- `, `* `) и нумерованных (`1. `) списков в `<ul><li>` / `<ol><li>`.
- Преобразование цитат (`> `) в `<blockquote>` с акцентной левой границей.
- **Слова внутри списков и цитат остаются кликабельными** (интерактивный клик-перевод работает!).
- [x] **Заголовки Markdown (`##`, `###`)**:
- Конвертация в `<h3>`, `<h4>` с удалением сырых решёток `#`.
- [x] **Таблицы Markdown (`| col | col |`)**:
- Адаптивные таблицы с рамками, стилизацией заголовков `<thead>`, зебра-подсветкой строк и горизонтальным скроллом на мобильных.
- Каждая ячейка поддерживает интерактивные слова для изучения и инлайн-код.
- [x] **HTML-блоки и теги в Markdown (`<p align="center">`, `<h1>`, `<em>`, `<strong>`, `<sub>`, `<br>`)**:
- Нативный парсинг через встроенный `DOMParser` без внешних библиотек.
- Устранена утечка сырых тегов (`<picture>`, `<source>`, `<p align=...>`) в словарные слова.
- [x] **Ссылки и изображения (`[text](url)`, `![alt](url)`, `<img>`)**:
- Поддержка бейджей shields.io, тренд-графиков и внешних картинок.
- Автоматическое скрытие битых/отсутствующих локальных путей (`assets/...`) через обработчик `onerror`.
- [x] **Точное позиционирование окна перевода у курсора/слова (Popup Positioning)**:
- Исправлен баг двойного смещения координат: убран `window.scrollY` при `position: fixed`.
- Окно перенесено в корень `<body>` для исключения искажений контекста позиционирования.
- Плавное отслеживание скролла через `requestAnimationFrame` с автозакрытием при уходе слова за границы экрана или под липкую шапку.
- [x] **Стилизация в CSS ([`app/static/css/style.css`](file:///home/ai-projects/services/study.qpid.pro/app/static/css/style.css))**:
- Добавлены стили для `.reader-content-body pre`, `code`, `blockquote`, `ul`, `ol`, `.reader-table`, `.reader-heading`, `.reader-link`, `.reader-img`.
---
### 2. 🗜️ Сжатие статического трафика (`GZipMiddleware`)
- [x] Подключить `GZipMiddleware(minimum_size=1000)` в [`app/main.py`](file:///home/ai-projects/services/study.qpid.pro/app/main.py).
- [x] Сократить объём передаваемых файлов `app.js` (111.8 КБ -> 21.5 КБ), `index.html` (55.2 КБ -> 10.3 КБ) и `style.css` (58.2 КБ -> 9.4 КБ) на 81.7% (суммарно с 225.2 КБ до 41.2 КБ).
- [x] Проверить заголовки `Content-Encoding: gzip` в ответах и добавить регрессионный тест в `tests/test_api.py`.
---
### 3. 🛡️ Дедупликация слов и защита от повторного добавления (Reader + API)
- [x] **Проверка дубликатов на бэкенде (`POST /api/cards`)**:
- Проверка слова без учёта регистра `lower(trim(term))`.
- При повторном добавлении не создаётся дубликат, а дополняется контекстное предложение и объединяются теги, возвращается `already_exists: True`.
- [x] **Индикация в читалке и карточке поиска**:
- В читалке при клике на слово и в карточке поиска выводится бейдж `⭐ В библиотеке`.
- Кнопка «+ В словарь» заменяется на бейдж `⭐ Слово уже в библиотеке` с опциональной кнопкой `+ Добавить эту цитату к карточке`.
- [x] **Индекс целостности в SQLite**:
- Создан `UNIQUE INDEX idx_vocab_user_term_nocase ON vocabulary_cards(user_id, term COLLATE NOCASE);` гарантирующий отсутствие дубликатов на уровне движка БД за $O(\log N)$.
- [x] **Слияние существующих дубликатов в базе**:
- Объединены дубликаты `admired` (ID 5 и ID 7) и `suddenly`/`Suddenly` (ID 2 и ID 9) с объединением контекстных предложений, слиянием тегов и сохранением прогресса SRS.
---
### 4. 📱 Мобильная оптимизация и адаптивная верстка (iPhone 12 / iOS Safari)
- [x] **Системный фундамент iOS и сброс ограничений (Core Foundation)**:
- Метатег `viewport`: добавлен `viewport-fit=cover` для поддержки выреза (notch) и нижней панели iPhone.
- Устранение бага принудительного авто-зума: установлен `font-size: 16px` для `<input>`, `<textarea>`, `<select>` на экранах `≤ 768px`.
- Внедрены динамические единицы `100dvh` (Dynamic Viewport Height) и безопасные отступы `env(safe-area-inset-top)` / `env(safe-area-inset-bottom)`.
- Защита от горизонтального сдвига (`overflow-x: hidden` на `html`, `body` и `#app-shell`).
- [x] **Мобильная навигация: переход к нативному паттерну (App Header + Bottom Tab Bar)**:
- Компактная верхняя шапка для смартфонов: логотип `📖 Notes`, переключатель темы `🌓`, кнопка вызова профиля `⚙️`.
- Фиксированная нижняя панель вкладок (Bottom Tab Bar) с нативным iOS UX:
1. 🔍 **Словарь** (Поиск и словарь)
2. 🎓 **Тренажёр** (SRS с бейджем количества повторений)
3. 📚 **Читалка** (Библиотека книг)
4. 📊 **Прогресс** (Статистика и стрик)
5. ⚙️ **Меню** (Смена пароля, экспорт, выход)
- Полное сохранение десктопного `navbar` без изменений на больших экранах (`> 768px`).
- [x] **Адаптация экрана словаря и карточек (Dictionary & Cards View)**:
- Поле поиска/перевода на полную ширину экрана с кнопкой «Перевести».
- Скрытие неактуальных десктопных подсказок горячих клавиш (`<kbd>Ctrl+Enter</kbd>`) на мобильных устройствах.
- Вертикальная раскладка полей метаданных при редактировании карточки.
- Горизонтальный скролл чипсов коллекций и тегов (`overflow-x: auto; white-space: nowrap; -webkit-overflow-scrolling: touch`).
- Увеличенные зоны нажатия (Touch Targets ≥ 44px) для кнопок действий над карточкой.
- [x] **Интерактивная читалка и переход к Mobile Bottom Sheet**:
- Трансформация всплывающего попапа перевода (`reader-word-popup`) в нативную выдвижную нижнюю шторку (Bottom Sheet) на смартфонах с ручкой перетаскивания `sheet-drag-handle`.
- Двухстрочный адаптивный тулбар читалки (навигация по главам + размер шрифта `A-/A+` и подсветка).
- Сетка библиотеки `bookshelf-grid` в одну колонку на экранах `≤ 640px`.
- [x] **Тренажёр интервальных повторений (SRS Trainer)**:
- Ограничение высоты карточки SRS (`max-height: 48dvh`), чтобы карточка и кнопки оценки гарантированно помещались без вертикального скролла на 390px.
- Кнопки оценки (Снова / Трудно / Хорошо / Легко) в сетку 2×2 с высотой от 48px и четкими цветовыми акцентами.
- Вертикальный список вариантов в режиме квиза (4 варианта) на всю ширину экрана.
- [x] **Модальные окна (Статистика, Пароль, Экспорт)**:
- Метрики статистики в сетку 2×2 вместо сжатых 4 колонок.
- Плавный горизонтальный скролл календаря активности (Heatmap).
- Разворачивание модальных окон в адаптивный мобильный слой с удобной кнопкой закрытия.
---
---
### 5. 🔤 Кастомизация оформления читалки (Типографика, темы, отступы, LocalStorage)
- [x] **Панель настроек оформления текста (`Aa`)**:
- Кнопка вызова настроек в тулбаре читалки: поповер на ПК и выдвижная шторка (Bottom Sheet) на смартфонах.
- [x] **Настройка размера шрифта и степпер**:
- Степпер `A-` / `A+` с индикатором точного размера (от 14px до 34px).
- [x] **Семейство шрифтов (Font Family)**:
- Переключение в 1 клик между `Sans` (системный), `Serif` (книжный с засечками), `Mono` (моноширинный).
- [x] **Межстрочный интервал (Line Height)**:
- Компактный (1.35), Оптимальный (1.65), Широкий (1.95).
- [x] **Поля и ширина колонки (Margins & Max Width)**:
- Узкие поля (940px), Стандарт (760px), Книжная колонка (600px).
- [x] **Цветовые темы читалки (Themes)**:
- 🌙 Тёмная (Dark Slate), 📜 Сепия (Тёплый пергамент), ☀️ Светлая (Чистый лист), 🖤 OLED (Абсолютный чёрный).
- [x] **Выравнивание текста (Text Alignment)**:
- По левому краю / По ширине (Justified).
- [x] **Автосохранение и персистентность**:
- Мгновенное реактивное применение стилей через CSS-переменные без перезагрузки и сохранение настроек в `localStorage`.
---
### 6. 🔌 Пул соединений HTTP (`httpx.AsyncClient` с Keep-Alive)
- [ ] В [`app/dictionary.py`](file:///home/ai-projects/services/study.qpid.pro/app/dictionary.py) создать синглтон-клиент `get_http_client()` с пулом соединений:
```python
limits = httpx.Limits(max_keepalive_connections=10, max_connections=20)
```
- [ ] Заменить вызовы `async with httpx.AsyncClient()` в парсерах на переиспользуемый клиент.
- [ ] Устранить 5 повторных TCP/TLS хэндшейков на каждое слово, сократив пинг внешних запросов на 300–600 мс.
---
### 7. 🗄️ Тюнинг SQLite PRAGMA и составных индексов
- [ ] В [`app/database.py`](file:///home/ai-projects/services/study.qpid.pro/app/database.py):
- Вынести `PRAGMA journal_mode=WAL;` в `init_db()` (убрать избыточный вызов при каждом запросе).
- Включить параметры производительности памяти Linux:
```python
conn.execute("PRAGMA synchronous = NORMAL;")
conn.execute("PRAGMA mmap_size = 268435456;") # 256MB mmap
conn.execute("PRAGMA cache_size = -32000;") # 32MB cache
```
- [ ] Обеспечить Zero-copy чтение страниц БД ядром Linux.
---
### 8. ✂️ Де-блоатинг внешних парсеров (YAGNI)
- [ ] Удалить лишний сетевой опрос Datamuse (`fetch_datamuse`) — он дублирует определения и перегружает ответ нерелевантными рифмами.
- [ ] Упростить хрупкий regex-парсинг разметки Wikitext, опираясь на стабильные REST JSON эндпоинты.
---
### 9. 📚 Локальный оффлайн-словарь (99%+ покрытия со словоформами, SQLite 10–20 МБ)
- [ ] Создать в SQLite таблицу:
```sql
CREATE TABLE IF NOT EXISTS offline_dictionary (
term TEXT PRIMARY KEY COLLATE NOCASE,
translation TEXT NOT NULL,
phonetic TEXT DEFAULT '',
pos TEXT DEFAULT ''
);
CREATE INDEX IF NOT EXISTS idx_offline_dict_term ON offline_dictionary(term COLLATE NOCASE);
```
- [ ] Сформировать и интегрировать базу на 120 000–180 000 статей (~10–20 МБ в SQLite, сжатый архив ~3.5–5 МБ):
- Включить все словоформы (past tense, irregular verbs, plurals, participles).
- Включить фразовые глаголы, современный сленг и IT/Tech терминологию.
- [ ] Использовать архитектуру **Zero Daemon**: нативный SQLite с `PRAGMA mmap_size` (без отдельного контейнера Redis, чтение < 0.1 мс прямо из оперативной памяти процесса).
- [ ] Реализовать логику словарного поиска:
1. Сначала запрос в `offline_dictionary` $\rightarrow$ мгновенный ответ за 0.1 мс.
2. Только при отсутствии слова в базе $\rightarrow$ fallback-запрос во внешнюю сеть.
- [ ] Полностью исключить исчерпание лимитов внешних API (MyMemory 100 req/day).
---
### 10. 🧩 Модульность фронтенда на нативных ES-модулях (без Webpack/Vite)
- [ ] Перевести [`app/static/js/app.js`](file:///home/ai-projects/services/study.qpid.pro/app/static/js/app.js) на нативный браузерный синтаксис `<script type="module">`.
- [ ] Выделить модули с нативным `import/export`:
- `modules/reader.js` — читалку, блок-парсер и навигацию по главам.
- `modules/srs.js` — алгоритм SM-2, флэшкарты и квиз.
- `modules/api.js` — клиентские сетевые вызовы.
- `modules/ui.js` — тосты, модальные окна, темы оформления.
- [ ] Сохранить полное отсутствие внешних сборщиков (0 npm-пакетов, чистая платформа).
---
## ⏳ Coming Soon
- [ ] **🌐 Быстрый захват из браузера (Bookmarklet)**:
- Создать JavaScript-букмарклет для добавления слова/фразы из любого окна браузера в личный словарь [`study.qpid.pro`](https://study.qpid.pro) (низший приоритет).
- [ ] **Нативная автономная озвучка (HTML5 Web Speech API / `speechSynthesis`)**:
- Использовать встроенный в браузер синтезатор речи `window.speechSynthesis` (en-US, en-GB).
- 0 сетевых запросов к серверу, 100% оффлайн-работа.
- Поддержка озвучивания отдельных слов, фраз, идиом и предложений-контекстов читалки.
- [ ] **Возврат режима «Диктант» в SRS**:
- Возобновление работы аудиотренажёра на базе нативного браузерного синтезатора речи без зависимости от внешних аудиофайлов.
---
## 🛠️ Правила и соглашения проекта (Ponytail Rules)
1. **Stdlib & Native First**: стандартная библиотека языка и возможности платформы (браузера, SQLite, Linux) всегда приоритетнее внешних библиотек и микросервисов.
2. **Меньше кода — меньше багов**: удаление кода и упрощение структуры всегда лучше усложнения.
3. **Безопасность**: все мутации данных изолированы по `user_id`, пароли защищены PBKDF2 с уникальной солью.
4. **Тестирование**: после каждого изменения запуск `pytest tests/test_api.py -v` (100% тестов должны быть зелеными).