Skip to content

Commit dcaeaef

Browse files
committed
refactor: re-design conflict panel
1 parent 36ecbcc commit dcaeaef

File tree

3 files changed

+187
-74
lines changed

3 files changed

+187
-74
lines changed

src/ViewModels/Conflict.cs

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
namespace SourceGit.ViewModels
2+
{
3+
public class Conflict
4+
{
5+
public object Theirs
6+
{
7+
get;
8+
private set;
9+
}
10+
11+
public object Mine
12+
{
13+
get;
14+
private set;
15+
}
16+
17+
public bool IsResolved
18+
{
19+
get;
20+
private set;
21+
}
22+
23+
public Conflict(Repository repo, WorkingCopy wc, Models.Change change)
24+
{
25+
_wc = wc;
26+
_change = change;
27+
28+
IsResolved = new Commands.IsConflictResolved(repo.FullPath, change).ReadToEnd().IsSuccess;
29+
30+
var context = wc.InProgressContext;
31+
if (context is CherryPickInProgress cherryPick)
32+
{
33+
Theirs = cherryPick.Head;
34+
Mine = repo.CurrentBranch;
35+
}
36+
else if (context is RebaseInProgress rebase)
37+
{
38+
Theirs = repo.Branches.Find(x => x.IsLocal && x.Name == rebase.HeadName) ??
39+
new Models.Branch()
40+
{
41+
IsLocal = true,
42+
Name = rebase.HeadName,
43+
FullName = $"refs/heads/{rebase.HeadName}"
44+
};
45+
46+
Mine = rebase.Onto;
47+
}
48+
else if (context is RevertInProgress revert)
49+
{
50+
Theirs = revert.Head;
51+
Mine = repo.CurrentBranch;
52+
}
53+
else if (context is MergeInProgress merge)
54+
{
55+
Theirs = merge.Source;
56+
Mine = repo.CurrentBranch;
57+
}
58+
}
59+
60+
public void UseTheirs()
61+
{
62+
_wc.UseTheirs([_change]);
63+
}
64+
65+
public void UseMine()
66+
{
67+
_wc.UseMine([_change]);
68+
}
69+
70+
public void OpenExternalMergeTool()
71+
{
72+
_wc.UseExternalMergeTool(_change);
73+
}
74+
75+
private WorkingCopy _wc = null;
76+
private Models.Change _change = null;
77+
}
78+
}

src/ViewModels/WorkingCopy.cs

Lines changed: 49 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -11,26 +11,6 @@
1111

1212
namespace SourceGit.ViewModels
1313
{
14-
public class ConflictContext : ObservableObject
15-
{
16-
public bool IsResolved
17-
{
18-
get => _isResolved;
19-
set => SetProperty(ref _isResolved, value);
20-
}
21-
22-
public ConflictContext(string repo, Models.Change change)
23-
{
24-
Task.Run(() =>
25-
{
26-
var result = new Commands.IsConflictResolved(repo, change).ReadToEnd().IsSuccess;
27-
Dispatcher.UIThread.Post(() => IsResolved = result);
28-
});
29-
}
30-
31-
private bool _isResolved = false;
32-
}
33-
3414
public class WorkingCopy : ObservableObject
3515
{
3616
public bool IncludeUntracked
@@ -440,6 +420,54 @@ public void Discard(List<Models.Change> changes)
440420
}
441421
}
442422

423+
public async void UseTheirs(List<Models.Change> changes)
424+
{
425+
var files = new List<string>();
426+
foreach (var change in changes)
427+
{
428+
if (change.IsConflit)
429+
files.Add(change.Path);
430+
}
431+
432+
_repo.SetWatcherEnabled(false);
433+
var succ = await Task.Run(() => new Commands.Checkout(_repo.FullPath).UseTheirs(files));
434+
if (succ)
435+
{
436+
await Task.Run(() => new Commands.Add(_repo.FullPath, changes).Exec());
437+
}
438+
_repo.MarkWorkingCopyDirtyManually();
439+
_repo.SetWatcherEnabled(true);
440+
}
441+
442+
public async void UseMine(List<Models.Change> changes)
443+
{
444+
var files = new List<string>();
445+
foreach (var change in changes)
446+
{
447+
if (change.IsConflit)
448+
files.Add(change.Path);
449+
}
450+
451+
_repo.SetWatcherEnabled(false);
452+
var succ = await Task.Run(() => new Commands.Checkout(_repo.FullPath).UseMine(files));
453+
if (succ)
454+
{
455+
await Task.Run(() => new Commands.Add(_repo.FullPath, changes).Exec());
456+
}
457+
_repo.MarkWorkingCopyDirtyManually();
458+
_repo.SetWatcherEnabled(true);
459+
}
460+
461+
public async void UseExternalMergeTool(Models.Change change)
462+
{
463+
var toolType = Preference.Instance.ExternalMergeToolType;
464+
var toolPath = Preference.Instance.ExternalMergeToolPath;
465+
466+
_repo.SetWatcherEnabled(false);
467+
await Task.Run(() => Commands.MergeTool.OpenForMerge(_repo.FullPath, toolType, toolPath, change.Path));
468+
_repo.SetWatcherEnabled(true);
469+
}
470+
443471
public void ContinueMerge()
444472
{
445473
if (_inProgressContext != null)
@@ -1438,59 +1466,11 @@ private void SetDetail(Models.Change change, bool isUnstaged)
14381466
if (change == null)
14391467
DetailContext = null;
14401468
else if (change.IsConflit && isUnstaged)
1441-
DetailContext = new ConflictContext(_repo.FullPath, change);
1469+
DetailContext = new Conflict(_repo, this, change);
14421470
else
14431471
DetailContext = new DiffContext(_repo.FullPath, new Models.DiffOption(change, isUnstaged), _detailContext as DiffContext);
14441472
}
14451473

