From a1bfbfe02e9051460bea03923317e6d0273fe8b4 Mon Sep 17 00:00:00 2001 From: leo Date: Thu, 24 Aug 2023 13:39:49 +0800 Subject: [PATCH] refactor: new blame tool --- src/Commands/Blame.cs | 17 +++++ src/Resources/Locales/en_US.xaml | 4 - src/Resources/Locales/zh_CN.xaml | 4 - src/Views/Blame.xaml | 97 ++++++++++++------------ src/Views/Blame.xaml.cs | 122 +++++++++++++------------------ 5 files changed, 121 insertions(+), 123 deletions(-) diff --git a/src/Commands/Blame.cs b/src/Commands/Blame.cs index 1a12a9b6..5fc8332a 100644 --- a/src/Commands/Blame.cs +++ b/src/Commands/Blame.cs @@ -9,6 +9,8 @@ namespace SourceGit.Commands { public class Blame : Command { private static readonly Regex REG_FORMAT = new Regex(@"^\^?([0-9a-f]+)\s+.*\((.*)\s+(\d+)\s+[\-\+]?\d+\s+\d+\) (.*)"); private Data data = new Data(); + private bool needUnifyCommitSHA = false; + private int minSHALen = 0; public class Data { public List Lines = new List(); @@ -22,6 +24,15 @@ namespace SourceGit.Commands { public Data Result() { Exec(); + + if (needUnifyCommitSHA) { + foreach (var line in data.Lines) { + if (line.CommitSHA.Length > minSHALen) { + line.CommitSHA = line.CommitSHA.Substring(0, minSHALen); + } + } + } + return data; } @@ -52,6 +63,12 @@ namespace SourceGit.Commands { Content = content, }; + if (line[0] == '^') { + needUnifyCommitSHA = true; + if (minSHALen == 0) minSHALen = commit.Length; + else if (commit.Length < minSHALen) minSHALen = commit.Length; + } + data.Lines.Add(blameLine); } } diff --git a/src/Resources/Locales/en_US.xaml b/src/Resources/Locales/en_US.xaml index 02edad22..d71f24d0 100644 --- a/src/Resources/Locales/en_US.xaml +++ b/src/Resources/Locales/en_US.xaml @@ -49,10 +49,6 @@ Select archive file path Blame - Right click to see commit info - COMMIT SHA - AUTHOR - MODIFY TIME SUBMODULES Add Submodule diff --git a/src/Resources/Locales/zh_CN.xaml b/src/Resources/Locales/zh_CN.xaml index 766c80eb..b01417c2 100644 --- a/src/Resources/Locales/zh_CN.xaml +++ b/src/Resources/Locales/zh_CN.xaml @@ -48,10 +48,6 @@ 选择存档文件的存放路径 逐行追溯 - 右键点击查看所选行修改记录 - 提交指纹 - 修改者 - 修改时间 子模块 添加子模块 diff --git a/src/Views/Blame.xaml b/src/Views/Blame.xaml index c5a5cdec..299cca9a 100644 --- a/src/Views/Blame.xaml +++ b/src/Views/Blame.xaml @@ -15,13 +15,13 @@ - + @@ -34,8 +34,17 @@ + + + - + @@ -49,49 +58,72 @@ HorizontalAlignment="Stretch" Fill="{DynamicResource Brush.Border0}"/> - - - - - - - - - - - - - + SizeChanged="OnViewerSizeChanged" + SelectionChanged="OnSelectionChanged"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + @@ -111,30 +143,5 @@ - - - - - - - - - - - - - - - - - - - - diff --git a/src/Views/Blame.xaml.cs b/src/Views/Blame.xaml.cs index f84ce549..8d1340e9 100644 --- a/src/Views/Blame.xaml.cs +++ b/src/Views/Blame.xaml.cs @@ -1,10 +1,8 @@ using System.Collections.ObjectModel; using System.ComponentModel; -using System.Globalization; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; -using System.Windows.Documents; using System.Windows.Media; namespace SourceGit.Views { @@ -12,33 +10,45 @@ namespace SourceGit.Views { /// 逐行追溯 /// public partial class Blame : Controls.Window { - private static readonly Brush[] BG = new Brush[] { - Brushes.Transparent, - new SolidColorBrush(Color.FromArgb(128, 0, 0, 0)) - }; - - private string repo = null; - private string lastSHA = null; - private int lastBG = 1; - + /// + /// DataGrid数据源结构 + /// public class Record : INotifyPropertyChanged { - private Brush bg = null; - public event PropertyChangedEventHandler PropertyChanged; + /// + /// 原始Blame行数据 + /// public Models.BlameLine Line { get; set; } - public Brush OrgBG { get; set; } - public Brush BG { - get { return bg; } + + /// + /// 是否是第一行 + /// + public bool IsFirstLine { get; set; } = false; + + /// + /// 前一行与本行的提交不同 + /// + public bool IsFirstLineInGroup { get; set; } = false; + + /// + /// 是否当前选中,会影响背景色 + /// + private bool isSelected = false; + public bool IsSelected { + get { return isSelected; } set { - if (value != bg) { - bg = value; - PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("BG")); + if (isSelected != value) { + isSelected = value; + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("IsSelected")); } } } } + /// + /// Blame数据 + /// public ObservableCollection Records { get; set; } public Blame(string repo, string file, string revision) { @@ -67,48 +77,33 @@ namespace SourceGit.Views { notSupport.Visibility = Visibility.Visible; }); } else { + string lastSHA = null; foreach (var line in rs.Lines) { var r = new Record(); r.Line = line; - r.BG = GetBG(line.CommitSHA); - r.OrgBG = r.BG; + r.IsSelected = false; + + if (line.CommitSHA != lastSHA) { + lastSHA = line.CommitSHA; + r.IsFirstLineInGroup = true; + } else { + r.IsFirstLineInGroup = false; + } + Records.Add(r); } + if (Records.Count > 0) Records[0].IsFirstLine = true; + Dispatcher.Invoke(() => { loading.IsAnimating = false; loading.Visibility = Visibility.Collapsed; - - var formatted = new FormattedText( - $"{Records.Count}", - CultureInfo.CurrentCulture, - FlowDirection.LeftToRight, - new Typeface(blame.FontFamily, FontStyles.Normal, FontWeights.Normal, FontStretches.Normal), - 12.0, - Brushes.Black, - VisualTreeHelper.GetDpi(this).PixelsPerDip); - - var lineNumberWidth = formatted.Width + 16; - var minWidth = blame.ActualWidth - lineNumberWidth; - if (Records.Count * 16 > blame.ActualHeight) minWidth -= 8; - blame.Columns[0].Width = lineNumberWidth; - blame.Columns[1].MinWidth = minWidth; blame.ItemsSource = Records; - blame.UpdateLayout(); }); } }); } - private Brush GetBG(string sha) { - if (lastSHA != sha) { - lastSHA = sha; - lastBG = 1 - lastBG; - } - - return BG[lastBG]; - } - #region WINDOW_COMMANDS private void Minimize(object sender, RoutedEventArgs e) { SystemCommands.MinimizeWindow(this); @@ -148,8 +143,8 @@ namespace SourceGit.Views { var scroller = GetVisualChild(blame); if (scroller != null && scroller.ComputedVerticalScrollBarVisibility == Visibility.Visible) minWidth -= 8; - blame.Columns[1].MinWidth = minWidth; - blame.Columns[1].Width = DataGridLength.SizeToCells; + blame.Columns[2].MinWidth = minWidth; + blame.Columns[2].Width = DataGridLength.SizeToCells; blame.UpdateLayout(); } @@ -157,31 +152,18 @@ namespace SourceGit.Views { e.Handled = true; } - private void OnViewerContextMenuOpening(object sender, ContextMenuEventArgs ev) { - var record = (sender as DataGridRow).DataContext as Record; - if (record == null) return; + private void OnSelectionChanged(object sender, SelectionChangedEventArgs e) { + var r = blame.SelectedItem as Record; + if (r == null) return; - foreach (var r in Records) { - if (r.Line.CommitSHA == record.Line.CommitSHA) { - r.BG = new SolidColorBrush(Color.FromArgb(60, 0, 255, 0)); - } else { - r.BG = r.OrgBG; - } + Models.Watcher.Get(repo).NavigateTo(r.Line.CommitSHA); + + foreach (var one in Records) { + one.IsSelected = one.Line.CommitSHA == r.Line.CommitSHA; } - - Hyperlink link = new Hyperlink(new Run(record.Line.CommitSHA)); - link.ToolTip = App.Text("Goto"); - link.Click += (o, e) => { - Models.Watcher.Get(repo).NavigateTo(record.Line.CommitSHA); - e.Handled = true; - }; - - commitID.Content = link; - authorName.Text = record.Line.Author; - authorTime.Text = record.Line.Time; - popup.IsOpen = true; - ev.Handled = true; } #endregion + + private string repo = null; } }