mirror of
https://github.com/sourcegit-scm/sourcegit.git
synced 2024-12-25 21:07:20 -08:00
Compare commits
5 commits
4b6bb70f20
...
882878dbe5
Author | SHA1 | Date | |
---|---|---|---|
|
882878dbe5 | ||
|
52c7388a38 | ||
|
134c71064e | ||
|
cd137e222c | ||
|
8d84d0f6a1 |
9 changed files with 191 additions and 51 deletions
2
.github/workflows/build.yml
vendored
2
.github/workflows/build.yml
vendored
|
@ -32,7 +32,7 @@ jobs:
|
|||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: 8.0.x
|
||||
dotnet-version: 9.0.x
|
||||
- name: Configure arm64 packages
|
||||
if: ${{ matrix.runtime == 'linux-arm64' }}
|
||||
run: |
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"sdk": {
|
||||
"version": "8.0.0",
|
||||
"version": "9.0.0",
|
||||
"rollForward": "latestMajor",
|
||||
"allowPrerelease": false
|
||||
}
|
||||
|
|
|
@ -28,9 +28,9 @@ namespace SourceGit.Commands
|
|||
Context = repo;
|
||||
|
||||
if (ignoreWhitespace)
|
||||
Args = $"diff --patch --ignore-cr-at-eol --ignore-all-space --unified={unified} {opt}";
|
||||
Args = $"diff --no-ext-diff --patch --ignore-cr-at-eol --ignore-all-space --unified={unified} {opt}";
|
||||
else
|
||||
Args = $"diff --patch --ignore-cr-at-eol --unified={unified} {opt}";
|
||||
Args = $"diff --no-ext-diff --patch --ignore-cr-at-eol --unified={unified} {opt}";
|
||||
}
|
||||
|
||||
public Models.DiffResult Result()
|
||||
|
|
|
@ -152,18 +152,12 @@ namespace SourceGit.Models
|
|||
set;
|
||||
} = "---";
|
||||
|
||||
public FilterMode GetHistoriesFilterMode(string pattern, FilterType type)
|
||||
public Dictionary<string, FilterMode> CollectHistoriesFilters()
|
||||
{
|
||||
var map = new Dictionary<string, FilterMode>();
|
||||
foreach (var filter in HistoriesFilters)
|
||||
{
|
||||
if (filter.Type != type)
|
||||
continue;
|
||||
|
||||
if (filter.Pattern.Equals(pattern, StringComparison.Ordinal))
|
||||
return filter.Mode;
|
||||
}
|
||||
|
||||
return FilterMode.None;
|
||||
map.Add(filter.Pattern, filter.Mode);
|
||||
return map;
|
||||
}
|
||||
|
||||
public bool UpdateHistoriesFilter(string pattern, FilterType type, FilterMode mode)
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<BuiltInComInteropSupport>true</BuiltInComInteropSupport>
|
||||
<ApplicationManifest>App.manifest</ApplicationManifest>
|
||||
<ApplicationIcon>App.ico</ApplicationIcon>
|
||||
|
|
|
@ -827,9 +827,6 @@ namespace SourceGit.ViewModels
|
|||
public void RefreshTags()
|
||||
{
|
||||
var tags = new Commands.QueryTags(_fullpath).Result();
|
||||
foreach (var tag in tags)
|
||||
tag.FilterMode = _settings.GetHistoriesFilterMode(tag.Name, Models.FilterType.Tag);
|
||||
|
||||
Dispatcher.UIThread.Invoke(() =>
|
||||
{
|
||||
Tags = tags;
|
||||
|
@ -2035,8 +2032,9 @@ namespace SourceGit.ViewModels
|
|||
builder.Run(visibles, remotes, true);
|
||||
}
|
||||
|
||||
UpdateBranchTreeFilterMode(builder.Locals, true);
|
||||
UpdateBranchTreeFilterMode(builder.Remotes, false);
|
||||
var historiesFilters = _settings.CollectHistoriesFilters();
|
||||
UpdateBranchTreeFilterMode(builder.Locals, historiesFilters);
|
||||
UpdateBranchTreeFilterMode(builder.Remotes, historiesFilters);
|
||||
return builder;
|
||||
}
|
||||
|
||||
|
@ -2056,7 +2054,8 @@ namespace SourceGit.ViewModels
|
|||
}
|
||||
}
|
||||
|
||||
UpdateTagFilterMode();
|
||||
var historiesFilters = _settings.CollectHistoriesFilters();
|
||||
UpdateTagFilterMode(historiesFilters);
|
||||
return visible;
|
||||
}
|
||||
|
||||
|
@ -2080,32 +2079,36 @@ namespace SourceGit.ViewModels
|
|||
|
||||
private void RefreshHistoriesFilters()
|
||||
{
|
||||
UpdateBranchTreeFilterMode(LocalBranchTrees, true);
|
||||
UpdateBranchTreeFilterMode(RemoteBranchTrees, false);
|
||||
UpdateTagFilterMode();
|
||||
var filters = _settings.CollectHistoriesFilters();
|
||||
UpdateBranchTreeFilterMode(LocalBranchTrees, filters);
|
||||
UpdateBranchTreeFilterMode(RemoteBranchTrees, filters);
|
||||
UpdateTagFilterMode(filters);
|
||||
Task.Run(RefreshCommits);
|
||||
}
|
||||
|
||||
private void UpdateBranchTreeFilterMode(List<BranchTreeNode> nodes, bool isLocal)
|
||||
private void UpdateBranchTreeFilterMode(List<BranchTreeNode> nodes, Dictionary<string, Models.FilterMode> filters)
|
||||
{
|
||||
foreach (var node in nodes)
|
||||
{
|
||||
if (node.IsBranch)
|
||||
{
|
||||
node.FilterMode = _settings.GetHistoriesFilterMode(node.Path, isLocal ? Models.FilterType.LocalBranch : Models.FilterType.RemoteBranch);
|
||||
}
|
||||
if (filters.TryGetValue(node.Path, out var value))
|
||||
node.FilterMode = value;
|
||||
else
|
||||
{
|
||||
node.FilterMode = _settings.GetHistoriesFilterMode(node.Path, isLocal ? Models.FilterType.LocalBranchFolder : Models.FilterType.RemoteBranchFolder);
|
||||
UpdateBranchTreeFilterMode(node.Children, isLocal);
|
||||
}
|
||||
node.FilterMode = Models.FilterMode.None;
|
||||
|
||||
if (!node.IsBranch)
|
||||
UpdateBranchTreeFilterMode(node.Children, filters);
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateTagFilterMode()
|
||||
private void UpdateTagFilterMode(Dictionary<string, Models.FilterMode> filters)
|
||||
{
|
||||
foreach (var tag in _tags)
|
||||
tag.FilterMode = _settings.GetHistoriesFilterMode(tag.Name, Models.FilterType.Tag);
|
||||
{
|
||||
if (filters.TryGetValue(tag.Name, out var value))
|
||||
tag.FilterMode = value;
|
||||
else
|
||||
tag.FilterMode = Models.FilterMode.None;
|
||||
}
|
||||
}
|
||||
|
||||
private void ResetBranchTreeFilterMode(List<BranchTreeNode> nodes)
|
||||
|
|
|
@ -34,8 +34,24 @@
|
|||
|
||||
<!-- Toolbar Buttons -->
|
||||
<StackPanel Grid.Column="3" Margin="8,0,0,0" Orientation="Horizontal" VerticalAlignment="Center">
|
||||
<Button Classes="icon_button"
|
||||
Width="28"
|
||||
Click="OnGotoPrevChange"
|
||||
IsVisible="{Binding IsTextDiff}"
|
||||
ToolTip.Tip="{DynamicResource Text.Diff.Prev}">
|
||||
<Path Width="12" Height="12" Stretch="Uniform" Margin="0,6,0,0" Data="{StaticResource Icons.Up}"/>
|
||||
</Button>
|
||||
|
||||
<Button Classes="icon_button"
|
||||
Width="28"
|
||||
Click="OnGotoNextChange"
|
||||
IsVisible="{Binding IsTextDiff}"
|
||||
ToolTip.Tip="{DynamicResource Text.Diff.Next}">
|
||||
<Path Width="12" Height="12" Stretch="Uniform" Margin="0,6,0,0" Data="{StaticResource Icons.Down}"/>
|
||||
</Button>
|
||||
|
||||
<Button Classes="icon_button"
|
||||
Width="32"
|
||||
Width="28"
|
||||
Command="{Binding IncrUnified}"
|
||||
IsVisible="{Binding IsTextDiff}"
|
||||
ToolTip.Tip="{DynamicResource Text.Diff.VisualLines.Incr}">
|
||||
|
@ -46,7 +62,7 @@
|
|||
</Button>
|
||||
|
||||
<Button Classes="icon_button"
|
||||
Width="32"
|
||||
Width="28"
|
||||
Command="{Binding DecrUnified}"
|
||||
IsVisible="{Binding IsTextDiff}"
|
||||
ToolTip.Tip="{DynamicResource Text.Diff.VisualLines.Decr}">
|
||||
|
@ -60,9 +76,7 @@
|
|||
</Button>
|
||||
|
||||
<ToggleButton Classes="line_path"
|
||||
Width="32" Height="18"
|
||||
Background="Transparent"
|
||||
Padding="9,6"
|
||||
Width="28"
|
||||
Command="{Binding ToggleFullTextDiff}"
|
||||
IsChecked="{Binding Source={x:Static vm:Preference.Instance}, Path=UseFullTextDiff, Mode=OneWay}"
|
||||
IsVisible="{Binding IsTextDiff}"
|
||||
|
@ -71,9 +85,8 @@
|
|||
</ToggleButton>
|
||||
|
||||
<ToggleButton Classes="line_path"
|
||||
Width="32" Height="18"
|
||||
Width="28"
|
||||
Background="Transparent"
|
||||
Padding="9,6"
|
||||
IsChecked="{Binding Source={x:Static vm:Preference.Instance}, Path=UseSyntaxHighlighting, Mode=TwoWay}"
|
||||
IsVisible="{Binding IsTextDiff}"
|
||||
ToolTip.Tip="{DynamicResource Text.Diff.SyntaxHighlight}">
|
||||
|
@ -81,9 +94,7 @@
|
|||
</ToggleButton>
|
||||
|
||||
<ToggleButton Classes="line_path"
|
||||
Width="32" Height="18"
|
||||
Background="Transparent"
|
||||
Padding="9,6"
|
||||
Width="28"
|
||||
IsChecked="{Binding Source={x:Static vm:Preference.Instance}, Path=EnableDiffViewWordWrap, Mode=TwoWay}"
|
||||
ToolTip.Tip="{DynamicResource Text.Diff.ToggleWordWrap}">
|
||||
<ToggleButton.IsVisible>
|
||||
|
@ -97,14 +108,14 @@
|
|||
</ToggleButton>
|
||||
|
||||
<ToggleButton Classes="line_path"
|
||||
Width="32"
|
||||
Width="28"
|
||||
IsChecked="{Binding IgnoreWhitespace, Mode=TwoWay}"
|
||||
ToolTip.Tip="{DynamicResource Text.Diff.IgnoreWhitespace}">
|
||||
<Path Width="14" Height="14" Stretch="Uniform" Data="{StaticResource Icons.Whitespace}"/>
|
||||
</ToggleButton>
|
||||
|
||||
<ToggleButton Classes="line_path"
|
||||
Width="32"
|
||||
Width="28"
|
||||
IsChecked="{Binding Source={x:Static vm:Preference.Instance}, Path=ShowHiddenSymbolsInDiffView, Mode=TwoWay}"
|
||||
IsVisible="{Binding IsTextDiff}"
|
||||
ToolTip.Tip="{DynamicResource Text.Diff.ShowHiddenSymbols}">
|
||||
|
@ -112,16 +123,14 @@
|
|||
</ToggleButton>
|
||||
|
||||
<ToggleButton Classes="line_path"
|
||||
Width="32" Height="18"
|
||||
Background="Transparent"
|
||||
Padding="9,6"
|
||||
Width="28" Height="18"
|
||||
IsChecked="{Binding Source={x:Static vm:Preference.Instance}, Path=UseSideBySideDiff, Mode=TwoWay}"
|
||||
IsVisible="{Binding IsTextDiff}"
|
||||
ToolTip.Tip="{DynamicResource Text.Diff.SideBySide}">
|
||||
<Path Width="12" Height="12" Data="{StaticResource Icons.LayoutHorizontal}" Margin="0,2,0,0"/>
|
||||
</ToggleButton>
|
||||
|
||||
<Button Classes="icon_button" Width="32" Command="{Binding OpenExternalMergeTool}" ToolTip.Tip="{DynamicResource Text.Diff.UseMerger}">
|
||||
<Button Classes="icon_button" Width="28" Command="{Binding OpenExternalMergeTool}" ToolTip.Tip="{DynamicResource Text.Diff.UseMerger}">
|
||||
<Path Width="12" Height="12" Stretch="Uniform" Data="{StaticResource Icons.OpenWith}"/>
|
||||
</Button>
|
||||
</StackPanel>
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
using Avalonia.Controls;
|
||||
using Avalonia.Interactivity;
|
||||
using Avalonia.VisualTree;
|
||||
|
||||
namespace SourceGit.Views
|
||||
{
|
||||
|
@ -8,5 +10,31 @@ namespace SourceGit.Views
|
|||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void OnGotoPrevChange(object _, RoutedEventArgs e)
|
||||
{
|
||||
var textDiff = this.FindDescendantOfType<ThemedTextDiffPresenter>();
|
||||
if (textDiff == null)
|
||||
return;
|
||||
|
||||
textDiff.GotoPrevChange();
|
||||
if (textDiff is SingleSideTextDiffPresenter presenter)
|
||||
presenter.ForceSyncScrollOffset();
|
||||
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private void OnGotoNextChange(object _, RoutedEventArgs e)
|
||||
{
|
||||
var textDiff = this.FindDescendantOfType<ThemedTextDiffPresenter>();
|
||||
if (textDiff == null)
|
||||
return;
|
||||
|
||||
textDiff.GotoNextChange();
|
||||
if (textDiff is SingleSideTextDiffPresenter presenter)
|
||||
presenter.ForceSyncScrollOffset();
|
||||
|
||||
e.Handled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -498,6 +498,106 @@ namespace SourceGit.Views
|
|||
{
|
||||
}
|
||||
|
||||
public void GotoPrevChange()
|
||||
{
|
||||
var view = TextArea.TextView;
|
||||
var lines = GetLines();
|
||||
var firstLineIdx = lines.Count;
|
||||
foreach (var line in view.VisualLines)
|
||||
{
|
||||
if (line.IsDisposed || line.FirstDocumentLine == null || line.FirstDocumentLine.IsDeleted)
|
||||
continue;
|
||||
|
||||
var index = line.FirstDocumentLine.LineNumber - 1;
|
||||
if (index >= lines.Count)
|
||||
continue;
|
||||
|
||||
if (firstLineIdx > index)
|
||||
firstLineIdx = index;
|
||||
}
|
||||
|
||||
if (firstLineIdx <= 1)
|
||||
return;
|
||||
|
||||
var firstLineType = lines[firstLineIdx].Type;
|
||||
var prevLineType = lines[firstLineIdx - 1].Type;
|
||||
var isChangeFirstLine = firstLineType != Models.TextDiffLineType.Normal && firstLineType != Models.TextDiffLineType.Indicator;
|
||||
var isChangePrevLine = prevLineType != Models.TextDiffLineType.Normal && prevLineType != Models.TextDiffLineType.Indicator;
|
||||
if (isChangeFirstLine && isChangePrevLine)
|
||||
{
|
||||
for (var i = firstLineIdx - 2; i >= 0; i--)
|
||||
{
|
||||
var prevType = lines[i].Type;
|
||||
if (prevType == Models.TextDiffLineType.Normal || prevType == Models.TextDiffLineType.Indicator)
|
||||
{
|
||||
ScrollToLine(i + 2);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var findChange = false;
|
||||
for (var i = firstLineIdx - 1; i >= 0; i--)
|
||||
{
|
||||
var prevType = lines[i].Type;
|
||||
if (prevType == Models.TextDiffLineType.Normal || prevType == Models.TextDiffLineType.Indicator)
|
||||
{
|
||||
if (findChange)
|
||||
{
|
||||
ScrollToLine(i + 2);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (!findChange)
|
||||
{
|
||||
findChange = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void GotoNextChange()
|
||||
{
|
||||
var view = TextArea.TextView;
|
||||
var lines = GetLines();
|
||||
var lastLineIdx = -1;
|
||||
foreach (var line in view.VisualLines)
|
||||
{
|
||||
if (line.IsDisposed || line.FirstDocumentLine == null || line.FirstDocumentLine.IsDeleted)
|
||||
continue;
|
||||
|
||||
var index = line.FirstDocumentLine.LineNumber - 1;
|
||||
if (index >= lines.Count)
|
||||
continue;
|
||||
|
||||
if (lastLineIdx < index)
|
||||
lastLineIdx = index;
|
||||
}
|
||||
|
||||
if (lastLineIdx >= lines.Count - 1)
|
||||
return;
|
||||
|
||||
var lastLineType = lines[lastLineIdx].Type;
|
||||
var findNormalLine = lastLineType == Models.TextDiffLineType.Normal || lastLineType == Models.TextDiffLineType.Indicator;
|
||||
for (var idx = lastLineIdx + 1; idx < lines.Count; idx++)
|
||||
{
|
||||
var nextType = lines[idx].Type;
|
||||
if (nextType == Models.TextDiffLineType.None ||
|
||||
nextType == Models.TextDiffLineType.Added ||
|
||||
nextType == Models.TextDiffLineType.Deleted)
|
||||
{
|
||||
if (findNormalLine)
|
||||
{
|
||||
ScrollToLine(idx + 1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (!findNormalLine)
|
||||
{
|
||||
findNormalLine = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void Render(DrawingContext context)
|
||||
{
|
||||
base.Render(context);
|
||||
|
@ -968,6 +1068,12 @@ namespace SourceGit.Views
|
|||
TextArea.LeftMargins.Add(new LineModifyTypeMargin());
|
||||
}
|
||||
|
||||
public void ForceSyncScrollOffset()
|
||||
{
|
||||
if (DataContext is ViewModels.TwoSideTextDiff diff)
|
||||
diff.SyncScrollOffset = _scrollViewer.Offset;
|
||||
}
|
||||
|
||||
public override List<Models.TextDiffLine> GetLines()
|
||||
{
|
||||
if (DataContext is ViewModels.TwoSideTextDiff diff)
|
||||
|
|
Loading…
Reference in a new issue