From d6d3cdd5739e6b8f8df36bf393e440f4857fb2b7 Mon Sep 17 00:00:00 2001
From: Isaac Marovitz <42140194+IsaacMarovitz@users.noreply.github.com>
Date: Mon, 25 Sep 2023 18:04:58 -0400
Subject: Ava UI: Refactor `async` usage (#5516)

* Remove `async void`

* Async LoadApplications

* Formatting and such

* Remove async from InstallUpdate

* Update src/Ryujinx.Ava/UI/Controls/ApplicationContextMenu.axaml.cs

Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com>

* Cleanup LoadApplications()

* Cleanup

* Formatting

* Revert some stuff

* Cleanup

* Update src/Ryujinx.Ava/UI/ViewModels/MainWindowViewModel.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Ack suggestions

* Whitespace

* Fix Peri suggestion

* Add missing trailing commas

* Remove redundant method override

* Remove Dispatcher.UIThread.InvokeAsync/Post where possible

---------

Co-authored-by: TSR Berry <20988865+TSRBerry@users.noreply.github.com>
Co-authored-by: Ac_K <Acoustik666@gmail.com>
---
 src/Ryujinx.Ava/App.axaml.cs                       |   2 +-
 src/Ryujinx.Ava/AppHost.cs                         |   1 -
 src/Ryujinx.Ava/Common/ApplicationHelper.cs        |   2 +-
 src/Ryujinx.Ava/Input/AvaloniaKeyboardDriver.cs    |   1 -
 src/Ryujinx.Ava/Modules/Updater/Updater.cs         | 162 +++++++++------------
 src/Ryujinx.Ava/UI/Applet/AvaHostUiHandler.cs      |   4 +-
 .../UI/Controls/ApplicationContextMenu.axaml.cs    |  32 ++--
 .../DownloadableContentManagerViewModel.cs         |   6 +-
 .../UI/ViewModels/MainWindowViewModel.cs           | 104 ++++++-------
 src/Ryujinx.Ava/UI/ViewModels/SettingsViewModel.cs |   9 +-
 .../UI/ViewModels/TitleUpdateViewModel.cs          |  19 +--
 .../UI/Views/Main/MainMenuBarView.axaml.cs         |  25 +---
 .../UI/Views/Settings/SettingsUIView.axaml.cs      |   8 +-
 .../User/UserProfileImageSelectorView.axaml.cs     |   6 +-
 src/Ryujinx.Ava/UI/Windows/MainWindow.axaml.cs     | 136 ++++++++---------
 src/Ryujinx.Ava/UI/Windows/StyleableWindow.cs      |   6 -
 16 files changed, 225 insertions(+), 298 deletions(-)

(limited to 'src')

diff --git a/src/Ryujinx.Ava/App.axaml.cs b/src/Ryujinx.Ava/App.axaml.cs
index 031e7e44..c1a3ab3e 100644
--- a/src/Ryujinx.Ava/App.axaml.cs
+++ b/src/Ryujinx.Ava/App.axaml.cs
@@ -104,7 +104,7 @@ namespace Ryujinx.Ava
                 {
                     "Light" => ThemeVariant.Light,
                     "Dark" => ThemeVariant.Dark,
-                    _ => ThemeVariant.Default
+                    _ => ThemeVariant.Default,
                 };
 
                 if (enableCustomTheme)
diff --git a/src/Ryujinx.Ava/AppHost.cs b/src/Ryujinx.Ava/AppHost.cs
index b6920821..c473cf56 100644
--- a/src/Ryujinx.Ava/AppHost.cs
+++ b/src/Ryujinx.Ava/AppHost.cs
@@ -3,7 +3,6 @@ using Avalonia;
 using Avalonia.Controls;
 using Avalonia.Controls.ApplicationLifetimes;
 using Avalonia.Input;
-using Avalonia.Rendering;
 using Avalonia.Threading;
 using LibHac.Tools.FsSystem;
 using Ryujinx.Audio.Backends.Dummy;
diff --git a/src/Ryujinx.Ava/Common/ApplicationHelper.cs b/src/Ryujinx.Ava/Common/ApplicationHelper.cs
index cfd929c6..b8cd06f3 100644
--- a/src/Ryujinx.Ava/Common/ApplicationHelper.cs
+++ b/src/Ryujinx.Ava/Common/ApplicationHelper.cs
@@ -145,7 +145,7 @@ namespace Ryujinx.Ava.Common
             var result = await storageProvider.OpenFolderPickerAsync(new FolderPickerOpenOptions
             {
                 Title = LocaleManager.Instance[LocaleKeys.FolderDialogExtractTitle],
-                AllowMultiple = false
+                AllowMultiple = false,
             });
 
             if (result.Count == 0)
diff --git a/src/Ryujinx.Ava/Input/AvaloniaKeyboardDriver.cs b/src/Ryujinx.Ava/Input/AvaloniaKeyboardDriver.cs
index 856ed6f7..bff24a81 100644
--- a/src/Ryujinx.Ava/Input/AvaloniaKeyboardDriver.cs
+++ b/src/Ryujinx.Ava/Input/AvaloniaKeyboardDriver.cs
@@ -1,6 +1,5 @@
 using Avalonia.Controls;
 using Avalonia.Input;
-using Avalonia.Interactivity;
 using Ryujinx.Ava.Common.Locale;
 using Ryujinx.Input;
 using System;
diff --git a/src/Ryujinx.Ava/Modules/Updater/Updater.cs b/src/Ryujinx.Ava/Modules/Updater/Updater.cs
index 5fa5241d..af7608d3 100644
--- a/src/Ryujinx.Ava/Modules/Updater/Updater.cs
+++ b/src/Ryujinx.Ava/Modules/Updater/Updater.cs
@@ -82,12 +82,9 @@ namespace Ryujinx.Modules
             {
                 Logger.Error?.Print(LogClass.Application, "Failed to convert the current Ryujinx version!");
 
-                Dispatcher.UIThread.Post(async () =>
-                {
-                    await ContentDialogHelper.CreateWarningDialog(
-                        LocaleManager.Instance[LocaleKeys.DialogUpdaterConvertFailedMessage],
-                        LocaleManager.Instance[LocaleKeys.DialogUpdaterCancelUpdateMessage]);
-                });
+                await ContentDialogHelper.CreateWarningDialog(
+                    LocaleManager.Instance[LocaleKeys.DialogUpdaterConvertFailedMessage],
+                    LocaleManager.Instance[LocaleKeys.DialogUpdaterCancelUpdateMessage]);
 
                 _running = false;
 
@@ -114,10 +111,9 @@ namespace Ryujinx.Modules
                         {
                             if (showVersionUpToDate)
                             {
-                                Dispatcher.UIThread.Post(async () =>
-                                {
-                                    await ContentDialogHelper.CreateUpdaterInfoDialog(LocaleManager.Instance[LocaleKeys.DialogUpdaterAlreadyOnLatestVersionMessage], "");
-                                });
+                                await ContentDialogHelper.CreateUpdaterInfoDialog(
+                                    LocaleManager.Instance[LocaleKeys.DialogUpdaterAlreadyOnLatestVersionMessage],
+                                    "");
                             }
 
                             _running = false;
@@ -134,10 +130,9 @@ namespace Ryujinx.Modules
                 {
                     if (showVersionUpToDate)
                     {
-                        Dispatcher.UIThread.Post(async () =>
-                        {
-                            await ContentDialogHelper.CreateUpdaterInfoDialog(LocaleManager.Instance[LocaleKeys.DialogUpdaterAlreadyOnLatestVersionMessage], "");
-                        });
+                        await ContentDialogHelper.CreateUpdaterInfoDialog(
+                            LocaleManager.Instance[LocaleKeys.DialogUpdaterAlreadyOnLatestVersionMessage],
+                            "");
                     }
 
                     _running = false;
@@ -149,10 +144,8 @@ namespace Ryujinx.Modules
             {
                 Logger.Error?.Print(LogClass.Application, exception.Message);
 
-                Dispatcher.UIThread.Post(async () =>
-                {
-                    await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance[LocaleKeys.DialogUpdaterFailedToGetVersionMessage]);
-                });
+                await ContentDialogHelper.CreateErrorDialog(
+                    LocaleManager.Instance[LocaleKeys.DialogUpdaterFailedToGetVersionMessage]);
 
                 _running = false;
 
@@ -167,12 +160,9 @@ namespace Ryujinx.Modules
             {
                 Logger.Error?.Print(LogClass.Application, "Failed to convert the received Ryujinx version from Github!");
 
-                Dispatcher.UIThread.Post(async () =>
-                {
-                    await ContentDialogHelper.CreateWarningDialog(
-                        LocaleManager.Instance[LocaleKeys.DialogUpdaterConvertFailedGithubMessage],
-                        LocaleManager.Instance[LocaleKeys.DialogUpdaterCancelUpdateMessage]);
-                });
+                await ContentDialogHelper.CreateWarningDialog(
+                    LocaleManager.Instance[LocaleKeys.DialogUpdaterConvertFailedGithubMessage],
+                    LocaleManager.Instance[LocaleKeys.DialogUpdaterCancelUpdateMessage]);
 
                 _running = false;
 
@@ -183,10 +173,9 @@ namespace Ryujinx.Modules
             {
                 if (showVersionUpToDate)
                 {
-                    Dispatcher.UIThread.Post(async () =>
-                    {
-                        await ContentDialogHelper.CreateUpdaterInfoDialog(LocaleManager.Instance[LocaleKeys.DialogUpdaterAlreadyOnLatestVersionMessage], "");
-                    });
+                    await ContentDialogHelper.CreateUpdaterInfoDialog(
+                        LocaleManager.Instance[LocaleKeys.DialogUpdaterAlreadyOnLatestVersionMessage],
+                        "");
                 }
 
                 _running = false;
@@ -212,7 +201,7 @@ namespace Ryujinx.Modules
                 _buildSize = -1;
             }
 
-            Dispatcher.UIThread.Post(async () =>
+            await Dispatcher.UIThread.InvokeAsync(async () =>
             {
                 // Show a message asking the user if they want to update
                 var shouldUpdate = await ContentDialogHelper.CreateChoiceDialog(
@@ -222,7 +211,7 @@ namespace Ryujinx.Modules
 
                 if (shouldUpdate)
                 {
-                    UpdateRyujinx(mainWindow, _buildUrl);
+                    await UpdateRyujinx(mainWindow, _buildUrl);
                 }
                 else
                 {
@@ -241,7 +230,7 @@ namespace Ryujinx.Modules
             return result;
         }
 
-        private static async void UpdateRyujinx(Window parent, string downloadUrl)
+        private static async Task UpdateRyujinx(Window parent, string downloadUrl)
         {
             _updateSuccessful = false;
 
@@ -579,27 +568,24 @@ namespace Ryujinx.Modules
             }
         }
 
-        private static async void InstallUpdate(TaskDialog taskDialog, string updateFile)
+        private static void InstallUpdate(TaskDialog taskDialog, string updateFile)
         {
             // Extract Update
             taskDialog.SubHeader = LocaleManager.Instance[LocaleKeys.UpdaterExtracting];
             taskDialog.SetProgressBarState(0, TaskDialogProgressState.Normal);
 
-            await Task.Run(() =>
+            if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS())
             {
-                if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS())
-                {
-                    ExtractTarGzipFile(taskDialog, updateFile, _updateDir);
-                }
-                else if (OperatingSystem.IsWindows())
-                {
-                    ExtractZipFile(taskDialog, updateFile, _updateDir);
-                }
-                else
-                {
-                    throw new NotSupportedException();
-                }
-            });
+                ExtractTarGzipFile(taskDialog, updateFile, _updateDir);
+            }
+            else if (OperatingSystem.IsWindows())
+            {
+                ExtractZipFile(taskDialog, updateFile, _updateDir);
+            }
+            else
+            {
+                throw new NotSupportedException();
+            }
 
             // Delete downloaded zip
             File.Delete(updateFile);
@@ -613,36 +599,33 @@ namespace Ryujinx.Modules
             if (!OperatingSystem.IsMacOS())
             {
                 // Replace old files
-                await Task.Run(() =>
+                double count = 0;
+                foreach (string file in allFiles)
                 {
-                    double count = 0;
-                    foreach (string file in allFiles)
+                    count++;
+                    try
                     {
-                        count++;
-                        try
-                        {
-                            File.Move(file, file + ".ryuold");
+                        File.Move(file, file + ".ryuold");
 
-                            Dispatcher.UIThread.Post(() =>
-                            {
-                                taskDialog.SetProgressBarState(GetPercentage(count, allFiles.Count), TaskDialogProgressState.Normal);
-                            });
-                        }
-                        catch
+                        Dispatcher.UIThread.InvokeAsync(() =>
                         {
-                            Logger.Warning?.Print(LogClass.Application, LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.UpdaterRenameFailed, file));
-                        }
+                            taskDialog.SetProgressBarState(GetPercentage(count, allFiles.Count), TaskDialogProgressState.Normal);
+                        });
                     }
-
-                    Dispatcher.UIThread.Post(() =>
+                    catch
                     {
-                        taskDialog.SubHeader = LocaleManager.Instance[LocaleKeys.UpdaterAddingFiles];
-                        taskDialog.SetProgressBarState(0, TaskDialogProgressState.Normal);
-                    });
+                        Logger.Warning?.Print(LogClass.Application, LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.UpdaterRenameFailed, file));
+                    }
+                }
 
-                    MoveAllFilesOver(_updatePublishDir, _homeDir, taskDialog);
+                Dispatcher.UIThread.InvokeAsync(() =>
+                {
+                    taskDialog.SubHeader = LocaleManager.Instance[LocaleKeys.UpdaterAddingFiles];
+                    taskDialog.SetProgressBarState(0, TaskDialogProgressState.Normal);
                 });
 
+                MoveAllFilesOver(_updatePublishDir, _homeDir, taskDialog);
+
                 Directory.Delete(_updateDir, true);
             }
 
@@ -658,12 +641,11 @@ namespace Ryujinx.Modules
             {
                 if (showWarnings)
                 {
-                    Dispatcher.UIThread.Post(async () =>
-                    {
-                        await ContentDialogHelper.CreateWarningDialog(
+                    Dispatcher.UIThread.InvokeAsync(() =>
+                        ContentDialogHelper.CreateWarningDialog(
                             LocaleManager.Instance[LocaleKeys.DialogUpdaterArchNotSupportedMessage],
-                            LocaleManager.Instance[LocaleKeys.DialogUpdaterArchNotSupportedSubMessage]);
-                    });
+                            LocaleManager.Instance[LocaleKeys.DialogUpdaterArchNotSupportedSubMessage])
+                    );
                 }
 
                 return false;
@@ -673,12 +655,11 @@ namespace Ryujinx.Modules
             {
                 if (showWarnings)
                 {
-                    Dispatcher.UIThread.Post(async () =>
-                    {
-                        await ContentDialogHelper.CreateWarningDialog(
+                    Dispatcher.UIThread.InvokeAsync(() =>
+                        ContentDialogHelper.CreateWarningDialog(
                             LocaleManager.Instance[LocaleKeys.DialogUpdaterNoInternetMessage],
-                            LocaleManager.Instance[LocaleKeys.DialogUpdaterNoInternetSubMessage]);
-                    });
+                            LocaleManager.Instance[LocaleKeys.DialogUpdaterNoInternetSubMessage])
+                    );
                 }
 
                 return false;
@@ -688,12 +669,11 @@ namespace Ryujinx.Modules
             {
                 if (showWarnings)
                 {
-                    Dispatcher.UIThread.Post(async () =>
-                    {
-                        await ContentDialogHelper.CreateWarningDialog(
+                    Dispatcher.UIThread.InvokeAsync(() =>
+                        ContentDialogHelper.CreateWarningDialog(
                             LocaleManager.Instance[LocaleKeys.DialogUpdaterDirtyBuildMessage],
-                            LocaleManager.Instance[LocaleKeys.DialogUpdaterDirtyBuildSubMessage]);
-                    });
+                            LocaleManager.Instance[LocaleKeys.DialogUpdaterDirtyBuildSubMessage])
+                    );
                 }
 
                 return false;
@@ -705,21 +685,19 @@ namespace Ryujinx.Modules
             {
                 if (ReleaseInformation.IsFlatHubBuild())
                 {
-                    Dispatcher.UIThread.Post(async () =>
-                    {
-                        await ContentDialogHelper.CreateWarningDialog(
+                    Dispatcher.UIThread.InvokeAsync(() =>
+                        ContentDialogHelper.CreateWarningDialog(
                             LocaleManager.Instance[LocaleKeys.UpdaterDisabledWarningTitle],
-                            LocaleManager.Instance[LocaleKeys.DialogUpdaterFlatpakNotSupportedMessage]);
-                    });
+                            LocaleManager.Instance[LocaleKeys.DialogUpdaterFlatpakNotSupportedMessage])
+                    );
                 }
                 else
                 {
-                    Dispatcher.UIThread.Post(async () =>
-                    {
-                        await ContentDialogHelper.CreateWarningDialog(
+                    Dispatcher.UIThread.InvokeAsync(() =>
+                        ContentDialogHelper.CreateWarningDialog(
                             LocaleManager.Instance[LocaleKeys.UpdaterDisabledWarningTitle],
-                            LocaleManager.Instance[LocaleKeys.DialogUpdaterDirtyBuildSubMessage]);
-                    });
+                            LocaleManager.Instance[LocaleKeys.DialogUpdaterDirtyBuildSubMessage])
+                    );
                 }
             }
 
diff --git a/src/Ryujinx.Ava/UI/Applet/AvaHostUiHandler.cs b/src/Ryujinx.Ava/UI/Applet/AvaHostUiHandler.cs
index a2a94429..9fc7c6b6 100644
--- a/src/Ryujinx.Ava/UI/Applet/AvaHostUiHandler.cs
+++ b/src/Ryujinx.Ava/UI/Applet/AvaHostUiHandler.cs
@@ -106,7 +106,7 @@ namespace Ryujinx.Ava.UI.Applet
             bool error = false;
             string inputText = args.InitialText ?? "";
 
-            Dispatcher.UIThread.Post(async () =>
+            Dispatcher.UIThread.InvokeAsync(async () =>
             {
                 try
                 {
@@ -149,7 +149,7 @@ namespace Ryujinx.Ava.UI.Applet
 
             bool showDetails = false;
 
-            Dispatcher.UIThread.Post(async () =>
+            Dispatcher.UIThread.InvokeAsync(async () =>
             {
                 try
                 {
diff --git a/src/Ryujinx.Ava/UI/Controls/ApplicationContextMenu.axaml.cs b/src/Ryujinx.Ava/UI/Controls/ApplicationContextMenu.axaml.cs
index f54e9df8..d75572e6 100644
--- a/src/Ryujinx.Ava/UI/Controls/ApplicationContextMenu.axaml.cs
+++ b/src/Ryujinx.Ava/UI/Controls/ApplicationContextMenu.axaml.cs
@@ -54,7 +54,7 @@ namespace Ryujinx.Ava.UI.Controls
         {
             if (sender is MenuItem { DataContext: MainWindowViewModel viewModel })
             {
-                OpenSaveDirectory(viewModel, SaveDataType.Account, userId: new UserId((ulong)viewModel.AccountManager.LastOpenedUser.UserId.High, (ulong)viewModel.AccountManager.LastOpenedUser.UserId.Low));
+                OpenSaveDirectory(viewModel, SaveDataType.Account, new UserId((ulong)viewModel.AccountManager.LastOpenedUser.UserId.High, (ulong)viewModel.AccountManager.LastOpenedUser.UserId.Low));
             }
         }
 
@@ -62,14 +62,14 @@ namespace Ryujinx.Ava.UI.Controls
         {
             var viewModel = (sender as MenuItem)?.DataContext as MainWindowViewModel;
 
-            OpenSaveDirectory(viewModel, SaveDataType.Device, userId: default);
+            OpenSaveDirectory(viewModel, SaveDataType.Device, default);
         }
 
         public void OpenBcatSaveDirectory_Click(object sender, RoutedEventArgs args)
         {
             var viewModel = (sender as MenuItem)?.DataContext as MainWindowViewModel;
 
-            OpenSaveDirectory(viewModel, SaveDataType.Bcat, userId: default);
+            OpenSaveDirectory(viewModel, SaveDataType.Bcat, default);
         }
 
         private static void OpenSaveDirectory(MainWindowViewModel viewModel, SaveDataType saveDataType, UserId userId)
@@ -158,11 +158,12 @@ namespace Ryujinx.Ava.UI.Controls
 
             if (viewModel?.SelectedApplication != null)
             {
-                UserResult result = await ContentDialogHelper.CreateConfirmationDialog(LocaleManager.Instance[LocaleKeys.DialogWarning],
-                                                                                       LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogPPTCDeletionMessage, viewModel.SelectedApplication.TitleName),
-                                                                                       LocaleManager.Instance[LocaleKeys.InputDialogYes],
-                                                                                       LocaleManager.Instance[LocaleKeys.InputDialogNo],
-                                                                                       LocaleManager.Instance[LocaleKeys.RyujinxConfirm]);
+                UserResult result = await ContentDialogHelper.CreateConfirmationDialog(
+                    LocaleManager.Instance[LocaleKeys.DialogWarning],
+                    LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogPPTCDeletionMessage, viewModel.SelectedApplication.TitleName),
+                    LocaleManager.Instance[LocaleKeys.InputDialogYes],
+                    LocaleManager.Instance[LocaleKeys.InputDialogNo],
+                    LocaleManager.Instance[LocaleKeys.RyujinxConfirm]);
 
                 if (result == UserResult.Yes)
                 {
@@ -205,11 +206,12 @@ namespace Ryujinx.Ava.UI.Controls
 
             if (viewModel?.SelectedApplication != null)
             {
-                UserResult result = await ContentDialogHelper.CreateConfirmationDialog(LocaleManager.Instance[LocaleKeys.DialogWarning],
-                                                                                       LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogShaderDeletionMessage, viewModel.SelectedApplication.TitleName),
-                                                                                       LocaleManager.Instance[LocaleKeys.InputDialogYes],
-                                                                                       LocaleManager.Instance[LocaleKeys.InputDialogNo],
-                                                                                       LocaleManager.Instance[LocaleKeys.RyujinxConfirm]);
+                UserResult result = await ContentDialogHelper.CreateConfirmationDialog(
+                    LocaleManager.Instance[LocaleKeys.DialogWarning],
+                    LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogShaderDeletionMessage, viewModel.SelectedApplication.TitleName),
+                    LocaleManager.Instance[LocaleKeys.InputDialogYes],
+                    LocaleManager.Instance[LocaleKeys.InputDialogNo],
+                    LocaleManager.Instance[LocaleKeys.RyujinxConfirm]);
 
                 if (result == UserResult.Yes)
                 {
@@ -335,13 +337,13 @@ namespace Ryujinx.Ava.UI.Controls
             }
         }
 
-        public void RunApplication_Click(object sender, RoutedEventArgs args)
+        public async void RunApplication_Click(object sender, RoutedEventArgs args)
         {
             var viewModel = (sender as MenuItem)?.DataContext as MainWindowViewModel;
 
             if (viewModel?.SelectedApplication != null)
             {
-                viewModel.LoadApplication(viewModel.SelectedApplication.Path);
+                await viewModel.LoadApplication(viewModel.SelectedApplication.Path);
             }
         }
     }
diff --git a/src/Ryujinx.Ava/UI/ViewModels/DownloadableContentManagerViewModel.cs b/src/Ryujinx.Ava/UI/ViewModels/DownloadableContentManagerViewModel.cs
index 74b73751..b88bd3d9 100644
--- a/src/Ryujinx.Ava/UI/ViewModels/DownloadableContentManagerViewModel.cs
+++ b/src/Ryujinx.Ava/UI/ViewModels/DownloadableContentManagerViewModel.cs
@@ -212,9 +212,9 @@ namespace Ryujinx.Ava.UI.ViewModels
                     {
                         Patterns = new[] { "*.nsp" },
                         AppleUniformTypeIdentifiers = new[] { "com.ryujinx.nsp" },
-                        MimeTypes = new[] { "application/x-nx-nsp" }
-                    }
-                }
+                        MimeTypes = new[] { "application/x-nx-nsp" },
+                    },
+                },
             });
 
             foreach (var file in result)
diff --git a/src/Ryujinx.Ava/UI/ViewModels/MainWindowViewModel.cs b/src/Ryujinx.Ava/UI/ViewModels/MainWindowViewModel.cs
index aa6e0326..bd852710 100644
--- a/src/Ryujinx.Ava/UI/ViewModels/MainWindowViewModel.cs
+++ b/src/Ryujinx.Ava/UI/ViewModels/MainWindowViewModel.cs
@@ -26,6 +26,7 @@ using Ryujinx.HLE.FileSystem;
 using Ryujinx.HLE.HOS;
 using Ryujinx.HLE.HOS.Services.Account.Acc;
 using Ryujinx.HLE.Ui;
+using Ryujinx.Input.HLE;
 using Ryujinx.Modules;
 using Ryujinx.Ui.App.Common;
 using Ryujinx.Ui.Common;
@@ -39,7 +40,6 @@ using System.IO;
 using System.Threading;
 using System.Threading.Tasks;
 using Image = SixLabors.ImageSharp.Image;
-using InputManager = Ryujinx.Input.HLE.InputManager;
 using Key = Ryujinx.Input.Key;
 using MissingKeyException = LibHac.Common.Keys.MissingKeyException;
 using ShaderCacheLoadingState = Ryujinx.Graphics.Gpu.Shader.ShaderCacheState;
@@ -1068,9 +1068,7 @@ namespace Ryujinx.Ava.UI.ViewModels
                 {
                     Logger.Error?.Print(LogClass.Application, ex.ToString());
 
-                    static async void Action() => await UserErrorDialog.ShowUserErrorDialog(UserError.NoKeys);
-
-                    Dispatcher.UIThread.Post(Action);
+                    await UserErrorDialog.ShowUserErrorDialog(UserError.NoKeys);
                 }
             }
             catch (Exception ex)
@@ -1163,16 +1161,13 @@ namespace Ryujinx.Ava.UI.ViewModels
             AppHost?.DisposeContext();
         }
 
-        private void HandleRelaunch()
+        private async Task HandleRelaunch()
         {
             if (UserChannelPersistence.PreviousIndex != -1 && UserChannelPersistence.ShouldRestart)
             {
                 UserChannelPersistence.ShouldRestart = false;
 
-                Dispatcher.UIThread.Post(() =>
-                {
-                    LoadApplication(_currentEmulatedGamePath);
-                });
+                await LoadApplication(_currentEmulatedGamePath);
             }
             else
             {
@@ -1191,7 +1186,7 @@ namespace Ryujinx.Ava.UI.ViewModels
                     Application.Current.Styles.TryGetResource(args.VSyncEnabled
                         ? "VsyncEnabled"
                         : "VsyncDisabled",
-                        Avalonia.Application.Current.ActualThemeVariant,
+                        Application.Current.ActualThemeVariant,
                         out object color);
 
                     if (color is not null)
@@ -1283,7 +1278,7 @@ namespace Ryujinx.Ava.UI.ViewModels
             Glyph = Glyph.Grid;
         }
 
-        public async void InstallFirmwareFromFile()
+        public async Task InstallFirmwareFromFile()
         {
             var result = await StorageProvider.OpenFilePickerAsync(new FilePickerOpenOptions
             {
@@ -1294,21 +1289,21 @@ namespace Ryujinx.Ava.UI.ViewModels
                     {
                         Patterns = new[] { "*.xci", "*.zip" },
                         AppleUniformTypeIdentifiers = new[] { "com.ryujinx.xci", "public.zip-archive" },
-                        MimeTypes = new[] { "application/x-nx-xci", "application/zip" }
+                        MimeTypes = new[] { "application/x-nx-xci", "application/zip" },
                     },
                     new("XCI")
                     {
                         Patterns = new[] { "*.xci" },
                         AppleUniformTypeIdentifiers = new[] { "com.ryujinx.xci" },
-                        MimeTypes = new[] { "application/x-nx-xci" }
+                        MimeTypes = new[] { "application/x-nx-xci" },
                     },
                     new("ZIP")
                     {
                         Patterns = new[] { "*.zip" },
                         AppleUniformTypeIdentifiers = new[] { "public.zip-archive" },
-                        MimeTypes = new[] { "application/zip" }
+                        MimeTypes = new[] { "application/zip" },
                     },
-                }
+                },
             });
 
             if (result.Count > 0)
@@ -1317,11 +1312,11 @@ namespace Ryujinx.Ava.UI.ViewModels
             }
         }
 
-        public async void InstallFirmwareFromFolder()
+        public async Task InstallFirmwareFromFolder()
         {
             var result = await StorageProvider.OpenFolderPickerAsync(new FolderPickerOpenOptions
             {
-                AllowMultiple = false
+                AllowMultiple = false,
             });
 
             if (result.Count > 0)
@@ -1352,7 +1347,7 @@ namespace Ryujinx.Ava.UI.ViewModels
             }
         }
 
-        public async void ExitCurrentState()
+        public async Task ExitCurrentState()
         {
             if (WindowState == WindowState.FullScreen)
             {
@@ -1377,7 +1372,7 @@ namespace Ryujinx.Ava.UI.ViewModels
             }
         }
 
-        public async void ManageProfiles()
+        public async Task ManageProfiles()
         {
             await NavigationDialogHost.Show(AccountManager, ContentManager, VirtualFileSystem, LibHacHorizonManager.RyujinxClient);
         }
@@ -1387,7 +1382,7 @@ namespace Ryujinx.Ava.UI.ViewModels
             AppHost.Device.System.SimulateWakeUpMessage();
         }
 
