fix(splash): reuse latest chat message preview

This commit is contained in:
2026-07-14 11:28:23 +08:00
parent b4904e738b
commit f9c15bd91f
13 changed files with 389 additions and 18 deletions
+6
View File
@@ -35,6 +35,7 @@ import { useChatUnlockNavigationFlow } from "./hooks/use-chat-unlock-navigation-
import { useChatGuestLogin } from "./hooks/use-chat-guest-login";
import { useChatMessageLimitBanner } from "./hooks/use-chat-message-limit-banner";
import { useChatPromotionBootstrap } from "./hooks/use-chat-promotion-bootstrap";
import { useSplashLatestMessageSync } from "./hooks/use-splash-latest-message-sync";
const chatShellStyle = {
"--chat-message-font-size": "clamp(16px, 3.333vw, 18px)",
@@ -47,6 +48,11 @@ export function ChatScreen() {
const state = useChatState();
const authState = useAuthState();
const authDispatch = useAuthDispatch();
useSplashLatestMessageSync({
historyLoaded: state.historyLoaded,
loginStatus: authState.loginStatus,
messages: state.historyMessages,
});
const isPromotionBootstrapReady = useChatPromotionBootstrap();
const visibleMessages = isPromotionBootstrapReady
? state.messages
@@ -0,0 +1,53 @@
"use client";
import { useEffect, useRef } from "react";
import type { LoginStatus } from "@/data/dto/auth";
import type { UiMessage } from "@/data/dto/chat";
import { resolveSplashLatestMessageCacheIdentity } from "@/lib/chat/splash_latest_message";
import { getLatestSplashMessagePreview } from "@/lib/chat/splash_latest_message_preview";
import { useSplashLatestMessageCache } from "@/providers/splash-latest-message-provider";
export interface UseSplashLatestMessageSyncInput {
historyLoaded: boolean;
loginStatus: LoginStatus;
messages: readonly UiMessage[];
}
export function useSplashLatestMessageSync({
historyLoaded,
loginStatus,
messages,
}: UseSplashLatestMessageSyncInput): void {
const cache = useSplashLatestMessageCache();
const hasObservedInitialSnapshotRef = useRef(false);
const identityPromiseRef = useRef<Promise<string | null> | null>(null);
useEffect(() => {
hasObservedInitialSnapshotRef.current = false;
identityPromiseRef.current = null;
}, [loginStatus]);
useEffect(() => {
if (!historyLoaded) return;
if (!hasObservedInitialSnapshotRef.current) {
hasObservedInitialSnapshotRef.current = true;
return;
}
const preview = getLatestSplashMessagePreview(messages);
let cancelled = false;
identityPromiseRef.current ??= resolveSplashLatestMessageCacheIdentity();
void identityPromiseRef.current.then((identity) => {
if (!cancelled && identity) {
cache.set(identity, preview);
}
});
return () => {
cancelled = true;
};
}, [cache, historyLoaded, messages]);
}