Skip to content

Commit 9a66a26

Browse files
committed
refactor: rewrite text-diff
This commit also contains a feature request #1722 Signed-off-by: leo <[email protected]>
1 parent 5c33198 commit 9a66a26

File tree

9 files changed

+366
-290
lines changed

9 files changed

+366
-290
lines changed

src/Commands/Diff.cs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,7 @@ public partial class Diff : Command
2020

2121
public Diff(string repo, Models.DiffOption opt, int unified, bool ignoreWhitespace)
2222
{
23-
_result.TextDiff = new Models.TextDiff()
24-
{
25-
Repo = repo,
26-
Option = opt,
27-
};
23+
_result.TextDiff = new Models.TextDiff() { Option = opt };
2824

2925
WorkingDirectory = repo;
3026
Context = repo;

src/Models/DiffResult.cs

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
using System.Collections.Generic;
22
using System.IO;
33
using System.Text.RegularExpressions;
4-
5-
using Avalonia;
64
using Avalonia.Media.Imaging;
75

86
namespace SourceGit.Models
@@ -62,13 +60,10 @@ public bool IsInRange(int idx)
6260
public partial class TextDiff
6361
{
6462
public string File { get; set; } = string.Empty;
63+
public DiffOption Option { get; set; } = null;
6564
public List<TextDiffLine> Lines { get; set; } = new List<TextDiffLine>();
66-
public Vector ScrollOffset { get; set; } = Vector.Zero;
6765
public int MaxLineNumber = 0;
6866

69-
public string Repo { get; set; } = null;
70-
public DiffOption Option { get; set; } = null;
71-
7267
public TextDiffSelection MakeSelection(int startLine, int endLine, bool isCombined, bool isOldSide)
7368
{
7469
var rs = new TextDiffSelection();

src/ViewModels/BlockNavigation.cs

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,8 @@ public BlockNavigation(object context)
5454
Current = -1;
5555

5656
var lines = new List<Models.TextDiffLine>();
57-
if (context is Models.TextDiff combined)
58-
lines = combined.Lines;
57+
if (context is CombinedTextDiff combined)
58+
lines = combined.Data.Lines;
5959
else if (context is TwoSideTextDiff twoSide)
6060
lines = twoSide.Old;
6161

@@ -96,7 +96,10 @@ public BlockNavigation(object context)
9696

9797
public Block GetCurrentBlock()
9898
{
99-
return (_current >= 0 && _current < Blocks.Count) ? Blocks[_current] : null;
99+
if (_current >= 0 && _current < Blocks.Count)
100+
return Blocks[_current];
101+
102+
return Blocks.Count > 0 ? Blocks[0] : null;
100103
}
101104

102105
public Block GotoFirst()
@@ -105,6 +108,7 @@ public Block GotoFirst()
105108
return null;
106109

107110
Current = 0;
111+
OnPropertyChanged(nameof(Indicator));
108112
return Blocks[_current];
109113
}
110114

@@ -117,6 +121,8 @@ public Block GotoPrev()
117121
Current = 0;
118122
else if (_current > 0)
119123
Current = _current - 1;
124+
125+
OnPropertyChanged(nameof(Indicator));
120126
return Blocks[_current];
121127
}
122128

@@ -127,6 +133,8 @@ public Block GotoNext()
127133

128134
if (_current < Blocks.Count - 1)
129135
Current = _current + 1;
136+
137+
OnPropertyChanged(nameof(Indicator));
130138
return Blocks[_current];
131139
}
132140

@@ -136,9 +144,35 @@ public Block GotoLast()
136144
return null;
137145

138146
Current = Blocks.Count - 1;
147+
OnPropertyChanged(nameof(Indicator));
139148
return Blocks[_current];
140149
}
141150

