feature: show MINE and THEIRS revision in merge conflict editor

- Rename some resources about conflicts
- Rename `MergeConflictEditor.XXXDiffLines` to `MergeConflictEditor.XXXLines`
- It's not necessary to show commit info in tooltip for conflict revisions
- New UI/UX for merge conflict editor

Signed-off-by: leo <longshuang@msn.cn>
This commit is contained in:
leo
2026-02-03 12:45:39 +08:00
parent 1038855a8f
commit 1d80d001dd
8 changed files with 172 additions and 125 deletions

View File

@@ -11,7 +11,9 @@
<Color x:Key="Color.Badge">#FFB0CEE8</Color>
<Color x:Key="Color.BadgeFG">#FF1F1F1F</Color>
<Color x:Key="Color.Conflict">#FF836C2E</Color>
<Color x:Key="Color.ConflictForeground">#FFFFFFFF</Color>
<Color x:Key="Color.Conflict.Foreground">#FFFFFFFF</Color>
<Color x:Key="Color.Conflict.MineBG">#400078D7</Color>
<Color x:Key="Color.Conflict.TheirsBG">#40FF8C00</Color>
<Color x:Key="Color.Border0">#FFCFCFCF</Color>
<Color x:Key="Color.Border1">#FF898989</Color>
<Color x:Key="Color.Border2">#FFCFCFCF</Color>
@@ -24,11 +26,6 @@
<Color x:Key="Color.Diff.DeletedBG">#80FF9797</Color>
<Color x:Key="Color.Diff.AddedHighlight">#A7E1A7</Color>
<Color x:Key="Color.Diff.DeletedHighlight">#F19B9D</Color>
<Color x:Key="Color.Diff.MineBG">#400078D7</Color>
<Color x:Key="Color.Diff.TheirsBG">#40FF8C00</Color>
<Color x:Key="Color.Diff.MineHeader">#FF0078D7</Color>
<Color x:Key="Color.Diff.TheirsHeader">#FFFF8C00</Color>
<Color x:Key="Color.Diff.CurrentConflict">#40FFFF00</Color>
<Color x:Key="Color.Link">#0000EE</Color>
<Color x:Key="Color.InlineCode">#FFE4E4E4</Color>
<Color x:Key="Color.InlineCodeFG">Black</Color>
@@ -44,7 +41,9 @@
<Color x:Key="Color.Badge">#FF8F8F8F</Color>
<Color x:Key="Color.BadgeFG">#FFDDDDDD</Color>
<Color x:Key="Color.Conflict">#FFFAFAD2</Color>
<Color x:Key="Color.ConflictForeground">#FF252525</Color>
<Color x:Key="Color.Conflict.Foreground">#FF252525</Color>
<Color x:Key="Color.Conflict.MineBG">#400078D7</Color>
<Color x:Key="Color.Conflict.TheirsBG">#40FF8C00</Color>
<Color x:Key="Color.Border0">#FF181818</Color>
<Color x:Key="Color.Border1">#FF7C7C7C</Color>
<Color x:Key="Color.Border2">#FF404040</Color>
@@ -57,11 +56,6 @@
<Color x:Key="Color.Diff.DeletedBG">#C0633F3E</Color>
<Color x:Key="Color.Diff.AddedHighlight">#A0308D3C</Color>
<Color x:Key="Color.Diff.DeletedHighlight">#A09F4247</Color>
<Color x:Key="Color.Diff.MineBG">#400078D7</Color>
<Color x:Key="Color.Diff.TheirsBG">#40FF8C00</Color>
<Color x:Key="Color.Diff.MineHeader">#FF0078D7</Color>
<Color x:Key="Color.Diff.TheirsHeader">#FFFF8C00</Color>
<Color x:Key="Color.Diff.CurrentConflict">#40FFFF00</Color>
<Color x:Key="Color.Link">#4DAAFC</Color>
<Color x:Key="Color.InlineCode">#FF383838</Color>
<Color x:Key="Color.InlineCodeFG">#FFF0F0F0</Color>
@@ -77,7 +71,9 @@
<SolidColorBrush x:Key="Brush.Badge" Color="{DynamicResource Color.Badge}"/>
<SolidColorBrush x:Key="Brush.BadgeFG" Color="{DynamicResource Color.BadgeFG}"/>
<SolidColorBrush x:Key="Brush.Conflict" Color="{DynamicResource Color.Conflict}"/>
<SolidColorBrush x:Key="Brush.ConflictForeground" Color="{DynamicResource Color.ConflictForeground}"/>
<SolidColorBrush x:Key="Brush.Conflict.Foreground" Color="{DynamicResource Color.Conflict.Foreground}"/>
<SolidColorBrush x:Key="Brush.Conflict.MineBG" Color="{DynamicResource Color.Conflict.MineBG}"/>
<SolidColorBrush x:Key="Brush.Conflict.TheirsBG" Color="{DynamicResource Color.Conflict.TheirsBG}"/>
<SolidColorBrush x:Key="Brush.Border0" Color="{DynamicResource Color.Border0}"/>
<SolidColorBrush x:Key="Brush.Border1" Color="{DynamicResource Color.Border1}"/>
<SolidColorBrush x:Key="Brush.Border2" Color="{DynamicResource Color.Border2}"/>
@@ -92,11 +88,6 @@
<SolidColorBrush x:Key="Brush.Diff.DeletedBG" Color="{DynamicResource Color.Diff.DeletedBG}"/>
<SolidColorBrush x:Key="Brush.Diff.AddedHighlight" Color="{DynamicResource Color.Diff.AddedHighlight}"/>
<SolidColorBrush x:Key="Brush.Diff.DeletedHighlight" Color="{DynamicResource Color.Diff.DeletedHighlight}"/>
<SolidColorBrush x:Key="Brush.Diff.MineBG" Color="{DynamicResource Color.Diff.MineBG}"/>
<SolidColorBrush x:Key="Brush.Diff.TheirsBG" Color="{DynamicResource Color.Diff.TheirsBG}"/>
<SolidColorBrush x:Key="Brush.Diff.MineHeader" Color="{DynamicResource Color.Diff.MineHeader}"/>
<SolidColorBrush x:Key="Brush.Diff.TheirsHeader" Color="{DynamicResource Color.Diff.TheirsHeader}"/>
<SolidColorBrush x:Key="Brush.Diff.CurrentConflict" Color="{DynamicResource Color.Diff.CurrentConflict}"/>
<SolidColorBrush x:Key="Brush.Link" Color="{DynamicResource Color.Link}"/>
<SolidColorBrush x:Key="Brush.InlineCode" Color="{DynamicResource Color.InlineCode}"/>
<SolidColorBrush x:Key="Brush.InlineCodeFG" Color="{DynamicResource Color.InlineCodeFG}"/>

