Make pagination requests abortable

This commit is contained in:
Jack Kingsman
2026-03-16 15:18:38 -07:00
parent 4277e0c924
commit 58b34a6a2f
34 changed files with 476 additions and 322 deletions
+46 -14
View File
@@ -161,6 +161,8 @@ export function useConversationMessages(
const [loadingNewer, setLoadingNewer] = useState(false);
const abortControllerRef = useRef<AbortController | null>(null);
const olderAbortControllerRef = useRef<AbortController | null>(null);
const newerAbortControllerRef = useRef<AbortController | null>(null);
const fetchingConversationIdRef = useRef<string | null>(null);
const latestReconcileRequestIdRef = useRef(0);
const messagesRef = useRef<Message[]>([]);
@@ -306,14 +308,19 @@ export function useConversationMessages(
loadingOlderRef.current = true;
setLoadingOlder(true);
const controller = new AbortController();
olderAbortControllerRef.current = controller;
try {
const data = await api.getMessages({
type: activeConversation.type === 'channel' ? 'CHAN' : 'PRIV',
conversation_key: conversationId,
limit: MESSAGE_PAGE_SIZE,
before: oldestMessage.received_at,
before_id: oldestMessage.id,
});
const data = await api.getMessages(
{
type: activeConversation.type === 'channel' ? 'CHAN' : 'PRIV',
conversation_key: conversationId,
limit: MESSAGE_PAGE_SIZE,
before: oldestMessage.received_at,
before_id: oldestMessage.id,
},
controller.signal
);
if (fetchingConversationIdRef.current !== conversationId) return;
@@ -335,11 +342,17 @@ export function useConversationMessages(
}
setHasOlderMessages(dataWithPendingAck.length >= MESSAGE_PAGE_SIZE);
} catch (err) {
if (isAbortError(err)) {
return;
}
console.error('Failed to fetch older messages:', err);
toast.error('Failed to load older messages', {
description: err instanceof Error ? err.message : 'Check your connection',
});
} finally {
if (olderAbortControllerRef.current === controller) {
olderAbortControllerRef.current = null;
}
loadingOlderRef.current = false;
setLoadingOlder(false);
}
@@ -361,14 +374,19 @@ export function useConversationMessages(
if (!newestMessage) return;
setLoadingNewer(true);
const controller = new AbortController();
newerAbortControllerRef.current = controller;
try {
const data = await api.getMessages({
type: activeConversation.type === 'channel' ? 'CHAN' : 'PRIV',
conversation_key: conversationId,
limit: MESSAGE_PAGE_SIZE,
after: newestMessage.received_at,
after_id: newestMessage.id,
});
const data = await api.getMessages(
{
type: activeConversation.type === 'channel' ? 'CHAN' : 'PRIV',
conversation_key: conversationId,
limit: MESSAGE_PAGE_SIZE,
after: newestMessage.received_at,
after_id: newestMessage.id,
},
controller.signal
);
if (fetchingConversationIdRef.current !== conversationId) return;
@@ -385,11 +403,17 @@ export function useConversationMessages(
}
setHasNewerMessages(dataWithPendingAck.length >= MESSAGE_PAGE_SIZE);
} catch (err) {
if (isAbortError(err)) {
return;
}
console.error('Failed to fetch newer messages:', err);
toast.error('Failed to load newer messages', {
description: err instanceof Error ? err.message : 'Check your connection',
});
} finally {
if (newerAbortControllerRef.current === controller) {
newerAbortControllerRef.current = null;
}
setLoadingNewer(false);
}
}, [activeConversation, applyPendingAck, hasNewerMessages, loadingNewer, messages]);
@@ -420,6 +444,14 @@ export function useConversationMessages(
if (abortControllerRef.current) {
abortControllerRef.current.abort();
}
if (olderAbortControllerRef.current) {
olderAbortControllerRef.current.abort();
olderAbortControllerRef.current = null;
}
if (newerAbortControllerRef.current) {
newerAbortControllerRef.current.abort();
newerAbortControllerRef.current = null;
}
const prevId = prevConversationIdRef.current;
const newId = activeConversation?.id ?? null;