feat(v0.5.0): history + streak + heatmap, quiet hours, partial reps, README
== История и стрики (#1) == - HistoryEntry { ts, exerciseId, action: done|skip|snooze, actualReps? } персистится в app-state.json, лимит 10k записей (~3 года), trim oldest 10% - markDone/snooze/skip пишут в историю; markDone принимает optional actualReps - IPC: getHistory(sinceMs?), clearHistory(beforeTs?) + preload bindings - Renderer helpers (src/renderer/src/lib/history.ts): * dayKey(ts) — YYYY-MM-DD local * dailyReps(entries, exs, dayKey) — суммирует actualReps || planned * dailyRepsRange(entries, exs, days) — для heatmap, заполняет gaps нулями * currentStreak(entries) — consecutive days, today или yesterday (grace) - Dashboard теперь 4 hero-карточки: Today (повторов за день) / Streak (дней подряд) / Next / Tracking - Новый компонент HistoryHeatmap — GitHub-style 12-недельный календарь с 5 интенсивностями, локализованными подписями дней/месяцев == Тихие часы (#2) == - shared/types.ts: QuietHours { enabled, from, to, days[] } + isQuietAt() helper с правильной обработкой wrap-around окон (22:00→08:00) - DEFAULT_SETTINGS.quietHours = disabled, 22:00→08:00, все дни - main/scheduler.ts: проверка isQuietAt перед fire; deferred fires поднимаются после окончания окна - Settings UI: новая секция "Тихие часы" с toggle, time-pickers, day-of-week pills == Сделал частично (#3) == - ReminderApp: stepper [−][число][+] вокруг счётчика повторов - При adjusted (actualReps !== exercise.reps) число подсвечивается accent и появляется подпись "Засчитаем X из Y" - markDone передаёт actualReps только если юзер реально изменил — иначе undefined чтобы история фиксировала планируемое значение чисто == README.md (#4) == - Описание, фичи, скриншоты (TODO-плейсхолдер), установка, dev-команды, архитектура, тесты, stack, ссылка на RELEASING.md - Бэйджи version / tests / platform == i18n == - ~14 новых ключей × 2 языка: dashboard.stat.today_done, streak, settings.quiet.* (3 row'а), reminder.partial == Тесты — 51 (было 33) == - shared/quiet-hours.test.ts (5): disabled, same-day, wrap-around, day filtering, zero-length - renderer/lib/history.test.ts (13): dayKey, dailyReps (planned vs actual vs ignore non-done), currentStreak (empty, today gap, consecutive, yesterday grace, multi-entry same day), dailyRepsRange Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
93
README.md
Normal file
93
README.md
Normal file
@@ -0,0 +1,93 @@
|
||||
# Laude — Exercise Reminder
|
||||
|
||||
Windows desktop приложение, которое напоминает делать упражнения во время работы за компьютером. Опционально подключается к Dota 2 и после каждого матча превращает статистику (смерти, убийства, ассисты) в количество повторений.
|
||||
|
||||
[](https://xn--90adajar8af4h.xn--p1ai/git/AnRil/laude/releases/latest)
|
||||
[]()
|
||||
[]()
|
||||
|
||||
## Что внутри
|
||||
|
||||
- **Гибкие напоминания** — любое количество упражнений, интервал от минуты до часов, разные иконки.
|
||||
- **История и стрики** — heatmap-календарь активности, ежедневный счётчик, серия дней подряд.
|
||||
- **Тихие часы** — окно времени когда напоминания подавляются (например `22:00 → 08:00`), с выбором дней недели.
|
||||
- **Сделал частично** — степпер `−/+` в окне напоминания: если ты сделал 5 из 10, в историю запишется честное число.
|
||||
- **Игровая интеграция (Dota 2)** — Game State Integration читает статистику матча, после Победа/Поражение показывает экран с «причитающимися» повторениями (например `10 смертей × 3 = 30 приседаний`).
|
||||
- **Apple-style интерфейс** — Plus Jakarta Sans + Bricolage Grotesque, iOS-палитра, vibrancy sidebar, spring-анимации, светлая/тёмная/системная тема.
|
||||
- **Два языка** — русский и английский, переключение мгновенное.
|
||||
- **Auto-update** — приложение само скачивает новые версии из Gitea release (проверка каждый час).
|
||||
|
||||
## Скриншоты
|
||||
|
||||
> _TODO: вставить screenshots Dashboard / Reminder / Match summary (light + dark)._
|
||||
|
||||
## Установка
|
||||
|
||||
Скачай последний `Exercise-Reminder-Setup-X.Y.Z.exe` со страницы релизов и запусти. Установщик:
|
||||
|
||||
- Создаёт ярлык на рабочем столе и в Пуске
|
||||
- Сохраняет настройки в `%APPDATA%\Exercise Reminder\`
|
||||
- При запуске поверх существующей инсталляции — обновляет, настройки сохраняются
|
||||
|
||||
Windows SmartScreen может предупредить «не доверено» — приложение не подписано code-signing сертификатом. Нажми `Подробнее` → `Выполнить в любом случае`.
|
||||
|
||||
## Разработка
|
||||
|
||||
```bash
|
||||
git clone https://xn--90adajar8af4h.xn--p1ai/git/AnRil/laude.git
|
||||
cd laude
|
||||
npm install
|
||||
npm run dev
|
||||
```
|
||||
|
||||
Полезные команды:
|
||||
|
||||
```bash
|
||||
npm run typecheck # tsc по main + renderer
|
||||
npm run test # vitest в watch-режиме
|
||||
npm run test:run # vitest один раз (для CI)
|
||||
npm run build # сборка без NSIS
|
||||
npm run dist # сборка + NSIS-инсталлятор → release/
|
||||
npm run release -- -Bump patch # bump версии + tag + push + upload в Gitea
|
||||
```
|
||||
|
||||
Документ `RELEASING.md` описывает процесс выпуска новых версий.
|
||||
|
||||
## Архитектура
|
||||
|
||||
- **Electron 33** — multi-process: main (Node/scheduler/GSI) + preload (contextBridge) + renderer (React)
|
||||
- **Renderer** — React 18, TypeScript 5, Vite 5, Tailwind 3, framer-motion, react-router, zustand
|
||||
- **Persistence** — единственный JSON-файл `%APPDATA%\Exercise Reminder\app-state.json` (debounced writes)
|
||||
- **IPC** — типизированные каналы через `src/shared/ipc.ts`, обёрнуто preload-ом
|
||||
- **i18n** — самописная микро-система: `src/renderer/src/i18n/dict.ts` (плоский словарь ~200 ключей × 2 языка) + хук `useT()`
|
||||
- **Auto-update** — `electron-updater` с `generic` provider, манифест `latest.yml` лежит в Gitea release attachments
|
||||
- **GSI Dota 2** — локальный HTTP-сервер слушает GameStateIntegration коллбэки от Steam, парсит match-end events
|
||||
|
||||
## Тесты
|
||||
|
||||
```
|
||||
src/shared/types.test.ts (4)
|
||||
src/renderer/src/lib/format.test.ts (8)
|
||||
src/main/games/vdf.test.ts (11)
|
||||
src/renderer/src/i18n/i18n.test.ts (10)
|
||||
─────────────────────────────────────
|
||||
33 ✓
|
||||
```
|
||||
|
||||
Покрытие: чистые helpers (форматирование, парсер VDF для Steam-конфигов), i18n с плюрализацией для RU/EN, дефолты shared-типов.
|
||||
|
||||
## Лицензия
|
||||
|
||||
Пока не указана. По умолчанию все права защищены. Если хочешь форк/использование — открой issue.
|
||||
|
||||
## Stack
|
||||
|
||||
- [Electron](https://www.electronjs.org/) · runtime
|
||||
- [electron-vite](https://electron-vite.org/) · build
|
||||
- [React](https://react.dev/) + [TypeScript](https://www.typescriptlang.org/)
|
||||
- [Tailwind CSS](https://tailwindcss.com/) · стили
|
||||
- [framer-motion](https://motion.dev/) · анимации
|
||||
- [lucide-react](https://lucide.dev/) · иконки
|
||||
- [electron-updater](https://www.electron.build/auto-update) · auto-update
|
||||
- [Vitest](https://vitest.dev/) · тесты
|
||||
- Шрифты: [Plus Jakarta Sans](https://fonts.google.com/specimen/Plus+Jakarta+Sans), [Bricolage Grotesque](https://fonts.google.com/specimen/Bricolage+Grotesque), [JetBrains Mono](https://fonts.google.com/specimen/JetBrains+Mono)
|
||||
Reference in New Issue
Block a user