View File

@@ -52,14 +52,14 @@ namespace SourceGit.ViewModels
if (CanMerge)
IsResolved = new Commands.IsConflictResolved(repo.FullPath, change).GetResult();
var head = new Commands.QuerySingleCommit(repo.FullPath, "HEAD").GetResult();
_head = new Commands.QuerySingleCommit(repo.FullPath, "HEAD").GetResult();
(Mine, Theirs) = wc.InProgressContext switch
{
CherryPickInProgress cherryPick => (head, cherryPick.Head),
CherryPickInProgress cherryPick => (_head, cherryPick.Head),
RebaseInProgress rebase => (rebase.Onto, rebase.StoppedAt),
RevertInProgress revert => (head, revert.Head),
MergeInProgress merge => (head, merge.Source),
_ => (head, (object)"Stash or Patch"),
RevertInProgress revert => (_head, revert.Head),
MergeInProgress merge => (_head, merge.Source),
_ => (_head, (object)"Stash or Patch"),
};
}
@@ -76,7 +76,7 @@ namespace SourceGit.ViewModels
public async Task MergeAsync()
{
if (CanMerge)
await App.ShowDialog(new MergeConflictEditor(_repo, _change.Path));
await App.ShowDialog(new MergeConflictEditor(_repo, _head, _change.Path));
}
public async Task MergeExternalAsync()
@@ -87,6 +87,7 @@ namespace SourceGit.ViewModels
private Repository _repo = null;
private WorkingCopy _wc = null;
private Models.Commit _head = null;
private Models.Change _change = null;
}
}

View File

