feat: the redesigned Event Clock
The new reader app replaces the old UI: Checklist with a rail (focus pills, Next to expire, today's dailies, pinned routines), Timeline in a new and a classic look, Routines, Archive and a Settings area, in a Structured (default) and a Relaxed interface. It follows the approved Round 6 B and Round 7 mockups, corrected screen by screen with the owner. Reader data moves to a v2 store (gacha-tracker:v2:*). Existing v1 data is migrated on first load, a recovery copy is written first, and the v1 keys are never removed, so a rollback finds them unchanged. Redeem codes for Genshin arrive as their own feed. Also: live's urgency ramp, editable per theme; completion and section-complete fireworks; a returning-user tour; the design mockups, specs, plans, reviews and handoff record. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
ddd9673f86
commit
50c6e91b00
@@ -0,0 +1,267 @@
|
||||
# Event Clock redesign: Relaxed and Structured
|
||||
|
||||
Date: 2026-10-16. Status: approved requirements; both the initial implementation and the 2026-10-17 fidelity correction were rejected by the owner. Current continuation instructions: `docs/handoffs/2026-10-17-redesign-second-rejection-handoff.md`. Launch the current server, then ask the owner for the biggest differences before further UI changes.
|
||||
|
||||
Owner amendment, 2026-10-17: Structured is the default; preserve explicit saved Relaxed.
|
||||
|
||||
## Intent and approval record
|
||||
|
||||
Make several games' events and routines easier to scan and act on, while retaining trustworthy
|
||||
deadlines and every existing reader choice. The owner approved the Round 7 visual direction,
|
||||
then explicitly chose **two UIs**, reversing the preceding single-UI decision. The second is
|
||||
**Round 6 B**, confirmed in conversation. Both have the same capabilities and data.
|
||||
|
||||
Visual references:
|
||||
|
||||
- [Relaxed: Round 7](../../../design/mockups/round7/converged.html)
|
||||
- [Structured: Round 6 B](../../../design/mockups/round6/b-rail.html)
|
||||
- [Accumulated review decisions](../../design-reviews/2026-10-16-redesign-round4.md),
|
||||
[Round 5](../../design-reviews/2026-10-16-redesign-round5.md),
|
||||
[Round 6](../../design-reviews/2026-10-16-redesign-round6.md),
|
||||
[Round 7](../../design-reviews/2026-10-16-redesign-round7.md)
|
||||
|
||||
The prototypes are visual/interaction references, not production code. Sample codes, archive
|
||||
history, source failures and backups must never become real reader data.
|
||||
|
||||
## Product choices
|
||||
|
||||
Settings → Appearance offers **Interface: Relaxed / Structured**, with preview thumbnails and
|
||||
short descriptions. Relaxed is the proposed default for new and upgraded installs; existing
|
||||
Dark/Light/System choices remain intact. Relaxed uses Round 7's separated panels, softer surfaces,
|
||||
Bricolage Grotesque/Figtree typography and generous gutters. Structured uses Round 6 B's ruled
|
||||
layout and Barlow typography. Both put the current-style game focus pills first in the left rail.
|
||||
Switch immediately, remember the choice, and preserve the current page, focus and progress.
|
||||
|
||||
Interface, Dark/Light/System, colour scheme and Standard/Compact event rows are independent
|
||||
preferences. Standard is the default row density. Content determines row height: missing
|
||||
descriptions reserve no blank line and receive no fabricated replacement text.
|
||||
|
||||
Use a shared component hierarchy with interface-specific tokens and narrowly scoped styles.
|
||||
Duplicating the app's React tree or maintaining two separate stores would double behavioural
|
||||
maintenance. A spacing-only switch would not reproduce the two approved visual directions.
|
||||
|
||||
## Navigation, settings and updates
|
||||
|
||||
Main pages: Checklist, Timeline, Routines, Archive, Settings. Preserve the existing stored
|
||||
Checklist view id `soon` and Timeline id `timeline`. Visiting a utility page must not overwrite
|
||||
the preferred main view. Settings has its own navigation, beginning with General, and includes
|
||||
Your games, Appearance, Lists, Region & time, Data & sources, Backup, About and Changelog.
|
||||
|
||||
Keep game focus behaviour from `GameFocus.tsx`: All/game pills, outstanding counts, tap the
|
||||
selected game to return to All, Next through games and back to All. Hide the picker for one game.
|
||||
Focus never changes followed games. Game ordering remains the reader's order, otherwise A–Z.
|
||||
|
||||
Checklist and Timeline share a compact updates area. New code notices, events new since the
|
||||
reader's last visit, release news and source-age notices have distinct labels and state. Do not
|
||||
clear one by acknowledging another. Omit empty update kinds and the entire area when empty.
|
||||
|
||||
Replace **Older schedules** with **Event data may be out of date**. Supporting copy names the
|
||||
affected followed games: “For games you track: Genshin Impact, …”. **Details & reasons** opens
|
||||
Data & sources. Show this row only when `freshness()` reports an affected followed game;
|
||||
temporary focus does not narrow it. Do not add a large warning banner or repeat it on every row.
|
||||
|
||||
Reuse the real 48-hour freshness rule and oldest-source-per-game semantics. The footer always
|
||||
states feed age from source data, never `generatedAt`, with Check for new data. The button requests
|
||||
the published feed; it cannot force wiki scraping. Source details retain last successful data,
|
||||
last confirmed check, content-change time, source links and known reasons. A recent check with
|
||||
unchanged content is different from an overdue check. If no failure reason is recorded, say
|
||||
“The reason for the delay is unavailable”; do not infer blocking or network failure. Offline
|
||||
status is distinct from source age.
|
||||
|
||||
About retains the colophon, Lucas Winther attribution, contributor acknowledgements, all source
|
||||
communities and studios, reset-clock reference, disclaimer and project links. Credits are not
|
||||
filtered by followed games. Changelog is a Settings page, with no footer link or About button.
|
||||
Existing release notices link to that page.
|
||||
|
||||
## Routines and game setup
|
||||
|
||||
Routines owns follow/unfollow, built-ins, Create your own routine, Make it mine, editing and
|
||||
independent Checklist/Timeline pins. A follow controls tracking; a pin controls placement.
|
||||
Stopping a routine preserves its history. Reader-authored games, events and task forms remain
|
||||
fully functional; prototype placeholders do not satisfy this requirement.
|
||||
|
||||
Routines → Checklist display controls Separate daily panel / Grouped with routines, also exposed
|
||||
in Appearance as the same preference. Separate is the proposed default. A daily tick appears in
|
||||
one place, is reachable with one action, and remains distinct per tracked server.
|
||||
|
||||
Routine group choices: Collapsed by default, Expanded by default, Always expanded. Default is
|
||||
Collapsed. A single-game focus expands its groups; returning to All restores the chosen policy.
|
||||
Always expanded removes collapse controls. Numeric inputs retain native steppers and `step=1`.
|
||||
|
||||
Game settings contains Setup, Codes and About. Setup offers Events / Dailies / Weeklies &
|
||||
monthlies / Cycles, plus individual routine choices. These types compose; events are visibility,
|
||||
not a routine. Save type intent separately from current follows. Unsupported or currently empty
|
||||
types remain selectable with an explanation. New built-ins matching saved intent are offered
|
||||
for review, never silently followed on an established install.
|
||||
|
||||
“Track another server” explains: “Play on more than one server? Add your other server to track
|
||||
both accounts separately.” It creates fresh choices with Events selected initially, and asks
|
||||
all tracking questions again. It copies no ticks, follows or pins. Changing an existing server
|
||||
is a different action and preserves that account's recorded history.
|
||||
|
||||
Game colour is shared across its servers, editable with picker/hex/preview/Reset to default.
|
||||
About lists every registered data source for that game with links and thanks to its editors,
|
||||
including event, banner and pass sources even when a source currently contributes no events.
|
||||
|
||||
## Appearance and clocks
|
||||
|
||||
Slate, Warm, Plum and Custom schemes are available in each interface. Custom edits background,
|
||||
surface, text and interface accent separately for light and dark. Retain chosen base colours;
|
||||
derive readable rendered text, game hues and semantic colours against their actual surfaces.
|
||||
Keep game identity distinct from urgency. Small text must clear 4.5:1 in both modes and UIs.
|
||||
Fonts must have usable offline fallback; do not make rendering depend on Google Fonts loading.
|
||||
|
||||
Display timezone defaults to Automatic, resolved from the browser. Allow searchable named IANA
|
||||
zones and Revert to Automatic. Display timezone changes formatting, never server periods or
|
||||
stored day keys. Custom event entry states the timezone in which its date/time is interpreted.
|
||||
|
||||
Per tracked game/server, reset timing defaults to Automatic and permits a custom server-local
|
||||
hour/minute, with Revert to Automatic. Reuse real game/server offsets, regional hours and
|
||||
built-in clock overrides. Explicit timestamps, `regionEnds` and reader-entered instants remain
|
||||
authoritative; only reset-based/day-precision boundaries use the resolved reset clock. A routine
|
||||
with its own explicit clock keeps it. No change to the global games table is needed for reader
|
||||
overrides.
|
||||
|
||||
Reset changes are effective from their saved timestamp. Preserve a clock revision history per
|
||||
tracked account and attach the revision to new logs. Previously stored day/period labels are
|
||||
never re-keyed or silently interpreted under a different clock. Legacy logs belong to the initial
|
||||
automatic-clock revision. Historical summaries must retain access to all revisions; transition
|
||||
overlap is displayed as recorded history rather than merging or dropping ticks. Reverting to
|
||||
Automatic starts another revision and preserves earlier records. Test the boundary immediately
|
||||
before and after a change, including a change that moves the current game-day backward.
|
||||
|
||||
## Onboarding
|
||||
|
||||
New-user setup starts with events only. Ask default game server, appearance and timezone, then
|
||||
games and What do you want to track?, then preferred Checklist/Timeline. **Show events that
|
||||
haven't started** belongs in the tracking step and begins off. Explain types inline, especially
|
||||
cycles: routines repeating on a game's cadence, such as every fourteen days. Explain “no active
|
||||
window” separately from “no supported built-in”. Initial setup may follow currently supported
|
||||
items deliberately selected by type; subsequent additions require review. Defer pin decisions
|
||||
until readers can see the views. Do not change old installs to the new-install defaults.
|
||||
|
||||
Returning readers receive a one-time release-specific welcome, available in either main view,
|
||||
with Take the quick tour / Keep browsing. The tour visits Routines, Checklist, Archive and
|
||||
Settings, with Back and Skip, then returns to the reader's preferred main view. Persist a marker
|
||||
separate from changelogSeen. Opening or skipping the tour changes no games, routines or progress.
|
||||
|
||||
## Archive and statistics
|
||||
|
||||
On Done or Ignore, persist the outcome and event snapshot immediately. Show “Completed · Moved
|
||||
to Archive” or “Ignored · Moved to Archive” in the row for about 1.5 seconds, then fade/collapse.
|
||||
Keep Undo for about eight seconds. Reduced motion removes the fade, retaining the confirmation.
|
||||
Archive Restore is always available; restoring an ended event restores its recorded status,
|
||||
but does not pretend it is running again.
|
||||
|
||||
Retain event metadata, description, source, dates/precision, region-specific ends, account,
|
||||
progress and outcome timestamp. Unknown end dates remain null. Cache snapshots of seen events
|
||||
before feed replacement so expired unfinished events can be recorded when they leave the live
|
||||
feed. Missing from a feed is not proof of expiry: retain an outstanding snapshot until its known
|
||||
deadline passes; unknown-end events remain unresolved and must not become unfinished by guess.
|
||||
Only archive events for tracking periods the reader actually followed, not hidden catalogue games.
|
||||
|
||||
Default Archive body is per-game, with version groups only where the source states a version.
|
||||
History timeline is an optional alternate body. The story panel shows monthly and overall
|
||||
completion rate, current/best completion run, event check-ins, unfinished counts and per-game
|
||||
outcome bars. Rates use done / (done + ended unfinished), excluding ignored and unresolved.
|
||||
Use outcome time for done and resolved end time for unfinished when grouping by month. Completion
|
||||
runs order those eligible outcomes by that time; ignored entries neither extend nor break them.
|
||||
Event check-ins sum recorded distinct days per event/account, not unique calendar days of play.
|
||||
Near-miss detail reports an actually recorded goal shortfall, only where a known target exists;
|
||||
no invented threshold or estimated play progress. Label all statistics as recorded archive history.
|
||||
|
||||
Old marks whose events are no longer available remain preserved but cannot acquire fabricated
|
||||
titles, deadlines or descriptions. Explain that earlier history may be incomplete.
|
||||
|
||||
## Persistent state, migration and backup
|
||||
|
||||
Keep existing event IDs, daily IDs, task IDs and day-key formats. Introduce stable tracked-account
|
||||
identities around game/server choices; do not turn a region change into a different event ID.
|
||||
Legacy progress, daily logs, ignores, task amounts and routine choices are associated once with
|
||||
each game's initial account at the reader's saved region. A migration marker records the mapping.
|
||||
Retain legacy key spaces and unknown/unreadable records; migration is idempotent and does not
|
||||
duplicate logs on reload. Additional accounts get independent state. Existing global preferences,
|
||||
game visibility/order, custom content and view survive. Migration must work for readers returning
|
||||
after months and for old exports, not only the current developer browser.
|
||||
|
||||
New state includes account configurations/logs, routine follows/pins and tracking intent, archive
|
||||
snapshots, reset revisions, appearance/timezone preferences, update-seen markers and code
|
||||
redemptions. Document concrete schemas and keys in DATA-MODEL with the storage implementation.
|
||||
Use a validated versioned full-state envelope for backup and restore; accept existing version-1
|
||||
exports through a tested legacy reader. Preserve the existing distinction between progress import
|
||||
and Import all. A new export must carry all new reader-owned state. Do not recursively include
|
||||
backup history inside each backup.
|
||||
|
||||
Automatic backups run on app use and after settled data changes. Use a stable UTC calendar basis,
|
||||
independent of display timezone. Keep latest snapshot per UTC day for today and the six previous
|
||||
days; older snapshots fold into four consecutive seven-day windows; older snapshots then fold
|
||||
into six calendar-month buckets measured backward from the oldest weekly window. Buckets are
|
||||
disjoint; retain the newest snapshot in each and discard anything older. A partially covered
|
||||
calendar month at the weekly boundary retains only eligible older snapshots. Maximum seventeen
|
||||
retained snapshots, plus one pre-restore recovery copy. Never invent snapshots for unused days.
|
||||
|
||||
Backup rows say **View backup**. Preview shows date and contents; **Restore this backup** is the
|
||||
explicit action. Validate the entire payload before changing live state, save current data as a
|
||||
recovery copy, and support Undo last restore. Make multi-key restore recoverable using a prepared
|
||||
transaction envelope; startup must resolve an interrupted restore before normal store writes.
|
||||
Storage writes must report success/failure rather than relying on today's silently failing
|
||||
`writeJson`. If persistence/quota prevents a recovery copy or complete restore, leave current
|
||||
data intact and offer export. Failed backup retention writes must not delete the last good copy.
|
||||
Explain that browser-local backups disappear if browser storage is cleared; export is the copy
|
||||
outside this browser. No accounts or remote sync.
|
||||
|
||||
## Codes and source boundaries
|
||||
|
||||
Codes belong in game settings and notify in-app in both main views. Discovery/newness is per game
|
||||
and independent from redemption per tracked account. Viewing a game's codes clears its new
|
||||
indicator, never redemption. Only declare a code new when present in a successfully read feed,
|
||||
not because its redemption checkbox is clear. Preserve first-observed metadata across builds.
|
||||
|
||||
The supplied Genshin Game8 codes URL is a source candidate, not a shipped feed. A deterministic
|
||||
codes source is a separate ingestion sub-project with its own source/robots review, fixture,
|
||||
parser/schema and refresh integration. It must follow existing scraping rules and publish only
|
||||
source-stated code/reward/expiry facts; unknown expiry stays unknown. The UI implementation
|
||||
includes a real empty/unavailable state and never ships sample codes as real. Integrating this
|
||||
source is required to finish the codes feature, but must not delay validating the shared UI shell.
|
||||
|
||||
## Implementation boundaries and delivery order
|
||||
|
||||
Use production React components, pure state/selectors and existing Bun tooling. Extract page
|
||||
coordination from App and settings from Controls as needed for the actual new page boundaries;
|
||||
avoid unrelated refactors. No added runtime dependencies, accounts, push service, SQLite work,
|
||||
parser rewrites or prototype JavaScript transplanted into production.
|
||||
|
||||
Deliver in independently verifiable stages:
|
||||
|
||||
1. Shared shell, both interfaces, settings/navigation, typography and responsive layouts.
|
||||
2. Validated state/envelope, account migration and reset revision machinery with recovery tests.
|
||||
3. Routines, game setup, independent pins, direct dailies and clock-aware views.
|
||||
4. Archive retention/outcomes/statistics and automatic backup/restore.
|
||||
5. Onboarding, shared updates/source details, credits/Changelog, themes/timezone/custom colours.
|
||||
6. Deterministic code ingestion and real code notices/redemption, then complete end-to-end review.
|
||||
|
||||
The detailed implementation plan must define file-level tasks and concrete storage schemas before
|
||||
stage 2. Each stage preserves a runnable app and documents what has actually landed. No staged
|
||||
delivery is a claim that the complete redesign is finished.
|
||||
|
||||
## Verification and documentation
|
||||
|
||||
Test migrations from realistic legacy saves and exports, idempotence, independent account progress,
|
||||
reset changes/reverts at boundaries, null ends, vanished feed rows, archive denominator/ordering,
|
||||
backup folding across calendar boundaries, quota failures and interrupted restores. Test code
|
||||
newness independently from redemption and source-age scope independently from focus. Existing
|
||||
date/parser/ID tests must remain green. Tests create their own fixtures and never require public
|
||||
build output, repository docs or network.
|
||||
|
||||
Run typecheck and the full offline suite; build CSS/JS/static shell with production JSX settings.
|
||||
Check actual built app in Chrome on a new port for each rebuild at phone and desktop widths,
|
||||
both interfaces, both themes, Standard/Compact, keyboard/focus, reduced motion and 200% zoom.
|
||||
Exercise custom palette contrast on all used surfaces, no horizontal page overflow, one-action
|
||||
dailies, timeline reset adjacency, both onboarding paths, archive Undo/Restore and backup recovery.
|
||||
Verify offline reopening and the real update flow without losing progress.
|
||||
|
||||
Update PRD, DATA-MODEL, ARCHITECTURE, DESIGN, PRODUCT and affected AGENTS guidance with each
|
||||
implemented stage. Source integration also updates INGESTION/SOURCES. The shipped documents
|
||||
continue to describe shipped behaviour until that implementation exists. Add changelog/release
|
||||
notes under the repository's normal commit workflow when authorized; do not commit or push merely
|
||||
because this specification has been written.
|
||||
Reference in New Issue
Block a user