feat(loading): chart wait lights houses up in order, people archive uses the orbit, today's line no longer jumps in after reveal (BUG-1125)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01N4f2nya58RoRu4yEmJgRGE
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
9a616107c2
commit
d327ca9c95
@@ -1,20 +1,20 @@
|
||||
import { EMPTY_NORTH_INDIAN_CHART, VedicChartSvg } from "@/components/personal-report/vedic-chart-svg";
|
||||
import { EMPTY_WESTERN_WHEEL, WesternWheelSvg } from "./western-wheel-svg";
|
||||
import { OrbitWaiting } from "@/components/orbit-waiting";
|
||||
|
||||
/** Only chart positions opt in; the shared page shell remains static. */
|
||||
export function ChartPageSkeleton({ copy, western = false }: { copy: string; western?: boolean }) {
|
||||
return (
|
||||
<div className={western ? "chart-page-western-layout" : "chart-page-vedic-layout"}>
|
||||
<div className={`chart-page-waiting-plot ${western ? "chart-page-western-wheel" : "chart-page-vedic-stage"}`} aria-busy="true" role="status">
|
||||
{/* The empty drawing is the whole wait (2026-09-30, product: 「星盘的加载动画
|
||||
太丑了」, chose 宫位依次点亮): faint static lines while the houses light up
|
||||
one after another in house order. No orbit logo over it any more. Same
|
||||
box as the finished chart, so the reveal does not jump (BUG-1101). */}
|
||||
<div className={western ? "chart-page-skeleton" : "chart-page-skeleton chart-page-vedic-plot"} aria-hidden="true">
|
||||
{western ? <WesternWheelSvg western={EMPTY_WESTERN_WHEEL} skeleton />
|
||||
: <VedicChartSvg chart={EMPTY_NORTH_INDIAN_CHART} ariaLabel={copy} skeleton />}
|
||||
</div>
|
||||
{/* Over the empty drawing, not under it, so the waiting stage and the
|
||||
finished one are the same height (BUG-1101). An orbit, not a sentence
|
||||
(2026-09-30); the sentence is for screen readers. */}
|
||||
<OrbitWaiting className="chart-page-skeleton-copy" label={copy} />
|
||||
<span className="sr-only">{copy}</span>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { MouseEvent, PointerEvent } from "react";
|
||||
import type { CSSProperties, MouseEvent, PointerEvent } from "react";
|
||||
|
||||
import type { ChartViewWesternOk } from "@/lib/chart-view-contract";
|
||||
import { SIGN_ORDER, signZh, type SignName } from "@/lib/chart-view-labels";
|
||||
@@ -183,6 +183,15 @@ export function WesternWheelSvg({
|
||||
/>
|
||||
);
|
||||
})}
|
||||
{/* Waiting wheel only: twelve sectors that light up in turn around the circle. */}
|
||||
{skeleton && SIGN_ORDER.map((sign, index) => (
|
||||
<path
|
||||
key={`${sign}-waiting`}
|
||||
d={westernRingSlice(WESTERN_R_ZODIAC, WESTERN_R_OUTER, westernScreenAngle(index * 30 + 30, asc), westernScreenAngle(index * 30, asc))}
|
||||
className="chart-skeleton-sector"
|
||||
style={{ "--house-index": index } as CSSProperties}
|
||||
/>
|
||||
))}
|
||||
<circle cx={WESTERN_CX} cy={WESTERN_CY} r={WESTERN_R_OUTER} className="chart-page-western-ring" />
|
||||
<circle cx={WESTERN_CX} cy={WESTERN_CY} r={WESTERN_R_ZODIAC} className="chart-page-western-ring" />
|
||||
<circle cx={WESTERN_CX} cy={WESTERN_CY} r={WESTERN_R_HOUSE} className="chart-page-western-ring" />
|
||||
|
||||
@@ -5,6 +5,7 @@ import { useEffect } from "react";
|
||||
import { useCurrentSubject, useCurrentSubjectProfile, useCurrentSubjectReady } from "@/lib/current-subject";
|
||||
import { resolveBirthTimeConsultationRoute } from "@/lib/birth-time-consultation-consent";
|
||||
import { missingOtherProfileStep } from "@/lib/home-profile";
|
||||
import { SELF_SUBJECT_ID } from "@/lib/subject-birth";
|
||||
import { calendarDateInTimeZone, dailyStarlanguageProfileKey } from "@/lib/daily-starlanguage";
|
||||
import type { BootstrapPhase } from "@/lib/home-bootstrap";
|
||||
import { readHomeWarmDaily, rememberHomeWarmDaily } from "@/lib/home-warm-snapshot";
|
||||
@@ -36,7 +37,18 @@ export function DailyStarlanguageBinder(props: {
|
||||
const natalMinuteAvailable = route?.kind === "consult" && Boolean(route.time);
|
||||
|
||||
useEffect(() => {
|
||||
if (bootstrapPhase === "account" || !accountId || !subjectReady || !profile || !profileComplete || !natalMinuteAvailable) {
|
||||
// Only another person needs the catalog; the owner's profile is already here.
|
||||
// While it loads the card is "pending", not "unavailable": "unavailable" counted
|
||||
// as settled, the home revealed without the line, and the line jumped in under
|
||||
// the greeting a moment later (BUG-1125). Pending holds the reveal (bounded by
|
||||
// the prepare timeout) so the line arrives with the first frame.
|
||||
const waitingForCatalog = !subjectReady && subjectId !== SELF_SUBJECT_ID;
|
||||
if (bootstrapPhase !== "account" && accountId && waitingForCatalog) {
|
||||
let cancelled = false;
|
||||
queueMicrotask(() => { if (!cancelled) setDailyStarlanguage({ kind: "pending" }); });
|
||||
return () => { cancelled = true; };
|
||||
}
|
||||
if (bootstrapPhase === "account" || !accountId || waitingForCatalog || !profile || !profileComplete || !natalMinuteAvailable) {
|
||||
let cancelled = false;
|
||||
queueMicrotask(() => { if (!cancelled) setDailyStarlanguage({ kind: "unavailable" }); });
|
||||
return () => { cancelled = true; };
|
||||
|
||||
@@ -298,8 +298,8 @@ export function PeoplePage() {
|
||||
}
|
||||
|
||||
return (
|
||||
<SecondaryPageShell title="星盘档案">
|
||||
{status === "loading" ? <p className="secondary-page-waiting">人物列表还在读</p> : null}
|
||||
// The shared waiting orbit, like 星盘 / 星历 / 报告 (2026-09-30, product: 「星盘档案这里也要加一个加载动画」).
|
||||
<SecondaryPageShell title="星盘档案" waiting={status === "loading" ? "人物列表还在读" : null}>
|
||||
{status === "failed" ? (
|
||||
<section className="chart-page-message">
|
||||
<p>人物列表暂时读不出来</p>
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
* Colour identifies a body. It is not a benefic/malefic signal.
|
||||
*/
|
||||
|
||||
import { useId } from "react";
|
||||
import { useId, type CSSProperties } from "react";
|
||||
|
||||
import type { ChartV1 } from "@/lib/personal-report-contract";
|
||||
import { SIGN_ORDER, signZh } from "@/lib/chart-view-labels";
|
||||
@@ -364,6 +364,8 @@ export function VedicChartSvgDrawing({ chart: suppliedChart, ariaLabel, highligh
|
||||
<polygon
|
||||
points={polygonPoints(polygon)}
|
||||
className={`personal-report-chart-cell${highlightHouseNumbers?.has(houseNumber) ? " is-changed" : ""}`}
|
||||
// The waiting chart lights the houses up in house order (chart-skeleton-house).
|
||||
style={skeleton ? ({ "--house-index": houseNumber - 1 } as CSSProperties) : undefined}
|
||||
/>
|
||||
{ordinal !== null && (
|
||||
<g
|
||||
|
||||
@@ -36,7 +36,9 @@ export function StarterGreeting({ starterGreeting, dailyTrend = null, dailyTrend
|
||||
<section className="starter-greeting-block" aria-labelledby="starter-heading">
|
||||
<h1 id="starter-heading">{starterGreeting.text}</h1>
|
||||
{dailyTrend ? (
|
||||
<p className="starter-greeting-sub" role={dailyTrendSettled ? undefined : "status"}>
|
||||
// Keyed on the text: a line that arrives or changes after the first frame
|
||||
// fades in instead of snapping in (BUG-1125).
|
||||
<p key={dailyTrend} className="starter-greeting-sub" role={dailyTrendSettled ? undefined : "status"}>
|
||||
{dailyTrend}
|
||||
</p>
|
||||
) : null}
|
||||
|
||||
@@ -9,6 +9,7 @@ import {
|
||||
type ChatProfileCatalogStatus,
|
||||
type ChatProfilePickerRow,
|
||||
} from "@/lib/chat-profile-picker-model";
|
||||
import { OrbitWaiting } from "@/components/orbit-waiting";
|
||||
import type { ChartLibraryRecord } from "@/lib/home-types";
|
||||
|
||||
export type SubjectSwitcherProps = {
|
||||
@@ -88,7 +89,7 @@ export function SubjectSwitcher({
|
||||
}}
|
||||
>
|
||||
<Popover.Title className="chat-profile-picker-title">当前星盘</Popover.Title>
|
||||
{status === "loading" ? <p className="chat-profile-picker-status" role="status">人物列表还在读</p> : null}
|
||||
{status === "loading" ? <OrbitWaiting className="chat-profile-picker-waiting" label="人物列表还在读" /> : null}
|
||||
{status === "failed" ? (
|
||||
<div className="chat-profile-picker-status" role="status">
|
||||
<p>人物列表暂时读不出来</p>
|
||||
|
||||
Reference in New Issue
Block a user