Files
laude/README.md
AnRil c9d4fc237e
Some checks failed
CI / Typecheck + Tests (push) Has been cancelled
CI / Build (Windows) (push) Has been cancelled
Release / Build installer + publish release (push) Has been cancelled
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>
2026-05-18 12:41:13 +07:00

94 lines
6.0 KiB
Markdown
Raw Permalink 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.
# Laude — Exercise Reminder
Windows desktop приложение, которое напоминает делать упражнения во время работы за компьютером. Опционально подключается к Dota 2 и после каждого матча превращает статистику (смерти, убийства, ассисты) в количество повторений.
[![release](https://img.shields.io/badge/release-v0.4.0-orange)](https://xn--90adajar8af4h.xn--p1ai/git/AnRil/laude/releases/latest)
[![tests](https://img.shields.io/badge/tests-33%20passing-green)]()
[![platform](https://img.shields.io/badge/platform-Windows%2010%2F11-blue)]()
## Что внутри
- **Гибкие напоминания** — любое количество упражнений, интервал от минуты до часов, разные иконки.
- **История и стрики** — 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)