From c80df6c97a4e73a275857b8a866c63e0f886e965 Mon Sep 17 00:00:00 2001 From: mpagani Date: Tue, 15 Apr 2025 08:55:10 +0200 Subject: [PATCH] feat: add author selection and highlighting functionality in statistics report - Introduced `SelectedAuthor` property in `StatisticsReport` to manage author selection. - Implemented `UpdateHighlighting` method to adjust visual representation based on selected author. - Updated `Statistics` view model to bind `SelectedAuthor` and reset selection appropriately. - Modified XAML to enable two-way binding for author selection in the UI. --- src/Models/Statistics.cs | 90 +++++++++++++++++++++++++++++++++++- src/ViewModels/Statistics.cs | 18 ++++++++ src/Views/Statistics.axaml | 1 + 3 files changed, 107 insertions(+), 2 deletions(-) diff --git a/src/Models/Statistics.cs b/src/Models/Statistics.cs index 87a6eabd..f8052892 100644 --- a/src/Models/Statistics.cs +++ b/src/Models/Statistics.cs @@ -32,6 +32,8 @@ namespace SourceGit.Models public class StatisticsReport { + private const float OPACITY_DIMMED = 0.3f; + public static readonly string[] WEEKDAYS = ["SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT"]; public int Total { get; set; } = 0; @@ -39,6 +41,18 @@ namespace SourceGit.Models public List Series { get; set; } = new List(); public List XAxes { get; set; } = new List(); public List YAxes { get; set; } = new List(); + + private StaticsticsAuthor _selectedAuthor = null; + public StaticsticsAuthor SelectedAuthor + { + get => _selectedAuthor; + set + { + _selectedAuthor = value; + + UpdateHighlighting(); + } + } public StatisticsReport(StaticsticsMode mode, DateTime start) { @@ -92,6 +106,18 @@ namespace SourceGit.Models _mapUsers[author] = vu + 1; else _mapUsers.Add(author, 1); + + if (!_authorCommitsByDate.TryGetValue(author, out var authorDates)) + { + authorDates = new Dictionary(); + + _authorCommitsByDate.Add(author, authorDates); + } + + if (authorDates.TryGetValue(normalized, out var authorDateCount)) + authorDates[normalized] = authorDateCount + 1; + else + authorDates.Add(normalized, 1); } public void Complete() @@ -121,13 +147,73 @@ namespace SourceGit.Models public void ChangeColor(uint color) { - if (Series is [ColumnSeries series]) - series.Fill = new SolidColorPaint(new SKColor(color)); + _currentColor = color; + + UpdateHighlighting(); + } + + private void UpdateHighlighting() + { + if (Series.Count == 0) + return; + + var skColor = new SKColor(_currentColor); + + if (_selectedAuthor == null) + { + if (Series.Count > 1) + Series.RemoveAt(1); + + if (Series is [ColumnSeries series]) + series.Fill = new SolidColorPaint(skColor); + } + else + { + var dimmedColor = new SKColor(skColor.Red, skColor.Green, skColor.Blue, (byte)(255 * OPACITY_DIMMED)); + + if (Series is [ColumnSeries series, ..]) + series.Fill = new SolidColorPaint(dimmedColor); + + if (_authorCommitsByDate.TryGetValue(_selectedAuthor.User, out var authorData)) + { + var highlightSamples = new List(); + + foreach (var kv in authorData) + highlightSamples.Add(new DateTimePoint(kv.Key, kv.Value)); + + highlightSamples.Sort((a, b) => a.DateTime.CompareTo(b.DateTime)); + + if (Series.Count > 1) + { + if (Series[1] is ColumnSeries highlightSeries) + highlightSeries.Values = highlightSamples; + } + else + { + Series.Add(new ColumnSeries + { + Values = highlightSamples, + Stroke = null, + Fill = new SolidColorPaint(skColor), + Padding = 1, + }); + } + } + } + } + + public void ResetSelection() + { + _selectedAuthor = null; + + UpdateHighlighting(); } private StaticsticsMode _mode = StaticsticsMode.All; private Dictionary _mapUsers = new Dictionary(); private Dictionary _mapSamples = new Dictionary(); + private Dictionary> _authorCommitsByDate = new Dictionary>(); + private uint _currentColor; } public class Statistics diff --git a/src/ViewModels/Statistics.cs b/src/ViewModels/Statistics.cs index 68098a63..ac6aceee 100644 --- a/src/ViewModels/Statistics.cs +++ b/src/ViewModels/Statistics.cs @@ -50,6 +50,20 @@ namespace SourceGit.ViewModels get => new SolidColorBrush(SampleColor); } + public Models.StaticsticsAuthor SelectedAuthor + { + get => _selectedAuthor; + set + { + if (SetProperty(ref _selectedAuthor, value)) + { + _selectedReport?.ResetSelection(); + + _selectedReport.SelectedAuthor = value; + } + } + } + public Statistics(string repo) { Task.Run(() => @@ -69,6 +83,8 @@ namespace SourceGit.ViewModels if (_data == null) return; + SetProperty(ref _selectedAuthor, null); + var report = _selectedIndex switch { 0 => _data.All, @@ -76,6 +92,7 @@ namespace SourceGit.ViewModels _ => _data.Week, }; + report.ResetSelection(); report.ChangeColor(SampleColor); SelectedReport = report; } @@ -84,5 +101,6 @@ namespace SourceGit.ViewModels private Models.Statistics _data = null; private Models.StatisticsReport _selectedReport = null; private int _selectedIndex = 0; + private Models.StaticsticsAuthor _selectedAuthor = null; } } diff --git a/src/Views/Statistics.axaml b/src/Views/Statistics.axaml index 3bbdafbe..5830b1e2 100644 --- a/src/Views/Statistics.axaml +++ b/src/Views/Statistics.axaml @@ -139,6 +139,7 @@