feat(ui): dirty Ziel-Verzeichnis beim Oeffnen des Merge-Dialogs melden statt nach dem Fehlschlag
MergeTargetsDto/MergeTargets bekommen TargetDirty (via HasChangesAsync, includeUntracked: false). Das Merge-Modal zeigt Warnung + Stash-Retry sofort in InitializeAsync statt erst nach dem dirty_target-Fehlschlag; der REVIEW-Block in der Detail-Pane zeigt denselben Hinweis neben Approve. Der dirty_target-Rueckgabepfad bleibt als Absicherung bestehen. Behebt Befund F6 aus docs/test-session-2026-09-16.md.
This commit is contained in:
@@ -726,6 +726,7 @@ public sealed partial class DetailsIslandViewModel : ViewModelBase, IDisposable
|
||||
Merge.MergeTargetBranches.Clear();
|
||||
foreach (var b in targets.LocalBranches) Merge.MergeTargetBranches.Add(b);
|
||||
Merge.SelectedMergeTarget = targets.DefaultBranch;
|
||||
Merge.TargetDirty = targets.TargetDirty;
|
||||
}
|
||||
}
|
||||
await Merge.RefreshMergePreviewAsync();
|
||||
@@ -776,6 +777,7 @@ public sealed partial class DetailsIslandViewModel : ViewModelBase, IDisposable
|
||||
foreach (var b in targets.LocalBranches)
|
||||
Merge.MergeTargetBranches.Add(b);
|
||||
Merge.SelectedMergeTarget = targets.DefaultBranch;
|
||||
Merge.TargetDirty = targets.TargetDirty;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -822,6 +824,7 @@ public sealed partial class DetailsIslandViewModel : ViewModelBase, IDisposable
|
||||
foreach (var b in targets.LocalBranches)
|
||||
Merge.MergeTargetBranches.Add(b);
|
||||
Merge.SelectedMergeTarget = targets.DefaultBranch;
|
||||
Merge.TargetDirty = targets.TargetDirty;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,6 +28,10 @@ public sealed partial class MergeSectionViewModel : ViewModelBase
|
||||
[ObservableProperty] private ObservableCollection<string> _mergeTargetBranches = new();
|
||||
[ObservableProperty] private string? _selectedMergeTarget;
|
||||
|
||||
// Mirrors MergeTargetsDto.TargetDirty — surfaced next to Approve so a dirty target working
|
||||
// dir is visible before anyone clicks, not just after the merge modal refuses it.
|
||||
[ObservableProperty] private bool _targetDirty;
|
||||
|
||||
// No CanExecute to gate here — RefreshMergePreviewAsync is triggered from the Bind path,
|
||||
// not a [RelayCommand], so PreviewOp only drives the indicator, never locks a button.
|
||||
public OperationStatus PreviewOp { get; } = new();
|
||||
@@ -141,6 +145,7 @@ public sealed partial class MergeSectionViewModel : ViewModelBase
|
||||
MergePreviewText = "";
|
||||
MergeIsClean = false;
|
||||
MergeIsConflict = false;
|
||||
TargetDirty = false;
|
||||
SyncWorktree(null, null, null, null, null);
|
||||
SyncTaskContext(null, null, false);
|
||||
SyncChildOutcomes(false, 0);
|
||||
|
||||
@@ -76,6 +76,14 @@ public sealed partial class MergeModalViewModel : ViewModelBase
|
||||
SelectedBranch = Branches.Contains(targets.DefaultBranch)
|
||||
? targets.DefaultBranch
|
||||
: Branches.FirstOrDefault();
|
||||
|
||||
// Known dirty before anyone clicks Merge — offer the stash retry right away instead
|
||||
// of making the user hit the "dirty_target" refusal first.
|
||||
if (targets.TargetDirty)
|
||||
{
|
||||
WarningMessage = Loc.T("vm.merge.targetDirty");
|
||||
ShowStashRetry = true;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
@@ -327,6 +327,10 @@
|
||||
<ComboBox ItemsSource="{Binding Merge.MergeTargetBranches}"
|
||||
SelectedItem="{Binding Merge.SelectedMergeTarget, Mode=TwoWay}"
|
||||
HorizontalAlignment="Stretch" />
|
||||
<TextBlock Classes="meta" Text="{loc:Tr details.workConsole.targetDirty}"
|
||||
TextWrapping="Wrap"
|
||||
Foreground="{DynamicResource AmberBrush}"
|
||||
IsVisible="{Binding Merge.TargetDirty}" />
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Spacing="0">
|
||||
|
||||
@@ -70,6 +70,11 @@
|
||||
TextWrapping="Wrap"
|
||||
IsVisible="{Binding ErrorMessage, Converter={x:Static ObjectConverters.IsNotNull}}" />
|
||||
|
||||
<TextBlock Text="{Binding WarningMessage}"
|
||||
Foreground="{DynamicResource AmberBrush}"
|
||||
TextWrapping="Wrap"
|
||||
IsVisible="{Binding WarningMessage, Converter={x:Static ObjectConverters.IsNotNull}}" />
|
||||
|
||||
<Button Classes="btn" HorizontalAlignment="Left"
|
||||
Content="{loc:Tr modals.merge.stashAndMerge}"
|
||||
Command="{Binding StashAndMergeCommand}"
|
||||
|
||||
Reference in New Issue
Block a user