feat(ui): separate OperationStatus per worktree action (refresh/cleanup/reset/force-remove/batch-merge)

Replaces the shared IsBusy/IsMerging flags in WorktreesOverviewModalViewModel and the
reset flow in WorktreesSettingsTabViewModel with dedicated OperationStatus instances
shown via OperationIndicator, so a running Refresh no longer blocks the Cleanup
indicator. ForceRemove gains a CanExecute guard against re-entrancy while it's running,
and the reconcile tick's busy guard now checks all four action statuses instead of the
old IsBusy||IsMerging pair.
This commit is contained in:
Mika Kuns
2026-08-12 09:39:10 +02:00
parent d3abd4b88b
commit a0d5db0db0
8 changed files with 189 additions and 100 deletions
@@ -257,7 +257,9 @@
<StackPanel Orientation="Horizontal" Spacing="8">
<Button Classes="btn" Content="{loc:Tr settings.cancel}" Command="{Binding Worktrees.CancelResetConfirmCommand}"/>
<Button Content="{loc:Tr settings.worktrees.removeAll}" Classes="danger"
Command="{Binding Worktrees.ConfirmResetAllCommand}"/>
Command="{Binding Worktrees.ConfirmResetAllCommand}"
IsEnabled="{Binding !Worktrees.ResetStatus.IsRunning}"/>
<ctl:OperationIndicator Status="{Binding Worktrees.ResetStatus}"/>
</StackPanel>
</StackPanel>
</Border>
@@ -104,8 +104,10 @@
BorderThickness="0,0,0,1"
Padding="12,8">
<StackPanel Orientation="Horizontal" Spacing="8">
<Button Classes="btn" Content="{loc:Tr modals.worktreesOverview.refresh}" Command="{Binding RefreshCommand}" IsEnabled="{Binding !IsBusy}"/>
<Button Classes="btn" Content="{loc:Tr modals.worktreesOverview.cleanupFinished}" Command="{Binding CleanupFinishedCommand}" IsEnabled="{Binding !IsBusy}"/>
<Button Classes="btn" Content="{loc:Tr modals.worktreesOverview.refresh}" Command="{Binding RefreshCommand}" IsEnabled="{Binding !RefreshStatus.IsRunning}"/>
<ctl:OperationIndicator Status="{Binding RefreshStatus}"/>
<Button Classes="btn" Content="{loc:Tr modals.worktreesOverview.cleanupFinished}" Command="{Binding CleanupFinishedCommand}" IsEnabled="{Binding !CleanupStatus.IsRunning}"/>
<ctl:OperationIndicator Status="{Binding CleanupStatus}"/>
<!-- Batch merge is per-list only: a single target branch is meaningless across repos. -->
<StackPanel Orientation="Horizontal" Spacing="8" IsVisible="{Binding !IsGlobal}">
<Button Classes="btn" Content="{loc:Tr modals.worktreesOverview.selectAll}" Command="{Binding ToggleSelectAllCommand}"/>
@@ -117,11 +119,15 @@
<Button Classes="btn accent"
Content="{loc:Tr modals.worktreesOverview.mergeAll}"
Command="{Binding MergeAllCommand}"/>
<ctl:OperationIndicator Status="{Binding BatchMergeStatus}"/>
<TextBlock Text="{Binding SelectedCount, StringFormat='{}{0} selected'}"
VerticalAlignment="Center" Foreground="{DynamicResource TextDimBrush}"/>
<!-- Post-run summary only ("N merged, M conflicts"); the live i/n ticker lives in the
OperationIndicator's label above so the two don't show the same count twice. -->
<TextBlock Text="{Binding BatchProgress}" VerticalAlignment="Center" Margin="8,0,0,0"
Foreground="{DynamicResource TextDimBrush}"/>
</StackPanel>
<ctl:OperationIndicator Status="{Binding ForceRemoveStatus}"/>
<TextBlock Text="{Binding StatusMessage}" VerticalAlignment="Center" Margin="8,0,0,0"
Foreground="{DynamicResource TextDimBrush}"/>
</StackPanel>