Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01N4f2nya58RoRu4yEmJgRGE
42 lines
1.5 KiB
TypeScript
42 lines
1.5 KiB
TypeScript
"use client";
|
|
|
|
import { useEffect, type Dispatch, type SetStateAction } from "react";
|
|
|
|
import type { ChatMessageFeedback } from "@/components/chat-message-actions";
|
|
import { loadReplyRatings } from "@/lib/reply-ratings";
|
|
|
|
type SessionLike = Readonly<{
|
|
id: string;
|
|
messagesHydrated?: boolean;
|
|
messages: readonly Readonly<{ role: string; text: string }>[];
|
|
}>;
|
|
|
|
/**
|
|
* Brings the stored 回复评价 of the open conversation into the page's
|
|
* feedback map once its messages are loaded (compliance round 2026-09-30).
|
|
* Owns no state; ratings the user sets in this visit win over stored ones.
|
|
*/
|
|
export function useReplyRatingsSync(
|
|
session: SessionLike | undefined,
|
|
setMessageFeedback: Dispatch<SetStateAction<Record<string, ChatMessageFeedback>>>,
|
|
): void {
|
|
const sessionId = session?.id ?? "";
|
|
const ready = Boolean(session?.messagesHydrated);
|
|
const count = session?.messages.length ?? 0;
|
|
const texts = session?.messages.map((message) => (message.role === "assistant" ? message.text : "")) ?? [];
|
|
const textKey = texts.join("\u0000");
|
|
useEffect(() => {
|
|
if (!sessionId || !ready || count === 0) return;
|
|
let cancelled = false;
|
|
void loadReplyRatings(sessionId, textKey.split("\u0000"))
|
|
.then((stored) => {
|
|
if (cancelled || Object.keys(stored).length === 0) return;
|
|
setMessageFeedback((current) => ({ ...stored, ...current }));
|
|
})
|
|
.catch(() => undefined);
|
|
return () => {
|
|
cancelled = true;
|
|
};
|
|
}, [sessionId, ready, count, textKey, setMessageFeedback]);
|
|
}
|