Skip to content

Commit e2feac3

Browse files
committed
refactor: rewrite TextDiffContext and fix the issue that text diff view does not navigate to the first change chunk after select a different commit with the same file
Signed-off-by: leo <longshuang@msn.cn>
1 parent ccfd7f0 commit e2feac3

File tree

6 files changed

+90
-104
lines changed

6 files changed

+90
-104
lines changed

src/Commands/Diff.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ public partial class Diff : Command
2121

2222
public Diff(string repo, Models.DiffOption opt, int unified, bool ignoreWhitespace)
2323
{
24-
_result.TextDiff = new Models.TextDiff() { Option = opt };
24+
_result.TextDiff = new Models.TextDiff();
2525

2626
WorkingDirectory = repo;
2727
Context = repo;

src/Models/DiffResult.cs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,6 @@ public class TextDiffSelection
5353

5454
public partial class TextDiff
5555
{
56-
public string File { get; set; } = string.Empty;
57-
public DiffOption Option { get; set; } = null;
5856
public List<TextDiffLine> Lines { get; set; } = new List<TextDiffLine>();
5957
public int MaxLineNumber = 0;
6058

src/ViewModels/DiffContext.cs

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,7 @@ public bool ShowEntireFile
3838
OnPropertyChanged();
3939

4040
if (Content is TextDiffContext ctx)
41-
{
42-
ctx.Data.File = string.Empty; // Just to ignore both previous `ScrollOffset` and `BlockNavigation`
4341
LoadContent();
44-
}
4542
}
4643
}
4744
}
@@ -156,7 +153,8 @@ private void LoadContent()
156153

