feat(chat): add promotional external entry flow

This commit is contained in:
2026-07-13 12:43:18 +08:00
parent e5ee9940ca
commit 3752b3b729
44 changed files with 1623 additions and 190 deletions
@@ -26,6 +26,7 @@ export class ChatLocalMessageStore {
...message.toJson(),
content: normalizeUnlockedContent(patch.content, message.content),
audioUrl: normalizeUnlockedAudioUrl(patch.audioUrl, message.audioUrl),
image: patch.image ?? message.image,
lockDetail: patch.lockDetail ?? {
...message.lockDetail,
locked: false,
@@ -132,6 +133,8 @@ function shouldMarkMessageUnlocked(
if (message.lockDetail.locked !== true) return false;
return (
Boolean(message.image.url) ||
message.lockDetail.reason === "image_paywall" ||
message.lockDetail.reason === "image" ||
message.lockDetail.reason === "private_message" ||
message.lockDetail.reason === "voice_message"
);
@@ -9,6 +9,7 @@ import {
UnlockPrivateResponse,
} from "@/data/dto/chat";
import type { ChatApi } from "@/data/services/api";
import type { UnlockPrivateMessageInput } from "@/data/repositories/interfaces";
import { Result } from "@/utils";
export class ChatRemoteDataSource {
@@ -36,10 +37,10 @@ export class ChatRemoteDataSource {
}
async unlockPrivateMessage(
messageId: string,
input: UnlockPrivateMessageInput,
): Promise<Result<UnlockPrivateResponse>> {
return Result.wrap(() =>
this.api.unlockPrivateMessage(UnlockPrivateRequest.from({ messageId })),
this.api.unlockPrivateMessage(UnlockPrivateRequest.from(input)),
);
}
+3 -2
View File
@@ -17,6 +17,7 @@ import type {
CacheRemoteChatMediaInput,
ChatMediaLookupInput,
IChatRepository,
UnlockPrivateMessageInput,
UnlockedPrivateMessageLocalPatch,
} from "@/data/repositories/interfaces";
import type { Result } from "@/utils";
@@ -53,9 +54,9 @@ export class ChatRepository implements IChatRepository {
/** 解锁单条历史付费 / 私密消息。 */
async unlockPrivateMessage(
messageId: string,
input: UnlockPrivateMessageInput,
): Promise<Result<UnlockPrivateResponse>> {
return this.remote.unlockPrivateMessage(messageId);
return this.remote.unlockPrivateMessage(input);
}
/** 一键解锁历史锁定消息。 */
@@ -21,6 +21,7 @@ import type {
UnlockPrivateResponse,
} from "@/data/dto/chat";
import type { ChatLockDetailData } from "@/data/schemas/chat";
import type { ChatImageData, ChatLockType } from "@/data/schemas/chat";
import type { LocalChatMediaRow } from "@/data/storage/chat";
export interface ChatMediaLookupInput {
@@ -35,9 +36,16 @@ export interface CacheRemoteChatMediaInput extends ChatMediaLookupInput {
export interface UnlockedPrivateMessageLocalPatch {
lockDetail?: ChatLockDetailData;
audioUrl?: string | null;
image?: ChatImageData;
content?: string;
}
export interface UnlockPrivateMessageInput {
messageId?: string;
lockType?: ChatLockType;
clientLockId?: string;
}
export interface IChatRepository {
/** 发送一条消息。 */
sendMessage(
@@ -49,7 +57,9 @@ export interface IChatRepository {
getHistory(limit?: number, offset?: number): Promise<Result<ChatHistoryResponse>>;
/** 解锁单条历史付费 / 私密消息。 */
unlockPrivateMessage(messageId: string): Promise<Result<UnlockPrivateResponse>>;
unlockPrivateMessage(
input: UnlockPrivateMessageInput,
): Promise<Result<UnlockPrivateResponse>>;
/** 一键解锁历史锁定消息。 */
unlockHistory(): Promise<Result<UnlockHistoryResponse>>;