refactor(chat): remove pagination-related state and logic from chat components
This commit is contained in:
@@ -40,9 +40,6 @@ function makeChatState(overrides: Partial<ChatState> = {}): ChatState {
|
|||||||
creditsCharged: 0,
|
creditsCharged: 0,
|
||||||
requiredCredits: 0,
|
requiredCredits: 0,
|
||||||
shortfallCredits: 0,
|
shortfallCredits: 0,
|
||||||
isLoadingMore: false,
|
|
||||||
hasMore: true,
|
|
||||||
historyOffset: 0,
|
|
||||||
historyLoaded: true,
|
historyLoaded: true,
|
||||||
paymentUnlockPending: false,
|
paymentUnlockPending: false,
|
||||||
unlockHistoryPromptVisible: false,
|
unlockHistoryPromptVisible: false,
|
||||||
|
|||||||
@@ -13,12 +13,6 @@ import type {
|
|||||||
UnlockMessageRequest,
|
UnlockMessageRequest,
|
||||||
} from "@/stores/chat/chat-machine.helpers";
|
} from "@/stores/chat/chat-machine.helpers";
|
||||||
|
|
||||||
interface LoadMoreHistoryOutput {
|
|
||||||
messages: UiMessage[];
|
|
||||||
hasMore: boolean;
|
|
||||||
newOffset: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface SendMessageHttpOutput {
|
interface SendMessageHttpOutput {
|
||||||
response: ChatSendResponse;
|
response: ChatSendResponse;
|
||||||
reply: UiMessage | null;
|
reply: UiMessage | null;
|
||||||
@@ -29,8 +23,6 @@ interface UnlockHistoryOutput {
|
|||||||
reason: string;
|
reason: string;
|
||||||
shortfallCredits: number;
|
shortfallCredits: number;
|
||||||
messages: UiMessage[];
|
messages: UiMessage[];
|
||||||
hasMore: boolean;
|
|
||||||
newOffset: number;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface TestUnlockMessageOutput {
|
interface TestUnlockMessageOutput {
|
||||||
@@ -83,13 +75,6 @@ function createTestChatMachine(
|
|||||||
return chatMachine.provide({
|
return chatMachine.provide({
|
||||||
actors: {
|
actors: {
|
||||||
loadHistory: createLoadHistoryCallback(options.historyMessages ?? []),
|
loadHistory: createLoadHistoryCallback(options.historyMessages ?? []),
|
||||||
loadMoreHistory: fromPromise<LoadMoreHistoryOutput, { offset: number }>(
|
|
||||||
async () => ({
|
|
||||||
messages: [],
|
|
||||||
hasMore: false,
|
|
||||||
newOffset: 0,
|
|
||||||
}),
|
|
||||||
),
|
|
||||||
sendMessageHttp: fromPromise<
|
sendMessageHttp: fromPromise<
|
||||||
SendMessageHttpOutput,
|
SendMessageHttpOutput,
|
||||||
{ content: string }
|
{ content: string }
|
||||||
@@ -116,8 +101,6 @@ function createTestChatMachine(
|
|||||||
reason: "ok",
|
reason: "ok",
|
||||||
shortfallCredits: 0,
|
shortfallCredits: 0,
|
||||||
messages: [],
|
messages: [],
|
||||||
hasMore: false,
|
|
||||||
newOffset: 0,
|
|
||||||
...options.unlockHistoryOutput,
|
...options.unlockHistoryOutput,
|
||||||
})),
|
})),
|
||||||
unlockMessage: fromPromise<
|
unlockMessage: fromPromise<
|
||||||
@@ -147,8 +130,6 @@ function createLoadHistoryCallback(
|
|||||||
type: "ChatLocalHistoryLoaded",
|
type: "ChatLocalHistoryLoaded",
|
||||||
output: {
|
output: {
|
||||||
messages,
|
messages,
|
||||||
hasMore: false,
|
|
||||||
newOffset: messages.length,
|
|
||||||
localCount: messages.length,
|
localCount: messages.length,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@@ -156,8 +137,6 @@ function createLoadHistoryCallback(
|
|||||||
type: "ChatNetworkHistoryLoaded",
|
type: "ChatNetworkHistoryLoaded",
|
||||||
output: {
|
output: {
|
||||||
messages: networkMessages,
|
messages: networkMessages,
|
||||||
hasMore: false,
|
|
||||||
newOffset: networkMessages.length,
|
|
||||||
localOverwritten: true,
|
localOverwritten: true,
|
||||||
localCount: messages.length,
|
localCount: messages.length,
|
||||||
networkCount: networkMessages.length,
|
networkCount: networkMessages.length,
|
||||||
@@ -283,8 +262,6 @@ describe("chatMachine transitions", () => {
|
|||||||
type: "ChatLocalHistoryLoaded",
|
type: "ChatLocalHistoryLoaded",
|
||||||
output: {
|
output: {
|
||||||
messages: [localMessage],
|
messages: [localMessage],
|
||||||
hasMore: false,
|
|
||||||
newOffset: 1,
|
|
||||||
localCount: 1,
|
localCount: 1,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@@ -293,8 +270,6 @@ describe("chatMachine transitions", () => {
|
|||||||
type: "ChatNetworkHistoryLoaded",
|
type: "ChatNetworkHistoryLoaded",
|
||||||
output: {
|
output: {
|
||||||
messages: [networkMessage],
|
messages: [networkMessage],
|
||||||
hasMore: false,
|
|
||||||
newOffset: 1,
|
|
||||||
localOverwritten: true,
|
localOverwritten: true,
|
||||||
localCount: 1,
|
localCount: 1,
|
||||||
networkCount: 1,
|
networkCount: 1,
|
||||||
@@ -399,13 +374,6 @@ describe("chatMachine transitions", () => {
|
|||||||
const machine = chatMachine.provide({
|
const machine = chatMachine.provide({
|
||||||
actors: {
|
actors: {
|
||||||
loadHistory: createLoadHistoryCallback([]),
|
loadHistory: createLoadHistoryCallback([]),
|
||||||
loadMoreHistory: fromPromise<LoadMoreHistoryOutput, { offset: number }>(
|
|
||||||
async () => ({
|
|
||||||
messages: [],
|
|
||||||
hasMore: false,
|
|
||||||
newOffset: 0,
|
|
||||||
}),
|
|
||||||
),
|
|
||||||
sendMessageHttp: fromPromise<
|
sendMessageHttp: fromPromise<
|
||||||
SendMessageHttpOutput,
|
SendMessageHttpOutput,
|
||||||
{ content: string }
|
{ content: string }
|
||||||
@@ -435,8 +403,6 @@ describe("chatMachine transitions", () => {
|
|||||||
reason: "ok",
|
reason: "ok",
|
||||||
shortfallCredits: 0,
|
shortfallCredits: 0,
|
||||||
messages: [],
|
messages: [],
|
||||||
hasMore: false,
|
|
||||||
newOffset: 0,
|
|
||||||
})),
|
})),
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@@ -526,8 +492,6 @@ describe("chatMachine transitions", () => {
|
|||||||
lockReason: null,
|
lockReason: null,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
hasMore: false,
|
|
||||||
newOffset: 1,
|
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
).start();
|
).start();
|
||||||
@@ -585,8 +549,6 @@ describe("chatMachine transitions", () => {
|
|||||||
lockReason: null,
|
lockReason: null,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
hasMore: false,
|
|
||||||
newOffset: 1,
|
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
).start();
|
).start();
|
||||||
|
|||||||
@@ -26,9 +26,6 @@ interface ChatState {
|
|||||||
isReplyingAI: boolean;
|
isReplyingAI: boolean;
|
||||||
upgradePromptVisible: boolean;
|
upgradePromptVisible: boolean;
|
||||||
upgradeReason: MachineContext["upgradeReason"];
|
upgradeReason: MachineContext["upgradeReason"];
|
||||||
isLoadingMore: boolean;
|
|
||||||
hasMore: boolean;
|
|
||||||
historyOffset: number;
|
|
||||||
/** history 初始加载完成标志(local → network → save 跑完) —— UI 可用此显示 loading */
|
/** history 初始加载完成标志(local → network → save 跑完) —— UI 可用此显示 loading */
|
||||||
historyLoaded: boolean;
|
historyLoaded: boolean;
|
||||||
unlockHistoryPromptVisible: boolean;
|
unlockHistoryPromptVisible: boolean;
|
||||||
@@ -63,9 +60,6 @@ export function ChatProvider({ children }: ChatProviderProps) {
|
|||||||
isReplyingAI: state.context.isReplyingAI,
|
isReplyingAI: state.context.isReplyingAI,
|
||||||
upgradePromptVisible: state.context.upgradePromptVisible,
|
upgradePromptVisible: state.context.upgradePromptVisible,
|
||||||
upgradeReason: state.context.upgradeReason,
|
upgradeReason: state.context.upgradeReason,
|
||||||
isLoadingMore: state.context.isLoadingMore,
|
|
||||||
hasMore: state.context.hasMore,
|
|
||||||
historyOffset: state.context.historyOffset,
|
|
||||||
historyLoaded: state.context.historyLoaded,
|
historyLoaded: state.context.historyLoaded,
|
||||||
unlockHistoryPromptVisible: state.context.unlockHistoryPromptVisible,
|
unlockHistoryPromptVisible: state.context.unlockHistoryPromptVisible,
|
||||||
lockedHistoryCount: state.context.lockedHistoryCount,
|
lockedHistoryCount: state.context.lockedHistoryCount,
|
||||||
|
|||||||
@@ -36,7 +36,6 @@ export type ChatEvent =
|
|||||||
// 业务事件
|
// 业务事件
|
||||||
| { type: "ChatSendMessage"; content: string }
|
| { type: "ChatSendMessage"; content: string }
|
||||||
| { type: "ChatSendImage"; imageBase64: string }
|
| { type: "ChatSendImage"; imageBase64: string }
|
||||||
| { type: "ChatLoadMoreHistory" }
|
|
||||||
| {
|
| {
|
||||||
type: "ChatPromotionInjected";
|
type: "ChatPromotionInjected";
|
||||||
promotion: PendingChatPromotion;
|
promotion: PendingChatPromotion;
|
||||||
|
|||||||
@@ -1,24 +1,16 @@
|
|||||||
import { fromCallback, fromPromise } from "xstate";
|
import { fromCallback } from "xstate";
|
||||||
|
|
||||||
import { getChatRepository } from "@/data/repositories/chat_repository";
|
import { Logger } from "@/utils";
|
||||||
import { resolveChatCacheOwnerKey } from "@/data/repositories/chat_cache_identity";
|
|
||||||
import { Logger, Result } from "@/utils";
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
readLocalHistorySnapshot,
|
readLocalHistorySnapshot,
|
||||||
resolveHistoryCacheIdentity,
|
resolveHistoryCacheIdentity,
|
||||||
syncNetworkHistory,
|
syncNetworkHistory,
|
||||||
} from "./chat-history-sync";
|
} from "./chat-history-sync";
|
||||||
import {
|
|
||||||
PAGE_SIZE,
|
|
||||||
localMessagesToUi,
|
|
||||||
} from "./chat-machine.helpers";
|
|
||||||
import type { ChatEvent } from "./chat-events";
|
import type { ChatEvent } from "./chat-events";
|
||||||
|
|
||||||
const log = new Logger("StoresChatChatHistoryFlow");
|
const log = new Logger("StoresChatChatHistoryFlow");
|
||||||
|
|
||||||
type UiMessage = import("@/data/dto/chat").UiMessage;
|
|
||||||
|
|
||||||
export const loadHistoryActor = fromCallback<ChatEvent>(({ sendBack }) => {
|
export const loadHistoryActor = fromCallback<ChatEvent>(({ sendBack }) => {
|
||||||
let cancelled = false;
|
let cancelled = false;
|
||||||
|
|
||||||
@@ -50,30 +42,3 @@ export const loadHistoryActor = fromCallback<ChatEvent>(({ sendBack }) => {
|
|||||||
cancelled = true;
|
cancelled = true;
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
export const loadMoreHistoryActor = fromPromise<
|
|
||||||
{ messages: UiMessage[]; hasMore: boolean; newOffset: number },
|
|
||||||
{ offset: number }
|
|
||||||
>(async ({ input }) => {
|
|
||||||
const chatRepo = getChatRepository();
|
|
||||||
const cacheIdentityResult = await resolveChatCacheOwnerKey();
|
|
||||||
const result = await chatRepo.getHistory(PAGE_SIZE, input.offset);
|
|
||||||
if (Result.isErr(result)) {
|
|
||||||
log.error("[chat-machine] loadMoreHistoryActor failed", {
|
|
||||||
error: result.error,
|
|
||||||
});
|
|
||||||
throw result.error;
|
|
||||||
}
|
|
||||||
const page = localMessagesToUi(result.data.messages);
|
|
||||||
if (Result.isOk(cacheIdentityResult)) {
|
|
||||||
void chatRepo.prefetchMediaForMessages(
|
|
||||||
result.data.messages,
|
|
||||||
cacheIdentityResult.data,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
messages: page,
|
|
||||||
hasMore: page.length >= PAGE_SIZE,
|
|
||||||
newOffset: input.offset + page.length,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|||||||
@@ -3,15 +3,16 @@ import { resolveChatCacheOwnerKey } from "@/data/repositories/chat_cache_identit
|
|||||||
import { getChatRepository } from "@/data/repositories/chat_repository";
|
import { getChatRepository } from "@/data/repositories/chat_repository";
|
||||||
import { Logger, Result, todayString } from "@/utils";
|
import { Logger, Result, todayString } from "@/utils";
|
||||||
|
|
||||||
import { localMessagesToUi, PAGE_SIZE } from "./chat-machine.helpers";
|
import {
|
||||||
|
CHAT_HISTORY_LIMIT,
|
||||||
|
localMessagesToUi,
|
||||||
|
} from "./chat-machine.helpers";
|
||||||
|
|
||||||
const log = new Logger("StoresChatChatHistorySync");
|
const log = new Logger("StoresChatChatHistorySync");
|
||||||
|
|
||||||
export type ReadAndSyncHistoryOutput = {
|
export type ReadAndSyncHistoryOutput = {
|
||||||
/** Network-authoritative messages. Empty network history includes a UI greeting. */
|
/** Network-authoritative messages. Empty network history includes a UI greeting. */
|
||||||
messages: UiMessage[];
|
messages: UiMessage[];
|
||||||
hasMore: boolean;
|
|
||||||
newOffset: number;
|
|
||||||
/** True when network history was written back to local storage. */
|
/** True when network history was written back to local storage. */
|
||||||
localOverwritten: boolean;
|
localOverwritten: boolean;
|
||||||
localCount: number;
|
localCount: number;
|
||||||
@@ -21,8 +22,6 @@ export type ReadAndSyncHistoryOutput = {
|
|||||||
export type LocalHistorySnapshotOutput = {
|
export type LocalHistorySnapshotOutput = {
|
||||||
/** Local cached messages. Empty local history includes a UI greeting. */
|
/** Local cached messages. Empty local history includes a UI greeting. */
|
||||||
messages: UiMessage[];
|
messages: UiMessage[];
|
||||||
hasMore: boolean;
|
|
||||||
newOffset: number;
|
|
||||||
localCount: number;
|
localCount: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -69,8 +68,6 @@ export async function readLocalHistorySnapshot(
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
messages: snapshotMessages,
|
messages: snapshotMessages,
|
||||||
hasMore: localMessages.length >= PAGE_SIZE,
|
|
||||||
newOffset: snapshotMessages.length,
|
|
||||||
localCount: localMessages.length,
|
localCount: localMessages.length,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -82,7 +79,7 @@ export async function syncNetworkHistory(
|
|||||||
const chatRepo = getChatRepository();
|
const chatRepo = getChatRepository();
|
||||||
const greetingMessage = createGreetingMessage();
|
const greetingMessage = createGreetingMessage();
|
||||||
|
|
||||||
const networkResult = await chatRepo.getHistory(PAGE_SIZE, 0);
|
const networkResult = await chatRepo.getHistory(CHAT_HISTORY_LIMIT, 0);
|
||||||
if (Result.isErr(networkResult)) {
|
if (Result.isErr(networkResult)) {
|
||||||
log.error("[chat-machine] loadHistory NETWORK FAILED", {
|
log.error("[chat-machine] loadHistory NETWORK FAILED", {
|
||||||
error: networkResult.error,
|
error: networkResult.error,
|
||||||
@@ -120,8 +117,6 @@ export async function syncNetworkHistory(
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
messages: finalMessages,
|
messages: finalMessages,
|
||||||
hasMore: finalMessages.length >= PAGE_SIZE,
|
|
||||||
newOffset: finalMessages.length,
|
|
||||||
localOverwritten,
|
localOverwritten,
|
||||||
localCount,
|
localCount,
|
||||||
networkCount: networkUi.length,
|
networkCount: networkUi.length,
|
||||||
@@ -145,8 +140,6 @@ export async function readAndSyncHistory(): Promise<ReadAndSyncHistoryOutput> {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
messages: localSnapshot.messages,
|
messages: localSnapshot.messages,
|
||||||
hasMore: localSnapshot.hasMore,
|
|
||||||
newOffset: localSnapshot.newOffset,
|
|
||||||
localOverwritten: false,
|
localOverwritten: false,
|
||||||
localCount: localSnapshot.localCount,
|
localCount: localSnapshot.localCount,
|
||||||
networkCount: 0,
|
networkCount: 0,
|
||||||
|
|||||||
@@ -6,10 +6,7 @@
|
|||||||
* - chat-send-flow
|
* - chat-send-flow
|
||||||
* - chat-unlock-flow
|
* - chat-unlock-flow
|
||||||
*/
|
*/
|
||||||
export {
|
export { loadHistoryActor } from "./chat-history-flow";
|
||||||
loadHistoryActor,
|
|
||||||
loadMoreHistoryActor,
|
|
||||||
} from "./chat-history-flow";
|
|
||||||
export {
|
export {
|
||||||
httpMessageQueueActor,
|
httpMessageQueueActor,
|
||||||
sendMessageHttpActor,
|
sendMessageHttpActor,
|
||||||
|
|||||||
@@ -2,8 +2,8 @@ import type { UiMessage } from "@/data/dto/chat";
|
|||||||
|
|
||||||
import type { ChatState } from "./chat-state";
|
import type { ChatState } from "./chat-state";
|
||||||
|
|
||||||
// History pagination size used by the history actors.
|
// The initial history request remains bounded even though pagination is disabled.
|
||||||
export const PAGE_SIZE = 50;
|
export const CHAT_HISTORY_LIMIT = 50;
|
||||||
|
|
||||||
export * from "./chat-message-mappers";
|
export * from "./chat-message-mappers";
|
||||||
export * from "./chat-promotion";
|
export * from "./chat-promotion";
|
||||||
@@ -13,17 +13,10 @@ export * from "./chat-unlock-helpers";
|
|||||||
export function applyHistoryLoadedOutput(
|
export function applyHistoryLoadedOutput(
|
||||||
output: {
|
output: {
|
||||||
messages: UiMessage[];
|
messages: UiMessage[];
|
||||||
hasMore: boolean;
|
|
||||||
newOffset: number;
|
|
||||||
},
|
},
|
||||||
): Pick<
|
): Pick<ChatState, "messages" | "historyLoaded"> {
|
||||||
ChatState,
|
|
||||||
"messages" | "hasMore" | "historyOffset" | "historyLoaded"
|
|
||||||
> {
|
|
||||||
return {
|
return {
|
||||||
messages: output.messages,
|
messages: output.messages,
|
||||||
hasMore: output.hasMore,
|
|
||||||
historyOffset: output.newOffset,
|
|
||||||
historyLoaded: true,
|
historyLoaded: true,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -32,18 +25,13 @@ export function applyNetworkHistoryLoadedOutput(
|
|||||||
context: ChatState,
|
context: ChatState,
|
||||||
output: {
|
output: {
|
||||||
messages: UiMessage[];
|
messages: UiMessage[];
|
||||||
hasMore: boolean;
|
localCount: number;
|
||||||
newOffset: number;
|
|
||||||
},
|
},
|
||||||
): Pick<
|
): Pick<ChatState, "messages" | "historyLoaded"> {
|
||||||
ChatState,
|
const localSnapshotSize = output.localCount === 0 ? 1 : output.localCount;
|
||||||
"messages" | "hasMore" | "historyOffset" | "historyLoaded"
|
const optimisticTail = context.messages.slice(localSnapshotSize);
|
||||||
> {
|
|
||||||
const optimisticTail = context.messages.slice(context.historyOffset);
|
|
||||||
return {
|
return {
|
||||||
messages: [...output.messages, ...optimisticTail],
|
messages: [...output.messages, ...optimisticTail],
|
||||||
hasMore: output.hasMore,
|
|
||||||
historyOffset: output.newOffset,
|
|
||||||
historyLoaded: true,
|
historyLoaded: true,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,10 +39,7 @@ import {
|
|||||||
shouldPromptUnlockHistory,
|
shouldPromptUnlockHistory,
|
||||||
createChatPromotionState,
|
createChatPromotionState,
|
||||||
} from "./chat-machine.helpers";
|
} from "./chat-machine.helpers";
|
||||||
import {
|
import { loadHistoryActor } from "./chat-history-flow";
|
||||||
loadHistoryActor,
|
|
||||||
loadMoreHistoryActor,
|
|
||||||
} from "./chat-history-flow";
|
|
||||||
import {
|
import {
|
||||||
appendGuestUserImageAction,
|
appendGuestUserImageAction,
|
||||||
appendUserImageAction,
|
appendUserImageAction,
|
||||||
@@ -87,7 +84,6 @@ export const chatMachine = setup({
|
|||||||
},
|
},
|
||||||
actors: {
|
actors: {
|
||||||
loadHistory: loadHistoryActor,
|
loadHistory: loadHistoryActor,
|
||||||
loadMoreHistory: loadMoreHistoryActor,
|
|
||||||
sendMessageHttp: sendMessageHttpActor,
|
sendMessageHttp: sendMessageHttpActor,
|
||||||
httpMessageQueue: httpMessageQueueActor,
|
httpMessageQueue: httpMessageQueueActor,
|
||||||
unlockHistory: unlockHistoryActor,
|
unlockHistory: unlockHistoryActor,
|
||||||
@@ -154,7 +150,6 @@ export const chatMachine = setup({
|
|||||||
if (event.type !== "ChatNetworkHistoryLoaded") return {};
|
if (event.type !== "ChatNetworkHistoryLoaded") return {};
|
||||||
return {
|
return {
|
||||||
...applyNetworkHistoryLoadedOutput(context, event.output),
|
...applyNetworkHistoryLoadedOutput(context, event.output),
|
||||||
isLoadingMore: false,
|
|
||||||
paymentUnlockPending: false,
|
paymentUnlockPending: false,
|
||||||
};
|
};
|
||||||
}),
|
}),
|
||||||
@@ -167,7 +162,6 @@ export const chatMachine = setup({
|
|||||||
);
|
);
|
||||||
return {
|
return {
|
||||||
...nextHistory,
|
...nextHistory,
|
||||||
isLoadingMore: false,
|
|
||||||
paymentUnlockPending: false,
|
paymentUnlockPending: false,
|
||||||
unlockHistoryPromptVisible: true,
|
unlockHistoryPromptVisible: true,
|
||||||
lockedHistoryCount: countLockedHistoryMessages(nextHistory.messages),
|
lockedHistoryCount: countLockedHistoryMessages(nextHistory.messages),
|
||||||
@@ -175,10 +169,7 @@ export const chatMachine = setup({
|
|||||||
};
|
};
|
||||||
}),
|
}),
|
||||||
|
|
||||||
markHistoryLoadFailed: assign({
|
markHistoryLoadFailed: assign({ historyLoaded: true }),
|
||||||
isLoadingMore: false,
|
|
||||||
historyLoaded: true,
|
|
||||||
}),
|
|
||||||
},
|
},
|
||||||
}).createMachine({
|
}).createMachine({
|
||||||
id: "chat",
|
id: "chat",
|
||||||
@@ -404,9 +395,6 @@ export const chatMachine = setup({
|
|||||||
ChatSendImage: {
|
ChatSendImage: {
|
||||||
actions: "appendUserImage",
|
actions: "appendUserImage",
|
||||||
},
|
},
|
||||||
ChatLoadMoreHistory: {
|
|
||||||
target: "loadingMore",
|
|
||||||
},
|
|
||||||
ChatUnlockMessageRequested: {
|
ChatUnlockMessageRequested: {
|
||||||
guard: ({ event }) => event.messageId.trim().length > 0,
|
guard: ({ event }) => event.messageId.trim().length > 0,
|
||||||
target: "unlockingMessage",
|
target: "unlockingMessage",
|
||||||
@@ -432,25 +420,6 @@ export const chatMachine = setup({
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
loadingMore: {
|
|
||||||
invoke: {
|
|
||||||
src: "loadMoreHistory",
|
|
||||||
input: ({ context }) => ({ offset: context.historyOffset }),
|
|
||||||
onDone: {
|
|
||||||
target: "ready",
|
|
||||||
actions: assign(({ context, event }) => ({
|
|
||||||
messages: [...event.output.messages, ...context.messages],
|
|
||||||
isLoadingMore: false,
|
|
||||||
hasMore: event.output.hasMore,
|
|
||||||
historyOffset: event.output.newOffset,
|
|
||||||
})),
|
|
||||||
},
|
|
||||||
onError: {
|
|
||||||
target: "ready",
|
|
||||||
actions: assign({ isLoadingMore: false }),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
unlockingHistory: {
|
unlockingHistory: {
|
||||||
invoke: {
|
invoke: {
|
||||||
id: "unlockHistory",
|
id: "unlockHistory",
|
||||||
@@ -466,8 +435,6 @@ export const chatMachine = setup({
|
|||||||
event.output.reason === "insufficient_balance";
|
event.output.reason === "insufficient_balance";
|
||||||
return {
|
return {
|
||||||
messages: event.output.messages,
|
messages: event.output.messages,
|
||||||
hasMore: event.output.hasMore,
|
|
||||||
historyOffset: event.output.newOffset,
|
|
||||||
historyLoaded: true,
|
historyLoaded: true,
|
||||||
paymentUnlockPending: false,
|
paymentUnlockPending: false,
|
||||||
unlockHistoryPromptVisible: insufficientBalance,
|
unlockHistoryPromptVisible: insufficientBalance,
|
||||||
|
|||||||
@@ -31,13 +31,7 @@ export interface ChatState {
|
|||||||
creditsCharged: number;
|
creditsCharged: number;
|
||||||
requiredCredits: number;
|
requiredCredits: number;
|
||||||
shortfallCredits: number;
|
shortfallCredits: number;
|
||||||
isLoadingMore: boolean;
|
/** history 首屏可展示标志(本地快照加载完成即可进入 ready)。 */
|
||||||
hasMore: boolean;
|
|
||||||
historyOffset: number;
|
|
||||||
/** history 首屏可展示标志(本地快照加载完成即可进入 ready)
|
|
||||||
* - 网络历史加载完成后会再次刷新消息列表
|
|
||||||
* - 不被 `loadMoreHistoryActor` 设置(翻页是另一码事)
|
|
||||||
*/
|
|
||||||
historyLoaded: boolean;
|
historyLoaded: boolean;
|
||||||
paymentUnlockPending: boolean;
|
paymentUnlockPending: boolean;
|
||||||
unlockHistoryPromptVisible: boolean;
|
unlockHistoryPromptVisible: boolean;
|
||||||
@@ -66,9 +60,6 @@ export const initialState: ChatState = {
|
|||||||
creditsCharged: 0,
|
creditsCharged: 0,
|
||||||
requiredCredits: 0,
|
requiredCredits: 0,
|
||||||
shortfallCredits: 0,
|
shortfallCredits: 0,
|
||||||
isLoadingMore: false,
|
|
||||||
hasMore: true,
|
|
||||||
historyOffset: 0,
|
|
||||||
historyLoaded: false,
|
historyLoaded: false,
|
||||||
paymentUnlockPending: false,
|
paymentUnlockPending: false,
|
||||||
unlockHistoryPromptVisible: false,
|
unlockHistoryPromptVisible: false,
|
||||||
|
|||||||
@@ -27,8 +27,6 @@ export const unlockHistoryActor = fromPromise<{
|
|||||||
reason: string;
|
reason: string;
|
||||||
shortfallCredits: number;
|
shortfallCredits: number;
|
||||||
messages: UiMessage[];
|
messages: UiMessage[];
|
||||||
hasMore: boolean;
|
|
||||||
newOffset: number;
|
|
||||||
}>(async () => {
|
}>(async () => {
|
||||||
const chatRepo = getChatRepository();
|
const chatRepo = getChatRepository();
|
||||||
const unlockResult = await chatRepo.unlockHistory();
|
const unlockResult = await chatRepo.unlockHistory();
|
||||||
@@ -45,8 +43,6 @@ export const unlockHistoryActor = fromPromise<{
|
|||||||
reason: unlockResult.data.reason,
|
reason: unlockResult.data.reason,
|
||||||
shortfallCredits: unlockResult.data.shortfallCredits,
|
shortfallCredits: unlockResult.data.shortfallCredits,
|
||||||
messages: history.messages,
|
messages: history.messages,
|
||||||
hasMore: history.hasMore,
|
|
||||||
newOffset: history.newOffset,
|
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user