mirror of
https://github.com/catlog22/Claude-Code-Workflow.git
synced 2026-03-06 16:31:12 +08:00
feat: implement infinite scrolling for native sessions and add reset functionality to queue scheduler
This commit is contained in:
@@ -4,7 +4,7 @@
|
||||
// TanStack Query hook for native CLI sessions list
|
||||
|
||||
import React from 'react';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { useQuery, useInfiniteQuery } from '@tanstack/react-query';
|
||||
import {
|
||||
fetchNativeSessions,
|
||||
type NativeSessionListItem,
|
||||
@@ -17,6 +17,7 @@ import { workspaceQueryKeys } from '@/lib/queryKeys';
|
||||
|
||||
const STALE_TIME = 2 * 60 * 1000; // 2 minutes (increased from 30s)
|
||||
const GC_TIME = 10 * 60 * 1000; // 10 minutes (increased from 5min)
|
||||
const PAGE_SIZE = 50; // Default page size for pagination
|
||||
|
||||
// ========== Types ==========
|
||||
|
||||
@@ -54,6 +55,29 @@ export interface UseNativeSessionsReturn {
|
||||
refetch: () => Promise<void>;
|
||||
}
|
||||
|
||||
export interface UseNativeSessionsInfiniteReturn {
|
||||
/** All sessions data (flattened from all pages) */
|
||||
sessions: NativeSessionListItem[];
|
||||
/** Sessions grouped by tool */
|
||||
byTool: ByToolRecord;
|
||||
/** Total count from current pages */
|
||||
count: number;
|
||||
/** Loading state for initial fetch */
|
||||
isLoading: boolean;
|
||||
/** Fetching state (initial or refetch) */
|
||||
isFetching: boolean;
|
||||
/** Fetching next page */
|
||||
isFetchingNextPage: boolean;
|
||||
/** Whether there are more pages */
|
||||
hasNextPage: boolean;
|
||||
/** Error object if query failed */
|
||||
error: Error | null;
|
||||
/** Fetch next page */
|
||||
fetchNextPage: () => Promise<void>;
|
||||
/** Manually refetch data */
|
||||
refetch: () => Promise<void>;
|
||||
}
|
||||
|
||||
// ========== Helper Functions ==========
|
||||
|
||||
/**
|
||||
@@ -95,7 +119,7 @@ export function useNativeSessions(
|
||||
|
||||
const query = useQuery<NativeSessionsListResponse>({
|
||||
queryKey: workspaceQueryKeys.nativeSessionsList(projectPath, tool),
|
||||
queryFn: () => fetchNativeSessions(tool, projectPath),
|
||||
queryFn: () => fetchNativeSessions({ tool, project: projectPath, limit: 200 }),
|
||||
staleTime,
|
||||
gcTime,
|
||||
enabled,
|
||||
@@ -107,7 +131,7 @@ export function useNativeSessions(
|
||||
// Memoize sessions and byTool calculations
|
||||
const { sessions, byTool } = React.useMemo(() => {
|
||||
const sessions = query.data?.sessions ?? [];
|
||||
const byTool = groupByTool(sessions);
|
||||
const byTool = query.data?.byTool ?? groupByTool(sessions);
|
||||
return { sessions, byTool };
|
||||
}, [query.data]);
|
||||
|
||||
@@ -125,3 +149,81 @@ export function useNativeSessions(
|
||||
refetch,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook for fetching native CLI sessions with infinite scroll/pagination
|
||||
*
|
||||
* @example
|
||||
* ```tsx
|
||||
* const { sessions, fetchNextPage, hasNextPage, isFetchingNextPage } = useNativeSessionsInfinite();
|
||||
*
|
||||
* // Load more button
|
||||
* <button onClick={() => fetchNextPage()} disabled={!hasNextPage || isFetchingNextPage}>
|
||||
* {isFetchingNextPage ? 'Loading...' : 'Load More'}
|
||||
* </button>
|
||||
* ```
|
||||
*/
|
||||
export function useNativeSessionsInfinite(
|
||||
options: UseNativeSessionsOptions = {}
|
||||
): UseNativeSessionsInfiniteReturn {
|
||||
const { tool, staleTime = STALE_TIME, gcTime = GC_TIME, enabled = true } = options;
|
||||
const projectPath = useWorkflowStore(selectProjectPath);
|
||||
|
||||
const query = useInfiniteQuery<NativeSessionsListResponse>({
|
||||
queryKey: [...workspaceQueryKeys.nativeSessionsList(projectPath, tool), 'infinite'],
|
||||
queryFn: ({ pageParam }) => fetchNativeSessions({
|
||||
tool,
|
||||
project: projectPath,
|
||||
limit: PAGE_SIZE,
|
||||
cursor: pageParam as string | null,
|
||||
}),
|
||||
initialPageParam: null as string | null,
|
||||
getNextPageParam: (lastPage) => {
|
||||
if (!lastPage.hasMore || !lastPage.nextCursor) return undefined;
|
||||
return lastPage.nextCursor;
|
||||
},
|
||||
staleTime,
|
||||
gcTime,
|
||||
enabled,
|
||||
refetchOnWindowFocus: false,
|
||||
retry: 2,
|
||||
retryDelay: (attemptIndex) => Math.min(1000 * 2 ** attemptIndex, 10000),
|
||||
});
|
||||
|
||||
// Flatten all pages into a single array and group by tool
|
||||
const { sessions, byTool, count } = React.useMemo(() => {
|
||||
const allSessions = query.data?.pages.flatMap(page => page.sessions) ?? [];
|
||||
// Merge byTool from all pages
|
||||
const mergedByTool: ByToolRecord = {};
|
||||
for (const page of query.data?.pages ?? []) {
|
||||
for (const [toolKey, toolSessions] of Object.entries(page.byTool ?? {})) {
|
||||
if (!mergedByTool[toolKey]) {
|
||||
mergedByTool[toolKey] = [];
|
||||
}
|
||||
mergedByTool[toolKey].push(...toolSessions);
|
||||
}
|
||||
}
|
||||
return { sessions: allSessions, byTool: mergedByTool, count: allSessions.length };
|
||||
}, [query.data]);
|
||||
|
||||
const fetchNextPage = async () => {
|
||||
await query.fetchNextPage();
|
||||
};
|
||||
|
||||
const refetch = async () => {
|
||||
await query.refetch();
|
||||
};
|
||||
|
||||
return {
|
||||
sessions,
|
||||
byTool,
|
||||
count,
|
||||
isLoading: query.isLoading,
|
||||
isFetching: query.isFetching,
|
||||
isFetchingNextPage: query.isFetchingNextPage,
|
||||
hasNextPage: query.hasNextPage,
|
||||
error: query.error,
|
||||
fetchNextPage,
|
||||
refetch,
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user