151+
public void AutoUpdate(int start, int end)
152+
{
153+
if (_current >= 0 && _current < Blocks.Count)
154+
{
155+
var block = Blocks[_current];
156+
if ((block.Start >= start && block.Start <= end) ||
157+
(block.End >= start && block.End <= end) ||
158+
(block.Start <= start && block.End >= end))
159+
return;
160+
}
161+
162+
for (var i = 0; i < Blocks.Count; i++)
163+
{
164+
var block = Blocks[i];
165+
if ((block.Start >= start && block.Start <= end) ||
166+
(block.End >= start && block.End <= end) ||
167+
(block.Start <= start && block.End >= end))
168+
{
169+
Current = i;
170+
OnPropertyChanged(nameof(Indicator));
171+
return;
172+
}
173+
}
174+
}
175+
142176
private int _current = -1;
143177
}
144178
}

src/ViewModels/DiffContext.cs

Lines changed: 130 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using System.IO;
33
using System.Threading.Tasks;
44

5+
using Avalonia;
56
using Avalonia.Threading;
67

78
using CommunityToolkit.Mvvm.ComponentModel;
@@ -24,7 +25,64 @@ public bool IgnoreWhitespace
2425
{
2526
Preferences.Instance.IgnoreWhitespaceChangesInDiff = value;
2627
OnPropertyChanged();
27-
LoadDiffContent();
28+
29+
if (_isTextDiff)
30+
LoadContent();
31+
}
32+
}
33+
}
34+
35+
public bool ShowEntireFile
36+
{
37+
get => Preferences.Instance.UseFullTextDiff;
38+
set
39+
{
40+
if (value != Preferences.Instance.UseFullTextDiff)
41+
{
42+
Preferences.Instance.UseFullTextDiff = value;
43+
OnPropertyChanged();
44+
45+
if (_isTextDiff)
46+
{
47+
if (Content is CombinedTextDiff combined)
48+
combined.ScrollOffset = Vector.Zero;
49+
else if (Content is TwoSideTextDiff twoSide)
50+
twoSide.Data.File = string.Empty;
51+
52+
LoadContent();
53+
}
54+
}
55+
}
56+
}
57+
58+
public bool UseBlockNavigation
59+
{
60+
get => Preferences.Instance.UseBlockNavigationInDiffView;
61+
set
62+
{
63+
if (value != Preferences.Instance.UseBlockNavigationInDiffView)
64+
{
65+
Preferences.Instance.UseBlockNavigationInDiffView = value;
66+
OnPropertyChanged();
67+
68+
if (Content is CombinedTextDiff combined)
69+
combined.BlockNavigation = value ? new BlockNavigation(combined) : null;
70+
else if (Content is TwoSideTextDiff twoSide)
71+
twoSide.BlockNavigation = value ? new BlockNavigation(twoSide) : null;
72+
}
73+
}
74+
}
75+
76+
public bool UseSideBySide
77+
{
78+
get => Preferences.Instance.UseSideBySideDiff;
79+
set
80+
{
81+
if (value != Preferences.Instance.UseSideBySideDiff)
82+
{
83+
Preferences.Instance.UseSideBySideDiff = value;
84+
OnPropertyChanged();
85+
SwitchTextDiffMode(value);
2886
}
2987
}
3088
}
@@ -72,33 +130,76 @@ public DiffContext(string repo, Models.DiffOption option, DiffContext previous =
72130
else
73131
Title = $"{_option.OrgPath}{_option.Path}";
74132

75-
LoadDiffContent();
76-
}
77-
78-
public void ToggleFullTextDiff()
79-
{
80-
Preferences.Instance.UseFullTextDiff = !Preferences.Instance.UseFullTextDiff;
81-
LoadDiffContent();
133+
LoadContent();
82134
}
83135

84136
public void IncrUnified()
85137
{
86138
UnifiedLines = _unifiedLines + 1;
87-
LoadDiffContent();
139+
LoadContent();
88140
}
89141

90142
public void DecrUnified()
91143
{
92144
UnifiedLines = Math.Max(4, _unifiedLines - 1);
93-
LoadDiffContent();
145+
LoadContent();
94146
}
95147

96148
public void OpenExternalMergeTool()
97149
{
98150
new Commands.DiffTool(_repo, _option).Open();
99151
}
100152