@@ -16,34 +16,44 @@ namespace SourceGit.ViewModels
get => _filePath;
}
public object Mine
{
get;
}
public object Theirs
{
get;
}
public string Error
{
get => _error;
private set => SetProperty(ref _error, value);
}
public List<Models.ConflictLine> OursDiffLines
public List<Models.ConflictLine> OursLines
{
get => _oursDiffLines;
private set => SetProperty(ref _oursDiffLines, value);
get => _oursLines;
private set => SetProperty(ref _oursLines, value);
}
public List<Models.ConflictLine> TheirsDiffLines
public List<Models.ConflictLine> TheirsLines
{
get => _theirsDiffLines;
private set => SetProperty(ref _theirsDiffLines, value);
get => _theirsLines;
private set => SetProperty(ref _theirsLines, value);
}
public List<Models.ConflictLine> ResultDiffLines
public List<Models.ConflictLine> ResultLines
{
get => _resultDiffLines;
private set => SetProperty(ref _resultDiffLines, value);
get => _resultLines;
private set => SetProperty(ref _resultLines, value);
}
public int DiffMaxLineNumber
public int MaxLineNumber
{
get => _diffMaxLineNumber;
private set => SetProperty(ref _diffMaxLineNumber, value);
get => _maxLineNumber;
private set => SetProperty(ref _maxLineNumber, value);
}
public int UnsolvedCount
@@ -69,11 +79,20 @@ namespace SourceGit.ViewModels
get => _conflictRegions;
}
public MergeConflictEditor(Repository repo, string filePath)
public MergeConflictEditor(Repository repo, Models.Commit head, string filePath)
{
_repo = repo;
_filePath = filePath;
(Mine, Theirs) = repo.InProgressContext switch
{
CherryPickInProgress cherryPick => (head, cherryPick.Head),
RebaseInProgress rebase => (rebase.Onto, rebase.StoppedAt),
RevertInProgress revert => (head, revert.Head),
MergeInProgress merge => (head, merge.Source),
_ => (head, (object)"Stash or Patch"),
};
var workingCopyPath = Path.Combine(_repo.FullPath, _filePath);
var workingCopyContent = string.Empty;
if (File.Exists(workingCopyPath))
@@ -291,10 +310,9 @@ namespace SourceGit.ViewModels
}
}
var maxLineNumber = Math.Max(oursLineNumber, theirsLineNumber);
DiffMaxLineNumber = maxLineNumber;
OursDiffLines = oursLines;
TheirsDiffLines = theirsLines;
MaxLineNumber = Math.Max(oursLineNumber, theirsLineNumber);
OursLines = oursLines;
TheirsLines = theirsLines;
}
private void RefreshDisplayData()
@@ -302,9 +320,9 @@ namespace SourceGit.ViewModels
var resultLines = new List<Models.ConflictLine>();
_lineStates.Clear();
if (_oursDiffLines == null || _oursDiffLines.Count == 0)
if (_oursLines == null || _oursLines.Count == 0)
{
ResultDiffLines = resultLines;
ResultLines = resultLines;
return;
}
@@ -312,7 +330,7 @@ namespace SourceGit.ViewModels
int currentLine = 0;
int conflictIdx = 0;
while (currentLine < _oursDiffLines.Count)
while (currentLine < _oursLines.Count)
{
// Check if we're at a conflict region
Models.ConflictRegion currentRegion = null;
@@ -424,7 +442,7 @@ namespace SourceGit.ViewModels
}
else
{
var oursLine = _oursDiffLines[currentLine];
var oursLine = _oursLines[currentLine];
resultLines.Add(new(oursLine.Type, oursLine.Content, resultLineNumber));
_lineStates.Add(Models.ConflictLineState.Normal);
resultLineNumber++;
@@ -433,7 +451,7 @@ namespace SourceGit.ViewModels
}
SelectedChunk = null;
ResultDiffLines = resultLines;
ResultLines = resultLines;
var unsolved = new List<int>();
for (var i = 0; i < _conflictRegions.Count; i++)
@@ -450,10 +468,10 @@ namespace SourceGit.ViewModels
private readonly string _filePath;
private string _originalContent = string.Empty;
private int _unsolvedCount = 0;
private int _diffMaxLineNumber = 0;
private List<Models.ConflictLine> _oursDiffLines = [];
private List<Models.ConflictLine> _theirsDiffLines = [];
private List<Models.ConflictLine> _resultDiffLines = [];
private int _maxLineNumber = 0;
private List<Models.ConflictLine> _oursLines = [];
private List<Models.ConflictLine> _theirsLines = [];
private List<Models.ConflictLine> _resultLines = [];
private List<Models.ConflictRegion> _conflictRegions = [];
private List<Models.ConflictLineState> _lineStates = [];
private Vector _scrollOffset = Vector.Zero;

View File