-        public async void OpenFile()
+        public async Task OpenFile()
         {
             var result = await StorageProvider.OpenFilePickerAsync(new FilePickerOpenOptions
             {
@@ -1404,7 +1399,7 @@ namespace Ryujinx.Ava.UI.ViewModels
                             "com.ryujinx.xci",
                             "com.ryujinx.nca",
                             "com.ryujinx.nro",
-                            "com.ryujinx.nso"
+                            "com.ryujinx.nso",
                         },
                         MimeTypes = new[]
                         {
@@ -1412,63 +1407,63 @@ namespace Ryujinx.Ava.UI.ViewModels
                             "application/x-nx-xci",
                             "application/x-nx-nca",
                             "application/x-nx-nro",
-                            "application/x-nx-nso"
-                        }
+                            "application/x-nx-nso",
+                        },
                     },
                     new("NSP")
                     {
                         Patterns = new[] { "*.nsp" },
                         AppleUniformTypeIdentifiers = new[] { "com.ryujinx.nsp" },
-                        MimeTypes = new[] { "application/x-nx-nsp" }
+                        MimeTypes = new[] { "application/x-nx-nsp" },
                     },
                     new("XCI")
                     {
                         Patterns = new[] { "*.xci" },
                         AppleUniformTypeIdentifiers = new[] { "com.ryujinx.xci" },
-                        MimeTypes = new[] { "application/x-nx-xci" }
+                        MimeTypes = new[] { "application/x-nx-xci" },
                     },
                     new("NCA")
                     {
                         Patterns = new[] { "*.nca" },
                         AppleUniformTypeIdentifiers = new[] { "com.ryujinx.nca" },
-                        MimeTypes = new[] { "application/x-nx-nca" }
+                        MimeTypes = new[] { "application/x-nx-nca" },
                     },
                     new("NRO")
                     {
                         Patterns = new[] { "*.nro" },
                         AppleUniformTypeIdentifiers = new[] { "com.ryujinx.nro" },
-                        MimeTypes = new[] { "application/x-nx-nro" }
+                        MimeTypes = new[] { "application/x-nx-nro" },
                     },
                     new("NSO")
                     {
                         Patterns = new[] { "*.nso" },
                         AppleUniformTypeIdentifiers = new[] { "com.ryujinx.nso" },
-                        MimeTypes = new[] { "application/x-nx-nso" }
+                        MimeTypes = new[] { "application/x-nx-nso" },
                     },
