feat(events): the app's event screens — M13 (Phase 16b cutover, 4 of 6) #46
Reference in New Issue
Block a user
No description provided.
Delete Branch "edge"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
The Event System cutover, step 4 of 6 (
EVENTS_PLAN.mdPhase 16b;docs/android/PLAN.mdM13).edge→main, a clean fast-forward —mainis 0 ahead. 2 commits, 39 files.No
v*tag with this merge (org lead, 2026-09-09). The release workflow fires on tags only, so this cuts the source over without cutting an APK; whether to publish a build is a separate decision once the released core is verified in the second half of 16b.What lands
Phase 14b — the four event screens. The calendar, an event page, arcs, and the player's own participation history, over the same four public routes the browser uses.
The prerequisite fix, and the rule that governs it: absence of an answer is not an answer of absence. The screens are gated on the host advertising the
eventscapability, and the three cases are not the same:/public/modulesread that omits the string hides the rows;Capability (per host) and feature (per viewer) are two gates that compose.
A second, older defect fixed here on the org lead's call: the app's website path → route table had been wrong since the module-system cutover on 2026-08-12. Core's NAV is 8 rows, not 16, and the nine shard rows moved to
/uo/*. Two existing tests had been passing vacuously since that day.The second commit is the inbox fix the emulator walk found — a retained view model showed one account another's participation history.
Verification
Walked on an emulator against the whole rig (real ServUO → sidecar on protocol 7 → core with
module-uoinstalled from a release-shaped bundle), which is where all three of Phase 14b's defects were found — 563 green tests had found none of them. The ungated player game-data rows, aLongscore field against aDECIMAL(18,4)column that made a 200 render as a server error (latent on the public results table for every visitor), and the retained view model above.Phase 16a's walk re-confirmed the calendar end to end:
/site/eventsshows a live run as Happening now in the browser and in the app — the app consumes the same route, so the calendar defect fixed inwebsite#198was breaking it too.🤖 Generated with Claude Code
https://claude.ai/code/session_016wDDVXWMDz82WqE1i969r4
The defect Phase 14b found in `MyEventsViewModel` and flagged next door: the notifications surface has the identical shape, and it leaks the same way. A drawer route's view model outlives a sign-out. `navigateTopLevel` uses `popUpTo(HOME) { saveState = true }` with `restoreState = true`, so the `NavBackStackEntry` keeps its `ViewModelStore` and a view model that loaded only in `init` never runs again. Signing out and back in as somebody else showed the second account the FIRST account's inbox — titles and body text written for another person — with no request made at all, while the badge above the list showed the new account's real unread count, because the shell refreshes that on every session change. `InboxCache` was never the hole: it is keyed by (base URL, user id) and a snapshot has never crossed an account. The hole was the in-memory state, which nothing invalidated. Both view models now key on the signed-in account id, so a resume revalidation that returns the same user does not refetch. The inbox resets its state *before* loading rather than after, because `load()` paints the cache only when there is no `Success` on screen — otherwise the previous account's rows stay up for the whole round trip. The settings screen behind the inbox's gear is fixed with it, and there the stale render is worse than disclosure: those controls are written from, so a screen still showing the previous account's preferences would send this account's PUT built out of them. Walked on the emulator against a local website, before and after: two accounts with deliberately different inboxes, signed out and in within one process. Before, the second account saw the first's rows and the server logged no inbox fetch; after, it logs the fetch and shows its own. 572 tests, 0 failures. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016wDDVXWMDz82WqE1i969r4