Fix session history loading (#1468)
Fix chat history pagination and scroll preservation Align session history loading with the expected scroll-up pagination UX while keeping OpenChamber-specific initial message limits for constrained runtimes. - Separate initial load sizes from older-history pagination size - Load older messages automatically when scrolling near the top - Continue fetching history until a visible older turn is available - Preserve the current viewport synchronously during prepends - Prevent history loading from fighting pinned-to-bottom follow behavior - Remove delayed scroll-to-bottom correction that caused jumpbacks - Fix the virtualizer fallback path that could render a large blank spacer - Track oldest loaded message per pagination iteration to avoid redundant fetches
This commit is contained in:
committed by
GitHub
parent
4a1ebd98da
commit
f9e9f30873
@@ -156,6 +156,7 @@ type ChatViewportProps = {
|
||||
handleMessageContentChange: (reason?: ContentChangeReason) => void;
|
||||
getAnimationHandlers: (messageId: string) => AnimationHandlers;
|
||||
handleLoadOlder: () => void;
|
||||
handleHistoryScroll: () => void;
|
||||
scrollToBottom: () => void;
|
||||
sessionQuestions: QuestionRequest[];
|
||||
sessionPermissions: PermissionRequest[];
|
||||
@@ -181,6 +182,7 @@ const ChatViewport = React.memo(({
|
||||
handleMessageContentChange,
|
||||
getAnimationHandlers,
|
||||
handleLoadOlder,
|
||||
handleHistoryScroll,
|
||||
scrollToBottom,
|
||||
sessionQuestions,
|
||||
sessionPermissions,
|
||||
@@ -217,6 +219,7 @@ const ChatViewport = React.memo(({
|
||||
hideTopShadow={isMobile && stickyUserHeader}
|
||||
tabIndex={0}
|
||||
onClick={focusScrollContainer}
|
||||
onScroll={handleHistoryScroll}
|
||||
data-scroll-shadow="true"
|
||||
data-scrollbar="chat"
|
||||
>
|
||||
@@ -280,6 +283,7 @@ const ChatViewport = React.memo(({
|
||||
&& prev.handleMessageContentChange === next.handleMessageContentChange
|
||||
&& prev.getAnimationHandlers === next.getAnimationHandlers
|
||||
&& prev.handleLoadOlder === next.handleLoadOlder
|
||||
&& prev.handleHistoryScroll === next.handleHistoryScroll
|
||||
&& prev.scrollToBottom === next.scrollToBottom
|
||||
&& prev.sessionQuestions === next.sessionQuestions
|
||||
&& prev.sessionPermissions === next.sessionPermissions
|
||||
@@ -655,7 +659,7 @@ export const ChatContainer: React.FC<ChatContainerProps> = ({ autoOpenDraft = tr
|
||||
}, [handleMessageContentChange, sessionPermissions, sessionQuestions]);
|
||||
|
||||
const handleLoadOlder = React.useCallback(() => {
|
||||
void loadEarlier();
|
||||
void loadEarlier({ userInitiated: true });
|
||||
}, [loadEarlier]);
|
||||
|
||||
const navigation = useChatTurnNavigation({
|
||||
@@ -950,6 +954,7 @@ export const ChatContainer: React.FC<ChatContainerProps> = ({ autoOpenDraft = tr
|
||||
handleMessageContentChange={handleMessageContentChange}
|
||||
getAnimationHandlers={getAnimationHandlers}
|
||||
handleLoadOlder={handleLoadOlder}
|
||||
handleHistoryScroll={timelineController.handleHistoryScroll}
|
||||
scrollToBottom={resumeToLatestInstant}
|
||||
sessionQuestions={sessionQuestions}
|
||||
sessionPermissions={sessionPermissions}
|
||||
|
||||
@@ -1005,15 +1005,9 @@ const StaticHistoryList = React.memo(({ entries, shouldVirtualize, virtualRows,
|
||||
}
|
||||
|
||||
if (virtualRows.length === 0 && entries.length > 0) {
|
||||
const fallbackStart = Math.max(0, entries.length - MESSAGE_LIST_OVERSCAN * 2);
|
||||
const fallbackEntries = entries.slice(fallbackStart);
|
||||
const fallbackHeight = fallbackEntries.reduce((total, entry) => total + estimateHistoryEntryHeight(entry), 0);
|
||||
const fallbackPaddingTop = Math.max(0, totalSize - fallbackHeight);
|
||||
|
||||
return (
|
||||
<div ref={contentRef} className="relative w-full">
|
||||
{fallbackPaddingTop > 0 ? <div aria-hidden="true" style={{ height: `${fallbackPaddingTop}px` }} /> : null}
|
||||
{fallbackEntries.map((entry) => (
|
||||
{entries.map((entry) => (
|
||||
<div
|
||||
key={entry.key}
|
||||
data-turn-entry={entry.key}
|
||||
@@ -1108,7 +1102,7 @@ StreamingTailContent.displayName = 'StreamingTailContent';
|
||||
const MessageList = React.forwardRef<MessageListHandle, MessageListProps>(({
|
||||
sessionKey,
|
||||
turnStart,
|
||||
disableStaging: _disableStaging,
|
||||
disableStaging = false,
|
||||
messages,
|
||||
sessionIsWorking = false,
|
||||
activeStreamingMessageId = null,
|
||||
@@ -1123,7 +1117,6 @@ const MessageList = React.forwardRef<MessageListHandle, MessageListProps>(({
|
||||
scrollRef,
|
||||
}, ref) => {
|
||||
streamPerfCount('ui.message_list.render');
|
||||
void _disableStaging;
|
||||
const stickyUserHeader = useUIStore(state => state.stickyUserHeader);
|
||||
const chatRenderMode = useUIStore((state) => state.chatRenderMode);
|
||||
const activityRenderMode = useUIStore((state) => state.activityRenderMode);
|
||||
@@ -1320,7 +1313,7 @@ const MessageList = React.forwardRef<MessageListHandle, MessageListProps>(({
|
||||
|
||||
const grew = currentLen > previousLen;
|
||||
const firstChanged = previousFirstKey !== currentFirstKey;
|
||||
if (!shouldVirtualizeHistory || !grew || !firstChanged || previousLen === 0) {
|
||||
if (!shouldVirtualizeHistory || isLoadingOlder || disableStaging || !grew || !firstChanged || previousLen === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1379,36 +1372,9 @@ const MessageList = React.forwardRef<MessageListHandle, MessageListProps>(({
|
||||
if (!shouldVirtualizeHistory) {
|
||||
return;
|
||||
}
|
||||
const scrollEl = resolveScrollContainer();
|
||||
const prevTotal = historyVirtualizer.getTotalSize();
|
||||
const nearBottom = scrollEl && prevTotal > 0
|
||||
? scrollEl.scrollTop + scrollEl.clientHeight >= prevTotal - 10
|
||||
: false
|
||||
|
||||
historyVirtualizer.measure();
|
||||
|
||||
// measure() defers via useAnimationFrameWithResizeObserver.
|
||||
// Wait two frames then, if we were near the estimated bottom, scroll
|
||||
// to the real bottom after measurements settle.
|
||||
let frame2: number | null = null;
|
||||
const frame1 = requestAnimationFrame(() => {
|
||||
frame2 = requestAnimationFrame(() => {
|
||||
if (!nearBottom) return
|
||||
const el = resolveScrollContainer()
|
||||
if (!el) return
|
||||
const target = Math.max(0, el.scrollHeight - el.clientHeight)
|
||||
if (target > 0 && Math.abs(el.scrollTop - target) > 5) {
|
||||
el.scrollTop = target
|
||||
}
|
||||
})
|
||||
})
|
||||
return () => {
|
||||
cancelAnimationFrame(frame1)
|
||||
if (frame2 !== null) {
|
||||
cancelAnimationFrame(frame2)
|
||||
}
|
||||
}
|
||||
}, [historyVirtualizer, resolveScrollContainer, shouldVirtualizeHistory]);
|
||||
}, [historyEntries.length, historyVirtualizer, shouldVirtualizeHistory]);
|
||||
|
||||
const scheduleVirtualMeasure = React.useCallback(() => {
|
||||
if (!shouldVirtualizeHistory) {
|
||||
@@ -1673,7 +1639,7 @@ const MessageList = React.forwardRef<MessageListHandle, MessageListProps>(({
|
||||
if (!applyAnchor()) {
|
||||
const index = messageIndexMap.get(anchor.messageId);
|
||||
if (typeof index === 'number' && index < historyEntries.length) {
|
||||
scrollHistoryIndexIntoView(index, 'auto');
|
||||
return scrollHistoryIndexIntoView(index, 'auto');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -50,22 +50,26 @@ export interface UseChatTimelineControllerResult {
|
||||
activeTurnId: string | null;
|
||||
showScrollToBottom: boolean;
|
||||
turnWindowModel: TurnWindowModel;
|
||||
loadEarlier: () => Promise<void>;
|
||||
loadEarlier: (options?: { userInitiated?: boolean }) => Promise<void>;
|
||||
revealBufferedTurns: () => Promise<boolean>;
|
||||
resumeToBottom: () => void;
|
||||
resumeToBottomInstant: () => Promise<void>;
|
||||
scrollToTurn: (turnId: string, options?: { behavior?: ScrollBehavior }) => Promise<boolean>;
|
||||
scrollToMessage: (messageId: string, options?: { behavior?: ScrollBehavior }) => Promise<boolean>;
|
||||
handleHistoryScroll: () => void;
|
||||
captureViewportAnchor: () => ViewportAnchor | null;
|
||||
restoreViewportAnchor: (anchor: ViewportAnchor) => boolean;
|
||||
handleActiveTurnChange: (turnId: string | null) => void;
|
||||
}
|
||||
|
||||
const TURN_MODEL_CACHE_MAX = 30
|
||||
const HISTORY_SCROLL_THRESHOLD = 200
|
||||
const VSCODE_TURN_MODEL_CACHE_MAX = 4
|
||||
const VSCODE_TURN_MODEL_CACHE_MAX_MESSAGES = 30
|
||||
const MOBILE_TURN_MODEL_CACHE_MAX = 4
|
||||
const MOBILE_TURN_MODEL_CACHE_MAX_MESSAGES = 30
|
||||
const HISTORY_RENDER_WAIT_TIMEOUT_MS = 250
|
||||
const HISTORY_INTERACTION_GUARD_MS = 2000
|
||||
const turnModelCache = new Map<string, { messages: ChatMessageEntry[]; model: TurnWindowModel }>()
|
||||
const getTurnModelCacheMax = () => {
|
||||
if (isVSCodeRuntime()) return VSCODE_TURN_MODEL_CACHE_MAX
|
||||
@@ -150,6 +154,8 @@ export const useChatTimelineController = ({
|
||||
const initializedSessionRef = React.useRef<string | null>(null);
|
||||
const pendingRenderResolversRef = React.useRef<Array<() => void>>([]);
|
||||
const pendingScrollRequestRef = React.useRef<PendingScrollRequest | null>(null);
|
||||
const historyInteractionRef = React.useRef(false);
|
||||
const historyInteractionTimerRef = React.useRef<number | null>(null);
|
||||
|
||||
const historySignals = React.useMemo(() => {
|
||||
const defaultLimit = getMemoryLimits().HISTORICAL_MESSAGES;
|
||||
@@ -178,10 +184,38 @@ export const useChatTimelineController = ({
|
||||
messagesRef.current = messages;
|
||||
historyMetaRef.current = historyMeta;
|
||||
|
||||
const beginHistoryInteraction = React.useCallback(() => {
|
||||
historyInteractionRef.current = true;
|
||||
if (historyInteractionTimerRef.current !== null && typeof window !== 'undefined') {
|
||||
window.clearTimeout(historyInteractionTimerRef.current);
|
||||
historyInteractionTimerRef.current = null;
|
||||
}
|
||||
}, []);
|
||||
|
||||
const settleHistoryInteraction = React.useCallback(() => {
|
||||
if (typeof window === 'undefined') {
|
||||
historyInteractionRef.current = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (historyInteractionTimerRef.current !== null) {
|
||||
window.clearTimeout(historyInteractionTimerRef.current);
|
||||
}
|
||||
historyInteractionTimerRef.current = window.setTimeout(() => {
|
||||
historyInteractionTimerRef.current = null;
|
||||
historyInteractionRef.current = false;
|
||||
}, HISTORY_INTERACTION_GUARD_MS);
|
||||
}, []);
|
||||
|
||||
React.useLayoutEffect(() => {
|
||||
if (initializedSessionRef.current === sessionId) {
|
||||
return;
|
||||
}
|
||||
if (historyInteractionTimerRef.current !== null && typeof window !== 'undefined') {
|
||||
window.clearTimeout(historyInteractionTimerRef.current);
|
||||
historyInteractionTimerRef.current = null;
|
||||
}
|
||||
historyInteractionRef.current = false;
|
||||
initializedSessionRef.current = sessionId;
|
||||
setTurnStart(getInitialTurnStart(turnWindowModel.turnCount));
|
||||
setIsLoadingOlder(false);
|
||||
@@ -204,7 +238,13 @@ export const useChatTimelineController = ({
|
||||
setTurnStart((current) => {
|
||||
const previousInitial = getInitialTurnStart(previousTurnCount);
|
||||
const nextInitial = getInitialTurnStart(nextTurnCount);
|
||||
if (isPinnedRef.current && current === previousInitial) {
|
||||
if (
|
||||
!historyInteractionRef.current
|
||||
&& !isLoadingOlderRef.current
|
||||
&& !pendingRevealWorkRef.current
|
||||
&& isPinnedRef.current
|
||||
&& current === previousInitial
|
||||
) {
|
||||
return nextInitial;
|
||||
}
|
||||
return clampTurnStart(current, nextTurnCount);
|
||||
@@ -228,6 +268,25 @@ export const useChatTimelineController = ({
|
||||
});
|
||||
}, []);
|
||||
|
||||
const waitForNextRenderCommitOrTimeout = React.useCallback((): Promise<void> => {
|
||||
return new Promise<void>((resolve) => {
|
||||
if (typeof window === 'undefined') {
|
||||
resolve();
|
||||
return;
|
||||
}
|
||||
|
||||
let settled = false;
|
||||
const finish = () => {
|
||||
if (settled) return;
|
||||
settled = true;
|
||||
window.clearTimeout(timer);
|
||||
resolve();
|
||||
};
|
||||
pendingRenderResolversRef.current.push(finish);
|
||||
const timer = window.setTimeout(finish, HISTORY_RENDER_WAIT_TIMEOUT_MS);
|
||||
});
|
||||
}, []);
|
||||
|
||||
const resolvePendingScrollRequest = React.useCallback((value: boolean) => {
|
||||
const pending = pendingScrollRequestRef.current;
|
||||
if (!pending) {
|
||||
@@ -271,6 +330,10 @@ export const useChatTimelineController = ({
|
||||
|
||||
React.useEffect(() => {
|
||||
return () => {
|
||||
if (historyInteractionTimerRef.current !== null && typeof window !== 'undefined') {
|
||||
window.clearTimeout(historyInteractionTimerRef.current);
|
||||
historyInteractionTimerRef.current = null;
|
||||
}
|
||||
resolvePendingRenderWaiters();
|
||||
resolvePendingScrollRequest(false);
|
||||
};
|
||||
@@ -328,6 +391,7 @@ export const useChatTimelineController = ({
|
||||
return false;
|
||||
}
|
||||
|
||||
beginHistoryInteraction();
|
||||
const container = scrollRef.current;
|
||||
if (container) {
|
||||
prePrependScrollRef.current = {
|
||||
@@ -343,10 +407,14 @@ export const useChatTimelineController = ({
|
||||
return next > 0 ? next : 0;
|
||||
});
|
||||
|
||||
await waitForNextRenderCommit();
|
||||
setPendingRevealWork(false);
|
||||
return true;
|
||||
}, [captureViewportAnchor, scrollRef, waitForNextRenderCommit]);
|
||||
try {
|
||||
await waitForNextRenderCommit();
|
||||
return true;
|
||||
} finally {
|
||||
setPendingRevealWork(false);
|
||||
settleHistoryInteraction();
|
||||
}
|
||||
}, [beginHistoryInteraction, captureViewportAnchor, scrollRef, settleHistoryInteraction, waitForNextRenderCommit]);
|
||||
|
||||
const fetchOlderHistory = React.useCallback(async (input: {
|
||||
preserveViewport: boolean;
|
||||
@@ -374,6 +442,7 @@ export const useChatTimelineController = ({
|
||||
};
|
||||
}
|
||||
|
||||
beginHistoryInteraction();
|
||||
setIsLoadingOlder(true);
|
||||
|
||||
try {
|
||||
@@ -382,31 +451,112 @@ export const useChatTimelineController = ({
|
||||
return false;
|
||||
}
|
||||
|
||||
await loadMoreMessages(targetSessionId, 'up');
|
||||
let loadedMessageCount = beforeMessageCount;
|
||||
let loadedOldestMessageId = beforeOldestMessageId;
|
||||
let loadedLimit = beforeLimit;
|
||||
const beforeTurnCount = turnModelRef.current.turnCount;
|
||||
|
||||
const afterMessages = messagesRef.current;
|
||||
const afterMessageCount = afterMessages.length;
|
||||
const afterOldestMessageId = afterMessages[0]?.info?.id ?? null;
|
||||
const afterLimit = historyMetaRef.current?.limit ?? beforeLimit;
|
||||
const historyGrew =
|
||||
afterMessageCount > beforeMessageCount
|
||||
|| (typeof beforeOldestMessageId === 'string'
|
||||
&& typeof afterOldestMessageId === 'string'
|
||||
&& beforeOldestMessageId !== afterOldestMessageId);
|
||||
while (true) {
|
||||
await loadMoreMessages(targetSessionId, 'up');
|
||||
if (sessionIdRef.current !== targetSessionId) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return historyGrew || afterLimit > beforeLimit;
|
||||
await waitForNextRenderCommitOrTimeout();
|
||||
|
||||
const afterMessages = messagesRef.current;
|
||||
const afterMessageCount = afterMessages.length;
|
||||
const afterOldestMessageId = afterMessages[0]?.info?.id ?? null;
|
||||
const afterLimit = historyMetaRef.current?.limit ?? loadedLimit;
|
||||
const messageGrowth =
|
||||
afterMessageCount > loadedMessageCount
|
||||
|| (typeof loadedOldestMessageId === 'string'
|
||||
&& typeof afterOldestMessageId === 'string'
|
||||
&& loadedOldestMessageId !== afterOldestMessageId)
|
||||
|| afterLimit > loadedLimit;
|
||||
const turnGrowth = turnModelRef.current.turnCount - beforeTurnCount;
|
||||
|
||||
if (turnGrowth > 0) {
|
||||
return true;
|
||||
}
|
||||
if (!messageGrowth) {
|
||||
return false;
|
||||
}
|
||||
if (!historySignalsRef.current.hasMoreAboveTurns) {
|
||||
return true;
|
||||
}
|
||||
|
||||
loadedMessageCount = afterMessageCount;
|
||||
loadedOldestMessageId = afterOldestMessageId;
|
||||
loadedLimit = afterLimit;
|
||||
}
|
||||
} finally {
|
||||
setIsLoadingOlder(false);
|
||||
settleHistoryInteraction();
|
||||
}
|
||||
}, [captureViewportAnchor, loadMoreMessages, scrollRef]);
|
||||
}, [beginHistoryInteraction, captureViewportAnchor, loadMoreMessages, scrollRef, settleHistoryInteraction, waitForNextRenderCommitOrTimeout]);
|
||||
|
||||
const loadEarlier = React.useCallback(async () => {
|
||||
if (await revealBufferedTurns()) {
|
||||
const loadEarlier = React.useCallback(async (options?: { userInitiated?: boolean }) => {
|
||||
beginHistoryInteraction();
|
||||
if (options?.userInitiated) {
|
||||
releaseAutoFollow();
|
||||
}
|
||||
|
||||
try {
|
||||
if (await revealBufferedTurns()) {
|
||||
return;
|
||||
}
|
||||
|
||||
void (await fetchOlderHistory({ preserveViewport: true }));
|
||||
} finally {
|
||||
settleHistoryInteraction();
|
||||
}
|
||||
}, [beginHistoryInteraction, fetchOlderHistory, releaseAutoFollow, revealBufferedTurns, settleHistoryInteraction]);
|
||||
|
||||
const handleHistoryScroll = React.useCallback(() => {
|
||||
const container = scrollRef.current;
|
||||
if (!container) return;
|
||||
if (isPinnedRef.current) return;
|
||||
if (container.scrollTop >= HISTORY_SCROLL_THRESHOLD) return;
|
||||
if (!historySignalsRef.current.canLoadEarlier) return;
|
||||
if (isLoadingOlderRef.current || pendingRevealWorkRef.current) return;
|
||||
|
||||
void loadEarlier({ userInitiated: true });
|
||||
}, [loadEarlier, scrollRef]);
|
||||
|
||||
React.useEffect(() => {
|
||||
if (!sessionId || isLoadingOlder || pendingRevealWork) {
|
||||
return;
|
||||
}
|
||||
if (!isPinned || !historySignals.canLoadEarlier) {
|
||||
return;
|
||||
}
|
||||
if (typeof window === 'undefined') {
|
||||
return;
|
||||
}
|
||||
|
||||
void (await fetchOlderHistory({ preserveViewport: true }));
|
||||
}, [fetchOlderHistory, revealBufferedTurns]);
|
||||
const frame = window.requestAnimationFrame(() => {
|
||||
const container = scrollRef.current;
|
||||
if (!container) return;
|
||||
if (!isPinnedRef.current) return;
|
||||
if (!historySignalsRef.current.canLoadEarlier) return;
|
||||
if (isLoadingOlderRef.current || pendingRevealWorkRef.current) return;
|
||||
if (container.scrollHeight > container.clientHeight + 1) return;
|
||||
|
||||
void loadEarlier();
|
||||
});
|
||||
|
||||
return () => window.cancelAnimationFrame(frame);
|
||||
}, [
|
||||
historySignals.canLoadEarlier,
|
||||
isLoadingOlder,
|
||||
isPinned,
|
||||
loadEarlier,
|
||||
pendingRevealWork,
|
||||
renderedMessages.length,
|
||||
scrollRef,
|
||||
sessionId,
|
||||
]);
|
||||
|
||||
const scrollToTurn = React.useCallback(async (
|
||||
turnId: string,
|
||||
@@ -552,6 +702,7 @@ export const useChatTimelineController = ({
|
||||
resumeToBottomInstant,
|
||||
scrollToTurn,
|
||||
scrollToMessage,
|
||||
handleHistoryScroll,
|
||||
captureViewportAnchor,
|
||||
restoreViewportAnchor,
|
||||
handleActiveTurnChange,
|
||||
|
||||
@@ -22,9 +22,10 @@ import {
|
||||
import { getSessionMaterializationStatus, materializeSessionSnapshots } from "./materialization"
|
||||
|
||||
const SKIP_PARTS = new Set(["patch", "step-start", "step-finish"])
|
||||
const MESSAGE_PAGE_SIZE = 150
|
||||
const VSCODE_MESSAGE_PAGE_SIZE = 30
|
||||
const MOBILE_MESSAGE_PAGE_SIZE = 30
|
||||
const INITIAL_MESSAGE_PAGE_SIZE = 150
|
||||
const VSCODE_INITIAL_MESSAGE_PAGE_SIZE = 30
|
||||
const MOBILE_INITIAL_MESSAGE_PAGE_SIZE = 30
|
||||
const HISTORY_MESSAGE_PAGE_SIZE = 200
|
||||
const VSCODE_INITIAL_PAGE_EXPANSION_LIMITS = [50, 80, 120] as const
|
||||
const MAX_SEEN_DIRS = 30
|
||||
const VSCODE_SESSION_CACHE_LIMIT = 4
|
||||
@@ -53,12 +54,12 @@ const getEffectiveSessionCacheLimit = () => {
|
||||
if (isMobileSurfaceRuntime()) return MOBILE_SESSION_CACHE_LIMIT
|
||||
return SESSION_CACHE_LIMIT
|
||||
}
|
||||
const getEffectiveMessagePageSize = () => {
|
||||
if (isVSCodeRuntime()) return VSCODE_MESSAGE_PAGE_SIZE
|
||||
if (isMobileSurfaceRuntime()) return MOBILE_MESSAGE_PAGE_SIZE
|
||||
return MESSAGE_PAGE_SIZE
|
||||
const getInitialMessagePageSize = () => {
|
||||
if (isVSCodeRuntime()) return VSCODE_INITIAL_MESSAGE_PAGE_SIZE
|
||||
if (isMobileSurfaceRuntime()) return MOBILE_INITIAL_MESSAGE_PAGE_SIZE
|
||||
return INITIAL_MESSAGE_PAGE_SIZE
|
||||
}
|
||||
const getDefaultMeta = (): SyncMeta => ({ limit: getEffectiveMessagePageSize(), cursor: undefined, complete: false, loading: false })
|
||||
const getDefaultMeta = (): SyncMeta => ({ limit: getInitialMessagePageSize(), cursor: undefined, complete: false, loading: false })
|
||||
|
||||
function getPrefetchMeta(directory: string, sessionID: string): SyncMeta | undefined {
|
||||
const info = getSessionPrefetch(directory, sessionID)
|
||||
@@ -78,7 +79,7 @@ function sortParts(parts: Part[]) {
|
||||
function isHeavyConstrainedSessionCache(state: Pick<State, "message" | "part">, sessionID: string): boolean {
|
||||
const messages = state.message[sessionID]
|
||||
if (!messages || messages.length === 0) return false
|
||||
return messages.length > getEffectiveMessagePageSize()
|
||||
return messages.length > getInitialMessagePageSize()
|
||||
}
|
||||
|
||||
function isUserMessage(message: Message): boolean {
|
||||
@@ -291,7 +292,7 @@ export function useSync() {
|
||||
setMetaFor(sessionID, { loading: true })
|
||||
|
||||
try {
|
||||
const limit = options?.before ? getEffectiveMessagePageSize() : m.limit
|
||||
const limit = options?.before ? HISTORY_MESSAGE_PAGE_SIZE : m.limit
|
||||
let page = await fetchMessages(sessionID, limit, options?.before)
|
||||
|
||||
// Constrained shells keep the initial page small for switch performance. Some
|
||||
@@ -385,7 +386,7 @@ export function useSync() {
|
||||
if (shouldSkipSessionPrefetch({
|
||||
hasMessages: cachedReady,
|
||||
info: prefetchInfo,
|
||||
pageSize: getEffectiveMessagePageSize(),
|
||||
pageSize: getInitialMessagePageSize(),
|
||||
})) return
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user