-                }
+                },
             });
 
             if (result.Count > 0)
             {
-                LoadApplication(result[0].Path.LocalPath);
+                await LoadApplication(result[0].Path.LocalPath);
             }
         }
 
-        public async void OpenFolder()
+        public async Task OpenFolder()
         {
             var result = await StorageProvider.OpenFolderPickerAsync(new FolderPickerOpenOptions
             {
                 Title = LocaleManager.Instance[LocaleKeys.OpenFolderDialogTitle],
-                AllowMultiple = false
+                AllowMultiple = false,
             });
 
             if (result.Count > 0)
             {
-                LoadApplication(result[0].Path.LocalPath);
+                await LoadApplication(result[0].Path.LocalPath);
             }
         }
 
-        public async void LoadApplication(string path, bool startFullscreen = false, string titleName = "")
+        public async Task LoadApplication(string path, bool startFullscreen = false, string titleName = "")
         {
             if (AppHost != null)
             {
@@ -1505,35 +1500,30 @@ namespace Ryujinx.Ava.UI.ViewModels
                 this,
                 TopLevel);
 
-            async void Action()
+            if (!await AppHost.LoadGuestApplication())
             {
-                if (!await AppHost.LoadGuestApplication())
-                {
-                    AppHost.DisposeContext();
-                    AppHost = null;
-
-                    return;
-                }
+                AppHost.DisposeContext();
+                AppHost = null;
 
-                CanUpdate = false;
+                return;
+            }
 
-                LoadHeading = TitleName = titleName;
+            CanUpdate = false;
 
-                if (string.IsNullOrWhiteSpace(titleName))
-                {
-                    LoadHeading = LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.LoadingHeading, AppHost.Device.Processes.ActiveApplication.Name);
-                    TitleName = AppHost.Device.Processes.ActiveApplication.Name;
-                }
+            LoadHeading = TitleName = titleName;
 
