fix(dashboard): wire scroll-to-top pagination instead of loading all messages

- Remove fetchAllMessagesInChat/fetchAllMessages helpers
- Keep limit:50 for initial load in useChat and useQuickChat
- Add IntersectionObserver sentinel at top of ChatView message list to
  trigger loadMoreMessages() when user scrolls to the top
- Keep stale-session guards (activeSessionRef checks) from original PR
- Tests: revert assertions back to { limit: 50 }
This commit is contained in:
Josemi Liebana
2026-05-26 21:48:35 +02:00
parent 6085e91295
commit e018701fed
3 changed files with 40 additions and 58 deletions

View File

@@ -183,22 +183,6 @@ function mapChatMessageToInfo(message: ChatMessage): ChatMessageInfo {
};
}
/**
* Fetch all messages for a session, paginating through the API's 200-message cap.
* Replaces the former hardcoded `limit: 50` that silently truncated long sessions.
*/
async function fetchAllMessages(sessionId: string, projectId?: string): Promise<ChatMessageInfo[]> {
const PAGE = 200; // API hard cap (Math.min(limit, 200))
const all: ChatMessageInfo[] = [];
let offset = 0;
for (;;) {
const data = await fetchChatMessages(sessionId, { limit: PAGE, offset }, projectId);
all.push(...data.messages.map(mapChatMessageToInfo));
if (data.messages.length < PAGE) break;
offset += PAGE;
}
return all;
}
/**
* Hook for the QuickChatFAB component.
* Provides chat session management and SSE streaming for real-time AI responses.
@@ -346,8 +330,8 @@ export function useQuickChat(
isStreamingRef.current = false;
streamRef.current = null;
lastAttachedGenerationRef.current = null;
void fetchAllMessages(sessionId, projectId).then((msgs) => {
if (activeSessionRef.current?.id === sessionId) setMessages(msgs);
void fetchChatMessages(sessionId, { limit: 50 }, projectId).then((data) => {
if (activeSessionRef.current?.id === sessionId) setMessages(data.messages.map(mapChatMessageToInfo));
}).catch(() => {});
flushPendingMessage();
},
@@ -363,8 +347,8 @@ export function useQuickChat(
if (!options?.silent) {
addToast?.(errorMessage, "error");
}
void fetchAllMessages(sessionId, projectId).then((msgs) => {
if (activeSessionRef.current?.id === sessionId) setMessages(msgs);
void fetchChatMessages(sessionId, { limit: 50 }, projectId).then((data) => {
if (activeSessionRef.current?.id === sessionId) setMessages(data.messages.map(mapChatMessageToInfo));
}).catch(() => {});
flushPendingMessage();
},
@@ -444,8 +428,8 @@ export function useQuickChat(
setMessagesLoading(true);
try {
const sessionId = activeSession.id;
const msgs = await fetchAllMessages(sessionId, projectId);
if (activeSessionRef.current?.id === sessionId) setMessages(msgs);
const data = await fetchChatMessages(sessionId, { limit: 50 }, projectId);
if (activeSessionRef.current?.id === sessionId) setMessages(data.messages.map(mapChatMessageToInfo));
} catch (err) {
console.error("[useQuickChat] Failed to load messages:", err);
} finally {
@@ -489,8 +473,8 @@ export function useQuickChat(
clearInterval(interval);
// Reload messages to pick up the completed assistant message
const sessionId = activeSession.id;
const msgs = await fetchAllMessages(sessionId, projectId);
if (activeSessionRef.current?.id === sessionId) setMessages(msgs);
const data = await fetchChatMessages(sessionId, { limit: 50 }, projectId);
if (activeSessionRef.current?.id === sessionId) setMessages(data.messages.map(mapChatMessageToInfo));
setStreamingText("");
setStreamingThinking("");
setStreamingToolCalls([]);
@@ -512,8 +496,8 @@ export function useQuickChat(
setMessagesLoading(true);
try {
const sessionId = activeSession.id;
const msgs = await fetchAllMessages(sessionId, projectId);
if (activeSessionRef.current?.id === sessionId) setMessages(msgs);
const data = await fetchChatMessages(sessionId, { limit: 50 }, projectId);
if (activeSessionRef.current?.id === sessionId) setMessages(data.messages.map(mapChatMessageToInfo));
} catch (err) {
console.error("[useQuickChat] Failed to reload messages:", err);
} finally {