Files
kandev/apps/web/hooks/use-message-navigation.ts
T

40 lines
1.5 KiB
TypeScript

import { useMemo } from "react";
import { useAppStore } from "@/components/state-provider";
const EMPTY_KEY = "";
/**
* Prev/next navigation between user messages in a session, sourced directly from
* the store rather than a drilled `allMessages` array.
*
* The selector returns a value-stable key (the comma-joined ids of the session's
* user messages). During agent token streaming the user-message set is unchanged,
* so the key is referentially equal and the subscribing message does not
* re-render — which keeps `ChatMessage` memoized instead of re-running its
* markdown render on every streamed token.
*/
export function useUserMessageNavigation(sessionId: string | null, currentMessageId: string) {
const userIdsKey = useAppStore((state) => {
const messages = sessionId ? state.messages.bySession[sessionId] : undefined;
if (!messages) return EMPTY_KEY;
let key = EMPTY_KEY;
for (const message of messages) {
if (message.author_type === "user") key += `${message.id},`;
}
return key;
});
return useMemo(() => {
const ids = userIdsKey ? userIdsKey.slice(0, -1).split(",") : [];
const index = ids.indexOf(currentMessageId);
const previousId = index > 0 ? ids[index - 1] : null;
const nextId = index >= 0 && index < ids.length - 1 ? ids[index + 1] : null;
return {
hasPrevious: previousId !== null,
hasNext: nextId !== null,
previousId,
nextId,
};
}, [userIdsKey, currentMessageId]);
}