Skip to content

Commit

Permalink
settings system implementation + better exception handling.
Browse files Browse the repository at this point in the history
  • Loading branch information
NoobNotFound committed Dec 5, 2024
1 parent cddab53 commit 96375cc
Show file tree
Hide file tree
Showing 22 changed files with 687 additions and 128 deletions.
127 changes: 118 additions & 9 deletions Emerald/App.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,42 +5,55 @@
using Uno.UI.HotDesign;
using Microsoft.Extensions.DependencyInjection;
using Emerald.CoreX.Store.Modrinth;
using System.Diagnostics;
using System;
using Emerald.Helpers;

namespace Emerald;
public partial class App : Application
{
private Helpers.Settings.SettingsSystem SS;
/// <summary>
/// Initializes the singleton application object. This is the first line of authored code
/// executed, and as such is the logical equivalent of main() or WinMain().
/// </summary>
public App()
{
this.InitializeComponent();
this.InitializeComponent();

// Register exception handlers

this.UnhandledException += App_UnhandledException;
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
TaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskException;
}


public Window? MainWindow { get; private set; }
protected IHost? Host { get; private set; }
public void ConfigureServices(IServiceCollection services)
private void ConfigureServices(IServiceCollection services)
{

//Stores
services.AddTransient(provider => new ModStore(typeof(ModStore).Log()));
services.AddTransient(provider => new PluginStore(typeof(PluginStore).Log()));
services.AddTransient(provider => new ResourcePackStore(typeof(ResourcePackStore).Log()));
services.AddTransient(provider => new ResourcePackStore(typeof(ShaderStore).Log()));
services.AddTransient(provider => new ModpackStore(typeof(ModpackStore).Log()));


//Settings
services.AddSingleton<Helpers.Settings.SettingsSystem>();


}

protected override void OnLaunched(LaunchActivatedEventArgs args)
protected override async void OnLaunched(LaunchActivatedEventArgs args)
{

var logPath = Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
"Emerald",
"logs",
"app_.log");


var builder = this.CreateBuilder(args)
.Configure(host => host
#if DEBUG
Expand All @@ -54,7 +67,7 @@ protected override void OnLaunched(LaunchActivatedEventArgs args)
.WriteTo.File(logPath,
rollingInterval: RollingInterval.Day,
retainedFileCountLimit: 7,
outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level}] ({SourceContext}.{Method}) {Message}{NewLine}{Exception}"))
outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level}] ({SourceContext}) {Message}{NewLine}{Exception}"))

.ConfigureServices((context, services) =>
{
Expand All @@ -71,8 +84,9 @@ protected override void OnLaunched(LaunchActivatedEventArgs args)
Host = builder.Build();

//Help me.
ServiceLocator.SetLocatorProvider(() => new Emerald.Helpers.Services.ServiceProviderLocator(Host!.Services));
ServiceLocator.SetLocatorProvider(() => new Emerald.Services.ServiceProviderLocator(Host!.Services));

SS = ServiceLocator.Current.GetInstance<Helpers.Settings.SettingsSystem>();
this.Log().LogInformation("New Instance was created. Logs are being saved at: {logPath}",logPath);

// Do not repeat app initialization when the Window already has content,
Expand All @@ -82,6 +96,9 @@ protected override void OnLaunched(LaunchActivatedEventArgs args)
// Create a Frame to act as the navigation context and navigate to the first page
rootFrame = new Frame();

//load settings,
SS.LoadData();

// Place the frame in the current Window
MainWindow.Content = rootFrame;
}
Expand All @@ -95,10 +112,102 @@ protected override void OnLaunched(LaunchActivatedEventArgs args)
}
// Ensure the current window is active
MainWindow.Activate();

MainWindow.Closed += MainWindow_Closed;
}

private void MainWindow_Closed(object sender, WindowEventArgs args)
{
//save settings,
SS.SaveData();
}

/// <summary>
/// Gets the current <see cref="App"/> instance in use
/// </summary>
public new static App Current => (App)Application.Current;

#region UnhandledExceptions
private void App_UnhandledException(object sender, Microsoft.UI.Xaml.UnhandledExceptionEventArgs e)
{
var logPath = Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
"Emerald");
e.Handled = true;
LogUnhandledException(e.Exception, "UI UnhandledException");
ShowPlatformErrorDialog($"An unexpected error occurred. The application needs to be closed.\n see logs at {logPath} for more details");
}

