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:
@@ -30,6 +30,15 @@ function shiftDays(base: Date, dayDelta: number): Date {
|
||||
* Reps logged on a given local day. Uses `actualReps` if present, otherwise
|
||||
* looks up exercise's planned `reps`.
|
||||
*/
|
||||
/**
|
||||
* Сколько reps пользователь сделал в заданный day-key. Источники в порядке
|
||||
* приоритета:
|
||||
* 1. entry.actualReps — что фактически сделал (stepper в reminder'е)
|
||||
* 2. entry.reps — snapshot planned-reps на момент записи (выживает после
|
||||
* удаления упражнения и работает для match-челленджей у которых нет
|
||||
* связанного Exercise)
|
||||
* 3. byId.get(exerciseId).reps — fallback для старых entries без snapshot'а
|
||||
*/
|
||||
export function dailyReps(
|
||||
entries: HistoryEntry[],
|
||||
exercises: Exercise[],
|
||||
@@ -40,7 +49,7 @@ export function dailyReps(
|
||||
for (const e of entries) {
|
||||
if (e.action !== 'done') continue
|
||||
if (dayKey(e.ts) !== dayKeyStr) continue
|
||||
sum += e.actualReps ?? byId.get(e.exerciseId)?.reps ?? 0
|
||||
sum += e.actualReps ?? e.reps ?? byId.get(e.exerciseId)?.reps ?? 0
|
||||
}
|
||||
return sum
|
||||
}
|
||||
@@ -72,7 +81,7 @@ export function dailyRepsRange(
|
||||
const k = dayKey(e.ts)
|
||||
const bucket = buckets.get(k)
|
||||
if (!bucket) continue
|
||||
const reps = e.actualReps ?? byId.get(e.exerciseId)?.reps ?? 0
|
||||
const reps = e.actualReps ?? e.reps ?? byId.get(e.exerciseId)?.reps ?? 0
|
||||
bucket.reps += reps
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user