diff --git a/src/Avalonia/Artemis.UI.Shared/Services/WindowService/ExceptionDialogView.axaml b/src/Avalonia/Artemis.UI.Shared/Services/WindowService/ExceptionDialogView.axaml index 5948cba7b..c4c3c9350 100644 --- a/src/Avalonia/Artemis.UI.Shared/Services/WindowService/ExceptionDialogView.axaml +++ b/src/Avalonia/Artemis.UI.Shared/Services/WindowService/ExceptionDialogView.axaml @@ -6,31 +6,34 @@ x:Class="Artemis.UI.Shared.Services.ExceptionDialogView" Title="{Binding Title}" ExtendClientAreaToDecorationsHint="True" - Width="800" + Width="800" Height="800" WindowStartupLocation="CenterOwner"> - - + + + + + + + - - - - Awww :( - - It looks like Artemis ran into an unhandled exception. If this keeps happening feel free to hit us up on Discord. - + + Awww :( + + It looks like Artemis ran into an unhandled exception. If this keeps happening feel free to hit us up on Discord. + + - - - - + + + + When reporting errors please don't take a screenshot of the error, instead copy the text, thanks! diff --git a/src/Avalonia/Artemis.UI.Shared/Services/WindowService/ExceptionDialogViewModel.cs b/src/Avalonia/Artemis.UI.Shared/Services/WindowService/ExceptionDialogViewModel.cs index 9aa31727b..7445077d8 100644 --- a/src/Avalonia/Artemis.UI.Shared/Services/WindowService/ExceptionDialogViewModel.cs +++ b/src/Avalonia/Artemis.UI.Shared/Services/WindowService/ExceptionDialogViewModel.cs @@ -31,7 +31,7 @@ namespace Artemis.UI.Shared.Services _notificationService.CreateNotification() .WithMessage("Copied stack trace to clipboard.") .WithSeverity(NotificationSeverity.Success) - .WithHorizontalPosition(HorizontalAlignment.Center) + .WithHorizontalPosition(HorizontalAlignment.Left) .Show(); } } diff --git a/src/Avalonia/Artemis.UI/ArtemisBootstrapper.cs b/src/Avalonia/Artemis.UI/ArtemisBootstrapper.cs index ef5d53e15..be40ac024 100644 --- a/src/Avalonia/Artemis.UI/ArtemisBootstrapper.cs +++ b/src/Avalonia/Artemis.UI/ArtemisBootstrapper.cs @@ -1,13 +1,17 @@ -using Artemis.Core.Ninject; +using System; +using System.Reactive; +using Artemis.Core.Ninject; using Artemis.Core; using Artemis.UI.Exceptions; using Artemis.UI.Ninject; using Artemis.UI.Screens.Root; using Artemis.UI.Shared.Ninject; +using Artemis.UI.Shared.Services.Interfaces; using Avalonia; using Avalonia.Controls; using Avalonia.Controls.ApplicationLifetimes; using Ninject; +using ReactiveUI; using Splat.Ninject; namespace Artemis.UI @@ -23,7 +27,7 @@ namespace Artemis.UI throw new ArtemisUIException("UI already bootstrapped"); Utilities.PrepareFirstLaunch(); - + _application = application; _kernel = new StandardKernel(); _kernel.Settings.InjectNonPublic = true; @@ -42,7 +46,7 @@ namespace Artemis.UI if (_application == null || _kernel == null) throw new ArtemisUIException("UI not yet bootstrapped"); if (_application.ApplicationLifetime is not IClassicDesktopStyleApplicationLifetime desktop) - return; + return; // Don't shut down when the last window closes, we might still be active in the tray desktop.ShutdownMode = ShutdownMode.OnExplicitShutdown; @@ -50,6 +54,13 @@ namespace Artemis.UI RootViewModel rootViewModel = _kernel.Get(); // Apply the root view model to the data context of the application so that tray icon commands work _application.DataContext = rootViewModel; + + RxApp.DefaultExceptionHandler = Observer.Create(DisplayUnhandledException); + } + + private static void DisplayUnhandledException(Exception exception) + { + _kernel?.Get().ShowExceptionDialog("Exception", exception); } } } \ No newline at end of file diff --git a/src/Avalonia/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/ProfileTreeView.axaml b/src/Avalonia/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/ProfileTreeView.axaml index 5ed606f00..192d579d3 100644 --- a/src/Avalonia/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/ProfileTreeView.axaml +++ b/src/Avalonia/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/ProfileTreeView.axaml @@ -21,7 +21,49 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Avalonia/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/ProfileTreeViewModel.cs b/src/Avalonia/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/ProfileTreeViewModel.cs index e193cd003..80a6bcf8d 100644 --- a/src/Avalonia/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/ProfileTreeViewModel.cs +++ b/src/Avalonia/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/ProfileTreeViewModel.cs @@ -22,12 +22,18 @@ namespace Artemis.UI.Screens.ProfileEditor.ProfileTree { profileEditorService.ProfileConfiguration.WhereNotNull().Subscribe(configuration => { - ProfileElement = configuration.Profile!.GetRootFolder(); + if (configuration.Profile == null) + { + windowService.ShowConfirmContentDialog("Failed to load profile", "It appears that this profile is corrupt and cannot be loaded. Please check your logs.", "Confirm", null); + return; + } + + ProfileElement = configuration.Profile.GetRootFolder(); SubscribeToProfileElement(d); CreateTreeItems(); }).DisposeWith(d); - profileEditorService.ProfileElement.WhereNotNull().Subscribe(SelectCurrentProfileElement).DisposeWith(d); + profileEditorService.ProfileElement.Subscribe(SelectCurrentProfileElement).DisposeWith(d); }); this.WhenAnyValue(vm => vm.SelectedChild).Subscribe(model => @@ -43,7 +49,7 @@ namespace Artemis.UI.Screens.ProfileEditor.ProfileTree set => this.RaiseAndSetIfChanged(ref _selectedChild, value); } - private void SelectCurrentProfileElement(RenderProfileElement element) + private void SelectCurrentProfileElement(RenderProfileElement? element) { if (SelectedChild?.ProfileElement == element) return; diff --git a/src/Avalonia/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/TreeItemViewModel.cs b/src/Avalonia/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/TreeItemViewModel.cs index 441089fc7..980563191 100644 --- a/src/Avalonia/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/TreeItemViewModel.cs +++ b/src/Avalonia/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/TreeItemViewModel.cs @@ -20,13 +20,16 @@ namespace Artemis.UI.Screens.ProfileEditor.ProfileTree { private readonly IProfileEditorVmFactory _profileEditorVmFactory; private readonly IWindowService _windowService; + private readonly IProfileEditorService _profileEditorService; private bool _isExpanded; private ProfileElement? _profileElement; + private RenderProfileElement? _currentProfileElement; protected TreeItemViewModel(TreeItemViewModel? parent, ProfileElement? profileElement, IWindowService windowService, IProfileEditorService profileEditorService, IProfileEditorVmFactory profileEditorVmFactory) { _windowService = windowService; + _profileEditorService = profileEditorService; _profileEditorVmFactory = profileEditorVmFactory; Parent = parent; @@ -50,6 +53,7 @@ namespace Artemis.UI.Screens.ProfileEditor.ProfileTree this.WhenActivated(d => { + _profileEditorService.ProfileElement.Subscribe(element => _currentProfileElement = element).DisposeWith(d); SubscribeToProfileElement(d); CreateTreeItems(); }); @@ -105,6 +109,10 @@ namespace Artemis.UI.Screens.ProfileEditor.ProfileTree List toRemove = Children.Where(t => t.ProfileElement == profileElement).ToList(); foreach (TreeItemViewModel treeItemViewModel in toRemove) Children.Remove(treeItemViewModel); + + // Deselect the current profile element if removed + if (_currentProfileElement == profileElement) + _profileEditorService.ChangeCurrentProfileElement(null); } protected void AddTreeItemIfMissing(ProfileElement profileElement) @@ -116,6 +124,10 @@ namespace Artemis.UI.Screens.ProfileEditor.ProfileTree Children.Insert(folder.Parent.Children.IndexOf(folder), _profileEditorVmFactory.FolderTreeItemViewModel(this, folder)); else if (profileElement is Layer layer) Children.Insert(layer.Parent.Children.IndexOf(layer), _profileEditorVmFactory.LayerTreeItemViewModel(this, layer)); + + // Select the newly added element + if (profileElement is RenderProfileElement renderProfileElement) + _profileEditorService.ChangeCurrentProfileElement(renderProfileElement); } protected void CreateTreeItems() @@ -127,10 +139,12 @@ namespace Artemis.UI.Screens.ProfileEditor.ProfileTree return; foreach (ProfileElement profileElement in ProfileElement.Children) + { if (profileElement is Folder folder) Children.Add(_profileEditorVmFactory.FolderTreeItemViewModel(this, folder)); else if (profileElement is Layer layer) Children.Add(_profileEditorVmFactory.LayerTreeItemViewModel(this, layer)); + } } } } \ No newline at end of file diff --git a/src/Avalonia/Artemis.UI/Screens/Sidebar/Dialogs/ProfileConfigurationEditViewModel.cs b/src/Avalonia/Artemis.UI/Screens/Sidebar/Dialogs/ProfileConfigurationEditViewModel.cs index d1f66f1df..06a005cea 100644 --- a/src/Avalonia/Artemis.UI/Screens/Sidebar/Dialogs/ProfileConfigurationEditViewModel.cs +++ b/src/Avalonia/Artemis.UI/Screens/Sidebar/Dialogs/ProfileConfigurationEditViewModel.cs @@ -143,7 +143,16 @@ namespace Artemis.UI.Screens.Sidebar if (!await _windowService.ShowConfirmContentDialog("Delete profile", "Are you sure you want to permanently delete this profile?")) return; - _profileService.RemoveProfileConfiguration(_profileConfiguration); + try + { + _profileService.RemoveProfileConfiguration(_profileConfiguration); + } + catch (Exception e) + { + Console.WriteLine(e); + throw; + } + Close(true); }