-                SwitchToRenderer(startFullscreen);
+            if (string.IsNullOrWhiteSpace(titleName))
+            {
+                LoadHeading = LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.LoadingHeading, AppHost.Device.Processes.ActiveApplication.Name);
+                TitleName = AppHost.Device.Processes.ActiveApplication.Name;
+            }
 
-                _currentEmulatedGamePath = path;
+            SwitchToRenderer(startFullscreen);
 
-                Thread gameThread = new(InitializeGame) { Name = "GUI.WindowThread" };
-                gameThread.Start();
-            }
+            _currentEmulatedGamePath = path;
 
-            Dispatcher.UIThread.Post(Action);
+            Thread gameThread = new(InitializeGame) { Name = "GUI.WindowThread" };
+            gameThread.Start();
         }
 
         public void SwitchToRenderer(bool startFullscreen)
@@ -1596,7 +1586,7 @@ namespace Ryujinx.Ava.UI.ViewModels
 
             IsGameRunning = false;
 
-            Dispatcher.UIThread.InvokeAsync(() =>
+            Dispatcher.UIThread.InvokeAsync(async () =>
             {
                 ShowMenuAndStatusBar = true;
                 ShowContent = true;
@@ -1609,7 +1599,7 @@ namespace Ryujinx.Ava.UI.ViewModels
 
                 AppHost = null;
 
-                HandleRelaunch();
+                await HandleRelaunch();
             });
 
             RendererHostControl.WindowCreated -= RendererHost_Created;
diff --git a/src/Ryujinx.Ava/UI/ViewModels/SettingsViewModel.cs b/src/Ryujinx.Ava/UI/ViewModels/SettingsViewModel.cs
index dd5b05a5..9c61becd 100644
--- a/src/Ryujinx.Ava/UI/ViewModels/SettingsViewModel.cs
+++ b/src/Ryujinx.Ava/UI/ViewModels/SettingsViewModel.cs
@@ -78,14 +78,13 @@ namespace Ryujinx.Ava.UI.ViewModels
 
                 if (_graphicsBackendMultithreadingIndex != (int)ConfigurationState.Instance.Graphics.BackendThreading.Value)
                 {
-                    Dispatcher.UIThread.Post(async () =>
-                    {
-                        await ContentDialogHelper.CreateInfoDialog(LocaleManager.Instance[LocaleKeys.DialogSettingsBackendThreadingWarningMessage],
+                    Dispatcher.UIThread.InvokeAsync(() =>
+                         ContentDialogHelper.CreateInfoDialog(LocaleManager.Instance[LocaleKeys.DialogSettingsBackendThreadingWarningMessage],
                             "",
                             "",
                             LocaleManager.Instance[LocaleKeys.InputDialogOk],
-                            LocaleManager.Instance[LocaleKeys.DialogSettingsBackendThreadingWarningTitle]);
-                    });
+                            LocaleManager.Instance[LocaleKeys.DialogSettingsBackendThreadingWarningTitle])
+                    );
                 }
 
                 OnPropertyChanged();
diff --git a/src/Ryujinx.Ava/UI/ViewModels/TitleUpdateViewModel.cs b/src/Ryujinx.Ava/UI/ViewModels/TitleUpdateViewModel.cs
index e3bca205..dd0b92a5 100644
--- a/src/Ryujinx.Ava/UI/ViewModels/TitleUpdateViewModel.cs
+++ b/src/Ryujinx.Ava/UI/ViewModels/TitleUpdateViewModel.cs
@@ -22,6 +22,7 @@ using System;
 using System.Collections.Generic;
 using System.IO;
 using System.Linq;
+using System.Threading.Tasks;
 using Path = System.IO.Path;
 using SpanHelpers = LibHac.Common.SpanHelpers;
 
@@ -184,18 +185,12 @@ namespace Ryujinx.Ava.UI.ViewModels
                     }
                     else
                     {
-                        Dispatcher.UIThread.Post(async () =>
-                        {
-                            await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance[LocaleKeys.DialogUpdateAddUpdateErrorMessage]);
-                        });
+                        Dispatcher.UIThread.InvokeAsync(() => ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance[LocaleKeys.DialogUpdateAddUpdateErrorMessage]));
                     }
                 }
                 catch (Exception ex)
                 {
-                    Dispatcher.UIThread.Post(async () =>
-                    {
-                        await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogLoadNcaErrorMessage, ex.Message, path));
-                    });
+                    Dispatcher.UIThread.InvokeAsync(() => ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogLoadNcaErrorMessage, ex.Message, path)));
                 }
             }
         }
