102 lines
2.9 KiB
TypeScript
102 lines
2.9 KiB
TypeScript
import type {
|
|
ChatLockType,
|
|
UnlockPrivateResponse,
|
|
} from "@/data/schemas/chat";
|
|
import type { UiMessage } from "@/stores/chat/ui-message";
|
|
|
|
export interface UnlockMessageRequest {
|
|
displayMessageId: string;
|
|
messageId?: string;
|
|
lockType?: ChatLockType;
|
|
clientLockId?: string;
|
|
}
|
|
|
|
export interface UnlockMessageOutput {
|
|
displayMessageId: string;
|
|
request: UnlockMessageRequest;
|
|
response: UnlockPrivateResponse;
|
|
}
|
|
|
|
export function countLockedHistoryMessages(messages: readonly UiMessage[]): number {
|
|
return messages.filter(isUnlockableLockedMessage).length;
|
|
}
|
|
|
|
export function applySingleUnlockOutput(
|
|
messages: readonly UiMessage[],
|
|
output: UnlockMessageOutput,
|
|
): UiMessage[] {
|
|
return messages.map((message) => {
|
|
if (!shouldApplySingleUnlock(message, output.displayMessageId)) {
|
|
return message;
|
|
}
|
|
|
|
const remoteId = output.response.messageId || message.remoteId;
|
|
if (!output.response.unlocked) {
|
|
return {
|
|
...message,
|
|
...(remoteId ? { remoteId } : {}),
|
|
};
|
|
}
|
|
|
|
const resolvedImageUrl =
|
|
output.response.image.url ?? message.imageUrl;
|
|
const resolvedContent =
|
|
message.lockReason === "private_message"
|
|
? output.response.content || message.content
|
|
: message.content;
|
|
|
|
return {
|
|
...message,
|
|
...(remoteId ? { remoteId } : {}),
|
|
content: resolvedContent,
|
|
audioUrl: getUnlockedAudioUrl(message, output.response),
|
|
imageUrl: resolvedImageUrl,
|
|
locked: false,
|
|
lockReason: null,
|
|
imagePaywalled: resolvedImageUrl ? false : undefined,
|
|
lockedPrivate: false,
|
|
privateMessageHint: null,
|
|
};
|
|
});
|
|
}
|
|
|
|
function getUnlockedAudioUrl(
|
|
message: UiMessage,
|
|
response: UnlockPrivateResponse,
|
|
): string | undefined {
|
|
if (message.lockReason !== "voice_message") return message.audioUrl;
|
|
if (response.audioUrl.length === 0) return message.audioUrl;
|
|
return response.audioUrl;
|
|
}
|
|
|
|
function shouldApplySingleUnlock(
|
|
message: UiMessage,
|
|
displayMessageId: string,
|
|
): boolean {
|
|
if (message.displayId !== displayMessageId) return false;
|
|
if (!message.isFromAI) return false;
|
|
if (message.locked !== true) return false;
|
|
return (
|
|
message.imagePaywalled === true ||
|
|
message.lockReason === "image_paywall" ||
|
|
message.lockReason === "image" ||
|
|
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 === "image_paywall" ||
|
|
message.lockReason === "image" ||
|
|
message.lockReason === "private_message" ||
|
|
message.lockReason === "voice_message"
|
|
);
|
|
}
|