f861af5db1ca262af3b17ec16257742403927d6c
13 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
f861af5db1 |
feat(updater): fixed-URL auto-update channel + silent retries
The auto-update system used a per-version publish URL
(releases/download/v${version}), so each installed build only ever
checked its own release page for new versions. To deliver an update we
had to manually copy the new manifest into every old release — easy to
forget, and any half-uploaded state showed users red "check failed"
banners.
Architectural fix:
- New rolling 'update-channel' Gitea release. publish.url is now a
fixed path (.../releases/download/update-channel) that never moves.
- release.ps1 uploads each new build to three places:
1. vX.Y.Z (historical archive + changelog)
2. update-channel (what every client polls)
3. -BridgeTags (transition: also fill in old releases so users
still on those versions can find the new build)
- upload-release-assets.ps1 gains -AssetVersion to upload version-X.Y.Z
artifacts into a non-version tag (channel/bridge).
Resilience fixes for the updater itself:
- Hourly checks and the boot check now run in SILENT mode: network
errors don't promote to a red error state, they're logged and
retried on the next tick. Only user-initiated "Check now" surfaces
errors. This prevents the cascade of "Ошибка проверки" cards on
flaky networks or partial uploads.
- Boot check retries up to 3 times (30s/2m/5m backoff) before giving
up until the hourly tick.
- Track lastCheckedAt; "Up to date" subtitle now shows "checked Nm ago".
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
|
||
|
|
c9d4fc237e |
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> |
||
|
|
973339ca62 |
feat(i18n): bilingual UI (Russian + English) + language selector
Все UI-строки приложения переведены и переключаются на лету через
Settings → Язык интерфейса.
== i18n архитектура ==
- src/renderer/src/i18n/dict.ts — плоский словарь ru/en с ~190 ключами,
поддержка интерполяции {var} и плюрализации
- src/renderer/src/i18n/index.ts — useT() React hook + чистые
translate/translateN функции (для ReminderApp вне store context)
- Settings.language: 'ru' | 'en', default 'ru'
- Изменение языка применяется немедленно через Zustand reactive update
== Что переведено ==
- Sidebar nav + slogan + status
- Titlebar window controls (aria-labels)
- Dashboard: hero, 3 stat-карточки (Активных / До следующего /
Трекинг матчей), Paused banner, empty state
- Exercises: hero, секции (активные / выключенные), row meta, empty
- Challenges: hero, formula subtitle, warning, row format
«{stat} × {mult} → {exercise}», empty
- Games: hero, status badges (Live/Ready/Queued/Installed/Not found),
queued/no_user banners, dev panel
- Settings: все секции + новый Language selector
- UpdaterCard: все состояния (checking/available/downloading/
downloaded/error/idle) с интерполяцией версии и MB/s
- ReminderApp: kicker «Время тренировки», reps подпись, snooze label
с динамическими минутами, кнопки done/skip
- Match summary: победа/поражение, плюрализация «N челлендж/-а/-ей»
vs «N challenge/-s»
- Format helpers (formatCountdown, formatInterval) — теперь принимают
Language параметр
== Локалезависимая дата ==
Dashboard hero показывает today в текущей локали:
ru-RU → "воскресенье, 17 мая"
en-US → "Sunday, May 17"
== STAT_LABELS bilingual ==
- shared/types.ts: STAT_LABELS_EN + statLabel(stat, lang) helper
- ChallengeResult получил поле stat?: GameStat (для resolve на стороне
renderer'а с актуальным языком, вместо baked-in label)
- main/games/registry.ts кладёт stat в результат
== Тесты ==
- src/renderer/src/i18n/i18n.test.ts: 10 кейсов
* translate: lookup, fallback, interpolation, multi-var, lang fallback
* translateN: ru plural rules (1/21/101 → one; 2-4 → few; 0/5-20 → many)
и en (1 → one, else → many)
- Всего 33 теста зелёные
== Известное ограничение ==
SAMPLE_EXERCISES (5-6 русских "Приседания / Отжимания / ...") остаются
русскими — это seed данных на первый запуск. Английский юзер сразу
переключит язык и сможет переименовать вручную. Делать seed-per-locale
оверкилл — слишком много кода ради малого.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
|
||
|
|
70eb4717ec |
release(v0.3.7): auto-check каждый час вместо 6
6 часов было выбрано произвольно как "вежливо для сервера". На практике слишком долго для backgound-приложения: новый релиз доезжает до пользователя только через полдня. Меняем на 1 час — все сравнимые приложения (Discord 30 мин, Slack 30 мин, VS Code 1 ч) используют похожие интервалы. Стартовая проверка (5 сек после запуска) остаётся. Нагрузка минимальна: запрос на latest.yml = 362 байта. UI текст «Авто-проверка раз в 6 часов» → «раз в час». Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> |
||
|
|
ee2dc19daa |
release(v0.3.4): шрифты — Plus Jakarta Sans + Bricolage Grotesque
Manrope воспринимался слишком строгим и корпоративным. Замена даёт больше характера и тёплый "попсовый" feel: - Body/UI: Manrope → Plus Jakarta Sans (мягкие округлые формы 'a' 'g', очень распространён в современных трендовых приложениях) - Display/hero: Fraunces → Bricolage Grotesque (variable шрифт с opsz axis: 24 для нормальных заголовков, 96 для hero — гротеск с характерными слегка сжатыми формами и большим контрастом штрихов) - Mono: JetBrains Mono без изменений Все hero-заголовки пробампаны до 34→40px и font-bold (700), Bricolage лучше всего смотрится в полужирном/жирном. Sidebar логотип «Laude» тоже font-bold. Также: - body line-height: 1.45 → 1.5 для лучшей читаемости - Reminder exercise name: 28→30, semibold→bold - Match summary title: 24→26, semibold→bold - Sidebar slogan: 12→13/medium, контраст 45→55 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> |
||
|
|
9b488164e0 |
release(v0.3.3): акцентная типография — все надписи крупнее и контрастнее
Жалоба: вторичные подписи (Активных / До следующего / Трекинг матчей / Возобнови чтобы продолжить отсчёт) выглядели мелко и плохо читались. Сделан sweep по всему UI: - Базовая шкала secondary text: 12px → 13-14px - Контрастность подписей: text-text/45 → text-text/65 (или /75 для лейблов) - font-medium → font-semibold для метаданных карточек Dashboard: - Дата: 13/font-medium → 14/font-semibold - HeroStat label: 12/medium/55 → 14/semibold/75 (вот эти "Активных" и пр.) - HeroStat value: 26/semibold → 28/bold - HeroStat subvalue: 12/45 → 13/60/medium - HeroStat icon plaque: 24px → 28px - Paused banner title: 14 → 16, hint: 12 → 14/70 - Иконка баннера 36→40px Settings: - ToggleRow/SelectRow label: medium → semibold - Hint: 12/55 → 13/65/medium - "Конфигурация": 13/45/medium → 14/65/semibold Exercises/Challenges (row + page): - Row title: 15/medium → 16/semibold - Row subtitle: 13/55 → 14/65/medium - Стат-метрики bold - Empty state: 14/55 → 15/65/medium - Warning banner: 13/80 → 14/85/medium + иконка крупнее Games: - Game title: 17/semibold → 18/bold - Install path subtitle: 12/45 → 13/55/medium - Queue/error banners: 13/80 → 14/85/medium + крупнее иконки и code ExerciseCard: - Title: 17/semibold → 18/bold - Reps meta: 13/55 → 14/65/medium - Countdown label "Через/Сейчас": 11/45 → 12/60/semibold - Countdown value: 22/semibold → 24/bold - "Готово" CTA: 14/semibold → 15/bold, h-10 → h-11 ReminderApp: - "Время тренировки" label: 12/45 → 13 + accent цвет + bold - "Раз" подпись: 14/55 → 15/65/semibold - "Следующее через": 12/45 → 13/65/medium - Match summary header: 11/45 → 12/65/semibold - Match summary subtitle: 12/45 → 13/65/medium - Match summary total: 12/55 → 13/65/medium + 14 → 16 для числа - ChallengeRow title: 14/medium → 15/semibold - ChallengeRow subtitle: 12/55 → 13/65/medium - CTA Готово: 15/semibold → 16/bold UpdaterCard: - Cell title medium → semibold - Cell subtitle: 12/55 → 13/65/medium - Иконка ячеек 36→40px - Progress download title medium → semibold + 18px процент Card SectionHeader: - 12/medium/45 → 13/semibold/60 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> |
||
|
|
aa60acb164 |
release(v0.3.2): новые шрифты, иконки сайдбара, light по умолчанию
== Шрифты == - Sans/display: Geist → Manrope (мягче, дружелюбнее, ближе к SF Rounded) - Serif (hero titles): Instrument Serif → Fraunces с opsz axis 144 - Mono: Geist Mono → JetBrains Mono с ss02/ss19/zero features == Размеры (iOS HIG calibration) == - Hero h1: 40-44px → 32-36px (ближе к настоящему iOS Large Title 34pt) - Reminder name: 32 → 28; reps counter: 64 → 56 - Match summary title: 22 → 24 - Dashboard stat value: 30 → 26 - Body line-height/letter-spacing подкручены под Manrope == Иконки сайдбара == - LayoutDashboard → Sun (Сегодня — утренняя энергия) - ListChecks → Dumbbell (Упражнения — спорт прямо) - Gamepad2 → Joystick (Игры — более игровая иконка) - Target → Flame (Челленджи — интенсивность) - Settings → Settings2 (немного объёмнее) - Размер плашки 28→32px, иконки 15→17px == Light theme == - DEFAULT_SETTINGS.theme: 'system' → 'light' (новые установки сразу получают светлую тему) - Light bg прогрет: 242,242,247 → 245,245,249 - surface-2 чуть темнее для лучшей сепарации полей ввода - text не pure black а 17,17,19 (легче глазам) - shadow-card получила тёплый slate-tinge Существующие пользователи с theme='system' продолжат следовать ОС. Для принудительного переключения — Settings → Тема → Светлая. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> |
||
|
|
c5a29214d2 |
redesign(ui): полный реворк в стиле Apple iOS/macOS
Ветка для нового интерфейса; main с предыдущим Strava-дизайном
не тронут — можно вернуться через checkout main.
== Design system (foundation) ==
- Шрифты: Geist (sans, display) + Geist Mono (HUD числа) +
Instrument Serif (hero titles) — все через Google Fonts. Близки
к SF Pro / SF Mono.
- Палитра: Apple Human Interface Guidelines
* accent: 255 107 53 (Apple Fitness Move orange)
* success: 52 199 89 (systemGreen — для switch)
* destructive: 255 59 48 (systemRed)
* info: 0 122 255 (systemBlue)
* warning: 255 159 10
* Light bg: 242 242 247 (iOS systemGroupedBackground)
* Dark bg: true black 0 0 0 (OLED-friendly), elevation через
28/44/56 grey steps как в iOS Settings
- Утилиты: .vibrancy (macOS Big Sur sidebar), .hairline-b/-t (0.5px
iOS-стиль), .shadow-card (soft layered), .font-display/-serif/-mono-num
== UI primitives ==
- Button: filled / tinted / plain / destructive / success (iOS UIButton);
active:scale-[0.97] press feedback. Старые имена primary/secondary/
ghost/danger/victory маппятся через legacyMap для совместимости.
- Switch: настоящий iOS UISwitch 51x31, spring физика knob, success
цвет on.
- Modal: центрированный sheet с rounded-3xl (22px), backdrop blur,
spring scale-in. Header с font-display, X в circle.
- Card + Row + SectionHeader: iOS grouped list — белая поверхность,
hairline-b dividers между rows, last={true} убирает последний.
== App frame ==
- Sidebar: vibrancy (semi-transparent + backdrop-blur saturate 180%),
font-serif лого, tinted icon-plaques на каждом пункте (как в iOS
Settings), плавный hover. Drawer на mobile со spring slide.
- Titlebar: центрированный title, window controls без glow, hamburger
только на <md.
- App.tsx: AnimatePresence cross-fade между маршрутами.
== Pages ==
- Dashboard: hero с font-serif Large Title + датой. 3-card Hero panel
(Apple Fitness style) с tinted icon squares. ExerciseCard теперь с
progress-ring вокруг иконки + появляющейся "Готово" pill только при
due. Three-dot menu (iOS-style popover).
- Exercises: групированный список iOS, разделение Активные/Выключенные,
chevron-right на каждом row.
- Challenges: тот же групированный паттерн + warning banner если игр
нет, formula preview карточка в редакторе с big number в accent.
- Games: cards в новом стиле, статус-чипы pulse-dot для LIVE, dev
кнопки в pill-стиле.
- Settings: классические iOS Settings секции с ToggleRow и SelectRow
inside Card. UpdaterCard полностью переработан под Cell pattern.
== Reminder window ==
- iOS action sheet: большая иконка в accent-circle сверху, font-serif
название упражнения, гигантское моноширинное число reps. Кнопки
стопкой: primary Готово full-width, потом snooze + skip в grid.
Хоткеи Enter/Space/Esc сохранены.
- Match summary: tone-цветной icon plaque (success/destructive/accent),
ChallengeRow с pill-shaped check button.
== Анимации ==
- Spring физика везде где layout (Switch knob, Modal, Sidebar drawer,
карточки)
- active:scale-[0.97] на всех интерактивных элементах (iOS touch feel)
- Cross-fade между страницами через AnimatePresence
- Никаких glow / pulse-ring — apple style это сдержанность
Verified: typecheck OK, 23 tests pass, build 36.35 KB CSS (на 6 KB
меньше предыдущего HUD-стиля), 1.56 MB JS.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
|
||
|
|
cec146ae3a |
redesign(ui): спортивная палитра Strava + полная адаптивность
== Цветовая гамма == Сменили esports cyan+violet на спортивную Strava-палитру: - accent: orange-500 (#F97316) — энергия, движение, "GO" - accent-2: rose-500 (#F43F5E) — интенсивность, gradient pair - victory: lime-500 — личный рекорд / готово - defeat: red-600 - xp: amber-500 Dark theme переведена с холодного navy на тёплый графит, light theme очищена в "athletic paper" feel. == Репозиционирование текста == Убрали esports-сленг в пользу спортивной лексики: - Sidebar: "Play hard · Train harder" → "Move every day" - Sidebar footer: "GSI-трекинг матчей" → "Трекинг активности" - Dashboard микрозаголовок: "Mission control" → "Тренировка дня" - Dashboard HUD: "Cooldown / READY" → "До следующего / СЕЙЧАС", "Game tracking / LIVE / OFF" → "Трекинг матчей / LIVE / OFF" - Exercises: "Loadout" → "Программа" - Games: "Game integrations" → "Трекинг матчей" - Challenges: "Match rules" → "Правила за матч" - Settings: "Config" → "Конфигурация" - ExerciseCard: "Cooldown / PAUSED" → "Через / пауза" - ReminderApp: "Cooldown ready" → "Время тренировки", "Время размяться" → "Двигайся", "Next drop" → "Следующее", "Victory · упражнения заработаны" → "Победа · тренировка заработана", "Defeat · но тело — нет" → "Проигрыш · но тело не сдаётся", "all clear" → "готово", "Total / reps" → "Всего / повторов", "GG" → "Готово" == Адаптивная вёрстка == - App.tsx: state mobileNavOpen, авто-закрытие drawer на route change - Sidebar: три режима через CSS breakpoints — * lg+ (≥1024px): полная ширина w-60 с лейблами * md (768-1023px): icon-only w-16 с title-тултипами * <md (<768px): скрыта, открывается drawer-ом по hamburger - Titlebar: hamburger button слева на <md, title скрывается на <sm - Все hero-блоки страниц: flex-col на sm, flex-row sm:items-end sm:justify-between с stack gap-4 - Padding страниц: p-4 sm:p-6 lg:p-8 вместо p-8 - Hero h1: text-3xl sm:text-4xl - Dashboard HUD strip: grid-cols-2 lg:grid-cols-4 (было 1/2/4) - Action buttons в карточках/строках: opacity-100 lg:opacity-0 lg:group-hover (на узких экранах всегда видны) - GameRow buttons: flex-wrap для длинных лейблов - Dashboard challenges shortcut: hint hidden sm:block - Sidebar mobile drawer: framer-motion слайд + backdrop с blur Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> |
||
|
|
92e15e69a3 |
feat: auto-update, тесты и CI/CD
Полная автоматизация релизного цикла. == Auto-update (electron-updater) == - src/main/updater.ts — обёртка над autoUpdater с дискриминированным UpdaterStatus union и broadcast через IPC. autoDownload=false, пользователь сам жмёт «Скачать». allowDowngrade=false. Проверка каждые 6 часов, первая через 5с после старта. - В dev-режиме (app.isPackaged=false) статус сразу становится 'unsupported' с пояснением — никаких exceptions из updater'а. - build.publish в package.json: provider=generic, url указывает на Gitea release assets конкретной версии. - src/main/ipc.ts: 4 новых канала — status/check/download/install. - src/preload: API window.api.updater* + onUpdaterStatus. - src/renderer/src/components/UpdaterCard.tsx: HUD-карточка в Settings с состояниями idle/checking/available/downloading/downloaded/error, прогресс-бар с скоростью в МБ/с. == Тесты (vitest) == - vitest.config.ts с алиасами @shared / @renderer - 23 теста, все зелёные: * format.test.ts — formatCountdown, formatInterval (8 cases) * vdf.test.ts — parseVdf / stringifyVdf / round-trip (11 cases) * types.test.ts — DEFAULT_SETTINGS, SAMPLE_EXERCISES sanity (4) - npm scripts: test (watch), test:run (CI) == CI/CD (Gitea Actions) == - .gitea/workflows/ci.yml — на push/PR: typecheck + тесты + smoke-сборка - .gitea/workflows/release.yml — на тег v*.*.*: сборка NSIS + Gitea release == Локальный релизный скрипт == - scripts/release.ps1 — один скрипт от бампа версии до публикации через Gitea API (params: -Bump patch/minor/major, -Version, -DryRun) - npm run release — обёртка - RELEASING.md — полная инструкция Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> |
||
|
|
d418b9bbd2 |
redesign(ui): phase 2 — все вторичные страницы и UI-примитивы
Распространили esports-HUD язык на оставшиеся экраны и общие UI:
- Modal: neon border accent/25 с двойным glow (cyan + violet),
gradient-divider, gradient-stripe слева от заголовка, defeat hover
на закрытие
- Switch: bg-gradient-brand с shadow-glow в on-состоянии
- Exercises: hero с gradient-text, статистика в моноширинном шрифте
(active count, total reps за цикл), HUD-список с анимированным
появлением, hover-row с accent tint
- Games: game cards с gradient orb-иконкой + glow на интегрированных,
shadow-glow-victory + анимированная LIVE точка для активной
интеграции, новые status badges (LIVE / READY / QUEUED / INSTALLED /
NOT FOUND) в display-шрифте, ошибки в защитных цветах (xp/defeat)
- Challenges: hero + formula-row "stat × N → reps" в моноширинном
шрифте, gradient-preview карточка в редакторе с большим итоговым
числом в text-gradient-brand
- Settings: hero, секции с иконкой в accent-плашке, заголовки секций
в display-шрифте uppercase tracking-wide
- ExerciseEditor: preview-карточка с gradient-orb иконкой в шапке
модала, моноширинные input для чисел, scale-up на выбранной иконке
Все правки используют существующие токены из phase 1 — никаких новых
CSS-переменных или конфигов.
Откат phase 2 один: git revert HEAD
Откат до начала редизайна: git reset --hard
|
||
|
|
4da83761d2 |
redesign(ui): phase 1 — esports HUD design system + core surfaces
Сменили визуальную ДНК на dark-first гейминг-эстетику: cyan→violet
неоновая палитра, спортивный display-шрифт Rajdhani, моноширинный
HUD для всех счётчиков, градиентные CTA с glow.
Дизайн-система (globals.css + tailwind.config.js):
- Brand-токены accent (cyan), accent-2 (violet), victory (lime),
defeat (rose), xp (amber); --bg-deep слой
- Утилиты .neon-border (анимированный обводный градиент),
.hud-pulse, .hud-scanlines, .dot-grid, .text-gradient-brand,
.bg-gradient-brand/-victory/-defeat
- Радиальные градиенты на body (cyan/violet glow по углам)
- Шрифты Rajdhani (display) и JetBrains Mono подключены через CDN
Компоненты:
- Sidebar: gradient-логотип, активный пункт с вертикальной gradient-
полосой и shadow-glow, статус-чип GSI tracking
- Titlebar: glass + scanlines, моноширинный лейбл, defeat hover на X
- Button: primary = bg-gradient-brand + shadow-glow; новый variant
victory (lime-gradient)
- ExerciseCard: SVG cooldown-ring как у способностей в MOBA,
градиентный stroke с drop-shadow, .neon-border на due, hover lift
- Dashboard: hero с gradient-text заголовком, HUD-полоса из 4 stat-
карточек (Cooldown / Active / Avg / Game tracking LIVE/OFF)
- ReminderApp: вращающийся conic-gradient вокруг иконки, HUD-блок
reps в моноширинном шрифте, кнопки с подписями хоткеев,
Match summary с heroGradient по результату (victory/defeat/brand)
ThemeProvider больше не перезаписывает --accent системным —
у laude теперь стабильная brand-идентичность.
Бонус: хоткеи на reminder-окне (Enter=done, Space=snooze, Esc=skip).
Откат: git revert HEAD или git reset --hard
|
||
|
|
688a86b611 | Initial commit |