native macOS codings agent orchestrator
6
fork

Configure Feed

Select the types of activity you want to include in your feed.

Fix worktree removal animation causing row to reappear

The bug was that withAnimation only wrapped the repositories state
change while deletingWorktreeIDs was cleared outside the animation
block. This timing mismatch caused the row to show as "removing..."
briefly then revert to showing the worktree name without being removed.

Fix by wrapping all related state changes (repositories,
pendingWorktrees, deletingWorktreeIDs, pendingSetupScriptWorktreeIDs)
in the same animation block.

khoi 5a684463 df976e97

+21 -15
+21 -15
supacode/Features/Repositories/Reducer/RepositoriesFeature.swift
··· 473 473 } 474 474 } 475 475 476 - private func loadRepositories(_ roots: [URL], animated: Bool) -> Effect<Action> { 477 - .run { send in 476 + private func loadRepositories(_ roots: [URL], animated: Bool = false) -> Effect<Action> { 477 + .run { [animated] send in 478 478 let (repositories, errors) = await loadRepositoriesData(roots) 479 479 await send(.repositoriesLoaded(repositories, errors: errors, animated: animated)) 480 480 } ··· 508 508 let previousCounts = Dictionary( 509 509 uniqueKeysWithValues: state.repositories.map { ($0.id, $0.worktrees.count) } 510 510 ) 511 - if animated { 512 - withAnimation { 513 - state.repositories = repositories 514 - } 515 - } else { 516 - state.repositories = repositories 517 - } 518 - if prunePinnedWorktreeIDs(state: &state) { 519 - repositoryPersistence.savePinnedWorktreeIDs(state.pinnedWorktreeIDs) 520 - } 521 511 let repositoryIDs = Set(repositories.map(\.id)) 522 512 let newCounts = Dictionary( 523 513 uniqueKeysWithValues: repositories.map { ($0.id, $0.worktrees.count) } ··· 530 520 addedCounts[id] = added 531 521 } 532 522 } 533 - state.pendingWorktrees = state.pendingWorktrees.filter { pending in 523 + let filteredPendingWorktrees = state.pendingWorktrees.filter { pending in 534 524 guard repositoryIDs.contains(pending.repositoryID) else { return false } 535 525 guard let remaining = addedCounts[pending.repositoryID], remaining > 0 else { return true } 536 526 addedCounts[pending.repositoryID] = remaining - 1 537 527 return false 538 528 } 539 529 let availableWorktreeIDs = Set(repositories.flatMap { $0.worktrees.map(\.id) }) 540 - state.deletingWorktreeIDs = state.deletingWorktreeIDs.intersection(availableWorktreeIDs) 541 - state.pendingSetupScriptWorktreeIDs = state.pendingSetupScriptWorktreeIDs.filter { 530 + let filteredDeletingIDs = state.deletingWorktreeIDs.intersection(availableWorktreeIDs) 531 + let filteredSetupScriptIDs = state.pendingSetupScriptWorktreeIDs.filter { 542 532 availableWorktreeIDs.contains($0) 533 + } 534 + if animated { 535 + withAnimation { 536 + state.repositories = repositories 537 + state.pendingWorktrees = filteredPendingWorktrees 538 + state.deletingWorktreeIDs = filteredDeletingIDs 539 + state.pendingSetupScriptWorktreeIDs = filteredSetupScriptIDs 540 + } 541 + } else { 542 + state.repositories = repositories 543 + state.pendingWorktrees = filteredPendingWorktrees 544 + state.deletingWorktreeIDs = filteredDeletingIDs 545 + state.pendingSetupScriptWorktreeIDs = filteredSetupScriptIDs 546 + } 547 + if prunePinnedWorktreeIDs(state: &state) { 548 + repositoryPersistence.savePinnedWorktreeIDs(state.pinnedWorktreeIDs) 543 549 } 544 550 if !isSelectionValid(state.selectedWorktreeID, state: state) { 545 551 state.selectedWorktreeID = nil