mirror of
https://github.com/bloxstraplabs/bloxstrap.git
synced 2025-04-16 02:01:29 -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.Models;
|
||||
using Bloxstrap.Models.Attributes;
|
||||
using Bloxstrap.UI;
|
||||
using Bloxstrap.UI.BootstrapperDialogs;
|
||||
using Bloxstrap.UI.MessageBox;
|
||||
using Bloxstrap.Utility;
|
||||
using Bloxstrap.UI;
|
||||
|
||||
namespace Bloxstrap
|
||||
{
|
||||
@ -100,8 +100,17 @@ namespace Bloxstrap
|
||||
Logger.WriteLine("[App::OnStartup] An exception occurred when running the main thread");
|
||||
Logger.WriteLine($"[App::OnStartup] {e.Exception}");
|
||||
|
||||
FinalizeExceptionHandling(e.Exception);
|
||||
}
|
||||
|
||||
void FinalizeExceptionHandling(Exception exception)
|
||||
{
|
||||
#if DEBUG
|
||||
throw exception;
|
||||
#endif
|
||||
|
||||
if (!IsQuiet)
|
||||
Settings.Prop.BootstrapperStyle.GetNew().ShowError($"{e.Exception.GetType()}: {e.Exception.Message}");
|
||||
Controls.ShowExceptionDialog(exception);
|
||||
|
||||
Terminate(Bootstrapper.ERROR_INSTALL_FAILURE);
|
||||
}
|
||||
@ -313,13 +322,9 @@ namespace Bloxstrap
|
||||
}
|
||||
}
|
||||
|
||||
// there's a bug here that i have yet to fix!
|
||||
// sometimes the task just terminates when the bootstrapper hasn't
|
||||
// actually finished, causing the bootstrapper to hang indefinitely
|
||||
// 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 =>
|
||||
Task bootstrapperTask = Task.Run(() => bootstrapper.Run());
|
||||
|
||||
bootstrapperTask.ContinueWith(t =>
|
||||
{
|
||||
Logger.WriteLine("[App::OnStartup] Bootstrapper task has finished");
|
||||
|
||||
@ -331,16 +336,18 @@ namespace Bloxstrap
|
||||
|
||||
Logger.WriteLine($"[App::OnStartup] {t.Exception}");
|
||||
|
||||
#if DEBUG
|
||||
throw t.Exception;
|
||||
#else
|
||||
var exception = t.Exception.InnerExceptions.Count >= 1 ? t.Exception.InnerExceptions[0] : t.Exception;
|
||||
dialog?.ShowError($"{exception.GetType()}: {exception.Message}");
|
||||
Terminate(Bootstrapper.ERROR_INSTALL_FAILURE);
|
||||
Exception exception = t.Exception;
|
||||
|
||||
#if !DEBUG
|
||||
if (t.Exception.GetType().ToString() == "System.AggregateException")
|
||||
exception = t.Exception.InnerException!;
|
||||
#endif
|
||||
|
||||
FinalizeExceptionHandling(exception);
|
||||
});
|
||||
|
||||
dialog?.ShowBootstrapper();
|
||||
|
||||
bootstrapperTask.Wait();
|
||||
|
||||
if (singletonMutex is not null)
|
||||
|
@ -16,9 +16,12 @@ namespace Bloxstrap
|
||||
public class Logger
|
||||
{
|
||||
private readonly SemaphoreSlim _semaphore = new(1, 1);
|
||||
private readonly List<string> _backlog = new();
|
||||
private FileStream? _filestream;
|
||||
|
||||
public readonly List<string> Backlog = new();
|
||||
public bool Initialized = false;
|
||||
public string? Filename;
|
||||
|
||||
public void Initialize(string filename)
|
||||
{
|
||||
if (_filestream is not null)
|
||||
@ -31,10 +34,13 @@ namespace Bloxstrap
|
||||
|
||||
_filestream = File.Open(filename, FileMode.Create, FileAccess.Write, FileShare.Read);
|
||||
|
||||
if (_backlog.Count > 0)
|
||||
WriteToLog(string.Join("\r\n", _backlog));
|
||||
if (Backlog.Count > 0)
|
||||
WriteToLog(string.Join("\r\n", Backlog));
|
||||
|
||||
WriteLine($"[Logger::Logger] Initialized at {filename}");
|
||||
|
||||
Initialized = true;
|
||||
Filename = filename;
|
||||
}
|
||||
|
||||
public void WriteLine(string message)
|
||||
@ -49,16 +55,16 @@ namespace Bloxstrap
|
||||
|
||||
private async void WriteToLog(string message)
|
||||
{
|
||||
if (_filestream is null)
|
||||
if (!Initialized)
|
||||
{
|
||||
_backlog.Add(message);
|
||||
Backlog.Add(message);
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
await _semaphore.WaitAsync();
|
||||
await _filestream.WriteAsync(Encoding.Unicode.GetBytes($"{message}\r\n"));
|
||||
await _filestream!.WriteAsync(Encoding.Unicode.GetBytes($"{message}\r\n"));
|
||||
await _filestream.FlushAsync();
|
||||
}
|
||||
finally
|
||||
|
@ -14,11 +14,5 @@ namespace Bloxstrap.UI.BootstrapperDialogs
|
||||
|
||||
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 CloseBootstrapper();
|
||||
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 ShowSuccess(string message, Action? callback) => BaseFunctions.ShowSuccess(message, callback);
|
||||
|
||||
public void ShowError(string message) => BaseFunctions.ShowError(message);
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
@ -86,10 +86,7 @@ namespace Bloxstrap.UI.BootstrapperDialogs.WPF.Views
|
||||
|
||||
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 ShowError(string message) => BaseFunctions.ShowError(message);
|
||||
#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 ShowError(string message) => BaseFunctions.ShowError(message);
|
||||
#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()
|
||||
{
|
||||
if (this.InvokeRequired)
|
||||
|
@ -1,4 +1,6 @@
|
||||
using System.Windows;
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Windows;
|
||||
|
||||
using Bloxstrap.Enums;
|
||||
using Bloxstrap.UI.Menu.Views;
|
||||
@ -22,5 +24,13 @@ namespace Bloxstrap.UI
|
||||
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