Files
cozsweet-frontend-nextjs/src/stores/chat/helper/promotion.ts
T

69 lines
1.8 KiB
TypeScript

import type { UiMessage } from "@/data/dto/chat";
import type { PendingChatPromotion } from "@/data/storage/navigation";
import { todayString } from "@/utils/date";
import {
applySingleUnlockOutput,
type UnlockMessageOutput,
} from "./unlock";
const PROMOTION_COPY = {
voice: "I left a voice message for you. Unlock it to listen.",
image: "I sent you a private photo. Unlock it to view.",
private: "I have something private to tell you. Unlock it to read.",
} as const;
export interface ChatPromotionState {
session: PendingChatPromotion;
message: UiMessage;
}
export function createChatPromotionState(
session: PendingChatPromotion,
messageId?: string,
): ChatPromotionState {
const isImage = session.promotionType === "image";
const isPrivate = session.promotionType === "private";
return {
session,
message: {
id: messageId || `promotion:${session.clientLockId}`,
content: "",
isFromAI: true,
date: todayString(),
locked: true,
lockReason: session.lockType,
imagePaywalled: isImage ? true : undefined,
lockedPrivate: isPrivate ? true : undefined,
privateMessageHint: PROMOTION_COPY[session.promotionType],
},
};
}
export function appendPromotionMessage(
messages: readonly UiMessage[],
promotion: ChatPromotionState | null,
): UiMessage[] {
if (!promotion) return [...messages];
return [
...messages.filter((message) => message.id !== promotion.message.id),
promotion.message,
];
}
export function applyPromotionUnlockOutput(
promotion: ChatPromotionState | null,
output: UnlockMessageOutput,
): ChatPromotionState | null {
if (!promotion || promotion.message.id !== output.displayMessageId) {
return promotion;
}
return {
...promotion,
message:
applySingleUnlockOutput([promotion.message], output)[0] ??
promotion.message,
};
}