refactor(diff): single DiffViewer replaces DiffModal + WorktreeModal + PlanningDiff
This commit is contained in:
@@ -0,0 +1,171 @@
|
||||
<Window xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:vm="using:ClaudeDo.Ui.ViewModels.Modals"
|
||||
xmlns:ctl="using:ClaudeDo.Ui.Views.Controls"
|
||||
xmlns:loc="using:ClaudeDo.Ui.Localization"
|
||||
x:Class="ClaudeDo.Ui.Views.Modals.DiffViewerView"
|
||||
x:DataType="vm:DiffViewerViewModel"
|
||||
Title="{loc:Tr modals.diff.windowTitle}"
|
||||
Width="1200" Height="800" MinWidth="700" MinHeight="450"
|
||||
CanResize="True"
|
||||
WindowDecorations="BorderOnly"
|
||||
ExtendClientAreaToDecorationsHint="True"
|
||||
ExtendClientAreaTitleBarHeightHint="-1"
|
||||
WindowStartupLocation="CenterOwner"
|
||||
Background="{DynamicResource SurfaceBrush}">
|
||||
|
||||
<Window.KeyBindings>
|
||||
<KeyBinding Gesture="Escape" Command="{Binding CloseCommand}"/>
|
||||
</Window.KeyBindings>
|
||||
|
||||
<ctl:ModalShell Title="{loc:Tr modals.diff.title}" CloseCommand="{Binding CloseCommand}">
|
||||
<ctl:ModalShell.Footer>
|
||||
<StackPanel Orientation="Horizontal" Spacing="8"
|
||||
HorizontalAlignment="Right" VerticalAlignment="Center">
|
||||
<Button Classes="btn" Content="{loc:Tr modals.diff.merge}"
|
||||
Command="{Binding MergeCommand}"
|
||||
IsVisible="{Binding ShowMerge}"/>
|
||||
</StackPanel>
|
||||
</ctl:ModalShell.Footer>
|
||||
|
||||
<DockPanel>
|
||||
|
||||
<!-- Planning toolbar: combined-mode toggle + warning/loading -->
|
||||
<StackPanel DockPanel.Dock="Top" Orientation="Horizontal" Spacing="8" Margin="16,8,16,0"
|
||||
IsVisible="{Binding IsPlanning}">
|
||||
<ToggleButton Content="{loc:Tr planning.diff.previewCombined}" IsChecked="{Binding IsCombinedMode}"/>
|
||||
<TextBlock Text="{Binding CombinedWarning}"
|
||||
Foreground="{DynamicResource BloodBrush}"
|
||||
VerticalAlignment="Center"
|
||||
IsVisible="{Binding CombinedWarning, Converter={x:Static ObjectConverters.IsNotNull}}"/>
|
||||
<TextBlock Text="{loc:Tr planning.diff.loading}"
|
||||
VerticalAlignment="Center"
|
||||
IsVisible="{Binding IsLoadingCombined}"/>
|
||||
</StackPanel>
|
||||
|
||||
<!-- Body: nav | splitter | diff -->
|
||||
<Grid ColumnDefinitions="280,4,*" Margin="16">
|
||||
|
||||
<!-- Left nav: file tree (Files) OR subtask list (Planning) -->
|
||||
<Border Grid.Column="0" Classes="island">
|
||||
<DockPanel>
|
||||
<Border DockPanel.Dock="Top" Classes="island-header" IsVisible="{Binding !IsPlanning}">
|
||||
<TextBlock Classes="eyebrow" Text="{loc:Tr modals.diff.filesHeader}"/>
|
||||
</Border>
|
||||
<Panel>
|
||||
<!-- Files: folder tree -->
|
||||
<TreeView x:Name="FileTree"
|
||||
ItemsSource="{Binding FileTree}"
|
||||
SelectedItem="{Binding SelectedNode, Mode=TwoWay}"
|
||||
Background="Transparent"
|
||||
BorderThickness="0"
|
||||
IsVisible="{Binding !IsPlanning}">
|
||||
<TreeView.Styles>
|
||||
<Style Selector="TreeViewItem" x:DataType="vm:DiffTreeNodeViewModel">
|
||||
<Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}"/>
|
||||
</Style>
|
||||
</TreeView.Styles>
|
||||
<TreeView.ItemTemplate>
|
||||
<TreeDataTemplate DataType="vm:DiffTreeNodeViewModel" ItemsSource="{Binding Children}">
|
||||
<Border Background="Transparent" Tapped="OnNodeTapped" Cursor="Hand" Padding="0,2">
|
||||
<Grid ColumnDefinitions="Auto,*,Auto">
|
||||
<Border Grid.Column="0" Tag="{Binding StatusCode}" CornerRadius="3" Padding="4,0" Margin="0,0,6,0"
|
||||
VerticalAlignment="Center"
|
||||
IsVisible="{Binding StatusCode, Converter={x:Static StringConverters.IsNotNullOrEmpty}}">
|
||||
<TextBlock Text="{Binding StatusCode}"
|
||||
FontFamily="{DynamicResource MonoFont}" FontSize="{StaticResource FontSizeEyebrow}"
|
||||
Foreground="{DynamicResource TextBrush}"/>
|
||||
</Border>
|
||||
<TextBlock Grid.Column="1" Classes="meta" Text="{Binding Name}"
|
||||
VerticalAlignment="Center" TextTrimming="CharacterEllipsis"/>
|
||||
<StackPanel Grid.Column="2" Orientation="Horizontal" Spacing="4" VerticalAlignment="Center"
|
||||
IsVisible="{Binding ShowStats}">
|
||||
<TextBlock Foreground="{DynamicResource MossBrightBrush}" FontSize="{StaticResource FontSizeEyebrow}"
|
||||
Text="{Binding Additions, StringFormat='+{0}'}"/>
|
||||
<TextBlock Foreground="{DynamicResource BloodBrush}" FontSize="{StaticResource FontSizeEyebrow}"
|
||||
Text="{Binding Deletions, StringFormat='−{0}'}"/>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Border>
|
||||
</TreeDataTemplate>
|
||||
</TreeView.ItemTemplate>
|
||||
</TreeView>
|
||||
|
||||
<!-- Planning: subtask list -->
|
||||
<ListBox ItemsSource="{Binding Subtasks}"
|
||||
SelectedItem="{Binding SelectedSubtask}"
|
||||
IsEnabled="{Binding !IsCombinedMode}"
|
||||
IsVisible="{Binding IsPlanning}"
|
||||
Background="Transparent"
|
||||
BorderThickness="0"
|
||||
ScrollViewer.HorizontalScrollBarVisibility="Disabled">
|
||||
<ListBox.ItemTemplate>
|
||||
<DataTemplate x:DataType="vm:SubtaskDiffRow">
|
||||
<Border Padding="10,8" Background="Transparent">
|
||||
<StackPanel Spacing="2">
|
||||
<TextBlock Classes="title" Text="{Binding Title}" TextTrimming="CharacterEllipsis"/>
|
||||
<TextBlock Classes="meta" Text="{Binding DiffStat}"/>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
</DataTemplate>
|
||||
</ListBox.ItemTemplate>
|
||||
</ListBox>
|
||||
</Panel>
|
||||
</DockPanel>
|
||||
</Border>
|
||||
|
||||
<GridSplitter Grid.Column="1" ResizeDirection="Columns" Background="{DynamicResource LineBrush}"/>
|
||||
|
||||
<!-- Right: diff content (Files per-file pane OR Planning flat diff) -->
|
||||
<Border Grid.Column="2" Classes="island">
|
||||
<Panel>
|
||||
|
||||
<!-- Files mode: per-file pane with header + placeholders -->
|
||||
<DockPanel IsVisible="{Binding !IsPlanning}">
|
||||
<Border DockPanel.Dock="Top" Classes="island-header"
|
||||
IsVisible="{Binding SelectedFile, Converter={x:Static ObjectConverters.IsNotNull}}">
|
||||
<Grid ColumnDefinitions="Auto,*">
|
||||
<Border Grid.Column="0" Tag="{Binding SelectedFile.StatusCode}"
|
||||
CornerRadius="3" Padding="4,0" Margin="0,0,8,0" VerticalAlignment="Center">
|
||||
<TextBlock Text="{Binding SelectedFile.StatusCode}"
|
||||
FontFamily="{DynamicResource MonoFont}" FontSize="{StaticResource FontSizeEyebrow}"
|
||||
Foreground="{DynamicResource TextBrush}"/>
|
||||
</Border>
|
||||
<TextBlock Grid.Column="1" Classes="path-mono" Text="{Binding SelectedFile.Path}"
|
||||
VerticalAlignment="Center" TextTrimming="PrefixCharacterEllipsis"/>
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
<Grid Background="{DynamicResource VoidBrush}">
|
||||
<TextBlock Classes="body" Text="{Binding StatusMessage}"
|
||||
IsVisible="{Binding StatusMessage, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"
|
||||
HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||||
<TextBlock Classes="body" Text="{loc:Tr modals.diff.binary}"
|
||||
Foreground="{DynamicResource TextMuteBrush}"
|
||||
IsVisible="{Binding SelectedFile.IsBinary}"
|
||||
HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||||
<TextBlock Classes="body" Text="{loc:Tr modals.diff.empty}"
|
||||
Foreground="{DynamicResource TextMuteBrush}"
|
||||
IsVisible="{Binding SelectedFile.IsEmptyContent}"
|
||||
HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||||
<ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto"
|
||||
IsVisible="{Binding SelectedFile.HasLines}">
|
||||
<ctl:DiffLinesView Lines="{Binding SelectedFile.Lines}"/>
|
||||
</ScrollViewer>
|
||||
</Grid>
|
||||
</DockPanel>
|
||||
|
||||
<!-- Planning mode: flat aggregate/combined diff -->
|
||||
<Grid Background="{DynamicResource VoidBrush}" IsVisible="{Binding IsPlanning}">
|
||||
<ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
|
||||
<ctl:DiffLinesView Lines="{Binding DiffLines}"/>
|
||||
</ScrollViewer>
|
||||
</Grid>
|
||||
|
||||
</Panel>
|
||||
</Border>
|
||||
</Grid>
|
||||
|
||||
</DockPanel>
|
||||
</ctl:ModalShell>
|
||||
</Window>
|
||||
Reference in New Issue
Block a user