fix: дедуп rapid-double-click + i18n native dialogs + пустой default exerciseName

ReminderApp MatchSummary: sentChallengesRef для дедупа rapid double-click
на ✓ — раньше один и тот же challenge мог записаться в историю несколько
раз, давая лишние reps. Ref сбрасывается на новый match.

ExerciseCard «Готово» (для due-упражнения): такая же ref-based дедуп.
Окно ~1 сек между click → IPC.markDone → store.markDone обновляет
nextFireAt → broadcastState → ticks broadcast → isDue=false. До этого
быстрый double-click писал 2 entries с близкими ts.

ipc.ts: title в showSaveDialog/showOpenDialog локализован по
settings.language. Раньше всегда был русский в EN-локали.

Challenges editor: EMPTY_DRAFT.exerciseName: '' вместо 'Приседания'.
В EN-локали дефолтный русский текст выглядел багом. Required-валидация
не пускает пустое значение в save.
This commit is contained in:
AnRil
2026-05-22 23:34:41 +07:00
parent 2b7eb412c7
commit e7c3088ee5
4 changed files with 40 additions and 5 deletions

View File

@@ -347,8 +347,12 @@ export function registerIpc(): void {
.replace(/[:T]/g, '-')
.slice(0, 16)
const defaultPath = `laude-backup-${stamp}.json`
// Native-диалоги OS читают локаль из системы. Title — единственная
// строка которую мы контролируем; локализуем по settings.language.
const lang = getState().settings.language ?? 'ru'
const result = await dialog.showSaveDialog(win!, {
title: 'Сохранить резервную копию',
title:
lang === 'en' ? 'Save backup' : 'Сохранить резервную копию',
defaultPath,
filters: [{ name: 'JSON', extensions: ['json'] }]
})
@@ -367,8 +371,10 @@ export function registerIpc(): void {
ipcMain.handle(IPC.importState, async (event) => {
const win = BrowserWindow.fromWebContents(event.sender) ?? undefined
const lang = getState().settings.language ?? 'ru'
const result = await dialog.showOpenDialog(win!, {
title: 'Восстановить из резервной копии',
title:
lang === 'en' ? 'Restore from backup' : 'Восстановить из резервной копии',
properties: ['openFile'],
filters: [{ name: 'JSON', extensions: ['json'] }]
})