@@ -207,7 +202,7 @@ namespace Ryujinx.Ava.UI.ViewModels
             SortUpdates();
         }
 
-        public async void Add()
+        public async Task Add()
         {
             var result = await StorageProvider.OpenFilePickerAsync(new FilePickerOpenOptions
             {
@@ -218,9 +213,9 @@ namespace Ryujinx.Ava.UI.ViewModels
                     {
                         Patterns = new[] { "*.nsp" },
                         AppleUniformTypeIdentifiers = new[] { "com.ryujinx.nsp" },
-                        MimeTypes = new[] { "application/x-nx-nsp" }
-                    }
-                }
+                        MimeTypes = new[] { "application/x-nx-nsp" },
+                    },
+                },
             });
 
             foreach (var file in result)
diff --git a/src/Ryujinx.Ava/UI/Views/Main/MainMenuBarView.axaml.cs b/src/Ryujinx.Ava/UI/Views/Main/MainMenuBarView.axaml.cs
index af8c4dab..4f2d262d 100644
--- a/src/Ryujinx.Ava/UI/Views/Main/MainMenuBarView.axaml.cs
+++ b/src/Ryujinx.Ava/UI/Views/Main/MainMenuBarView.axaml.cs
@@ -17,7 +17,6 @@ using System;
 using System.Collections.Generic;
 using System.IO;
 using System.Linq;