@@ -36,23 +36,7 @@
Foreground="DarkOrange"
TextDecorations="Underline"
Cursor="Hand"
PointerPressed="OnPressedSHA"
ToolTip.Tip="{Binding}"
ToolTip.ShowDelay="0">
<TextBlock.DataTemplates>
<DataTemplate DataType="m:Commit">
<StackPanel MinWidth="400" Orientation="Vertical">
<Grid ColumnDefinitions="Auto,*,Auto">
<v:Avatar Grid.Column="0" Width="16" Height="16" VerticalAlignment="Center" IsHitTestVisible="False" User="{Binding Author}"/>
<TextBlock Grid.Column="1" Text="{Binding Author.Name}" Margin="8,0,0,0"/>
<TextBlock Grid.Column="2" Text="{Binding CommitterTimeStr}" Foreground="{DynamicResource Brush.FG2}" Margin="8,0,0,0"/>
</Grid>
<TextBlock Margin="0,8,0,0" Text="{Binding Subject}" TextWrapping="Wrap"/>
</StackPanel>
</DataTemplate>
</TextBlock.DataTemplates>
</TextBlock>
PointerPressed="OnPressedSHA"/>
<TextBlock Margin="4,0,0,0" Text="{Binding Subject}"/>
</StackPanel>
</DataTemplate>

View File

