Files
laude/src/shared/release-notes.ts
2026-06-09 00:56:40 +07:00

572 lines
20 KiB
TypeScript
Raw 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.
/**
* Заметки релизов для UI «Что нового». Хардкодные — синхронизируются
* с CHANGELOG.md руками при релизе. Не парсим .md в runtime: лишняя
* сложность, плюс отделение «коротких заметок для пользователя» от
* «развёрнутого технического CHANGELOG'а».
*
* Формат: версия → язык → массив пунктов (короткий заголовок + опц. деталь).
* Не более 5-7 пунктов на версию, иначе пользователь скроллит.
*/
import type { Language } from './types'
export type ReleaseNoteItem = {
/** Лаконичная строка-заголовок (≤ 60 символов). */
title: string
/** Опциональная одна строка-деталь (≤ 140 символов). */
detail?: string
/** Категория для tint'а иконки. */
tag?: 'new' | 'fix' | 'security' | 'perf'
}
export type ReleaseNotes = Record<Language, ReleaseNoteItem[]>
export const RELEASE_NOTES: Record<string, ReleaseNotes> = {
'0.6.6': {
ru: [
{
title: 'Настройки стали панелью состояния',
detail:
'Сверху видно, работают ли напоминания, включены ли тихие часы, встречи и запуск вместе с Windows.',
tag: 'new'
},
{
title: 'Главный экран стал точнее по текстам',
detail:
'Дата больше не кричит заглавными буквами, а цели показывают понятные единицы: “осталось 30 раз”.',
tag: 'fix'
},
{
title: 'Сводные карточки читаются лучше',
detail:
'Длинные значения в карточках больше не обрезаются, а сетка спокойнее держит десктопные ширины.',
tag: 'fix'
},
{
title: 'Безопасный стенд для проверки интерфейса',
detail:
'Добавлен dev:renderer: можно открыть UI в браузере с демо-данными и не трогать реальные настройки.',
tag: 'new'
}
],
en: [
{
title: 'Settings now show app status first',
detail:
'The top panel shows whether reminders, quiet hours, meeting pause and Windows autostart are active.',
tag: 'new'
},
{
title: 'Overview copy is clearer',
detail:
'The date no longer gets artificial capitalization, and goals show units like “30 reps left”.',
tag: 'fix'
},
{
title: 'Summary cards are easier to read',
detail:
'Long values no longer get clipped, and the card grid behaves better on desktop widths.',
tag: 'fix'
},
{
title: 'Safe renderer preview for UI checks',
detail:
'Added dev:renderer so the UI can be opened with demo data without touching real settings.',
tag: 'new'
}
]
},
'0.6.5': {
ru: [
{
title: 'Главный экран стал обзором действий',
detail:
'Верхний заголовок теперь показывает состояние: что сделать сейчас, что ждёт, пауза или встреча.',
tag: 'new'
},
{
title: 'Исправлен запуск с Windows',
detail:
'Проверка автозапуска теперь использует тот же путь и аргументы, что и запись в Windows.',
tag: 'fix'
},
{
title: 'Discord больше не ставит перерывы на паузу',
detail:
'Авто-пауза встреч реагирует на Zoom, Teams, Webex и Slack-huddle, но не на обычный Discord.',
tag: 'fix'
}
],
en: [
{
title: 'The main screen is now an action overview',
detail:
'The header shows the current state: what to do now, what is due, pause or meeting.',
tag: 'new'
},
{
title: 'Fixed Start with Windows',
detail:
'Autostart now reads Windows login items with the same path and arguments it writes.',
tag: 'fix'
},
{
title: 'Discord no longer pauses breaks',
detail:
'Meeting auto-pause still handles Zoom, Teams, Webex and Slack-huddle, but ignores Discord.',
tag: 'fix'
}
]
},
'0.6.4': {
ru: [
{
title: 'Новый видимый бренд “Разомнись”',
detail:
'Название стало короче и понятнее для русской аудитории: действие видно сразу.',
tag: 'new'
},
{
title: 'Сводки на каждом экране',
detail:
'Упражнения, питание, игры, челленджи и настройки теперь быстрее сканируются сверху.',
tag: 'new'
},
{
title: 'Улучшена структура вторичных страниц',
detail:
'Важные статусы вынесены выше списков, чтобы сразу видеть активность и проблемные места.',
tag: 'new'
}
],
en: [
{
title: 'New visible “Razomnis” brand',
detail:
'The name is shorter and more action-focused for the Russian audience.',
tag: 'new'
},
{
title: 'Overview cards on every screen',
detail:
'Exercises, meals, games, challenges and settings are easier to scan from the top.',
tag: 'new'
},
{
title: 'Secondary pages are more structured',
detail:
'Important statuses moved above long lists so active and risky areas are visible immediately.',
tag: 'new'
}
]
},
'0.6.3': {
ru: [
{
title: 'Новый главный экран “Не Залипай”',
detail:
'Сегодня теперь показывает не только план, но и недельный ритм, уровень и игровые долги.',
tag: 'new'
},
{
title: 'Мини-челленджи недели',
detail:
'5 дней без нуля, 1000 повторов, “сегодня не ноль” и закрытые катки считаются автоматически.',
tag: 'new'
},
{
title: 'Игровой долг после каток',
detail:
'На Dashboard видно, сколько Dota-долгов закрыто сегодня и за неделю.',
tag: 'new'
},
{
title: 'Мягкая система уровней',
detail:
'XP считается из повторов, активных дней и закрытых игровых челленджей.',
tag: 'new'
}
],
en: [
{
title: 'New “Ne Zalipay” Today screen',
detail:
'Today now shows the day plan, weekly rhythm, level and game debts.',
tag: 'new'
},
{
title: 'Weekly mini-challenges',
detail:
'5 non-zero days, 1000 reps, “today is not zero” and closed matches are tracked automatically.',
tag: 'new'
},
{
title: 'Game debt after matches',
detail:
'Dashboard shows how many Dota debts were closed today and this week.',
tag: 'new'
},
{
title: 'Soft level system',
detail:
'XP comes from reps, active days and completed game challenges.',
tag: 'new'
}
]
},
'0.5.8': {
ru: [
{
title: 'Heatmap и стрик обновляются сразу после нажатия «Готово»',
detail:
'Был регресс — статистика не обновлялась пока не изменишь упражнение. Починено через новое событие evtHistoryChanged.',
tag: 'fix'
},
{
title: 'Двойной клик на ✓ больше не пишет 2 раза',
detail:
'Rapid double-click на ✓ в Match Summary и «Готово» давал лишние повторы в стрик. Добавлен ref-based дедуп.',
tag: 'fix'
},
{
title: 'Native save/open dialogs локализованы',
tag: 'fix'
},
{
title: '+18 тестов на новые модули',
detail:
'achievements, match-challenge edge cases, deleted exercise survival.',
tag: 'new'
}
],
en: [
{
title: 'Heatmap and streak update immediately after pressing "Done"',
detail:
'There was a regression — stats did not update until you edited an exercise. Fixed via new evtHistoryChanged event.',
tag: 'fix'
},
{
title: 'Double-click on ✓ no longer writes twice',
detail:
'Rapid double-click on ✓ in Match Summary and "Done" added extra reps to streak. ref-based dedup.',
tag: 'fix'
},
{
title: 'Native save/open dialogs localised',
tag: 'fix'
},
{
title: '+18 tests for new modules',
detail:
'achievements, match-challenge edge cases, deleted exercise survival.',
tag: 'new'
}
]
},
'0.5.7': {
ru: [
{
title: 'Челленджи из матчей идут в историю',
detail:
'Раньше ✓ в Match Summary не считался — стрик и достижения игнорировали игровые тренировки. Исправлено.',
tag: 'fix'
},
{
title: 'Пауза из трея и из Dashboard теперь синхронизированы',
detail: 'Раньше Dashboard показывал «running» когда tray был на паузе.',
tag: 'fix'
},
{
title: 'Удаление упражнения спрашивает подтверждение',
tag: 'fix'
},
{
title: 'Daily goal: «Цель закрыта · 100/100»',
detail:
'Когда дневная цель достигнута — больше не показываем обратный отсчёт «25ч 13м».',
tag: 'fix'
},
{
title: 'Видно когда мы молчим из-за ВКС',
detail:
'Запущен Zoom/Teams — на Dashboard появляется баннер активной встречи.',
tag: 'new'
},
{
title: 'Celebration анимация на новых достижениях',
tag: 'new'
},
{
title: 'Tracking-badge точнее',
detail:
'Live / Setup (закрой Steam) / Off — раньше зелёный показывался даже когда launch option не применён.',
tag: 'fix'
}
],
en: [
{
title: 'Match challenges now write to history',
detail:
'Previously ✓ in Match Summary did not count — streak and achievements ignored game training. Fixed.',
tag: 'fix'
},
{
title: 'Tray pause and Dashboard pause are now synced',
detail: "Previously Dashboard showed 'running' while tray was paused.",
tag: 'fix'
},
{
title: 'Exercise deletion asks for confirmation',
tag: 'fix'
},
{
title: 'Daily goal: "Goal hit · 100/100"',
detail:
'When the daily goal is met — no more confusing 25h countdown to tomorrow.',
tag: 'fix'
},
{
title: "Visible when we're quiet because of a meeting",
detail:
"Zoom/Teams running — Dashboard shows a banner: 'You're in a meeting'.",
tag: 'new'
},
{
title: 'Celebration animation on newly unlocked achievements',
tag: 'new'
},
{
title: 'Tracking badge more accurate',
detail:
'Live / Setup (close Steam) / Off — previously green even when launch option was not applied.',
tag: 'fix'
}
]
},
'0.5.6': {
ru: [
{
title: 'Категории напоминаний',
detail:
'Помимо упражнений — гидратация, отдых глазам (20-20-20), осанка.',
tag: 'new'
},
{
title: 'Голосовые подсказки',
detail:
'Диктор произносит название упражнения и количество. Включается в настройках.',
tag: 'new'
},
{
title: 'Достижения',
detail:
'Milestones по количеству повторений и серий — с прогресс-баром до ближайшей цели.',
tag: 'new'
},
{
title: 'Дневная цель',
detail:
'Soft-cap на упражнение: набрал N повторов — реминдер умолкает до завтра.',
tag: 'new'
},
{
title: 'Авто-пауза на ВКС',
detail:
'Ставит напоминания на паузу, если запущен Zoom/Teams/Webex/Slack-huddle.',
tag: 'new'
},
{
title: 'Адаптивный шедулер',
detail:
'Учит часы, в которые ты честно делаешь упражнение, и сдвигает fire-ы туда.',
tag: 'new'
},
{
title: 'Экспорт и импорт',
detail:
'Резервная копия упражнений, истории и настроек в JSON — для переноса на другую машину.',
tag: 'new'
},
{
title: 'Кнопка «Что нового»',
detail: 'Это окно. Открывается автоматически после обновления.',
tag: 'new'
}
],
en: [
{
title: 'Reminder categories',
detail: 'Beyond exercises — hydration, eye rest (20-20-20), posture.',
tag: 'new'
},
{
title: 'Voice prompts',
detail: 'Speaks the exercise name and count. Toggle in Settings.',
tag: 'new'
},
{
title: 'Achievements',
detail:
'Milestones by total reps and streaks, with a progress bar to the next one.',
tag: 'new'
},
{
title: 'Daily goal',
detail:
'Soft cap per exercise: hit N reps and that reminder goes quiet until tomorrow.',
tag: 'new'
},
{
title: 'Meeting auto-pause',
detail:
'Pauses reminders while Zoom/Teams/Webex/Slack-huddle is running.',
tag: 'new'
},
{
title: 'Adaptive scheduling',
detail:
'Learns the hours you reliably do an exercise and shifts fires into those windows.',
tag: 'new'
},
{
title: 'Export & import',
detail:
'JSON backup of exercises, history and settings — for moving to another machine.',
tag: 'new'
},
{
title: "What's new screen",
detail: 'This screen. Opens automatically after an update.',
tag: 'new'
}
]
},
'0.5.5': {
ru: [
{
title: 'Sandbox для окон',
detail:
'Окна изолированы на уровне OS — даже RCE в рендере не достанет main.',
tag: 'security'
},
{
title: 'Self-hosted шрифты',
detail:
'Plus Jakarta Sans + Bricolage Grotesque локально в bundle — работает без интернета.',
tag: 'security'
},
{
title: 'Логи для диагностики',
detail:
'%APPDATA%/Exercise Reminder/logs/latest.log — отдашь файл при проблеме.',
tag: 'new'
},
{
title: 'UI не залипает при retry-ях I/O',
tag: 'perf'
},
{
title: 'GSI больше не зависает на TIME_WAIT при выходе',
tag: 'fix'
}
],
en: [
{
title: 'Window sandbox',
detail:
'OS-level isolation — even RCE in the renderer cannot reach main.',
tag: 'security'
},
{
title: 'Self-hosted fonts',
detail:
'Plus Jakarta Sans + Bricolage Grotesque shipped in-bundle — works offline.',
tag: 'security'
},
{
title: 'Diagnostic logs',
detail:
'%APPDATA%/Exercise Reminder/logs/latest.log — share it when something breaks.',
tag: 'new'
},
{
title: 'UI no longer freezes during I/O retries',
tag: 'perf'
},
{
title: 'GSI port no longer stuck in TIME_WAIT after exit',
tag: 'fix'
}
]
},
'0.5.4': {
ru: [
{
title: 'Фоновое скачивание апдейта',
detail:
'Можно уйти на Dashboard и заниматься — апдейт качается в фоне.',
tag: 'new'
},
{
title: 'Моментальный рестарт',
detail:
'Кнопка «Рестарт» — ~1-2 сек до открытия новой версии, без диалогов NSIS.',
tag: 'new'
}
],
en: [
{
title: 'Background update download',
detail:
'You can go to Dashboard and work — the update keeps downloading.',
tag: 'new'
},
{
title: 'Instant restart',
detail:
'Restart button — ~1-2 sec to the new version, no NSIS dialogs.',
tag: 'new'
}
]
}
}
/**
* Возвращает версии, отсортированные desc, для которых есть заметки,
* с версиями, не виденными пользователем. Используется для «show whatsnew
* after update»: если пользователь прыгнул через несколько версий, показываем
* все пропущенные одним списком.
*/
export function unseenVersions(
current: string,
lastSeen: string | undefined
): string[] {
const all = Object.keys(RELEASE_NOTES).sort(compareSemverDesc)
if (!lastSeen) {
// Первый запуск этого механизма — показываем только текущую версию
// чтобы не перегружать историей. Старые версии показывает только
// явный «What's new» из Settings.
return all.filter((v) => v === current)
}
return all.filter(
(v) => compareSemver(v, lastSeen) > 0 && compareSemver(v, current) <= 0
)
}
function parseSemver(v: string): [number, number, number] {
const parts = v.split('.').map((n) => parseInt(n, 10))
return [parts[0] ?? 0, parts[1] ?? 0, parts[2] ?? 0]
}
function compareSemver(a: string, b: string): number {
const [a1, a2, a3] = parseSemver(a)
const [b1, b2, b3] = parseSemver(b)
if (a1 !== b1) return a1 - b1
if (a2 !== b2) return a2 - b2
return a3 - b3
}
function compareSemverDesc(a: string, b: string): number {
return -compareSemver(a, b)
}