refactor<Exception>: add context to exception to filter exceptions; each page has it's own error display control

This commit is contained in:
leo 2023-10-13 11:16:03 +08:00
parent c85052bbcc
commit 838e688a0c
15 changed files with 79 additions and 44 deletions

View file

@ -8,6 +8,7 @@ namespace SourceGit {
/// 程序入口.
/// </summary>
public partial class App : Application {
public static event Action<string, string> ExceptionRaised;
/// <summary>
/// 读取本地化字串
@ -21,6 +22,15 @@ namespace SourceGit {
return string.Format(data, args);
}
/// <summary>
/// 触发错误
/// </summary>
/// <param name="ctx">错误上下文</param>
/// <param name="detail">错误内容</param>
public static void Exception(string ctx, string detail) {
ExceptionRaised?.Invoke(ctx, detail);
}
/// <summary>
/// 启动.
/// </summary>

View file

@ -178,7 +178,7 @@ namespace SourceGit.Commands {
/// </summary>
/// <param name="message"></param>
public virtual void OnException(string message) {
Models.Exception.Raise(message);
App.Exception(Cwd, message);
}
}
}

View file

@ -1,15 +0,0 @@
using System;
namespace SourceGit.Models {
/// <summary>
/// 错误通知
/// </summary>
public static class Exception {
public static Action<string> Handler { get; set; }
public static void Raise(string error) {
Handler?.Invoke(error);
}
}
}

View file

@ -63,7 +63,7 @@ namespace SourceGit.Views {
}
if (!Directory.Exists(path)) {
Models.Exception.Raise($"Folder {path} not found!");
Dispatcher.Invoke(() => txtError.Text = $"Folder {path} not found!");
return false;
}

View file

@ -70,11 +70,5 @@
<!-- Contents -->
<controls:PageContainer x:Name="container" Grid.Row="1"/>
<!-- Alerts -->
<widgets:Exceptions
Grid.Row="1"
HorizontalAlignment="Right" VerticalAlignment="Top"
Width="330" Height="Auto"/>
</Grid>
</controls:Window>

View file

@ -34,7 +34,7 @@ namespace SourceGit.Views.Popups {
var squash = chkSquash.IsChecked == true;
if (repo.SubTrees.FindIndex(x => x.Prefix == Prefix) >= 0) {
Models.Exception.Raise($"Subtree add failed. Prefix({Prefix}) already exists!");
App.Exception(repo.Path, $"Subtree add failed. Prefix({Prefix}) already exists!");
return null;
}

View file

@ -14,7 +14,7 @@ namespace SourceGit.Views.Popups {
public FastForwardWithoutCheckout(string repo, string branch, string upstream) {
int idx = upstream.IndexOf('/');
if (idx < 0 || idx == upstream.Length - 1) {
Models.Exception.Raise($"Invalid upstream: {upstream}");
App.Exception(repo, $"Invalid upstream: {upstream}");
return;
}

View file

@ -1,4 +1,5 @@
<UserControl x:Class="SourceGit.Views.Widgets.Dashboard"
x:Name="me"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
@ -592,5 +593,12 @@
</Grid>
</Border>
</Grid>
<!-- Alerts -->
<widgets:Exceptions
Grid.Row="1"
HorizontalAlignment="Right" VerticalAlignment="Top"
Width="330" Height="Auto"
Context="{Binding ElementName=me, Path=ExceptionContext}"/>
</Grid>
</UserControl>

View file

@ -54,6 +54,8 @@ namespace SourceGit.Views.Widgets {
}
}
public string ExceptionContext => repo.Path;
public Dashboard(Models.Repository repo) {
this.repo = repo;
@ -402,7 +404,7 @@ namespace SourceGit.Views.Widgets {
private void OpenInTerminal(object sender, RoutedEventArgs e) {
var bash = Path.Combine(Models.Preference.Instance.Git.Path, "..", "bash.exe");
if (!File.Exists(bash)) {
Models.Exception.Raise(App.Text("MissingBash"));
App.Exception(repo.Path, App.Text("MissingBash"));
return;
}
@ -428,7 +430,7 @@ namespace SourceGit.Views.Widgets {
private void OpenFetch(object sender, RoutedEventArgs e) {
if (repo.Remotes.Count == 0) {
Models.Exception.Raise("No remotes added to this repository!!!");
App.Exception(repo.Path, "No remotes added to this repository!!!");
return;
}
@ -438,7 +440,7 @@ namespace SourceGit.Views.Widgets {
private void OpenPull(object sender, RoutedEventArgs e) {
if (repo.Remotes.Count == 0) {
Models.Exception.Raise("No remotes added to this repository!!!");
App.Exception(repo.Path, "No remotes added to this repository!!!");
return;
}
@ -448,7 +450,7 @@ namespace SourceGit.Views.Widgets {
private void OpenPush(object sender, RoutedEventArgs e) {
if (repo.Remotes.Count == 0) {
Models.Exception.Raise("No remotes added to this repository!!!");
App.Exception(repo.Path, "No remotes added to this repository!!!");
return;
}
@ -576,7 +578,7 @@ namespace SourceGit.Views.Widgets {
if (current != null) {
new Popups.CreateBranch(repo, current).Show();
} else {
Models.Exception.Raise(App.Text("CreateBranch.Idle"));
App.Exception(repo.Path, App.Text("CreateBranch.Idle"));
}
e.Handled = true;
}

View file

@ -604,7 +604,7 @@ namespace SourceGit.Views.Widgets {
var merger = Models.MergeTool.Supported.Find(x => x.Type == mergeType);
if (merger == null || merger.Type == 0 || !System.IO.File.Exists(mergeExe)) {
Models.Exception.Raise("Invalid merge tool in preference setting!");
App.Exception(repo, "Invalid merge tool in preference setting!");
return;
}

View file

@ -10,9 +10,31 @@ namespace SourceGit.Views.Widgets {
public partial class Exceptions : UserControl {
public ObservableCollection<string> Messages { get; set; }
/// <summary>
/// 用于判断异常是否属于自己的上下文属性
/// </summary>
public static readonly DependencyProperty ContextProperty = DependencyProperty.Register(
"Context",
typeof(string),
typeof(Exceptions),
new PropertyMetadata(null));
/// <summary>
/// 上下文
/// </summary>
public string Context {
get { return (string)GetValue(ContextProperty); }
set { SetValue(ContextProperty, value); }
}
public Exceptions() {
App.ExceptionRaised += (ctx, detail) => {
Dispatcher.Invoke(() => {
if (ctx == Context) Messages.Add(detail);
});
};
Messages = new ObservableCollection<string>();
Models.Exception.Handler = e => Dispatcher.Invoke(() => Messages.Add(e));
InitializeComponent();
}

View file

@ -303,7 +303,7 @@ namespace SourceGit.Views.Widgets {
}
}
Models.Exception.Raise("Can NOT found parent of HEAD!");
App.Exception(repo.Path, "Can NOT found parent of HEAD!");
e.Handled = true;
};
menu.Items.Add(squash);

View file

@ -1,4 +1,5 @@
<UserControl x:Class="SourceGit.Views.Widgets.Welcome"
x:Name="me"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
@ -157,5 +158,12 @@
Text="{DynamicResource Text.Welcome.DragDropTip}"
Foreground="{DynamicResource Brush.FG2}"/>
</StackPanel>
<!-- Alerts -->
<local:Exceptions
Grid.Row="1"
HorizontalAlignment="Right" VerticalAlignment="Top"
Width="330" Height="Auto"
Context="{Binding ElementName=me, Path=ExceptionContext}"/>
</Grid>
</UserControl>

View file

@ -14,8 +14,14 @@ namespace SourceGit.Views.Widgets {
/// 新标签页
/// </summary>
public partial class Welcome : UserControl {
public string ExceptionContext {
get;
set;
}
public Welcome() {
ExceptionContext = Guid.NewGuid().ToString();
InitializeComponent();
UpdateVisibles();
@ -34,7 +40,7 @@ namespace SourceGit.Views.Widgets {
if (MakeSureReady()) {
var bash = Path.Combine(Models.Preference.Instance.Git.Path, "..", "bash.exe");
if (!File.Exists(bash)) {
Models.Exception.Raise(App.Text("MissingBash"));
App.Exception(ExceptionContext, App.Text("MissingBash"));
return;
}
@ -175,7 +181,7 @@ namespace SourceGit.Views.Widgets {
var bash = Path.Combine(Models.Preference.Instance.Git.Path, "..", "bash.exe");
if (!File.Exists(bash)) {
Models.Exception.Raise(App.Text("MissingBash"));
App.Exception(ExceptionContext, App.Text("MissingBash"));
return;
}
@ -245,7 +251,7 @@ namespace SourceGit.Views.Widgets {
private bool MakeSureReady() {
if (!Models.Preference.Instance.IsReady) {
Models.Exception.Raise(App.Text("NotConfigured"));
App.Exception(ExceptionContext, App.Text("NotConfigured"));
return false;
}
return true;
@ -255,7 +261,7 @@ namespace SourceGit.Views.Widgets {
if (!MakeSureReady()) return;
if (!Directory.Exists(path)) {
Models.Exception.Raise(App.Text("PathNotFound", path));
App.Exception(ExceptionContext, App.Text("PathNotFound", path));
return;
}

View file

@ -220,7 +220,7 @@ namespace SourceGit.Views.Widgets {
var merger = Models.MergeTool.Supported.Find(x => x.Type == mergeType);
if (merger == null || merger.Type == 0 || !File.Exists(mergeExe)) {
Models.Exception.Raise("Invalid merge tool in preference setting!");
App.Exception(repo.Path, "Invalid merge tool in preference setting!");
return;
}
@ -289,7 +289,7 @@ namespace SourceGit.Views.Widgets {
private void StartAmend(object sender, RoutedEventArgs e) {
var commits = new Commands.Commits(repo.Path, "-n 1", false).Result();
if (commits.Count == 0) {
Models.Exception.Raise("No commits to amend!");
App.Exception(repo.Path, "No commits to amend!");
chkAmend.IsChecked = false;
return;
}
@ -316,12 +316,12 @@ namespace SourceGit.Views.Widgets {
var changes = await Task.Run(() => new Commands.LocalChanges(repo.Path).Result());
var conflict = changes.Find(x => x.IsConflit);
if (conflict != null) {
Models.Exception.Raise("You have unsolved conflicts in your working copy!");
App.Exception(repo.Path, "You have unsolved conflicts in your working copy!");
return;
}
if (stagedContainer.Changes.Count == 0) {
Models.Exception.Raise("No files added to commit!");
App.Exception(repo.Path, "No files added to commit!");
return;
}
@ -351,12 +351,12 @@ namespace SourceGit.Views.Widgets {
var changes = await Task.Run(() => new Commands.LocalChanges(repo.Path).Result());
var conflict = changes.Find(x => x.IsConflit);
if (conflict != null) {
Models.Exception.Raise("You have unsolved conflicts in your working copy!");
App.Exception(repo.Path, "You have unsolved conflicts in your working copy!");
return;
}
if (stagedContainer.Changes.Count == 0) {
Models.Exception.Raise("No files added to commit!");
App.Exception(repo.Path, "No files added to commit!");
return;
}