@@ -17,7 +17,7 @@
<!-- TitleBar -->
<Grid Grid.Row="0" Height="28" IsVisible="{Binding !#ThisControl.UseSystemWindowFrame}">
<Border Background="{DynamicResource Brush.TitleBar}"
BorderThickness="0,0,0,1" BorderBrush="{DynamicResource Brush.Border2}"
BorderThickness="0,0,0,1" BorderBrush="{DynamicResource Brush.Border0}"
DoubleTapped="MaximizeOrRestoreWindow"
PointerPressed="BeginMoveWindow"/>
@@ -36,7 +36,7 @@
</Grid>
<!-- Toolbar -->
<Border Grid.Row="1" Padding="8,0" BorderThickness="0,0,0,1" BorderBrush="{DynamicResource Brush.Border2}">
<Border Grid.Row="1" Padding="8,0" Background="{DynamicResource Brush.ToolBar}" BorderThickness="0,0,0,1" BorderBrush="{DynamicResource Brush.Border2}">
<Grid ColumnDefinitions="Auto,*,Auto">
<!-- File Path -->
<StackPanel Grid.Column="0" Orientation="Horizontal" VerticalAlignment="Center">
@@ -70,11 +70,13 @@
<Rectangle Width="1" Fill="{DynamicResource Brush.Border2}" Margin="4,6"/>
<!-- Save -->
<Button Classes="flat primary"
Margin="0,2" Padding="6,3"
Content="{DynamicResource Text.MergeConflictEditor.SaveAndStage}"
<Button Classes="icon_button"
Margin="0" Padding="0"
Click="OnSaveAndStage"
HotKey="{OnPlatform Ctrl+S, macOS=⌘+S}"/>
HotKey="{OnPlatform Ctrl+S, macOS=⌘+S}"
ToolTip.Tip="{DynamicResource Text.MergeConflictEditor.SaveAndStage}">
<Path Width="16" Height="16" Data="{StaticResource Icons.Save}"/>
</Button>
</StackPanel>
</Grid>
</Border>
@@ -85,22 +87,49 @@
<Grid Grid.Row="0" Grid.Column="0" ColumnDefinitions="*,*" Margin="4,4,4,2">
<!-- Mine (Ours) Panel -->
<Border Grid.Column="0" Margin="0,0,2,0">
<Grid RowDefinitions="Auto,*" Background="{DynamicResource Brush.Contents}">
<Border Grid.Row="0" Padding="8,4" Background="{DynamicResource Brush.Diff.MineHeader}">
<TextBlock Text="{DynamicResource Text.MergeConflictEditor.Mine}"
Foreground="White"
FontWeight="Bold"/>
<Grid RowDefinitions="26,*">
<Border Grid.Row="0" Padding="8,0" Background="{DynamicResource Brush.Popup}" BorderThickness="1,1,1,0" BorderBrush="{DynamicResource Brush.Border2}">
<Grid ColumnDefinitions="Auto,*">
<TextBlock Grid.Column="0"
Text="{DynamicResource Text.MergeConflictEditor.Mine}"
FontWeight="Bold"
VerticalAlignment="Center"/>
<ContentControl Grid.Column="1" Margin="8,0,0,0" Content="{Binding Mine, Mode=OneWay}">
<ContentControl.DataTemplates>
<DataTemplate DataType="m:Commit">
<StackPanel Orientation="Horizontal">
<v:CommitRefsPresenter Foreground="{DynamicResource Brush.FG1}"
FontSize="12"
VerticalAlignment="Center"
UseGraphColor="False"/>
<TextBlock Margin="4,0,0,0"
Text="{Binding SHA, Converter={x:Static c:StringConverters.ToShortSHA}}"
Foreground="DarkOrange"
TextDecorations="Underline"
Cursor="Hand"/>
<TextBlock Margin="4,0,0,0" Text="{Binding Subject}"/>
</StackPanel>
</DataTemplate>
<DataTemplate DataType="x:String">
<StackPanel Orientation="Horizontal">
<Path Width="12" Height="12" Data="{StaticResource Icons.Changes}"/>
<TextBlock Margin="4,0,0,0" Text="{Binding}"/>
</StackPanel>
</DataTemplate>
</ContentControl.DataTemplates>
</ContentControl>
</Grid>
</Border>
<Grid Grid.Row="1">
<Grid Grid.Row="1" Background="{DynamicResource Brush.Contents}">
<v:MergeConflictTextPresenter x:Name="OursPresenter"
PanelType="Ours"
Lines="{Binding OursDiffLines, Mode=OneWay}"
MaxLineNumber="{Binding DiffMaxLineNumber}"
Lines="{Binding OursLines, Mode=OneWay}"
MaxLineNumber="{Binding MaxLineNumber}"
FileName="{Binding FilePath}"
SelectedChunk="{Binding SelectedChunk}"
FontFamily="{DynamicResource Fonts.Monospace}"
TheirsContentBackground="{DynamicResource Brush.Diff.TheirsBG}"
OursContentBackground="{DynamicResource Brush.Diff.MineBG}"
TheirsContentBackground="{DynamicResource Brush.Conflict.TheirsBG}"
OursContentBackground="{DynamicResource Brush.Conflict.MineBG}"
BorderThickness="1"
BorderBrush="{DynamicResource Brush.Border2}"/>
<Border x:Name="MinePopup"
@@ -124,22 +153,49 @@
<!-- Theirs Panel -->
<Border Grid.Column="1" Margin="2,0,0,0">
<Grid RowDefinitions="Auto,*" Background="{DynamicResource Brush.Contents}">
<Border Grid.Row="0" Padding="8,4" Background="{DynamicResource Brush.Diff.TheirsHeader}">
<TextBlock Text="{DynamicResource Text.MergeConflictEditor.Theirs}"
Foreground="White"
FontWeight="Bold"/>
<Grid RowDefinitions="26,*">
<Border Grid.Row="0" Padding="8,0" Background="{DynamicResource Brush.Popup}" BorderThickness="1,1,1,0" BorderBrush="{DynamicResource Brush.Border2}">
<Grid ColumnDefinitions="Auto,*">
<TextBlock Grid.Column="0"
Text="{DynamicResource Text.MergeConflictEditor.Theirs}"
FontWeight="Bold"
VerticalAlignment="Center"/>
<ContentControl Grid.Column="1" Margin="8,0,0,0" Content="{Binding Theirs, Mode=OneWay}">
<ContentControl.DataTemplates>
<DataTemplate DataType="m:Commit">
<StackPanel Orientation="Horizontal">
<v:CommitRefsPresenter Foreground="{DynamicResource Brush.FG1}"
FontSize="12"
VerticalAlignment="Center"
UseGraphColor="False"/>
<TextBlock Margin="4,0,0,0"
Text="{Binding SHA, Converter={x:Static c:StringConverters.ToShortSHA}}"
Foreground="DarkOrange"
TextDecorations="Underline"
Cursor="Hand"/>
<TextBlock Margin="4,0,0,0" Text="{Binding Subject}"/>
</StackPanel>
</DataTemplate>
<DataTemplate DataType="x:String">
<StackPanel Orientation="Horizontal">
<Path Width="12" Height="12" Data="{StaticResource Icons.Changes}"/>
<TextBlock Margin="4,0,0,0" Text="{Binding}"/>
</StackPanel>
</DataTemplate>
</ContentControl.DataTemplates>
</ContentControl>
</Grid>
</Border>
<Grid Grid.Row="1">
<Grid Grid.Row="1" Background="{DynamicResource Brush.Contents}">
<v:MergeConflictTextPresenter x:Name="TheirsPresenter"
PanelType="Theirs"
Lines="{Binding TheirsDiffLines, Mode=OneWay}"
MaxLineNumber="{Binding DiffMaxLineNumber}"
Lines="{Binding TheirsLines, Mode=OneWay}"
MaxLineNumber="{Binding MaxLineNumber}"
FileName="{Binding FilePath}"
SelectedChunk="{Binding SelectedChunk}"
FontFamily="{DynamicResource Fonts.Monospace}"
TheirsContentBackground="{DynamicResource Brush.Diff.TheirsBG}"
OursContentBackground="{DynamicResource Brush.Diff.MineBG}"
TheirsContentBackground="{DynamicResource Brush.Conflict.TheirsBG}"
OursContentBackground="{DynamicResource Brush.Conflict.MineBG}"
BorderThickness="1"
BorderBrush="{DynamicResource Brush.Border2}"/>
<Border x:Name="TheirsPopup"
@@ -164,20 +220,20 @@
<!-- Result Panel -->
<Border Grid.Row="1" Grid.Column="0" Margin="4,2,4,4">
<Grid RowDefinitions="Auto,*" Background="{DynamicResource Brush.Contents}">
<Border Grid.Row="0" Padding="8,4" Background="{DynamicResource Brush.ToolBar}" BorderThickness="1,1,1,0" BorderBrush="{DynamicResource Brush.Border2}">
<TextBlock Text="{DynamicResource Text.MergeConflictEditor.Result}" FontWeight="Bold"/>
<Grid RowDefinitions="26,*">
<Border Grid.Row="0" Padding="8,0" Background="{DynamicResource Brush.Popup}" BorderThickness="1,1,1,0" BorderBrush="{DynamicResource Brush.Border2}">
<TextBlock Text="{DynamicResource Text.MergeConflictEditor.Result}" FontWeight="Bold" VerticalAlignment="Center"/>
</Border>
<Grid Grid.Row="1">
<Grid Grid.Row="1" Background="{DynamicResource Brush.Contents}">
<v:MergeConflictTextPresenter x:Name="ResultPresenter"
PanelType="Result"
Lines="{Binding ResultDiffLines, Mode=OneWay}"
MaxLineNumber="{Binding DiffMaxLineNumber}"
Lines="{Binding ResultLines, Mode=OneWay}"
MaxLineNumber="{Binding MaxLineNumber}"
FileName="{Binding FilePath}"
SelectedChunk="{Binding SelectedChunk}"
FontFamily="{DynamicResource Fonts.Monospace}"
TheirsContentBackground="{DynamicResource Brush.Diff.TheirsBG}"
OursContentBackground="{DynamicResource Brush.Diff.MineBG}"
TheirsContentBackground="{DynamicResource Brush.Conflict.TheirsBG}"
OursContentBackground="{DynamicResource Brush.Conflict.MineBG}"
BorderThickness="1"
BorderBrush="{DynamicResource Brush.Border2}"/>
<Border x:Name="ResultPopup"
@@ -207,17 +263,11 @@
<Button.Flyout>
<MenuFlyout Placement="BottomEdgeAlignedLeft">
<MenuItem Command="{Binding Resolve}" CommandParameter="{x:Static m:ConflictResolution.UseBothMineFirst}">
<MenuItem.Icon>
<Path Width="12" Height="12" Data="{StaticResource Icons.February}" Fill="{DynamicResource Brush.Diff.MineHeader}"/>
</MenuItem.Icon>
<MenuItem.Header>
<TextBlock Text="{DynamicResource Text.MergeConflictEditor.AcceptBoth.MineFirst}"/>
</MenuItem.Header>
</MenuItem>
<MenuItem Command="{Binding Resolve}" CommandParameter="{x:Static m:ConflictResolution.UseBothTheirsFirst}">
<MenuItem.Icon>
<Path Width="12" Height="12" Data="{StaticResource Icons.February}" Fill="{DynamicResource Brush.Diff.TheirsHeader}"/>
</MenuItem.Icon>
<MenuItem.Header>
<TextBlock Text="{DynamicResource Text.MergeConflictEditor.AcceptBoth.TheirsFirst}"/>
</MenuItem.Header>
@@ -248,8 +298,8 @@
<!-- Minimap -->
<Border Grid.Row="0" Grid.RowSpan="2" Grid.Column="1"
Margin="0,0,4,4"
BorderThickness="1,0,1,1" BorderBrush="{DynamicResource Brush.Border2}">
Margin="0,4,4,4"
BorderThickness="1" BorderBrush="{DynamicResource Brush.Border2}">
<v:MergeConflictMinimap DisplayRange="{Binding #ResultPresenter.DisplayRange, Mode=OneWay}"
UnsolvedCount="{Binding UnsolvedCount, Mode=OneWay}"/>
</Border>

