Files
cozsweet-frontend-nextjs/src/stores/chat/chat-unlock-helpers.ts
T

58 lines
1.7 KiB
TypeScript

import type { UiMessage, UnlockPrivateResponse } from "@/data/dto/chat";
export interface UnlockMessageOutput {
messageId: string;
response: UnlockPrivateResponse;
}
export function countLockedHistoryMessages(messages: readonly UiMessage[]): number {
return messages.filter(isUnlockableLockedMessage).length;
}
export function applySingleUnlockOutput(
messages: readonly UiMessage[],
output: UnlockMessageOutput,
): UiMessage[] {
if (!output.response.unlocked) return [...messages];
return messages.map((message) => {
if (!shouldApplySingleUnlock(message, output.messageId)) return message;
return {
...message,
locked: output.response.lockDetail.locked,
lockReason: output.response.lockDetail.reason,
imagePaywalled: message.imageUrl
? output.response.lockDetail.locked &&
output.response.lockDetail.showUpgrade
: undefined,
lockedPrivate: false,
privateMessageHint: null,
};
});
}
function shouldApplySingleUnlock(message: UiMessage, messageId: string): boolean {
if (message.id !== messageId) return false;
if (!message.isFromAI) return false;
if (message.locked !== true) return false;
return (
message.imagePaywalled === true ||
message.lockReason === "private_message" ||
message.lockReason === "voice_message"
);
}
export function shouldPromptUnlockHistory(messages: readonly UiMessage[]): boolean {
return countLockedHistoryMessages(messages) > 1;
}
function isUnlockableLockedMessage(message: UiMessage): boolean {
if (!message.isFromAI || message.locked !== true) return false;
if (message.imagePaywalled === true) return true;
return (
message.lockReason === "private_message" ||
message.lockReason === "voice_message"
);
}