Files
cozsweet-frontend-nextjs/src/stores/chat/machine/session-flow.ts
T

262 lines
6.8 KiB
TypeScript

import { createChatPromotionState } from "../helper/promotion";
import { shouldPromptUnlockHistory } from "../helper/unlock";
import { createInitialChatState } from "../chat-state";
import {
guestInitializingState,
historyPaginationTransitions,
userInitializingState,
} from "./history-flow";
import {
guestReadyState,
guestSendingState,
userSendingViaHttpState,
} from "./send-flow";
import {
unlockingHistoryState,
unlockingMessageState,
unlockMachineSetup,
} from "./unlock-flow";
const startGuestSessionAction = unlockMachineSetup.assign(
({ context }) => ({
...createInitialChatState(
context.characterId,
context.emptyChatGreeting,
),
promotion: context.promotion,
}),
);
const startUserSessionAction = unlockMachineSetup.assign(
({ context }) => ({
...createInitialChatState(
context.characterId,
context.emptyChatGreeting,
),
promotion: context.promotion,
}),
);
const clearChatSessionAction = unlockMachineSetup.assign(({ context }) => ({
...createInitialChatState(context.characterId, context.emptyChatGreeting),
}));
const injectPromotionAction = unlockMachineSetup.assign(({ event }) => {
if (event.type !== "ChatPromotionInjected") return {};
return {
promotion: createChatPromotionState(
event.promotion,
event.messageId,
),
};
});
const clearPromotionAction = unlockMachineSetup.assign({ promotion: null });
export const chatMachineSetup = unlockMachineSetup.extend({
actions: {
startGuestSession: startGuestSessionAction,
startUserSession: startUserSessionAction,
clearChatSession: clearChatSessionAction,
injectPromotion: injectPromotionAction,
clearPromotion: clearPromotionAction,
},
});
const idleState = chatMachineSetup.createStateConfig({
on: {
ChatGuestLogin: {
target: "#chat.guestSession",
actions: "startGuestSession",
},
ChatUserLogin: {
target: "#chat.userSession",
actions: "startUserSession",
},
},
});
const guestSessionState = chatMachineSetup.createStateConfig({
invoke: [
{
id: "messageQueue",
src: "httpMessageQueue",
input: ({ context }) => ({ characterId: context.characterId }),
},
{
id: "loadHistory",
src: "loadHistory",
input: ({ context }) => ({
characterId: context.characterId,
emptyChatGreeting: context.emptyChatGreeting,
}),
},
{
id: "loadMoreHistory",
src: "loadMoreHistory",
input: ({ context }) => ({
characterId: context.characterId,
emptyChatGreeting: context.emptyChatGreeting,
}),
},
],
on: {
...historyPaginationTransitions,
ChatUserLogin: {
target: "#chat.userSession",
actions: "startUserSession",
},
ChatNetworkHistoryLoaded: {
actions: "applyNetworkHistoryLoaded",
},
ChatHistoryLoadFailed: {
actions: "markHistoryLoadFailed",
},
ChatQueuedSendStarted: {
actions: "markQueuedSendStarted",
},
ChatQueuedHttpDone: {
actions: "applyQueuedHttpOutput",
},
ChatQueuedSendError: {
actions: "appendQueuedSendErrorMessage",
},
},
initial: "initializing",
states: {
initializing: guestInitializingState,
ready: guestReadyState,
sending: guestSendingState,
},
});
const userReadyState = chatMachineSetup.createStateConfig({
on: {
ChatNetworkHistoryLoaded: [
{
guard: ({ context, event }) =>
event.type === "ChatNetworkHistoryLoaded" &&
context.paymentUnlockPending &&
shouldPromptUnlockHistory(event.output.messages),
actions: "showUnlockHistoryPromptFromNetwork",
},
{
guard: ({ context }) => context.paymentUnlockPending,
actions: "applyNetworkHistoryLoadedAndClearPayment",
},
{
actions: "applyNetworkHistoryLoaded",
},
],
ChatSendMessage: {
guard: ({ context, event }) =>
context.canSendMessage && event.content.trim().length > 0,
actions: ["appendUserMessage", "enqueueMessage"],
},
ChatSendImage: {
actions: "appendUserImage",
},
ChatUnlockMessageRequested: {
guard: ({ event }) => event.messageId.trim().length > 0,
target: "unlockingMessage",
actions: "markUnlockMessageStarted",
},
},
});
const userSessionState = chatMachineSetup.createStateConfig({
invoke: [
{
id: "messageQueue",
src: "httpMessageQueue",
input: ({ context }) => ({ characterId: context.characterId }),
},
{
id: "loadHistory",
src: "loadHistory",
input: ({ context }) => ({
characterId: context.characterId,
emptyChatGreeting: context.emptyChatGreeting,
}),
},
{
id: "loadMoreHistory",
src: "loadMoreHistory",
input: ({ context }) => ({
characterId: context.characterId,
emptyChatGreeting: context.emptyChatGreeting,
}),
},
],
on: {
...historyPaginationTransitions,
ChatGuestLogin: {
target: "#chat.guestSession",
actions: "startGuestSession",
},
ChatLogout: {
target: "#chat.idle",
actions: "clearChatSession",
},
ChatHistoryLoadFailed: {
actions: "markHistoryLoadFailed",
},
ChatQueuedSendStarted: {
actions: "markQueuedSendStarted",
},
ChatQueuedHttpDone: {
actions: "applyQueuedHttpOutput",
},
ChatQueuedSendError: {
actions: "appendQueuedSendErrorMessage",
},
ChatPaymentSucceeded: [
{
guard: ({ context }) =>
context.historyLoaded &&
shouldPromptUnlockHistory(context.messages),
actions: ["clearUpgradePrompt", "showUnlockHistoryPrompt"],
},
{
guard: ({ context }) => !context.historyLoaded,
actions: ["clearUpgradePrompt", "markPaymentUnlockPending"],
},
{
guard: ({ context }) => context.historyLoaded,
actions: ["clearUpgradePrompt", "dismissUnlockHistoryPrompt"],
},
],
ChatUnlockHistoryConfirmed: {
target: ".unlockingHistory",
actions: "markUnlockHistoryStarted",
},
ChatUnlockHistoryDismissed: {
actions: "dismissUnlockHistoryPrompt",
},
ChatUnlockPaywallNavigationConsumed: {
actions: "clearUnlockPaywallRequest",
},
},
initial: "initializing",
states: {
initializing: userInitializingState,
ready: userReadyState,
sendingViaHttp: userSendingViaHttpState,
unlockingHistory: unlockingHistoryState,
unlockingMessage: unlockingMessageState,
},
});
export const chatRootStateConfig = chatMachineSetup.createStateConfig({
initial: "idle",
on: {
ChatPromotionInjected: { actions: "injectPromotion" },
ChatPromotionCleared: { actions: "clearPromotion" },
},
states: {
idle: idleState,
guestSession: guestSessionState,
userSession: userSessionState,
},
});