fix: enhance chat scroll manager to track first and last message IDs
This commit is contained in:
@@ -106,6 +106,8 @@ export const useChatScrollManager = ({
|
|||||||
const lastScrolledAnchorIdRef = React.useRef<string | null>(null);
|
const lastScrolledAnchorIdRef = React.useRef<string | null>(null);
|
||||||
const lastSessionIdRef = React.useRef<string | null>(null);
|
const lastSessionIdRef = React.useRef<string | null>(null);
|
||||||
const lastMessageCountRef = React.useRef<number>(sessionMessages.length);
|
const lastMessageCountRef = React.useRef<number>(sessionMessages.length);
|
||||||
|
const lastFirstMessageIdRef = React.useRef<string | null>(sessionMessages.length > 0 ? getMessageId(sessionMessages[0]) : null);
|
||||||
|
const lastLastMessageIdRef = React.useRef<string | null>(sessionMessages.length > 0 ? getMessageId(sessionMessages[sessionMessages.length - 1]) : null);
|
||||||
const spacerHeightRef = React.useRef(0);
|
const spacerHeightRef = React.useRef(0);
|
||||||
|
|
||||||
const viewportHeightRef = React.useRef<number>(0);
|
const viewportHeightRef = React.useRef<number>(0);
|
||||||
@@ -175,7 +177,6 @@ export const useChatScrollManager = ({
|
|||||||
const container = scrollRef.current;
|
const container = scrollRef.current;
|
||||||
|
|
||||||
if (!container || !anchorIdRef.current) {
|
if (!container || !anchorIdRef.current) {
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -246,7 +247,6 @@ export const useChatScrollManager = ({
|
|||||||
}, [scrollEngine]);
|
}, [scrollEngine]);
|
||||||
|
|
||||||
const scrollToNewAnchor = React.useCallback((messageId: string) => {
|
const scrollToNewAnchor = React.useCallback((messageId: string) => {
|
||||||
|
|
||||||
if (lastScrolledAnchorIdRef.current === messageId) {
|
if (lastScrolledAnchorIdRef.current === messageId) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -366,6 +366,8 @@ export const useChatScrollManager = ({
|
|||||||
lastSessionIdRef.current = currentSessionId;
|
lastSessionIdRef.current = currentSessionId;
|
||||||
MessageFreshnessDetector.getInstance().recordSessionStart(currentSessionId);
|
MessageFreshnessDetector.getInstance().recordSessionStart(currentSessionId);
|
||||||
lastMessageCountRef.current = sessionMessages.length;
|
lastMessageCountRef.current = sessionMessages.length;
|
||||||
|
lastFirstMessageIdRef.current = sessionMessages.length > 0 ? getMessageId(sessionMessages[0]) : null;
|
||||||
|
lastLastMessageIdRef.current = sessionMessages.length > 0 ? getMessageId(sessionMessages[sessionMessages.length - 1]) : null;
|
||||||
lastScrolledAnchorIdRef.current = null;
|
lastScrolledAnchorIdRef.current = null;
|
||||||
|
|
||||||
anchorIdRef.current = null;
|
anchorIdRef.current = null;
|
||||||
@@ -381,6 +383,8 @@ export const useChatScrollManager = ({
|
|||||||
|
|
||||||
if (isSyncing) {
|
if (isSyncing) {
|
||||||
lastMessageCountRef.current = sessionMessages.length;
|
lastMessageCountRef.current = sessionMessages.length;
|
||||||
|
lastFirstMessageIdRef.current = sessionMessages.length > 0 ? getMessageId(sessionMessages[0]) : null;
|
||||||
|
lastLastMessageIdRef.current = sessionMessages.length > 0 ? getMessageId(sessionMessages[sessionMessages.length - 1]) : null;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -392,14 +396,31 @@ export const useChatScrollManager = ({
|
|||||||
const nextCount = sessionMessages.length;
|
const nextCount = sessionMessages.length;
|
||||||
|
|
||||||
if (nextCount > previousCount && previousCount > 0) {
|
if (nextCount > previousCount && previousCount > 0) {
|
||||||
|
const addedCount = nextCount - previousCount;
|
||||||
|
|
||||||
const previousLastId = getMessageId(sessionMessages[previousCount - 1]);
|
const previousFirstId = lastFirstMessageIdRef.current;
|
||||||
|
const newFirstId = getMessageId(sessionMessages[0]);
|
||||||
|
const newLastId = getMessageId(sessionMessages[nextCount - 1]);
|
||||||
|
const previousLastId = lastLastMessageIdRef.current;
|
||||||
|
|
||||||
const wasAppended = previousLastId !== null &&
|
const firstIdChanged = previousFirstId !== null && newFirstId !== previousFirstId;
|
||||||
getMessageId(sessionMessages[Math.min(previousCount - 1, nextCount - 1)]) === previousLastId;
|
const lastIdChanged = previousLastId !== null && newLastId !== previousLastId;
|
||||||
|
|
||||||
|
const wasPrepended = firstIdChanged && !lastIdChanged;
|
||||||
|
const wasAppended = lastIdChanged && !firstIdChanged;
|
||||||
|
|
||||||
|
if (wasPrepended) {
|
||||||
|
anchorIdRef.current = null;
|
||||||
|
hasAnchoredOnceRef.current = false;
|
||||||
|
setAnchorId(null);
|
||||||
|
updateSpacerHeight(0);
|
||||||
|
lastMessageCountRef.current = nextCount;
|
||||||
|
lastFirstMessageIdRef.current = newFirstId;
|
||||||
|
lastLastMessageIdRef.current = newLastId;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (wasAppended) {
|
if (wasAppended) {
|
||||||
|
|
||||||
const appendedMessages = sessionMessages.slice(previousCount, nextCount);
|
const appendedMessages = sessionMessages.slice(previousCount, nextCount);
|
||||||
const newUserMessage = appendedMessages.find(isUserMessage);
|
const newUserMessage = appendedMessages.find(isUserMessage);
|
||||||
|
|
||||||
@@ -411,16 +432,14 @@ export const useChatScrollManager = ({
|
|||||||
scrollToNewAnchor(newAnchorId);
|
scrollToNewAnchor(newAnchorId);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
refreshSpacer();
|
refreshSpacer();
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
|
|
||||||
refreshSpacer();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
lastMessageCountRef.current = nextCount;
|
lastMessageCountRef.current = nextCount;
|
||||||
|
lastFirstMessageIdRef.current = sessionMessages.length > 0 ? getMessageId(sessionMessages[0]) : null;
|
||||||
|
lastLastMessageIdRef.current = sessionMessages.length > 0 ? getMessageId(sessionMessages[sessionMessages.length - 1]) : null;
|
||||||
}, [currentSessionId, isSyncing, refreshSpacer, scrollToNewAnchor, sessionMessages]);
|
}, [currentSessionId, isSyncing, refreshSpacer, scrollToNewAnchor, sessionMessages]);
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
|
|||||||
Reference in New Issue
Block a user