feat(merge): unify planning conflicts onto the resolver + 3-pane VM foundation

Route planning unit-merge conflicts through ConflictResolverViewModel
(OpenForPlanningAsync) and delete the old ConflictResolutionViewModel dialog.
Add active-file 3-pane reconstruction (MergeFile OursText/TheirsText/ResultText,
ActiveFile, SelectFileCommand, active-file readout) as the VM foundation for the
Rider-style editor. Seam preserved; Ui.Tests 128/128.
This commit is contained in:
Mika Kuns
2026-06-19 09:58:32 +02:00
parent 983c177c9a
commit 378a92c156
10 changed files with 288 additions and 337 deletions

View File

@@ -42,11 +42,6 @@ public partial class MainWindow : Window
{
if (DataContext is IslandsShellViewModel vm)
{
vm.ShowConflictDialog = async (conflictVm) =>
{
var modal = new ConflictResolutionView { DataContext = conflictVm };
await modal.ShowDialog(this);
};
vm.ShowAboutModal = async (aboutVm) =>
{
var dlg = new AboutModalView { DataContext = aboutVm };

View File

@@ -1,52 +0,0 @@
<Window xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="using:ClaudeDo.Ui.ViewModels.Planning"
xmlns:ctl="using:ClaudeDo.Ui.Views.Controls"
xmlns:loc="using:ClaudeDo.Ui.Localization"
x:DataType="vm:ConflictResolutionViewModel"
x:Class="ClaudeDo.Ui.Views.Planning.ConflictResolutionView"
Title="{loc:Tr planning.conflict.windowTitle}"
Width="560" SizeToContent="Height" MinWidth="460"
CanResize="True"
WindowDecorations="BorderOnly"
ExtendClientAreaToDecorationsHint="True"
ExtendClientAreaTitleBarHeightHint="-1"
WindowStartupLocation="CenterOwner"
Background="{DynamicResource SurfaceBrush}">
<Window.KeyBindings>
<KeyBinding Gesture="Escape" Command="{Binding AbortCommand}"/>
</Window.KeyBindings>
<ctl:ModalShell Title="{loc:Tr planning.conflict.modalTitle}" CloseCommand="{Binding AbortCommand}">
<ctl:ModalShell.Footer>
<StackPanel Orientation="Horizontal" Spacing="8"
HorizontalAlignment="Right" VerticalAlignment="Center">
<Button Classes="btn" Content="{loc:Tr planning.conflict.openInVsCode}" Command="{Binding OpenInVsCodeCommand}"/>
<Button Classes="btn" Content="{loc:Tr planning.conflict.resolved}" Command="{Binding ContinueCommand}"/>
<Button Classes="btn" Content="{loc:Tr planning.conflict.abort}" Command="{Binding AbortCommand}"/>
</StackPanel>
</ctl:ModalShell.Footer>
<!-- Content -->
<StackPanel Spacing="12" Margin="20,16" MinWidth="520">
<TextBlock Classes="heading"
Text="{Binding SubtaskLabel}"/>
<TextBlock Classes="body" Text="{Binding TargetLabel}"/>
<ItemsControl ItemsSource="{Binding ConflictedFiles}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock Classes="path-mono" Text="{Binding}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<TextBlock Classes="meta" Text="{Binding VsCodeError}" Foreground="{DynamicResource BloodBrush}"
IsVisible="{Binding VsCodeError, Converter={x:Static ObjectConverters.IsNotNull}}"
TextWrapping="Wrap"/>
<TextBlock Classes="meta" Text="{Binding ActionError}" Foreground="{DynamicResource BloodBrush}"
IsVisible="{Binding ActionError, Converter={x:Static ObjectConverters.IsNotNull}}"
TextWrapping="Wrap"/>
</StackPanel>
</ctl:ModalShell>
</Window>

View File

@@ -1,19 +0,0 @@
using Avalonia.Controls;
using ClaudeDo.Ui.ViewModels.Planning;
namespace ClaudeDo.Ui.Views.Planning;
public partial class ConflictResolutionView : Window
{
public ConflictResolutionView()
{
InitializeComponent();
}
protected override void OnDataContextChanged(EventArgs e)
{
base.OnDataContextChanged(e);
if (DataContext is ConflictResolutionViewModel vm)
vm.CloseRequested = Close;
}
}