mirror of
https://github.com/bloxstraplabs/bloxstrap.git
synced 2025-04-21 10:01:27 -07:00
Add new exception dialog
This commit is contained in:
parent
e708ef30fa
commit
dc0531eb38
@ -16,10 +16,10 @@ using Microsoft.Win32;
|
|||||||
using Bloxstrap.Extensions;
|
using Bloxstrap.Extensions;
|
||||||
using Bloxstrap.Models;
|
using Bloxstrap.Models;
|
||||||
using Bloxstrap.Models.Attributes;
|
using Bloxstrap.Models.Attributes;
|
||||||
|
using Bloxstrap.UI;
|
||||||
using Bloxstrap.UI.BootstrapperDialogs;
|
using Bloxstrap.UI.BootstrapperDialogs;
|
||||||
using Bloxstrap.UI.MessageBox;
|
using Bloxstrap.UI.MessageBox;
|
||||||
using Bloxstrap.Utility;
|
using Bloxstrap.Utility;
|
||||||
using Bloxstrap.UI;
|
|
||||||
|
|
||||||
namespace Bloxstrap
|
namespace Bloxstrap
|
||||||
{
|
{
|
||||||
@ -100,8 +100,17 @@ namespace Bloxstrap
|
|||||||
Logger.WriteLine("[App::OnStartup] An exception occurred when running the main thread");
|
Logger.WriteLine("[App::OnStartup] An exception occurred when running the main thread");
|
||||||
Logger.WriteLine($"[App::OnStartup] {e.Exception}");
|
Logger.WriteLine($"[App::OnStartup] {e.Exception}");
|
||||||
|
|
||||||
|
FinalizeExceptionHandling(e.Exception);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FinalizeExceptionHandling(Exception exception)
|
||||||
|
{
|
||||||
|
#if DEBUG
|
||||||
|
throw exception;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (!IsQuiet)
|
if (!IsQuiet)
|
||||||
Settings.Prop.BootstrapperStyle.GetNew().ShowError($"{e.Exception.GetType()}: {e.Exception.Message}");
|
Controls.ShowExceptionDialog(exception);
|
||||||
|
|
||||||
Terminate(Bootstrapper.ERROR_INSTALL_FAILURE);
|
Terminate(Bootstrapper.ERROR_INSTALL_FAILURE);
|
||||||
}
|
}
|
||||||
@ -313,13 +322,9 @@ namespace Bloxstrap
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// there's a bug here that i have yet to fix!
|
Task bootstrapperTask = Task.Run(() => bootstrapper.Run());
|
||||||
// sometimes the task just terminates when the bootstrapper hasn't
|
|
||||||
// actually finished, causing the bootstrapper to hang indefinitely
|
bootstrapperTask.ContinueWith(t =>
|
||||||
// i have no idea how the fuck this happens, but it happens like VERY
|
|
||||||
// rarely so i'm not too concerned by it
|
|
||||||
// maybe one day ill find out why it happens
|
|
||||||
Task bootstrapperTask = Task.Run(() => bootstrapper.Run()).ContinueWith(t =>
|
|
||||||
{
|
{
|
||||||
Logger.WriteLine("[App::OnStartup] Bootstrapper task has finished");
|
Logger.WriteLine("[App::OnStartup] Bootstrapper task has finished");
|
||||||
|
|
||||||
@ -331,16 +336,18 @@ namespace Bloxstrap
|
|||||||
|
|
||||||
Logger.WriteLine($"[App::OnStartup] {t.Exception}");
|
Logger.WriteLine($"[App::OnStartup] {t.Exception}");
|
||||||
|
|
||||||
#if DEBUG
|
Exception exception = t.Exception;
|
||||||
throw t.Exception;
|
|
||||||
#else
|
#if !DEBUG
|
||||||
var exception = t.Exception.InnerExceptions.Count >= 1 ? t.Exception.InnerExceptions[0] : t.Exception;
|
if (t.Exception.GetType().ToString() == "System.AggregateException")
|
||||||
dialog?.ShowError($"{exception.GetType()}: {exception.Message}");
|
exception = t.Exception.InnerException!;
|
||||||
Terminate(Bootstrapper.ERROR_INSTALL_FAILURE);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
FinalizeExceptionHandling(exception);
|
||||||
});
|
});
|
||||||
|
|
||||||
dialog?.ShowBootstrapper();
|
dialog?.ShowBootstrapper();
|
||||||
|
|
||||||
bootstrapperTask.Wait();
|
bootstrapperTask.Wait();
|
||||||
|
|
||||||
if (singletonMutex is not null)
|
if (singletonMutex is not null)
|
||||||
|
@ -16,9 +16,12 @@ namespace Bloxstrap
|
|||||||
public class Logger
|
public class Logger
|
||||||
{
|
{
|
||||||
private readonly SemaphoreSlim _semaphore = new(1, 1);
|
private readonly SemaphoreSlim _semaphore = new(1, 1);
|
||||||
private readonly List<string> _backlog = new();
|
|
||||||
private FileStream? _filestream;
|
private FileStream? _filestream;
|
||||||
|
|
||||||
|
public readonly List<string> Backlog = new();
|
||||||
|
public bool Initialized = false;
|
||||||
|
public string? Filename;
|
||||||
|
|
||||||
public void Initialize(string filename)
|
public void Initialize(string filename)
|
||||||
{
|
{
|
||||||
if (_filestream is not null)
|
if (_filestream is not null)
|
||||||
@ -31,10 +34,13 @@ namespace Bloxstrap
|
|||||||
|
|
||||||
_filestream = File.Open(filename, FileMode.Create, FileAccess.Write, FileShare.Read);
|
_filestream = File.Open(filename, FileMode.Create, FileAccess.Write, FileShare.Read);
|
||||||
|
|
||||||
if (_backlog.Count > 0)
|
if (Backlog.Count > 0)
|
||||||
WriteToLog(string.Join("\r\n", _backlog));
|
WriteToLog(string.Join("\r\n", Backlog));
|
||||||
|
|
||||||
WriteLine($"[Logger::Logger] Initialized at {filename}");
|
WriteLine($"[Logger::Logger] Initialized at {filename}");
|
||||||
|
|
||||||
|
Initialized = true;
|
||||||
|
Filename = filename;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void WriteLine(string message)
|
public void WriteLine(string message)
|
||||||
@ -49,16 +55,16 @@ namespace Bloxstrap
|
|||||||
|
|
||||||
private async void WriteToLog(string message)
|
private async void WriteToLog(string message)
|
||||||
{
|
{
|
||||||
if (_filestream is null)
|
if (!Initialized)
|
||||||
{
|
{
|
||||||
_backlog.Add(message);
|
Backlog.Add(message);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await _semaphore.WaitAsync();
|
await _semaphore.WaitAsync();
|
||||||
await _filestream.WriteAsync(Encoding.Unicode.GetBytes($"{message}\r\n"));
|
await _filestream!.WriteAsync(Encoding.Unicode.GetBytes($"{message}\r\n"));
|
||||||
await _filestream.FlushAsync();
|
await _filestream.FlushAsync();
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
|
@ -14,11 +14,5 @@ namespace Bloxstrap.UI.BootstrapperDialogs
|
|||||||
|
|
||||||
App.Terminate();
|
App.Terminate();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void ShowError(string message)
|
|
||||||
{
|
|
||||||
Controls.ShowMessageBox($"An error occurred while starting Roblox\n\nDetails: {message}", MessageBoxImage.Error);
|
|
||||||
App.Terminate(Bootstrapper.ERROR_INSTALL_FAILURE);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,5 @@ namespace Bloxstrap.UI.BootstrapperDialogs
|
|||||||
void ShowBootstrapper();
|
void ShowBootstrapper();
|
||||||
void CloseBootstrapper();
|
void CloseBootstrapper();
|
||||||
void ShowSuccess(string message, Action? callback = null);
|
void ShowSuccess(string message, Action? callback = null);
|
||||||
void ShowError(string message);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -92,8 +92,6 @@ namespace Bloxstrap.UI.BootstrapperDialogs.WPF.Views
|
|||||||
public void CloseBootstrapper() => Dispatcher.BeginInvoke(this.Close);
|
public void CloseBootstrapper() => Dispatcher.BeginInvoke(this.Close);
|
||||||
|
|
||||||
public void ShowSuccess(string message, Action? callback) => BaseFunctions.ShowSuccess(message, callback);
|
public void ShowSuccess(string message, Action? callback) => BaseFunctions.ShowSuccess(message, callback);
|
||||||
|
|
||||||
public void ShowError(string message) => BaseFunctions.ShowError(message);
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -86,10 +86,7 @@ namespace Bloxstrap.UI.BootstrapperDialogs.WPF.Views
|
|||||||
|
|
||||||
public void CloseBootstrapper() => Dispatcher.BeginInvoke(this.Close);
|
public void CloseBootstrapper() => Dispatcher.BeginInvoke(this.Close);
|
||||||
|
|
||||||
// TODO: make prompts use dialog view natively rather than using message dialog boxes
|
|
||||||
public void ShowSuccess(string message, Action? callback) => BaseFunctions.ShowSuccess(message, callback);
|
public void ShowSuccess(string message, Action? callback) => BaseFunctions.ShowSuccess(message, callback);
|
||||||
|
|
||||||
public void ShowError(string message) => BaseFunctions.ShowError(message);
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -101,8 +101,6 @@ namespace Bloxstrap.UI.BootstrapperDialogs.WinForms
|
|||||||
}
|
}
|
||||||
|
|
||||||
public virtual void ShowSuccess(string message, Action? callback) => BaseFunctions.ShowSuccess(message, callback);
|
public virtual void ShowSuccess(string message, Action? callback) => BaseFunctions.ShowSuccess(message, callback);
|
||||||
|
|
||||||
public virtual void ShowError(string message) => BaseFunctions.ShowError(message);
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -109,36 +109,6 @@ namespace Bloxstrap.UI.BootstrapperDialogs.WinForms
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void ShowError(string message)
|
|
||||||
{
|
|
||||||
if (this.InvokeRequired)
|
|
||||||
{
|
|
||||||
this.Invoke(ShowError, message);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
TaskDialogPage errorDialog = new()
|
|
||||||
{
|
|
||||||
Icon = TaskDialogIcon.Error,
|
|
||||||
Caption = App.Settings.Prop.BootstrapperTitle,
|
|
||||||
Heading = "An error occurred while starting Roblox",
|
|
||||||
Buttons = { TaskDialogButton.Close },
|
|
||||||
Expander = new TaskDialogExpander()
|
|
||||||
{
|
|
||||||
Text = message,
|
|
||||||
CollapsedButtonText = "See details",
|
|
||||||
ExpandedButtonText = "Hide details",
|
|
||||||
Position = TaskDialogExpanderPosition.AfterText
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
errorDialog.Buttons[0].Click += (sender, e) => App.Terminate(Bootstrapper.ERROR_INSTALL_FAILURE);
|
|
||||||
|
|
||||||
_dialogPage.Navigate(errorDialog);
|
|
||||||
_dialogPage = errorDialog;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void CloseBootstrapper()
|
public override void CloseBootstrapper()
|
||||||
{
|
{
|
||||||
if (this.InvokeRequired)
|
if (this.InvokeRequired)
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
using System.Windows;
|
using System;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Windows;
|
||||||
|
|
||||||
using Bloxstrap.Enums;
|
using Bloxstrap.Enums;
|
||||||
using Bloxstrap.UI.Menu.Views;
|
using Bloxstrap.UI.Menu.Views;
|
||||||
@ -22,5 +24,13 @@ namespace Bloxstrap.UI
|
|||||||
return NativeMessageBox.Show(message, icon, buttons, defaultResult);
|
return NativeMessageBox.Show(message, icon, buttons, defaultResult);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void ShowExceptionDialog(Exception exception)
|
||||||
|
{
|
||||||
|
Application.Current.Dispatcher.Invoke(() =>
|
||||||
|
{
|
||||||
|
new ExceptionDialog(exception).ShowDialog();
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
49
Bloxstrap/UI/ExceptionDialog.xaml
Normal file
49
Bloxstrap/UI/ExceptionDialog.xaml
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
<ui:UiWindow x:Class="Bloxstrap.UI.ExceptionDialog"
|
||||||
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
|
xmlns:ui="http://schemas.lepo.co/wpfui/2022/xaml"
|
||||||
|
xmlns:local="clr-namespace:Bloxstrap.UI.MessageBox"
|
||||||
|
mc:Ignorable="d"
|
||||||
|
Width="480"
|
||||||
|
MinHeight="0"
|
||||||
|
SizeToContent="Height"
|
||||||
|
Background="{ui:ThemeResource ApplicationBackgroundBrush}"
|
||||||
|
ExtendsContentIntoTitleBar="True"
|
||||||
|
WindowStartupLocation="CenterScreen">
|
||||||
|
<Grid>
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition Height="Auto" />
|
||||||
|
<RowDefinition Height="*" />
|
||||||
|
<RowDefinition Height="Auto" />
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
|
||||||
|
<ui:TitleBar Grid.Row="0" Grid.ColumnSpan="2" Padding="8" x:Name="RootTitleBar" ShowMinimize="False" ShowMaximize="False" CanMaximize="False" KeyboardNavigation.TabNavigation="None" />
|
||||||
|
|
||||||
|
<Grid Grid.Row="1" Margin="16">
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="Auto" />
|
||||||
|
<ColumnDefinition Width="*" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<Image Grid.Column="0" Width="32" Height="32" Margin="0,0,15,0" VerticalAlignment="Top" RenderOptions.BitmapScalingMode="HighQuality" Source="pack://application:,,,/Resources/MessageBox/Error.png" />
|
||||||
|
<StackPanel Grid.Column="1">
|
||||||
|
<TextBlock Text="An exception occurred while running Bloxstrap" FontSize="18" Foreground="{DynamicResource TextFillColorPrimaryBrush}" />
|
||||||
|
<RichTextBox x:Name="ErrorRichTextBox" Padding="8" Margin="0,16,0,0" Block.LineHeight="2" FontFamily="Courier New" IsReadOnly="True" />
|
||||||
|
<TextBlock Text="Please report this exception through a GitHub issue or in our Discord chat, along with a copy of the log file that was created." Margin="0,16,0,0" TextWrapping="Wrap" Foreground="{DynamicResource TextFillColorPrimaryBrush}" />
|
||||||
|
</StackPanel>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
<Border Grid.Row="2" Padding="15" Background="{ui:ThemeResource SolidBackgroundFillColorSecondaryBrush}">
|
||||||
|
<StackPanel Orientation="Horizontal" FlowDirection="LeftToRight" HorizontalAlignment="Right">
|
||||||
|
<Button x:Name="LocateLogFileButton" Content="Locate log file" />
|
||||||
|
<ComboBox x:Name="ReportOptions" SelectedIndex="0" Padding="12,6,12,6" Margin="12,0,0,0">
|
||||||
|
<ComboBoxItem Content="Report exception" Visibility="Collapsed" />
|
||||||
|
<ComboBoxItem Content="Report via GitHub" />
|
||||||
|
<ComboBoxItem Content="Report via Discord" />
|
||||||
|
</ComboBox>
|
||||||
|
<Button x:Name="CloseButton" MinWidth="100" Content="Close" Margin="12,0,0,0" />
|
||||||
|
</StackPanel>
|
||||||
|
</Border>
|
||||||
|
</Grid>
|
||||||
|
</ui:UiWindow>
|
65
Bloxstrap/UI/ExceptionDialog.xaml.cs
Normal file
65
Bloxstrap/UI/ExceptionDialog.xaml.cs
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Configuration;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Media;
|
||||||
|
using System.Windows;
|
||||||
|
using System.Windows.Controls;
|
||||||
|
using System.Windows.Interop;
|
||||||
|
using System.Windows.Media.Imaging;
|
||||||
|
|
||||||
|
using Bloxstrap.Utility;
|
||||||
|
|
||||||
|
namespace Bloxstrap.UI
|
||||||
|
{
|
||||||
|
// hmm... do i use MVVM for this?
|
||||||
|
// this is entirely static, so i think im fine without it, and this way is just so much more efficient
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Interaction logic for ExceptionDialog.xaml
|
||||||
|
/// </summary>
|
||||||
|
public partial class ExceptionDialog
|
||||||
|
{
|
||||||
|
public ExceptionDialog(Exception exception)
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
|
||||||
|
Title = RootTitleBar.Title = $"{App.ProjectName} Exception";
|
||||||
|
ErrorRichTextBox.Selection.Text = $"{exception.GetType()}: {exception.Message}";
|
||||||
|
|
||||||
|
if (!App.Logger.Initialized)
|
||||||
|
LocateLogFileButton.Content = "Copy log contents";
|
||||||
|
|
||||||
|
LocateLogFileButton.Click += delegate
|
||||||
|
{
|
||||||
|
if (App.Logger.Initialized)
|
||||||
|
Process.Start("explorer.exe", $"/select,\"{App.Logger.Filename}\"");
|
||||||
|
else
|
||||||
|
Clipboard.SetText(String.Join("\r\n", App.Logger.Backlog));
|
||||||
|
};
|
||||||
|
|
||||||
|
ReportOptions.DropDownClosed += (sender, e) =>
|
||||||
|
{
|
||||||
|
string? selectionName = ReportOptions.SelectedItem.ToString();
|
||||||
|
|
||||||
|
ReportOptions.SelectedIndex = 0;
|
||||||
|
|
||||||
|
if (selectionName is null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (selectionName.EndsWith("GitHub"))
|
||||||
|
Utilities.ShellExecute($"https://github.com/{App.ProjectRepository}/issues");
|
||||||
|
else if (selectionName.EndsWith("Discord"))
|
||||||
|
Utilities.ShellExecute("https://discord.gg/nKjV3mGq6R");
|
||||||
|
};
|
||||||
|
|
||||||
|
CloseButton.Click += delegate
|
||||||
|
{
|
||||||
|
Close();
|
||||||
|
};
|
||||||
|
|
||||||
|
SystemSounds.Hand.Play();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user