diff --git a/src/SourceGit.csproj b/src/SourceGit.csproj index b2d603770..009d2c89d 100644 --- a/src/SourceGit.csproj +++ b/src/SourceGit.csproj @@ -55,9 +55,9 @@ - - - + + + diff --git a/src/ViewModels/Histories.cs b/src/ViewModels/Histories.cs index fcd77b17f..d6c15930c 100644 --- a/src/ViewModels/Histories.cs +++ b/src/ViewModels/Histories.cs @@ -2,6 +2,7 @@ using System.Collections; using System.Collections.Generic; using System.IO; +using System.Linq; using System.Threading.Tasks; using Avalonia.Controls; @@ -60,15 +61,7 @@ public bool IsDateTimeColumnVisible public List Commits { get => _commits; - set - { - var lastSelected = SelectedCommit; - if (SetProperty(ref _commits, value)) - { - if (value.Count > 0 && lastSelected != null) - SelectedCommit = value.Find(x => x.SHA == lastSelected.SHA); - } - } + set => SetProperty(ref _commits, value); } public Models.CommitGraph Graph @@ -83,6 +76,18 @@ public Models.Commit SelectedCommit set => SetProperty(ref _selectedCommit, value); } + public Models.Commit LastSelectedCommit + { + get => _lastSelectedCommit; + set => SetProperty(ref _lastSelectedCommit, value); + } + + public List LastSelectedCommits + { + get => _lastSelectedCommits; + private set => SetProperty(ref _lastSelectedCommits, value); + } + public long NavigationId { get => _navigationId; @@ -137,6 +142,8 @@ public void Dispose() _repo = null; _graph = null; _selectedCommit = null; + _lastSelectedCommits = null; + _lastSelectedCommit = null; _detailContext?.Dispose(); _detailContext = null; } @@ -209,7 +216,14 @@ public void NavigateTo(string commitSHA) }); } - public void Select(IList commits) + /// + /// + /// notes: if multi selects, `AutoSelectedCommit` which `Binding Mode=OneWay` will not be updated, + /// so that we could not get the lastSelectedCommit automatically + /// + /// + /// + public void Select(IList commits, object selectedCommit) { if (_ignoreSelectionChange) return; @@ -218,6 +232,7 @@ public void Select(IList commits) { _repo.SearchCommitContext.Selected = null; DetailContext = null; + return; } else if (commits.Count == 1) { @@ -225,6 +240,7 @@ public void Select(IList commits) if (_repo.SearchCommitContext.Selected == null || _repo.SearchCommitContext.Selected.SHA != commit.SHA) _repo.SearchCommitContext.Selected = _repo.SearchCommitContext.Results?.Find(x => x.SHA == commit.SHA); + // MarkLastSelectedCommitsAsSelected(); SelectedCommit = commit; NavigationId = _navigationId + 1; @@ -252,6 +268,25 @@ public void Select(IList commits) _repo.SearchCommitContext.Selected = null; DetailContext = new Models.Count(commits.Count); } + + LastSelectedCommit = selectedCommit as Models.Commit; + LastSelectedCommits = commits.Cast().ToList(); + } + + public void MarkLastSelectedCommitsAsSelected(params IList commits) + { + var availableCommits = Commits.Where(x => commits.Any(y => y.SHA == x.SHA)).ToList(); + + // if LastSelectedCommits is not empty, find the AutoSelectedCommit or get last one + if (availableCommits.Count > 0 && LastSelectedCommit != null) + { + // find in oldAvailable or get last one + SelectedCommit = availableCommits.Find(x => x.SHA == LastSelectedCommit.SHA) + ?? availableCommits.FirstOrDefault(); + } + // set selectItem above(1item), now select others too + LastSelectedCommits = availableCommits; + NavigationId = _navigationId + 1; } public async Task GetCommitAsync(string sha) @@ -466,6 +501,8 @@ public void CompareWithWorktree(Models.Commit commit) private CommitDetailSharedData _commitDetailSharedData = null; private bool _isLoading = true; private List _commits = new List(); + private List _lastSelectedCommits = []; + private Models.Commit _lastSelectedCommit = null; private Models.CommitGraph _graph = null; private Models.Commit _selectedCommit = null; private Models.Bisect _bisect = null; diff --git a/src/ViewModels/Repository.cs b/src/ViewModels/Repository.cs index 2945f7c63..82b0e8d4b 100644 --- a/src/ViewModels/Repository.cs +++ b/src/ViewModels/Repository.cs @@ -1,13 +1,12 @@ using System; using System.Collections.Generic; using System.IO; +using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; - using Avalonia.Collections; using Avalonia.Threading; - using CommunityToolkit.Mvvm.ComponentModel; namespace SourceGit.ViewModels @@ -282,6 +281,12 @@ public SearchCommitContext SearchCommitContext get => _searchCommitContext; } + public List SelectedCommits + { + get => _selectCommits; + set => SetProperty(ref _selectCommits, value); + } + public bool IsLocalBranchGroupExpanded { get => _uiStates.IsLocalBranchesExpandedInSideBar; @@ -1219,6 +1224,7 @@ public void RefreshCommits() { if (_cancellationRefreshCommits is { IsCancellationRequested: false }) _cancellationRefreshCommits.Cancel(); + var oldSelectedCommits = _selectCommits.ToList(); _cancellationRefreshCommits = new CancellationTokenSource(); var token = _cancellationRefreshCommits.Token; @@ -1248,6 +1254,8 @@ public void RefreshCommits() BisectState = _histories.UpdateBisectInfo(); + _histories.MarkLastSelectedCommitsAsSelected(_histories.LastSelectedCommits); + if (!string.IsNullOrEmpty(_navigateToCommitDelayed)) NavigateToCommit(_navigateToCommitDelayed); } @@ -1957,6 +1965,7 @@ private async Task AutoFetchOnUIThread() private bool _isSearchingCommits = false; private SearchCommitContext _searchCommitContext = null; + private List _selectCommits = new List(); private string _filter = string.Empty; private List _remotes = []; diff --git a/src/Views/Histories.axaml.cs b/src/Views/Histories.axaml.cs index 39312ec6e..e4fb4fc96 100644 --- a/src/Views/Histories.axaml.cs +++ b/src/Views/Histories.axaml.cs @@ -123,6 +123,15 @@ public long NavigationId set => SetValue(NavigationIdProperty, value); } + public static readonly StyledProperty> LastSelectedCommitsProperty = + AvaloniaProperty.Register>(nameof(LastSelectedCommits)); + + public List LastSelectedCommits + { + get => GetValue(LastSelectedCommitsProperty); + set => SetValue(LastSelectedCommitsProperty, value); + } + public static readonly StyledProperty IsScrollToTopVisibleProperty = AvaloniaProperty.Register(nameof(IsScrollToTopVisible)); @@ -146,6 +155,18 @@ protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs chang if (CommitListContainer is { SelectedItems.Count: 1, IsLoaded: true } dataGrid) dataGrid.ScrollIntoView(dataGrid.SelectedItem, null); } + if (change.Property == LastSelectedCommitsProperty) + { + if (LastSelectedCommits?.Count > 1 && + (CommitListContainer is DataGrid { IsLoaded: true } dataGrid)) + { + foreach (var c in LastSelectedCommits) + { + dataGrid.SelectedItems.Add(c); + } + } + } + } private void OnCommitListLoaded(object sender, RoutedEventArgs e) @@ -301,7 +322,7 @@ private void OnScrollToTopPointerPressed(object sender, PointerPressedEventArgs private void OnCommitListSelectionChanged(object _, SelectionChangedEventArgs e) { if (DataContext is ViewModels.Histories histories) - histories.Select(CommitListContainer.SelectedItems); + histories.Select(CommitListContainer.SelectedItems, CommitListContainer.SelectedItem); e.Handled = true; } diff --git a/src/Views/Repository.axaml b/src/Views/Repository.axaml index 8151765df..3866331e4 100644 --- a/src/Views/Repository.axaml +++ b/src/Views/Repository.axaml @@ -424,7 +424,7 @@ - + - +