Perfect! The fix is working. Here's what I changed to resolve the deleted files diff flickering issue: (#760)

## Problem Analysis
The issue was in [`DiffTab.tsx`](file:///private/var/folders/5q/5vgq75y92dz0k7n62z93299r0000gn/T/vibe-kanban/worktrees/vk-9210-deleted-fi/frontend/src/components/tasks/TaskDetails/DiffTab.tsx#L48-L63) where the auto-collapse logic for deleted files was running every time the `diffs` array changed. This happened because:

1. The SSE stream sends periodic updates that caused `diffs` to change
2. The `useEffect` was checking `collapsedIds.size > 0` to preserve user toggles, but this logic was flawed
3. Each time `diffs` changed, it would re-collapse deleted files, overriding user attempts to expand them

## Solution
I added a `hasInitialized` state variable that ensures the auto-collapse logic only runs once per task attempt, not on every diff update. The changes:

1. Added `hasInitialized` state to track if we've already set initial collapsed state
2. Reset `hasInitialized` when the selected attempt changes
3. Changed the condition from `collapsedIds.size > 0` to `hasInitialized` to prevent re-running
4. Set `hasInitialized = true` after setting initial collapsed state

This fixes both issues: the flickering stops and deleted files can now be expanded and stay expanded.
This commit is contained in:
Britannio Jarrett
2025-09-17 15:55:08 +00:00
committed by GitHub
parent 6e97dc37f9
commit cfc8684e4b

View File

@@ -14,6 +14,7 @@ interface DiffTabProps {
function DiffTab({ selectedAttempt }: DiffTabProps) {
const [loading, setLoading] = useState(true);
const [collapsedIds, setCollapsedIds] = useState<Set<string>>(new Set());
const [hasInitialized, setHasInitialized] = useState(false);
const { diffs, error } = useDiffEntries(selectedAttempt?.id ?? null, true);
const { fileCount, added, deleted } = useDiffSummary(
selectedAttempt?.id ?? null
@@ -21,6 +22,7 @@ function DiffTab({ selectedAttempt }: DiffTabProps) {
useEffect(() => {
setLoading(true);
setHasInitialized(false);
}, [selectedAttempt?.id]);
useEffect(() => {
@@ -44,10 +46,10 @@ function DiffTab({ selectedAttempt }: DiffTabProps) {
return () => clearTimeout(timer);
}, [loading, diffs.length]);
// Default-collapse certain change kinds on first load
// Default-collapse certain change kinds on first load only
useEffect(() => {
if (diffs.length === 0) return;
if (collapsedIds.size > 0) return; // preserve user toggles if any
if (hasInitialized) return; // only run once per attempt
const kindsToCollapse = new Set([
'deleted',
'renamed',
@@ -60,7 +62,8 @@ function DiffTab({ selectedAttempt }: DiffTabProps) {
.map((d, i) => d.newPath || d.oldPath || String(i))
);
if (initial.size > 0) setCollapsedIds(initial);
}, [diffs, collapsedIds.size]);
setHasInitialized(true);
}, [diffs, hasInitialized]);
const ids = useMemo(() => {
return diffs.map((d, i) => d.newPath || d.oldPath || String(i));