feat(birth-sky): poster-only dialog, date/time/city caption, slower reveal, paywall on first refused send (P1–P5, BUG-1080)
TASK-birth-sky-polish-20260928. - P1: chart page dialog shows only the picture on a dimmed stage, 「保存图片」 below, icon × in the corner. - P2: BFF returns one server-built `caption` (「1994年5月18日 07:40 · 杭州」); printed under the fact line in all three places; adopted time adds 「 · 校正后」. - P3: convergence 3 s + words 2.5 s + fade 1 s; settled frame still equals the exported cover. - P4: redeem paywall no longer opens when the starter home appears; first send refused for credits opens it, later ones open billing; convergence dialog portalled to <body>. BUG-1080 investigating (Chrome repro rules out the overlay covering the convergence). 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
1a4f77584b
commit
dec36bce01
@@ -5,6 +5,7 @@ import type { Dispatch, MutableRefObject, RefObject, SetStateAction } from "reac
|
||||
|
||||
import { composerDraftSnapshot } from "@/lib/composer-draft";
|
||||
import { appendQueuedText, queuedDraftSettleAction } from "@/lib/queued-draft";
|
||||
import { tryOpenRedeemPaywall } from "@/lib/redeem-paywall-once";
|
||||
import { useQueuedMessage } from "@/hooks/use-queued-message";
|
||||
|
||||
import { showChatNotice as setComposerNotice } from "@/lib/chat-notice";
|
||||
@@ -150,6 +151,9 @@ export type ConsultationRunParams = {
|
||||
continueInNewChat: (prompt: { question: string; theme: Theme }) => Promise<void>;
|
||||
refreshAccount: () => Promise<void>;
|
||||
openAccountDialog: (dialog: AccountDialog, options?: HTMLButtonElement | null | OpenAccountDialogOptions) => void;
|
||||
/** Set once the redeem paywall has been shown on this page (TASK-birth-sky-polish-20260928 P4). */
|
||||
onboardingPaywallShown?: MutableRefObject<boolean>;
|
||||
setOnboardingPaywallOpen?: (open: boolean) => void;
|
||||
openRectificationFromHomepage: (pendingConsultationQuestion?: string | null) => Promise<void>;
|
||||
openRectificationSession: (exactSessionId: string) => Promise<void> | void;
|
||||
};
|
||||
@@ -209,9 +213,17 @@ export function useConsultationRun(params: ConsultationRunParams) {
|
||||
continueInNewChat,
|
||||
refreshAccount,
|
||||
openAccountDialog,
|
||||
onboardingPaywallShown,
|
||||
setOnboardingPaywallOpen,
|
||||
openRectificationFromHomepage,
|
||||
openRectificationSession,
|
||||
} = params;
|
||||
// First refusal for credits on this page → redeem paywall; later ones → billing (P4, BUG-1080).
|
||||
const openRedeemPaywallOnce = () => tryOpenRedeemPaywall({
|
||||
uiPreview: uiPreview.current,
|
||||
shown: onboardingPaywallShown,
|
||||
open: setOnboardingPaywallOpen,
|
||||
});
|
||||
const queued = useQueuedMessage();
|
||||
|
||||
function enqueueQueuedDraft(incoming: string) {
|
||||
@@ -614,7 +626,7 @@ export function useConsultationRun(params: ConsultationRunParams) {
|
||||
: initialConsultationRoute;
|
||||
|
||||
if (account.credits <= 0 && !account.activeSubscription) {
|
||||
openAccountDialog("billing", { source: "insufficient-credits" });
|
||||
if (!openRedeemPaywallOnce()) openAccountDialog("billing", { source: "insufficient-credits" });
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -854,7 +866,7 @@ export function useConsultationRun(params: ConsultationRunParams) {
|
||||
// it is open (BUG-1074): same status semantics either way.
|
||||
const rejectRun = (status: number, message: string, code?: string): never => {
|
||||
if (status === 401) window.location.assign("/login");
|
||||
if (status === 402) openAccountDialog("billing", { source: "insufficient-credits" });
|
||||
if (status === 402 && !openRedeemPaywallOnce()) openAccountDialog("billing", { source: "insufficient-credits" });
|
||||
throw new ConsultationResponseError(status, message, code);
|
||||
};
|
||||
if (!response.ok) {
|
||||
|
||||
Reference in New Issue
Block a user