fix(P0): match-history, tray/dashboard pause sync, whatsnew для upgraders
P0 #1 — Match-челленджи теперь пишутся в историю. HistoryEntry расширен полями `reps?`, `name?`, `source?` (snapshot planned-reps + name на момент записи + 'reminder'/'match'). Новый store.markChallengeDone(challengeId, reps) пишет entry с exerciseId='challenge:<id>' и source='match'. Зарегистрирован IPC.markChallengeDone handler (раньше канал был в enum, но handler не подключен). ReminderApp.MatchSummaryView вызывает window.api.markChallengeDone при ✓-клике. Стрик, today_done, achievements теперь учитывают игровые тренировки. Заодно dailyReps/dailyRepsRange/totalDoneReps используют entry.reps как fallback — heatmap не теряет данные после удаления упражнения (закрывает P2 #12). P0 #2 — Tray-пауза синхронизирована с Dashboard. Раньше tray держал scheduler-local `paused` boolean, который не отражался в settings.globalEnabled — Dashboard показывал «running» с тикающим таймером, хотя fires не приходили. Сейчас оба пути (tray и Dashboard-кнопка) меняют единственный source of truth — settings.globalEnabled. setPaused/isPaused/paused удалены, IPC pauseAll/resumeAll переписаны на updateSettings. P0 #3 — Whats-new покажется существующим пользователям при апгрейде. Раньше для всех undefined lastSeenVersion (включая обновляющихся с v0.5.5) делали silent-save без модалки — никто бы не увидел v0.5.6 changelog. Сейчас: если есть Exercise с lastDoneAt → это обновляющийся пользователь, показываем заметки текущей версии; если нет — новичок, silent.
This commit is contained in:
@@ -111,13 +111,34 @@ export type PersistedState = AppState & {
|
||||
|
||||
export type HistoryAction = 'done' | 'skip' | 'snooze'
|
||||
|
||||
/**
|
||||
* Источник записи: обычное напоминание (от scheduler'а) или матч (челлендж).
|
||||
* Используется для UI («подтянулся в матче» vs «по таймеру») и аналитики.
|
||||
*/
|
||||
export type HistorySource = 'reminder' | 'match'
|
||||
|
||||
export type HistoryEntry = {
|
||||
/** ms epoch */
|
||||
ts: number
|
||||
/**
|
||||
* Для обычных напоминаний — Exercise.id. Для challenge'ей — `challenge:<id>`
|
||||
* (синтетический ключ; renderer'у не нужно искать exercise по нему).
|
||||
*/
|
||||
exerciseId: string
|
||||
action: HistoryAction
|
||||
/** When user did less than planned. Only meaningful for `done`. */
|
||||
actualReps?: number
|
||||
/**
|
||||
* Snapshot повторений на момент записи. Гарантирует, что после удаления
|
||||
* упражнения история не теряет «сколько было сделано» (раньше lookup
|
||||
* `byId.get(exerciseId).reps` возвращал undefined → heatmap показывал 0).
|
||||
* Для match-челленджей — фактическое число повторов из match summary.
|
||||
*/
|
||||
reps?: number
|
||||
/** Snapshot названия упражнения/челленджа — для будущего log-view. */
|
||||
name?: string
|
||||
/** undefined = reminder (для обратной совместимости со старыми entries). */
|
||||
source?: HistorySource
|
||||
}
|
||||
|
||||
export type Tick = {
|
||||
|
||||
Reference in New Issue
Block a user