From 7f8b8a19a02d9837fcda5d834d26dbb2160f0b6e Mon Sep 17 00:00:00 2001 From: leo Date: Tue, 30 Jul 2024 15:59:54 +0800 Subject: [PATCH] feature: add auto complete box for searching commits by file path --- src/Commands/QueryCurrentRevisionFiles.cs | 21 ++++ src/ViewModels/Repository.cs | 77 +++++++++++++- src/Views/Repository.axaml | 116 ++++++++++++++++------ src/Views/Repository.axaml.cs | 56 ++++++++++- 4 files changed, 235 insertions(+), 35 deletions(-) create mode 100644 src/Commands/QueryCurrentRevisionFiles.cs diff --git a/src/Commands/QueryCurrentRevisionFiles.cs b/src/Commands/QueryCurrentRevisionFiles.cs new file mode 100644 index 00000000..217ea20e --- /dev/null +++ b/src/Commands/QueryCurrentRevisionFiles.cs @@ -0,0 +1,21 @@ +namespace SourceGit.Commands +{ + public class QueryCurrentRevisionFiles : Command + { + public QueryCurrentRevisionFiles(string repo) + { + WorkingDirectory = repo; + Context = repo; + Args = "ls-tree -r --name-only HEAD"; + } + + public string[] Result() + { + var rs = ReadToEnd(); + if (rs.IsSuccess) + return rs.StdOut.Split('\n', System.StringSplitOptions.RemoveEmptyEntries); + + return []; + } + } +} diff --git a/src/ViewModels/Repository.cs b/src/ViewModels/Repository.cs index 16290c67..92160b2d 100644 --- a/src/ViewModels/Repository.cs +++ b/src/ViewModels/Repository.cs @@ -4,6 +4,7 @@ using System.IO; using System.Text.Json; using System.Threading.Tasks; +using Avalonia.Collections; using Avalonia.Controls; using Avalonia.Media; using Avalonia.Media.Imaging; @@ -170,8 +171,15 @@ namespace SourceGit.ViewModels { SearchedCommits = new List(); SearchCommitFilter = string.Empty; + SearchCommitFilterSuggestion.Clear(); + IsSearchCommitSuggestionOpen = false; + _revisionFiles.Clear(); + if (value) + { SelectedViewIndex = 0; + UpdateCurrentRevisionFilesForSearchSuggestion(); + } } } } @@ -185,15 +193,59 @@ namespace SourceGit.ViewModels public int SearchCommitFilterType { get => _searchCommitFilterType; - set => SetProperty(ref _searchCommitFilterType, value); + set + { + if (SetProperty(ref _searchCommitFilterType, value)) + UpdateCurrentRevisionFilesForSearchSuggestion(); + } } public string SearchCommitFilter { get => _searchCommitFilter; - set => SetProperty(ref _searchCommitFilter, value); + set + { + if (SetProperty(ref _searchCommitFilter, value) && + _searchCommitFilterType == 3 && + !string.IsNullOrEmpty(value) && + value.Length >= 2 && + _revisionFiles.Count > 0) + { + var suggestion = new List(); + foreach (var file in _revisionFiles) + { + if (file.Contains(value, StringComparison.OrdinalIgnoreCase) && file.Length != value.Length) + { + suggestion.Add(file); + if (suggestion.Count > 100) + break; + } + } + + SearchCommitFilterSuggestion.Clear(); + SearchCommitFilterSuggestion.AddRange(suggestion); + IsSearchCommitSuggestionOpen = SearchCommitFilterSuggestion.Count > 0; + } + else if (SearchCommitFilterSuggestion.Count > 0) + { + SearchCommitFilterSuggestion.Clear(); + IsSearchCommitSuggestionOpen = false; + } + } } + public bool IsSearchCommitSuggestionOpen + { + get => _isSearchCommitSuggestionOpen; + set => SetProperty(ref _isSearchCommitSuggestionOpen, value); + } + + public AvaloniaList SearchCommitFilterSuggestion + { + get; + private set; + } = new AvaloniaList(); + public List SearchedCommits { get => _searchedCommits; @@ -306,6 +358,9 @@ namespace SourceGit.ViewModels _visibleTags.Clear(); _submodules.Clear(); _searchedCommits.Clear(); + + _revisionFiles.Clear(); + SearchCommitFilterSuggestion.Clear(); } public void RefreshAll() @@ -450,6 +505,8 @@ namespace SourceGit.ViewModels return; IsSearchLoadingVisible = true; + IsSearchCommitSuggestionOpen = false; + SearchCommitFilterSuggestion.Clear(); Task.Run(() => { @@ -1886,6 +1943,20 @@ namespace SourceGit.ViewModels return visible; } + private void UpdateCurrentRevisionFilesForSearchSuggestion() + { + _revisionFiles.Clear(); + + if (_searchCommitFilterType == 3) + { + Task.Run(() => + { + var files = new Commands.QueryCurrentRevisionFiles(_fullpath).Result(); + Dispatcher.UIThread.Invoke(() => _revisionFiles.AddRange(files)); + }); + } + } + private string _fullpath = string.Empty; private string _gitDir = string.Empty; private Models.RepositorySettings _settings = null; @@ -1899,9 +1970,11 @@ namespace SourceGit.ViewModels private bool _isSearching = false; private bool _isSearchLoadingVisible = false; + private bool _isSearchCommitSuggestionOpen = false; private int _searchCommitFilterType = 0; private string _searchCommitFilter = string.Empty; private List _searchedCommits = new List(); + private List _revisionFiles = new List(); private bool _isLocalBranchGroupExpanded = true; private bool _isRemoteGroupExpanded = false; diff --git a/src/Views/Repository.axaml b/src/Views/Repository.axaml index cfaaf1f2..825bb235 100644 --- a/src/Views/Repository.axaml +++ b/src/Views/Repository.axaml @@ -453,40 +453,92 @@ - + - - - - - - - - - + Margin="6,0,0,0" + Fill="{DynamicResource Brush.FG2}" + Data="{StaticResource Icons.Search}"/> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +