The China city table loads on demand; old code-only profiles load it before the people list settles, so they resolve exactly as before. The gate keeps the six holdout fields it reads, pinned to the JSON by a test. The onboarding shell is preloaded before reveal only when the profile is incomplete. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01N4f2nya58RoRu4yEmJgRGE
69 lines
2.5 KiB
TypeScript
69 lines
2.5 KiB
TypeScript
import type { ChinaLocationData } from "@/data/china-locations";
|
|
|
|
/**
|
|
* The China city table on the client, loaded on demand (TASK-home-first-load
|
|
* T7, BUG-1130). The table (≈227 KB, ≈47 KB brotli) used to ride in the home
|
|
* page's first-screen bundle through `home-types.ts`, although only two things
|
|
* need it: the birth-place picker (which imports it statically and registers it
|
|
* here) and old profiles that carry province / city codes but no coordinates.
|
|
*
|
|
* `selectedBirthPlace` stays synchronous and reads `loadedChinaCountry()`. The
|
|
* cold boot awaits `ensureChinaLocations()` before reveal whenever the account
|
|
* or the people list holds such an old profile, so those profiles resolve to
|
|
* exactly the place they did before (see session-list-context.tsx and
|
|
* current-subject.ts). Profiles saved with coordinates never need it.
|
|
*/
|
|
export type ChinaCountry = ChinaLocationData["country"];
|
|
|
|
let country: ChinaCountry | null = null;
|
|
let loading: Promise<ChinaCountry> | null = null;
|
|
|
|
export function loadedChinaCountry(): ChinaCountry | null {
|
|
return country;
|
|
}
|
|
|
|
export function registerChinaCountry(value: ChinaCountry): void {
|
|
country = value;
|
|
}
|
|
|
|
export function ensureChinaLocations(): Promise<ChinaCountry> {
|
|
if (country) return Promise.resolve(country);
|
|
loading ??= import("@/data/china-locations").then((module) => {
|
|
country = module.chinaLocations.country;
|
|
return country;
|
|
}, (error: unknown) => {
|
|
loading = null;
|
|
throw error;
|
|
});
|
|
return loading;
|
|
}
|
|
|
|
type PlaceFields = Readonly<{
|
|
provinceCode?: string;
|
|
birthPlaceLabel?: string;
|
|
latitude?: number | null;
|
|
longitude?: number | null;
|
|
timezoneId?: string;
|
|
timezoneOffset?: number | null;
|
|
}>;
|
|
|
|
/**
|
|
* True when `selectedBirthPlace` would have to look the place up by code: the
|
|
* profile has a province code but not the saved label + coordinates + zone.
|
|
* Mirrors the first branch of `selectedBirthPlace` in home-profile.ts.
|
|
*/
|
|
export function profileNeedsChinaLocations(profile: PlaceFields | null | undefined): boolean {
|
|
if (!profile || !profile.provinceCode) return false;
|
|
const saved = Boolean(profile.birthPlaceLabel)
|
|
&& Number.isFinite(profile.latitude)
|
|
&& Number.isFinite(profile.longitude)
|
|
&& Boolean(profile.timezoneId?.trim())
|
|
&& (profile.timezoneOffset === null || profile.timezoneOffset === undefined || Number.isFinite(profile.timezoneOffset));
|
|
return !saved;
|
|
}
|
|
|
|
export function resetChinaLocationsForTests(): void {
|
|
country = null;
|
|
loading = null;
|
|
}
|