feat(rust): the Rust server list and one server's page — M14 (module-rust phase 5, Android leg A) #47
Reference in New Issue
Block a user
No description provided.
Delete Branch "feature/rust-p5-android-a"
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 app's half of
module-rust's read path. R10 says each Android leg trails the website surface it consumes by one phase, so this is built against routes that exist and was walked against a running one.Criterion met, and walked in an emulator rather than asserted: the app renders a Rust site it has never seen, and a UO site unchanged.
What it adds
Two screens, mirroring what phase 4 shipped:
/rustis the server list (D12) — not a hub above one. The module registers its pages withpath: ''and core strips the trailing separator, so there is no landing page between the drawer row and the servers.Both render entirely from the website's own tables, so the phase criterion holds here for the same reason it holds on the web: a fleet that is entirely off still shows its maps, seeds, wipe dates, killfeeds, leaderboards and last known presence.
What is new to the app rather than copied
A poll that is not a load (D17). The app has had exactly one shape for a read — blank, ask, replace. That is right for opening a screen and would clear the killfeed three times a minute here; the website hit the same wall one tier along, which is why
module-rustbundles its ownusePolledinstead of using core'suseAsync.PollWhileResumed+refreshIntoare that hook's other half: a refresh is invisible when it succeeds and keeps the rows when it fails.repeatOnLifecycle(RESUMED)gives the phone's version of D14's Page Visibility gate — nothing runs while the app is away, and returning refreshes at once. Only the visible live panel is polled; the leaderboard and the wipe list never are, because a leaderboard that re-sorted itself under a finger every twenty seconds is worse than a stale one.A second game module in the drawer.
Capability.RUST, gating one row — and deliberately notservers/killfeed/leaderboard/presence/wipes. Every one of those names a surface, and core flattens all modules' capabilities into one list, soserversis a word another module could declare tomorrow and silently reveal these screens on a site with no Rust. Module-Rust#5 adds the identity string./rustinNavPaths, so an admin's nav override on that row — or an added link to it — opens natively instead of handing off to a browser.A live player count on the drawer row (D19) — the phone's answer to D15's footer slot, which has no analogue here. It rides in the same
NavigationDrawerItembadge slot the inbox's unread count uses, with the same screen-reader treatment. Zero renders nothing, a failed read keeps the last number, and it never polls.Two things carried across rather than rediscovered
The website's own page walk found both, and this leg inherits them:
lastSeenAt, neverupdatedAt— a failed poll moves the second, which is what made an offline server claim it had just checked in every thirty seconds for as long as it stayed down.What the walk found
Three defects, none visible to a unit test — all fixed in the second commit:
ShardCardcarries no padding of its own; each caller pads its own content, and these four did not.How it was proven
Against the phase-4 rig — a core with the module installed, one live server and one seeded fixture that has never reported:
Offline, the page still rendered its map, size, seed, wipe date, killfeed, both leaderboards, its last known presence board and its wipe history.refreshInto, against a genuinely dead backend — the core was stopped with the list on screen; a poll tick later the rows were unchanged with one quiet line above them.describebranch rendered from real rows: a player kill with weapon/distance/grid, an NPC kill, a suicide, an environment death, chat with its colon in the join, a disconnect with reason and session, and "while sleeping".One commit here is not phase 5, and says so
fix(ci): stop setup-android installing a package Google has removed. Included here on the org lead's call (2026-09-17), because it blocks verifying anything at all.android-actions/setup-android@v3is a floating tag and the action'spackagesinput defaults totools— an obsolete package Google has since removed from the SDK repository. The step runssdkmanager tools, getsWarning: Failed to find package 'tools', exits 1, and CI fails in Set up Android SDK before a line of this repo is compiled. PR #46 passed on this same workflow yesterday; every Android PR fails now.packages: ''turns that install off, and it was always redundant here — the next step installs exactly what the build targets (platform-tools,platforms;android-35,build-tools;35.0.0) precisely so the build never depends on what an action decided to fetch.Not addressed, and worth its own decision:
@v3is a floating major tag, so the next upstream change can break CI the same way without warning.Rig note worth keeping
The debug
network_security_config.xmlpermits cleartext to127.0.0.1andlocalhostonly — not10.0.2.2. An emulator walk against a local core needsadb reverse tcp:<port> tcp:<port>and the loopback address, or every request fails withUnknownServiceException: CLEARTEXT communication to 10.0.2.2 not permitted.The four navigation tests that moved
APP_MENUgained a row and the website's nav number line gained an index, so the merge's expected shapes shifted by one. Each now says which, and why both game modules appear in a table no single backend serves.Base branch
This targets
edge, per the org lead's decision to move the Rust workstream's repos and work ontoedge(2026-09-16).pr-checks.ymlalready triggers on[main, edge].AI disclosure
🤖 Generated with Claude Code
https://claude.ai/code/session_016wDDVXWMDz82WqE1i969r4