fix(chat): use weekly limit for message quota
This commit is contained in:
@@ -44,7 +44,7 @@ export function ChatScreen() {
|
|||||||
|
|
||||||
// 消息数量限制由后端统一返回 lockDetail,前端不再处理本地额度。
|
// 消息数量限制由后端统一返回 lockDetail,前端不再处理本地额度。
|
||||||
const showMessageLimitBanner =
|
const showMessageLimitBanner =
|
||||||
state.upgradePromptVisible && state.upgradeReason === "daily_limit";
|
state.upgradePromptVisible && state.upgradeReason === "weekly_limit";
|
||||||
const messageLimitTitle = "The limit for free chat times\nhas been reached";
|
const messageLimitTitle = "The limit for free chat times\nhas been reached";
|
||||||
|
|
||||||
const externalBrowserPromptShownRef = useRef(false);
|
const externalBrowserPromptShownRef = useRef(false);
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
* ChatQuotaExhaustedBanner 游客配额耗尽横幅
|
* ChatQuotaExhaustedBanner 游客配额耗尽横幅
|
||||||
*
|
*
|
||||||
* 何时显示:
|
* 何时显示:
|
||||||
* - 后端返回 lockDetail.reason="daily_limit" 且 showUpgrade=true
|
* - 后端返回 lockDetail.reason="weekly_limit" 且 showUpgrade=true
|
||||||
*
|
*
|
||||||
* 视觉规格(与设计稿对齐):
|
* 视觉规格(与设计稿对齐):
|
||||||
* - 粉→品红渐变背景(与 splash 渐变一致)
|
* - 粉→品红渐变背景(与 splash 渐变一致)
|
||||||
|
|||||||
@@ -132,7 +132,7 @@ describe("sendResponseToUiMessage", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe("applyHttpSendOutput", () => {
|
describe("applyHttpSendOutput", () => {
|
||||||
it("removes the optimistic user message when the daily limit is reached", () => {
|
it("removes the optimistic user message when the weekly limit is reached", () => {
|
||||||
const context = makeChatState({
|
const context = makeChatState({
|
||||||
messages: [
|
messages: [
|
||||||
{
|
{
|
||||||
@@ -151,11 +151,11 @@ describe("applyHttpSendOutput", () => {
|
|||||||
locked: true,
|
locked: true,
|
||||||
showContent: false,
|
showContent: false,
|
||||||
showUpgrade: true,
|
showUpgrade: true,
|
||||||
reason: "daily_limit",
|
reason: "weekly_limit",
|
||||||
hint: "Free message limit reached.",
|
hint: "Free message limit reached.",
|
||||||
detail: {
|
detail: {
|
||||||
type: "daily_msg_limit",
|
type: "weekly_msg_limit",
|
||||||
usedToday: 3,
|
usedThisWeek: 3,
|
||||||
limit: 3,
|
limit: 3,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -166,7 +166,7 @@ describe("applyHttpSendOutput", () => {
|
|||||||
expect(nextState.messages).toEqual([]);
|
expect(nextState.messages).toEqual([]);
|
||||||
expect(nextState.isReplyingAI).toBe(false);
|
expect(nextState.isReplyingAI).toBe(false);
|
||||||
expect(nextState.upgradePromptVisible).toBe(true);
|
expect(nextState.upgradePromptVisible).toBe(true);
|
||||||
expect(nextState.upgradeReason).toBe("daily_limit");
|
expect(nextState.upgradeReason).toBe("weekly_limit");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -262,7 +262,7 @@ describe("countLockedHistoryMessages", () => {
|
|||||||
isFromAI: true,
|
isFromAI: true,
|
||||||
date: "2026-06-29",
|
date: "2026-06-29",
|
||||||
locked: true,
|
locked: true,
|
||||||
lockReason: "daily_limit",
|
lockReason: "weekly_limit",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
content: "user text",
|
content: "user text",
|
||||||
|
|||||||
@@ -437,7 +437,7 @@ describe("chatMachine transitions", () => {
|
|||||||
actor.stop();
|
actor.stop();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("clears the daily limit prompt after payment succeeds", async () => {
|
it("clears the weekly limit prompt after payment succeeds", async () => {
|
||||||
const actor = createActor(createTestChatMachine()).start();
|
const actor = createActor(createTestChatMachine()).start();
|
||||||
|
|
||||||
actor.send({ type: "ChatUserLogin", token: "token" });
|
actor.send({ type: "ChatUserLogin", token: "token" });
|
||||||
@@ -459,11 +459,11 @@ describe("chatMachine transitions", () => {
|
|||||||
locked: true,
|
locked: true,
|
||||||
showContent: false,
|
showContent: false,
|
||||||
showUpgrade: true,
|
showUpgrade: true,
|
||||||
reason: "daily_limit",
|
reason: "weekly_limit",
|
||||||
hint: "Free message limit reached.",
|
hint: "Free message limit reached.",
|
||||||
detail: {
|
detail: {
|
||||||
type: "daily_msg_limit",
|
type: "weekly_msg_limit",
|
||||||
usedToday: 3,
|
usedThisWeek: 3,
|
||||||
limit: 3,
|
limit: 3,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -473,7 +473,7 @@ describe("chatMachine transitions", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
expect(actor.getSnapshot().context.upgradePromptVisible).toBe(true);
|
expect(actor.getSnapshot().context.upgradePromptVisible).toBe(true);
|
||||||
expect(actor.getSnapshot().context.upgradeReason).toBe("daily_limit");
|
expect(actor.getSnapshot().context.upgradeReason).toBe("weekly_limit");
|
||||||
|
|
||||||
actor.send({ type: "ChatPaymentSucceeded" });
|
actor.send({ type: "ChatPaymentSucceeded" });
|
||||||
|
|
||||||
|
|||||||
@@ -156,12 +156,12 @@ async function sendMessageViaHttp(content: string): Promise<{
|
|||||||
log.error("[chat-machine] sendMessageHttpActor failed", { error: result.error });
|
log.error("[chat-machine] sendMessageHttpActor failed", { error: result.error });
|
||||||
throw result.error;
|
throw result.error;
|
||||||
}
|
}
|
||||||
const isDailyLimit =
|
const isMessageLimit =
|
||||||
result.data.lockDetail.locked &&
|
result.data.lockDetail.locked &&
|
||||||
result.data.lockDetail.showUpgrade &&
|
result.data.lockDetail.showUpgrade &&
|
||||||
result.data.lockDetail.reason === "daily_limit";
|
result.data.lockDetail.reason === "weekly_limit";
|
||||||
return {
|
return {
|
||||||
response: result.data,
|
response: result.data,
|
||||||
reply: isDailyLimit ? null : sendResponseToUiMessage(result.data),
|
reply: isMessageLimit ? null : sendResponseToUiMessage(result.data),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -173,7 +173,7 @@ export function applyHttpSendOutput(
|
|||||||
const isMessageLimitBlocked =
|
const isMessageLimitBlocked =
|
||||||
lockDetail.locked &&
|
lockDetail.locked &&
|
||||||
lockDetail.showUpgrade &&
|
lockDetail.showUpgrade &&
|
||||||
lockDetail.reason === "daily_limit";
|
lockDetail.reason === "weekly_limit";
|
||||||
|
|
||||||
if (isMessageLimitBlocked) {
|
if (isMessageLimitBlocked) {
|
||||||
const lastMessage = context.messages[context.messages.length - 1];
|
const lastMessage = context.messages[context.messages.length - 1];
|
||||||
@@ -186,7 +186,7 @@ export function applyHttpSendOutput(
|
|||||||
messages,
|
messages,
|
||||||
...finishPendingReply(context),
|
...finishPendingReply(context),
|
||||||
upgradePromptVisible: true,
|
upgradePromptVisible: true,
|
||||||
upgradeReason: "daily_limit",
|
upgradeReason: "weekly_limit",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,7 @@
|
|||||||
*
|
*
|
||||||
* 配额:
|
* 配额:
|
||||||
* - 前端不再处理本地消息额度;游客 / 注册用户均以后端响应为准。
|
* - 前端不再处理本地消息额度;游客 / 注册用户均以后端响应为准。
|
||||||
* - 后端返回 `lockDetail.reason="daily_limit"` 且需要升级时展示会员引导。
|
* - 后端返回 `lockDetail.reason="weekly_limit"` 且需要升级时展示会员引导。
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ export interface ChatState {
|
|||||||
isReplyingAI: boolean;
|
isReplyingAI: boolean;
|
||||||
pendingReplyCount: number;
|
pendingReplyCount: number;
|
||||||
upgradePromptVisible: boolean;
|
upgradePromptVisible: boolean;
|
||||||
upgradeReason: "daily_limit" | null;
|
upgradeReason: "weekly_limit" | null;
|
||||||
isLoadingMore: boolean;
|
isLoadingMore: boolean;
|
||||||
hasMore: boolean;
|
hasMore: boolean;
|
||||||
historyOffset: number;
|
historyOffset: number;
|
||||||
|
|||||||
Reference in New Issue
Block a user