From 28b6ce49936402eda7479971334370a44a3d8496 Mon Sep 17 00:00:00 2001 From: Gadfly Date: Mon, 2 Sep 2024 10:51:48 +0800 Subject: [PATCH 01/21] enhance: save preference.json instantly --- src/App.axaml.cs | 1 - src/ViewModels/Preference.cs | 40 ++++++++++++++++++++++++++++++++++- src/Views/Preference.axaml.cs | 6 ++++-- 3 files changed, 43 insertions(+), 4 deletions(-) diff --git a/src/App.axaml.cs b/src/App.axaml.cs index 98d671d3..ffce8a51 100644 --- a/src/App.axaml.cs +++ b/src/App.axaml.cs @@ -522,7 +522,6 @@ namespace SourceGit var pref = ViewModels.Preference.Instance; if (pref.ShouldCheck4UpdateOnStartup()) { - pref.Save(); Check4Update(); } } diff --git a/src/ViewModels/Preference.cs b/src/ViewModels/Preference.cs index ed3c0724..afe40cf5 100644 --- a/src/ViewModels/Preference.cs +++ b/src/ViewModels/Preference.cs @@ -1,9 +1,11 @@ using System; using System.Collections.Generic; +using System.ComponentModel; using System.IO; using System.Text.Json; using System.Text.Json.Serialization; - +using System.Threading; +using System.Threading.Tasks; using CommunityToolkit.Mvvm.ComponentModel; namespace SourceGit.ViewModels @@ -414,10 +416,44 @@ namespace SourceGit.ViewModels public void Save() { + lock (_saveCtsLock) + { + _saveCts.Cancel(); + _saveCts = new CancellationTokenSource(); + } var data = JsonSerializer.Serialize(this, JsonCodeGen.Default.Preference); File.WriteAllText(_savePath, data); } + public async Task SaveAsync() + { + lock (_saveCtsLock) + { + _saveCts.Cancel(); + _saveCts = new CancellationTokenSource(); + } + + try + { + await Task.Delay(3000, _saveCts.Token); + } + catch (TaskCanceledException) + { + return; + } + + var data = JsonSerializer.Serialize(this, JsonCodeGen.Default.Preference); + await File.WriteAllTextAsync(_savePath, data); + } + + protected override void OnPropertyChanged(PropertyChangedEventArgs e) + { + base.OnPropertyChanged(e); +#pragma warning disable CS4014 + SaveAsync(); +#pragma warning restore CS4014 + } + private RepositoryNode FindNodeRecursive(string id, List collection) { foreach (var node in collection) @@ -468,6 +504,8 @@ namespace SourceGit.ViewModels private static Preference _instance = null; private static bool _isLoading = false; private static readonly string _savePath = Path.Combine(Native.OS.DataDir, "preference.json"); + private static CancellationTokenSource _saveCts = new(); + private static readonly object _saveCtsLock = new(); private string _locale = "en_US"; private string _theme = "Default"; diff --git a/src/Views/Preference.axaml.cs b/src/Views/Preference.axaml.cs index 2621bcaf..6fedd052 100644 --- a/src/Views/Preference.axaml.cs +++ b/src/Views/Preference.axaml.cs @@ -138,7 +138,7 @@ namespace SourceGit.Views if (!GPGFormat.Value.Equals("ssh", StringComparison.Ordinal)) SetIfChanged(config, $"gpg.{GPGFormat.Value}.program", GPGExecutableFile); - + base.OnClosing(e); } @@ -261,7 +261,9 @@ namespace SourceGit.Views if (sender is CheckBox box) { ViewModels.Preference.Instance.UseSystemWindowFrame = box.IsChecked == true; - ViewModels.Preference.Instance.Save(); +#pragma warning disable CS4014 + ViewModels.Preference.Instance.SaveAsync(); +#pragma warning restore CS4014 var dialog = new ConfirmRestart(); App.OpenDialog(dialog); From c85293c86a247fe0bde5c3ba28a02755fdc4fb03 Mon Sep 17 00:00:00 2001 From: Gadfly Date: Mon, 2 Sep 2024 12:05:24 +0800 Subject: [PATCH 02/21] enhance: support save RepositoryNode changes instantly --- src/App.axaml.cs | 6 ++++++ src/ViewModels/Preference.cs | 17 +++++++++-------- src/Views/Preference.axaml.cs | 3 --- 3 files changed, 15 insertions(+), 11 deletions(-) diff --git a/src/App.axaml.cs b/src/App.axaml.cs index ffce8a51..c6ae4513 100644 --- a/src/App.axaml.cs +++ b/src/App.axaml.cs @@ -75,6 +75,12 @@ namespace SourceGit AvaloniaXamlLoader.Load(this); var pref = ViewModels.Preference.Instance; + pref.PropertyChanged += (_1, _2) => + { +#pragma warning disable CS4014 + pref.SaveAsync(); +#pragma warning restore CS4014 + }; SetLocale(pref.Locale); SetTheme(pref.Theme, pref.ThemeOverrides); SetFonts(pref.DefaultFontFamily, pref.MonospaceFontFamily, pref.OnlyUseMonoFontInEditor); diff --git a/src/ViewModels/Preference.cs b/src/ViewModels/Preference.cs index afe40cf5..a7aa6532 100644 --- a/src/ViewModels/Preference.cs +++ b/src/ViewModels/Preference.cs @@ -356,6 +356,9 @@ namespace SourceGit.ViewModels return string.Compare(l.Name, r.Name, StringComparison.Ordinal); }); +#pragma warning disable CS4014 + SaveAsync(); +#pragma warning restore CS4014 } public RepositoryNode FindNode(string id) @@ -400,6 +403,9 @@ namespace SourceGit.ViewModels public void RemoveNode(RepositoryNode node) { RemoveNodeRecursive(node, RepositoryNodes); +#pragma warning disable CS4014 + SaveAsync(); +#pragma warning restore CS4014 } public void SortByRenamedNode(RepositoryNode node) @@ -412,6 +418,9 @@ namespace SourceGit.ViewModels return string.Compare(l.Name, r.Name, StringComparison.Ordinal); }); +#pragma warning disable CS4014 + SaveAsync(); +#pragma warning restore CS4014 } public void Save() @@ -446,14 +455,6 @@ namespace SourceGit.ViewModels await File.WriteAllTextAsync(_savePath, data); } - protected override void OnPropertyChanged(PropertyChangedEventArgs e) - { - base.OnPropertyChanged(e); -#pragma warning disable CS4014 - SaveAsync(); -#pragma warning restore CS4014 - } - private RepositoryNode FindNodeRecursive(string id, List collection) { foreach (var node in collection) diff --git a/src/Views/Preference.axaml.cs b/src/Views/Preference.axaml.cs index 6fedd052..25dbfd96 100644 --- a/src/Views/Preference.axaml.cs +++ b/src/Views/Preference.axaml.cs @@ -261,9 +261,6 @@ namespace SourceGit.Views if (sender is CheckBox box) { ViewModels.Preference.Instance.UseSystemWindowFrame = box.IsChecked == true; -#pragma warning disable CS4014 - ViewModels.Preference.Instance.SaveAsync(); -#pragma warning restore CS4014 var dialog = new ConfirmRestart(); App.OpenDialog(dialog); From 9fe8ffcea933a74323fcf039c2f6047cb9f945c7 Mon Sep 17 00:00:00 2001 From: leo Date: Mon, 2 Sep 2024 12:20:11 +0800 Subject: [PATCH 03/21] code_review: PR #436 It's ok to call `Save()` multiple times after property of `ViewModels.Preference` changed immediately. If we delay the saving operation 3 seconds after the property changed event, we reduce the times calling `Save`, but the issue metioned in #436 may still exists. --- src/App.axaml.cs | 10 ++---- src/ViewModels/Preference.cs | 62 ++++++++++-------------------------- 2 files changed, 18 insertions(+), 54 deletions(-) diff --git a/src/App.axaml.cs b/src/App.axaml.cs index c6ae4513..f4ec6a11 100644 --- a/src/App.axaml.cs +++ b/src/App.axaml.cs @@ -75,12 +75,8 @@ namespace SourceGit AvaloniaXamlLoader.Load(this); var pref = ViewModels.Preference.Instance; - pref.PropertyChanged += (_1, _2) => - { -#pragma warning disable CS4014 - pref.SaveAsync(); -#pragma warning restore CS4014 - }; + pref.PropertyChanged += (_1, _2) => pref.Save(); + SetLocale(pref.Locale); SetTheme(pref.Theme, pref.ThemeOverrides); SetFonts(pref.DefaultFontFamily, pref.MonospaceFontFamily, pref.OnlyUseMonoFontInEditor); @@ -527,9 +523,7 @@ namespace SourceGit var pref = ViewModels.Preference.Instance; if (pref.ShouldCheck4UpdateOnStartup()) - { Check4Update(); - } } private ViewModels.Launcher _launcher = null; diff --git a/src/ViewModels/Preference.cs b/src/ViewModels/Preference.cs index a7aa6532..3badb359 100644 --- a/src/ViewModels/Preference.cs +++ b/src/ViewModels/Preference.cs @@ -1,11 +1,9 @@ using System; using System.Collections.Generic; -using System.ComponentModel; using System.IO; using System.Text.Json; using System.Text.Json.Serialization; -using System.Threading; -using System.Threading.Tasks; + using CommunityToolkit.Mvvm.ComponentModel; namespace SourceGit.ViewModels @@ -155,9 +153,9 @@ namespace SourceGit.ViewModels public string IgnoreUpdateTag { - get; - set; - } = string.Empty; + get => _ignoreUpdateTag; + set => SetProperty(ref _ignoreUpdateTag, value); + } public bool ShowTagsAsTree { @@ -320,9 +318,9 @@ namespace SourceGit.ViewModels public double LastCheckUpdateTime { - get; - set; - } = 0; + get => _lastCheckUpdateTime; + set => SetProperty(ref _lastCheckUpdateTime, value); + } public bool IsGitConfigured() { @@ -356,9 +354,8 @@ namespace SourceGit.ViewModels return string.Compare(l.Name, r.Name, StringComparison.Ordinal); }); -#pragma warning disable CS4014 - SaveAsync(); -#pragma warning restore CS4014 + + Save(); } public RepositoryNode FindNode(string id) @@ -398,14 +395,13 @@ namespace SourceGit.ViewModels RemoveNode(node); AddNode(node, to); + Save(); } public void RemoveNode(RepositoryNode node) { RemoveNodeRecursive(node, RepositoryNodes); -#pragma warning disable CS4014 - SaveAsync(); -#pragma warning restore CS4014 + Save(); } public void SortByRenamedNode(RepositoryNode node) @@ -418,43 +414,16 @@ namespace SourceGit.ViewModels return string.Compare(l.Name, r.Name, StringComparison.Ordinal); }); -#pragma warning disable CS4014 - SaveAsync(); -#pragma warning restore CS4014 + + Save(); } public void Save() { - lock (_saveCtsLock) - { - _saveCts.Cancel(); - _saveCts = new CancellationTokenSource(); - } var data = JsonSerializer.Serialize(this, JsonCodeGen.Default.Preference); File.WriteAllText(_savePath, data); } - public async Task SaveAsync() - { - lock (_saveCtsLock) - { - _saveCts.Cancel(); - _saveCts = new CancellationTokenSource(); - } - - try - { - await Task.Delay(3000, _saveCts.Token); - } - catch (TaskCanceledException) - { - return; - } - - var data = JsonSerializer.Serialize(this, JsonCodeGen.Default.Preference); - await File.WriteAllTextAsync(_savePath, data); - } - private RepositoryNode FindNodeRecursive(string id, List collection) { foreach (var node in collection) @@ -505,8 +474,6 @@ namespace SourceGit.ViewModels private static Preference _instance = null; private static bool _isLoading = false; private static readonly string _savePath = Path.Combine(Native.OS.DataDir, "preference.json"); - private static CancellationTokenSource _saveCts = new(); - private static readonly object _saveCtsLock = new(); private string _locale = "en_US"; private string _theme = "Default"; @@ -522,7 +489,10 @@ namespace SourceGit.ViewModels private int _subjectGuideLength = 50; private bool _restoreTabs = false; private bool _useFixedTabWidth = true; + private bool _check4UpdatesOnStartup = true; + private double _lastCheckUpdateTime = 0; + private string _ignoreUpdateTag = string.Empty; private bool _showTagsAsTree = false; private bool _useTwoColumnsLayoutInHistories = false; From 931831431b7be331f7e0ac1a4b942ffa1a209deb Mon Sep 17 00:00:00 2001 From: leo Date: Mon, 2 Sep 2024 14:14:52 +0800 Subject: [PATCH 04/21] enhance: reduce the times calling `Save()` (#436) --- src/ViewModels/CreateGroup.cs | 2 +- src/ViewModels/DeleteRepositoryNode.cs | 2 +- src/ViewModels/Preference.cs | 25 +++++++++++++++---------- src/ViewModels/Welcome.cs | 2 +- 4 files changed, 18 insertions(+), 13 deletions(-) diff --git a/src/ViewModels/CreateGroup.cs b/src/ViewModels/CreateGroup.cs index 865ca4ac..cb94a0f6 100644 --- a/src/ViewModels/CreateGroup.cs +++ b/src/ViewModels/CreateGroup.cs @@ -27,7 +27,7 @@ namespace SourceGit.ViewModels Name = _name, IsRepository = false, IsExpanded = false, - }, _parent); + }, _parent, true); Welcome.Instance.Refresh(); return null; diff --git a/src/ViewModels/DeleteRepositoryNode.cs b/src/ViewModels/DeleteRepositoryNode.cs index 3354d41e..7cd0df5c 100644 --- a/src/ViewModels/DeleteRepositoryNode.cs +++ b/src/ViewModels/DeleteRepositoryNode.cs @@ -18,7 +18,7 @@ namespace SourceGit.ViewModels public override Task Sure() { - Preference.Instance.RemoveNode(_node); + Preference.Instance.RemoveNode(_node, true); Welcome.Instance.Refresh(); return null; } diff --git a/src/ViewModels/Preference.cs b/src/ViewModels/Preference.cs index 3badb359..44ae9c1a 100644 --- a/src/ViewModels/Preference.cs +++ b/src/ViewModels/Preference.cs @@ -343,7 +343,7 @@ namespace SourceGit.ViewModels return true; } - public void AddNode(RepositoryNode node, RepositoryNode to = null) + public void AddNode(RepositoryNode node, RepositoryNode to, bool save) { var collection = to == null ? RepositoryNodes : to.SubNodes; collection.Add(node); @@ -355,7 +355,8 @@ namespace SourceGit.ViewModels return string.Compare(l.Name, r.Name, StringComparison.Ordinal); }); - Save(); + if (save) + Save(); } public RepositoryNode FindNode(string id) @@ -376,32 +377,36 @@ namespace SourceGit.ViewModels IsRepository = true, }; - AddNode(node, parent); + AddNode(node, parent, true); } else if (shouldMoveNode) { - MoveNode(node, parent); + MoveNode(node, parent, true); } return node; } - public void MoveNode(RepositoryNode node, RepositoryNode to = null) + public void MoveNode(RepositoryNode node, RepositoryNode to, bool save) { if (to == null && RepositoryNodes.Contains(node)) return; if (to != null && to.SubNodes.Contains(node)) return; - RemoveNode(node); - AddNode(node, to); - Save(); + RemoveNode(node, false); + AddNode(node, to, false); + + if (save) + Save(); } - public void RemoveNode(RepositoryNode node) + public void RemoveNode(RepositoryNode node, bool save) { RemoveNodeRecursive(node, RepositoryNodes); - Save(); + + if (save) + Save(); } public void SortByRenamedNode(RepositoryNode node) diff --git a/src/ViewModels/Welcome.cs b/src/ViewModels/Welcome.cs index b193d5a4..420e9b03 100644 --- a/src/ViewModels/Welcome.cs +++ b/src/ViewModels/Welcome.cs @@ -139,7 +139,7 @@ namespace SourceGit.ViewModels public void MoveNode(RepositoryNode from, RepositoryNode to) { - Preference.Instance.MoveNode(from, to); + Preference.Instance.MoveNode(from, to, true); Refresh(); } From de8689001247920312bdc22484bf9d6a57926377 Mon Sep 17 00:00:00 2001 From: leo Date: Mon, 2 Sep 2024 14:34:51 +0800 Subject: [PATCH 05/21] ux: make it easier to change the width of column `AUTHOR` --- src/Views/Histories.axaml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/Views/Histories.axaml b/src/Views/Histories.axaml index 4696b9ef..6e694fa9 100644 --- a/src/Views/Histories.axaml +++ b/src/Views/Histories.axaml @@ -22,15 +22,17 @@ - + - - + + + + From fe7972684c4c379f614c2bca90ea5b6a93a6a53f Mon Sep 17 00:00:00 2001 From: leo Date: Mon, 2 Sep 2024 14:44:42 +0800 Subject: [PATCH 06/21] ux: change the icon for `Check refs that contains this commit` button --- src/Resources/Icons.axaml | 2 +- src/Views/CommitBaseInfo.axaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Resources/Icons.axaml b/src/Resources/Icons.axaml index 8090e576..e7e09246 100644 --- a/src/Resources/Icons.axaml +++ b/src/Resources/Icons.axaml @@ -80,7 +80,7 @@ M432 0h160c27 0 48 21 48 48v336h175c36 0 53 43 28 68L539 757c-15 15-40 15-55 0L180 452c-25-25-7-68 28-68H384V48c0-27 21-48 48-48zm592 752v224c0 27-21 48-48 48H48c-27 0-48-21-48-48V752c0-27 21-48 48-48h293l98 98c40 40 105 40 145 0l98-98H976c27 0 48 21 48 48zm-248 176c0-22-18-40-40-40s-40 18-40 40s18 40 40 40s40-18 40-40zm128 0c0-22-18-40-40-40s-40 18-40 40s18 40 40 40s40-18 40-40z M592 768h-160c-27 0-48-21-48-48V384h-175c-36 0-53-43-28-68L485 11c15-15 40-15 55 0l304 304c25 25 7 68-28 68H640v336c0 27-21 48-48 48zm432-16v224c0 27-21 48-48 48H48c-27 0-48-21-48-48V752c0-27 21-48 48-48h272v16c0 62 50 112 112 112h160c62 0 112-50 112-112v-16h272c27 0 48 21 48 48zm-248 176c0-22-18-40-40-40s-40 18-40 40s18 40 40 40s40-18 40-40zm128 0c0-22-18-40-40-40s-40 18-40 40s18 40 40 40s40-18 40-40z M277 85a149 149 0 00-43 292v230a32 32 0 0064 0V555h267A160 160 0 00725 395v-12a149 149 0 10-64-5v17a96 96 0 01-96 96H299V383A149 149 0 00277 85zM228 720a32 32 0 00-37-52 150 150 0 00-53 68 32 32 0 1060 23 85 85 0 0130-39zm136-52a32 32 0 00-37 52 86 86 0 0130 39 32 32 0 1060-23 149 149 0 00-53-68zM204 833a32 32 0 10-55 32 149 149 0 0063 58 32 32 0 0028-57 85 85 0 01-36-33zm202 32a32 32 0 00-55-32 85 85 0 01-36 33 32 32 0 0028 57 149 149 0 0063-58z - M672 336l64-89c-13-19-26-45-26-70 0-64 51-115 109-115s109 51 109 115-51 115-109 115c-19 0-38-6-51-13l-64 89c32 38 51 89 51 147 0 70-32 128-77 172l51 64c13-6 32-13 51-13 57 0 109 51 109 115s-51 109-109 109-109-51-109-115c0-26 13-51 26-70L646 707c-32 19-64 26-102 26-121 0-217-102-217-223v-38l-57-13c-19 32-57 57-96 57C116 515 65 464 65 400s51-115 109-115 109 51 109 115v13l57 19C372 349 448 292 538 292c51 0 102 19 134 45z + m224 154a166 166 0 00-166 166v192a166 166 0 00166 166h64v-76h-64a90 90 0 01-90-90v-192a90 90 0 0190-90h320a90 90 0 0190 90v192a90 90 0 01-90 90h-128v77h128a166 166 0 00166-167v-192a166 166 0 00-166-166h-320zm166 390a90 90 0 0190-90h128v-76h-128a166 166 0 00-166 166v192a166 166 0 00166 166h320a166 166 0 00166-166v-192a166 166 0 00-166-166h-64v77h64a90 90 0 0190 90v192a90 90 0 01-90 90h-320a90 90 0 01-90-90v-192z M706 302a289 289 0 00-173 44 27 27 0 1029 46 234 234 0 01125-36c23 0 45 3 66 9 93 28 161 114 161 215C914 704 813 805 687 805H337C211 805 110 704 110 580c0-96 61-178 147-210C282 263 379 183 495 183a245 245 0 01210 119z M364 512h67v108h108v67h-108v108h-67v-108h-108v-67h108v-108zm298-64A107 107 0 01768 555C768 614 720 660 660 660h-108v-54h-108v-108h-94v108h-94c4-21 22-47 44-51l-1-12a75 75 0 0171-75a128 128 0 01239-7a106 106 0 0153-14z M1024 64v704h-128v128h-128v128h-768v-704h128v-128h128v-128zM64 960h640v-576h-640zM320 128v64h576v512h64v-576zM192 256v64h576v512h64v-576zM432 688L576 832H480L384 736 288 832H192l144-144L192 544h96L384 640l96-96H576z diff --git a/src/Views/CommitBaseInfo.axaml b/src/Views/CommitBaseInfo.axaml index 6734ecdb..2ded8ac7 100644 --- a/src/Views/CommitBaseInfo.axaml +++ b/src/Views/CommitBaseInfo.axaml @@ -65,7 +65,7 @@