feat(chat): migrate chat protocol to lock detail
This commit is contained in:
@@ -27,15 +27,15 @@
|
||||
* - 每个任务都是独立 actor,不互相等待(除非 `always` barrier)
|
||||
*
|
||||
* 消息发送路径(业务事实):
|
||||
* - guestSession:走 HTTP,消息数量限制以后端 `blocked` 响应为准
|
||||
* - nonVipUserSession:走 HTTP,让后端返回 daily_limit blocked
|
||||
* - guestSession:走 HTTP,消息数量限制以后端 `lockDetail` 响应为准
|
||||
* - nonVipUserSession:走 HTTP,让后端返回 daily_limit lockDetail
|
||||
* - vipUserSession + WS 已连:走 WS,不受每日免费次数限制
|
||||
* - `ChatWebSocketConnected` 事件 → `wsConnected = true`
|
||||
* - `vipUserSession.exit` action → `wsConnected = false`(WS actor cleanup 时也会跑 exit)
|
||||
*
|
||||
* 配额:
|
||||
* - 前端不再处理本地消息额度;游客 / 注册用户均以后端响应为准。
|
||||
* - 后端返回 `blocked=true && blockReason="daily_limit"` 时展示会员引导。
|
||||
* - 后端返回 `lockDetail.reason="daily_limit"` 且需要升级时展示会员引导。
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -45,7 +45,10 @@ import { todayString, Logger } from "@/utils";
|
||||
|
||||
import { ChatState, initialState } from "./chat-state";
|
||||
import type { ChatEvent } from "./chat-events";
|
||||
import { applyHttpSendOutput } from "./chat-machine.helpers";
|
||||
import {
|
||||
applyHttpSendOutput,
|
||||
normalizeLockDetail,
|
||||
} from "./chat-machine.helpers";
|
||||
import {
|
||||
loadHistoryActor,
|
||||
sendMessageHttpActor,
|
||||
@@ -112,9 +115,10 @@ export const chatMachine = setup({
|
||||
},
|
||||
],
|
||||
isReplyingAI: true,
|
||||
paywallTriggered: false,
|
||||
paywallReason: null,
|
||||
paywallDetail: null,
|
||||
upgradePromptVisible: false,
|
||||
upgradeReason: null,
|
||||
upgradeHint: null,
|
||||
upgradeDetail: null,
|
||||
};
|
||||
}),
|
||||
|
||||
@@ -139,9 +143,10 @@ export const chatMachine = setup({
|
||||
},
|
||||
],
|
||||
isReplyingAI: true,
|
||||
paywallTriggered: false,
|
||||
paywallReason: null,
|
||||
paywallDetail: null,
|
||||
upgradePromptVisible: false,
|
||||
upgradeReason: null,
|
||||
upgradeHint: null,
|
||||
upgradeDetail: null,
|
||||
};
|
||||
}),
|
||||
|
||||
@@ -164,9 +169,10 @@ export const chatMachine = setup({
|
||||
},
|
||||
],
|
||||
isReplyingAI: true,
|
||||
paywallTriggered: false,
|
||||
paywallReason: null,
|
||||
paywallDetail: null,
|
||||
upgradePromptVisible: false,
|
||||
upgradeReason: null,
|
||||
upgradeHint: null,
|
||||
upgradeDetail: null,
|
||||
};
|
||||
}),
|
||||
|
||||
@@ -190,9 +196,10 @@ export const chatMachine = setup({
|
||||
},
|
||||
],
|
||||
isReplyingAI: true,
|
||||
paywallTriggered: false,
|
||||
paywallReason: null,
|
||||
paywallDetail: null,
|
||||
upgradePromptVisible: false,
|
||||
upgradeReason: null,
|
||||
upgradeHint: null,
|
||||
upgradeDetail: null,
|
||||
};
|
||||
}),
|
||||
|
||||
@@ -244,14 +251,14 @@ export const chatMachine = setup({
|
||||
messages[messages.length - 1] = {
|
||||
...last,
|
||||
content: "",
|
||||
imageUrl: event.imageUrl,
|
||||
imageUrl: event.url,
|
||||
};
|
||||
} else {
|
||||
messages.push({
|
||||
content: "",
|
||||
isFromAI: true,
|
||||
date: todayString(),
|
||||
imageUrl: event.imageUrl,
|
||||
imageUrl: event.url,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -262,25 +269,31 @@ export const chatMachine = setup({
|
||||
|
||||
return {
|
||||
messages,
|
||||
paywallTriggered: false,
|
||||
paywallReason: null,
|
||||
paywallDetail: null,
|
||||
upgradePromptVisible: false,
|
||||
upgradeReason: null,
|
||||
upgradeHint: null,
|
||||
upgradeDetail: null,
|
||||
};
|
||||
}),
|
||||
|
||||
applyPaywallStatus: assign(({ event }) => {
|
||||
if (event.type !== "ChatPaywallStatusReceived") return {};
|
||||
if (!event.showUpgrade) {
|
||||
if (!event.lockDetail.showUpgrade) {
|
||||
return {
|
||||
paywallTriggered: false,
|
||||
paywallReason: null,
|
||||
paywallDetail: null,
|
||||
upgradePromptVisible: false,
|
||||
upgradeReason: null,
|
||||
upgradeHint: null,
|
||||
upgradeDetail: null,
|
||||
};
|
||||
}
|
||||
return {
|
||||
paywallTriggered: true,
|
||||
paywallReason: "photo_paywall",
|
||||
paywallDetail: null,
|
||||
upgradePromptVisible: true,
|
||||
upgradeReason:
|
||||
event.lockDetail.reason === "private_message"
|
||||
? "private_message"
|
||||
: "image",
|
||||
upgradeHint: event.lockDetail.hint,
|
||||
upgradeDetail: normalizeLockDetail(event.lockDetail.detail),
|
||||
};
|
||||
}),
|
||||
|
||||
@@ -288,9 +301,10 @@ export const chatMachine = setup({
|
||||
if (event.type !== "ChatUnlockPrivateMessage") return {};
|
||||
return {
|
||||
unlockingPrivateMessageId: event.messageId,
|
||||
paywallTriggered: false,
|
||||
paywallReason: null,
|
||||
paywallDetail: null,
|
||||
upgradePromptVisible: false,
|
||||
upgradeReason: null,
|
||||
upgradeHint: null,
|
||||
upgradeDetail: null,
|
||||
};
|
||||
}),
|
||||
|
||||
@@ -309,25 +323,27 @@ export const chatMachine = setup({
|
||||
? {
|
||||
...message,
|
||||
content: response.content ?? message.content,
|
||||
privateLocked: false,
|
||||
privateHint: null,
|
||||
lockedPrivate: false,
|
||||
privateMessageHint: null,
|
||||
isPrivate: message.isPrivate ?? true,
|
||||
}
|
||||
: message,
|
||||
),
|
||||
unlockingPrivateMessageId: null,
|
||||
paywallTriggered: false,
|
||||
paywallReason: null,
|
||||
paywallDetail: null,
|
||||
upgradePromptVisible: false,
|
||||
upgradeReason: null,
|
||||
upgradeHint: null,
|
||||
upgradeDetail: null,
|
||||
};
|
||||
}
|
||||
|
||||
if (response.showUpgrade) {
|
||||
return {
|
||||
unlockingPrivateMessageId: null,
|
||||
paywallTriggered: true,
|
||||
paywallReason: "private_paywall",
|
||||
paywallDetail: {
|
||||
upgradePromptVisible: true,
|
||||
upgradeReason: "private_message",
|
||||
upgradeHint: null,
|
||||
upgradeDetail: {
|
||||
usedToday: response.privateUsedToday,
|
||||
limit: response.privateFreeLimit,
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user