feat: a bare URL opens on FiDi, not on 1,551 km of tan
One California is the product; the first frame is still the coarsest pose the pack owns, because createScene opens on chapters[0] and the state tour starts there. Capture and ?city=california keep that. A visitor typing tera.lumbridgecorp.com gets openingChapter fidi — a city they can read — without reordering the pack.
This commit is contained in:
+24
-6
@@ -459,6 +459,18 @@ export interface SceneOptions {
|
||||
* `stage.setScene(handle.stageScene)` that presents it.
|
||||
*/
|
||||
present?: boolean;
|
||||
/**
|
||||
* Which chapter the camera opens on. Defaults to `chapters[0]`.
|
||||
*
|
||||
* The pack's chapter list is a numbered tour and a capture contract — index
|
||||
* 0 is the state's whole-board pose, and twenty-nine shot-list guards aim at
|
||||
* buttons by that order. The *visitor* landing is a different question: a
|
||||
* bare tera.lumbridgecorp.com should open on a city you can read, not on
|
||||
* 1,551 km of tan. Passing `fidi` here does that without reordering the pack.
|
||||
* Unknown ids throw rather than silently falling back, so a renamed chapter
|
||||
* cannot photograph the state under a caption about downtown.
|
||||
*/
|
||||
openingChapter?: string;
|
||||
}
|
||||
|
||||
export interface SceneHandle {
|
||||
@@ -1419,8 +1431,14 @@ export async function createScene(
|
||||
const chapterById = Object.fromEntries(city.chapters.map((c) => [c.id, c]));
|
||||
const first = city.chapters[0];
|
||||
if (!first) throw new Error(`City "${city.id}" declares no chapters`);
|
||||
if (options.openingChapter !== undefined && chapterById[options.openingChapter] === undefined) {
|
||||
throw new Error(
|
||||
`openingChapter "${options.openingChapter}" is not a chapter of city "${city.id}"`,
|
||||
);
|
||||
}
|
||||
const landing = chapterById[options.openingChapter ?? first.id] ?? first;
|
||||
|
||||
let currentChapter = first.id;
|
||||
let currentChapter = landing.id;
|
||||
const chapterListeners: ((id: string) => void)[] = [];
|
||||
const controlModeListeners: ((mode: CityControlMode) => void)[] = [];
|
||||
|
||||
@@ -1518,10 +1536,10 @@ export async function createScene(
|
||||
* Two rules govern everything below and both were learned from a picture.
|
||||
*
|
||||
* **The board settles exactly where the pack said it would.** `openingPose`
|
||||
* is `chapterPose(first)` unchanged, so the resting frame is the one the pack
|
||||
* authored, chapter 01 keeps meaning what it says, and a capture of this
|
||||
* board is the same capture it was before an arrival existed. The wow is the
|
||||
* *approach*; nothing about the destination is second-guessed here.
|
||||
* is `chapterPose(landing)` — `chapters[0]` unless the caller named a
|
||||
* chapter, so a capture that does not pass `openingChapter` is the same
|
||||
* capture it was, and a bare URL that does can land on a city without
|
||||
* reordering the pack. The wow is the *approach*.
|
||||
*
|
||||
* **Under `prefers-reduced-motion` there is no move at all.** Not a shorter
|
||||
* one — none: the camera is placed on the resting pose and that is the whole
|
||||
@@ -1529,7 +1547,7 @@ export async function createScene(
|
||||
* capture harness honest, because a screenshot of a board mid-flight is a
|
||||
* screenshot of a different board every time you take it.
|
||||
*/
|
||||
const openingPose = chapterPose(first);
|
||||
const openingPose = chapterPose(landing);
|
||||
|
||||
/**
|
||||
* The opening move, or `null` when there is not one running.
|
||||
|
||||
+7
-3
@@ -339,9 +339,10 @@ const CITIES: { id: string; label: string; city: City }[] = ONE_CALIFORNIA
|
||||
/*
|
||||
* With one board there is nothing to choose: the argument above is entirely
|
||||
* about which of three products a bare URL lands on, and `?one=1` is the answer
|
||||
* that there are not three. The landing *pose* is a separate question and still
|
||||
* belongs to the chapter list — `california-overview` frames the state, and the
|
||||
* metro rungs restored in `cities/unify.ts` are how you get down from it.
|
||||
* that there are not three. The landing *pose* is a separate question: the
|
||||
* pack still opens its chapter list on `california-overview` so capture and
|
||||
* `?city=california` frame the state, and a bare URL passes `openingChapter:
|
||||
* "fidi"` so a visitor's first frame is a city they can read.
|
||||
*/
|
||||
const DEFAULT_CITY_ID = ONE_CALIFORNIA ? "california" : "sf";
|
||||
|
||||
@@ -1916,6 +1917,9 @@ async function buildBoard(
|
||||
const drawsMigration = carriesSky && access.feeds?.birds === true;
|
||||
const handle = await createScene(stage, {
|
||||
city: entry.city,
|
||||
// Bare URL on one California: land in the city, not on 1,551 km of state.
|
||||
// `?city=california` (and every capture shot) still opens on chapters[0].
|
||||
...(ONE_CALIFORNIA && CITY_PARAM === null ? { openingChapter: "fidi" } : {}),
|
||||
// The page's one rig, shared with the office. Handed in rather than built
|
||||
// per board; see the note where it is constructed.
|
||||
environment,
|
||||
|
||||
@@ -601,6 +601,17 @@ test("the water reflects rather than absorbing, now that there is a sky to refle
|
||||
|
||||
const MAIN = readFileSync(path.join(ROOT, "src/main.ts"), "utf8");
|
||||
|
||||
test("a bare URL on one California opens on FiDi, not on the whole state", () => {
|
||||
assert.ok(
|
||||
MAIN.includes('openingChapter: "fidi"'),
|
||||
"the visitor landing lost its city; they will see 1,551 km of tan",
|
||||
);
|
||||
assert.ok(
|
||||
MAIN.includes("CITY_PARAM === null"),
|
||||
"the fidi opening must not apply to ?city=california — that is the capture harness",
|
||||
);
|
||||
});
|
||||
|
||||
test("main.ts makes exactly one call into the chrome, and writes no visibility itself", () => {
|
||||
const applies = [...MAIN.matchAll(/chrome\?\.apply\(chromeState\(/g)].length;
|
||||
assert.equal(
|
||||
|
||||
@@ -165,6 +165,7 @@ describe("one California's chapters", () => {
|
||||
// Nothing merged twice, which a naive concat of two packs sharing an id
|
||||
// would do without failing anything else.
|
||||
assert.equal(new Set(ids).size, ids.length);
|
||||
assert.ok(ids.includes("fidi"), "the visitor landing names a chapter the merge dropped");
|
||||
});
|
||||
|
||||
it("restates each merged rung in this board's units, keeping its true metres", () => {
|
||||
|
||||
Reference in New Issue
Block a user