157154
Task.Run(async () =>
158155
{
159-
var numLines = Preferences.Instance.UseFullTextDiff ? _entireFileLine : _unifiedLines;
156+
var showEntireFile = Preferences.Instance.UseFullTextDiff;
157+
var numLines = showEntireFile ? _entireFileLine : _unifiedLines;
160158
var ignoreWhitespace = Preferences.Instance.IgnoreWhitespaceChangesInDiff;
161159

162160
var latest = await new Commands.Diff(_repo, _option, numLines, ignoreWhitespace)
@@ -200,10 +198,7 @@ private void LoadContent()
200198
}
201199

202200
if (!isSubmodule)
203-
{
204-
latest.TextDiff.File = _option.Path;
205201
rs = latest.TextDiff;
206-
}
207202
}
208203
else if (latest.IsBinary)
209204
{
@@ -282,9 +277,9 @@ private void LoadContent()
282277
IsTextDiff = true;
283278

284279
if (Preferences.Instance.UseSideBySideDiff)
285-
Content = new TwoSideTextDiff(cur, _content as TwoSideTextDiff);
280+
Content = new TwoSideTextDiff(_option, showEntireFile, cur, _content as TwoSideTextDiff);
286281
else
287-
Content = new CombinedTextDiff(cur, _content as CombinedTextDiff);
282+
Content = new CombinedTextDiff(_option, showEntireFile, cur, _content as CombinedTextDiff);
288283
}
289284
else
290285
{

src/ViewModels/TextDiffContext.cs

Lines changed: 37 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,8 @@ public static bool IsChanged(TextDiffSelectedChunk oldValue, TextDiffSelectedChu
2828

2929
public class TextDiffContext : ObservableObject
3030
{
31+
public Models.DiffOption Option => _option;
3132
public Models.TextDiff Data => _data;
32-
public string File => _data.File;
33-
public bool IsUnstaged => _data.Option.IsUnstaged;
34-
public bool EnableChunkOption => _data.Option.WorkingCopyChange != null;
3533

3634
public Vector ScrollOffset
3735
{
@@ -132,6 +130,30 @@ public virtual TextDiffContext SwitchMode()
132130
return null;
133131
}
134132

133+
protected bool TryKeepPrevScrollOffset(TextDiffContext prev)
134+
{
135+
var fastTest = prev != null &&
136+
prev._showEntireFile == _showEntireFile &&
137+
prev._option.IsUnstaged == _option.IsUnstaged &&
138+
prev._option.Path.Equals(_option.Path, StringComparison.Ordinal) &&
139+
prev._option.OrgPath.Equals(_option.OrgPath, StringComparison.Ordinal) &&
140+
prev._option.Revisions.Count == _option.Revisions.Count;
141+
142+
if (!fastTest)
143+
return false;
144+
145+
for (int i = 0; i < _option.Revisions.Count; i++)
146+
{
147+
if (!prev._option.Revisions[i].Equals(_option.Revisions[i], StringComparison.Ordinal))
148+
return false;
149+
}
150+
151+
_scrollOffset = prev._scrollOffset;
152+
return true;
153+
}
154+
155+
protected Models.DiffOption _option = null;
156+
protected bool _showEntireFile = false;
135157
protected Models.TextDiff _data = null;
136158
protected Vector _scrollOffset = Vector.Zero;
137159
protected BlockNavigation _blockNavigation = null;
@@ -142,24 +164,19 @@ public virtual TextDiffContext SwitchMode()
142164

143165
public class CombinedTextDiff : TextDiffContext
144166
{
145-
public CombinedTextDiff(Models.TextDiff diff, CombinedTextDiff previous = null)
167+
public CombinedTextDiff(Models.DiffOption option, bool showEntireFile, Models.TextDiff diff, CombinedTextDiff previous = null)
146168
{
169+
_option = option;
170+
_showEntireFile = showEntireFile;
147171
_data = diff;
148172

149-
if (previous != null && previous.File.Equals(File, StringComparison.Ordinal))
150-
{
151-
_blockNavigation = new BlockNavigation(_data.Lines, false);
152-
_scrollOffset = previous._scrollOffset;
153-
}
154-
else
155-
{
156-
_blockNavigation = new BlockNavigation(_data.Lines, true);
157-
}
173+
var keep = TryKeepPrevScrollOffset(previous);
174+
_blockNavigation = new BlockNavigation(_data.Lines, !keep);
158175
}
159176

160177
public override TextDiffContext SwitchMode()
161178
{
162-
return new TwoSideTextDiff(_data);
179+
return new TwoSideTextDiff(_option, _showEntireFile, _data);
163180
}
164181
}
165182

@@ -168,8 +185,10 @@ public class TwoSideTextDiff : TextDiffContext
168185
public List<Models.TextDiffLine> Old { get; } = [];
169186
public List<Models.TextDiffLine> New { get; } = [];
170187

171-
public TwoSideTextDiff(Models.TextDiff diff, TwoSideTextDiff previous = null)
188+
public TwoSideTextDiff(Models.DiffOption option, bool showEntireFile, Models.TextDiff diff, TwoSideTextDiff previous = null)
172189
{
190+
_option = option;
191+
_showEntireFile = showEntireFile;
173192
_data = diff;
174193

175194
foreach (var line in diff.Lines)
@@ -192,15 +211,8 @@ public TwoSideTextDiff(Models.TextDiff diff, TwoSideTextDiff previous = null)
192211

193212
FillEmptyLines();
194213

195-
if (previous != null && previous.File.Equals(File, StringComparison.Ordinal))
196-
{
197-
_blockNavigation = new BlockNavigation(Old, false);
198-
_scrollOffset = previous._scrollOffset;
199-
}
200-
else
201-
{
202-
_blockNavigation = new BlockNavigation(Old, true);
203-
}
214+
var keep = TryKeepPrevScrollOffset(previous);
215+
_blockNavigation = new BlockNavigation(Old, !keep);
204216
}
205217

206218
public override bool IsSideBySide()
@@ -210,7 +222,7 @@ public override bool IsSideBySide()
210222

211223
public override TextDiffContext SwitchMode()
212224
{
213-
return new CombinedTextDiff(_data);
225+
return new CombinedTextDiff(_option, _showEntireFile, _data);
214226
}
215227

216228
public void ConvertsToCombinedRange(ref int startLine, ref int endLine, bool isOldSide)

src/Views/TextDiffView.axaml

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
<DataTemplate DataType="vm:CombinedTextDiff">
1515
<Grid ColumnDefinitions="*,1,12">
1616
<v:CombinedTextDiffPresenter Grid.Column="0"
17-
FileName="{Binding File}"
17+
FileName="{Binding Option.Path}"
1818
Foreground="{DynamicResource Brush.FG1}"
1919
LineBrush="{DynamicResource Brush.Border2}"
2020
EmptyContentBackground="{DynamicResource Brush.Diff.EmptyBG}"
@@ -29,7 +29,6 @@
2929
UseSyntaxHighlighting="{Binding Source={x:Static vm:Preferences.Instance}, Path=UseSyntaxHighlighting}"
3030
WordWrap="{Binding Source={x:Static vm:Preferences.Instance}, Path=EnableDiffViewWordWrap}"
3131
ShowHiddenSymbols="{Binding Source={x:Static vm:Preferences.Instance}, Path=ShowHiddenSymbolsInDiffView}"
32-
EnableChunkSelection="{Binding EnableChunkOption}"
3332
SelectedChunk="{Binding SelectedChunk, Mode=TwoWay}"
3433
BlockNavigation="{Binding BlockNavigation, Mode=OneWay}"/>
3534

@@ -46,7 +45,7 @@
4645
<Grid ColumnDefinitions="*,1,*,1,12">
4746
<v:SingleSideTextDiffPresenter Grid.Column="0"
4847
IsOld="True"
49-
FileName="{Binding File}"
48+
FileName="{Binding Option.Path}"
5049
Foreground="{DynamicResource Brush.FG1}"
5150
LineBrush="{DynamicResource Brush.Border2}"
5251
EmptyContentBackground="{DynamicResource Brush.Diff.EmptyBG}"
@@ -61,15 +60,14 @@
6160
UseSyntaxHighlighting="{Binding Source={x:Static vm:Preferences.Instance}, Path=UseSyntaxHighlighting}"
6261
WordWrap="False"
6362
ShowHiddenSymbols="{Binding Source={x:Static vm:Preferences.Instance}, Path=ShowHiddenSymbolsInDiffView}"
64-
EnableChunkSelection="{Binding EnableChunkOption, Mode=OneWay}"
6563
SelectedChunk="{Binding SelectedChunk, Mode=TwoWay}"
6664
BlockNavigation="{Binding BlockNavigation, Mode=OneWay}"/>
6765

6866
<Rectangle Grid.Column="1" Fill="{DynamicResource Brush.Border2}" Width="1" HorizontalAlignment="Center" VerticalAlignment="Stretch"/>
6967

7068
<v:SingleSideTextDiffPresenter Grid.Column="2"
7169
IsOld="False"
72-
FileName="{Binding File}"
70+
FileName="{Binding Option.Path}"
7371
Foreground="{DynamicResource Brush.FG1}"
7472
LineBrush="{DynamicResource Brush.Border2}"
7573
EmptyContentBackground="{DynamicResource Brush.Diff.EmptyBG}"
@@ -84,7 +82,6 @@
8482
UseSyntaxHighlighting="{Binding Source={x:Static vm:Preferences.Instance}, Path=UseSyntaxHighlighting}"
8583
WordWrap="False"
8684
ShowHiddenSymbols="{Binding Source={x:Static vm:Preferences.Instance}, Path=ShowHiddenSymbolsInDiffView}"
87-
EnableChunkSelection="{Binding EnableChunkOption, Mode=OneWay}"
8885
SelectedChunk="{Binding SelectedChunk, Mode=TwoWay}"
8986
BlockNavigation="{Binding BlockNavigation, Mode=OneWay}"/>
9087

@@ -100,7 +97,7 @@
10097
</ContentControl>
10198

10299
<StackPanel x:Name="Popup" IsVisible="False" Orientation="Horizontal" VerticalAlignment="Top" HorizontalAlignment="Right" Effect="drop-shadow(0 0 8 #80000000)">
103-
<Button Classes="flat" Click="OnStageChunk" HotKey="{OnPlatform Ctrl+S, macOS=⌘+S}" IsVisible="{Binding IsUnstaged}">
100+
<Button Classes="flat" Click="OnStageChunk" HotKey="{OnPlatform Ctrl+S, macOS=⌘+S}" IsVisible="{Binding Option.IsUnstaged}">
104101
<TextBlock>
105102
<Run Text="{DynamicResource Text.Hunk.Stage}"/>
106103
<Run Text=" "/>
@@ -111,7 +108,7 @@
111108
</TextBlock>
112109
</Button>
113110

114-
<Button Classes="flat" Click="OnUnstageChunk" HotKey="{OnPlatform Ctrl+U, macOS=⌘+U}" IsVisible="{Binding IsUnstaged, Converter={x:Static BoolConverters.Not}}">
111+
<Button Classes="flat" Click="OnUnstageChunk" HotKey="{OnPlatform Ctrl+U, macOS=⌘+U}" IsVisible="{Binding Option.IsUnstaged, Converter={x:Static BoolConverters.Not}}">
115112
<TextBlock>
116113
<Run Text="{DynamicResource Text.Hunk.Unstage}"/>
117114
<Run Text=" "/>
@@ -122,7 +119,7 @@
122119
</TextBlock>
123120
</Button>
124121

125-
<Button Classes="flat" Margin="8,0,0,0" HotKey="{OnPlatform Ctrl+D, macOS=⌘+D}" Click="OnDiscardChunk" IsVisible="{Binding IsUnstaged}">
122+
<Button Classes="flat" Margin="8,0,0,0" HotKey="{OnPlatform Ctrl+D, macOS=⌘+D}" Click="OnDiscardChunk" IsVisible="{Binding Option.IsUnstaged}">
126123
<TextBlock>
127124
<Run Text="{DynamicResource Text.Hunk.Discard}"/>
128125
<Run Text=" "/>

0 commit comments

Comments
 (0)