From ee4d8a6a0e50a63bc3700541023db442830c0b89 Mon Sep 17 00:00:00 2001 From: leo Date: Tue, 10 Jun 2025 11:18:20 +0800 Subject: [PATCH] code_review: PR #1408 Signed-off-by: leo --- src/ViewModels/Blame.cs | 213 ++++++++++++++++++++------------- src/ViewModels/CommitDetail.cs | 4 +- src/Views/Blame.axaml | 55 ++++++--- src/Views/Blame.axaml.cs | 40 +++---- 4 files changed, 182 insertions(+), 130 deletions(-) diff --git a/src/ViewModels/Blame.cs b/src/ViewModels/Blame.cs index 4b57575b..e9917aaf 100644 --- a/src/ViewModels/Blame.cs +++ b/src/ViewModels/Blame.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Threading; using System.Threading.Tasks; using Avalonia.Threading; @@ -10,10 +11,25 @@ namespace SourceGit.ViewModels { public class Blame : ObservableObject { - public string Title + public string FilePath { - get => _title; - private set => SetProperty(ref _title, value); + get; + } + + public Models.Commit Revision + { + get => _revision; + private set => SetProperty(ref _revision, value); + } + + public Models.BlameData Data + { + get => _data; + private set + { + if (SetProperty(ref _data, value)) + OnPropertyChanged(nameof(IsBinary)); + } } public bool IsBinary @@ -21,92 +37,27 @@ namespace SourceGit.ViewModels get => _data != null && _data.IsBinary; } - public bool CanMoveBack + public bool CanBack { - get => _shaHistoryIndex > 0 && _shaHistory.Count > 1; - } - public bool CanMoveForward - { - get => _shaHistoryIndex < _shaHistory.Count - 1; + get => _navigationActiveIndex > 0; } - public Models.BlameData Data + public bool CanForward { - get => _data; - private set => SetProperty(ref _data, value); + get => _navigationActiveIndex < _navigationHistory.Count - 1; } - public Blame(string repo, string file, string revision) + public Blame(string repo, string file, Models.Commit commit) { + var sha = commit.SHA.Substring(0, 10); + + FilePath = file; + Revision = commit; + _repo = repo; - _file = file; - - SetBlameData($"{revision.AsSpan(0, 10)}", true); - } - - private void SetBlameData(string commitSHA, bool resetHistoryForward) - { - Title = $"{_file} @ {commitSHA}"; - - Task.Run(() => - { - var result = new Commands.Blame(_repo, _file, commitSHA).Result(); - Dispatcher.UIThread.Invoke(() => - { - Data = result; - OnPropertyChanged(nameof(IsBinary)); - }); - }); - - if (resetHistoryForward) - { - if (_shaHistoryIndex < _shaHistory.Count - 1) - _shaHistory.RemoveRange(_shaHistoryIndex + 1, _shaHistory.Count - _shaHistoryIndex - 1); - - if (_shaHistory.Count == 0 || _shaHistory[_shaHistoryIndex] != commitSHA) - { - _shaHistory.Add(commitSHA); - _shaHistoryIndex = _shaHistory.Count - 1; - } - } - - OnPropertyChanged(nameof(CanMoveBack)); - OnPropertyChanged(nameof(CanMoveForward)); - } - - public void Back() - { - --_shaHistoryIndex; - if (_shaHistoryIndex < 0) - _shaHistoryIndex = 0; - - NavigateToCommit(_shaHistory[_shaHistoryIndex], false); - } - - public void Forward() - { - ++_shaHistoryIndex; - if (_shaHistoryIndex >= _shaHistory.Count) - _shaHistoryIndex = _shaHistory.Count - 1; - - NavigateToCommit(_shaHistory[_shaHistoryIndex], false); - } - - public void NavigateToCommit(string commitSHA, bool resetHistoryForward) - { - var launcher = App.GetLauncher(); - if (launcher == null) - return; - - foreach (var page in launcher.Pages) - { - if (page.Data is Repository repo && repo.FullPath.Equals(_repo)) - { - repo.NavigateToCommit(commitSHA); - SetBlameData(commitSHA, resetHistoryForward); - break; - } - } + _navigationHistory.Add(sha); + _commits.Add(sha, commit); + SetBlameData(sha); } public string GetCommitMessage(string sha) @@ -119,12 +70,102 @@ namespace SourceGit.ViewModels return msg; } + public void Back() + { + if (_navigationActiveIndex <= 0) + return; + + _navigationActiveIndex--; + OnPropertyChanged(nameof(CanBack)); + OnPropertyChanged(nameof(CanForward)); + NavigateToCommit(_navigationHistory[_navigationActiveIndex]); + } + + public void Forward() + { + if (_navigationActiveIndex >= _navigationHistory.Count - 1) + return; + + _navigationActiveIndex++; + OnPropertyChanged(nameof(CanBack)); + OnPropertyChanged(nameof(CanForward)); + NavigateToCommit(_navigationHistory[_navigationActiveIndex]); + } + + public void NavigateToCommit(string commitSHA) + { + if (!_navigationHistory[_navigationActiveIndex].Equals(commitSHA, StringComparison.Ordinal)) + { + _navigationHistory.Add(commitSHA); + _navigationActiveIndex = _navigationHistory.Count - 1; + OnPropertyChanged(nameof(CanBack)); + OnPropertyChanged(nameof(CanForward)); + } + + if (!Revision.SHA.StartsWith(commitSHA, StringComparison.Ordinal)) + SetBlameData(commitSHA); + + if (App.GetLauncher() is { Pages: { } pages }) + { + foreach (var page in pages) + { + if (page.Data is Repository repo && repo.FullPath.Equals(_repo)) + { + repo.NavigateToCommit(commitSHA); + break; + } + } + } + } + + private void SetBlameData(string commitSHA) + { + if (_cancellationSource is { IsCancellationRequested: false }) + _cancellationSource.Cancel(); + + _cancellationSource = new CancellationTokenSource(); + var token = _cancellationSource.Token; + + if (_commits.TryGetValue(commitSHA, out var c)) + { + Revision = c; + } + else + { + Task.Run(() => + { + var result = new Commands.QuerySingleCommit(_repo, commitSHA).Result(); + + Dispatcher.UIThread.Invoke(() => + { + if (!token.IsCancellationRequested) + { + _commits.Add(commitSHA, result); + Revision = result ?? new Models.Commit() { SHA = commitSHA }; + } + }); + }, token); + } + + Task.Run(() => + { + var result = new Commands.Blame(_repo, FilePath, commitSHA).Result(); + + Dispatcher.UIThread.Invoke(() => + { + if (!token.IsCancellationRequested) + Data = result; + }); + }, token); + } + private string _repo; - private string _file; - private string _title; - private int _shaHistoryIndex = 0; - private List _shaHistory = []; + private Models.Commit _revision; + private CancellationTokenSource _cancellationSource = null; + private int _navigationActiveIndex = 0; + private List _navigationHistory = []; private Models.BlameData _data = null; - private Dictionary _commitMessages = new Dictionary(); + private Dictionary _commits = new(); + private Dictionary _commitMessages = new(); } } diff --git a/src/ViewModels/CommitDetail.cs b/src/ViewModels/CommitDetail.cs index 8d2ade09..3ec168db 100644 --- a/src/ViewModels/CommitDetail.cs +++ b/src/ViewModels/CommitDetail.cs @@ -313,7 +313,7 @@ namespace SourceGit.ViewModels blame.IsEnabled = change.Index != Models.ChangeState.Deleted; blame.Click += (_, ev) => { - App.ShowWindow(new Blame(_repo.FullPath, change.Path, _commit.SHA), false); + App.ShowWindow(new Blame(_repo.FullPath, change.Path, _commit), false); ev.Handled = true; }; @@ -481,7 +481,7 @@ namespace SourceGit.ViewModels blame.IsEnabled = file.Type == Models.ObjectType.Blob; blame.Click += (_, ev) => { - App.ShowWindow(new Blame(_repo.FullPath, file.Path, _commit.SHA), false); + App.ShowWindow(new Blame(_repo.FullPath, file.Path, _commit), false); ev.Handled = true; }; diff --git a/src/Views/Blame.axaml b/src/Views/Blame.axaml index e89bb2ec..6f299f8e 100644 --- a/src/Views/Blame.axaml +++ b/src/Views/Blame.axaml @@ -4,6 +4,7 @@ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:vm="using:SourceGit.ViewModels" xmlns:v="using:SourceGit.Views" + xmlns:c="using:SourceGit.Converters" mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" x:Class="SourceGit.Views.Blame" x:DataType="vm:Blame" @@ -43,22 +44,44 @@ - - - - - - + + + + + + + + + + + + + + + + diff --git a/src/Views/Blame.axaml.cs b/src/Views/Blame.axaml.cs index 47f3809d..72dd605d 100644 --- a/src/Views/Blame.axaml.cs +++ b/src/Views/Blame.axaml.cs @@ -224,9 +224,7 @@ namespace SourceGit.Views if (rect.Contains(pos)) { if (DataContext is ViewModels.Blame blame) - { - blame.NavigateToCommit(info.CommitSHA, true); - } + blame.NavigateToCommit(info.CommitSHA); e.Handled = true; break; @@ -433,8 +431,6 @@ namespace SourceGit.Views public Blame() { InitializeComponent(); - - AddHandler(PointerReleasedEvent, MouseUpHandler, handledEventsToo: true); } protected override void OnClosed(EventArgs e) @@ -443,30 +439,22 @@ namespace SourceGit.Views GC.Collect(); } - private void HistoryBack(object _, RoutedEventArgs e) + protected override void OnPointerReleased(PointerReleasedEventArgs e) { - if (DataContext is ViewModels.Blame blame) - { - blame.Back(); - } - } - private void HistoryForward(object _, RoutedEventArgs e) - { - if (DataContext is ViewModels.Blame blame) - { - blame.Forward(); - } - } + base.OnPointerReleased(e); - private void MouseUpHandler(object sender, PointerReleasedEventArgs e) - { - if (e.InitialPressMouseButton == MouseButton.XButton1) + if (!e.Handled && DataContext is ViewModels.Blame blame) { - HistoryBack(null, null); - } - else if (e.InitialPressMouseButton == MouseButton.XButton2) - { - HistoryForward(null, null); + if (e.InitialPressMouseButton == MouseButton.XButton1) + { + blame.Back(); + e.Handled = true; + } + else if (e.InitialPressMouseButton == MouseButton.XButton2) + { + blame.Forward(); + e.Handled = true; + } } } }