-using System.Threading.Tasks;
 
 namespace Ryujinx.Ava.UI.Views.Main
 {
@@ -107,20 +106,14 @@ namespace Ryujinx.Ava.UI.Views.Main
             await Window.ViewModel.AppHost?.ShowExitPrompt();
         }
 
-        private async void PauseEmulation_Click(object sender, RoutedEventArgs e)
+        private void PauseEmulation_Click(object sender, RoutedEventArgs e)
         {
-            await Task.Run(() =>
-            {
-                Window.ViewModel.AppHost?.Pause();
-            });
+            Window.ViewModel.AppHost?.Pause();
         }
 
-        private async void ResumeEmulation_Click(object sender, RoutedEventArgs e)
+        private void ResumeEmulation_Click(object sender, RoutedEventArgs e)
         {
-            await Task.Run(() =>
-            {
-                Window.ViewModel.AppHost?.Resume();
-            });
+            Window.ViewModel.AppHost?.Resume();
         }
 
         public async void OpenSettings(object sender, RoutedEventArgs e)
@@ -132,13 +125,13 @@ namespace Ryujinx.Ava.UI.Views.Main
             ViewModel.LoadConfigurableHotKeys();
         }
 
-        public void OpenMiiApplet(object sender, RoutedEventArgs e)
+        public async void OpenMiiApplet(object sender, RoutedEventArgs e)
         {
             string contentPath = ViewModel.ContentManager.GetInstalledContentPath(0x0100000000001009, StorageId.BuiltInSystem, NcaContentType.Program);
 
             if (!string.IsNullOrEmpty(contentPath))
             {
-                ViewModel.LoadApplication(contentPath, false, "Mii Applet");
+                await ViewModel.LoadApplication(contentPath, false, "Mii Applet");
             }
         }
 
