diff --git a/src/Commands/IsCommitSHA.cs b/src/Commands/IsCommitSHA.cs new file mode 100644 index 00000000..1b0c50e3 --- /dev/null +++ b/src/Commands/IsCommitSHA.cs @@ -0,0 +1,17 @@ +namespace SourceGit.Commands +{ + public class IsCommitSHA : Command + { + public IsCommitSHA(string repo, string hash) + { + WorkingDirectory = repo; + Args = $"cat-file -t {hash}"; + } + + public bool Result() + { + var rs = ReadToEnd(); + return rs.IsSuccess && rs.StdOut.Trim().Equals("commit"); + } + } +} diff --git a/src/Commands/QueryCommitsWithFullMessage.cs b/src/Commands/QueryCommitsForInteractiveRebase.cs similarity index 86% rename from src/Commands/QueryCommitsWithFullMessage.cs rename to src/Commands/QueryCommitsForInteractiveRebase.cs index c15cdbe1..232d86e5 100644 --- a/src/Commands/QueryCommitsWithFullMessage.cs +++ b/src/Commands/QueryCommitsForInteractiveRebase.cs @@ -3,18 +3,18 @@ using System.Collections.Generic; namespace SourceGit.Commands { - public class QueryCommitsWithFullMessage : Command + public class QueryCommitsForInteractiveRebase : Command { - public QueryCommitsWithFullMessage(string repo, string args) + public QueryCommitsForInteractiveRebase(string repo, string on) { _boundary = $"----- BOUNDARY OF COMMIT {Guid.NewGuid()} -----"; WorkingDirectory = repo; Context = repo; - Args = $"log --date-order --no-show-signature --decorate=full --pretty=format:\"%H%n%P%n%D%n%aN±%aE%n%at%n%cN±%cE%n%ct%n%B%n{_boundary}\" {args}"; + Args = $"log --date-order --no-show-signature --decorate=full --pretty=format:\"%H%n%P%n%D%n%aN±%aE%n%at%n%cN±%cE%n%ct%n%B%n{_boundary}\" {on}..HEAD"; } - public List Result() + public List Result() { var rs = ReadToEnd(); if (!rs.IsSuccess) @@ -29,7 +29,7 @@ namespace SourceGit.Commands switch (nextPartIdx) { case 0: - _current = new Models.CommitWithMessage(); + _current = new Models.InteractiveCommit(); _current.Commit.SHA = line; _commits.Add(_current); break; @@ -52,7 +52,7 @@ namespace SourceGit.Commands _current.Commit.CommitterTime = ulong.Parse(line); break; default: - var boundary = rs.StdOut.IndexOf(_boundary, end + 1); + var boundary = rs.StdOut.IndexOf(_boundary, end + 1, StringComparison.Ordinal); if (boundary > end) { _current.Message = rs.StdOut.Substring(start, boundary - start - 1); @@ -88,8 +88,8 @@ namespace SourceGit.Commands _current.Commit.Parents.AddRange(data.Split(separator: ' ', options: StringSplitOptions.RemoveEmptyEntries)); } - private List _commits = new List(); - private Models.CommitWithMessage _current = null; + private List _commits = []; + private Models.InteractiveCommit _current = null; private string _boundary = ""; } } diff --git a/src/Models/Commit.cs b/src/Models/Commit.cs index f015130a..5c48b0c0 100644 --- a/src/Models/Commit.cs +++ b/src/Models/Commit.cs @@ -112,9 +112,9 @@ namespace SourceGit.Models } } - public class CommitWithMessage + public class CommitFullMessage { - public Commit Commit { get; set; } = new Commit(); - public string Message { get; set; } = ""; + public string Message { get; set; } = string.Empty; + public List Links { get; set; } = []; } } diff --git a/src/Models/InteractiveRebase.cs b/src/Models/InteractiveRebase.cs index 0980587a..691aadeb 100644 --- a/src/Models/InteractiveRebase.cs +++ b/src/Models/InteractiveRebase.cs @@ -12,6 +12,12 @@ namespace SourceGit.Models Drop, } + public class InteractiveCommit + { + public Commit Commit { get; set; } = new Commit(); + public string Message { get; set; } = string.Empty; + } + public class InteractiveRebaseJob { public string SHA { get; set; } = string.Empty; diff --git a/src/Models/RevisionFile.cs b/src/Models/RevisionFile.cs index f1f5265f..8cc1be2a 100644 --- a/src/Models/RevisionFile.cs +++ b/src/Models/RevisionFile.cs @@ -29,6 +29,6 @@ namespace SourceGit.Models public class RevisionSubmodule { public Commit Commit { get; set; } = null; - public string FullMessage { get; set; } = string.Empty; + public CommitFullMessage FullMessage { get; set; } = null; } } diff --git a/src/ViewModels/CommitDetail.cs b/src/ViewModels/CommitDetail.cs index 7c5aa28f..26fa37c1 100644 --- a/src/ViewModels/CommitDetail.cs +++ b/src/ViewModels/CommitDetail.cs @@ -5,7 +5,6 @@ using System.IO; using System.Text.RegularExpressions; using System.Threading.Tasks; -using Avalonia.Collections; using Avalonia.Controls; using Avalonia.Media.Imaging; using Avalonia.Platform.Storage; @@ -46,7 +45,7 @@ namespace SourceGit.ViewModels } } - public string FullMessage + public Models.CommitFullMessage FullMessage { get => _fullMessage; private set => SetProperty(ref _fullMessage, value); @@ -85,11 +84,11 @@ namespace SourceGit.ViewModels } } - public AvaloniaList Children + public List Children { - get; - private set; - } = []; + get => _children; + private set => SetProperty(ref _children, value); + } public string SearchChangeFilter { @@ -109,17 +108,12 @@ namespace SourceGit.ViewModels set => SetProperty(ref _viewRevisionFileContent, value); } - public AvaloniaList WebLinks + public List WebLinks { get; private set; } = []; - public AvaloniaList IssueTrackerRules - { - get => _repo.Settings?.IssueTrackerRules; - } - public string RevisionFileSearchFilter { get => _revisionFileSearchFilter; @@ -127,25 +121,23 @@ namespace SourceGit.ViewModels { if (SetProperty(ref _revisionFileSearchFilter, value)) { - RevisionFileSearchSuggestion.Clear(); - if (!string.IsNullOrEmpty(value)) { - if (_revisionFiles.Count == 0) + if (_revisionFiles == null) { var sha = Commit.SHA; Task.Run(() => { var files = new Commands.QueryRevisionFileNames(_repo.FullPath, sha).Result(); + var filesList = new List(); + filesList.AddRange(files); Dispatcher.UIThread.Invoke(() => { if (sha == Commit.SHA) { - _revisionFiles.Clear(); - _revisionFiles.AddRange(files); - + _revisionFiles = filesList; if (!string.IsNullOrEmpty(_revisionFileSearchFilter)) UpdateRevisionFileSearchSuggestion(); } @@ -159,23 +151,17 @@ namespace SourceGit.ViewModels } else { - IsRevisionFileSearchSuggestionOpen = false; + RevisionFileSearchSuggestion = null; GC.Collect(); } } } } - public AvaloniaList RevisionFileSearchSuggestion + public List RevisionFileSearchSuggestion { - get; - private set; - } = []; - - public bool IsRevisionFileSearchSuggestionOpen - { - get => _isRevisionFileSearchSuggestionOpen; - set => SetProperty(ref _isRevisionFileSearchSuggestionOpen, value); + get => _revisionFileSearchSuggestion; + private set => SetProperty(ref _revisionFileSearchSuggestion, value); } public CommitDetail(Repository repo) @@ -212,23 +198,17 @@ namespace SourceGit.ViewModels { _repo = null; _commit = null; - - if (_changes != null) - _changes.Clear(); - if (_visibleChanges != null) - _visibleChanges.Clear(); - if (_selectedChanges != null) - _selectedChanges.Clear(); - + _changes = null; + _visibleChanges = null; + _selectedChanges = null; _signInfo = null; _searchChangeFilter = null; _diffContext = null; _viewRevisionFileContent = null; _cancelToken = null; - WebLinks.Clear(); - _revisionFiles.Clear(); - RevisionFileSearchSuggestion.Clear(); + _revisionFiles = null; + _revisionFileSearchSuggestion = null; } public void NavigateTo(string commitSHA) @@ -251,6 +231,11 @@ namespace SourceGit.ViewModels RevisionFileSearchFilter = string.Empty; } + public void CancelRevisionFileSuggestions() + { + RevisionFileSearchSuggestion = null; + } + public Models.Commit GetParent(string sha) { return new Commands.QuerySingleCommit(_repo.FullPath, sha).Result(); @@ -322,7 +307,12 @@ namespace SourceGit.ViewModels if (commit != null) { var body = new Commands.QueryCommitFullMessage(submoduleRoot, file.SHA).Result(); - var submodule = new Models.RevisionSubmodule() { Commit = commit, FullMessage = body }; + var submodule = new Models.RevisionSubmodule() + { + Commit = commit, + FullMessage = new Models.CommitFullMessage { Message = body } + }; + Dispatcher.UIThread.Invoke(() => ViewRevisionFileContent = submodule); } else @@ -332,7 +322,7 @@ namespace SourceGit.ViewModels ViewRevisionFileContent = new Models.RevisionSubmodule() { Commit = new Models.Commit() { SHA = file.SHA }, - FullMessage = string.Empty, + FullMessage = null, }; }); } @@ -622,23 +612,22 @@ namespace SourceGit.ViewModels private void Refresh() { _changes = null; - _revisionFiles.Clear(); + _revisionFiles = null; SignInfo = null; ViewRevisionFileContent = null; - Children.Clear(); + Children = null; RevisionFileSearchFilter = string.Empty; - IsRevisionFileSearchSuggestionOpen = false; - - GC.Collect(); + RevisionFileSearchSuggestion = null; if (_commit == null) return; Task.Run(() => { - var fullMessage = new Commands.QueryCommitFullMessage(_repo.FullPath, _commit.SHA).Result(); - Dispatcher.UIThread.Invoke(() => FullMessage = fullMessage); + var message = new Commands.QueryCommitFullMessage(_repo.FullPath, _commit.SHA).Result(); + var links = ParseLinksInMessage(message); + Dispatcher.UIThread.Invoke(() => FullMessage = new Models.CommitFullMessage { Message = message, Links = links }); }); Task.Run(() => @@ -694,6 +683,49 @@ namespace SourceGit.ViewModels }); } + private List ParseLinksInMessage(string message) + { + var links = new List(); + if (_repo.Settings.IssueTrackerRules is { Count: > 0 } rules) + { + foreach (var rule in rules) + rule.Matches(links, message); + } + + var shas = REG_SHA_FORMAT().Matches(message); + for (int i = 0; i < shas.Count; i++) + { + var sha = shas[i]; + if (!sha.Success) + continue; + + var hash = sha.Groups[1].Value; + var test = new Commands.IsCommitSHA(_repo.FullPath, hash).Result(); + if (!test) + continue; + + var start = sha.Index; + var len = sha.Length; + var intersect = false; + foreach (var link in links) + { + if (link.Intersect(start, len)) + { + intersect = true; + break; + } + } + + if (!intersect) + links.Add(new Models.Hyperlink(start, len, hash, true)); + } + + if (links.Count > 0) + links.Sort((l, r) => l.Start - r.Start); + + return links; + } + private void RefreshVisibleChanges() { if (_changes == null) @@ -813,11 +845,12 @@ namespace SourceGit.ViewModels break; } - RevisionFileSearchSuggestion.Clear(); - RevisionFileSearchSuggestion.AddRange(suggestion); - IsRevisionFileSearchSuggestionOpen = suggestion.Count > 0; + RevisionFileSearchSuggestion = suggestion; } + [GeneratedRegex(@"\b([0-9a-fA-F]{6,40})\b")] + private static partial Regex REG_SHA_FORMAT(); + [GeneratedRegex(@"^version https://git-lfs.github.com/spec/v\d+\r?\noid sha256:([0-9a-f]+)\r?\nsize (\d+)[\r\n]*$")] private static partial Regex REG_LFS_FORMAT(); @@ -828,8 +861,9 @@ namespace SourceGit.ViewModels private Repository _repo = null; private Models.Commit _commit = null; - private string _fullMessage = string.Empty; + private Models.CommitFullMessage _fullMessage = null; private Models.CommitSignInfo _signInfo = null; + private List _children = null; private List _changes = null; private List _visibleChanges = null; private List _selectedChanges = null; @@ -837,8 +871,8 @@ namespace SourceGit.ViewModels private DiffContext _diffContext = null; private object _viewRevisionFileContent = null; private Commands.Command.CancelToken _cancelToken = null; - private List _revisionFiles = []; + private List _revisionFiles = null; private string _revisionFileSearchFilter = string.Empty; - private bool _isRevisionFileSearchSuggestionOpen = false; + private List _revisionFileSearchSuggestion = null; } } diff --git a/src/ViewModels/DiffContext.cs b/src/ViewModels/DiffContext.cs index b10f4b62..6dd836bf 100644 --- a/src/ViewModels/DiffContext.cs +++ b/src/ViewModels/DiffContext.cs @@ -235,13 +235,17 @@ namespace SourceGit.ViewModels if (commit != null) { var body = new Commands.QueryCommitFullMessage(repo, sha).Result(); - return new Models.RevisionSubmodule() { Commit = commit, FullMessage = body }; + return new Models.RevisionSubmodule() + { + Commit = commit, + FullMessage = new Models.CommitFullMessage { Message = body } + }; } return new Models.RevisionSubmodule() { Commit = new Models.Commit() { SHA = sha }, - FullMessage = string.Empty, + FullMessage = null, }; } diff --git a/src/ViewModels/FileHistories.cs b/src/ViewModels/FileHistories.cs index 7e248274..417b816d 100644 --- a/src/ViewModels/FileHistories.cs +++ b/src/ViewModels/FileHistories.cs @@ -123,12 +123,20 @@ namespace SourceGit.ViewModels if (commit != null) { var message = new Commands.QueryCommitFullMessage(submoduleRoot, obj.SHA).Result(); - var module = new Models.RevisionSubmodule() { Commit = commit, FullMessage = message }; + var module = new Models.RevisionSubmodule() + { + Commit = commit, + FullMessage = new Models.CommitFullMessage { Message = message } + }; Dispatcher.UIThread.Invoke(() => ViewContent = new FileHistoriesRevisionFile(_file, module)); } else { - var module = new Models.RevisionSubmodule() { Commit = new Models.Commit() { SHA = obj.SHA }, FullMessage = "" }; + var module = new Models.RevisionSubmodule() + { + Commit = new Models.Commit() { SHA = obj.SHA }, + FullMessage = null + }; Dispatcher.UIThread.Invoke(() => ViewContent = new FileHistoriesRevisionFile(_file, module)); } }); diff --git a/src/ViewModels/InteractiveRebase.cs b/src/ViewModels/InteractiveRebase.cs index 9f28fbc7..2fd2d67c 100644 --- a/src/ViewModels/InteractiveRebase.cs +++ b/src/ViewModels/InteractiveRebase.cs @@ -118,7 +118,7 @@ namespace SourceGit.ViewModels Task.Run(() => { - var commits = new Commands.QueryCommitsWithFullMessage(repoPath, $"{on.SHA}..HEAD").Result(); + var commits = new Commands.QueryCommitsForInteractiveRebase(repoPath, on.SHA).Result(); var list = new List(); foreach (var c in commits) diff --git a/src/Views/CommitBaseInfo.axaml b/src/Views/CommitBaseInfo.axaml index c92a3612..4ff8f20f 100644 --- a/src/Views/CommitBaseInfo.axaml +++ b/src/Views/CommitBaseInfo.axaml @@ -95,8 +95,8 @@ - - + + @@ -133,8 +133,8 @@ - - + + @@ -187,8 +187,7 @@ diff --git a/src/Views/CommitBaseInfo.axaml.cs b/src/Views/CommitBaseInfo.axaml.cs index ce1a7cfd..8767db9f 100644 --- a/src/Views/CommitBaseInfo.axaml.cs +++ b/src/Views/CommitBaseInfo.axaml.cs @@ -1,7 +1,7 @@ +using System.Collections.Generic; using System.Threading.Tasks; using Avalonia; -using Avalonia.Collections; using Avalonia.Controls; using Avalonia.Input; using Avalonia.Interactivity; @@ -11,13 +11,13 @@ namespace SourceGit.Views { public partial class CommitBaseInfo : UserControl { - public static readonly StyledProperty MessageProperty = - AvaloniaProperty.Register(nameof(Message), string.Empty); + public static readonly StyledProperty FullMessageProperty = + AvaloniaProperty.Register(nameof(FullMessage)); - public string Message + public Models.CommitFullMessage FullMessage { - get => GetValue(MessageProperty); - set => SetValue(MessageProperty, value); + get => GetValue(FullMessageProperty); + set => SetValue(FullMessageProperty, value); } public static readonly StyledProperty SignInfoProperty = @@ -38,28 +38,19 @@ namespace SourceGit.Views set => SetValue(SupportsContainsInProperty, value); } - public static readonly StyledProperty> WebLinksProperty = - AvaloniaProperty.Register>(nameof(WebLinks)); + public static readonly StyledProperty> WebLinksProperty = + AvaloniaProperty.Register>(nameof(WebLinks)); - public AvaloniaList WebLinks + public List WebLinks { get => GetValue(WebLinksProperty); set => SetValue(WebLinksProperty, value); } - public static readonly StyledProperty> IssueTrackerRulesProperty = - AvaloniaProperty.Register>(nameof(IssueTrackerRules)); + public static readonly StyledProperty> ChildrenProperty = + AvaloniaProperty.Register>(nameof(Children)); - public AvaloniaList IssueTrackerRules - { - get => GetValue(IssueTrackerRulesProperty); - set => SetValue(IssueTrackerRulesProperty, value); - } - - public static readonly StyledProperty> ChildrenProperty = - AvaloniaProperty.Register>(nameof(Children)); - - public AvaloniaList Children + public List Children { get => GetValue(ChildrenProperty); set => SetValue(ChildrenProperty, value); diff --git a/src/Views/CommitDetail.axaml b/src/Views/CommitDetail.axaml index d0d52473..28b21eb7 100644 --- a/src/Views/CommitDetail.axaml +++ b/src/Views/CommitDetail.axaml @@ -20,12 +20,11 @@ + Children="{Binding Children}"/> diff --git a/src/Views/CommitMessagePresenter.cs b/src/Views/CommitMessagePresenter.cs index dc8a3bb7..002beda1 100644 --- a/src/Views/CommitMessagePresenter.cs +++ b/src/Views/CommitMessagePresenter.cs @@ -1,10 +1,8 @@ using System; using System.Collections.Generic; -using System.Text.RegularExpressions; using System.Threading.Tasks; using Avalonia; -using Avalonia.Collections; using Avalonia.Controls; using Avalonia.Controls.Documents; using Avalonia.Input; @@ -13,27 +11,15 @@ using Avalonia.VisualTree; namespace SourceGit.Views { - public partial class CommitMessagePresenter : SelectableTextBlock + public class CommitMessagePresenter : SelectableTextBlock { - [GeneratedRegex(@"\b([0-9a-fA-F]{6,40})\b")] - private static partial Regex REG_SHA_FORMAT(); + public static readonly StyledProperty FullMessageProperty = + AvaloniaProperty.Register(nameof(FullMessage)); - public static readonly StyledProperty MessageProperty = - AvaloniaProperty.Register(nameof(Message)); - - public string Message + public Models.CommitFullMessage FullMessage { - get => GetValue(MessageProperty); - set => SetValue(MessageProperty, value); - } - - public static readonly StyledProperty> IssueTrackerRulesProperty = - AvaloniaProperty.Register>(nameof(IssueTrackerRules)); - - public AvaloniaList IssueTrackerRules - { - get => GetValue(IssueTrackerRulesProperty); - set => SetValue(IssueTrackerRulesProperty, value); + get => GetValue(FullMessageProperty); + set => SetValue(FullMessageProperty, value); } protected override Type StyleKeyOverride => typeof(SelectableTextBlock); @@ -42,69 +28,36 @@ namespace SourceGit.Views { base.OnPropertyChanged(change); - if (change.Property == MessageProperty || change.Property == IssueTrackerRulesProperty) + if (change.Property == FullMessageProperty) { Inlines!.Clear(); _inlineCommits.Clear(); - _matches = null; _lastHover = null; ClearHoveredIssueLink(); - var message = Message; + var message = FullMessage?.Message; if (string.IsNullOrEmpty(message)) return; - var matches = new List(); - if (IssueTrackerRules is { Count: > 0 } rules) - { - foreach (var rule in rules) - rule.Matches(matches, message); - } - - var shas = REG_SHA_FORMAT().Matches(message); - for (int i = 0; i < shas.Count; i++) - { - var sha = shas[i]; - if (!sha.Success) - continue; - - var start = sha.Index; - var len = sha.Length; - var intersect = false; - foreach (var match in matches) - { - if (match.Intersect(start, len)) - { - intersect = true; - break; - } - } - - if (!intersect) - matches.Add(new Models.Hyperlink(start, len, sha.Groups[1].Value, true)); - } - - if (matches.Count == 0) + var links = FullMessage?.Links; + if (links == null || links.Count == 0) { Inlines.Add(new Run(message)); return; } - matches.Sort((l, r) => l.Start - r.Start); - _matches = matches; - var inlines = new List(); var pos = 0; - foreach (var match in matches) + foreach (var link in links) { - if (match.Start > pos) - inlines.Add(new Run(message.Substring(pos, match.Start - pos))); + if (link.Start > pos) + inlines.Add(new Run(message.Substring(pos, link.Start - pos))); - var link = new Run(message.Substring(match.Start, match.Length)); - link.Classes.Add(match.IsCommitSHA ? "commit_link" : "issue_link"); - inlines.Add(link); + var run = new Run(message.Substring(link.Start, link.Length)); + run.Classes.Add(link.IsCommitSHA ? "commit_link" : "issue_link"); + inlines.Add(run); - pos = match.Start + match.Length; + pos = link.Start + link.Length; } if (pos < message.Length) @@ -134,7 +87,7 @@ namespace SourceGit.Views scrollViewer.LineDown(); } } - else if (_matches != null) + else if (FullMessage is { Links: { Count: > 0 } links }) { var point = e.GetPosition(this) - new Point(Padding.Left, Padding.Top); var x = Math.Min(Math.Max(point.X, 0), Math.Max(TextLayout.WidthIncludingTrailingWhitespace, 0)); @@ -142,25 +95,25 @@ namespace SourceGit.Views point = new Point(x, y); var pos = TextLayout.HitTestPoint(point).TextPosition; - foreach (var match in _matches) + foreach (var link in links) { - if (!match.Intersect(pos, 1)) + if (!link.Intersect(pos, 1)) continue; - if (match == _lastHover) + if (link == _lastHover) return; SetCurrentValue(CursorProperty, Cursor.Parse("Hand")); - _lastHover = match; - if (!match.IsCommitSHA) + _lastHover = link; + if (!link.IsCommitSHA) { - ToolTip.SetTip(this, match.Link); + ToolTip.SetTip(this, link.Link); ToolTip.SetIsOpen(this, true); } else { - ProcessHoverCommitLink(match); + ProcessHoverCommitLink(link); } return; @@ -361,7 +314,6 @@ namespace SourceGit.Views } } - private List _matches = null; private Models.Hyperlink _lastHover = null; private Dictionary _inlineCommits = new(); } diff --git a/src/Views/DiffView.axaml b/src/Views/DiffView.axaml index 3644f8fc..2842715c 100644 --- a/src/Views/DiffView.axaml +++ b/src/Views/DiffView.axaml @@ -257,7 +257,7 @@ - + @@ -271,7 +271,7 @@ - + diff --git a/src/Views/RevisionFileContentViewer.axaml b/src/Views/RevisionFileContentViewer.axaml index de8b3b75..f7599ba0 100644 --- a/src/Views/RevisionFileContentViewer.axaml +++ b/src/Views/RevisionFileContentViewer.axaml @@ -63,7 +63,7 @@ - + diff --git a/src/Views/RevisionFiles.axaml b/src/Views/RevisionFiles.axaml index 3d5cff38..6847b14b 100644 --- a/src/Views/RevisionFiles.axaml +++ b/src/Views/RevisionFiles.axaml @@ -44,7 +44,7 @@ + IsOpen="{Binding RevisionFileSearchSuggestion, Converter={x:Static c:ListConverters.IsNotNullOrEmpty}}"> 0) { SearchSuggestionBox.Focus(NavigationMethod.Tab); SearchSuggestionBox.SelectedIndex = 0; @@ -33,12 +33,7 @@ namespace SourceGit.Views } else if (e.Key == Key.Escape) { - if (vm.IsRevisionFileSearchSuggestionOpen) - { - vm.RevisionFileSearchSuggestion.Clear(); - vm.IsRevisionFileSearchSuggestionOpen = false; - } - + vm.CancelRevisionFileSuggestions(); e.Handled = true; } } @@ -57,7 +52,7 @@ namespace SourceGit.Views if (e.Key == Key.Escape) { - vm.RevisionFileSearchSuggestion.Clear(); + vm.CancelRevisionFileSuggestions(); e.Handled = true; } else if (e.Key == Key.Enter && SearchSuggestionBox.SelectedItem is string content)