feat(chat): handle credit-gated send responses

This commit is contained in:
2026-06-30 14:17:14 +08:00
parent f4d0f76466
commit 958a0f8ffd
12 changed files with 303 additions and 17 deletions
+26 -3
View File
@@ -6,6 +6,7 @@ import { useRouter } from "next/navigation";
import { useAuthState } from "@/stores/auth/auth-context";
import { useChatDispatch, useChatState } from "@/stores/chat/chat-context";
import { useUserState } from "@/stores/user/user-context";
import { MobileShell } from "@/app/_components/core";
@@ -22,6 +23,7 @@ import {
import {
deriveIsGuest,
getChatPaywallNavigationUrl,
getInsufficientCreditsSubscriptionType,
isChatDevelopmentEnvironment,
openChatInExternalBrowser,
recordExternalBrowserPromptShown,
@@ -34,6 +36,7 @@ export function ChatScreen() {
const state = useChatState();
const chatDispatch = useChatDispatch();
const authState = useAuthState();
const userState = useUserState();
const router = useRouter();
const [showExternalBrowserDialog, setShowExternalBrowserDialog] =
useState(false);
@@ -43,8 +46,17 @@ export function ChatScreen() {
// 消息数量限制由后端统一返回 lockDetail,前端不再处理本地额度。
const showMessageLimitBanner =
state.upgradePromptVisible && state.upgradeReason === "weekly_limit";
const messageLimitTitle = "The limit for free chat times\nhas been reached";
state.upgradePromptVisible &&
(state.upgradeReason === "weekly_limit" ||
state.upgradeReason === "insufficient_credits");
const messageLimitTitle =
state.upgradeReason === "insufficient_credits"
? "Insufficient credits\nTop up to continue chatting"
: "The limit for free chat times\nhas been reached";
const messageLimitCtaLabel =
state.upgradeReason === "insufficient_credits"
? "Top up credits to continue"
: "Unlock your membership to continue";
const externalBrowserPromptShownRef = useRef(false);
@@ -102,7 +114,17 @@ export function ChatScreen() {
}
function handleMessageLimitUnlock(): void {
openChatPaywallSubscription();
const subscriptionType =
state.upgradeReason === "insufficient_credits"
? getInsufficientCreditsSubscriptionType(userState.isVip)
: "vip";
router.push(
getChatPaywallNavigationUrl(
authState.loginStatus,
subscriptionType,
),
);
}
function handleUnlockVoiceMessage(): void {
@@ -137,6 +159,7 @@ export function ChatScreen() {
{showMessageLimitBanner ? (
<ChatQuotaExhaustedBanner
title={messageLimitTitle}
ctaLabel={messageLimitCtaLabel}
onUnlock={handleMessageLimitUnlock}
/>
) : (