chore: sprint A — мелкая полировка

#15 a11y: <html lang> синхронизируется с settings.language через
    ThemeProvider — screen-readers больше не читают EN-текст с
    русским акцентом и наоборот.
#14 dev:simulateMatchEnd channel вынесен в IPC enum
    (IPC.devSimulateMatchEnd) — main/preload не разойдутся в hardcoded
    строках.
#34 ChallengeEditor: multiplier клампится к [0.5, 1000] (max="1000",
    Math.min(1000, ...)). Совпадает с validate.ts — раньше save с 9999
    молча отклонялся IPC, теперь UI не даёт ввести.
#28 package.json: добавлен `test:coverage` script.
This commit is contained in:
AnRil
2026-05-22 01:13:01 +07:00
parent 9378cabfe5
commit a41dce511b
6 changed files with 25 additions and 3 deletions

View File

@@ -264,11 +264,18 @@ function ChallengeEditor({
type="number"
step="0.5"
min="0.5"
max="1000"
value={draft.multiplier}
onChange={(e) =>
setDraft({
...draft,
multiplier: Math.max(0.5, Number(e.target.value) || 1)
// Клампим к диапазону [0.5, 1000] — совпадает с validate.ts
// (multiplier ∈ [0, 1000]). Без max=1000 пользователь мог
// ввести 9999 и save молча отклонялся IPC-валидатором.
multiplier: Math.max(
0.5,
Math.min(1000, Number(e.target.value) || 1)
)
})
}
className="ios-input font-mono-num"

View File

@@ -25,5 +25,15 @@ export function ThemeProvider({
else document.documentElement.classList.remove('dark')
}, [settings?.theme, osTheme])
// Синхронизируем <html lang> с языком приложения. Без этого screen-readers
// продолжают читать английский текст как кириллицу (или ломаются) при
// переключении на EN, и наоборот — это a11y-баг.
useEffect(() => {
const lang = settings?.language ?? 'ru'
if (document.documentElement.lang !== lang) {
document.documentElement.lang = lang
}
}, [settings?.language])
return <>{children}</>
}