Repository navigation
v1.30.0
Maintenance release implementing the "Suggestions — rest of the app" section of docs/REVIEW-2026-09-30.md. Nothing changes in how the app behaves day to day; a few small things got better on the side.
Refactor (no behaviour change)
ui.jssplit by job (1 255 lines → 6 modules):dom.js($,$$,esc,shake,pctText,signed),toast.js(toasts, sparkles, celebrate),sheet.js(the bottom sheet, its back-button history handling, and the newconfirmDialog),widgets.js(row builders shared by renderers and sheets),sheets.js(the twelve non-quest sheets),ui.js(the renderers,tabbar,diffHtml).ui.jsre-exports the rest, soimport * as U from './ui.js'is still the one door forapp.js.app.jstap handling: the 55-caseswitchis now six per-area maps (SHELL,LIVE,QUEST,MOMENT,SETUP,OBactions) merged intoACTIONS; each handler gets(btn, now)and returns early.- Deduplicated:
shake(×5 →dom.js),pctText(×2),fmtDate(new Date(day + 'T12:00'))(×3 →time.fmtDay(key)),new Date(day + 'T12:00').getDay()(×2 →time.weekday(key)). - Dead parameters and keys:
fmtClock(ts, lang)andfmtDuration(ms, lang)never readlang— gone at the 19 call sites;update.js announce(worker)likewise; 23 unused i18n keys (appName,tagline,obQ_*,obPick*,toastMissed,minutesShort…) and the duplicatednowremoved from both languages. - Rough-patch detection (three misses in a row) moved from
app.jsintoengine.missRun(now), so it is unit-tested.
Changed
- Confirmations — deleting a moment, a premade or a quest, giving a quest up, replacing a premade of the same name — use the app's own dialog (
confirmDialog, promise-based, floats above the open sheet) instead of the browser'sconfirm()pop-up. Cancel keeps you where you were. - Accessibility: every switch and select in Setup is named after its row (
aria-labelinjected bytoggleRow); rows and cards that react to a tap are focusable (tabindex=0 role=button) and Enter / Space activates them; the active tab carriesaria-current="page"; the importance dot on a moment has a name, not just a colour. - Layout guards: tab labels ellipsise instead of pushing the bar around at large font scales; the clock and the four pills fit one row at 375 px in French.
- Midnight: whichever tab is open re-renders when the day changes (previously only Now and Quests).
Fixed
- A moment set inside the hour the clocks skip in spring (e.g. 02:30–03:30 on the switch day) collapsed to a zero-length window and was missed instantly. It now keeps its nominal length. Found by the new DST test.
Tests
41 unit + 4 relay. New: a DST switch day (both directions), settlePastDays after a 46-day gap (catches up on the 45-day window only, old records untouched), mergeWithDefaults on a v1 save (migrations, back-filled day start, every field defaulted), engine.missRun. Not added: the relay double-fire test — the double-fire itself is still an open decision in the review.