fix(ui): improve React Query hooks and fix edge cases

- Update query keys to include all relevant parameters (branches, agents)
- Fix use-branches to pass includeRemote parameter to query key
- Fix use-settings to include sources in agents query key
- Update running-agents-view to use correct query key structure
- Update use-spec-loading to properly use spec query hooks
- Add missing queryClient invalidation in auto-mode mutations
- Add missing cache invalidation in spec mutations after creation

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Shirone
2026-01-15 19:11:25 +01:00
parent 3170e22383
commit 361cb06bf0
11 changed files with 57 additions and 25 deletions

View File

@@ -1,4 +1,4 @@
import { useState, useEffect, useCallback } from 'react';
import { useState, useEffect, useCallback, useRef } from 'react';
import { createLogger } from '@automaker/utils/logger';
import { useQueryClient } from '@tanstack/react-query';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
@@ -119,6 +119,9 @@ export function SessionManager({
// Use React Query for sessions list - always include archived, filter client-side
const { data: sessions = [], refetch: refetchSessions } = useSessions(true);
// Ref to track if we've done the initial running sessions check
const hasCheckedInitialRef = useRef(false);
// Check running state for all sessions
const checkRunningSessions = useCallback(async (sessionList: SessionListItem[]) => {
const api = getElectronAPI();
@@ -152,12 +155,13 @@ export function SessionManager({
}
}, [queryClient, refetchSessions, checkRunningSessions]);
// Check running state on initial load
// Check running state on initial load (runs only once when sessions first load)
useEffect(() => {
if (sessions.length > 0) {
if (sessions.length > 0 && !hasCheckedInitialRef.current) {
hasCheckedInitialRef.current = true;
checkRunningSessions(sessions);
}
}, [sessions.length > 0]); // Only run when sessions first load
}, [sessions, checkRunningSessions]);
// Periodically check running state for sessions (useful for detecting when agents finish)
useEffect(() => {

View File

@@ -304,7 +304,7 @@ export function UsagePopover() {
variant="ghost"
size="icon"
className={cn('h-6 w-6', claudeLoading && 'opacity-80')}
onClick={() => !claudeLoading && fetchClaudeUsage(false)}
onClick={() => !claudeLoading && fetchClaudeUsage()}
>
<RefreshCw className="w-3.5 h-3.5" />
</Button>
@@ -411,7 +411,7 @@ export function UsagePopover() {
variant="ghost"
size="icon"
className={cn('h-6 w-6', codexLoading && 'opacity-80')}
onClick={() => !codexLoading && fetchCodexUsage(false)}
onClick={() => !codexLoading && fetchCodexUsage()}
>
<RefreshCw className="w-3.5 h-3.5" />
</Button>

View File

@@ -22,9 +22,11 @@ export function useBranches() {
const branches = branchData?.branches ?? [];
const aheadCount = branchData?.aheadCount ?? 0;
const behindCount = branchData?.behindCount ?? 0;
// Use conservative defaults (false) until data is confirmed
// This prevents the UI from assuming git capabilities before the query completes
const gitRepoStatus: GitRepoStatus = {
isGitRepo: branchData?.isGitRepo ?? true,
hasCommits: branchData?.hasCommits ?? true,
isGitRepo: branchData?.isGitRepo ?? false,
hasCommits: branchData?.hasCommits ?? false,
};
const fetchBranches = useCallback(

View File

@@ -34,8 +34,8 @@ export function RunningAgentsView() {
}, [refetch]);
const handleStopAgent = useCallback(
(featureId: string) => {
stopFeature.mutate(featureId);
(featureId: string, projectPath: string) => {
stopFeature.mutate({ featureId, projectPath });
},
[stopFeature]
);
@@ -168,7 +168,7 @@ export function RunningAgentsView() {
<Button
variant="destructive"
size="sm"
onClick={() => handleStopAgent(agent.featureId)}
onClick={() => handleStopAgent(agent.featureId, agent.projectPath)}
disabled={stopFeature.isPending}
>
<Square className="h-3.5 w-3.5 mr-1.5" />

View File

@@ -27,15 +27,13 @@ export function useSpecLoading() {
const loadSpec = useCallback(async () => {
if (!currentProject?.path) return;
// First check if generation is running
await queryClient.invalidateQueries({
// Fetch fresh status data to avoid stale cache issues
// Using fetchQuery ensures we get the latest data before checking
const statusData = await queryClient.fetchQuery<{ isRunning: boolean }>({
queryKey: queryKeys.specRegeneration.status(currentProject.path),
staleTime: 0, // Force fresh fetch
});
const statusData = queryClient.getQueryData<{ isRunning: boolean }>(
queryKeys.specRegeneration.status(currentProject.path)
);
if (statusData?.isRunning) {
return;
}