View File

@@ -347,6 +347,8 @@ namespace SourceGit.Views
Models.TextMateHelper.SetThemeByApp(_textMate);
else if (change.Property == SelectedChunkProperty)
TextArea.TextView.InvalidateVisual();
else if (change.Property == MaxLineNumberProperty)
TextArea.LeftMargins[0].InvalidateMeasure();
}
private void UpdateContent()
@@ -562,7 +564,7 @@ namespace SourceGit.Views
if (DataContext is not ViewModels.MergeConflictEditor vm)
return;
var total = vm.OursDiffLines.Count;
var total = vm.OursLines.Count;
var unitHeight = Bounds.Height / (total * 1.0);
var conflicts = vm.ConflictRegions;
var blockBGs = new SolidColorBrush[] { new SolidColorBrush(Colors.Red, 0.6), new SolidColorBrush(Colors.Green, 0.6) };
@@ -607,7 +609,7 @@ namespace SourceGit.Views
if (DataContext is not ViewModels.MergeConflictEditor vm)
return;
var total = vm.OursDiffLines.Count;
var total = vm.OursLines.Count;
var range = DisplayRange;
if (range == null || range.End == 0)
return;
@@ -684,7 +686,7 @@ namespace SourceGit.Views
if (IsLoaded && DataContext is ViewModels.MergeConflictEditor vm && vm.UnsolvedCount > 0)
{
var view = OursPresenter.TextArea?.TextView;
var lines = vm.OursDiffLines;
var lines = vm.OursLines;
var minY = double.MaxValue;
var minLineIdx = lines.Count;
if (view is { VisualLinesValid: true })
@@ -727,7 +729,7 @@ namespace SourceGit.Views
if (IsLoaded && DataContext is ViewModels.MergeConflictEditor vm && vm.UnsolvedCount > 0)
{
var view = OursPresenter.TextArea?.TextView;
var lines = vm.OursDiffLines;
var lines = vm.OursLines;
var maxY = 0.0;
var maxLineIdx = 0;
if (view is { VisualLinesValid: true })

View File

@@ -652,8 +652,8 @@
<DataTemplate DataType="vm:CherryPickInProgress">
<Grid ColumnDefinitions="*,Auto">
<StackPanel Grid.Column="0" Orientation="Horizontal">
<TextBlock FontWeight="Bold" Foreground="{DynamicResource Brush.ConflictForeground}" Text="{DynamicResource Text.InProgress.CherryPick}"/>
<TextBlock FontWeight="Bold" Margin="4,0,0,0" Foreground="{DynamicResource Brush.ConflictForeground}" Text="{DynamicResource Text.InProgress.CherryPick.Head}"/>
<TextBlock FontWeight="Bold" Foreground="{DynamicResource Brush.Conflict.Foreground}" Text="{DynamicResource Text.InProgress.CherryPick}"/>
<TextBlock FontWeight="Bold" Margin="4,0,0,0" Foreground="{DynamicResource Brush.Conflict.Foreground}" Text="{DynamicResource Text.InProgress.CherryPick.Head}"/>
<TextBlock FontWeight="Bold" Margin="4,0,0,0" Foreground="DarkOrange" Text="{Binding Head.SHA, Converter={x:Static c:StringConverters.ToShortSHA}}" ToolTip.Tip="{Binding Head}"/>
</StackPanel>
@@ -664,8 +664,8 @@
<DataTemplate DataType="vm:RebaseInProgress">
<Grid ColumnDefinitions="*,Auto">
<StackPanel Grid.Column="0" Orientation="Horizontal">
<TextBlock FontWeight="Bold" Foreground="{DynamicResource Brush.ConflictForeground}" Text="{DynamicResource Text.InProgress.Rebase}"/>
<TextBlock FontWeight="Bold" Margin="4,0,0,0" Foreground="{DynamicResource Brush.ConflictForeground}"
<TextBlock FontWeight="Bold" Foreground="{DynamicResource Brush.Conflict.Foreground}" Text="{DynamicResource Text.InProgress.Rebase}"/>
<TextBlock FontWeight="Bold" Margin="4,0,0,0" Foreground="{DynamicResource Brush.Conflict.Foreground}"
Text="{DynamicResource Text.InProgress.Rebase.StoppedAt}"
IsVisible="{Binding StoppedAt, Converter={x:Static ObjectConverters.IsNotNull}}" />
<TextBlock FontWeight="Bold" Margin="4,0,0,0" Foreground="DarkOrange"
@@ -683,8 +683,8 @@
<DataTemplate DataType="vm:RevertInProgress">
<Grid ColumnDefinitions="*,Auto">
<StackPanel Grid.Column="0" Orientation="Horizontal">
<TextBlock FontWeight="Bold" Foreground="{DynamicResource Brush.ConflictForeground}" Text="{DynamicResource Text.InProgress.Revert}"/>
<TextBlock FontWeight="Bold" Margin="4,0,0,0" Foreground="{DynamicResource Brush.ConflictForeground}" Text="{DynamicResource Text.InProgress.Revert.Head}"/>
<TextBlock FontWeight="Bold" Foreground="{DynamicResource Brush.Conflict.Foreground}" Text="{DynamicResource Text.InProgress.Revert}"/>
<TextBlock FontWeight="Bold" Margin="4,0,0,0" Foreground="{DynamicResource Brush.Conflict.Foreground}" Text="{DynamicResource Text.InProgress.Revert.Head}"/>
<TextBlock FontWeight="Bold" Margin="4,0,0,0" Foreground="DarkOrange" Text="{Binding Head.SHA, Converter={x:Static c:StringConverters.ToShortSHA}}" ToolTip.Tip="{Binding Head}"/>
</StackPanel>
@@ -694,10 +694,10 @@
<DataTemplate DataType="vm:MergeInProgress">
<StackPanel Orientation="Horizontal">
<TextBlock FontWeight="Bold" Foreground="{DynamicResource Brush.ConflictForeground}" Text="{DynamicResource Text.InProgress.Merge}"/>
<TextBlock FontWeight="Bold" Margin="4,0,0,0" Foreground="{DynamicResource Brush.ConflictForeground}" Text="{DynamicResource Text.InProgress.Merge.Operating}"/>
<TextBlock FontWeight="Bold" Foreground="{DynamicResource Brush.Conflict.Foreground}" Text="{DynamicResource Text.InProgress.Merge}"/>
<TextBlock FontWeight="Bold" Margin="4,0,0,0" Foreground="{DynamicResource Brush.Conflict.Foreground}" Text="{DynamicResource Text.InProgress.Merge.Operating}"/>
<TextBlock FontWeight="Bold" Margin="4,0,0,0" Foreground="DarkOrange" Text="{Binding SourceName}" ToolTip.Tip="{Binding Source}"/>
<TextBlock FontWeight="Bold" Margin="4,0,0,0" Foreground="{DynamicResource Brush.ConflictForeground}" Text="→"/>
<TextBlock FontWeight="Bold" Margin="4,0,0,0" Foreground="{DynamicResource Brush.Conflict.Foreground}" Text="→"/>
<TextBlock FontWeight="Bold" Margin="4,0,0,0" Foreground="DarkOrange" Text="{Binding Current}"/>
</StackPanel>
</DataTemplate>
@@ -730,14 +730,14 @@
<TextBlock Grid.Column="0"
FontWeight="Bold"
Margin="8,0"
Foreground="{DynamicResource Brush.ConflictForeground}"
Foreground="{DynamicResource Brush.Conflict.Foreground}"
Text="{DynamicResource Text.Bisect.WaitingForRange}"
IsVisible="{Binding BisectState, Converter={x:Static ObjectConverters.Equal}, ConverterParameter={x:Static m:BisectState.WaitingForRange}}"/>
<TextBlock Grid.Column="0"
FontWeight="Bold"
Margin="8,0"
Foreground="{DynamicResource Brush.ConflictForeground}"
Foreground="{DynamicResource Brush.Conflict.Foreground}"
Text="{DynamicResource Text.Bisect.Detecting}"
IsVisible="{Binding BisectState, Converter={x:Static ObjectConverters.Equal}, ConverterParameter={x:Static m:BisectState.Detecting}}"/>

View File

@@ -343,7 +343,8 @@ namespace SourceGit.Views
mergeBuiltin.Icon = App.CreateMenuIcon("Icons.Conflict");
mergeBuiltin.Click += async (_, e) =>
{
await App.ShowDialog(new ViewModels.MergeConflictEditor(repo, change.Path));
var head = await new Commands.QuerySingleCommit(repo.FullPath, "HEAD").GetResultAsync();
await App.ShowDialog(new ViewModels.MergeConflictEditor(repo, head, change.Path));
e.Handled = true;
};