101-
private void LoadDiffContent()
153+
public void CheckSettings()
154+
{
155+
if (_isTextDiff)
156+
{
157+
if ((ShowEntireFile && _info.UnifiedLines != _entireFileLine) ||
158+
(!ShowEntireFile && _info.UnifiedLines == _entireFileLine) ||
159+
(IgnoreWhitespace != _info.IgnoreWhitespace))
160+
{
161+
LoadContent();
162+
return;
163+
}
164+
}
165+
166+
if (Content is CombinedTextDiff combined)
167+
{
168+
if (UseSideBySide)
169+
{
170+
SwitchTextDiffMode(true);
171+
return;
172+
}
173+
174+
if (UseBlockNavigation && combined.BlockNavigation == null)
175+
combined.BlockNavigation = new BlockNavigation(combined);
176+
else if (!UseBlockNavigation && combined.BlockNavigation != null)
177+
combined.BlockNavigation = null;
178+
}
179+
else if (Content is TwoSideTextDiff twoSide)
180+
{
181+
if (!UseSideBySide)
182+
{
183+
SwitchTextDiffMode(false);
184+
return;
185+
}
186+
187+
if (UseBlockNavigation && twoSide.BlockNavigation == null)
188+
twoSide.BlockNavigation = new BlockNavigation(twoSide);
189+
else if (!UseBlockNavigation && twoSide.BlockNavigation != null)
190+
twoSide.BlockNavigation = null;
191+
}
192+
}
193+
194+
private void SwitchTextDiffMode(bool sideBySide)
195+
{
196+
if (sideBySide && _content is CombinedTextDiff combined)
197+
Content = new TwoSideTextDiff(combined.Data, UseBlockNavigation);
198+
else if (!sideBySide && _content is TwoSideTextDiff twoSide)
199+
Content = new CombinedTextDiff(twoSide.Data, UseBlockNavigation);
200+
}
201+
202+
private void LoadContent()
102203
{
103204
if (_option.Path.EndsWith('/'))
104205
{
@@ -109,7 +210,7 @@ private void LoadDiffContent()
109210

110211
Task.Run(async () =>
111212
{
112-
var numLines = Preferences.Instance.UseFullTextDiff ? 999999999 : _unifiedLines;
213+
var numLines = Preferences.Instance.UseFullTextDiff ? _entireFileLine : _unifiedLines;
113214
var ignoreWhitespace = Preferences.Instance.IgnoreWhitespaceChangesInDiff;
114215

115216
var latest = await new Commands.Diff(_repo, _option, numLines, ignoreWhitespace)
@@ -228,12 +329,23 @@ private void LoadDiffContent()
228329

229330
Dispatcher.UIThread.Post(() =>
230331
{
231-
if (_content is Models.TextDiff old && rs is Models.TextDiff cur && old.File == cur.File)
232-
cur.ScrollOffset = old.ScrollOffset;
233-
234332
FileModeChange = latest.FileModeChange;
235-
Content = rs;
236-
IsTextDiff = rs is Models.TextDiff;
333+
334+
if (rs is Models.TextDiff cur)
335+
{
336+
IsTextDiff = true;
337+
338+
var hasBlockNavigation = Preferences.Instance.UseBlockNavigationInDiffView;
339+
if (Preferences.Instance.UseSideBySideDiff)
340+
Content = new TwoSideTextDiff(cur, hasBlockNavigation, _content as TwoSideTextDiff);
341+
else
342+
Content = new CombinedTextDiff(cur, hasBlockNavigation, _content as CombinedTextDiff);
343+
}
344+
else
345+
{
346+
IsTextDiff = false;
347+
Content = rs;
348+
}
237349
});
238350
});
239351
}
@@ -279,6 +391,7 @@ public bool IsSame(Info other)
279391
}
280392
}
281393

394+
private readonly int _entireFileLine = 999999999;
282395
private readonly string _repo;
283396
private readonly Models.DiffOption _option = null;
284397
private string _fileModeChange = string.Empty;

0 commit comments

Comments
 (0)