@@ -196,8 +189,7 @@ namespace Ryujinx.Ava.UI.Views.Main
         {
             if (FileAssociationHelper.Install())
             {
-                await ContentDialogHelper.CreateInfoDialog(LocaleManager.Instance[LocaleKeys.DialogInstallFileTypesSuccessMessage],
-                    string.Empty, LocaleManager.Instance[LocaleKeys.InputDialogOk], string.Empty, string.Empty);
+                await ContentDialogHelper.CreateInfoDialog(LocaleManager.Instance[LocaleKeys.DialogInstallFileTypesSuccessMessage], string.Empty, LocaleManager.Instance[LocaleKeys.InputDialogOk], string.Empty, string.Empty);
             }
             else
             {
@@ -209,8 +201,7 @@ namespace Ryujinx.Ava.UI.Views.Main
         {
             if (FileAssociationHelper.Uninstall())
             {
-                await ContentDialogHelper.CreateInfoDialog(LocaleManager.Instance[LocaleKeys.DialogUninstallFileTypesSuccessMessage],
-                    string.Empty, LocaleManager.Instance[LocaleKeys.InputDialogOk], string.Empty, string.Empty);
+                await ContentDialogHelper.CreateInfoDialog(LocaleManager.Instance[LocaleKeys.DialogUninstallFileTypesSuccessMessage], string.Empty, LocaleManager.Instance[LocaleKeys.InputDialogOk], string.Empty, string.Empty);
             }
             else
             {
diff --git a/src/Ryujinx.Ava/UI/Views/Settings/SettingsUIView.axaml.cs b/src/Ryujinx.Ava/UI/Views/Settings/SettingsUIView.axaml.cs
index a38a8865..6d9299dd 100644
--- a/src/Ryujinx.Ava/UI/Views/Settings/SettingsUIView.axaml.cs
+++ b/src/Ryujinx.Ava/UI/Views/Settings/SettingsUIView.axaml.cs
@@ -34,7 +34,7 @@ namespace Ryujinx.Ava.UI.Views.Settings
                 {
                     var result = await window.StorageProvider.OpenFolderPickerAsync(new FolderPickerOpenOptions
                     {
-                        AllowMultiple = false
+                        AllowMultiple = false,
                     });
 
                     if (result.Count > 0)
@@ -75,9 +75,9 @@ namespace Ryujinx.Ava.UI.Views.Settings
                     {
                         Patterns = new[] { "*.xaml" },
                         AppleUniformTypeIdentifiers = new[] { "com.ryujinx.xaml" },
-                        MimeTypes = new[] { "application/xaml+xml" }
-                    }
-                }
+                        MimeTypes = new[] { "application/xaml+xml" },
+                    },
+                },
             });
 
             if (result.Count > 0)
diff --git a/src/Ryujinx.Ava/UI/Views/User/UserProfileImageSelectorView.axaml.cs b/src/Ryujinx.Ava/UI/Views/User/UserProfileImageSelectorView.axaml.cs
index e9bf4408..fabfaa4e 100644
--- a/src/Ryujinx.Ava/UI/Views/User/UserProfileImageSelectorView.axaml.cs
+++ b/src/Ryujinx.Ava/UI/Views/User/UserProfileImageSelectorView.axaml.cs
@@ -75,9 +75,9 @@ namespace Ryujinx.Ava.UI.Views.User
                     {
                         Patterns = new[] { "*.jpg", "*.jpeg", "*.png", "*.bmp" },
                         AppleUniformTypeIdentifiers = new[] { "public.jpeg", "public.png", "com.microsoft.bmp" },
-                        MimeTypes = new[] { "image/jpeg", "image/png", "image/bmp" }
-                    }
-                }
+                        MimeTypes = new[] { "image/jpeg", "image/png", "image/bmp" },
+                    },
+                },
             });
 
             if (result.Count > 0)
diff --git a/src/Ryujinx.Ava/UI/Windows/MainWindow.axaml.cs b/src/Ryujinx.Ava/UI/Windows/MainWindow.axaml.cs
index b6e4be55..3596c9aa 100644
--- a/src/Ryujinx.Ava/UI/Windows/MainWindow.axaml.cs
+++ b/src/Ryujinx.Ava/UI/Windows/MainWindow.axaml.cs
@@ -25,6 +25,7 @@ using Ryujinx.Ui.Common.Helper;
 using System;
 using System.IO;
 using System.Runtime.Versioning;
+using System.Threading;
 using System.Threading.Tasks;
 
 namespace Ryujinx.Ava.UI.Windows
@@ -79,35 +80,11 @@ namespace Ryujinx.Ava.UI.Windows
 
             if (Program.PreviewerDetached)
             {
-                Initialize();
-
                 InputManager = new InputManager(new AvaloniaKeyboardDriver(this), new SDL2GamepadDriver());
 
-                ViewModel.Initialize(
-                    ContentManager,
-                    StorageProvider,
-                    ApplicationLibrary,
-                    VirtualFileSystem,
-                    AccountManager,
-                    InputManager,
-                    _userChannelPersistence,
-                    LibHacHorizonManager,
-                    UiHandler,
-                    ShowLoading,
-                    SwitchToGameControl,
-                    SetMainContent,
-                    this);
-
-                ViewModel.RefreshFirmwareStatus();
-
-                LoadGameList();
-
                 this.GetObservable(IsActiveProperty).Subscribe(IsActiveChanged);
                 this.ScalingChanged += OnScalingChanged;
             }
-
-            ApplicationLibrary.ApplicationCountUpdated += ApplicationLibrary_ApplicationCountUpdated;
-            ApplicationLibrary.ApplicationAdded += ApplicationLibrary_ApplicationAdded;
         }
 
         protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
@@ -122,38 +99,19 @@ namespace Ryujinx.Ava.UI.Windows
             ViewModel.IsActive = obj;
         }
 
-        public void LoadGameList()
-        {
-            if (_isLoading)
-            {
-                return;
-            }
-
-            _isLoading = true;
-
-            LoadApplications();
-
-            _isLoading = false;
-        }
-
         private void OnScalingChanged(object sender, EventArgs e)
         {
             Program.DesktopScaleFactor = this.RenderScaling;
         }
 
-        public void AddApplication(ApplicationData applicationData)
+        private void ApplicationLibrary_ApplicationAdded(object sender, ApplicationAddedEventArgs e)
         {
-            Dispatcher.UIThread.InvokeAsync(() =>
+            Dispatcher.UIThread.Post(() =>
             {
-                ViewModel.Applications.Add(applicationData);
+                ViewModel.Applications.Add(e.AppData);
             });
         }
 
-        private void ApplicationLibrary_ApplicationAdded(object sender, ApplicationAddedEventArgs e)
-        {
-            AddApplication(e.AppData);
-        }
-
         private void ApplicationLibrary_ApplicationCountUpdated(object sender, ApplicationCountUpdatedEventArgs e)
         {
             LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.StatusBarGamesLoaded, e.NumAppsLoaded, e.NumAppsFound);
@@ -183,7 +141,7 @@ namespace Ryujinx.Ava.UI.Windows
 
                 string path = new FileInfo(args.Application.Path).FullName;
 
-                ViewModel.LoadApplication(path);
+                ViewModel.LoadApplication(path).Wait();
             }
 
             args.Handled = true;
@@ -202,13 +160,10 @@ namespace Ryujinx.Ava.UI.Windows
             ViewModel.ShowContent = true;
             ViewModel.IsLoadingIndeterminate = false;
 
-            Dispatcher.UIThread.InvokeAsync(() =>
+            if (startFullscreen && ViewModel.WindowState != WindowState.FullScreen)
             {
-                if (startFullscreen && ViewModel.WindowState != WindowState.FullScreen)
-                {
-                    ViewModel.ToggleFullscreen();
-                }
-            });
+                ViewModel.ToggleFullscreen();
+            }
         }
 
         public void ShowLoading(bool startFullscreen = false)
@@ -217,13 +172,10 @@ namespace Ryujinx.Ava.UI.Windows
             ViewModel.ShowLoadProgress = true;
             ViewModel.IsLoadingIndeterminate = true;
 
