18 KiB
18 KiB
📋 Задачи проекта: study.qpid.pro (Backlog & Execution Queue)
Список задач для последовательной реализации в рамках принципов Ponytail (максимальная надёжность, нативные средства платформы, zero-dependency, высокая скорость).
🚀 Очередь реализации (Пошаговый план)
1. 📑 Полноценный рендеринг Markdown (.md) в читалке
- Блоки кода (Fenced Code Blocks
```language):- Выделение блоков кода в контейнер
<pre><code class="language-...">. - Моноширинный шрифт (
JetBrains Mono,Consolas), сохранение отступов и табуляции (white-space: pre). - Тёмная подложка, горизонтальный скролл при переполнении, отключение красной строки (
text-indent: 0). - Кнопка «Копировать код» в шапке блока.
- Отключение создания интерактивных словарных спанов
<span class="reader-word">для кода, чтобы синтаксис не ломал форматирование.
- Выделение блоков кода в контейнер
- Инлайн-код (
`variable`):- Оборачивание в нативный тег
<code class="reader-inline-code">с бейджик-стилем.
- Оборачивание в нативный тег
- Списки и цитаты:
- Преобразование маркированных (
-,*) и нумерованных (1.) списков в<ul><li>/<ol><li>. - Преобразование цитат (
>) в<blockquote>с акцентной левой границей. - Слова внутри списков и цитат остаются кликабельными (интерактивный клик-перевод работает!).
- Преобразование маркированных (
- Заголовки Markdown (
##,###):- Конвертация в
<h3>,<h4>с удалением сырых решёток#.
- Конвертация в
- Таблицы Markdown (
| col | col |):- Адаптивные таблицы с рамками, стилизацией заголовков
<thead>, зебра-подсветкой строк и горизонтальным скроллом на мобильных. - Каждая ячейка поддерживает интерактивные слова для изучения и инлайн-код.
- Адаптивные таблицы с рамками, стилизацией заголовков
- HTML-блоки и теги в Markdown (
<p align="center">,<h1>,<em>,<strong>,<sub>,<br>):- Нативный парсинг через встроенный
DOMParserбез внешних библиотек. - Устранена утечка сырых тегов (
<picture>,<source>,<p align=...>) в словарные слова.
- Нативный парсинг через встроенный
- Ссылки и изображения (
[text](url),,<img>):- Поддержка бейджей shields.io, тренд-графиков и внешних картинок.
- Автоматическое скрытие битых/отсутствующих локальных путей (
assets/...) через обработчикonerror.
- Точное позиционирование окна перевода у курсора/слова (Popup Positioning):
- Исправлен баг двойного смещения координат: убран
window.scrollYприposition: fixed. - Окно перенесено в корень
<body>для исключения искажений контекста позиционирования. - Плавное отслеживание скролла через
requestAnimationFrameс автозакрытием при уходе слова за границы экрана или под липкую шапку.
- Исправлен баг двойного смещения координат: убран
- Стилизация в CSS (
app/static/css/style.css):- Добавлены стили для
.reader-content-body pre,code,blockquote,ul,ol,.reader-table,.reader-heading,.reader-link,.reader-img.
- Добавлены стили для
2. 🗜️ Сжатие статического трафика (GZipMiddleware)
- Подключить
GZipMiddleware(minimum_size=1000)вapp/main.py. - Сократить объём передаваемых файлов
app.js(111.8 КБ -> 21.5 КБ),index.html(55.2 КБ -> 10.3 КБ) иstyle.css(58.2 КБ -> 9.4 КБ) на 81.7% (суммарно с 225.2 КБ до 41.2 КБ). - Проверить заголовки
Content-Encoding: gzipв ответах и добавить регрессионный тест вtests/test_api.py.
3. 🛡️ Дедупликация слов и защита от повторного добавления (Reader + API)
- Проверка дубликатов на бэкенде (
POST /api/cards):- Проверка слова без учёта регистра
lower(trim(term)). - При повторном добавлении не создаётся дубликат, а дополняется контекстное предложение и объединяются теги, возвращается
already_exists: True.
- Проверка слова без учёта регистра
- Индикация в читалке и карточке поиска:
- В читалке при клике на слово и в карточке поиска выводится бейдж
⭐ В библиотеке. - Кнопка «+ В словарь» заменяется на бейдж
⭐ Слово уже в библиотекес опциональной кнопкой+ Добавить эту цитату к карточке.
- В читалке при клике на слово и в карточке поиска выводится бейдж
- Индекс целостности в SQLite:
- Создан
UNIQUE INDEX idx_vocab_user_term_nocase ON vocabulary_cards(user_id, term COLLATE NOCASE);гарантирующий отсутствие дубликатов на уровне движка БД заO(\log N).
- Создан
- Слияние существующих дубликатов в базе:
- Объединены дубликаты
admired(ID 5 и ID 7) иsuddenly/Suddenly(ID 2 и ID 9) с объединением контекстных предложений, слиянием тегов и сохранением прогресса SRS.
- Объединены дубликаты
4. 📱 Мобильная оптимизация и адаптивная верстка (iPhone 12 / iOS Safari)
- Системный фундамент iOS и сброс ограничений (Core Foundation):
- Метатег
viewport: добавитьviewport-fit=coverдля поддержки челки и нижней панели iPhone. - Устранение бага принудительного авто-зума: установить
font-size: 16pxдля<input>,<textarea>,<select>на экранах≤ 768px(сохраняя компактные внутренние отступы). - Замена
100vhна динамические единицы100dvh(Dynamic Viewport Height) для модальных окон, оверлеев и экрана авторизации. - Добавление безопасных отступов
env(safe-area-inset-top)иenv(safe-area-inset-bottom). - Предотвращение горизонтального скролла (
overflow-x: hiddenна уровне контейнера приложения).
- Метатег
- Мобильная навигация: переход к нативному паттерну (App Header + Bottom Tab Bar):
- Компактная верхняя шапка: логотип
📖 Notes, переключатель темы🌓, кнопка вызова профиля/действий. - Фиксированная нижняя панель вкладок (Bottom Tab Bar) с нативным iOS UX:
- 🔍 Словарь (Поиск и словарь)
- 🎓 Тренажёр (SRS с бейджем количества повторений)
- 📚 Читалка (Библиотека книг)
- 📊 Прогресс (Статистика и стрик)
- ⚙️ Меню (Смена пароля, экспорт, выход)
- Сохранение текущей десктопной строки без изменений на больших экранах (
> 768px).
- Компактная верхняя шапка: логотип
- Адаптация экрана словаря и карточек (Dictionary & Cards View):
- Поле поиска/перевода на полную ширину экрана с удобной сенсорной кнопкой «Перевести».
- Скрытие неактуальных десктопных подсказок горячих клавиш (
<kbd>Ctrl+Enter</kbd>) на мобильных устройствах. - Вертикальная раскладка полей метаданных при редактировании карточки (папка, теги, заметка).
- Горизонтальный скролл чипсов коллекций и тегов (
overflow-x: auto; white-space: nowrap; -webkit-overflow-scrolling: touch) вместо многострочного переноса. - Увеличенные зоны нажатия (Touch Targets ≥ 44px) для кнопок действий над карточкой (удаление, редактирование, озвучка).
- Интерактивная читалка и переход к Mobile Bottom Sheet:
- Трансформация всплывающего попапа перевода (
reader-word-popup) в нативную выдвижную нижнюю шторку (Bottom Sheet) на смартфонах:- Заголовок с термином, транскрипцией и бейджем
⭐ В библиотеке. - Блок перевода и контекстной цитаты книги.
- Большая кнопка «💾 Добавить в словарь» под большой палец.
- Исключение вылетов за границы экрана и перекрытия текста пальцем.
- Заголовок с термином, транскрипцией и бейджем
- Двухстрочный адаптивный тулбар читалки (навигация по главам + размер шрифта
A-/A+и подсветка). - Сетка библиотеки
bookshelf-gridв одну колонку на экранах≤ 640px.
- Трансформация всплывающего попапа перевода (
- Тренажёр интервальных повторений (SRS Trainer):
- Ограничение высоты карточки SRS (
max-height: 48dvh), чтобы карточка и кнопки оценки гарантированно помещались без вертикального скролла на 390px. - Кнопки оценки (Снова / Трудно / Хорошо / Легко) в сетку 2×2 с высотой от 50px и четкими цветовыми акцентами.
- Вертикальный список вариантов в режиме квиза (4 варианта) на всю ширину экрана.
- Ограничение высоты карточки SRS (
- Модальные окна (Статистика, Пароль, Экспорт):
- Метрики статистики в сетку 2×2 вместо сжатых 4 колонок.
- Плавный горизонтальный скролл календаря активности (Heatmap).
- Разворачивание модальных окон в адаптивный мобильный слой с удобной кнопкой закрытия.
5. 🔌 Пул соединений HTTP (httpx.AsyncClient с Keep-Alive)
- В
app/dictionary.pyсоздать синглтон-клиентget_http_client()с пулом соединений:limits = httpx.Limits(max_keepalive_connections=10, max_connections=20) - Заменить вызовы
async with httpx.AsyncClient()в парсерах на переиспользуемый клиент. - Устранить 5 повторных TCP/TLS хэндшейков на каждое слово, сократив пинг внешних запросов на 300–600 мс.
6. 🗄️ Тюнинг SQLite PRAGMA и составных индексов
- В
app/database.py:- Вынести
PRAGMA journal_mode=WAL;вinit_db()(убрать избыточный вызов при каждом запросе). - Включить параметры производительности памяти Linux:
conn.execute("PRAGMA synchronous = NORMAL;") conn.execute("PRAGMA mmap_size = 268435456;") # 256MB mmap conn.execute("PRAGMA cache_size = -32000;") # 32MB cache
- Вынести
- Обеспечить Zero-copy чтение страниц БД ядром Linux.
7. ✂️ Де-блоатинг внешних парсеров (YAGNI)
- Удалить лишний сетевой опрос Datamuse (
fetch_datamuse) — он дублирует определения и перегружает ответ нерелевантными рифмами. - Упростить хрупкий regex-парсинг разметки Wikitext, опираясь на стабильные REST JSON эндпоинты.
8. 📚 Локальный оффлайн-словарь (99%+ покрытия со словоформами, SQLite 10–20 МБ)
- Создать в SQLite таблицу:
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 мс прямо из оперативной памяти процесса). - Реализовать логику словарного поиска:
- Сначала запрос в
offline_dictionary\rightarrowмгновенный ответ за 0.1 мс. - Только при отсутствии слова в базе
\rightarrowfallback-запрос во внешнюю сеть.
- Сначала запрос в
- Полностью исключить исчерпание лимитов внешних API (MyMemory 100 req/day).
9. 🧩 Модульность фронтенда на нативных ES-модулях (без Webpack/Vite)
- Перевести
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(низший приоритет).
- Создать JavaScript-букмарклет для добавления слова/фразы из любого окна браузера в личный словарь
- Нативная автономная озвучка (HTML5 Web Speech API /
speechSynthesis):- Использовать встроенный в браузер синтезатор речи
window.speechSynthesis(en-US, en-GB). - 0 сетевых запросов к серверу, 100% оффлайн-работа.
- Поддержка озвучивания отдельных слов, фраз, идиом и предложений-контекстов читалки.
- Использовать встроенный в браузер синтезатор речи
- Возврат режима «Диктант» в SRS:
- Возобновление работы аудиотренажёра на базе нативного браузерного синтезатора речи без зависимости от внешних аудиофайлов.
🛠️ Правила и соглашения проекта (Ponytail Rules)
- Stdlib & Native First: стандартная библиотека языка и возможности платформы (браузера, SQLite, Linux) всегда приоритетнее внешних библиотек и микросервисов.
- Меньше кода — меньше багов: удаление кода и упрощение структуры всегда лучше усложнения.
- Безопасность: все мутации данных изолированы по
user_id, пароли защищены PBKDF2 с уникальной солью. - Тестирование: после каждого изменения запуск
pytest tests/test_api.py -v(100% тестов должны быть зелеными).