fix: Improve loading state handling on chat/threads page (#576)

* Apply patch

* Apply patch

* Apply patch

* cr

---------

Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
Co-authored-by: bracesproul <braceasproul@gmail.com>
This commit is contained in:
open-swe[bot] 2025-07-28 16:33:37 -07:00 • committed by GitHub
parent 2c774ee517
commit 25c3709e69
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -29,7 +29,7 @@ type FilterStatus =
function AllThreadsPageContent() {
const router = useRouter();
const { currentInstallation } = useGitHubAppProvider();
const { currentInstallation, installationsLoading } = useGitHubAppProvider();
const { threads, isLoading: threadsLoading } = useThreadsSWR({
assistantId: MANAGER_GRAPH_ID,
currentInstallation,
@ -48,40 +48,52 @@ function AllThreadsPageContent() {
isLoading: statusLoading,
} = useThreadsStatus(threadIds, threads);
const filteredThreads = threadsMetadata.filter((thread: ThreadMetadata) => {
const matchesSearch =
thread.title.toLowerCase().includes(searchQuery.toLowerCase()) ||
thread.repository.toLowerCase().includes(searchQuery.toLowerCase());
const filteredThreads = useMemo(() => {
return threadsMetadata.filter((thread: ThreadMetadata) => {
const matchesSearch =
thread.title.toLowerCase().includes(searchQuery.toLowerCase()) ||
thread.repository.toLowerCase().includes(searchQuery.toLowerCase());
const matchesStatus =
statusFilter === "all" || statusMap[thread.id] === statusFilter;
const matchesStatus =
statusFilter === "all" || statusMap[thread.id] === statusFilter;
return matchesSearch && matchesStatus;
});
return matchesSearch && matchesStatus;
});
}, [threadsMetadata, searchQuery, statusFilter, statusMap]);
const groupedThreads = {
running: filteredThreads.filter(
(thread: ThreadMetadata) => statusMap[thread.id] === "running",
),
completed: filteredThreads.filter(
(thread: ThreadMetadata) => statusMap[thread.id] === "completed",
),
failed: filteredThreads.filter(
(thread: ThreadMetadata) => statusMap[thread.id] === "failed",
),
pending: filteredThreads.filter(
(thread: ThreadMetadata) => statusMap[thread.id] === "pending",
),
idle: filteredThreads.filter(
(thread: ThreadMetadata) => statusMap[thread.id] === "idle",
),
paused: filteredThreads.filter(
(thread: ThreadMetadata) => statusMap[thread.id] === "paused",
),
error: filteredThreads.filter(
(thread: ThreadMetadata) => statusMap[thread.id] === "error",
),
};
const groupedThreads = useMemo(() => {
return {
running: filteredThreads.filter(
(thread: ThreadMetadata) => statusMap[thread.id] === "running",
),
completed: filteredThreads.filter(
(thread: ThreadMetadata) => statusMap[thread.id] === "completed",
),
failed: filteredThreads.filter(
(thread: ThreadMetadata) => statusMap[thread.id] === "failed",
),
pending: filteredThreads.filter(
(thread: ThreadMetadata) => statusMap[thread.id] === "pending",
),
idle: filteredThreads.filter(
(thread: ThreadMetadata) => statusMap[thread.id] === "idle",
),
paused: filteredThreads.filter(
(thread: ThreadMetadata) => statusMap[thread.id] === "paused",
),
error: filteredThreads.filter(
(thread: ThreadMetadata) => statusMap[thread.id] === "error",
),
};
}, [filteredThreads, statusMap]);
// Show loading state if threads/status/installation requests are loading, and there are no
// threads to display (conditional of the status filter)
const showThreadsLoading =
(threadsLoading || statusLoading || installationsLoading) &&
(statusFilter === "all"
? Object.values(groupedThreads).flat().length === 0
: filteredThreads.length === 0);
return (
<div className="bg-background flex h-screen flex-col">
@ -236,21 +248,20 @@ function AllThreadsPageContent() {
</div>
)}
{(threadsLoading || statusLoading) &&
(!threads || threads.length === 0) && (
<div>
<div className="mb-3 flex items-center gap-2">
<h2 className="text-foreground text-base font-semibold capitalize">
Loading threads...
</h2>
</div>
<div className="grid gap-3 md:grid-cols-2 lg:grid-cols-3">
{Array.from({ length: 9 }).map((_, index) => (
<ThreadCardLoading key={`all-threads-loading-${index}`} />
))}
</div>
{showThreadsLoading && (
<div>
<div className="mb-3 flex items-center gap-2">
<h2 className="text-foreground text-base font-semibold capitalize">
Loading threads...
</h2>
</div>
)}
<div className="grid gap-3 md:grid-cols-2 lg:grid-cols-3">
{Array.from({ length: 9 }).map((_, index) => (
<ThreadCardLoading key={`all-threads-loading-${index}`} />
))}
</div>
</div>
)}
</div>
</div>
</div>