1446-
private async void UseTheirs(List<Models.Change> changes)
1447-
{
1448-
var files = new List<string>();
1449-
foreach (var change in changes)
1450-
{
1451-
if (change.IsConflit)
1452-
files.Add(change.Path);
1453-
}
1454-
1455-
_repo.SetWatcherEnabled(false);
1456-
var succ = await Task.Run(() => new Commands.Checkout(_repo.FullPath).UseTheirs(files));
1457-
if (succ)
1458-
{
1459-
await Task.Run(() => new Commands.Add(_repo.FullPath, changes).Exec());
1460-
}
1461-
_repo.MarkWorkingCopyDirtyManually();
1462-
_repo.SetWatcherEnabled(true);
1463-
}
1464-
1465-
private async void UseMine(List<Models.Change> changes)
1466-
{
1467-
var files = new List<string>();
1468-
foreach (var change in changes)
1469-
{
1470-
if (change.IsConflit)
1471-
files.Add(change.Path);
1472-
}
1473-
1474-
_repo.SetWatcherEnabled(false);
1475-
var succ = await Task.Run(() => new Commands.Checkout(_repo.FullPath).UseMine(files));
1476-
if (succ)
1477-
{
1478-
await Task.Run(() => new Commands.Add(_repo.FullPath, changes).Exec());
1479-
}
1480-
_repo.MarkWorkingCopyDirtyManually();
1481-
_repo.SetWatcherEnabled(true);
1482-
}
1483-
1484-
private async void UseExternalMergeTool(Models.Change change)
1485-
{
1486-
var toolType = Preference.Instance.ExternalMergeToolType;
1487-
var toolPath = Preference.Instance.ExternalMergeToolPath;
1488-
1489-
_repo.SetWatcherEnabled(false);
1490-
await Task.Run(() => Commands.MergeTool.OpenForMerge(_repo.FullPath, toolType, toolPath, change.Path));
1491-
_repo.SetWatcherEnabled(true);
1492-
}
1493-
14941474
private void DoCommit(bool autoStage, bool autoPush, bool allowEmpty)
14951475
{
14961476
if (!PopupHost.CanCreatePopup())

src/Views/WorkingCopy.axaml

Lines changed: 60 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
33
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
44
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
5+
xmlns:m="using:SourceGit.Models"
56
xmlns:vm="using:SourceGit.ViewModels"
67
xmlns:v="using:SourceGit.Views"
78
xmlns:c="using:SourceGit.Converters"
@@ -169,13 +170,67 @@
169170

170171
<ContentControl Content="{Binding DetailContext}">
171172
<ContentControl.DataTemplates>
172-
<DataTemplate DataType="vm:ConflictContext">
173+
<DataTemplate DataType="vm:Conflict">
173174
<Border Background="{DynamicResource Brush.Window}" BorderThickness="1" BorderBrush="{DynamicResource Brush.Border2}">
174-
<Grid HorizontalAlignment="Center" VerticalAlignment="Center">
175+
<Grid VerticalAlignment="Center">
175176
<StackPanel Orientation="Vertical" IsVisible="{Binding !IsResolved}">
176-
<Path Width="64" Height="64" Data="{StaticResource Icons.Conflict}" Fill="{DynamicResource Brush.FG2}"/>
177-
<TextBlock Margin="0,16,0,8" FontSize="20" FontWeight="Bold" Text="{DynamicResource Text.WorkingCopy.Conflicts}" Foreground="{DynamicResource Brush.FG2}" HorizontalAlignment="Center"/>
178-
<TextBlock Text="{DynamicResource Text.WorkingCopy.ResolveTip}" Foreground="{DynamicResource Brush.FG2}" HorizontalAlignment="Center"/>
177+
<StackPanel.DataTemplates>
178+
<DataTemplate DataType="m:Branch">
179+
<StackPanel Orientation="Horizontal">
180+
<Path Width="12" Height="12" Data="{StaticResource Icons.Branch}"/>
181+
<TextBlock Margin="4,0,0,0" Text="{Binding FriendlyName}"/>
182+
<TextBlock Margin="4,0,0,0" Text="{Binding Head, Converter={x:Static c:StringConverters.ToShortSHA}}" Foreground="DarkOrange"/>
183+
</StackPanel>
184+
</DataTemplate>
185+
186+
<DataTemplate DataType="m:Commit">
187+
<StackPanel Orientation="Horizontal">
188+
<Path Width="12" Height="12" Margin="0,6,0,0" Data="{StaticResource Icons.Commit}"/>
189+
<v:CommitRefsPresenter Margin="8,0,0,0"
190+
TagBackground="{DynamicResource Brush.DecoratorTag}"
191+
Foreground="{DynamicResource Brush.FG1}"
192+
FontFamily="{DynamicResource Fonts.Primary}"
193+
FontSize="11"
194+
VerticalAlignment="Center"
195+
UseGraphColor="False"/>
196+
<TextBlock Margin="4,0,0,0" Text="{Binding SHA, Converter={x:Static c:StringConverters.ToShortSHA}}" Foreground="DarkOrange"/>
197+
<TextBlock Margin="4,0,0,0" Text="{Binding Subject}"/>
198+
</StackPanel>
199+
</DataTemplate>
200+
201+
<DataTemplate DataType="m:Tag">
202+
<StackPanel Orientation="Horizontal">
203+
<Path Width="12" Height="12" Data="{StaticResource Icons.Tag}"/>
204+
<TextBlock Margin="4,0,0,0" Text="{Binding Name}"/>
205+
<TextBlock Margin="4,0,0,0" Text="{Binding SHA, Converter={x:Static c:StringConverters.ToShortSHA}}" Foreground="DarkOrange"/>
206+
</StackPanel>
207+
</DataTemplate>
208+
</StackPanel.DataTemplates>
209+
210+
<Path Width="64" Height="64" Data="{StaticResource Icons.Conflict}" Fill="{DynamicResource Brush.FG2}" HorizontalAlignment="Center"/>
211+
<TextBlock Margin="0,16" FontSize="20" FontWeight="Bold" Text="{DynamicResource Text.WorkingCopy.Conflicts}" Foreground="{DynamicResource Brush.FG2}" HorizontalAlignment="Center"/>
212+
213+
<Border Margin="16,0" Padding="8" CornerRadius="4" BorderThickness="1" BorderBrush="{DynamicResource Brush.Border2}">
214+
<Border.IsVisible>
215+
<MultiBinding Converter="{x:Static BoolConverters.And}">
216+
<Binding Path="Theirs" Converter="{x:Static ObjectConverters.IsNotNull}"/>
217+
<Binding Path="Mine" Converter="{x:Static ObjectConverters.IsNotNull}"/>
218+
</MultiBinding>
219+
</Border.IsVisible>
220+
221+
<Grid Margin="8,0,0,0" RowDefinitions="32,32" ColumnDefinitions="Auto,*">
222+
<TextBlock Grid.Row="0" Grid.Column="0" Classes="info_label" Text="THEIRS"/>
223+
<ContentControl Grid.Row="0" Grid.Column="1" Margin="16,0,0,0" Content="{Binding Theirs}"/>
224+
<TextBlock Grid.Row="1" Grid.Column="0" Classes="info_label" Text="MINE"/>
225+
<ContentControl Grid.Row="1" Grid.Column="1" Margin="16,0,0,0" Content="{Binding Mine}"/>
226+
</Grid>
227+
</Border>
228+
229+
<StackPanel Margin="0,8,0,0" Orientation="Horizontal" HorizontalAlignment="Center">
230+
<Button Classes="flat" Content="USE THEIRS" Command="{Binding UseTheirs}"/>
231+
<Button Classes="flat" Margin="8,0,0,0" Content="USE MINE" Command="{Binding UseMine}"/>
232+
<Button Classes="flat" Margin="8,0,0,0" Content="OPEN EXTERNAL MERGETOOL" Command="{Binding OpenExternalMergeTool}"/>
233+
</StackPanel>
179234
</StackPanel>
180235

181236
<StackPanel Orientation="Vertical" IsVisible="{Binding IsResolved}">

0 commit comments

Comments
 (0)