-            Dispatcher.UIThread.InvokeAsync(() =>
+            if (startFullscreen && ViewModel.WindowState != WindowState.FullScreen)
             {
-                if (startFullscreen && ViewModel.WindowState != WindowState.FullScreen)
-                {
-                    ViewModel.ToggleFullscreen();
-                }
-            });
+                ViewModel.ToggleFullscreen();
+            }
         }
 
         private void Initialize()
@@ -255,7 +207,7 @@ namespace Ryujinx.Ava.UI.Windows
         }
 
         [SupportedOSPlatform("linux")]
-        private static async void ShowVmMaxMapCountWarning()
+        private static async Task ShowVmMaxMapCountWarning()
         {
             LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.LinuxVmMaxMapCountWarningTextSecondary,
                 LinuxHelper.VmMaxMapCount, LinuxHelper.RecommendedVmMaxMapCount);
@@ -267,7 +219,7 @@ namespace Ryujinx.Ava.UI.Windows
         }
 
         [SupportedOSPlatform("linux")]
-        private static async void ShowVmMaxMapCountDialog()
+        private static async Task ShowVmMaxMapCountDialog()
         {
             LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.LinuxVmMaxMapCountDialogTextPrimary,
                 LinuxHelper.RecommendedVmMaxMapCount);
@@ -317,8 +269,7 @@ namespace Ryujinx.Ava.UI.Windows
             {
                 ShowKeyErrorOnLoad = false;
 
-                Dispatcher.UIThread.Post(async () => await
-                    UserErrorDialog.ShowUserErrorDialog(UserError.NoKeys));
+                UserErrorDialog.ShowUserErrorDialog(UserError.NoKeys).Wait();
             }
 
             if (OperatingSystem.IsLinux() && LinuxHelper.VmMaxMapCount < LinuxHelper.RecommendedVmMaxMapCount)
@@ -327,11 +278,11 @@ namespace Ryujinx.Ava.UI.Windows
 
                 if (LinuxHelper.PkExecPath is not null)
                 {
-                    Dispatcher.UIThread.Post(ShowVmMaxMapCountDialog);
+                    ShowVmMaxMapCountDialog().Wait();
                 }
                 else
                 {
-                    Dispatcher.UIThread.Post(ShowVmMaxMapCountWarning);
+                    ShowVmMaxMapCountWarning().Wait();
                 }
             }
 
@@ -339,7 +290,7 @@ namespace Ryujinx.Ava.UI.Windows
             {
                 _deferLoad = false;
 
-                ViewModel.LoadApplication(_launchPath, _startFullscreen);
+                ViewModel.LoadApplication(_launchPath, _startFullscreen).Wait();
             }
 
             if (ConfigurationState.Instance.CheckUpdatesOnStart.Value && Updater.CanUpdate(false))
@@ -372,7 +323,7 @@ namespace Ryujinx.Ava.UI.Windows
             ViewModel.WindowHeight = ConfigurationState.Instance.Ui.WindowStartup.WindowSizeHeight * Program.WindowScaleFactor;
             ViewModel.WindowWidth = ConfigurationState.Instance.Ui.WindowStartup.WindowSizeWidth * Program.WindowScaleFactor;
 
-            ViewModel.WindowState = ConfigurationState.Instance.Ui.WindowStartup.WindowMaximized.Value is true ? WindowState.Maximized : WindowState.Normal;
+            ViewModel.WindowState = ConfigurationState.Instance.Ui.WindowStartup.WindowMaximized.Value ? WindowState.Maximized : WindowState.Normal;
 
             if (CheckScreenBounds(savedPoint))
             {
@@ -415,6 +366,30 @@ namespace Ryujinx.Ava.UI.Windows
         {
             base.OnOpened(e);
 
+            Initialize();
+
+            ViewModel.Initialize(
+                ContentManager,
+                StorageProvider,
+                ApplicationLibrary,
+                VirtualFileSystem,
+                AccountManager,
+                InputManager,
+                _userChannelPersistence,
+                LibHacHorizonManager,
+                UiHandler,
+                ShowLoading,
+                SwitchToGameControl,
+                SetMainContent,
+                this);
+
+            ApplicationLibrary.ApplicationCountUpdated += ApplicationLibrary_ApplicationCountUpdated;
+            ApplicationLibrary.ApplicationAdded += ApplicationLibrary_ApplicationAdded;
+
+            ViewModel.RefreshFirmwareStatus();
+
+            LoadApplications();
+
             CheckLaunchState();
         }
 
@@ -514,18 +489,15 @@ namespace Ryujinx.Ava.UI.Windows
             });
         }
 
-        public async void LoadApplications()
+        public void LoadApplications()
         {
-            await Dispatcher.UIThread.InvokeAsync(() =>
-            {
-                ViewModel.Applications.Clear();
+            ViewModel.Applications.Clear();
 
-                StatusBarView.LoadProgressBar.IsVisible = true;
-                ViewModel.StatusBarProgressMaximum = 0;
-                ViewModel.StatusBarProgressValue = 0;
+            StatusBarView.LoadProgressBar.IsVisible = true;
+            ViewModel.StatusBarProgressMaximum = 0;
+            ViewModel.StatusBarProgressValue = 0;
 
-                LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.StatusBarGamesLoaded, 0, 0);
-            });
+            LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.StatusBarGamesLoaded, 0, 0);
 
             ReloadGameList();
         }
@@ -558,9 +530,17 @@ namespace Ryujinx.Ava.UI.Windows
 
             _isLoading = true;
 
-            ApplicationLibrary.LoadApplications(ConfigurationState.Instance.Ui.GameDirs.Value, ConfigurationState.Instance.System.Language);
+            Thread applicationLibraryThread = new(() =>
+            {
+                ApplicationLibrary.LoadApplications(ConfigurationState.Instance.Ui.GameDirs, ConfigurationState.Instance.System.Language);
 
-            _isLoading = false;
+                _isLoading = false;
+            })
+            {
+                Name = "GUI.ApplicationLibraryThread",
+                IsBackground = true,
+            };
+            applicationLibraryThread.Start();
         }
     }
 }
diff --git a/src/Ryujinx.Ava/UI/Windows/StyleableWindow.cs b/src/Ryujinx.Ava/UI/Windows/StyleableWindow.cs
index 43e42804..3fedd5a2 100644
--- a/src/Ryujinx.Ava/UI/Windows/StyleableWindow.cs
+++ b/src/Ryujinx.Ava/UI/Windows/StyleableWindow.cs
@@ -3,7 +3,6 @@ using Avalonia.Controls.Primitives;
 using Avalonia.Media.Imaging;
 using Avalonia.Platform;
 using Ryujinx.Ui.Common.Configuration;
-using System;
 using System.IO;
 using System.Reflection;
 
@@ -25,11 +24,6 @@ namespace Ryujinx.Ava.UI.Windows
             IconImage = new Bitmap(stream);
         }
 
-        protected override void OnOpened(EventArgs e)
-        {
-            base.OnOpened(e);
-        }
-
         protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
         {
             base.OnApplyTemplate(e);
-- 
cgit v1.2.3-70-g09d2