14 KiB
Changelog
Все заметные изменения проекта документируются здесь. Формат основан на Keep a Changelog, проект следует Semantic Versioning.
Unreleased
0.5.4 — 2026-05-19
Обновление приложения теперь по-настоящему фоновое + почти моментальный рестарт в новую версию.
Changed
- Скачивание апдейта — фоновое. Раньше клик «Скачать» блокировал
кнопку (
busy=true) до конца download'а (минуты на медленной сети). Теперь IPCupdaterDownload— fire-and-forget, прогресс приходит через события. Пользователь сразу может уйти на Dashboard и продолжать упражнения, апдейт качается в фоне. - «Рестарт» — почти моментальный.
quitAndInstall(true, true): isSilent=true — NSIS без UI установщика (~1-2 сек вместо ~5-10), isForceRunAfter=true — гарантия что приложение откроется после. Раньше показывался диалог установщика с прогрессом, теперь — только мгновение между закрытием и появлением новой версии. - Подсказка на экране скачивания: «можно закрыть это окно, продолжится в фоне». На downloaded-экране: «нажми Рестарт — приложение моментально откроется в новой версии».
0.5.3 — 2026-05-19
Полировка кастомного тайтлбара и размера окна.
Added
- Maximize/Restore. Средняя кнопка тайтлбара (иконка квадрата)
раньше была «спрятать в трей» — выглядела как нативная Windows
maximize и сбивала с толку. Теперь это настоящий toggle на
весь экран: иконка свапается
Square↔Copyв зависимости от состояния, aria-label локализован. - Double-click по тайтлбару тоже toggleMaximize — стандартный Windows-жест.
- CLAUDE.md в корне — контекст проекта для будущих сессий Claude Code (стек, архитектура, команды, тех. долг).
Fixed
- Drag-зона тайтлбара. Окно не двигалось, если хватать его
рядом с кнопками свернуть/закрыть. Класс
titlebar-nodragстоял на обёртке кластера сflex-1 basis-0, поэтому пустое место слева от иконок тоже было no-drag. Перенеслиno-dragна сами кнопки — теперь тащить можно отовсюду, кроме самих квадратиков.
Changed
- Минимальный размер окна 900×600 → 1100×700. Гарантирует
срабатывание Tailwind
lg:(4 hero-stat в один ряд, heatmap и сетка упражнений помещаются без горизонтального скролла).
0.5.2 — 2026-05-19
Большая внутренняя итерация: тройной независимый аудит (~220 находок), закрыты топ-приоритеты. Тестов 53, ESLint и Prettier чистые, typecheck OK.
Added
- Prettier + ESLint + EditorConfig. Конфиги, скрипты
npm run format/format:check/lint, CI-готовые правила. Всяsrc/единообразно отформатирована. - Error Boundary на двух уровнях: вокруг всего App и вокруг роутов. Крах одной страницы (например, malformed history в HistoryHeatmap) больше не блэнкит окно — показывается локализованный fallback с кнопкой «Попробовать снова». Stack trace только в dev.
- IPC validation layer (
src/main/validate.ts) — hand-rolled схемы для всех renderer-supplied payload (intervalMinutes ∈ [1,1440], reps ∈ [1,9999], multiplier ∈ [0,1000], string-cap 200 chars, enum-валидация для theme/lang/notify-mode/stat, regex для HH:MM, дедупликация quietHours.days). Compromised renderer больше не может засунутьreps: NaNилиintervalMinutes: -1в стор. - Schema migrations framework.
__schemaVersionв persisted-state,MIGRATIONSmap для будущих структурных правок. - Modal focus trap + focus restore + aria-labelledby. Tab/Shift-Tab больше не вываливаются на нижний слой; на закрытии фокус возвращается на триггер.
- Sidebar mobile drawer: Esc закрывает, focus trap внутри, focus
restore на гамбургер,
role="dialog"+aria-modal. - Tray menu i18n — пункты меню следуют
settings.language. - Bilingual heatmap. Title, легенда, weekday-лейблы и tooltip
с плюрализацией (1 повтор / 2 повтора / 5 повторов) — всё через
i18n. 7 новых ключей
weekday.short.*. - CHANGELOG.md по формату Keep a Changelog.
Fixed
- Critical: данные больше не теряются на corrupt JSON. Раньше
catch → makeInitial()молча затирал упражнения/историю. Теперь файл уезжает вapp-state.json.corrupt-<timestamp>. - Atomic write через
.tmp+ rename + retry на EBUSY/EPERM (антивирус, OneDrive). Раньше обрыв питания мог дать truncate. - HIGH security: GSI server теперь верифицирует auth.token
через
timingSafeEqualпротив per-install токена. Раньше эндпоинт был полностью неаутентифицирован — любой локальный процесс мог подделать match-end. - HIGH security:
shell.openExternalallowlist — толькоhttp/https/mailto. Раньшеfile:/javascript:/steam:уходили в OS handler. - HIGH security: dev IPC
simulateMatchEndубран из production билдов (gate на!app.isPackaged+import.meta.env.MODE). - HIGH security: GSI server reject
Origin/Sec-Fetch-Site— блокирует CSRF от browser-вкладок. Body cap 256 KB (OOM-вектор закрыт). Requireapplication/json. Generic 400 без error-echo. isQuietAtwrap-around + day filter. С22:00 → 07:00, days=[Mon..Fri]теперь правильно проверяется день начала окна (старт Fri 22:00 → активно ночью Sat 02:00).- DST drift в
history.ts. Календарная арифметика (setDate) вместо ms-арифметики — на границе DST дни больше не дублируются. - Scheduler:
broadcastState()после fire, защита от двойной регистрацииpowerMonitorlisteners. - Settings IPC chatter. QuietTimesRow держит локальное состояние,
IPC летит только на
onBlur. Раньше скрабинг времени давал ~5 IPC, каждый переписывалapp-state.json. - Dashboard «До следующего» показывает
—при паузе вместо обманчиво тикающего таймера. - HistoryHeatmap percentile-bucketing (p25/p50/p85) вместо относительной шкалы — outlier-день больше не схлопывает все нормальные дни в самый слабый бакет.
- ReminderApp: Enter теперь корректно передаёт adjusted reps
(раньше всегда planned).
key={exercise.id+nextFireAt}сбрасывает степпер на новом fire. Степпер capped at 5× planned. Space не работает когда фокус на кнопке. Esc закрывает MatchSummary. i18n.translate— split/join вместо regex (var-значения с регулярными метасимволами теперь интерполируются буквально).icon.tsxlookup сужен доICON_CHOICES— произвольное имя больше не зарезолвится вLucide.default.- UpdaterCard NaN guard на download-progress (electron-updater даёт undefined в ранних событиях).
format.tsguard от NaN/Infinity вformatCountdown.updateExercise/updateChallengeстрипаютidиз patch — рендер не может перезаписать identity.- clearHistory(undefined) теперь no-op (нужен явный boundary).
Removed
.gitea/workflows/*.yml— без runners оставляли queued runs. Релизим черезrelease.ps1. has_actions на репо выключен.
0.5.1 — 2026-05-18
Fixed
- Auto-update архитектурно переписан. Раньше
publish.urlвключал${version}и запекался в каждый билд — установленные копии видели только свой собственный релиз. Введён фиксированный…/releases/download/update-channel, который никогда не меняется. - Hourly auto-проверка работает в silent-режиме: транзитные сетевые ошибки (504, TLS drops) больше не показывают красный баннер «Ошибка проверки». Только ручной клик «Проверить» поднимает ошибку.
- Boot-check ретраит 3 раза с backoff 30s/2m/5m.
- В
Up to dateпоказывается «проверено N мин назад». release.ps1теперь публикует в три-четыре места одной командой: vX.Y.Z, update-channel, и переданные-BridgeTagsдля миграции пользователей со старых версий.upload-release-assets.ps1ретраит curl до 4 раз с backoff на 504 / TLS-сбрасывание; до ретрая проверяет, не залился ли файл на самом деле (Gitea часто принимает body, но таймаутит ответ).- Скрипты — ASCII-only (PS5.1 без BOM падает на em-dash).
Removed
.gitea/workflows/*.yml— Gitea Actions без настроенных runners оставляли queued runs в репозитории. Релизим черезrelease.ps1.
0.5.0 — 2026-05-18
Added
- История + стрики. Каждое выполненное упражнение пишется в
app-state.json(cap 10k записей, trim oldest 10% на overflow). Heatmap-календарь 12 недель на Dashboard, ежедневный счётчик «сделано сегодня», серия дней подряд (с grace-периодом за вчера). - Тихие часы. Окно времени, в которое напоминания подавляются. Поддержка wrap-around (22:00 → 08:00) и фильтра по дням недели.
- Частичное выполнение. Степпер
−/+в окне напоминания: можно отметить «сделал 5 из 10», в историю запишется честное число. - README.md на русском — описание, фичи, установка, dev-команды, архитектура, стек.
Changed
markDone(id, actualReps?)принимает фактическое число повторений.
Tests
+18тестов (5 для тихих часов, 13 для истории/стриков). Всего 51.
0.4.0 — 2026-05-17
Added
- Английская локализация. Самописная i18n: плоский словарь
~200 ключей × 2 языка + хук
useT()+ плюрализация (CLDR rules для RU: one/few/many). - Селектор языка в Settings, переключение мгновенное.
[0.3.x] — 2026-05-17
Серия мелких релизов с дизайн-итерациями (Apple iOS / macOS aesthetic): шрифты Plus Jakarta Sans + Bricolage Grotesque, светлая/тёмная/системная тема, vibrancy sidebar, iOS-grouped lists, spring-анимации.
0.2.0 — 2026-05-16
Added
- Dota 2 Game State Integration: локальный HTTP-сервер парсит callbacks
от Steam, после Победа/Поражение показывает «причитающиеся»
повторения (например
10 смертей × 3 = 30 приседаний).
[0.1.x] — 2026-05-15 .. 2026-05-16
Первые публичные сборки: ядро напоминаний (упражнения, интервалы, иконки), системный трей, автозапуск с Windows, native-уведомления, NSIS-инсталлятор, auto-update через electron-updater.