All checks were successful
PR checks / checks (pull_request) Successful in 2m55s
Nine captures tagged rust (D65): the server list, feed, leaderboard, live map, permissions and the RunicNPC profile editor on the web, and a server's feed, its map and the player's Rust account in the app, from an Android-app edge debug build. D80: every name in a capture is a role (admin, moderator, player...), from this phase on. D81: the Rust demo's players are mock data written by scripts/mockRustDemo.mjs; the server, its status, map, permission groups and RunicNPC sync state are the real Oxide test server's. The captions and /modules/rust/ and /app/ say which part is a demo cast. seedDemo.mjs gains --game rust (server row with a weekly wipe, public presence for the demo, two NPC profiles, a VIP group). captureScreens.mjs gains a click list per screen. The homepage shows the Rust live map beside the UO capture (D76); three Rust docs pages carry their screen. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
118 lines
4.0 KiB
Plaintext
118 lines
4.0 KiB
Plaintext
---
|
|
import { screensOf, PHONE } from '../../data/screens.mjs';
|
|
import platform from '../../data/platform.json';
|
|
|
|
/**
|
|
* The app's screenshot strip. Reserved in phase 5 (D26), filled in phase 9.
|
|
*
|
|
* ---------------------------------------------------------------------------------------
|
|
* WHY THIS COMPONENT EXISTED FOR A PHASE WITH NOTHING IN IT
|
|
* ---------------------------------------------------------------------------------------
|
|
* PLAN.md §10 said `/app/` shows "the 14 existing screenshots". They exist —
|
|
* `docs/android/screenshots/` on the `docs` repository — and they are the wrong fourteen: a
|
|
* trusted-device and recovery-code smoke test from 2026-07-22, captured against a
|
|
* development instance with no seeded content, before the theming work that changed how
|
|
* every screen looks. Five of them are two-factor prompts. The home shot is an empty page.
|
|
*
|
|
* Shipping them would have broken D4 and §1 at once, so D26 reserved the slot for the phase
|
|
* that stands up the review stack anyway. The shape was defined then and the data arrived
|
|
* now, which is exactly what it was for: filling it was a data change.
|
|
*
|
|
* ---------------------------------------------------------------------------------------
|
|
* WHY IT READS screens.mjs RATHER THAN HOLDING ITS OWN LIST
|
|
* ---------------------------------------------------------------------------------------
|
|
* The draft carried its own `shots` array, written before there was anywhere else to put
|
|
* one. There is now: `src/data/screens.mjs` holds every capture the site ships, web and
|
|
* phone alike, and `scripts/checkScreens.mjs` proves each one exists at the size the markup
|
|
* claims. A second list here would be the one nothing checks.
|
|
*
|
|
* The phone captures come from an emulator pointed at the same seeded deployment the web
|
|
* screenshots were taken from, on the same day — which is the property D26 was really
|
|
* after, since the app takes its colours, type and navigation from the site it connects to.
|
|
*/
|
|
|
|
const shots = screensOf('phone');
|
|
---
|
|
|
|
{
|
|
shots.length > 0 && (
|
|
<section class="page section shots">
|
|
<h2>What it looks like</h2>
|
|
<p class="prose shots__lede">
|
|
Captured from the app against two demo deployments: one with a real Ultima Online
|
|
server behind it, and one with a real Rust server whose players are a demo cast. The
|
|
app takes its colours, type and navigation from the site it is connected to, so these
|
|
show one community's app rather than a neutral one.
|
|
</p>
|
|
|
|
<ul class="shots__grid">
|
|
{shots.map((shot) => (
|
|
<li class="shots__item" data-game={shot.game}>
|
|
<img
|
|
src={`/screens/${shot.id}.webp`}
|
|
alt={shot.alt}
|
|
width={PHONE.width}
|
|
height={PHONE.height}
|
|
loading="lazy"
|
|
decoding="async"
|
|
/>
|
|
<p class="shots__caption">
|
|
{shot.game && <span class="shots__game">{platform.games[shot.game].name}</span>}
|
|
{shot.caption}
|
|
</p>
|
|
</li>
|
|
))}
|
|
</ul>
|
|
</section>
|
|
)
|
|
}
|
|
|
|
<style>
|
|
.shots h2 {
|
|
margin: 0 0 0.75rem;
|
|
font-size: clamp(1.6rem, 3.2vw, 2.1rem);
|
|
}
|
|
|
|
.shots__lede {
|
|
margin: 0 0 2.25rem;
|
|
color: var(--muted);
|
|
}
|
|
|
|
.shots__grid {
|
|
display: grid;
|
|
gap: 1.5rem;
|
|
margin: 0;
|
|
padding: 0;
|
|
list-style: none;
|
|
grid-template-columns: repeat(auto-fit, minmax(min(100%, 15rem), 1fr));
|
|
}
|
|
|
|
.shots__item img {
|
|
display: block;
|
|
width: 100%;
|
|
height: auto;
|
|
border: 1px solid var(--line);
|
|
border-radius: var(--radius-card);
|
|
box-shadow: var(--shadow-card);
|
|
}
|
|
|
|
/* The game's name on a game's screen (D67), as Screenshot.astro prints it. */
|
|
.shots__game {
|
|
display: inline-block;
|
|
margin-right: 0.5rem;
|
|
padding: 0.05rem 0.55rem;
|
|
border: 1px solid var(--line);
|
|
border-radius: var(--radius-pill);
|
|
color: var(--muted);
|
|
font-size: 0.74rem;
|
|
letter-spacing: 0.04em;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.shots__caption {
|
|
margin: 0.85rem 0 0;
|
|
color: var(--dim);
|
|
font-size: 0.88rem;
|
|
}
|
|
</style>
|