feat(chat): render commercial actions and persist greetings
Docker Image / Build and Push Docker Image (push) Successful in 1m56s

This commit is contained in:
Codex
2026-07-23 14:52:34 +08:00
parent 79397af739
commit 02f6964484
26 changed files with 548 additions and 1 deletions
@@ -9,6 +9,7 @@
* - 用户:[占位 spacer] [Content] [Avatar]
*/
import { useUserSelector } from "@/stores/user/user-context";
import type { CommercialAction } from "@/data/schemas/chat";
import { MessageAvatar } from "./message-avatar";
import { MessageContent } from "./message-content";
@@ -27,6 +28,7 @@ export interface MessageBubbleProps {
lockReason?: string | null;
lockedPrivate?: boolean | null;
privateMessageHint?: string | null;
commercialAction?: CommercialAction | null;
isUnlockingMessage?: boolean;
onUnlockPrivateMessage?: ChatMessageAction;
onUnlockVoiceMessage?: ChatMessageAction;
@@ -34,6 +36,8 @@ export interface MessageBubbleProps {
onOpenImage?: (displayMessageId: string) => void;
onUserAvatarClick?: () => void;
onCharacterAvatarClick?: () => void;
onCommercialAction?: (action: CommercialAction) => void;
onCommercialActionDismiss?: (action: CommercialAction) => void;
}
type ChatMessageAction = (
@@ -54,6 +58,7 @@ export function MessageBubble({
lockReason,
lockedPrivate,
privateMessageHint,
commercialAction,
isUnlockingMessage,
onUnlockPrivateMessage,
onUnlockVoiceMessage,
@@ -61,6 +66,8 @@ export function MessageBubble({
onOpenImage,
onUserAvatarClick,
onCharacterAvatarClick,
onCommercialAction,
onCommercialActionDismiss,
}: MessageBubbleProps) {
const avatarUrl = useUserSelector((state) => state.context.avatarUrl);
@@ -89,11 +96,14 @@ export function MessageBubble({
lockReason={lockReason}
lockedPrivate={lockedPrivate}
privateMessageHint={privateMessageHint}
commercialAction={commercialAction}
isUnlockingMessage={isUnlockingMessage}
onUnlockPrivateMessage={onUnlockPrivateMessage}
onUnlockVoiceMessage={onUnlockVoiceMessage}
onUnlockImageMessage={onUnlockImageMessage}
onOpenImage={onOpenImage}
onCommercialAction={onCommercialAction}
onCommercialActionDismiss={onCommercialActionDismiss}
/>
<div className={styles.bubbleAvatarSpacer} aria-hidden="true" />
</div>