private void CurrentDomain_UnhandledException(object sender, System.UnhandledExceptionEventArgs e)
{
var logPath = Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
"Emerald");
LogUnhandledException((Exception)e.ExceptionObject, "AppDomain UnhandledException");
ShowPlatformErrorDialog($"A critical error occurred. The application needs to be closed.\n see logs at {logPath} for more details");
}

private void TaskScheduler_UnobservedTaskException(object sender, UnobservedTaskExceptionEventArgs e)
{
var logPath = Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
"Emerald");
e.SetObserved();
LogUnhandledException(e.Exception, "Task UnobservedException");
ShowPlatformErrorDialog($"A unobserved error occurred. The application needs to be closed.\n see logs at {logPath} for more details");
}

private void LogUnhandledException(Exception exception, string source)
{
try
{
this.Log().LogCritical(exception,
"Unhandled exception ({Source}). Platform: {Platform}",
source,
DirectResoucres.Platform
);

// Save to crash file (platform-specific path)
var crashPath = Path.Combine(
#if WINDOWS
Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
#else
Environment.GetFolderPath(Environment.SpecialFolder.Personal),
#endif
"Emerald",
"crashes",
$"crash_{DateTime.Now:yyyyMMdd_HHmmss}.txt"
);

Directory.CreateDirectory(Path.GetDirectoryName(crashPath));
File.WriteAllText(crashPath, $"""
Exception Details:
Time: {DateTime.Now}
Platform: {DirectResoucres.Platform}
Type: {exception.GetType().FullName}
Message: {exception.Message}
Stack Trace: {exception.StackTrace}
""");
}
catch (Exception ex)
{
Debug.WriteLine($"Failed to log unhandled exception: {ex.Message}");
}
}

private async void ShowPlatformErrorDialog(string message)
{
try
{
await MessageBox.Show("AppCrash".Localize(), message, Helpers.Enums.MessageBoxButtons.Ok);
Application.Current.Exit();

}
catch (Exception ex)
{
Debug.WriteLine($"Error: {message}");
}
Process.GetCurrentProcess().Kill();
}
#endregion
}
15 changes: 15 additions & 0 deletions Emerald/DirectResources.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,21 @@ public static int MinRAM
public static string SettingsAPIVersion
=> "1.3";

public static string Platform
{
get
{
#if WINDOWS
return "Windows";
#elif MACCATALYST
return "OSX";
#elif DESKTOP
return "Skia";
#else
return "Unknown";
#endif
}
}
public static string BuildType
{
get
Expand Down
9 changes: 9 additions & 0 deletions Emerald/Emerald.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
<None Remove="Views\Settings\AppearancePage.xaml" />
<None Remove="Views\Settings\GeneralPage.xaml" />
<None Remove="Views\Settings\SettingsPage.xaml" />
<None Remove="Views\Store\ModrinthStorePage.xaml" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="CommunityToolkit.WinUI.Controls.SettingsControls" />
Expand Down Expand Up @@ -98,4 +99,12 @@
<UpToDateCheckInput Remove="Views\Settings\AppearancePage.xaml" />
</ItemGroup>

<ItemGroup>
<UpToDateCheckInput Remove="Views\Store\ModrinthStorePage.xaml" />
</ItemGroup>

<ItemGroup>
<Folder Include="Services\Interfaces\" />
</ItemGroup>

</Project>
22 changes: 22 additions & 0 deletions Emerald/Helpers/Enums/MessageBox.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
namespace Emerald.Helpers.Enums;

public enum MessageBoxResults
{
Ok,
Cancel,
Yes,
No,
CustomResult1,
CustomResult2,
OpenFailed
}

public enum MessageBoxButtons
{
Ok,
OkCancel,
YesNo,
YesNoCancel,
Custom,
CustomWithCancel
}
3 changes: 2 additions & 1 deletion Emerald/Helpers/Extensions.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using CommonServiceLocator;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.Windows.ApplicationModel.Resources;
Expand Down Expand Up @@ -78,7 +79,7 @@ public static ContentDialog ToContentDialog(this UIElement content, string title
Content = content,
Padding = new(12)
} : content,
RequestedTheme = (ElementTheme)Settings.SettingsSystem.Settings.App.Appearance.Theme
RequestedTheme = (ElementTheme)ServiceLocator.Current.GetInstance< Helpers.Settings.SettingsSystem>().Settings.App.Appearance.Theme
};
App.Current.Log().LogInformation("Created ContentDialog with title: {title}", title);
return dialog;
Expand Down
Loading

0 comments on commit 96375cc

Please sign in to comment.