Răsfoiți Sursa

[Ryujinx.Ava] Address dotnet-format issues (#5361)

* dotnet format style --severity info

Some changes were manually reverted.

* dotnet format analyzers --serverity info

Some changes have been minimally adapted.

* Restore a few unused methods and variables

* Silence dotnet format IDE0060 warnings

* Silence dotnet format IDE0052 warnings

* Silence dotnet format IDE0059 warnings

* Address or silence dotnet format IDE1006 warnings

* Address dotnet format CA1816 warnings

* Address dotnet format CA1822 warnings

* Address or silence dotnet format CA1069 warnings

* Make dotnet format succeed in style mode

* Address dotnet format CA1401 warnings

* Address remaining dotnet format analyzer warnings

* Address review comments

* dotnet-format fixes after rebase

* Address most dotnet format whitespace warnings

* Apply dotnet format whitespace formatting

A few of them have been manually reverted and the corresponding warning was silenced

* Format if-blocks correctly

* Another rebase, another dotnet format run

* Run dotnet format whitespace after rebase

* Run dotnet format style after rebase

* Run dotnet format after rebase and remove unused usings

- analyzers
- style
- whitespace

* Add comments to disabled warnings

* Remove a few unused parameters

* Simplify properties and array initialization, Use const when possible, Remove trailing commas

* Start working on disabled warnings

* Fix and silence a few dotnet-format warnings again

* Address IDE0260 warnings

* Address a few disabled IDE0060 warnings

* Silence IDE0060 in .editorconfig

* Revert "Simplify properties and array initialization, Use const when possible, Remove trailing commas"

This reverts commit 9462e4136c0a2100dc28b20cf9542e06790aa67e.

* dotnet format whitespace after rebase

* dotnet format pass with new editorconfig

* Fix naming style issues

* Apply suggestions from code review

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

* Revert one suggestion

* Second dotnet format pass and fix build issues

* Final pass of dotnet format

* Add trailing commas

* Fix formatting issues

* Keep unnecessary assignment in IconColorPicker.cs

* Use using declarations and extend resource lifetimes

* Fix rebase issues

* Adjust comment spacing

* Fix typo

* Fix naming issues

* Apply suggestions from code review

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

* Revert unintentional change

* Remove unused file

* Remove static keyword from ViewModels

Binding of static members doesn't work and is silently ignored.

---------

Co-authored-by: Ac_K <Acoustik666@gmail.com>
TSRBerry 2 ani în urmă
părinte
comite
6c515e1822
100 a modificat fișierele cu 1093 adăugiri și 1461 ștergeri
  1. 2 3
      src/Ryujinx.Ava/App.axaml.cs
  2. 117 116
      src/Ryujinx.Ava/AppHost.cs
  3. 13 12
      src/Ryujinx.Ava/Common/ApplicationHelper.cs
  4. 2 2
      src/Ryujinx.Ava/Common/ApplicationSort.cs
  5. 2 2
      src/Ryujinx.Ava/Common/KeyboardHotkeyState.cs
  6. 3 3
      src/Ryujinx.Ava/Common/Locale/LocaleExtension.cs
  7. 10 10
      src/Ryujinx.Ava/Common/Locale/LocaleManager.cs
  8. 15 13
      src/Ryujinx.Ava/Input/AvaloniaKeyboard.cs
  9. 10 10
      src/Ryujinx.Ava/Input/AvaloniaKeyboardDriver.cs
  10. 2 2
      src/Ryujinx.Ava/Input/AvaloniaKeyboardMappingHelper.cs
  11. 5 5
      src/Ryujinx.Ava/Input/AvaloniaMouse.cs
  12. 22 22
      src/Ryujinx.Ava/Input/AvaloniaMouseDriver.cs
  13. 93 101
      src/Ryujinx.Ava/Modules/Updater/Updater.cs
  14. 16 16
      src/Ryujinx.Ava/Program.cs
  15. 5 8
      src/Ryujinx.Ava/UI/Applet/AvaHostUiHandler.cs
  16. 3 5
      src/Ryujinx.Ava/UI/Applet/AvaloniaDynamicTextInputHandler.cs
  17. 4 6
      src/Ryujinx.Ava/UI/Applet/AvaloniaHostUiTheme.cs
  18. 4 2
      src/Ryujinx.Ava/UI/Applet/ErrorAppletWindow.axaml.cs
  19. 9 11
      src/Ryujinx.Ava/UI/Applet/SwkbdAppletDialog.axaml.cs
  20. 2 3
      src/Ryujinx.Ava/UI/Controls/ApplicationContextMenu.axaml.cs
  21. 1 1
      src/Ryujinx.Ava/UI/Controls/ApplicationGridView.axaml.cs
  22. 1 1
      src/Ryujinx.Ava/UI/Controls/ApplicationListView.axaml.cs
  23. 10 11
      src/Ryujinx.Ava/UI/Controls/NavigationDialogHost.axaml.cs
  24. 1 1
      src/Ryujinx.Ava/UI/Controls/UpdateWaitWindow.axaml.cs
  25. 1 1
      src/Ryujinx.Ava/UI/Helpers/ApplicationOpenedEventArgs.cs
  26. 1 1
      src/Ryujinx.Ava/UI/Helpers/BitmapArrayValueConverter.cs
  27. 1 1
      src/Ryujinx.Ava/UI/Helpers/ButtonKeyAssigner.cs
  28. 29 32
      src/Ryujinx.Ava/UI/Helpers/ContentDialogHelper.cs
  29. 9 8
      src/Ryujinx.Ava/UI/Helpers/GlyphValueConverter.cs
  30. 1 1
      src/Ryujinx.Ava/UI/Helpers/HotKeyControl.cs
  31. 1 1
      src/Ryujinx.Ava/UI/Helpers/KeyValueConverter.cs
  32. 15 13
      src/Ryujinx.Ava/UI/Helpers/LoggerAdapter.cs
  33. 2 2
      src/Ryujinx.Ava/UI/Helpers/MiniCommand.cs
  34. 4 4
      src/Ryujinx.Ava/UI/Helpers/NotificationHelper.cs
  35. 1 1
      src/Ryujinx.Ava/UI/Helpers/NullableDateTimeConverter.cs
  36. 5 5
      src/Ryujinx.Ava/UI/Helpers/OffscreenTextBox.cs
  37. 6 7
      src/Ryujinx.Ava/UI/Helpers/UserErrorDialog.cs
  38. 1 1
      src/Ryujinx.Ava/UI/Helpers/UserResult.cs
  39. 28 26
      src/Ryujinx.Ava/UI/Helpers/Win32NativeInterop.cs
  40. 4 4
      src/Ryujinx.Ava/UI/Models/CheatModel.cs
  41. 3 3
      src/Ryujinx.Ava/UI/Models/CheatsList.cs
  42. 2 2
      src/Ryujinx.Ava/UI/Models/DeviceType.cs
  43. 6 6
      src/Ryujinx.Ava/UI/Models/DownloadableContentModel.cs
  44. 1 1
      src/Ryujinx.Ava/UI/Models/Generic/LastPlayedSortComparer.cs
  45. 157 157
      src/Ryujinx.Ava/UI/Models/InputConfiguration.cs
  46. 1 1
      src/Ryujinx.Ava/UI/Models/ProfileImageModel.cs
  47. 7 6
      src/Ryujinx.Ava/UI/Models/SaveModel.cs
  48. 1 1
      src/Ryujinx.Ava/UI/Models/StatusUpdatedEventArgs.cs
  49. 2 2
      src/Ryujinx.Ava/UI/Models/TempProfile.cs
  50. 1 1
      src/Ryujinx.Ava/UI/Models/TimeZone.cs
  51. 1 1
      src/Ryujinx.Ava/UI/Models/TitleUpdateModel.cs
  52. 3 2
      src/Ryujinx.Ava/UI/Models/UserProfile.cs
  53. 41 37
      src/Ryujinx.Ava/UI/Renderer/EmbeddedWindow.cs
  54. 1 1
      src/Ryujinx.Ava/UI/Renderer/EmbeddedWindowOpenGL.cs
  55. 2 2
      src/Ryujinx.Ava/UI/Renderer/EmbeddedWindowVulkan.cs
  56. 1 1
      src/Ryujinx.Ava/UI/Renderer/OpenTKBindingsContext.cs
  57. 4 4
      src/Ryujinx.Ava/UI/Renderer/RendererHost.axaml.cs
  58. 3 3
      src/Ryujinx.Ava/UI/Renderer/SPBOpenGLContext.cs
  59. 3 2
      src/Ryujinx.Ava/UI/ViewModels/AboutWindowViewModel.cs
  60. 18 20
      src/Ryujinx.Ava/UI/ViewModels/AmiiboWindowViewModel.cs
  61. 0 363
      src/Ryujinx.Ava/UI/ViewModels/AvatarProfileViewModel.cs
  62. 1 1
      src/Ryujinx.Ava/UI/ViewModels/BaseModel.cs
  63. 49 52
      src/Ryujinx.Ava/UI/ViewModels/ControllerInputViewModel.cs
  64. 24 25
      src/Ryujinx.Ava/UI/ViewModels/DownloadableContentManagerViewModel.cs
  65. 57 45
      src/Ryujinx.Ava/UI/ViewModels/MainWindowViewModel.cs
  66. 1 1
      src/Ryujinx.Ava/UI/ViewModels/MotionInputViewModel.cs
  67. 1 1
      src/Ryujinx.Ava/UI/ViewModels/RumbleInputViewModel.cs
  68. 3 4
      src/Ryujinx.Ava/UI/ViewModels/SettingsViewModel.cs
  69. 30 31
      src/Ryujinx.Ava/UI/ViewModels/TitleUpdateViewModel.cs
  70. 77 85
      src/Ryujinx.Ava/UI/ViewModels/UserFirmwareAvatarSelectorViewModel.cs
  71. 2 2
      src/Ryujinx.Ava/UI/ViewModels/UserProfileImageSelectorViewModel.cs
  72. 6 3
      src/Ryujinx.Ava/UI/ViewModels/UserProfileViewModel.cs
  73. 11 14
      src/Ryujinx.Ava/UI/ViewModels/UserSaveManagerViewModel.cs
  74. 2 2
      src/Ryujinx.Ava/UI/Views/Input/ControllerInputView.axaml.cs
  75. 4 4
      src/Ryujinx.Ava/UI/Views/Input/MotionInputView.axaml.cs
  76. 4 4
      src/Ryujinx.Ava/UI/Views/Input/RumbleInputView.axaml.cs
  77. 11 11
      src/Ryujinx.Ava/UI/Views/Main/MainMenuBarView.axaml.cs
  78. 1 1
      src/Ryujinx.Ava/UI/Views/Main/MainStatusBarView.axaml.cs
  79. 4 4
      src/Ryujinx.Ava/UI/Views/Main/MainViewControls.axaml.cs
  80. 1 1
      src/Ryujinx.Ava/UI/Views/Settings/SettingsAudioView.axaml.cs
  81. 1 1
      src/Ryujinx.Ava/UI/Views/Settings/SettingsCPUView.axaml.cs
  82. 1 1
      src/Ryujinx.Ava/UI/Views/Settings/SettingsGraphicsView.axaml.cs
  83. 6 6
      src/Ryujinx.Ava/UI/Views/Settings/SettingsHotkeysView.axaml.cs
  84. 1 1
      src/Ryujinx.Ava/UI/Views/Settings/SettingsInputView.axaml.cs
  85. 1 1
      src/Ryujinx.Ava/UI/Views/Settings/SettingsLoggingView.axaml.cs
  86. 1 1
      src/Ryujinx.Ava/UI/Views/Settings/SettingsNetworkView.axaml.cs
  87. 2 2
      src/Ryujinx.Ava/UI/Views/Settings/SettingsSystemView.axaml.cs
  88. 1 1
      src/Ryujinx.Ava/UI/Views/Settings/SettingsUIView.axaml
  89. 10 9
      src/Ryujinx.Ava/UI/Views/Settings/SettingsUIView.axaml.cs
  90. 7 7
      src/Ryujinx.Ava/UI/Views/User/UserEditorView.axaml.cs
  91. 3 2
      src/Ryujinx.Ava/UI/Views/User/UserFirmwareAvatarSelectorView.axaml.cs
  92. 9 11
      src/Ryujinx.Ava/UI/Views/User/UserProfileImageSelectorView.axaml.cs
  93. 1 1
      src/Ryujinx.Ava/UI/Views/User/UserRecovererView.axaml.cs
  94. 10 9
      src/Ryujinx.Ava/UI/Views/User/UserSaveManagerView.axaml.cs
  95. 4 3
      src/Ryujinx.Ava/UI/Views/User/UserSelectorView.axaml.cs
  96. 6 5
      src/Ryujinx.Ava/UI/Windows/AboutWindow.axaml.cs
  97. 5 4
      src/Ryujinx.Ava/UI/Windows/AmiiboWindow.axaml.cs
  98. 10 10
      src/Ryujinx.Ava/UI/Windows/CheatWindow.axaml.cs
  99. 4 3
      src/Ryujinx.Ava/UI/Windows/ContentDialogOverlayWindow.axaml.cs
  100. 2 2
      src/Ryujinx.Ava/UI/Windows/DownloadableContentManagerWindow.axaml

+ 2 - 3
src/Ryujinx.Ava/App.axaml.cs

@@ -5,7 +5,6 @@ using Avalonia.Styling;
 using Avalonia.Threading;
 using FluentAvalonia.Styling;
 using Ryujinx.Ava.Common.Locale;
-using Ryujinx.Ava.UI.Controls;
 using Ryujinx.Ava.UI.Helpers;
 using Ryujinx.Ava.UI.Windows;
 using Ryujinx.Common;
@@ -67,7 +66,7 @@ namespace Ryujinx.Ava
 
                     if (result == UserResult.Yes)
                     {
-                        var path = Process.GetCurrentProcess().MainModule.FileName;
+                        var path = Environment.ProcessPath;
                         var proc = Process.Start(path, CommandLineState.Arguments);
                         desktop.Shutdown();
                         Environment.Exit(0);
@@ -151,4 +150,4 @@ namespace Ryujinx.Ava
             }
         }
     }
-}
+}

+ 117 - 116
src/Ryujinx.Ava/AppHost.cs

@@ -1,4 +1,5 @@
 using ARMeilleure.Translation;
+using Avalonia;
 using Avalonia.Controls;
 using Avalonia.Controls.ApplicationLifetimes;
 using Avalonia.Input;
@@ -26,6 +27,7 @@ using Ryujinx.Graphics.GAL.Multithreading;
 using Ryujinx.Graphics.Gpu;
 using Ryujinx.Graphics.OpenGL;
 using Ryujinx.Graphics.Vulkan;
+using Ryujinx.HLE;
 using Ryujinx.HLE.FileSystem;
 using Ryujinx.HLE.HOS;
 using Ryujinx.HLE.HOS.Services.Account.Acc;
@@ -41,7 +43,6 @@ using SixLabors.ImageSharp;
 using SixLabors.ImageSharp.Formats.Png;
 using SixLabors.ImageSharp.PixelFormats;
 using SixLabors.ImageSharp.Processing;
-using SPB.Graphics.Exceptions;
 using SPB.Graphics.Vulkan;
 using System;
 using System.Collections.Generic;
@@ -50,10 +51,12 @@ using System.IO;
 using System.Threading;
 using System.Threading.Tasks;
 using static Ryujinx.Ava.UI.Helpers.Win32NativeInterop;
+using AntiAliasing = Ryujinx.Common.Configuration.AntiAliasing;
 using Image = SixLabors.ImageSharp.Image;
 using InputManager = Ryujinx.Input.HLE.InputManager;
 using Key = Ryujinx.Input.Key;
 using MouseButton = Ryujinx.Input.MouseButton;
+using ScalingFilter = Ryujinx.Common.Configuration.ScalingFilter;
 using Size = Avalonia.Size;
 using Switch = Ryujinx.HLE.Switch;
 
@@ -61,31 +64,31 @@ namespace Ryujinx.Ava
 {
     internal class AppHost
     {
-        private const int   CursorHideIdleTime = 5;    // Hide Cursor seconds.
+        private const int CursorHideIdleTime = 5; // Hide Cursor seconds.
         private const float MaxResolutionScale = 4.0f; // Max resolution hotkeys can scale to before wrapping.
-        private const int   TargetFps          = 60;
-        private const float VolumeDelta        = 0.05f;
+        private const int TargetFps = 60;
+        private const float VolumeDelta = 0.05f;
 
-        private static readonly Cursor InvisibleCursor = new(StandardCursorType.None);
-        private readonly IntPtr        InvisibleCursorWin;
-        private readonly IntPtr        DefaultCursorWin;
+        private static readonly Cursor _invisibleCursor = new(StandardCursorType.None);
+        private readonly IntPtr _invisibleCursorWin;
+        private readonly IntPtr _defaultCursorWin;
 
-        private readonly long      _ticksPerFrame;
+        private readonly long _ticksPerFrame;
         private readonly Stopwatch _chrono;
-        private long               _ticks;
+        private long _ticks;
 
-        private readonly AccountManager         _accountManager;
+        private readonly AccountManager _accountManager;
         private readonly UserChannelPersistence _userChannelPersistence;
-        private readonly InputManager           _inputManager;
+        private readonly InputManager _inputManager;
 
         private readonly MainWindowViewModel _viewModel;
-        private readonly IKeyboard           _keyboardInterface;
-        private readonly TopLevel            _topLevel;
-        public           RendererHost        _rendererHost;
+        private readonly IKeyboard _keyboardInterface;
+        private readonly TopLevel _topLevel;
+        public RendererHost RendererHost;
 
         private readonly GraphicsDebugLevel _glLogLevel;
-        private float                       _newVolume;
-        private KeyboardHotkeyState         _prevHotkeyState;
+        private float _newVolume;
+        private KeyboardHotkeyState _prevHotkeyState;
 
         private long _lastCursorMoveTime;
         private bool _isCursorInRenderer = true;
@@ -94,14 +97,14 @@ namespace Ryujinx.Ava
         private bool _isActive;
         private bool _renderingStarted;
 
-        private ManualResetEvent _gpuDoneEvent;
+        private readonly ManualResetEvent _gpuDoneEvent;
 
-        private IRenderer                        _renderer;
-        private readonly Thread                  _renderingThread;
+        private IRenderer _renderer;
+        private readonly Thread _renderingThread;
         private readonly CancellationTokenSource _gpuCancellationTokenSource;
         private WindowsMultimediaTimerResolution _windowsMultimediaTimerResolution;
 
-        private bool          _dialogShown;
+        private bool _dialogShown;
         private readonly bool _isFirmwareTitle;
 
         private readonly object _lockObject = new();
@@ -109,55 +112,55 @@ namespace Ryujinx.Ava
         public event EventHandler AppExit;
         public event EventHandler<StatusUpdatedEventArgs> StatusUpdatedEvent;
 
-        public VirtualFileSystem  VirtualFileSystem  { get; }
-        public ContentManager     ContentManager     { get; }
-        public NpadManager        NpadManager        { get; }
+        public VirtualFileSystem VirtualFileSystem { get; }
+        public ContentManager ContentManager { get; }
+        public NpadManager NpadManager { get; }
         public TouchScreenManager TouchScreenManager { get; }
-        public Switch             Device             { get; set; }
+        public Switch Device { get; set; }
 
-        public int    Width               { get; private set; }
-        public int    Height              { get; private set; }
-        public string ApplicationPath     { get; private set; }
-        public bool   ScreenshotRequested { get; set; }
+        public int Width { get; private set; }
+        public int Height { get; private set; }
+        public string ApplicationPath { get; private set; }
+        public bool ScreenshotRequested { get; set; }
 
         public AppHost(
-            RendererHost           renderer,
-            InputManager           inputManager,
-            string                 applicationPath,
-            VirtualFileSystem      virtualFileSystem,
-            ContentManager         contentManager,
-            AccountManager         accountManager,
+            RendererHost renderer,
+            InputManager inputManager,
+            string applicationPath,
+            VirtualFileSystem virtualFileSystem,
+            ContentManager contentManager,
+            AccountManager accountManager,
             UserChannelPersistence userChannelPersistence,
-            MainWindowViewModel    viewmodel,
-            TopLevel               topLevel)
+            MainWindowViewModel viewmodel,
+            TopLevel topLevel)
         {
-            _viewModel              = viewmodel;
-            _inputManager           = inputManager;
-            _accountManager         = accountManager;
+            _viewModel = viewmodel;
+            _inputManager = inputManager;
+            _accountManager = accountManager;
             _userChannelPersistence = userChannelPersistence;
-            _renderingThread        = new Thread(RenderLoop) { Name = "GUI.RenderThread" };
-            _lastCursorMoveTime     = Stopwatch.GetTimestamp();
-            _glLogLevel             = ConfigurationState.Instance.Logger.GraphicsDebugLevel;
-            _topLevel               = topLevel;
+            _renderingThread = new Thread(RenderLoop) { Name = "GUI.RenderThread" };
+            _lastCursorMoveTime = Stopwatch.GetTimestamp();
+            _glLogLevel = ConfigurationState.Instance.Logger.GraphicsDebugLevel;
+            _topLevel = topLevel;
 
             _inputManager.SetMouseDriver(new AvaloniaMouseDriver(_topLevel, renderer));
 
             _keyboardInterface = (IKeyboard)_inputManager.KeyboardDriver.GetGamepad("0");
 
-            NpadManager        = _inputManager.CreateNpadManager();
+            NpadManager = _inputManager.CreateNpadManager();
             TouchScreenManager = _inputManager.CreateTouchScreenManager();
-            ApplicationPath    = applicationPath;
-            VirtualFileSystem  = virtualFileSystem;
-            ContentManager     = contentManager;
+            ApplicationPath = applicationPath;
+            VirtualFileSystem = virtualFileSystem;
+            ContentManager = contentManager;
 
-            _rendererHost = renderer;
+            RendererHost = renderer;
 
-            _chrono        = new Stopwatch();
+            _chrono = new Stopwatch();
             _ticksPerFrame = Stopwatch.Frequency / TargetFps;
 
             if (ApplicationPath.StartsWith("@SystemContent"))
             {
-                ApplicationPath = _viewModel.VirtualFileSystem.SwitchPathToSystemPath(ApplicationPath);
+                ApplicationPath = VirtualFileSystem.SwitchPathToSystemPath(ApplicationPath);
 
                 _isFirmwareTitle = true;
             }
@@ -170,21 +173,21 @@ namespace Ryujinx.Ava
 
             if (OperatingSystem.IsWindows())
             {
-                InvisibleCursorWin = CreateEmptyCursor();
-                DefaultCursorWin   = CreateArrowCursor();
+                _invisibleCursorWin = CreateEmptyCursor();
+                _defaultCursorWin = CreateArrowCursor();
             }
 
             ConfigurationState.Instance.System.IgnoreMissingServices.Event += UpdateIgnoreMissingServicesState;
-            ConfigurationState.Instance.Graphics.AspectRatio.Event         += UpdateAspectRatioState;
-            ConfigurationState.Instance.System.EnableDockedMode.Event      += UpdateDockedModeState;
-            ConfigurationState.Instance.System.AudioVolume.Event           += UpdateAudioVolumeState;
-            ConfigurationState.Instance.System.EnableDockedMode.Event      += UpdateDockedModeState;
-            ConfigurationState.Instance.System.AudioVolume.Event           += UpdateAudioVolumeState;
-            ConfigurationState.Instance.Graphics.AntiAliasing.Event        += UpdateAntiAliasing;
-            ConfigurationState.Instance.Graphics.ScalingFilter.Event       += UpdateScalingFilter;
-            ConfigurationState.Instance.Graphics.ScalingFilterLevel.Event  += UpdateScalingFilterLevel;
+            ConfigurationState.Instance.Graphics.AspectRatio.Event += UpdateAspectRatioState;
+            ConfigurationState.Instance.System.EnableDockedMode.Event += UpdateDockedModeState;
+            ConfigurationState.Instance.System.AudioVolume.Event += UpdateAudioVolumeState;
+            ConfigurationState.Instance.System.EnableDockedMode.Event += UpdateDockedModeState;
+            ConfigurationState.Instance.System.AudioVolume.Event += UpdateAudioVolumeState;
+            ConfigurationState.Instance.Graphics.AntiAliasing.Event += UpdateAntiAliasing;
+            ConfigurationState.Instance.Graphics.ScalingFilter.Event += UpdateScalingFilter;
+            ConfigurationState.Instance.Graphics.ScalingFilterLevel.Event += UpdateScalingFilterLevel;
 
-            ConfigurationState.Instance.Multiplayer.LanInterfaceId.Event   += UpdateLanInterfaceIdState;
+            ConfigurationState.Instance.Multiplayer.LanInterfaceId.Event += UpdateLanInterfaceIdState;
 
             _gpuCancellationTokenSource = new CancellationTokenSource();
             _gpuDoneEvent = new ManualResetEvent(false);
@@ -196,10 +199,10 @@ namespace Ryujinx.Ava
             {
                 _lastCursorMoveTime = Stopwatch.GetTimestamp();
 
-                if (_rendererHost.EmbeddedWindow.TransformedBounds != null)
+                if (RendererHost.EmbeddedWindow.TransformedBounds != null)
                 {
-                    var point  = e.GetCurrentPoint(window).Position;
-                    var bounds = _rendererHost.EmbeddedWindow.TransformedBounds.Value.Clip;
+                    var point = e.GetCurrentPoint(window).Position;
+                    var bounds = RendererHost.EmbeddedWindow.TransformedBounds.Value.Clip;
 
                     _isCursorInRenderer = point.X >= bounds.X &&
                                           point.X <= bounds.Width + bounds.X &&
@@ -220,7 +223,7 @@ namespace Ryujinx.Ava
             _renderer.Window?.SetScalingFilterLevel(ConfigurationState.Instance.Graphics.ScalingFilterLevel.Value);
         }
 
-        private void UpdateScalingFilter(object sender, ReactiveEventArgs<Ryujinx.Common.Configuration.ScalingFilter> e)
+        private void UpdateScalingFilter(object sender, ReactiveEventArgs<ScalingFilter> e)
         {
             _renderer.Window?.SetScalingFilter((Graphics.GAL.ScalingFilter)ConfigurationState.Instance.Graphics.ScalingFilter.Value);
             _renderer.Window?.SetScalingFilterLevel(ConfigurationState.Instance.Graphics.ScalingFilterLevel.Value);
@@ -234,7 +237,7 @@ namespace Ryujinx.Ava
 
                 if (OperatingSystem.IsWindows())
                 {
-                    SetCursor(DefaultCursorWin);
+                    SetCursor(_defaultCursorWin);
                 }
             });
         }
@@ -243,11 +246,11 @@ namespace Ryujinx.Ava
         {
             Dispatcher.UIThread.Post(() =>
             {
-                _viewModel.Cursor = InvisibleCursor;
+                _viewModel.Cursor = _invisibleCursor;
 
                 if (OperatingSystem.IsWindows())
                 {
-                    SetCursor(InvisibleCursorWin);
+                    SetCursor(_invisibleCursorWin);
                 }
             });
         }
@@ -271,12 +274,12 @@ namespace Ryujinx.Ava
                     lock (_lockObject)
                     {
                         DateTime currentTime = DateTime.Now;
-                        string   filename    = $"ryujinx_capture_{currentTime.Year}-{currentTime.Month:D2}-{currentTime.Day:D2}_{currentTime.Hour:D2}-{currentTime.Minute:D2}-{currentTime.Second:D2}.png";
+                        string filename = $"ryujinx_capture_{currentTime.Year}-{currentTime.Month:D2}-{currentTime.Day:D2}_{currentTime.Hour:D2}-{currentTime.Minute:D2}-{currentTime.Second:D2}.png";
 
                         string directory = AppDataManager.Mode switch
                         {
                             AppDataManager.LaunchMode.Portable or AppDataManager.LaunchMode.Custom => Path.Combine(AppDataManager.BaseDirPath, "screenshots"),
-                            _                                  => Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyPictures), "Ryujinx")
+                            _ => Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyPictures), "Ryujinx"),
                         };
 
                         string path = Path.Combine(directory, filename);
@@ -305,9 +308,9 @@ namespace Ryujinx.Ava
                             image.Mutate(x => x.Flip(FlipMode.Vertical));
                         }
 
-                        image.SaveAsPng(path, new PngEncoder()
+                        image.SaveAsPng(path, new PngEncoder
                         {
-                            ColorType = PngColorType.Rgb
+                            ColorType = PngColorType.Rgb,
                         });
 
                         image.Dispose();
@@ -336,21 +339,21 @@ namespace Ryujinx.Ava
 
             _viewModel.IsGameRunning = true;
 
-            var activeProcess   = Device.Processes.ActiveApplication;
+            var activeProcess = Device.Processes.ActiveApplication;
 
-            string titleNameSection    = string.IsNullOrWhiteSpace(activeProcess.Name) ? string.Empty : $" {activeProcess.Name}";
+            string titleNameSection = string.IsNullOrWhiteSpace(activeProcess.Name) ? string.Empty : $" {activeProcess.Name}";
             string titleVersionSection = string.IsNullOrWhiteSpace(activeProcess.DisplayVersion) ? string.Empty : $" v{activeProcess.DisplayVersion}";
-            string titleIdSection      = $" ({activeProcess.ProgramIdText.ToUpper()})";
-            string titleArchSection    = activeProcess.Is64Bit ? " (64-bit)" : " (32-bit)";
+            string titleIdSection = $" ({activeProcess.ProgramIdText.ToUpper()})";
+            string titleArchSection = activeProcess.Is64Bit ? " (64-bit)" : " (32-bit)";
 
             Dispatcher.UIThread.InvokeAsync(() =>
             {
                 _viewModel.Title = $"Ryujinx {Program.Version} -{titleNameSection}{titleVersionSection}{titleIdSection}{titleArchSection}";
             });
 
-            _viewModel.SetUIProgressHandlers(Device);
+            _viewModel.SetUiProgressHandlers(Device);
 
-            _rendererHost.SizeChanged += Window_SizeChanged;
+            RendererHost.SizeChanged += Window_SizeChanged;
 
             _isActive = true;
 
@@ -379,7 +382,7 @@ namespace Ryujinx.Ava
             }
         }
 
-        private void UpdateAntiAliasing(object sender, ReactiveEventArgs<Ryujinx.Common.Configuration.AntiAliasing> e)
+        private void UpdateAntiAliasing(object sender, ReactiveEventArgs<AntiAliasing> e)
         {
             _renderer?.Window?.SetAntiAliasing((Graphics.GAL.AntiAliasing)e.NewValue);
         }
@@ -419,7 +422,7 @@ namespace Ryujinx.Ava
             }
 
             _isStopped = true;
-            _isActive  = false;
+            _isActive = false;
         }
 
         public void DisposeContext()
@@ -448,16 +451,16 @@ namespace Ryujinx.Ava
         {
             if (Device.Processes != null)
             {
-                _viewModel.UpdateGameMetadata(Device.Processes.ActiveApplication.ProgramIdText);
+                MainWindowViewModel.UpdateGameMetadata(Device.Processes.ActiveApplication.ProgramIdText);
             }
 
             ConfigurationState.Instance.System.IgnoreMissingServices.Event -= UpdateIgnoreMissingServicesState;
-            ConfigurationState.Instance.Graphics.AspectRatio.Event         -= UpdateAspectRatioState;
-            ConfigurationState.Instance.System.EnableDockedMode.Event      -= UpdateDockedModeState;
-            ConfigurationState.Instance.System.AudioVolume.Event           -= UpdateAudioVolumeState;
-            ConfigurationState.Instance.Graphics.ScalingFilter.Event       -= UpdateScalingFilter;
-            ConfigurationState.Instance.Graphics.ScalingFilterLevel.Event  -= UpdateScalingFilterLevel;
-            ConfigurationState.Instance.Graphics.AntiAliasing.Event        -= UpdateAntiAliasing;
+            ConfigurationState.Instance.Graphics.AspectRatio.Event -= UpdateAspectRatioState;
+            ConfigurationState.Instance.System.EnableDockedMode.Event -= UpdateDockedModeState;
+            ConfigurationState.Instance.System.AudioVolume.Event -= UpdateAudioVolumeState;
+            ConfigurationState.Instance.Graphics.ScalingFilter.Event -= UpdateScalingFilter;
+            ConfigurationState.Instance.Graphics.ScalingFilterLevel.Event -= UpdateScalingFilterLevel;
+            ConfigurationState.Instance.Graphics.AntiAliasing.Event -= UpdateAntiAliasing;
 
             _topLevel.PointerMoved -= TopLevel_PointerEnterOrMoved;
             _topLevel.PointerEnter -= TopLevel_PointerEnterOrMoved;
@@ -477,7 +480,7 @@ namespace Ryujinx.Ava
                 _windowsMultimediaTimerResolution = null;
             }
 
-            if (_rendererHost.EmbeddedWindow is EmbeddedWindowOpenGL openGlWindow)
+            if (RendererHost.EmbeddedWindow is EmbeddedWindowOpenGL openGlWindow)
             {
                 // Try to bind the OpenGL context before calling the shutdown event.
                 openGlWindow.MakeCurrent(false, false);
@@ -508,7 +511,7 @@ namespace Ryujinx.Ava
 
             SystemVersion firmwareVersion = ContentManager.GetCurrentFirmwareVersion();
 
-            if (Avalonia.Application.Current.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
+            if (Application.Current.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
             {
                 if (!SetupValidator.CanStartApplication(ContentManager, ApplicationPath, out UserError userError))
                 {
@@ -526,7 +529,7 @@ namespace Ryujinx.Ava
 
                                 if (result != UserResult.Yes)
                                 {
-                                    await UserErrorDialog.ShowUserErrorDialog(userError, (desktop.MainWindow as MainWindow));
+                                    await UserErrorDialog.ShowUserErrorDialog(userError);
                                     Device.Dispose();
 
                                     return false;
@@ -535,7 +538,7 @@ namespace Ryujinx.Ava
 
                             if (!SetupValidator.TryFixStartApplication(ContentManager, ApplicationPath, userError, out _))
                             {
-                                await UserErrorDialog.ShowUserErrorDialog(userError, (desktop.MainWindow as MainWindow));
+                                await UserErrorDialog.ShowUserErrorDialog(userError);
                                 Device.Dispose();
 
                                 return false;
@@ -558,7 +561,7 @@ namespace Ryujinx.Ava
                         }
                         else
                         {
-                            await UserErrorDialog.ShowUserErrorDialog(userError, (desktop.MainWindow as MainWindow));
+                            await UserErrorDialog.ShowUserErrorDialog(userError);
                             Device.Dispose();
 
                             return false;
@@ -727,7 +730,7 @@ namespace Ryujinx.Ava
             {
                 renderer = new VulkanRenderer(
                     Vk.GetApi(),
-                    (_rendererHost.EmbeddedWindow as EmbeddedWindowVulkan).CreateSurface,
+                    (RendererHost.EmbeddedWindow as EmbeddedWindowVulkan).CreateSurface,
                     VulkanHelper.GetRequiredInstanceExtensions,
                     ConfigurationState.Instance.Graphics.PreferredGpu.Value);
             }
@@ -738,18 +741,18 @@ namespace Ryujinx.Ava
 
             BackendThreading threadingMode = ConfigurationState.Instance.Graphics.BackendThreading;
 
-            var isGALthreaded = threadingMode == BackendThreading.On || (threadingMode == BackendThreading.Auto && renderer.PreferThreading);
-            if (isGALthreaded)
+            var isGALThreaded = threadingMode == BackendThreading.On || (threadingMode == BackendThreading.Auto && renderer.PreferThreading);
+            if (isGALThreaded)
             {
                 renderer = new ThreadedRenderer(renderer);
             }
 
-            Logger.Info?.PrintMsg(LogClass.Gpu, $"Backend Threading ({threadingMode}): {isGALthreaded}");
+            Logger.Info?.PrintMsg(LogClass.Gpu, $"Backend Threading ({threadingMode}): {isGALThreaded}");
 
             // Initialize Configuration.
-            var memoryConfiguration = ConfigurationState.Instance.System.ExpandRam.Value ? HLE.MemoryConfiguration.MemoryConfiguration6GiB : HLE.MemoryConfiguration.MemoryConfiguration4GiB;
+            var memoryConfiguration = ConfigurationState.Instance.System.ExpandRam.Value ? MemoryConfiguration.MemoryConfiguration6GiB : MemoryConfiguration.MemoryConfiguration4GiB;
 
-            HLE.HLEConfiguration configuration = new(VirtualFileSystem,
+            HLEConfiguration configuration = new(VirtualFileSystem,
                                                      _viewModel.LibHacHorizonManager,
                                                      ContentManager,
                                                      _accountManager,
@@ -780,12 +783,12 @@ namespace Ryujinx.Ava
 
         private static IHardwareDeviceDriver InitializeAudio()
         {
-            var availableBackends = new List<AudioBackend>()
+            var availableBackends = new List<AudioBackend>
             {
                 AudioBackend.SDL2,
                 AudioBackend.SoundIo,
                 AudioBackend.OpenAl,
-                AudioBackend.Dummy
+                AudioBackend.Dummy,
             };
 
             AudioBackend preferredBackend = ConfigurationState.Instance.System.AudioBackend.Value;
@@ -806,12 +809,10 @@ namespace Ryujinx.Ava
                 {
                     return new T();
                 }
-                else
-                {
-                    Logger.Warning?.Print(LogClass.Audio, $"{backend} is not supported, falling back to {nextBackend}.");
 
-                    return null;
-                }
+                Logger.Warning?.Print(LogClass.Audio, $"{backend} is not supported, falling back to {nextBackend}.");
+
+                return null;
             }
 
             IHardwareDeviceDriver deviceDriver = null;
@@ -819,14 +820,14 @@ namespace Ryujinx.Ava
             for (int i = 0; i < availableBackends.Count; i++)
             {
                 AudioBackend currentBackend = availableBackends[i];
-                AudioBackend nextBackend    = i + 1 < availableBackends.Count ? availableBackends[i + 1] : AudioBackend.Dummy;
+                AudioBackend nextBackend = i + 1 < availableBackends.Count ? availableBackends[i + 1] : AudioBackend.Dummy;
 
                 deviceDriver = currentBackend switch
                 {
-                    AudioBackend.SDL2    => InitializeAudioBackend<SDL2HardwareDeviceDriver>(AudioBackend.SDL2, nextBackend),
+                    AudioBackend.SDL2 => InitializeAudioBackend<SDL2HardwareDeviceDriver>(AudioBackend.SDL2, nextBackend),
                     AudioBackend.SoundIo => InitializeAudioBackend<SoundIoHardwareDeviceDriver>(AudioBackend.SoundIo, nextBackend),
-                    AudioBackend.OpenAl  => InitializeAudioBackend<OpenALHardwareDeviceDriver>(AudioBackend.OpenAl, nextBackend),
-                    _                    => new DummyHardwareDeviceDriver()
+                    AudioBackend.OpenAl => InitializeAudioBackend<OpenALHardwareDeviceDriver>(AudioBackend.OpenAl, nextBackend),
+                    _ => new DummyHardwareDeviceDriver(),
                 };
 
                 if (deviceDriver != null)
@@ -843,7 +844,7 @@ namespace Ryujinx.Ava
 
         private void Window_SizeChanged(object sender, Size e)
         {
-            Width  = (int)e.Width;
+            Width = (int)e.Width;
             Height = (int)e.Height;
 
             SetRendererWindowSize(e);
@@ -879,7 +880,7 @@ namespace Ryujinx.Ava
 
             _renderer.ScreenCaptured += Renderer_ScreenCaptured;
 
-            (_rendererHost.EmbeddedWindow as EmbeddedWindowOpenGL)?.InitializeBackgroundContext(_renderer);
+            (RendererHost.EmbeddedWindow as EmbeddedWindowOpenGL)?.InitializeBackgroundContext(_renderer);
 
             Device.Gpu.Renderer.Initialize(_glLogLevel);
 
@@ -887,8 +888,8 @@ namespace Ryujinx.Ava
             _renderer?.Window?.SetScalingFilter((Graphics.GAL.ScalingFilter)ConfigurationState.Instance.Graphics.ScalingFilter.Value);
             _renderer?.Window?.SetScalingFilterLevel(ConfigurationState.Instance.Graphics.ScalingFilterLevel.Value);
 
-            Width = (int)_rendererHost.Bounds.Width;
-            Height = (int)_rendererHost.Bounds.Height;
+            Width = (int)RendererHost.Bounds.Width;
+            Height = (int)RendererHost.Bounds.Height;
 
             _renderer.Window.SetSize((int)(Width * _topLevel.PlatformImpl.RenderScaling), (int)(Height * _topLevel.PlatformImpl.RenderScaling));
 
@@ -923,7 +924,7 @@ namespace Ryujinx.Ava
                             _viewModel.SwitchToRenderer(false);
                         }
 
-                        Device.PresentFrame(() => (_rendererHost.EmbeddedWindow as EmbeddedWindowOpenGL)?.SwapBuffers());
+                        Device.PresentFrame(() => (RendererHost.EmbeddedWindow as EmbeddedWindowOpenGL)?.SwapBuffers());
                     }
 
                     if (_ticks >= _ticksPerFrame)
@@ -941,7 +942,7 @@ namespace Ryujinx.Ava
                 _gpuDoneEvent.Set();
             });
 
-            (_rendererHost.EmbeddedWindow as EmbeddedWindowOpenGL)?.MakeCurrent(true);
+            (RendererHost.EmbeddedWindow as EmbeddedWindowOpenGL)?.MakeCurrent(true);
         }
 
         public void UpdateStatus()
@@ -1175,4 +1176,4 @@ namespace Ryujinx.Ava
             return state;
         }
     }
-}
+}

+ 13 - 12
src/Ryujinx.Ava/Common/ApplicationHelper.cs

@@ -18,7 +18,6 @@ using Ryujinx.Ava.UI.Helpers;
 using Ryujinx.Ava.UI.Windows;
 using Ryujinx.Common.Logging;
 using Ryujinx.HLE.FileSystem;
-using Ryujinx.HLE.HOS;
 using Ryujinx.HLE.HOS.Services.Account.Acc;
 using Ryujinx.Ui.App.Common;
 using Ryujinx.Ui.Common.Helper;
@@ -27,6 +26,7 @@ using System.Buffers;
 using System.IO;
 using System.Threading;
 using System.Threading.Tasks;
+using ApplicationId = LibHac.Ncm.ApplicationId;
 using Path = System.IO.Path;
 
 namespace Ryujinx.Ava.Common
@@ -57,7 +57,7 @@ namespace Ryujinx.Ava.Common
 
                 Logger.Info?.Print(LogClass.Application, $"Creating save directory for Title: {titleName} [{titleId:x16}]");
 
-                if (Utilities.IsZeros(controlHolder.ByteSpan))
+                if (controlHolder.ByteSpan.IsZeros())
                 {
                     // If the current application doesn't have a loaded control property, create a dummy one
                     // and set the savedata sizes so a user savedata will be created.
@@ -72,7 +72,7 @@ namespace Ryujinx.Ava.Common
 
                 Uid user = new((ulong)_accountManager.LastOpenedUser.UserId.High, (ulong)_accountManager.LastOpenedUser.UserId.Low);
 
-                result = _horizonClient.Fs.EnsureApplicationSaveData(out _, new LibHac.Ncm.ApplicationId(titleId), in control, in user);
+                result = _horizonClient.Fs.EnsureApplicationSaveData(out _, new ApplicationId(titleId), in control, in user);
                 if (result.IsFailure())
                 {
                     Dispatcher.UIThread.InvokeAsync(async () =>
@@ -147,11 +147,11 @@ namespace Ryujinx.Ava.Common
         {
             OpenFolderDialog folderDialog = new()
             {
-                Title = LocaleManager.Instance[LocaleKeys.FolderDialogExtractTitle]
+                Title = LocaleManager.Instance[LocaleKeys.FolderDialogExtractTitle],
             };
 
-            string destination       = await folderDialog.ShowAsync(_owner);
-            var    cancellationToken = new CancellationTokenSource();
+            string destination = await folderDialog.ShowAsync(_owner);
+            var cancellationToken = new CancellationTokenSource();
 
             UpdateWaitWindow waitingDialog = new(
                 LocaleManager.Instance[LocaleKeys.DialogNcaExtractionTitle],
@@ -166,7 +166,7 @@ namespace Ryujinx.Ava.Common
 
                     using FileStream file = new(titleFilePath, FileMode.Open, FileAccess.Read);
 
-                    Nca mainNca  = null;
+                    Nca mainNca = null;
                     Nca patchNca = null;
 
                     string extension = Path.GetExtension(titleFilePath).ToLower();
@@ -293,10 +293,11 @@ namespace Ryujinx.Ava.Common
                             await ContentDialogHelper.CreateErrorDialog(ex.Message);
                         });
                     }
-                });
-
-                extractorThread.Name = "GUI.NcaSectionExtractorThread";
-                extractorThread.IsBackground = true;
+                })
+                {
+                    Name = "GUI.NcaSectionExtractorThread",
+                    IsBackground = true,
+                };
                 extractorThread.Start();
             }
         }
@@ -413,4 +414,4 @@ namespace Ryujinx.Ava.Common
             return Result.Success;
         }
     }
-}
+}

+ 2 - 2
src/Ryujinx.Ava/Common/ApplicationSort.cs

@@ -10,6 +10,6 @@ namespace Ryujinx.Ava.Common
         FileType,
         FileSize,
         Path,
-        Favorite
+        Favorite,
     }
-}
+}

+ 2 - 2
src/Ryujinx.Ava/Common/KeyboardHotkeyState.cs

@@ -11,6 +11,6 @@
         ResScaleUp,
         ResScaleDown,
         VolumeUp,
-        VolumeDown
+        VolumeDown,
     }
-}
+}

+ 3 - 3
src/Ryujinx.Ava/Common/Locale/LocaleExtension.cs

@@ -20,11 +20,11 @@ namespace Ryujinx.Ava.Common.Locale
 
             ReflectionBindingExtension binding = new($"[{keyToUse}]")
             {
-                Mode   = BindingMode.OneWay,
-                Source = LocaleManager.Instance
+                Mode = BindingMode.OneWay,
+                Source = LocaleManager.Instance,
             };
 
             return binding.ProvideValue(serviceProvider);
         }
     }
-}
+}

+ 10 - 10
src/Ryujinx.Ava/Common/Locale/LocaleManager.cs

@@ -13,17 +13,17 @@ namespace Ryujinx.Ava.Common.Locale
     {
         private const string DefaultLanguageCode = "en_US";
 
-        private Dictionary<LocaleKeys, string>                      _localeStrings;
-        private Dictionary<LocaleKeys, string>                      _localeDefaultStrings;
+        private readonly Dictionary<LocaleKeys, string> _localeStrings;
+        private Dictionary<LocaleKeys, string> _localeDefaultStrings;
         private readonly ConcurrentDictionary<LocaleKeys, object[]> _dynamicValues;
 
-        public static LocaleManager Instance { get; } = new LocaleManager();
+        public static LocaleManager Instance { get; } = new();
 
         public LocaleManager()
         {
-            _localeStrings        = new Dictionary<LocaleKeys, string>();
+            _localeStrings = new Dictionary<LocaleKeys, string>();
             _localeDefaultStrings = new Dictionary<LocaleKeys, string>();
-            _dynamicValues        = new ConcurrentDictionary<LocaleKeys, object[]>();
+            _dynamicValues = new ConcurrentDictionary<LocaleKeys, object[]>();
 
             Load();
         }
@@ -126,11 +126,11 @@ namespace Ryujinx.Ava.Common.Locale
             }
         }
 
-        private Dictionary<LocaleKeys, string> LoadJsonLanguage(string languageCode = DefaultLanguageCode)
+        private static Dictionary<LocaleKeys, string> LoadJsonLanguage(string languageCode = DefaultLanguageCode)
         {
-            var    localeStrings = new Dictionary<LocaleKeys, string>();
-            string languageJson  = EmbeddedResources.ReadAllText($"Ryujinx.Ava/Assets/Locales/{languageCode}.json");
-            var    strings       = JsonHelper.Deserialize(languageJson, CommonJsonContext.Default.StringDictionary);
+            var localeStrings = new Dictionary<LocaleKeys, string>();
+            string languageJson = EmbeddedResources.ReadAllText($"Ryujinx.Ava/Assets/Locales/{languageCode}.json");
+            var strings = JsonHelper.Deserialize(languageJson, CommonJsonContext.Default.StringDictionary);
 
             foreach (var item in strings)
             {
@@ -143,4 +143,4 @@ namespace Ryujinx.Ava.Common.Locale
             return localeStrings;
         }
     }
-}
+}

+ 15 - 13
src/Ryujinx.Ava/Input/AvaloniaKeyboard.cs

@@ -12,25 +12,25 @@ namespace Ryujinx.Ava.Input
     internal class AvaloniaKeyboard : IKeyboard
     {
         private readonly List<ButtonMappingEntry> _buttonsUserMapping;
-        private readonly AvaloniaKeyboardDriver   _driver;
-        private StandardKeyboardInputConfig       _configuration;
+        private readonly AvaloniaKeyboardDriver _driver;
+        private StandardKeyboardInputConfig _configuration;
 
         private readonly object _userMappingLock = new();
 
-        public string Id   { get; }
+        public string Id { get; }
         public string Name { get; }
 
-        public bool                IsConnected => true;
-        public GamepadFeaturesFlag Features    => GamepadFeaturesFlag.None;
+        public bool IsConnected => true;
+        public GamepadFeaturesFlag Features => GamepadFeaturesFlag.None;
 
         private class ButtonMappingEntry
         {
-            public readonly Key                  From;
+            public readonly Key From;
             public readonly GamepadButtonInputId To;
 
             public ButtonMappingEntry(GamepadButtonInputId to, Key from)
             {
-                To   = to;
+                To = to;
                 From = from;
             }
         }
@@ -40,8 +40,8 @@ namespace Ryujinx.Ava.Input
             _buttonsUserMapping = new List<ButtonMappingEntry>();
 
             _driver = driver;
-            Id      = id;
-            Name    = name;
+            Id = id;
+            Name = name;
         }
 
         public KeyboardStateSnapshot GetKeyboardStateSnapshot()
@@ -52,7 +52,7 @@ namespace Ryujinx.Ava.Input
         public GamepadStateSnapshot GetMappedStateSnapshot()
         {
             KeyboardStateSnapshot rawState = GetKeyboardStateSnapshot();
-            GamepadStateSnapshot  result   = default;
+            GamepadStateSnapshot result = default;
 
             lock (_userMappingLock)
             {
@@ -75,10 +75,10 @@ namespace Ryujinx.Ava.Input
                     }
                 }
 
-                (short leftStickX,  short leftStickY)  = GetStickValues(ref rawState, _configuration.LeftJoyconStick);
+                (short leftStickX, short leftStickY) = GetStickValues(ref rawState, _configuration.LeftJoyconStick);
                 (short rightStickX, short rightStickY) = GetStickValues(ref rawState, _configuration.RightJoyconStick);
 
-                result.SetStick(StickInputId.Left,  ConvertRawStickValue(leftStickX),  ConvertRawStickValue(leftStickY));
+                result.SetStick(StickInputId.Left, ConvertRawStickValue(leftStickX), ConvertRawStickValue(leftStickY));
                 result.SetStick(StickInputId.Right, ConvertRawStickValue(rightStickX), ConvertRawStickValue(rightStickY));
             }
 
@@ -120,6 +120,7 @@ namespace Ryujinx.Ava.Input
 
                 _buttonsUserMapping.Clear();
 
+#pragma warning disable IDE0055 // Disable formatting
                 // Left JoyCon
                 _buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.LeftStick,           (Key)_configuration.LeftJoyconStick.StickButton));
                 _buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.DpadUp,              (Key)_configuration.LeftJoycon.DpadUp));
@@ -143,6 +144,7 @@ namespace Ryujinx.Ava.Input
                 _buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.RightTrigger,        (Key)_configuration.RightJoycon.ButtonZr));
                 _buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.SingleRightTrigger1, (Key)_configuration.RightJoycon.ButtonSr));
                 _buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.SingleLeftTrigger1,  (Key)_configuration.RightJoycon.ButtonSl));
+#pragma warning restore IDE0055
             }
         }
 
@@ -198,4 +200,4 @@ namespace Ryujinx.Ava.Input
 
         public void Dispose() { }
     }
-}
+}

+ 10 - 10
src/Ryujinx.Ava/Input/AvaloniaKeyboardDriver.cs

@@ -13,23 +13,23 @@ namespace Ryujinx.Ava.Input
     internal class AvaloniaKeyboardDriver : IGamepadDriver
     {
         private static readonly string[] _keyboardIdentifers = new string[1] { "0" };
-        private readonly Control         _control;
+        private readonly Control _control;
         private readonly HashSet<AvaKey> _pressedKeys;
 
         public event EventHandler<KeyEventArgs> KeyPressed;
         public event EventHandler<KeyEventArgs> KeyRelease;
-        public event EventHandler<string>       TextInput;
+        public event EventHandler<string> TextInput;
 
-        public string               DriverName  => "AvaloniaKeyboardDriver";
+        public string DriverName => "AvaloniaKeyboardDriver";
         public ReadOnlySpan<string> GamepadsIds => _keyboardIdentifers;
 
         public AvaloniaKeyboardDriver(Control control)
         {
-            _control     = control;
+            _control = control;
             _pressedKeys = new HashSet<AvaKey>();
 
-            _control.KeyDown   += OnKeyPress;
-            _control.KeyUp     += OnKeyRelease;
+            _control.KeyDown += OnKeyPress;
+            _control.KeyUp += OnKeyRelease;
             _control.TextInput += Control_TextInput;
             _control.AddHandler(InputElement.TextInputEvent, Control_LastChanceTextInput, RoutingStrategies.Bubble);
         }
@@ -47,13 +47,13 @@ namespace Ryujinx.Ava.Input
 
         public event Action<string> OnGamepadConnected
         {
-            add    { }
+            add { }
             remove { }
         }
 
         public event Action<string> OnGamepadDisconnected
         {
-            add    { }
+            add { }
             remove { }
         }
 
@@ -71,7 +71,7 @@ namespace Ryujinx.Ava.Input
         {
             if (disposing)
             {
-                _control.KeyUp   -= OnKeyPress;
+                _control.KeyUp -= OnKeyPress;
                 _control.KeyDown -= OnKeyRelease;
             }
         }
@@ -112,4 +112,4 @@ namespace Ryujinx.Ava.Input
             Dispose(true);
         }
     }
-}
+}

+ 2 - 2
src/Ryujinx.Ava/Input/AvaloniaKeyboardMappingHelper.cs

@@ -143,7 +143,7 @@ namespace Ryujinx.Ava.Input
             AvaKey.OemBackslash,
 
             // NOTE: invalid
-            AvaKey.None
+            AvaKey.None,
         };
 
         private static readonly Dictionary<AvaKey, Key> _avaKeyMapping;
@@ -182,4 +182,4 @@ namespace Ryujinx.Ava.Input
             return _avaKeyMapping.GetValueOrDefault(key, Key.Unknown);
         }
     }
-}
+}

+ 5 - 5
src/Ryujinx.Ava/Input/AvaloniaMouse.cs

@@ -10,12 +10,12 @@ namespace Ryujinx.Ava.Input
     {
         private AvaloniaMouseDriver _driver;
 
-        public string Id   => "0";
+        public string Id => "0";
         public string Name => "AvaloniaMouse";
 
-        public bool                IsConnected => true;
-        public GamepadFeaturesFlag Features    => throw new NotImplementedException();
-        public bool[]              Buttons     => _driver.PressedButtons;
+        public bool IsConnected => true;
+        public GamepadFeaturesFlag Features => throw new NotImplementedException();
+        public bool[] Buttons => _driver.PressedButtons;
 
         public AvaloniaMouse(AvaloniaMouseDriver driver)
         {
@@ -84,4 +84,4 @@ namespace Ryujinx.Ava.Input
             _driver = null;
         }
     }
-}
+}

+ 22 - 22
src/Ryujinx.Ava/Input/AvaloniaMouseDriver.cs

@@ -11,16 +11,16 @@ namespace Ryujinx.Ava.Input
 {
     internal class AvaloniaMouseDriver : IGamepadDriver
     {
-        private Control           _widget;
-        private bool              _isDisposed;
-        private Size              _size;
+        private Control _widget;
+        private bool _isDisposed;
+        private Size _size;
         private readonly TopLevel _window;
 
-        public bool[]  PressedButtons  { get; }
+        public bool[] PressedButtons { get; }
         public Vector2 CurrentPosition { get; private set; }
-        public Vector2 Scroll          { get; private set; }
+        public Vector2 Scroll { get; private set; }
 
-        public string               DriverName  => "AvaloniaMouseDriver";
+        public string DriverName => "AvaloniaMouseDriver";
         public ReadOnlySpan<string> GamepadsIds => new[] { "0" };
 
         public AvaloniaMouseDriver(TopLevel window, Control parent)
@@ -28,14 +28,14 @@ namespace Ryujinx.Ava.Input
             _widget = parent;
             _window = window;
 
-            _widget.PointerMoved        += Parent_PointerMovedEvent;
-            _widget.PointerPressed      += Parent_PointerPressedEvent;
-            _widget.PointerReleased     += Parent_PointerReleasedEvent;
+            _widget.PointerMoved += Parent_PointerMovedEvent;
+            _widget.PointerPressed += Parent_PointerPressedEvent;
+            _widget.PointerReleased += Parent_PointerReleasedEvent;
             _widget.PointerWheelChanged += Parent_PointerWheelChanged;
-            
-            _window.PointerMoved        += Parent_PointerMovedEvent;
-            _window.PointerPressed      += Parent_PointerPressedEvent;
-            _window.PointerReleased     += Parent_PointerReleasedEvent;
+
+            _window.PointerMoved += Parent_PointerMovedEvent;
+            _window.PointerPressed += Parent_PointerPressedEvent;
+            _window.PointerReleased += Parent_PointerReleasedEvent;
             _window.PointerWheelChanged += Parent_PointerWheelChanged;
 
             PressedButtons = new bool[(int)MouseButton.Count];
@@ -47,13 +47,13 @@ namespace Ryujinx.Ava.Input
 
         public event Action<string> OnGamepadConnected
         {
-            add    { }
+            add { }
             remove { }
         }
 
         public event Action<string> OnGamepadDisconnected
         {
-            add    { }
+            add { }
             remove { }
         }
 
@@ -143,17 +143,17 @@ namespace Ryujinx.Ava.Input
 
             _isDisposed = true;
 
-            _widget.PointerMoved        -= Parent_PointerMovedEvent;
-            _widget.PointerPressed      -= Parent_PointerPressedEvent;
-            _widget.PointerReleased     -= Parent_PointerReleasedEvent;
+            _widget.PointerMoved -= Parent_PointerMovedEvent;
+            _widget.PointerPressed -= Parent_PointerPressedEvent;
+            _widget.PointerReleased -= Parent_PointerReleasedEvent;
             _widget.PointerWheelChanged -= Parent_PointerWheelChanged;
 
-            _window.PointerMoved        -= Parent_PointerMovedEvent;
-            _window.PointerPressed      -= Parent_PointerPressedEvent;
-            _window.PointerReleased     -= Parent_PointerReleasedEvent;
+            _window.PointerMoved -= Parent_PointerMovedEvent;
+            _window.PointerPressed -= Parent_PointerPressedEvent;
+            _window.PointerReleased -= Parent_PointerReleasedEvent;
             _window.PointerWheelChanged -= Parent_PointerWheelChanged;
 
             _widget = null;
         }
     }
-}
+}

+ 93 - 101
src/Ryujinx.Ava/Modules/Updater/Updater.cs

@@ -31,22 +31,22 @@ namespace Ryujinx.Modules
 {
     internal static class Updater
     {
-        private const string GitHubApiURL = "https://api.github.com";
-        private static readonly GithubReleasesJsonSerializerContext SerializerContext = new(JsonHelper.GetDefaultSerializerOptions());
+        private const string GitHubApiUrl = "https://api.github.com";
+        private static readonly GithubReleasesJsonSerializerContext _serializerContext = new(JsonHelper.GetDefaultSerializerOptions());
 
-        private static readonly string HomeDir          = AppDomain.CurrentDomain.BaseDirectory;
-        private static readonly string UpdateDir        = Path.Combine(Path.GetTempPath(), "Ryujinx", "update");
-        private static readonly string UpdatePublishDir = Path.Combine(UpdateDir, "publish");
-        private static readonly int    ConnectionCount  = 4;
+        private static readonly string _homeDir = AppDomain.CurrentDomain.BaseDirectory;
+        private static readonly string _updateDir = Path.Combine(Path.GetTempPath(), "Ryujinx", "update");
+        private static readonly string _updatePublishDir = Path.Combine(_updateDir, "publish");
+        private static readonly int _connectionCount = 4;
 
         private static string _buildVer;
         private static string _platformExt;
         private static string _buildUrl;
-        private static long   _buildSize;
-        private static bool   _updateSuccessful;
-        private static bool   _running;
+        private static long _buildSize;
+        private static bool _updateSuccessful;
+        private static bool _running;
 
-        private static readonly string[] WindowsDependencyDirs = Array.Empty<string>();
+        private static readonly string[] _windowsDependencyDirs = Array.Empty<string>();
 
         public static async Task BeginParse(Window mainWindow, bool showVersionUpToDate)
         {
@@ -99,9 +99,9 @@ namespace Ryujinx.Modules
             {
                 using HttpClient jsonClient = ConstructHttpClient();
 
-                string  buildInfoURL = $"{GitHubApiURL}/repos/{ReleaseInformation.ReleaseChannelOwner}/{ReleaseInformation.ReleaseChannelRepo}/releases/latest";
-                string  fetchedJson  = await jsonClient.GetStringAsync(buildInfoURL);
-                var fetched = JsonHelper.Deserialize(fetchedJson, SerializerContext.GithubReleasesJsonResponse);
+                string buildInfoUrl = $"{GitHubApiUrl}/repos/{ReleaseInformation.ReleaseChannelOwner}/{ReleaseInformation.ReleaseChannelRepo}/releases/latest";
+                string fetchedJson = await jsonClient.GetStringAsync(buildInfoUrl);
+                var fetched = JsonHelper.Deserialize(fetchedJson, _serializerContext.GithubReleasesJsonResponse);
                 _buildVer = fetched.Name;
 
                 foreach (var asset in fetched.Assets)
@@ -195,23 +195,21 @@ namespace Ryujinx.Modules
             }
 
             // Fetch build size information to learn chunk sizes.
-            using (HttpClient buildSizeClient = ConstructHttpClient())
+            using HttpClient buildSizeClient = ConstructHttpClient();
+            try
             {
-                try
-                {
-                    buildSizeClient.DefaultRequestHeaders.Add("Range", "bytes=0-0");
+                buildSizeClient.DefaultRequestHeaders.Add("Range", "bytes=0-0");
 
-                    HttpResponseMessage message = await buildSizeClient.GetAsync(new Uri(_buildUrl), HttpCompletionOption.ResponseHeadersRead);
+                HttpResponseMessage message = await buildSizeClient.GetAsync(new Uri(_buildUrl), HttpCompletionOption.ResponseHeadersRead);
 
-                    _buildSize = message.Content.Headers.ContentRange.Length.Value;
-                }
-                catch (Exception ex)
-                {
-                    Logger.Warning?.Print(LogClass.Application, ex.Message);
-                    Logger.Warning?.Print(LogClass.Application, "Couldn't determine build size for update, using single-threaded updater");
+                _buildSize = message.Content.Headers.ContentRange.Length.Value;
+            }
+            catch (Exception ex)
+            {
+                Logger.Warning?.Print(LogClass.Application, ex.Message);
+                Logger.Warning?.Print(LogClass.Application, "Couldn't determine build size for update, using single-threaded updater");
 
-                    _buildSize = -1;
-                }
+                _buildSize = -1;
             }
 
             Dispatcher.UIThread.Post(async () =>
@@ -248,23 +246,22 @@ namespace Ryujinx.Modules
             _updateSuccessful = false;
 
             // Empty update dir, although it shouldn't ever have anything inside it
-            if (Directory.Exists(UpdateDir))
+            if (Directory.Exists(_updateDir))
             {
-                Directory.Delete(UpdateDir, true);
+                Directory.Delete(_updateDir, true);
             }
 
-            Directory.CreateDirectory(UpdateDir);
+            Directory.CreateDirectory(_updateDir);
 
-            string updateFile = Path.Combine(UpdateDir, "update.bin");
+            string updateFile = Path.Combine(_updateDir, "update.bin");
 
             TaskDialog taskDialog = new()
             {
-                Header          = LocaleManager.Instance[LocaleKeys.RyujinxUpdater],
-                SubHeader       = LocaleManager.Instance[LocaleKeys.UpdaterDownloading],
-                IconSource      = new SymbolIconSource { Symbol = Symbol.Download },
-                Buttons         = { },
+                Header = LocaleManager.Instance[LocaleKeys.RyujinxUpdater],
+                SubHeader = LocaleManager.Instance[LocaleKeys.UpdaterDownloading],
+                IconSource = new SymbolIconSource { Symbol = Symbol.Download },
                 ShowProgressBar = true,
-                XamlRoot        = parent
+                XamlRoot = parent,
             };
 
             taskDialog.Opened += (s, e) =>
@@ -301,7 +298,7 @@ namespace Ryujinx.Modules
                     if (OperatingSystem.IsMacOS())
                     {
                         string baseBundlePath = Path.GetFullPath(Path.Combine(executableDirectory, "..", ".."));
-                        string newBundlePath = Path.Combine(UpdateDir, "Ryujinx.app");
+                        string newBundlePath = Path.Combine(_updateDir, "Ryujinx.app");
                         string updaterScriptPath = Path.Combine(newBundlePath, "Contents", "Resources", "updater.sh");
                         string currentPid = Environment.ProcessId.ToString();
 
@@ -328,7 +325,7 @@ namespace Ryujinx.Modules
                         ProcessStartInfo processStart = new(ryuName)
                         {
                             UseShellExecute = true,
-                            WorkingDirectory = executableDirectory
+                            WorkingDirectory = executableDirectory,
                         };
 
                         foreach (string argument in CommandLineState.Arguments)
@@ -347,22 +344,22 @@ namespace Ryujinx.Modules
         private static void DoUpdateWithMultipleThreads(TaskDialog taskDialog, string downloadUrl, string updateFile)
         {
             // Multi-Threaded Updater
-            long chunkSize      = _buildSize / ConnectionCount;
-            long remainderChunk = _buildSize % ConnectionCount;
+            long chunkSize = _buildSize / _connectionCount;
+            long remainderChunk = _buildSize % _connectionCount;
 
-            int   completedRequests       = 0;
-            int   totalProgressPercentage = 0;
-            int[] progressPercentage      = new int[ConnectionCount];
+            int completedRequests = 0;
+            int totalProgressPercentage = 0;
+            int[] progressPercentage = new int[_connectionCount];
 
-            List<byte[]>    list       = new(ConnectionCount);
-            List<WebClient> webClients = new(ConnectionCount);
+            List<byte[]> list = new(_connectionCount);
+            List<WebClient> webClients = new(_connectionCount);
 
-            for (int i = 0; i < ConnectionCount; i++)
+            for (int i = 0; i < _connectionCount; i++)
             {
                 list.Add(Array.Empty<byte>());
             }
 
-            for (int i = 0; i < ConnectionCount; i++)
+            for (int i = 0; i < _connectionCount; i++)
             {
 #pragma warning disable SYSLIB0014
                 // TODO: WebClient is obsolete and need to be replaced with a more complex logic using HttpClient.
@@ -371,7 +368,7 @@ namespace Ryujinx.Modules
 
                 webClients.Add(client);
 
-                if (i == ConnectionCount - 1)
+                if (i == _connectionCount - 1)
                 {
                     client.Headers.Add("Range", $"bytes={chunkSize * i}-{(chunkSize * (i + 1) - 1) + remainderChunk}");
                 }
@@ -388,7 +385,7 @@ namespace Ryujinx.Modules
                     Interlocked.Exchange(ref progressPercentage[index], args.ProgressPercentage);
                     Interlocked.Add(ref totalProgressPercentage, args.ProgressPercentage);
 
-                    taskDialog.SetProgressBarState(totalProgressPercentage / ConnectionCount, TaskDialogProgressState.Normal);
+                    taskDialog.SetProgressBarState(totalProgressPercentage / _connectionCount, TaskDialogProgressState.Normal);
                 };
 
                 client.DownloadDataCompleted += (_, args) =>
@@ -407,10 +404,10 @@ namespace Ryujinx.Modules
                     list[index] = args.Result;
                     Interlocked.Increment(ref completedRequests);
 
-                    if (Equals(completedRequests, ConnectionCount))
+                    if (Equals(completedRequests, _connectionCount))
                     {
                         byte[] mergedFileBytes = new byte[_buildSize];
-                        for (int connectionIndex = 0, destinationOffset = 0; connectionIndex < ConnectionCount; connectionIndex++)
+                        for (int connectionIndex = 0, destinationOffset = 0; connectionIndex < _connectionCount; connectionIndex++)
                         {
                             Array.Copy(list[connectionIndex], 0, mergedFileBytes, destinationOffset, list[connectionIndex].Length);
                             destinationOffset += list[connectionIndex].Length;
@@ -421,10 +418,9 @@ namespace Ryujinx.Modules
                         // On macOS, ensure that we remove the quarantine bit to prevent Gatekeeper from blocking execution.
                         if (OperatingSystem.IsMacOS())
                         {
-                            using (Process xattrProcess = Process.Start("xattr", new List<string> { "-d", "com.apple.quarantine", updateFile }))
-                            {
-                                xattrProcess.WaitForExit();
-                            }
+                            using Process xattrProcess = Process.Start("xattr", new List<string> { "-d", "com.apple.quarantine", updateFile });
+
+                            xattrProcess.WaitForExit();
                         }
 
                         try
@@ -437,8 +433,6 @@ namespace Ryujinx.Modules
                             Logger.Warning?.Print(LogClass.Application, "Multi-Threaded update failed, falling back to single-threaded updater.");
 
                             DoUpdateWithSingleThread(taskDialog, downloadUrl, updateFile);
-
-                            return;
                         }
                     }
                 };
@@ -470,31 +464,29 @@ namespace Ryujinx.Modules
             // We do not want to timeout while downloading
             client.Timeout = TimeSpan.FromDays(1);
 
-            using (HttpResponseMessage response         = client.GetAsync(downloadUrl, HttpCompletionOption.ResponseHeadersRead).Result)
-            using (Stream              remoteFileStream = response.Content.ReadAsStreamAsync().Result)
-            {
-                using Stream updateFileStream = File.Open(updateFile, FileMode.Create);
+            using HttpResponseMessage response = client.GetAsync(downloadUrl, HttpCompletionOption.ResponseHeadersRead).Result;
+            using Stream remoteFileStream = response.Content.ReadAsStreamAsync().Result;
+            using Stream updateFileStream = File.Open(updateFile, FileMode.Create);
 
-                long totalBytes  = response.Content.Headers.ContentLength.Value;
-                long byteWritten = 0;
+            long totalBytes = response.Content.Headers.ContentLength.Value;
+            long byteWritten = 0;
 
-                byte[] buffer = new byte[32 * 1024];
+            byte[] buffer = new byte[32 * 1024];
 
-                while (true)
-                {
-                    int readSize = remoteFileStream.Read(buffer);
+            while (true)
+            {
+                int readSize = remoteFileStream.Read(buffer);
 
-                    if (readSize == 0)
-                    {
-                        break;
-                    }
+                if (readSize == 0)
+                {
+                    break;
+                }
 
-                    byteWritten += readSize;
+                byteWritten += readSize;
 
-                    taskDialog.SetProgressBarState(GetPercentage(byteWritten, totalBytes), TaskDialogProgressState.Normal);
+                taskDialog.SetProgressBarState(GetPercentage(byteWritten, totalBytes), TaskDialogProgressState.Normal);
 
-                    updateFileStream.Write(buffer, 0, readSize);
-                }
+                updateFileStream.Write(buffer, 0, readSize);
             }
 
             InstallUpdate(taskDialog, updateFile);
@@ -510,7 +502,7 @@ namespace Ryujinx.Modules
         {
             Thread worker = new(() => DoUpdateWithSingleThreadWorker(taskDialog, downloadUrl, updateFile))
             {
-                Name = "Updater.SingleThreadWorker"
+                Name = "Updater.SingleThreadWorker",
             };
 
             worker.Start();
@@ -520,9 +512,9 @@ namespace Ryujinx.Modules
         [SupportedOSPlatform("macos")]
         private static void ExtractTarGzipFile(TaskDialog taskDialog, string archivePath, string outputDirectoryPath)
         {
-            using Stream          inStream   = File.OpenRead(archivePath);
+            using Stream inStream = File.OpenRead(archivePath);
             using GZipInputStream gzipStream = new(inStream);
-            using TarInputStream  tarStream  = new(gzipStream, Encoding.ASCII);
+            using TarInputStream tarStream = new(gzipStream, Encoding.ASCII);
 
             TarEntry tarEntry;
 
@@ -537,10 +529,8 @@ namespace Ryujinx.Modules
 
                 Directory.CreateDirectory(Path.GetDirectoryName(outPath));
 
-                using (FileStream outStream = File.OpenWrite(outPath))
-                {
-                    tarStream.CopyEntryContents(outStream);
-                }
+                using FileStream outStream = File.OpenWrite(outPath);
+                tarStream.CopyEntryContents(outStream);
 
                 File.SetUnixFileMode(outPath, (UnixFileMode)tarEntry.TarHeader.Mode);
                 File.SetLastWriteTime(outPath, DateTime.SpecifyKind(tarEntry.ModTime, DateTimeKind.Utc));
@@ -559,24 +549,26 @@ namespace Ryujinx.Modules
 
         private static void ExtractZipFile(TaskDialog taskDialog, string archivePath, string outputDirectoryPath)
         {
-            using Stream  inStream = File.OpenRead(archivePath);
-            using ZipFile zipFile  = new(inStream);
+            using Stream inStream = File.OpenRead(archivePath);
+            using ZipFile zipFile = new(inStream);
 
             double count = 0;
             foreach (ZipEntry zipEntry in zipFile)
             {
                 count++;
-                if (zipEntry.IsDirectory) continue;
+                if (zipEntry.IsDirectory)
+                {
+                    continue;
+                }
 
                 string outPath = Path.Combine(outputDirectoryPath, zipEntry.Name);
 
                 Directory.CreateDirectory(Path.GetDirectoryName(outPath));
 
-                using (Stream     zipStream = zipFile.GetInputStream(zipEntry))
-                using (FileStream outStream = File.OpenWrite(outPath))
-                {
-                    zipStream.CopyTo(outStream);
-                }
+                using Stream zipStream = zipFile.GetInputStream(zipEntry);
+                using FileStream outStream = File.OpenWrite(outPath);
+
+                zipStream.CopyTo(outStream);
 
                 File.SetLastWriteTime(outPath, DateTime.SpecifyKind(zipEntry.DateTime, DateTimeKind.Utc));
 
@@ -597,11 +589,11 @@ namespace Ryujinx.Modules
             {
                 if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS())
                 {
-                    ExtractTarGzipFile(taskDialog, updateFile, UpdateDir);
+                    ExtractTarGzipFile(taskDialog, updateFile, _updateDir);
                 }
                 else if (OperatingSystem.IsWindows())
                 {
-                    ExtractZipFile(taskDialog, updateFile, UpdateDir);
+                    ExtractZipFile(taskDialog, updateFile, _updateDir);
                 }
                 else
                 {
@@ -648,10 +640,10 @@ namespace Ryujinx.Modules
                         taskDialog.SetProgressBarState(0, TaskDialogProgressState.Normal);
                     });
 
-                    MoveAllFilesOver(UpdatePublishDir, HomeDir, taskDialog);
+                    MoveAllFilesOver(_updatePublishDir, _homeDir, taskDialog);
                 });
 
-                Directory.Delete(UpdateDir, true);
+                Directory.Delete(_updateDir, true);
             }
 
             _updateSuccessful = true;
@@ -738,15 +730,15 @@ namespace Ryujinx.Modules
         // NOTE: This method should always reflect the latest build layout.
         private static IEnumerable<string> EnumerateFilesToDelete()
         {
-            var files = Directory.EnumerateFiles(HomeDir); // All files directly in base dir.
+            var files = Directory.EnumerateFiles(_homeDir); // All files directly in base dir.
 
             // Determine and exclude user files only when the updater is running, not when cleaning old files
             if (_running && !OperatingSystem.IsMacOS())
             {
                 // Compare the loose files in base directory against the loose files from the incoming update, and store foreign ones in a user list.
-                var oldFiles = Directory.EnumerateFiles(HomeDir, "*", SearchOption.TopDirectoryOnly).Select(Path.GetFileName);
-                var newFiles = Directory.EnumerateFiles(UpdatePublishDir, "*", SearchOption.TopDirectoryOnly).Select(Path.GetFileName);
-                var userFiles = oldFiles.Except(newFiles).Select(filename => Path.Combine(HomeDir, filename));
+                var oldFiles = Directory.EnumerateFiles(_homeDir, "*", SearchOption.TopDirectoryOnly).Select(Path.GetFileName);
+                var newFiles = Directory.EnumerateFiles(_updatePublishDir, "*", SearchOption.TopDirectoryOnly).Select(Path.GetFileName);
+                var userFiles = oldFiles.Except(newFiles).Select(filename => Path.Combine(_homeDir, filename));
 
                 // Remove user files from the paths in files.
                 files = files.Except(userFiles);
@@ -754,9 +746,9 @@ namespace Ryujinx.Modules
 
             if (OperatingSystem.IsWindows())
             {
-                foreach (string dir in WindowsDependencyDirs)
+                foreach (string dir in _windowsDependencyDirs)
                 {
-                    string dirPath = Path.Combine(HomeDir, dir);
+                    string dirPath = Path.Combine(_homeDir, dir);
                     if (Directory.Exists(dirPath))
                     {
                         files = files.Concat(Directory.EnumerateFiles(dirPath, "*", SearchOption.AllDirectories));
@@ -798,10 +790,10 @@ namespace Ryujinx.Modules
 
         public static void CleanupUpdate()
         {
-            foreach (string file in Directory.GetFiles(HomeDir, "*.ryuold", SearchOption.AllDirectories))
+            foreach (string file in Directory.GetFiles(_homeDir, "*.ryuold", SearchOption.AllDirectories))
             {
                 File.Delete(file);
             }
         }
     }
-}
+}

+ 16 - 16
src/Ryujinx.Ava/Program.cs

@@ -22,16 +22,16 @@ namespace Ryujinx.Ava
 {
     internal partial class Program
     {
-        public static double WindowScaleFactor  { get; set; }
+        public static double WindowScaleFactor { get; set; }
         public static double DesktopScaleFactor { get; set; } = 1.0;
-        public static string Version            { get; private set; }
-        public static string ConfigurationPath  { get; private set; }
-        public static bool   PreviewerDetached  { get; private set; }
+        public static string Version { get; private set; }
+        public static string ConfigurationPath { get; private set; }
+        public static bool PreviewerDetached { get; private set; }
 
         [LibraryImport("user32.dll", SetLastError = true)]
         public static partial int MessageBoxA(IntPtr hWnd, [MarshalAs(UnmanagedType.LPStr)] string text, [MarshalAs(UnmanagedType.LPStr)] string caption, uint type);
 
-        private const uint MB_ICONWARNING = 0x30;
+        private const uint MbIconwarning = 0x30;
 
         public static void Main(string[] args)
         {
@@ -39,7 +39,7 @@ namespace Ryujinx.Ava
 
             if (OperatingSystem.IsWindows() && !OperatingSystem.IsWindowsVersionAtLeast(10, 0, 17134))
             {
-                _ = MessageBoxA(IntPtr.Zero, "You are running an outdated version of Windows.\n\nStarting on June 1st 2022, Ryujinx will only support Windows 10 1803 and newer.\n", $"Ryujinx {Version}", MB_ICONWARNING);
+                _ = MessageBoxA(IntPtr.Zero, "You are running an outdated version of Windows.\n\nStarting on June 1st 2022, Ryujinx will only support Windows 10 1803 and newer.\n", $"Ryujinx {Version}", MbIconwarning);
             }
 
             PreviewerDetached = true;
@@ -58,15 +58,15 @@ namespace Ryujinx.Ava
                 .With(new X11PlatformOptions
                 {
                     EnableMultiTouch = true,
-                    EnableIme        = true,
-                    UseEGL           = false,
-                    UseGpu           = true
+                    EnableIme = true,
+                    UseEGL = false,
+                    UseGpu = true,
                 })
                 .With(new Win32PlatformOptions
                 {
-                    EnableMultitouch                = true,
-                    UseWgl                          = false,
-                    AllowEglInitialization          = false,
+                    EnableMultitouch = true,
+                    UseWgl = false,
+                    AllowEglInitialization = false,
                     CompositionBackdropCornerRadius = 8.0f,
                 })
                 .UseSkia();
@@ -84,7 +84,7 @@ namespace Ryujinx.Ava
 
             // Hook unhandled exception and process exit events.
             AppDomain.CurrentDomain.UnhandledException += (sender, e) => ProcessUnhandledException(e.ExceptionObject as Exception, e.IsTerminating);
-            AppDomain.CurrentDomain.ProcessExit        += (sender, e) => Exit();
+            AppDomain.CurrentDomain.ProcessExit += (sender, e) => Exit();
 
             // Setup base data directory.
             AppDataManager.Initialize(CommandLineState.BaseDirPathArg);
@@ -130,7 +130,7 @@ namespace Ryujinx.Ava
 
         public static void ReloadConfig()
         {
-            string localConfigurationPath   = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Config.json");
+            string localConfigurationPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Config.json");
             string appDataConfigurationPath = Path.Combine(AppDataManager.BaseDirPath, "Config.json");
 
             // Now load the configuration as the other subsystems are now registered
@@ -192,7 +192,7 @@ namespace Ryujinx.Ava
                     "never" => HideCursorMode.Never,
                     "onidle" => HideCursorMode.OnIdle,
                     "always" => HideCursorMode.Always,
-                    _ => ConfigurationState.Instance.HideCursor.Value
+                    _ => ConfigurationState.Instance.HideCursor.Value,
                 };
             }
         }
@@ -238,4 +238,4 @@ namespace Ryujinx.Ava
             Logger.Shutdown();
         }
     }
-}
+}

+ 5 - 8
src/Ryujinx.Ava/UI/Applet/AvaHostUiHandler.cs

@@ -64,7 +64,7 @@ namespace Ryujinx.Ava.UI.Applet
                        LocaleManager.Instance[LocaleKeys.SettingsButtonClose],
                        (int)Symbol.Important,
                        deferEvent,
-                       async (window) =>
+                       async window =>
                        {
                            if (opened)
                            {
@@ -112,7 +112,7 @@ namespace Ryujinx.Ava.UI.Applet
             {
                 try
                 {
-                    var response = await SwkbdAppletDialog.ShowInputDialog(_parent, LocaleManager.Instance[LocaleKeys.SoftwareKeyboard], args);
+                    var response = await SwkbdAppletDialog.ShowInputDialog(LocaleManager.Instance[LocaleKeys.SoftwareKeyboard], args);
 
                     if (response.Result == UserResult.Ok)
                     {
@@ -142,10 +142,7 @@ namespace Ryujinx.Ava.UI.Applet
         public void ExecuteProgram(Switch device, ProgramSpecifyKind kind, ulong value)
         {
             device.Configuration.UserChannelPersistence.ExecuteProgram(kind, value);
-            if (_parent.ViewModel.AppHost != null)
-            {
-                _parent.ViewModel.AppHost.Stop();
-            }
+            _parent.ViewModel.AppHost?.Stop();
         }
 
         public bool DisplayErrorAppletDialog(string title, string message, string[] buttons)
@@ -162,7 +159,7 @@ namespace Ryujinx.Ava.UI.Applet
                     {
                         Title = title,
                         WindowStartupLocation = WindowStartupLocation.CenterScreen,
-                        Width = 400
+                        Width = 400,
                     };
 
                     object response = await msgDialog.Run();
@@ -194,4 +191,4 @@ namespace Ryujinx.Ava.UI.Applet
             return new AvaloniaDynamicTextInputHandler(_parent);
         }
     }
-}
+}

+ 3 - 5
src/Ryujinx.Ava/UI/Applet/AvaloniaDynamicTextInputHandler.cs

@@ -3,13 +3,11 @@ using Avalonia.Controls;
 using Avalonia.Input;
 using Avalonia.Threading;
 using Ryujinx.Ava.Input;
-using Ryujinx.Ava.UI.Controls;
 using Ryujinx.Ava.UI.Helpers;
 using Ryujinx.Ava.UI.Windows;
 using Ryujinx.HLE.Ui;
 using System;
 using System.Threading;
-
 using HidKey = Ryujinx.Common.Configuration.Hid.Key;
 
 namespace Ryujinx.Ava.UI.Applet
@@ -17,7 +15,7 @@ namespace Ryujinx.Ava.UI.Applet
     class AvaloniaDynamicTextInputHandler : IDynamicTextInputHandler
     {
         private MainWindow _parent;
-        private OffscreenTextBox _hiddenTextBox;
+        private readonly OffscreenTextBox _hiddenTextBox;
         private bool _canProcessInput;
         private IDisposable _textChangedSubscription;
         private IDisposable _selectionStartChangedSubscription;
@@ -76,7 +74,7 @@ namespace Ryujinx.Ava.UI.Applet
                 return;
             }
 
-            e.RoutedEvent = _hiddenTextBox.GetKeyUpRoutedEvent();
+            e.RoutedEvent = OffscreenTextBox.GetKeyUpRoutedEvent();
 
             Dispatcher.UIThread.InvokeAsync(() =>
             {
@@ -96,7 +94,7 @@ namespace Ryujinx.Ava.UI.Applet
                 return;
             }
 
-            e.RoutedEvent = _hiddenTextBox.GetKeyUpRoutedEvent();
+            e.RoutedEvent = OffscreenTextBox.GetKeyUpRoutedEvent();
 
             Dispatcher.UIThread.InvokeAsync(() =>
             {

+ 4 - 6
src/Ryujinx.Ava/UI/Applet/AvaloniaHostUiTheme.cs

@@ -9,7 +9,7 @@ namespace Ryujinx.Ava.UI.Applet
     {
         public AvaloniaHostUiTheme(MainWindow parent)
         {
-            FontFamily = OperatingSystem.IsWindows() && OperatingSystem.IsWindowsVersionAtLeast(10, 0, 22000, 0) ? "Segoe UI Variable" : parent.FontFamily.Name;
+            FontFamily = OperatingSystem.IsWindows() && OperatingSystem.IsWindowsVersionAtLeast(10, 0, 22000) ? "Segoe UI Variable" : parent.FontFamily.Name;
             DefaultBackgroundColor = BrushToThemeColor(parent.Background);
             DefaultForegroundColor = BrushToThemeColor(parent.Foreground);
             DefaultBorderColor = BrushToThemeColor(parent.BorderBrush);
@@ -25,7 +25,7 @@ namespace Ryujinx.Ava.UI.Applet
         public ThemeColor SelectionBackgroundColor { get; }
         public ThemeColor SelectionForegroundColor { get; }
 
-        private ThemeColor BrushToThemeColor(IBrush brush)
+        private static ThemeColor BrushToThemeColor(IBrush brush)
         {
             if (brush is SolidColorBrush solidColor)
             {
@@ -34,10 +34,8 @@ namespace Ryujinx.Ava.UI.Applet
                     (float)solidColor.Color.G / 255,
                     (float)solidColor.Color.B / 255);
             }
-            else
-            {
-                return new ThemeColor();
-            }
+
+            return new ThemeColor();
         }
     }
 }

+ 4 - 2
src/Ryujinx.Ava/UI/Applet/ErrorAppletWindow.axaml.cs

@@ -1,10 +1,12 @@
-using Avalonia;
 using Avalonia.Controls;
 using Avalonia.Interactivity;
 using Avalonia.Threading;
 using Ryujinx.Ava.Common.Locale;
 using Ryujinx.Ava.UI.Windows;
 using System.Threading.Tasks;
+#if DEBUG
+using Avalonia;
+#endif
 
 namespace Ryujinx.Ava.UI.Applet
 {
@@ -77,4 +79,4 @@ namespace Ryujinx.Ava.UI.Applet
             return _buttonResponse;
         }
     }
-}
+}

+ 9 - 11
src/Ryujinx.Ava/UI/Applet/SwkbdAppletDialog.axaml.cs

@@ -1,13 +1,10 @@
-using Avalonia;
 using Avalonia.Controls;
 using Avalonia.Input;
 using Avalonia.Interactivity;
 using Avalonia.Media;
-using FluentAvalonia.Core;
 using FluentAvalonia.UI.Controls;
 using Ryujinx.Ava.Common.Locale;
 using Ryujinx.Ava.UI.Helpers;
-using Ryujinx.Ava.UI.Windows;
 using Ryujinx.HLE.HOS.Applets;
 using Ryujinx.HLE.HOS.Applets.SoftwareKeyboard;
 using System;
@@ -22,7 +19,7 @@ namespace Ryujinx.Ava.UI.Controls
         private Predicate<string> _checkInput = _ => true;
         private int _inputMax;
         private int _inputMin;
-        private string _placeholder;
+        private readonly string _placeholder;
 
         private ContentDialog _host;
 
@@ -57,13 +54,13 @@ namespace Ryujinx.Ava.UI.Controls
         public string MainText { get; set; } = "";
         public string SecondaryText { get; set; } = "";
 
-        public static async Task<(UserResult Result, string Input)> ShowInputDialog(StyleableWindow window, string title, SoftwareKeyboardUiArgs args)
+        public static async Task<(UserResult Result, string Input)> ShowInputDialog(string title, SoftwareKeyboardUiArgs args)
         {
-            ContentDialog contentDialog = new ContentDialog();
+            ContentDialog contentDialog = new();
 
             UserResult result = UserResult.Cancel;
 
-            SwkbdAppletDialog content = new SwkbdAppletDialog(args.HeaderText, args.SubtitleText, args.GuideText, args.InitialText);
+            SwkbdAppletDialog content = new(args.HeaderText, args.SubtitleText, args.GuideText, args.InitialText);
 
             string input = string.Empty;
 
@@ -78,15 +75,16 @@ namespace Ryujinx.Ava.UI.Controls
             contentDialog.CloseButtonText = LocaleManager.Instance[LocaleKeys.InputDialogCancel];
             contentDialog.Content = content;
 
-            TypedEventHandler<ContentDialog, ContentDialogClosedEventArgs> handler = (sender, eventArgs) =>
+            void Handler(ContentDialog sender, ContentDialogClosedEventArgs eventArgs)
             {
                 if (eventArgs.Result == ContentDialogResult.Primary)
                 {
                     result = UserResult.Ok;
                     input = content.Input.Text;
                 }
-            };
-            contentDialog.Closed += handler;
+            }
+
+            contentDialog.Closed += Handler;
 
             await ContentDialogHelper.ShowAsync(contentDialog);
 
@@ -182,4 +180,4 @@ namespace Ryujinx.Ava.UI.Controls
             }
         }
     }
-}
+}

+ 2 - 3
src/Ryujinx.Ava/UI/Controls/ApplicationContextMenu.axaml.cs

@@ -18,7 +18,6 @@ using System.Collections.Generic;
 using System.Globalization;
 using System.IO;
 using Path = System.IO.Path;
-using UserId = LibHac.Fs.UserId;
 
 namespace Ryujinx.Ava.UI.Controls
 {
@@ -53,7 +52,7 @@ namespace Ryujinx.Ava.UI.Controls
 
         public void OpenUserSaveDirectory_Click(object sender, RoutedEventArgs args)
         {
-            if ((sender as MenuItem)?.DataContext is MainWindowViewModel viewModel)
+            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));
             }
@@ -334,4 +333,4 @@ namespace Ryujinx.Ava.UI.Controls
             }
         }
     }
-}
+}

+ 1 - 1
src/Ryujinx.Ava/UI/Controls/ApplicationGridView.axaml.cs

@@ -16,7 +16,7 @@ namespace Ryujinx.Ava.UI.Controls
 
         public event EventHandler<ApplicationOpenedEventArgs> ApplicationOpened
         {
-            add    { AddHandler(ApplicationOpenedEvent,    value); }
+            add { AddHandler(ApplicationOpenedEvent, value); }
             remove { RemoveHandler(ApplicationOpenedEvent, value); }
         }
 

+ 1 - 1
src/Ryujinx.Ava/UI/Controls/ApplicationListView.axaml.cs

@@ -16,7 +16,7 @@ namespace Ryujinx.Ava.UI.Controls
 
         public event EventHandler<ApplicationOpenedEventArgs> ApplicationOpened
         {
-            add    { AddHandler(ApplicationOpenedEvent,    value); }
+            add { AddHandler(ApplicationOpenedEvent, value); }
             remove { RemoveHandler(ApplicationOpenedEvent, value); }
         }
 

+ 10 - 11
src/Ryujinx.Ava/UI/Controls/NavigationDialogHost.axaml.cs

@@ -2,7 +2,6 @@ using Avalonia;
 using Avalonia.Controls;
 using Avalonia.Styling;
 using Avalonia.Threading;
-using FluentAvalonia.Core;
 using FluentAvalonia.UI.Controls;
 using LibHac;
 using LibHac.Common;
@@ -10,7 +9,6 @@ using LibHac.Fs;
 using LibHac.Fs.Shim;
 using Ryujinx.Ava.Common.Locale;
 using Ryujinx.Ava.UI.Helpers;
-using Ryujinx.Ava.UI.Models;
 using Ryujinx.Ava.UI.ViewModels;
 using Ryujinx.Ava.UI.Views.User;
 using Ryujinx.HLE.FileSystem;
@@ -19,6 +17,7 @@ using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Threading.Tasks;
+using UserId = Ryujinx.HLE.HOS.Services.Account.Acc.UserId;
 using UserProfile = Ryujinx.Ava.UI.Models.UserProfile;
 
 namespace Ryujinx.Ava.UI.Controls
@@ -56,7 +55,7 @@ namespace Ryujinx.Ava.UI.Controls
             InitializeComponent();
         }
 
-        public void GoBack(object parameter = null)
+        public void GoBack()
         {
             if (ContentFrame.BackStack.Count > 0)
             {
@@ -75,14 +74,14 @@ namespace Ryujinx.Ava.UI.Controls
             VirtualFileSystem ownerVirtualFileSystem, HorizonClient ownerHorizonClient)
         {
             var content = new NavigationDialogHost(ownerAccountManager, ownerContentManager, ownerVirtualFileSystem, ownerHorizonClient);
-            ContentDialog contentDialog = new ContentDialog
+            ContentDialog contentDialog = new()
             {
                 Title = LocaleManager.Instance[LocaleKeys.UserProfileWindowTitle],
                 PrimaryButtonText = "",
                 SecondaryButtonText = "",
                 CloseButtonText = "",
                 Content = content,
-                Padding = new Thickness(0)
+                Padding = new Thickness(0),
             };
 
             contentDialog.Closed += (sender, args) =>
@@ -125,7 +124,7 @@ namespace Ryujinx.Ava.UI.Controls
 
             Span<SaveDataInfo> saveDataInfo = stackalloc SaveDataInfo[10];
 
-            HashSet<HLE.HOS.Services.Account.Acc.UserId> lostAccounts = new();
+            HashSet<UserId> lostAccounts = new();
 
             while (true)
             {
@@ -139,15 +138,15 @@ namespace Ryujinx.Ava.UI.Controls
                 for (int i = 0; i < readCount; i++)
                 {
                     var save = saveDataInfo[i];
-                    var id = new HLE.HOS.Services.Account.Acc.UserId((long)save.UserId.Id.Low, (long)save.UserId.Id.High);
-                    if (ViewModel.Profiles.Cast<UserProfile>().FirstOrDefault( x=> x.UserId == id) == null)
+                    var id = new UserId((long)save.UserId.Id.Low, (long)save.UserId.Id.High);
+                    if (ViewModel.Profiles.Cast<UserProfile>().FirstOrDefault(x => x.UserId == id) == null)
                     {
                         lostAccounts.Add(id);
                     }
                 }
             }
 
-            foreach(var account in lostAccounts)
+            foreach (var account in lostAccounts)
             {
                 ViewModel.LostProfiles.Add(new UserProfile(new HLE.HOS.Services.Account.Acc.UserProfile(account, "", null), this));
             }
@@ -166,7 +165,7 @@ namespace Ryujinx.Ava.UI.Controls
 
                 if (profile == null)
                 {
-                    async void Action()
+                    static async void Action()
                     {
                         await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance[LocaleKeys.DialogUserProfileDeletionWarningMessage]);
                     }
@@ -215,4 +214,4 @@ namespace Ryujinx.Ava.UI.Controls
             Navigate(typeof(UserSaveManagerView), (this, AccountManager, HorizonClient, VirtualFileSystem));
         }
     }
-}
+}

+ 1 - 1
src/Ryujinx.Ava/UI/Controls/UpdateWaitWindow.axaml.cs

@@ -28,4 +28,4 @@ namespace Ryujinx.Ava.UI.Controls
             InitializeComponent();
         }
     }
-}
+}

+ 1 - 1
src/Ryujinx.Ava/UI/Helpers/ApplicationOpenedEventArgs.cs

@@ -13,4 +13,4 @@ namespace Ryujinx.Ava.UI.Helpers
             RoutedEvent = routedEvent;
         }
     }
-}
+}

+ 1 - 1
src/Ryujinx.Ava/UI/Helpers/BitmapArrayValueConverter.cs

@@ -33,4 +33,4 @@ namespace Ryujinx.Ava.UI.Helpers
             throw new NotSupportedException();
         }
     }
-}
+}

+ 1 - 1
src/Ryujinx.Ava/UI/Helpers/ButtonKeyAssigner.cs

@@ -23,7 +23,7 @@ namespace Ryujinx.Ava.UI.Helpers
                 IsAssigned = isAssigned;
             }
         }
-        
+
         public ToggleButton ToggledButton { get; set; }
 
         private bool _isWaitingForInput;

+ 29 - 32
src/Ryujinx.Ava/UI/Helpers/ContentDialogHelper.cs

@@ -1,6 +1,7 @@
 using Avalonia;
 using Avalonia.Controls;
 using Avalonia.Controls.ApplicationLifetimes;
+using Avalonia.Layout;
 using Avalonia.Media;
 using Avalonia.Threading;
 using FluentAvalonia.Core;
@@ -32,18 +33,17 @@ namespace Ryujinx.Ava.UI.Helpers
 
             ContentDialog contentDialog = new()
             {
-                Title               = title,
-                PrimaryButtonText   = primaryButton,
+                Title = title,
+                PrimaryButtonText = primaryButton,
                 SecondaryButtonText = secondaryButton,
-                CloseButtonText     = closeButton,
-                Content             = content
+                CloseButtonText = closeButton,
+                Content = content,
+                PrimaryButtonCommand = MiniCommand.Create(() =>
+                {
+                    result = primaryButtonResult;
+                }),
             };
 
-            contentDialog.PrimaryButtonCommand = MiniCommand.Create(() =>
-            {
-                result = primaryButtonResult;
-            });
-
             contentDialog.SecondaryButtonCommand = MiniCommand.Create(() =>
             {
                 result = UserResult.No;
@@ -96,7 +96,6 @@ namespace Ryujinx.Ava.UI.Helpers
             Func<Window, Task> doWhileDeferred = null)
         {
             bool startedDeferring = false;
-            UserResult result = UserResult.None;
 
             return await ShowTextDialog(
                 title,
@@ -123,8 +122,6 @@ namespace Ryujinx.Ava.UI.Helpers
 
                 var deferral = args.GetDeferral();
 
-                result = primaryButton == LocaleManager.Instance[LocaleKeys.InputDialogYes] ? UserResult.Yes : UserResult.Ok;
-
                 sender.PrimaryButtonClick -= DeferClose;
 
                 _ = Task.Run(() =>
@@ -150,18 +147,18 @@ namespace Ryujinx.Ava.UI.Helpers
         {
             Grid content = new()
             {
-                RowDefinitions    = new RowDefinitions()    { new RowDefinition(), new RowDefinition() },
-                ColumnDefinitions = new ColumnDefinitions() { new ColumnDefinition(GridLength.Auto), new ColumnDefinition() },
+                RowDefinitions = new RowDefinitions { new(), new() },
+                ColumnDefinitions = new ColumnDefinitions { new(GridLength.Auto), new() },
 
-                MinHeight = 80
+                MinHeight = 80,
             };
 
             SymbolIcon icon = new()
             {
-                Symbol            = (Symbol)symbol,
-                Margin            = new Thickness(10),
-                FontSize          = 40,
-                VerticalAlignment = Avalonia.Layout.VerticalAlignment.Center
+                Symbol = (Symbol)symbol,
+                Margin = new Thickness(10),
+                FontSize = 40,
+                VerticalAlignment = VerticalAlignment.Center,
             };
 
             Grid.SetColumn(icon, 0);
@@ -170,18 +167,18 @@ namespace Ryujinx.Ava.UI.Helpers
 
             TextBlock primaryLabel = new()
             {
-                Text         = primaryText,
-                Margin       = new Thickness(5),
+                Text = primaryText,
+                Margin = new Thickness(5),
                 TextWrapping = TextWrapping.Wrap,
-                MaxWidth     = 450
+                MaxWidth = 450,
             };
 
             TextBlock secondaryLabel = new()
             {
-                Text         = secondaryText,
-                Margin       = new Thickness(5),
+                Text = secondaryText,
+                Margin = new Thickness(5),
                 TextWrapping = TextWrapping.Wrap,
-                MaxWidth     = 450
+                MaxWidth = 450,
             };
 
             Grid.SetColumn(primaryLabel, 1);
@@ -318,14 +315,14 @@ namespace Ryujinx.Ava.UI.Helpers
 
             Window parent = GetMainWindow();
 
-            if (parent != null && parent.IsActive && (parent as MainWindow).ViewModel.IsGameRunning)
+            if (parent is { IsActive: true } and MainWindow window && window.ViewModel.IsGameRunning)
             {
                 contentDialogOverlayWindow = new()
                 {
-                    Height        = parent.Bounds.Height,
-                    Width         = parent.Bounds.Width,
-                    Position      = parent.PointToScreen(new Point()),
-                    ShowInTaskbar = false
+                    Height = parent.Bounds.Height,
+                    Width = parent.Bounds.Width,
+                    Position = parent.PointToScreen(new Point()),
+                    ShowInTaskbar = false,
                 };
 
                 parent.PositionChanged += OverlayOnPositionChanged;
@@ -389,7 +386,7 @@ namespace Ryujinx.Ava.UI.Helpers
 
         private static Window GetMainWindow()
         {
-            if (Application.Current.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime al)
+            if (Application.Current?.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime al)
             {
                 foreach (Window item in al.Windows)
                 {
@@ -403,4 +400,4 @@ namespace Ryujinx.Ava.UI.Helpers
             return null;
         }
     }
-}
+}

+ 9 - 8
src/Ryujinx.Ava/UI/Helpers/GlyphValueConverter.cs

@@ -1,5 +1,6 @@
 using Avalonia.Data;
 using Avalonia.Markup.Xaml;
+using Avalonia.Markup.Xaml.MarkupExtensions;
 using FluentAvalonia.UI.Controls;
 using System;
 using System.Collections.Generic;
@@ -8,13 +9,13 @@ namespace Ryujinx.Ava.UI.Helpers
 {
     public class GlyphValueConverter : MarkupExtension
     {
-        private string _key;
+        private readonly string _key;
 
-        private static Dictionary<Glyph, string> _glyphs = new Dictionary<Glyph, string>
+        private static readonly Dictionary<Glyph, string> _glyphs = new()
         {
-            { Glyph.List, char.ConvertFromUtf32((int)Symbol.List).ToString() },
-            { Glyph.Grid, char.ConvertFromUtf32((int)Symbol.ViewAll).ToString() },
-            { Glyph.Chip, char.ConvertFromUtf32(59748).ToString() }
+            { Glyph.List, char.ConvertFromUtf32((int)Symbol.List) },
+            { Glyph.Grid, char.ConvertFromUtf32((int)Symbol.ViewAll) },
+            { Glyph.Chip, char.ConvertFromUtf32(59748) },
         };
 
         public GlyphValueConverter(string key)
@@ -37,13 +38,13 @@ namespace Ryujinx.Ava.UI.Helpers
 
         public override object ProvideValue(IServiceProvider serviceProvider)
         {
-            Avalonia.Markup.Xaml.MarkupExtensions.ReflectionBindingExtension binding = new($"[{_key}]")
+            ReflectionBindingExtension binding = new($"[{_key}]")
             {
                 Mode = BindingMode.OneWay,
-                Source = this
+                Source = this,
             };
 
             return binding.ProvideValue(serviceProvider);
         }
     }
-}
+}

+ 1 - 1
src/Ryujinx.Ava/UI/Helpers/HotKeyControl.cs

@@ -49,4 +49,4 @@ namespace Ryujinx.Ava.UI.Helpers
             }
         }
     }
-}
+}

+ 1 - 1
src/Ryujinx.Ava/UI/Helpers/KeyValueConverter.cs

@@ -43,4 +43,4 @@ namespace Ryujinx.Ava.UI.Helpers
             return key;
         }
     }
-}
+}

+ 15 - 13
src/Ryujinx.Ava/UI/Helpers/LoggerAdapter.cs

@@ -1,15 +1,17 @@
+using Avalonia.Logging;
 using Avalonia.Utilities;
+using Ryujinx.Common.Logging;
 using System;
 using System.Text;
 
 namespace Ryujinx.Ava.UI.Helpers
 {
-    using AvaLogger   = Avalonia.Logging.Logger;
-    using AvaLogLevel = Avalonia.Logging.LogEventLevel;
-    using RyuLogClass = Ryujinx.Common.Logging.LogClass;
-    using RyuLogger   = Ryujinx.Common.Logging.Logger;
+    using AvaLogger = Avalonia.Logging.Logger;
+    using AvaLogLevel = LogEventLevel;
+    using RyuLogClass = LogClass;
+    using RyuLogger = Ryujinx.Common.Logging.Logger;
 
-    internal class LoggerAdapter : Avalonia.Logging.ILogSink
+    internal class LoggerAdapter : ILogSink
     {
         public static void Register()
         {
@@ -20,13 +22,13 @@ namespace Ryujinx.Ava.UI.Helpers
         {
             return level switch
             {
-                AvaLogLevel.Verbose     => RyuLogger.Debug,
-                AvaLogLevel.Debug       => RyuLogger.Debug,
+                AvaLogLevel.Verbose => RyuLogger.Debug,
+                AvaLogLevel.Debug => RyuLogger.Debug,
                 AvaLogLevel.Information => RyuLogger.Debug,
-                AvaLogLevel.Warning     => RyuLogger.Debug,
-                AvaLogLevel.Error       => RyuLogger.Error,
-                AvaLogLevel.Fatal       => RyuLogger.Error,
-                _ => throw new ArgumentOutOfRangeException(nameof(level), level, null)
+                AvaLogLevel.Warning => RyuLogger.Debug,
+                AvaLogLevel.Error => RyuLogger.Error,
+                AvaLogLevel.Fatal => RyuLogger.Error,
+                _ => throw new ArgumentOutOfRangeException(nameof(level), level, null),
             };
         }
 
@@ -45,7 +47,7 @@ namespace Ryujinx.Ava.UI.Helpers
             GetLog(level)?.PrintMsg(RyuLogClass.Ui, Format(level, area, messageTemplate, source, new object[] { propertyValue0 }));
         }
 
-        public void Log<T0, T1>(AvaLogLevel level, string area, object source, string messageTemplate, T0 propertyValue0,  T1 propertyValue1)
+        public void Log<T0, T1>(AvaLogLevel level, string area, object source, string messageTemplate, T0 propertyValue0, T1 propertyValue1)
         {
             GetLog(level)?.PrintMsg(RyuLogClass.Ui, Format(level, area, messageTemplate, source, new object[] { propertyValue0, propertyValue1 }));
         }
@@ -112,4 +114,4 @@ namespace Ryujinx.Ava.UI.Helpers
             return result.ToString();
         }
     }
-}
+}

+ 2 - 2
src/Ryujinx.Ava/UI/Helpers/MiniCommand.cs

@@ -8,7 +8,7 @@ namespace Ryujinx.Ava.UI.Helpers
     {
         private readonly Action<T> _callback;
         private bool _busy;
-        private Func<T, Task> _asyncCallback;
+        private readonly Func<T, Task> _asyncCallback;
 
         public MiniCommand(Action<T> callback)
         {
@@ -68,4 +68,4 @@ namespace Ryujinx.Ava.UI.Helpers
         public abstract void Execute(object parameter);
         public abstract event EventHandler CanExecuteChanged;
     }
-}
+}

+ 4 - 4
src/Ryujinx.Ava/UI/Helpers/NotificationHelper.cs

@@ -12,12 +12,12 @@ namespace Ryujinx.Ava.UI.Helpers
 {
     public static class NotificationHelper
     {
-        private const int MaxNotifications      = 4;
+        private const int MaxNotifications = 4;
         private const int NotificationDelayInMs = 5000;
 
         private static WindowNotificationManager _notificationManager;
 
-        private static readonly BlockingCollection<Notification> _notifications        = new();
+        private static readonly BlockingCollection<Notification> _notifications = new();
 
         public static void SetNotificationManager(Window host)
         {
@@ -25,7 +25,7 @@ namespace Ryujinx.Ava.UI.Helpers
             {
                 Position = NotificationPosition.BottomRight,
                 MaxItems = MaxNotifications,
-                Margin   = new Thickness(0, 0, 15, 40)
+                Margin = new Thickness(0, 0, 15, 40),
             };
 
             var maybeAsyncWorkQueue = new Lazy<AsyncWorkQueue<Notification>>(
@@ -67,4 +67,4 @@ namespace Ryujinx.Ava.UI.Helpers
             Show(LocaleManager.Instance[LocaleKeys.DialogErrorTitle], $"{LocaleManager.Instance[LocaleKeys.DialogErrorMessage]}\n\n{message}", NotificationType.Error);
         }
     }
-}
+}

+ 1 - 1
src/Ryujinx.Ava/UI/Helpers/NullableDateTimeConverter.cs

@@ -35,4 +35,4 @@ namespace Ryujinx.Ava.UI.Helpers
             return _instance;
         }
     }
-}
+}

+ 5 - 5
src/Ryujinx.Ava/UI/Helpers/OffscreenTextBox.cs

@@ -6,12 +6,12 @@ namespace Ryujinx.Ava.UI.Helpers
 {
     public class OffscreenTextBox : TextBox
     {
-        public RoutedEvent<KeyEventArgs> GetKeyDownRoutedEvent()
+        public static RoutedEvent<KeyEventArgs> GetKeyDownRoutedEvent()
         {
             return KeyDownEvent;
         }
 
-        public RoutedEvent<KeyEventArgs> GetKeyUpRoutedEvent()
+        public static RoutedEvent<KeyEventArgs> GetKeyUpRoutedEvent()
         {
             return KeyUpEvent;
         }
@@ -28,13 +28,13 @@ namespace Ryujinx.Ava.UI.Helpers
 
         public void SendText(string text)
         {
-            OnTextInput(new TextInputEventArgs()
+            OnTextInput(new TextInputEventArgs
             {
                 Text = text,
                 Device = KeyboardDevice.Instance,
                 Source = this,
-                RoutedEvent = TextInputEvent
+                RoutedEvent = TextInputEvent,
             });
         }
     }
-}
+}

+ 6 - 7
src/Ryujinx.Ava/UI/Helpers/UserErrorDialog.cs

@@ -1,5 +1,4 @@
 using Ryujinx.Ava.Common.Locale;
-using Ryujinx.Ava.UI.Windows;
 using Ryujinx.Ui.Common;
 using Ryujinx.Ui.Common.Helper;
 using System.Threading.Tasks;
@@ -24,7 +23,7 @@ namespace Ryujinx.Ava.UI.Helpers
                 UserError.FirmwareParsingFailed => LocaleManager.Instance[LocaleKeys.UserErrorFirmwareParsingFailed],
                 UserError.ApplicationNotFound => LocaleManager.Instance[LocaleKeys.UserErrorApplicationNotFound],
                 UserError.Unknown => LocaleManager.Instance[LocaleKeys.UserErrorUnknown],
-                _ => LocaleManager.Instance[LocaleKeys.UserErrorUndefined]
+                _ => LocaleManager.Instance[LocaleKeys.UserErrorUndefined],
             };
         }
 
@@ -37,7 +36,7 @@ namespace Ryujinx.Ava.UI.Helpers
                 UserError.FirmwareParsingFailed => LocaleManager.Instance[LocaleKeys.UserErrorFirmwareParsingFailedDescription],
                 UserError.ApplicationNotFound => LocaleManager.Instance[LocaleKeys.UserErrorApplicationNotFoundDescription],
                 UserError.Unknown => LocaleManager.Instance[LocaleKeys.UserErrorUnknownDescription],
-                _ => LocaleManager.Instance[LocaleKeys.UserErrorUndefinedDescription]
+                _ => LocaleManager.Instance[LocaleKeys.UserErrorUndefinedDescription],
             };
         }
 
@@ -48,7 +47,7 @@ namespace Ryujinx.Ava.UI.Helpers
                 UserError.NoKeys or
                     UserError.NoFirmware or
                     UserError.FirmwareParsingFailed => true,
-                _ => false
+                _ => false,
             };
         }
 
@@ -63,11 +62,11 @@ namespace Ryujinx.Ava.UI.Helpers
             {
                 UserError.NoKeys => SetupGuideUrl + "#initial-setup---placement-of-prodkeys",
                 UserError.NoFirmware => SetupGuideUrl + "#initial-setup-continued---installation-of-firmware",
-                _ => SetupGuideUrl
+                _ => SetupGuideUrl,
             };
         }
 
-        public static async Task ShowUserErrorDialog(UserError error, StyleableWindow owner)
+        public static async Task ShowUserErrorDialog(UserError error)
         {
             string errorCode = GetErrorCode(error);
 
@@ -88,4 +87,4 @@ namespace Ryujinx.Ava.UI.Helpers
             }
         }
     }
-}
+}

+ 1 - 1
src/Ryujinx.Ava/UI/Helpers/UserResult.cs

@@ -9,4 +9,4 @@ namespace Ryujinx.Ava.UI.Helpers
         Cancel,
         None,
     }
-}
+}

+ 28 - 26
src/Ryujinx.Ava/UI/Helpers/Win32NativeInterop.cs

@@ -1,4 +1,5 @@
 using System;
+using System.Diagnostics.CodeAnalysis;
 using System.Runtime.InteropServices;
 using System.Runtime.Versioning;
 
@@ -10,46 +11,47 @@ namespace Ryujinx.Ava.UI.Helpers
         [Flags]
         public enum ClassStyles : uint
         {
-            CS_CLASSDC = 0x40,
-            CS_OWNDC = 0x20,
+            CsClassdc = 0x40,
+            CsOwndc = 0x20,
         }
 
         [Flags]
         public enum WindowStyles : uint
         {
-            WS_CHILD = 0x40000000
+            WsChild = 0x40000000,
         }
 
         public enum Cursors : uint
         {
-            IDC_ARROW = 32512
+            IdcArrow = 32512,
         }
 
+        [SuppressMessage("Design", "CA1069: Enums values should not be duplicated")]
         public enum WindowsMessages : uint
         {
-            MOUSEMOVE = 0x0200,
-            LBUTTONDOWN = 0x0201,
-            LBUTTONUP = 0x0202,
-            LBUTTONDBLCLK = 0x0203,
-            RBUTTONDOWN = 0x0204,
-            RBUTTONUP = 0x0205,
-            RBUTTONDBLCLK = 0x0206,
-            MBUTTONDOWN = 0x0207,
-            MBUTTONUP = 0x0208,
-            MBUTTONDBLCLK = 0x0209,
-            MOUSEWHEEL = 0x020A,
-            XBUTTONDOWN = 0x020B,
-            XBUTTONUP = 0x020C,
-            XBUTTONDBLCLK = 0x020D,
-            MOUSEHWHEEL = 0x020E,
-            MOUSELAST = 0x020E
+            Mousemove = 0x0200,
+            Lbuttondown = 0x0201,
+            Lbuttonup = 0x0202,
+            Lbuttondblclk = 0x0203,
+            Rbuttondown = 0x0204,
+            Rbuttonup = 0x0205,
+            Rbuttondblclk = 0x0206,
+            Mbuttondown = 0x0207,
+            Mbuttonup = 0x0208,
+            Mbuttondblclk = 0x0209,
+            Mousewheel = 0x020A,
+            Xbuttondown = 0x020B,
+            Xbuttonup = 0x020C,
+            Xbuttondblclk = 0x020D,
+            Mousehwheel = 0x020E,
+            Mouselast = 0x020E,
         }
 
         [UnmanagedFunctionPointer(CallingConvention.Winapi)]
         internal delegate IntPtr WindowProc(IntPtr hWnd, WindowsMessages msg, IntPtr wParam, IntPtr lParam);
 
         [StructLayout(LayoutKind.Sequential)]
-        public struct WNDCLASSEX
+        public struct WndClassEx
         {
             public int cbSize;
             public ClassStyles style;
@@ -64,9 +66,9 @@ namespace Ryujinx.Ava.UI.Helpers
             public IntPtr lpszClassName;
             public IntPtr hIconSm;
 
-            public WNDCLASSEX()
+            public WndClassEx()
             {
-                cbSize = Marshal.SizeOf<WNDCLASSEX>();
+                cbSize = Marshal.SizeOf<WndClassEx>();
             }
         }
 
@@ -77,17 +79,17 @@ namespace Ryujinx.Ava.UI.Helpers
 
         public static IntPtr CreateArrowCursor()
         {
-            return LoadCursor(IntPtr.Zero, (IntPtr)Cursors.IDC_ARROW);
+            return LoadCursor(IntPtr.Zero, (IntPtr)Cursors.IdcArrow);
         }
 
         [LibraryImport("user32.dll")]
         public static partial IntPtr SetCursor(IntPtr handle);
 
         [LibraryImport("user32.dll")]
-        public static partial IntPtr CreateCursor(IntPtr hInst, int xHotSpot, int yHotSpot, int nWidth, int nHeight, byte[] pvANDPlane, byte[] pvXORPlane);
+        public static partial IntPtr CreateCursor(IntPtr hInst, int xHotSpot, int yHotSpot, int nWidth, int nHeight, byte[] pvAndPlane, byte[] pvXorPlane);
 
         [LibraryImport("user32.dll", SetLastError = true, EntryPoint = "RegisterClassExW")]
-        public static partial ushort RegisterClassEx(ref WNDCLASSEX param);
+        public static partial ushort RegisterClassEx(ref WndClassEx param);
 
         [LibraryImport("user32.dll", SetLastError = true, EntryPoint = "UnregisterClassW")]
         public static partial short UnregisterClass([MarshalAs(UnmanagedType.LPWStr)] string lpClassName, IntPtr instance);

+ 4 - 4
src/Ryujinx.Ava/UI/Models/CheatModel.cs

@@ -11,8 +11,8 @@ namespace Ryujinx.Ava.UI.Models
 
         public CheatModel(string name, string buildId, bool isEnabled)
         {
-            Name      = name;
-            BuildId   = buildId;
+            Name = name;
+            BuildId = buildId;
             IsEnabled = isEnabled;
         }
 
@@ -35,6 +35,6 @@ namespace Ryujinx.Ava.UI.Models
 
         public string Name { get; }
 
-        public string CleanName => Name.Substring(1, Name.Length - 8);
+        public string CleanName => Name[1..^7];
     }
-}
+}

+ 3 - 3
src/Ryujinx.Ava/UI/Models/CheatsList.cs

@@ -10,13 +10,13 @@ namespace Ryujinx.Ava.UI.Models
         public CheatsList(string buildId, string path)
         {
             BuildId = buildId;
-            Path    = path;
+            Path = path;
 
             CollectionChanged += CheatsList_CollectionChanged;
         }
 
         public string BuildId { get; }
-        public string Path    { get; }
+        public string Path { get; }
 
         public bool IsEnabled
         {
@@ -48,4 +48,4 @@ namespace Ryujinx.Ava.UI.Models
             OnPropertyChanged(new PropertyChangedEventArgs(nameof(IsEnabled)));
         }
     }
-}
+}

+ 2 - 2
src/Ryujinx.Ava/UI/Models/DeviceType.cs

@@ -4,6 +4,6 @@ namespace Ryujinx.Ava.UI.Models
     {
         None,
         Keyboard,
-        Controller
+        Controller,
     }
-}
+}

+ 6 - 6
src/Ryujinx.Ava/UI/Models/DownloadableContentModel.cs

@@ -18,18 +18,18 @@ namespace Ryujinx.Ava.UI.Models
             }
         }
 
-        public string TitleId       { get; }
+        public string TitleId { get; }
         public string ContainerPath { get; }
-        public string FullPath      { get; }
+        public string FullPath { get; }
 
         public string FileName => Path.GetFileName(ContainerPath);
 
         public DownloadableContentModel(string titleId, string containerPath, string fullPath, bool enabled)
         {
-            TitleId       = titleId;
+            TitleId = titleId;
             ContainerPath = containerPath;
-            FullPath      = fullPath;
-            Enabled       = enabled;
+            FullPath = fullPath;
+            Enabled = enabled;
         }
     }
-}
+}

+ 1 - 1
src/Ryujinx.Ava/UI/Models/Generic/LastPlayedSortComparer.cs

@@ -29,4 +29,4 @@ namespace Ryujinx.Ava.UI.Models.Generic
             return (IsAscending ? 1 : -1) * DateTime.Compare(bValue.Value, aValue.Value);
         }
     }
-}
+}

+ 157 - 157
src/Ryujinx.Ava/UI/Models/InputConfiguration.cs

@@ -7,16 +7,16 @@ using System;
 
 namespace Ryujinx.Ava.UI.Models
 {
-    internal class InputConfiguration<Key, Stick> : BaseModel
+    internal class InputConfiguration<TKey, TStick> : BaseModel
     {
         private float _deadzoneRight;
         private float _triggerThreshold;
         private float _deadzoneLeft;
         private double _gyroDeadzone;
         private int _sensitivity;
-        private bool enableMotion;
-        private float weakRumble;
-        private float strongRumble;
+        private bool _enableMotion;
+        private float _weakRumble;
+        private float _strongRumble;
         private float _rangeLeft;
         private float _rangeRight;
 
@@ -37,17 +37,17 @@ namespace Ryujinx.Ava.UI.Models
         /// </summary>
         public PlayerIndex PlayerIndex { get; set; }
 
-        public Stick LeftJoystick { get; set; }
+        public TStick LeftJoystick { get; set; }
         public bool LeftInvertStickX { get; set; }
         public bool LeftInvertStickY { get; set; }
         public bool RightRotate90 { get; set; }
-        public Key LeftControllerStickButton { get; set; }
+        public TKey LeftControllerStickButton { get; set; }
 
-        public Stick RightJoystick { get; set; }
+        public TStick RightJoystick { get; set; }
         public bool RightInvertStickX { get; set; }
         public bool RightInvertStickY { get; set; }
         public bool LeftRotate90 { get; set; }
-        public Key RightControllerStickButton { get; set; }
+        public TKey RightControllerStickButton { get; set; }
 
         public float DeadzoneLeft
         {
@@ -106,38 +106,37 @@ namespace Ryujinx.Ava.UI.Models
 
         public MotionInputBackendType MotionBackend { get; set; }
 
-        public Key ButtonMinus { get; set; }
-        public Key ButtonL { get; set; }
-        public Key ButtonZl { get; set; }
-        public Key LeftButtonSl { get; set; }
-        public Key LeftButtonSr { get; set; }
-        public Key DpadUp { get; set; }
-        public Key DpadDown { get; set; }
-        public Key DpadLeft { get; set; }
-        public Key DpadRight { get; set; }
-
-        public Key ButtonPlus { get; set; }
-        public Key ButtonR { get; set; }
-        public Key ButtonZr { get; set; }
-        public Key RightButtonSl { get; set; }
-        public Key RightButtonSr { get; set; }
-        public Key ButtonX { get; set; }
-        public Key ButtonB { get; set; }
-        public Key ButtonY { get; set; }
-        public Key ButtonA { get; set; }
-
-
-        public Key LeftStickUp { get; set; }
-        public Key LeftStickDown { get; set; }
-        public Key LeftStickLeft { get; set; }
-        public Key LeftStickRight { get; set; }
-        public Key LeftKeyboardStickButton { get; set; }
-
-        public Key RightStickUp { get; set; }
-        public Key RightStickDown { get; set; }
-        public Key RightStickLeft { get; set; }
-        public Key RightStickRight { get; set; }
-        public Key RightKeyboardStickButton { get; set; }
+        public TKey ButtonMinus { get; set; }
+        public TKey ButtonL { get; set; }
+        public TKey ButtonZl { get; set; }
+        public TKey LeftButtonSl { get; set; }
+        public TKey LeftButtonSr { get; set; }
+        public TKey DpadUp { get; set; }
+        public TKey DpadDown { get; set; }
+        public TKey DpadLeft { get; set; }
+        public TKey DpadRight { get; set; }
+
+        public TKey ButtonPlus { get; set; }
+        public TKey ButtonR { get; set; }
+        public TKey ButtonZr { get; set; }
+        public TKey RightButtonSl { get; set; }
+        public TKey RightButtonSr { get; set; }
+        public TKey ButtonX { get; set; }
+        public TKey ButtonB { get; set; }
+        public TKey ButtonY { get; set; }
+        public TKey ButtonA { get; set; }
+
+        public TKey LeftStickUp { get; set; }
+        public TKey LeftStickDown { get; set; }
+        public TKey LeftStickLeft { get; set; }
+        public TKey LeftStickRight { get; set; }
+        public TKey LeftKeyboardStickButton { get; set; }
+
+        public TKey RightStickUp { get; set; }
+        public TKey RightStickDown { get; set; }
+        public TKey RightStickLeft { get; set; }
+        public TKey RightStickRight { get; set; }
+        public TKey RightKeyboardStickButton { get; set; }
 
         public int Sensitivity
         {
@@ -163,9 +162,9 @@ namespace Ryujinx.Ava.UI.Models
 
         public bool EnableMotion
         {
-            get => enableMotion; set
+            get => _enableMotion; set
             {
-                enableMotion = value;
+                _enableMotion = value;
 
                 OnPropertyChanged();
             }
@@ -181,18 +180,18 @@ namespace Ryujinx.Ava.UI.Models
         public bool EnableRumble { get; set; }
         public float WeakRumble
         {
-            get => weakRumble; set
+            get => _weakRumble; set
             {
-                weakRumble = value;
+                _weakRumble = value;
 
                 OnPropertyChanged();
             }
         }
         public float StrongRumble
         {
-            get => strongRumble; set
+            get => _strongRumble; set
             {
-                strongRumble = value;
+                _strongRumble = value;
 
                 OnPropertyChanged();
             }
@@ -209,71 +208,71 @@ namespace Ryujinx.Ava.UI.Models
 
                 if (config is StandardKeyboardInputConfig keyboardConfig)
                 {
-                    LeftStickUp = (Key)(object)keyboardConfig.LeftJoyconStick.StickUp;
-                    LeftStickDown = (Key)(object)keyboardConfig.LeftJoyconStick.StickDown;
-                    LeftStickLeft = (Key)(object)keyboardConfig.LeftJoyconStick.StickLeft;
-                    LeftStickRight = (Key)(object)keyboardConfig.LeftJoyconStick.StickRight;
-                    LeftKeyboardStickButton = (Key)(object)keyboardConfig.LeftJoyconStick.StickButton;
-
-                    RightStickUp = (Key)(object)keyboardConfig.RightJoyconStick.StickUp;
-                    RightStickDown = (Key)(object)keyboardConfig.RightJoyconStick.StickDown;
-                    RightStickLeft = (Key)(object)keyboardConfig.RightJoyconStick.StickLeft;
-                    RightStickRight = (Key)(object)keyboardConfig.RightJoyconStick.StickRight;
-                    RightKeyboardStickButton = (Key)(object)keyboardConfig.RightJoyconStick.StickButton;
-
-                    ButtonA = (Key)(object)keyboardConfig.RightJoycon.ButtonA;
-                    ButtonB = (Key)(object)keyboardConfig.RightJoycon.ButtonB;
-                    ButtonX = (Key)(object)keyboardConfig.RightJoycon.ButtonX;
-                    ButtonY = (Key)(object)keyboardConfig.RightJoycon.ButtonY;
-                    ButtonR = (Key)(object)keyboardConfig.RightJoycon.ButtonR;
-                    RightButtonSl = (Key)(object)keyboardConfig.RightJoycon.ButtonSl;
-                    RightButtonSr = (Key)(object)keyboardConfig.RightJoycon.ButtonSr;
-                    ButtonZr = (Key)(object)keyboardConfig.RightJoycon.ButtonZr;
-                    ButtonPlus = (Key)(object)keyboardConfig.RightJoycon.ButtonPlus;
-
-                    DpadUp = (Key)(object)keyboardConfig.LeftJoycon.DpadUp;
-                    DpadDown = (Key)(object)keyboardConfig.LeftJoycon.DpadDown;
-                    DpadLeft = (Key)(object)keyboardConfig.LeftJoycon.DpadLeft;
-                    DpadRight = (Key)(object)keyboardConfig.LeftJoycon.DpadRight;
-                    ButtonMinus = (Key)(object)keyboardConfig.LeftJoycon.ButtonMinus;
-                    LeftButtonSl = (Key)(object)keyboardConfig.LeftJoycon.ButtonSl;
-                    LeftButtonSr = (Key)(object)keyboardConfig.LeftJoycon.ButtonSr;
-                    ButtonZl = (Key)(object)keyboardConfig.LeftJoycon.ButtonZl;
-                    ButtonL = (Key)(object)keyboardConfig.LeftJoycon.ButtonL;
+                    LeftStickUp = (TKey)(object)keyboardConfig.LeftJoyconStick.StickUp;
+                    LeftStickDown = (TKey)(object)keyboardConfig.LeftJoyconStick.StickDown;
+                    LeftStickLeft = (TKey)(object)keyboardConfig.LeftJoyconStick.StickLeft;
+                    LeftStickRight = (TKey)(object)keyboardConfig.LeftJoyconStick.StickRight;
+                    LeftKeyboardStickButton = (TKey)(object)keyboardConfig.LeftJoyconStick.StickButton;
+
+                    RightStickUp = (TKey)(object)keyboardConfig.RightJoyconStick.StickUp;
+                    RightStickDown = (TKey)(object)keyboardConfig.RightJoyconStick.StickDown;
+                    RightStickLeft = (TKey)(object)keyboardConfig.RightJoyconStick.StickLeft;
+                    RightStickRight = (TKey)(object)keyboardConfig.RightJoyconStick.StickRight;
+                    RightKeyboardStickButton = (TKey)(object)keyboardConfig.RightJoyconStick.StickButton;
+
+                    ButtonA = (TKey)(object)keyboardConfig.RightJoycon.ButtonA;
+                    ButtonB = (TKey)(object)keyboardConfig.RightJoycon.ButtonB;
+                    ButtonX = (TKey)(object)keyboardConfig.RightJoycon.ButtonX;
+                    ButtonY = (TKey)(object)keyboardConfig.RightJoycon.ButtonY;
+                    ButtonR = (TKey)(object)keyboardConfig.RightJoycon.ButtonR;
+                    RightButtonSl = (TKey)(object)keyboardConfig.RightJoycon.ButtonSl;
+                    RightButtonSr = (TKey)(object)keyboardConfig.RightJoycon.ButtonSr;
+                    ButtonZr = (TKey)(object)keyboardConfig.RightJoycon.ButtonZr;
+                    ButtonPlus = (TKey)(object)keyboardConfig.RightJoycon.ButtonPlus;
+
+                    DpadUp = (TKey)(object)keyboardConfig.LeftJoycon.DpadUp;
+                    DpadDown = (TKey)(object)keyboardConfig.LeftJoycon.DpadDown;
+                    DpadLeft = (TKey)(object)keyboardConfig.LeftJoycon.DpadLeft;
+                    DpadRight = (TKey)(object)keyboardConfig.LeftJoycon.DpadRight;
+                    ButtonMinus = (TKey)(object)keyboardConfig.LeftJoycon.ButtonMinus;
+                    LeftButtonSl = (TKey)(object)keyboardConfig.LeftJoycon.ButtonSl;
+                    LeftButtonSr = (TKey)(object)keyboardConfig.LeftJoycon.ButtonSr;
+                    ButtonZl = (TKey)(object)keyboardConfig.LeftJoycon.ButtonZl;
+                    ButtonL = (TKey)(object)keyboardConfig.LeftJoycon.ButtonL;
                 }
                 else if (config is StandardControllerInputConfig controllerConfig)
                 {
-                    LeftJoystick = (Stick)(object)controllerConfig.LeftJoyconStick.Joystick;
+                    LeftJoystick = (TStick)(object)controllerConfig.LeftJoyconStick.Joystick;
                     LeftInvertStickX = controllerConfig.LeftJoyconStick.InvertStickX;
                     LeftInvertStickY = controllerConfig.LeftJoyconStick.InvertStickY;
                     LeftRotate90 = controllerConfig.LeftJoyconStick.Rotate90CW;
-                    LeftControllerStickButton = (Key)(object)controllerConfig.LeftJoyconStick.StickButton;
+                    LeftControllerStickButton = (TKey)(object)controllerConfig.LeftJoyconStick.StickButton;
 
-                    RightJoystick = (Stick)(object)controllerConfig.RightJoyconStick.Joystick;
+                    RightJoystick = (TStick)(object)controllerConfig.RightJoyconStick.Joystick;
                     RightInvertStickX = controllerConfig.RightJoyconStick.InvertStickX;
                     RightInvertStickY = controllerConfig.RightJoyconStick.InvertStickY;
                     RightRotate90 = controllerConfig.RightJoyconStick.Rotate90CW;
-                    RightControllerStickButton = (Key)(object)controllerConfig.RightJoyconStick.StickButton;
-
-                    ButtonA = (Key)(object)controllerConfig.RightJoycon.ButtonA;
-                    ButtonB = (Key)(object)controllerConfig.RightJoycon.ButtonB;
-                    ButtonX = (Key)(object)controllerConfig.RightJoycon.ButtonX;
-                    ButtonY = (Key)(object)controllerConfig.RightJoycon.ButtonY;
-                    ButtonR = (Key)(object)controllerConfig.RightJoycon.ButtonR;
-                    RightButtonSl = (Key)(object)controllerConfig.RightJoycon.ButtonSl;
-                    RightButtonSr = (Key)(object)controllerConfig.RightJoycon.ButtonSr;
-                    ButtonZr = (Key)(object)controllerConfig.RightJoycon.ButtonZr;
-                    ButtonPlus = (Key)(object)controllerConfig.RightJoycon.ButtonPlus;
-
-                    DpadUp = (Key)(object)controllerConfig.LeftJoycon.DpadUp;
-                    DpadDown = (Key)(object)controllerConfig.LeftJoycon.DpadDown;
-                    DpadLeft = (Key)(object)controllerConfig.LeftJoycon.DpadLeft;
-                    DpadRight = (Key)(object)controllerConfig.LeftJoycon.DpadRight;
-                    ButtonMinus = (Key)(object)controllerConfig.LeftJoycon.ButtonMinus;
-                    LeftButtonSl = (Key)(object)controllerConfig.LeftJoycon.ButtonSl;
-                    LeftButtonSr = (Key)(object)controllerConfig.LeftJoycon.ButtonSr;
-                    ButtonZl = (Key)(object)controllerConfig.LeftJoycon.ButtonZl;
-                    ButtonL = (Key)(object)controllerConfig.LeftJoycon.ButtonL;
+                    RightControllerStickButton = (TKey)(object)controllerConfig.RightJoyconStick.StickButton;
+
+                    ButtonA = (TKey)(object)controllerConfig.RightJoycon.ButtonA;
+                    ButtonB = (TKey)(object)controllerConfig.RightJoycon.ButtonB;
+                    ButtonX = (TKey)(object)controllerConfig.RightJoycon.ButtonX;
+                    ButtonY = (TKey)(object)controllerConfig.RightJoycon.ButtonY;
+                    ButtonR = (TKey)(object)controllerConfig.RightJoycon.ButtonR;
+                    RightButtonSl = (TKey)(object)controllerConfig.RightJoycon.ButtonSl;
+                    RightButtonSr = (TKey)(object)controllerConfig.RightJoycon.ButtonSr;
+                    ButtonZr = (TKey)(object)controllerConfig.RightJoycon.ButtonZr;
+                    ButtonPlus = (TKey)(object)controllerConfig.RightJoycon.ButtonPlus;
+
+                    DpadUp = (TKey)(object)controllerConfig.LeftJoycon.DpadUp;
+                    DpadDown = (TKey)(object)controllerConfig.LeftJoycon.DpadDown;
+                    DpadLeft = (TKey)(object)controllerConfig.LeftJoycon.DpadLeft;
+                    DpadRight = (TKey)(object)controllerConfig.LeftJoycon.DpadRight;
+                    ButtonMinus = (TKey)(object)controllerConfig.LeftJoycon.ButtonMinus;
+                    LeftButtonSl = (TKey)(object)controllerConfig.LeftJoycon.ButtonSl;
+                    LeftButtonSr = (TKey)(object)controllerConfig.LeftJoycon.ButtonSr;
+                    ButtonZl = (TKey)(object)controllerConfig.LeftJoycon.ButtonZl;
+                    ButtonL = (TKey)(object)controllerConfig.LeftJoycon.ButtonL;
 
                     DeadzoneLeft = controllerConfig.DeadzoneLeft;
                     DeadzoneRight = controllerConfig.DeadzoneRight;
@@ -317,65 +316,66 @@ namespace Ryujinx.Ava.UI.Models
         {
             if (Backend == InputBackendType.WindowKeyboard)
             {
-                return new StandardKeyboardInputConfig()
+                return new StandardKeyboardInputConfig
                 {
                     Id = Id,
                     Backend = Backend,
                     PlayerIndex = PlayerIndex,
                     ControllerType = ControllerType,
-                    LeftJoycon = new LeftJoyconCommonConfig<Ryujinx.Common.Configuration.Hid.Key>()
+                    LeftJoycon = new LeftJoyconCommonConfig<Key>
                     {
-                        DpadUp = (Ryujinx.Common.Configuration.Hid.Key)(object)DpadUp,
-                        DpadDown = (Ryujinx.Common.Configuration.Hid.Key)(object)DpadDown,
-                        DpadLeft = (Ryujinx.Common.Configuration.Hid.Key)(object)DpadLeft,
-                        DpadRight = (Ryujinx.Common.Configuration.Hid.Key)(object)DpadRight,
-                        ButtonL = (Ryujinx.Common.Configuration.Hid.Key)(object)ButtonL,
-                        ButtonZl = (Ryujinx.Common.Configuration.Hid.Key)(object)ButtonZl,
-                        ButtonSl = (Ryujinx.Common.Configuration.Hid.Key)(object)LeftButtonSl,
-                        ButtonSr = (Ryujinx.Common.Configuration.Hid.Key)(object)LeftButtonSr,
-                        ButtonMinus = (Ryujinx.Common.Configuration.Hid.Key)(object)ButtonMinus
+                        DpadUp = (Key)(object)DpadUp,
+                        DpadDown = (Key)(object)DpadDown,
+                        DpadLeft = (Key)(object)DpadLeft,
+                        DpadRight = (Key)(object)DpadRight,
+                        ButtonL = (Key)(object)ButtonL,
+                        ButtonZl = (Key)(object)ButtonZl,
+                        ButtonSl = (Key)(object)LeftButtonSl,
+                        ButtonSr = (Key)(object)LeftButtonSr,
+                        ButtonMinus = (Key)(object)ButtonMinus,
                     },
-                    RightJoycon = new RightJoyconCommonConfig<Ryujinx.Common.Configuration.Hid.Key>()
+                    RightJoycon = new RightJoyconCommonConfig<Key>
                     {
-                        ButtonA = (Ryujinx.Common.Configuration.Hid.Key)(object)ButtonA,
-                        ButtonB = (Ryujinx.Common.Configuration.Hid.Key)(object)ButtonB,
-                        ButtonX = (Ryujinx.Common.Configuration.Hid.Key)(object)ButtonX,
-                        ButtonY = (Ryujinx.Common.Configuration.Hid.Key)(object)ButtonY,
-                        ButtonPlus = (Ryujinx.Common.Configuration.Hid.Key)(object)ButtonPlus,
-                        ButtonSl = (Ryujinx.Common.Configuration.Hid.Key)(object)RightButtonSl,
-                        ButtonSr = (Ryujinx.Common.Configuration.Hid.Key)(object)RightButtonSr,
-                        ButtonR = (Ryujinx.Common.Configuration.Hid.Key)(object)ButtonR,
-                        ButtonZr = (Ryujinx.Common.Configuration.Hid.Key)(object)ButtonZr
+                        ButtonA = (Key)(object)ButtonA,
+                        ButtonB = (Key)(object)ButtonB,
+                        ButtonX = (Key)(object)ButtonX,
+                        ButtonY = (Key)(object)ButtonY,
+                        ButtonPlus = (Key)(object)ButtonPlus,
+                        ButtonSl = (Key)(object)RightButtonSl,
+                        ButtonSr = (Key)(object)RightButtonSr,
+                        ButtonR = (Key)(object)ButtonR,
+                        ButtonZr = (Key)(object)ButtonZr,
                     },
-                    LeftJoyconStick = new JoyconConfigKeyboardStick<Ryujinx.Common.Configuration.Hid.Key>()
+                    LeftJoyconStick = new JoyconConfigKeyboardStick<Key>
                     {
-                        StickUp = (Ryujinx.Common.Configuration.Hid.Key)(object)LeftStickUp,
-                        StickDown = (Ryujinx.Common.Configuration.Hid.Key)(object)LeftStickDown,
-                        StickRight = (Ryujinx.Common.Configuration.Hid.Key)(object)LeftStickRight,
-                        StickLeft = (Ryujinx.Common.Configuration.Hid.Key)(object)LeftStickLeft,
-                        StickButton = (Ryujinx.Common.Configuration.Hid.Key)(object)LeftKeyboardStickButton
+                        StickUp = (Key)(object)LeftStickUp,
+                        StickDown = (Key)(object)LeftStickDown,
+                        StickRight = (Key)(object)LeftStickRight,
+                        StickLeft = (Key)(object)LeftStickLeft,
+                        StickButton = (Key)(object)LeftKeyboardStickButton,
                     },
-                    RightJoyconStick = new JoyconConfigKeyboardStick<Ryujinx.Common.Configuration.Hid.Key>()
+                    RightJoyconStick = new JoyconConfigKeyboardStick<Key>
                     {
-                        StickUp = (Ryujinx.Common.Configuration.Hid.Key)(object)RightStickUp,
-                        StickDown = (Ryujinx.Common.Configuration.Hid.Key)(object)RightStickDown,
-                        StickLeft = (Ryujinx.Common.Configuration.Hid.Key)(object)RightStickLeft,
-                        StickRight = (Ryujinx.Common.Configuration.Hid.Key)(object)RightStickRight,
-                        StickButton = (Ryujinx.Common.Configuration.Hid.Key)(object)RightKeyboardStickButton
+                        StickUp = (Key)(object)RightStickUp,
+                        StickDown = (Key)(object)RightStickDown,
+                        StickLeft = (Key)(object)RightStickLeft,
+                        StickRight = (Key)(object)RightStickRight,
+                        StickButton = (Key)(object)RightKeyboardStickButton,
                     },
-                    Version = InputConfig.CurrentVersion
+                    Version = InputConfig.CurrentVersion,
                 };
 
             }
-            else if (Backend == InputBackendType.GamepadSDL2)
+
+            if (Backend == InputBackendType.GamepadSDL2)
             {
-                var config = new StandardControllerInputConfig()
+                var config = new StandardControllerInputConfig
                 {
                     Id = Id,
                     Backend = Backend,
                     PlayerIndex = PlayerIndex,
                     ControllerType = ControllerType,
-                    LeftJoycon = new LeftJoyconCommonConfig<GamepadInputId>()
+                    LeftJoycon = new LeftJoyconCommonConfig<GamepadInputId>
                     {
                         DpadUp = (GamepadInputId)(object)DpadUp,
                         DpadDown = (GamepadInputId)(object)DpadDown,
@@ -387,7 +387,7 @@ namespace Ryujinx.Ava.UI.Models
                         ButtonSr = (GamepadInputId)(object)LeftButtonSr,
                         ButtonMinus = (GamepadInputId)(object)ButtonMinus,
                     },
-                    RightJoycon = new RightJoyconCommonConfig<GamepadInputId>()
+                    RightJoycon = new RightJoyconCommonConfig<GamepadInputId>
                     {
                         ButtonA = (GamepadInputId)(object)ButtonA,
                         ButtonB = (GamepadInputId)(object)ButtonB,
@@ -399,7 +399,7 @@ namespace Ryujinx.Ava.UI.Models
                         ButtonR = (GamepadInputId)(object)ButtonR,
                         ButtonZr = (GamepadInputId)(object)ButtonZr,
                     },
-                    LeftJoyconStick = new JoyconConfigControllerStick<GamepadInputId, StickInputId>()
+                    LeftJoyconStick = new JoyconConfigControllerStick<GamepadInputId, StickInputId>
                     {
                         Joystick = (StickInputId)(object)LeftJoystick,
                         InvertStickX = LeftInvertStickX,
@@ -407,7 +407,7 @@ namespace Ryujinx.Ava.UI.Models
                         Rotate90CW = LeftRotate90,
                         StickButton = (GamepadInputId)(object)LeftControllerStickButton,
                     },
-                    RightJoyconStick = new JoyconConfigControllerStick<GamepadInputId, StickInputId>()
+                    RightJoyconStick = new JoyconConfigControllerStick<GamepadInputId, StickInputId>
                     {
                         Joystick = (StickInputId)(object)RightJoystick,
                         InvertStickX = RightInvertStickX,
@@ -415,11 +415,11 @@ namespace Ryujinx.Ava.UI.Models
                         Rotate90CW = RightRotate90,
                         StickButton = (GamepadInputId)(object)RightControllerStickButton,
                     },
-                    Rumble = new RumbleConfigController()
+                    Rumble = new RumbleConfigController
                     {
                         EnableRumble = EnableRumble,
                         WeakRumble = WeakRumble,
-                        StrongRumble = StrongRumble
+                        StrongRumble = StrongRumble,
                     },
                     Version = InputConfig.CurrentVersion,
                     DeadzoneLeft = DeadzoneLeft,
@@ -428,19 +428,19 @@ namespace Ryujinx.Ava.UI.Models
                     RangeRight = RangeRight,
                     TriggerThreshold = TriggerThreshold,
                     Motion = EnableCemuHookMotion
-                           ? new CemuHookMotionConfigController()
-                           {
-                               DsuServerHost = DsuServerHost,
-                               DsuServerPort = DsuServerPort,
-                               Slot = Slot,
-                               AltSlot = AltSlot,
-                               MirrorInput = MirrorInput,
-                               MotionBackend = MotionInputBackendType.CemuHook
-                           }
-                           : new StandardMotionConfigController()
-                           {
-                               MotionBackend = MotionInputBackendType.GamepadDriver
-                           }
+                        ? new CemuHookMotionConfigController
+                        {
+                            DsuServerHost = DsuServerHost,
+                            DsuServerPort = DsuServerPort,
+                            Slot = Slot,
+                            AltSlot = AltSlot,
+                            MirrorInput = MirrorInput,
+                            MotionBackend = MotionInputBackendType.CemuHook,
+                        }
+                        : new StandardMotionConfigController
+                        {
+                            MotionBackend = MotionInputBackendType.GamepadDriver,
+                        },
                 };
 
                 config.Motion.Sensitivity = Sensitivity;
@@ -453,4 +453,4 @@ namespace Ryujinx.Ava.UI.Models
             return null;
         }
     }
-}
+}

+ 1 - 1
src/Ryujinx.Ava/UI/Models/ProfileImageModel.cs

@@ -29,4 +29,4 @@ namespace Ryujinx.Ava.UI.Models
             }
         }
     }
-}
+}

+ 7 - 6
src/Ryujinx.Ava/UI/Models/SaveModel.cs

@@ -2,12 +2,12 @@ using LibHac.Fs;
 using LibHac.Ncm;
 using Ryujinx.Ava.UI.ViewModels;
 using Ryujinx.Ava.UI.Windows;
-using Ryujinx.HLE.FileSystem;
 using Ryujinx.Ui.App.Common;
 using System;
 using System.IO;
 using System.Linq;
 using System.Threading.Tasks;
+using Path = System.IO.Path;
 
 namespace Ryujinx.Ava.UI.Models
 {
@@ -58,7 +58,7 @@ namespace Ryujinx.Ava.UI.Models
             return "0 KiB";
         }
 
-        public SaveModel(SaveDataInfo info, VirtualFileSystem virtualFileSystem)
+        public SaveModel(SaveDataInfo info)
         {
             SaveId = info.SaveDataId;
             TitleId = info.ProgramId;
@@ -81,10 +81,11 @@ namespace Ryujinx.Ava.UI.Models
 
             Task.Run(() =>
             {
-                var saveRoot = System.IO.Path.Combine(virtualFileSystem.GetNandPath(), $"user/save/{info.SaveDataId:x16}");
+                var saveRoot = Path.Combine(MainWindow.MainWindowViewModel.VirtualFileSystem.GetNandPath(), $"user/save/{info.SaveDataId:x16}");
 
-                long total_size = GetDirectorySize(saveRoot);
-                long GetDirectorySize(string path)
+                long totalSize = GetDirectorySize(saveRoot);
+
+                static long GetDirectorySize(string path)
                 {
                     long size = 0;
                     if (Directory.Exists(path))
@@ -105,7 +106,7 @@ namespace Ryujinx.Ava.UI.Models
                     return size;
                 }
 
-                Size = total_size;
+                Size = totalSize;
             });
 
         }

+ 1 - 1
src/Ryujinx.Ava/UI/Models/StatusUpdatedEventArgs.cs

@@ -25,4 +25,4 @@ namespace Ryujinx.Ava.UI.Models
             GpuName = gpuName;
         }
     }
-}
+}

+ 2 - 2
src/Ryujinx.Ava/UI/Models/TempProfile.cs

@@ -11,7 +11,7 @@ namespace Ryujinx.Ava.UI.Models
         private string _name = String.Empty;
         private UserId _userId;
 
-        public uint MaxProfileNameLength => 0x20;
+        public static uint MaxProfileNameLength => 0x20;
 
         public byte[] Image
         {
@@ -58,4 +58,4 @@ namespace Ryujinx.Ava.UI.Models
             }
         }
     }
-}
+}

+ 1 - 1
src/Ryujinx.Ava/UI/Models/TimeZone.cs

@@ -13,4 +13,4 @@ namespace Ryujinx.Ava.UI.Models
         public string Location { get; set; }
         public string Abbreviation { get; set; }
     }
-}
+}

+ 1 - 1
src/Ryujinx.Ava/UI/Models/TitleUpdateModel.cs

@@ -16,4 +16,4 @@ namespace Ryujinx.Ava.UI.Models
             Path = path;
         }
     }
-}
+}

+ 3 - 2
src/Ryujinx.Ava/UI/Models/UserProfile.cs

@@ -1,3 +1,4 @@
+using Avalonia;
 using Avalonia.Media;
 using Ryujinx.Ava.UI.Controls;
 using Ryujinx.Ava.UI.ViewModels;
@@ -87,7 +88,7 @@ namespace Ryujinx.Ava.UI.Models
 
         private void UpdateBackground()
         {
-            Avalonia.Application.Current.Styles.TryGetResource("ControlFillColorSecondary", out object color);
+            Application.Current.Styles.TryGetResource("ControlFillColorSecondary", out object color);
 
             if (color is not null)
             {
@@ -100,4 +101,4 @@ namespace Ryujinx.Ava.UI.Models
             _owner.Navigate(typeof(UserEditorView), (_owner, userProfile, true));
         }
     }
-}
+}

+ 41 - 37
src/Ryujinx.Ava/UI/Renderer/EmbeddedWindow.cs

@@ -21,20 +21,20 @@ namespace Ryujinx.Ava.UI.Renderer
     public class EmbeddedWindow : NativeControlHost
     {
         private WindowProc _wndProcDelegate;
-        private string     _className;
+        private string _className;
 
         protected GLXWindow X11Window { get; set; }
 
         protected IntPtr WindowHandle { get; set; }
-        protected IntPtr X11Display   { get; set; }
-        protected IntPtr NsView       { get; set; }
-        protected IntPtr MetalLayer   { get; set; }
+        protected IntPtr X11Display { get; set; }
+        protected IntPtr NsView { get; set; }
+        protected IntPtr MetalLayer { get; set; }
 
         public delegate void UpdateBoundsCallbackDelegate(Rect rect);
         private UpdateBoundsCallbackDelegate _updateBoundsCallback;
 
         public event EventHandler<IntPtr> WindowCreated;
-        public event EventHandler<Size>   SizeChanged;
+        public event EventHandler<Size> SizeChanged;
 
         public EmbeddedWindow()
         {
@@ -50,9 +50,9 @@ namespace Ryujinx.Ava.UI.Renderer
         protected virtual void OnWindowDestroying()
         {
             WindowHandle = IntPtr.Zero;
-            X11Display   = IntPtr.Zero;
-            NsView       = IntPtr.Zero;
-            MetalLayer   = IntPtr.Zero;
+            X11Display = IntPtr.Zero;
+            NsView = IntPtr.Zero;
+            MetalLayer = IntPtr.Zero;
         }
 
         private void OnNativeEmbeddedWindowCreated(object sender, EventArgs e)
@@ -77,11 +77,13 @@ namespace Ryujinx.Ava.UI.Renderer
             {
                 return CreateLinux(control);
             }
-            else if (OperatingSystem.IsWindows())
+
+            if (OperatingSystem.IsWindows())
             {
                 return CreateWin32(control);
             }
-            else if (OperatingSystem.IsMacOS())
+
+            if (OperatingSystem.IsMacOS())
             {
                 return CreateMacOS();
             }
@@ -127,7 +129,7 @@ namespace Ryujinx.Ava.UI.Renderer
             }
 
             WindowHandle = X11Window.WindowHandle.RawHandle;
-            X11Display   = X11Window.DisplayHandle.RawHandle;
+            X11Display = X11Window.DisplayHandle.RawHandle;
 
             return new PlatformHandle(WindowHandle, "X11");
         }
@@ -141,23 +143,23 @@ namespace Ryujinx.Ava.UI.Renderer
             {
                 if (VisualRoot != null)
                 {
-                    if (msg == WindowsMessages.LBUTTONDOWN ||
-                        msg == WindowsMessages.RBUTTONDOWN ||
-                        msg == WindowsMessages.LBUTTONUP   ||
-                        msg == WindowsMessages.RBUTTONUP   ||
-                        msg == WindowsMessages.MOUSEMOVE)
+                    if (msg == WindowsMessages.Lbuttondown ||
+                        msg == WindowsMessages.Rbuttondown ||
+                        msg == WindowsMessages.Lbuttonup ||
+                        msg == WindowsMessages.Rbuttonup ||
+                        msg == WindowsMessages.Mousemove)
                     {
-                        Point   rootVisualPosition = this.TranslatePoint(new Point((long)lParam & 0xFFFF, (long)lParam >> 16 & 0xFFFF), VisualRoot).Value;
-                        Pointer pointer            = new(0, PointerType.Mouse, true);
+                        Point rootVisualPosition = this.TranslatePoint(new Point((long)lParam & 0xFFFF, (long)lParam >> 16 & 0xFFFF), VisualRoot).Value;
+                        Pointer pointer = new(0, PointerType.Mouse, true);
 
                         switch (msg)
                         {
-                            case WindowsMessages.LBUTTONDOWN:
-                            case WindowsMessages.RBUTTONDOWN:
+                            case WindowsMessages.Lbuttondown:
+                            case WindowsMessages.Rbuttondown:
                                 {
-                                    bool                   isLeft               = msg == WindowsMessages.LBUTTONDOWN;
-                                    RawInputModifiers      pointerPointModifier = isLeft ? RawInputModifiers.LeftMouseButton : RawInputModifiers.RightMouseButton;
-                                    PointerPointProperties properties           = new(pointerPointModifier, isLeft ? PointerUpdateKind.LeftButtonPressed : PointerUpdateKind.RightButtonPressed);
+                                    bool isLeft = msg == WindowsMessages.Lbuttondown;
+                                    RawInputModifiers pointerPointModifier = isLeft ? RawInputModifiers.LeftMouseButton : RawInputModifiers.RightMouseButton;
+                                    PointerPointProperties properties = new(pointerPointModifier, isLeft ? PointerUpdateKind.LeftButtonPressed : PointerUpdateKind.RightButtonPressed);
 
                                     var evnt = new PointerPressedEventArgs(
                                         this,
@@ -172,12 +174,12 @@ namespace Ryujinx.Ava.UI.Renderer
 
                                     break;
                                 }
-                            case WindowsMessages.LBUTTONUP:
-                            case WindowsMessages.RBUTTONUP:
+                            case WindowsMessages.Lbuttonup:
+                            case WindowsMessages.Rbuttonup:
                                 {
-                                    bool                   isLeft               = msg == WindowsMessages.LBUTTONUP;
-                                    RawInputModifiers      pointerPointModifier = isLeft ? RawInputModifiers.LeftMouseButton : RawInputModifiers.RightMouseButton;
-                                    PointerPointProperties properties           = new(pointerPointModifier, isLeft ? PointerUpdateKind.LeftButtonReleased : PointerUpdateKind.RightButtonReleased);
+                                    bool isLeft = msg == WindowsMessages.Lbuttonup;
+                                    RawInputModifiers pointerPointModifier = isLeft ? RawInputModifiers.LeftMouseButton : RawInputModifiers.RightMouseButton;
+                                    PointerPointProperties properties = new(pointerPointModifier, isLeft ? PointerUpdateKind.LeftButtonReleased : PointerUpdateKind.RightButtonReleased);
 
                                     var evnt = new PointerReleasedEventArgs(
                                         this,
@@ -193,7 +195,7 @@ namespace Ryujinx.Ava.UI.Renderer
 
                                     break;
                                 }
-                            case WindowsMessages.MOUSEMOVE:
+                            case WindowsMessages.Mousemove:
                                 {
                                     var evnt = new PointerEventArgs(
                                         PointerMovedEvent,
@@ -216,19 +218,19 @@ namespace Ryujinx.Ava.UI.Renderer
                 return DefWindowProc(hWnd, msg, wParam, lParam);
             };
 
-            WNDCLASSEX wndClassEx = new()
+            WndClassEx wndClassEx = new()
             {
-                cbSize        = Marshal.SizeOf<WNDCLASSEX>(),
-                hInstance     = GetModuleHandle(null),
-                lpfnWndProc   = Marshal.GetFunctionPointerForDelegate(_wndProcDelegate),
-                style         = ClassStyles.CS_OWNDC,
+                cbSize = Marshal.SizeOf<WndClassEx>(),
+                hInstance = GetModuleHandle(null),
+                lpfnWndProc = Marshal.GetFunctionPointerForDelegate(_wndProcDelegate),
+                style = ClassStyles.CsOwndc,
                 lpszClassName = Marshal.StringToHGlobalUni(_className),
-                hCursor       = CreateArrowCursor()
+                hCursor = CreateArrowCursor(),
             };
 
             RegisterClassEx(ref wndClassEx);
 
-            WindowHandle = CreateWindowEx(0, _className, "NativeWindow", WindowStyles.WS_CHILD, 0, 0, 640, 480, control.Handle, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero);
+            WindowHandle = CreateWindowEx(0, _className, "NativeWindow", WindowStyles.WsChild, 0, 0, 640, 480, control.Handle, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero);
 
             Marshal.FreeHGlobal(wndClassEx.lpszClassName);
 
@@ -280,9 +282,11 @@ namespace Ryujinx.Ava.UI.Renderer
         }
 
         [SupportedOSPlatform("macos")]
+#pragma warning disable CA1822 // Mark member as static
         void DestroyMacOS()
         {
             // TODO
         }
+#pragma warning restore CA1822
     }
-}
+}

+ 1 - 1
src/Ryujinx.Ava/UI/Renderer/EmbeddedWindowOpenGL.cs

@@ -91,4 +91,4 @@ namespace Ryujinx.Ava.UI.Renderer
             MakeCurrent();
         }
     }
-}
+}

+ 2 - 2
src/Ryujinx.Ava/UI/Renderer/EmbeddedWindowVulkan.cs

@@ -34,9 +34,9 @@ namespace Ryujinx.Ava.UI.Renderer
             return new SurfaceKHR((ulong?)VulkanHelper.CreateWindowSurface(instance.Handle, nativeWindowBase));
         }
 
-        public SurfaceKHR CreateSurface(Instance instance, Vk api)
+        public SurfaceKHR CreateSurface(Instance instance, Vk _)
         {
             return CreateSurface(instance);
         }
     }
-}
+}

+ 1 - 1
src/Ryujinx.Ava/UI/Renderer/OpenTKBindingsContext.cs

@@ -17,4 +17,4 @@ namespace Ryujinx.Ava.UI.Renderer
             return _getProcAddress(procName);
         }
     }
-}
+}

+ 4 - 4
src/Ryujinx.Ava/UI/Renderer/RendererHost.axaml.cs

@@ -11,7 +11,7 @@ namespace Ryujinx.Ava.UI.Renderer
         public readonly EmbeddedWindow EmbeddedWindow;
 
         public event EventHandler<EventArgs> WindowCreated;
-        public event Action<object, Size>    SizeChanged;
+        public event Action<object, Size> SizeChanged;
 
         public RendererHost()
         {
@@ -32,7 +32,7 @@ namespace Ryujinx.Ava.UI.Renderer
         private void Initialize()
         {
             EmbeddedWindow.WindowCreated += CurrentWindow_WindowCreated;
-            EmbeddedWindow.SizeChanged   += CurrentWindow_SizeChanged;
+            EmbeddedWindow.SizeChanged += CurrentWindow_SizeChanged;
 
             Content = EmbeddedWindow;
         }
@@ -42,7 +42,7 @@ namespace Ryujinx.Ava.UI.Renderer
             if (EmbeddedWindow != null)
             {
                 EmbeddedWindow.WindowCreated -= CurrentWindow_WindowCreated;
-                EmbeddedWindow.SizeChanged   -= CurrentWindow_SizeChanged;
+                EmbeddedWindow.SizeChanged -= CurrentWindow_SizeChanged;
             }
 
             GC.SuppressFinalize(this);
@@ -65,4 +65,4 @@ namespace Ryujinx.Ava.UI.Renderer
             WindowCreated?.Invoke(this, EventArgs.Empty);
         }
     }
-}
+}

+ 3 - 3
src/Ryujinx.Ava/UI/Renderer/SPBOpenGLContext.cs

@@ -10,12 +10,12 @@ namespace Ryujinx.Ava.UI.Renderer
     class SPBOpenGLContext : IOpenGLContext
     {
         private readonly OpenGLContextBase _context;
-        private readonly NativeWindowBase  _window;
+        private readonly NativeWindowBase _window;
 
         private SPBOpenGLContext(OpenGLContextBase context, NativeWindowBase window)
         {
             _context = context;
-            _window  = window;
+            _window = window;
         }
 
         public void Dispose()
@@ -32,7 +32,7 @@ namespace Ryujinx.Ava.UI.Renderer
         public static SPBOpenGLContext CreateBackgroundContext(OpenGLContextBase sharedContext)
         {
             OpenGLContextBase context = PlatformHelper.CreateOpenGLContext(FramebufferFormat.Default, 3, 3, OpenGLContextFlags.Compat, true, sharedContext);
-            NativeWindowBase  window  = PlatformHelper.CreateOpenGLWindow(FramebufferFormat.Default, 0, 0, 100, 100);
+            NativeWindowBase window = PlatformHelper.CreateOpenGLWindow(FramebufferFormat.Default, 0, 0, 100, 100);
 
             context.Initialize(window);
             context.MakeCurrent(window);

+ 3 - 2
src/Ryujinx.Ava/UI/ViewModels/AboutWindowViewModel.cs

@@ -1,5 +1,6 @@
 using Avalonia;
 using Avalonia.Media.Imaging;
+using Avalonia.Platform;
 using Avalonia.Threading;
 using Ryujinx.Ava.Common.Locale;
 using Ryujinx.Common.Utilities;
@@ -87,7 +88,7 @@ namespace Ryujinx.Ava.UI.ViewModels
         {
             Version = Program.Version;
 
-            var assets = AvaloniaLocator.Current.GetService<Avalonia.Platform.IAssetLoader>();
+            var assets = AvaloniaLocator.Current.GetService<IAssetLoader>();
 
             if (ConfigurationState.Instance.Ui.BaseStyle.Value == "Light")
             {
@@ -130,4 +131,4 @@ namespace Ryujinx.Ava.UI.ViewModels
             }
         }
     }
-}
+}

+ 18 - 20
src/Ryujinx.Ava/UI/ViewModels/AmiiboWindowViewModel.cs

@@ -18,7 +18,6 @@ using System.Linq;
 using System.Net.Http;
 using System.Text;
 using System.Threading.Tasks;
-using AmiiboJsonSerializerContext = Ryujinx.Ui.Common.Models.Amiibo.AmiiboJsonSerializerContext;
 
 namespace Ryujinx.Ava.UI.ViewModels
 {
@@ -44,7 +43,7 @@ namespace Ryujinx.Ava.UI.ViewModels
         private bool _useRandomUuid;
         private string _usage;
 
-        private static readonly AmiiboJsonSerializerContext SerializerContext = new(JsonHelper.GetDefaultSerializerOptions());
+        private static readonly AmiiboJsonSerializerContext _serializerContext = new(JsonHelper.GetDefaultSerializerOptions());
 
         public AmiiboWindowViewModel(StyleableWindow owner, string lastScannedAmiiboId, string titleId)
         {
@@ -52,7 +51,7 @@ namespace Ryujinx.Ava.UI.ViewModels
 
             _httpClient = new HttpClient
             {
-                Timeout = TimeSpan.FromSeconds(30)
+                Timeout = TimeSpan.FromSeconds(30),
             };
 
             LastScannedAmiiboId = lastScannedAmiiboId;
@@ -185,6 +184,7 @@ namespace Ryujinx.Ava.UI.ViewModels
 
         public void Dispose()
         {
+            GC.SuppressFinalize(this);
             _httpClient.Dispose();
         }
 
@@ -196,7 +196,7 @@ namespace Ryujinx.Ava.UI.ViewModels
             {
                 amiiboJsonString = await File.ReadAllTextAsync(_amiiboJsonPath);
 
-                if (await NeedsUpdate(JsonHelper.Deserialize(amiiboJsonString, SerializerContext.AmiiboJson).LastUpdated))
+                if (await NeedsUpdate(JsonHelper.Deserialize(amiiboJsonString, _serializerContext.AmiiboJson).LastUpdated))
                 {
                     amiiboJsonString = await DownloadAmiiboJson();
                 }
@@ -215,7 +215,7 @@ namespace Ryujinx.Ava.UI.ViewModels
                 }
             }
 
-            _amiiboList = JsonHelper.Deserialize(amiiboJsonString, SerializerContext.AmiiboJson).Amiibo;
+            _amiiboList = JsonHelper.Deserialize(amiiboJsonString, _serializerContext.AmiiboJson).Amiibo;
             _amiiboList = _amiiboList.OrderBy(amiibo => amiibo.AmiiboSeries).ToList();
 
             ParseAmiiboData();
@@ -426,18 +426,17 @@ namespace Ryujinx.Ava.UI.ViewModels
             if (response.IsSuccessStatusCode)
             {
                 byte[] amiiboPreviewBytes = await response.Content.ReadAsByteArrayAsync();
-                using (MemoryStream memoryStream = new(amiiboPreviewBytes))
-                {
-                    Bitmap bitmap = new(memoryStream);
+                using MemoryStream memoryStream = new(amiiboPreviewBytes);
+
+                Bitmap bitmap = new(memoryStream);
 
-                    double ratio = Math.Min(AmiiboImageSize / bitmap.Size.Width,
+                double ratio = Math.Min(AmiiboImageSize / bitmap.Size.Width,
                         AmiiboImageSize / bitmap.Size.Height);
 
-                    int resizeHeight = (int)(bitmap.Size.Height * ratio);
-                    int resizeWidth = (int)(bitmap.Size.Width * ratio);
+                int resizeHeight = (int)(bitmap.Size.Height * ratio);
+                int resizeWidth = (int)(bitmap.Size.Width * ratio);
 
-                    AmiiboImage = bitmap.CreateScaledBitmap(new PixelSize(resizeWidth, resizeHeight));
-                }
+                AmiiboImage = bitmap.CreateScaledBitmap(new PixelSize(resizeWidth, resizeHeight));
             }
             else
             {
@@ -447,15 +446,14 @@ namespace Ryujinx.Ava.UI.ViewModels
 
         private void ResetAmiiboPreview()
         {
-            using (MemoryStream memoryStream = new(_amiiboLogoBytes))
-            {
-                Bitmap bitmap = new(memoryStream);
+            using MemoryStream memoryStream = new(_amiiboLogoBytes);
 
-                AmiiboImage = bitmap;
-            }
+            Bitmap bitmap = new(memoryStream);
+
+            AmiiboImage = bitmap;
         }
 
-        private async void ShowInfoDialog()
+        private static async void ShowInfoDialog()
         {
             await ContentDialogHelper.CreateInfoDialog(LocaleManager.Instance[LocaleKeys.DialogAmiiboApiTitle],
                 LocaleManager.Instance[LocaleKeys.DialogAmiiboApiConnectErrorMessage],
@@ -464,4 +462,4 @@ namespace Ryujinx.Ava.UI.ViewModels
                 LocaleManager.Instance[LocaleKeys.RyujinxInfo]);
         }
     }
-}
+}

+ 0 - 363
src/Ryujinx.Ava/UI/ViewModels/AvatarProfileViewModel.cs

@@ -1,363 +0,0 @@
-using Avalonia.Media;
-using DynamicData;
-using LibHac.Common;
-using LibHac.Fs;
-using LibHac.Fs.Fsa;
-using LibHac.FsSystem;
-using LibHac.Ncm;
-using LibHac.Tools.Fs;
-using LibHac.Tools.FsSystem;
-using LibHac.Tools.FsSystem.NcaUtils;
-using Ryujinx.Ava.UI.Models;
-using Ryujinx.HLE.FileSystem;
-using SixLabors.ImageSharp;
-using SixLabors.ImageSharp.Formats.Png;
-using SixLabors.ImageSharp.PixelFormats;
-using SixLabors.ImageSharp.Processing;
-using System;
-using System.Buffers.Binary;
-using System.Collections.Generic;
-using System.Collections.ObjectModel;
-using System.IO;
-using System.Linq;
-using System.Threading;
-using System.Threading.Tasks;
-using Color = Avalonia.Media.Color;
-
-namespace Ryujinx.Ava.UI.ViewModels
-{
-    internal class AvatarProfileViewModel : BaseModel, IDisposable
-    {
-        private const int MaxImageTasks = 4;
-        
-        private static readonly Dictionary<string, byte[]> _avatarStore = new();
-        private static bool _isPreloading;
-        private static Action _loadCompleteAction;
-
-        private ObservableCollection<ProfileImageModel> _images;
-        private Color _backgroundColor = Colors.White;
-
-        private int _selectedIndex;
-        private int _imagesLoaded;
-        private bool _isActive;
-        private byte[] _selectedImage;
-        private bool _isIndeterminate = true;
-
-        public bool IsActive
-        {
-            get => _isActive;
-            set => _isActive = value;
-        }
-
-        public AvatarProfileViewModel()
-        {
-            _images = new ObservableCollection<ProfileImageModel>();
-        }
-        
-        public AvatarProfileViewModel(Action loadCompleteAction)
-        {
-            _images = new ObservableCollection<ProfileImageModel>();
-
-            if (_isPreloading)
-            {
-                _loadCompleteAction = loadCompleteAction;
-            }
-            else
-            {
-                ReloadImages();
-            }
-        }
-
-        public Color BackgroundColor
-        {
-            get => _backgroundColor;
-            set
-            {
-                _backgroundColor = value;
-
-                IsActive = false;
-                
-                ReloadImages();
-            }
-        }
-
-        public ObservableCollection<ProfileImageModel> Images
-        {
-            get => _images;
-            set
-            {
-                _images = value;
-                OnPropertyChanged();
-            }
-        }
-
-        public bool IsIndeterminate
-        {
-            get => _isIndeterminate;
-            set
-            {
-                _isIndeterminate = value;
-                
-                OnPropertyChanged();
-            }
-        }
-
-        public int ImageCount => _avatarStore.Count;
-
-        public int ImagesLoaded
-        {
-            get => _imagesLoaded;
-            set
-            {
-                _imagesLoaded = value;
-                OnPropertyChanged();
-            }
-        }
-
-        public int SelectedIndex
-        {
-            get => _selectedIndex;
-            set
-            {
-                _selectedIndex = value;
-
-                if (_selectedIndex == -1)
-                {
-                    SelectedImage = null;
-                }
-                else
-                {
-                    SelectedImage = _images[_selectedIndex].Data;
-                }
-
-                OnPropertyChanged();
-            }
-        }
-
-        public byte[] SelectedImage
-        {
-            get => _selectedImage;
-            private set => _selectedImage = value;
-        }
-
-        public void ReloadImages()
-        {
-            if (_isPreloading)
-            {
-                IsIndeterminate = false;
-                return;
-            }
-            Task.Run(() =>
-            {
-                IsActive = true;
-
-                Images.Clear();
-                int selectedIndex = _selectedIndex;
-                int index = 0;
-                
-                ImagesLoaded = 0;
-                IsIndeterminate = false;
-
-                var keys = _avatarStore.Keys.ToList();
-
-                var newImages = new List<ProfileImageModel>();
-                var tasks = new List<Task>();
-
-                for (int i = 0; i < MaxImageTasks; i++)
-                {
-                    var start = i;
-                    tasks.Add(Task.Run(() => ImageTask(start)));
-                }
-
-                Task.WaitAll(tasks.ToArray());
-                
-                Images.AddRange(newImages);
-
-                void ImageTask(int start)
-                {
-                    for (int i = start; i < keys.Count; i += MaxImageTasks)
-                    {
-                        if (!IsActive)
-                        {
-                            return;
-                        }
-
-                        var key = keys[i];
-                        var image = _avatarStore[keys[i]];
-
-                        var data = ProcessImage(image);
-                        newImages.Add(new ProfileImageModel(key, data));
-                        if (index++ == selectedIndex)
-                        {
-                            SelectedImage = data;
-                        }
-
-                        Interlocked.Increment(ref _imagesLoaded);
-                        OnPropertyChanged(nameof(ImagesLoaded));
-                    }
-                }
-            });
-        }
-
-        private byte[] ProcessImage(byte[] data)
-        {
-            using (MemoryStream streamJpg = new())
-            {
-                Image avatarImage = Image.Load(data, new PngDecoder());
-
-                avatarImage.Mutate(x => x.BackgroundColor(new Rgba32(BackgroundColor.R,
-                    BackgroundColor.G,
-                    BackgroundColor.B,
-                    BackgroundColor.A)));
-                avatarImage.SaveAsJpeg(streamJpg);
-
-                return streamJpg.ToArray();
-            }
-        }
-
-        public static void PreloadAvatars(ContentManager contentManager, VirtualFileSystem virtualFileSystem)
-        {
-            try
-            {
-                if (_avatarStore.Count > 0)
-                {
-                    return;
-                }
-
-                _isPreloading = true;
-
-                string contentPath =
-                    contentManager.GetInstalledContentPath(0x010000000000080A, StorageId.BuiltInSystem,
-                        NcaContentType.Data);
-                string avatarPath = virtualFileSystem.SwitchPathToSystemPath(contentPath);
-
-                if (!string.IsNullOrWhiteSpace(avatarPath))
-                {
-                    using (IStorage ncaFileStream = new LocalStorage(avatarPath, FileAccess.Read, FileMode.Open))
-                    {
-                        Nca nca = new(virtualFileSystem.KeySet, ncaFileStream);
-                        IFileSystem romfs = nca.OpenFileSystem(NcaSectionType.Data, IntegrityCheckLevel.ErrorOnInvalid);
-
-                        foreach (DirectoryEntryEx item in romfs.EnumerateEntries())
-                        {
-                            // TODO: Parse DatabaseInfo.bin and table.bin files for more accuracy.
-                            if (item.Type == DirectoryEntryType.File && item.FullPath.Contains("chara") &&
-                                item.FullPath.Contains("szs"))
-                            {
-                                using var file = new UniqueRef<IFile>();
-
-                                romfs.OpenFile(ref file.Ref, ("/" + item.FullPath).ToU8Span(), OpenMode.Read)
-                                    .ThrowIfFailure();
-
-                                using (MemoryStream stream = new())
-                                using (MemoryStream streamPng = new())
-                                {
-                                    file.Get.AsStream().CopyTo(stream);
-
-                                    stream.Position = 0;
-
-                                    Image avatarImage = Image.LoadPixelData<Rgba32>(DecompressYaz0(stream), 256, 256);
-
-                                    avatarImage.SaveAsPng(streamPng);
-
-                                    _avatarStore.Add(item.FullPath, streamPng.ToArray());
-                                }
-                            }
-                        }
-                    }
-                }
-            }
-            finally
-            {
-                _isPreloading = false;
-                _loadCompleteAction?.Invoke();
-            }
-        }
-
-        private static byte[] DecompressYaz0(Stream stream)
-        {
-            using (BinaryReader reader = new(stream))
-            {
-                reader.ReadInt32(); // Magic
-
-                uint decodedLength = BinaryPrimitives.ReverseEndianness(reader.ReadUInt32());
-
-                reader.ReadInt64(); // Padding
-
-                byte[] input = new byte[stream.Length - stream.Position];
-                stream.Read(input, 0, input.Length);
-
-                uint inputOffset = 0;
-
-                byte[] output = new byte[decodedLength];
-                uint outputOffset = 0;
-
-                ushort mask = 0;
-                byte header = 0;
-
-                while (outputOffset < decodedLength)
-                {
-                    if ((mask >>= 1) == 0)
-                    {
-                        header = input[inputOffset++];
-                        mask = 0x80;
-                    }
-
-                    if ((header & mask) != 0)
-                    {
-                        if (outputOffset == output.Length)
-                        {
-                            break;
-                        }
-
-                        output[outputOffset++] = input[inputOffset++];
-                    }
-                    else
-                    {
-                        byte byte1 = input[inputOffset++];
-                        byte byte2 = input[inputOffset++];
-
-                        uint dist = (uint)((byte1 & 0xF) << 8) | byte2;
-                        uint position = outputOffset - (dist + 1);
-
-                        uint length = (uint)byte1 >> 4;
-                        if (length == 0)
-                        {
-                            length = (uint)input[inputOffset++] + 0x12;
-                        }
-                        else
-                        {
-                            length += 2;
-                        }
-
-                        uint gap = outputOffset - position;
-                        uint nonOverlappingLength = length;
-
-                        if (nonOverlappingLength > gap)
-                        {
-                            nonOverlappingLength = gap;
-                        }
-
-                        Buffer.BlockCopy(output, (int)position, output, (int)outputOffset, (int)nonOverlappingLength);
-                        outputOffset += nonOverlappingLength;
-                        position += nonOverlappingLength;
-                        length -= nonOverlappingLength;
-
-                        while (length-- > 0)
-                        {
-                            output[outputOffset++] = output[position++];
-                        }
-                    }
-                }
-
-                return output;
-            }
-        }
-
-        public void Dispose()
-        {
-            _loadCompleteAction = null;
-            IsActive = false;
-        }
-    }
-}

+ 1 - 1
src/Ryujinx.Ava/UI/ViewModels/BaseModel.cs

@@ -12,4 +12,4 @@ namespace Ryujinx.Ava.UI.ViewModels
             PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
         }
     }
-}
+}

+ 49 - 52
src/Ryujinx.Ava/UI/ViewModels/ControllerInputViewModel.cs

@@ -1,3 +1,4 @@
+using Avalonia;
 using Avalonia.Collections;
 using Avalonia.Controls;
 using Avalonia.Controls.ApplicationLifetimes;
@@ -44,15 +45,14 @@ namespace Ryujinx.Ava.UI.ViewModels
 
         private PlayerIndex _playerId;
         private int _controller;
-        private int _controllerNumber = 0;
+        private int _controllerNumber;
         private string _controllerImage;
         private int _device;
         private object _configuration;
         private string _profileName;
         private bool _isLoaded;
-        private readonly UserControl _owner;
 
-        private static readonly InputConfigJsonSerializerContext SerializerContext = new(JsonHelper.GetDefaultSerializerOptions());
+        private static readonly InputConfigJsonSerializerContext _serializerContext = new(JsonHelper.GetDefaultSerializerOptions());
 
         public IGamepadDriver AvaloniaKeyboardDriver { get; }
         public IGamepad SelectedGamepad { get; private set; }
@@ -176,11 +176,11 @@ namespace Ryujinx.Ava.UI.ViewModels
         {
             get
             {
-                SvgImage image = new SvgImage();
+                SvgImage image = new();
 
                 if (!string.IsNullOrWhiteSpace(_controllerImage))
                 {
-                    SvgSource source = new SvgSource();
+                    SvgSource source = new();
 
                     source.Load(EmbeddedResources.GetStream(_controllerImage));
 
@@ -234,22 +234,18 @@ namespace Ryujinx.Ava.UI.ViewModels
 
         public ControllerInputViewModel(UserControl owner) : this()
         {
-            _owner = owner;
-
             if (Program.PreviewerDetached)
             {
                 _mainWindow =
-                    (MainWindow)((IClassicDesktopStyleApplicationLifetime)Avalonia.Application.Current
+                    (MainWindow)((IClassicDesktopStyleApplicationLifetime)Application.Current
                         .ApplicationLifetime).MainWindow;
 
                 AvaloniaKeyboardDriver = new AvaloniaKeyboardDriver(owner);
 
                 _mainWindow.InputManager.GamepadDriver.OnGamepadConnected += HandleOnGamepadConnected;
                 _mainWindow.InputManager.GamepadDriver.OnGamepadDisconnected += HandleOnGamepadDisconnected;
-                if (_mainWindow.ViewModel.AppHost != null)
-                {
-                    _mainWindow.ViewModel.AppHost.NpadManager.BlockInputUpdates();
-                }
+
+                _mainWindow.ViewModel.AppHost?.NpadManager.BlockInputUpdates();
 
                 _isLoaded = false;
 
@@ -351,7 +347,8 @@ namespace Ryujinx.Ava.UI.ViewModels
             {
                 return;
             }
-            else if (type == DeviceType.Keyboard)
+
+            if (type == DeviceType.Keyboard)
             {
                 if (_mainWindow.InputManager.KeyboardDriver is AvaloniaKeyboardDriver)
                 {
@@ -448,7 +445,7 @@ namespace Ryujinx.Ava.UI.ViewModels
             const string Hyphen = "-";
             const int Offset = 1;
 
-            return str.Substring(str.IndexOf(Hyphen) + Offset);
+            return str[(str.IndexOf(Hyphen) + Offset)..];
         }
 
         public void LoadDevices()
@@ -562,7 +559,7 @@ namespace Ryujinx.Ava.UI.ViewModels
                         ButtonL = Key.E,
                         ButtonZl = Key.Q,
                         ButtonSl = Key.Unbound,
-                        ButtonSr = Key.Unbound
+                        ButtonSr = Key.Unbound,
                     },
                     LeftJoyconStick =
                         new JoyconConfigKeyboardStick<Key>
@@ -571,7 +568,7 @@ namespace Ryujinx.Ava.UI.ViewModels
                             StickDown = Key.S,
                             StickLeft = Key.A,
                             StickRight = Key.D,
-                            StickButton = Key.F
+                            StickButton = Key.F,
                         },
                     RightJoycon = new RightJoyconCommonConfig<Key>
                     {
@@ -583,7 +580,7 @@ namespace Ryujinx.Ava.UI.ViewModels
                         ButtonR = Key.U,
                         ButtonZr = Key.O,
                         ButtonSl = Key.Unbound,
-                        ButtonSr = Key.Unbound
+                        ButtonSr = Key.Unbound,
                     },
                     RightJoyconStick = new JoyconConfigKeyboardStick<Key>
                     {
@@ -591,8 +588,8 @@ namespace Ryujinx.Ava.UI.ViewModels
                         StickDown = Key.K,
                         StickLeft = Key.J,
                         StickRight = Key.L,
-                        StickButton = Key.H
-                    }
+                        StickButton = Key.H,
+                    },
                 };
             }
             else if (activeDevice.Type == DeviceType.Controller)
@@ -622,14 +619,14 @@ namespace Ryujinx.Ava.UI.ViewModels
                         ButtonL = ConfigGamepadInputId.LeftShoulder,
                         ButtonZl = ConfigGamepadInputId.LeftTrigger,
                         ButtonSl = ConfigGamepadInputId.Unbound,
-                        ButtonSr = ConfigGamepadInputId.Unbound
+                        ButtonSr = ConfigGamepadInputId.Unbound,
                     },
                     LeftJoyconStick = new JoyconConfigControllerStick<ConfigGamepadInputId, ConfigStickInputId>
                     {
                         Joystick = ConfigStickInputId.Left,
                         StickButton = ConfigGamepadInputId.LeftStick,
                         InvertStickX = false,
-                        InvertStickY = false
+                        InvertStickY = false,
                     },
                     RightJoycon = new RightJoyconCommonConfig<ConfigGamepadInputId>
                     {
@@ -641,28 +638,28 @@ namespace Ryujinx.Ava.UI.ViewModels
                         ButtonR = ConfigGamepadInputId.RightShoulder,
                         ButtonZr = ConfigGamepadInputId.RightTrigger,
                         ButtonSl = ConfigGamepadInputId.Unbound,
-                        ButtonSr = ConfigGamepadInputId.Unbound
+                        ButtonSr = ConfigGamepadInputId.Unbound,
                     },
                     RightJoyconStick = new JoyconConfigControllerStick<ConfigGamepadInputId, ConfigStickInputId>
                     {
                         Joystick = ConfigStickInputId.Right,
                         StickButton = ConfigGamepadInputId.RightStick,
                         InvertStickX = false,
-                        InvertStickY = false
+                        InvertStickY = false,
                     },
                     Motion = new StandardMotionConfigController
                     {
                         MotionBackend = MotionInputBackendType.GamepadDriver,
                         EnableMotion = true,
                         Sensitivity = 100,
-                        GyroDeadzone = 1
+                        GyroDeadzone = 1,
                     },
                     Rumble = new RumbleConfigController
                     {
                         StrongRumble = 1f,
                         WeakRumble = 1f,
-                        EnableRumble = false
-                    }
+                        EnableRumble = false,
+                    },
                 };
             }
             else
@@ -709,7 +706,7 @@ namespace Ryujinx.Ava.UI.ViewModels
 
                 try
                 {
-                    config = JsonHelper.DeserializeFromFile(path, SerializerContext.InputConfig);
+                    config = JsonHelper.DeserializeFromFile(path, _serializerContext.InputConfig);
                 }
                 catch (JsonException) { }
                 catch (InvalidOperationException)
@@ -754,37 +751,35 @@ namespace Ryujinx.Ava.UI.ViewModels
 
                 return;
             }
-            else
-            {
-                bool validFileName = ProfileName.IndexOfAny(Path.GetInvalidFileNameChars()) == -1;
-
-                if (validFileName)
-                {
-                    string path = Path.Combine(GetProfileBasePath(), ProfileName + ".json");
 
-                    InputConfig config = null;
+            bool validFileName = ProfileName.IndexOfAny(Path.GetInvalidFileNameChars()) == -1;
 
-                    if (IsKeyboard)
-                    {
-                        config = (Configuration as InputConfiguration<Key, ConfigStickInputId>).GetConfig();
-                    }
-                    else if (IsController)
-                    {
-                        config = (Configuration as InputConfiguration<GamepadInputId, ConfigStickInputId>).GetConfig();
-                    }
-
-                    config.ControllerType = Controllers[_controller].Type;
-
-                    string jsonString = JsonHelper.Serialize(config, SerializerContext.InputConfig);
+            if (validFileName)
+            {
+                string path = Path.Combine(GetProfileBasePath(), ProfileName + ".json");
 
-                    await File.WriteAllTextAsync(path, jsonString);
+                InputConfig config = null;
 
-                    LoadProfiles();
+                if (IsKeyboard)
+                {
+                    config = (Configuration as InputConfiguration<Key, ConfigStickInputId>).GetConfig();
                 }
-                else
+                else if (IsController)
                 {
-                    await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance[LocaleKeys.DialogProfileInvalidProfileNameErrorMessage]);
+                    config = (Configuration as InputConfiguration<GamepadInputId, ConfigStickInputId>).GetConfig();
                 }
+
+                config.ControllerType = Controllers[_controller].Type;
+
+                string jsonString = JsonHelper.Serialize(config, _serializerContext.InputConfig);
+
+                await File.WriteAllTextAsync(path, jsonString);
+
+                LoadProfiles();
+            }
+            else
+            {
+                await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance[LocaleKeys.DialogProfileInvalidProfileNameErrorMessage]);
             }
         }
 
@@ -887,6 +882,8 @@ namespace Ryujinx.Ava.UI.ViewModels
 
         public void Dispose()
         {
+            GC.SuppressFinalize(this);
+
             _mainWindow.InputManager.GamepadDriver.OnGamepadConnected -= HandleOnGamepadConnected;
             _mainWindow.InputManager.GamepadDriver.OnGamepadDisconnected -= HandleOnGamepadDisconnected;
 
@@ -897,4 +894,4 @@ namespace Ryujinx.Ava.UI.ViewModels
             AvaloniaKeyboardDriver.Dispose();
         }
     }
-}
+}

+ 24 - 25
src/Ryujinx.Ava/UI/ViewModels/DownloadableContentManagerViewModel.cs

@@ -22,6 +22,7 @@ using System.Collections.Generic;
 using System.IO;
 using System.Linq;
 using System.Threading.Tasks;
+using Application = Avalonia.Application;
 using Path = System.IO.Path;
 
 namespace Ryujinx.Ava.UI.ViewModels
@@ -29,18 +30,17 @@ namespace Ryujinx.Ava.UI.ViewModels
     public class DownloadableContentManagerViewModel : BaseModel
     {
         private readonly List<DownloadableContentContainer> _downloadableContentContainerList;
-        private readonly string                             _downloadableContentJsonPath;
+        private readonly string _downloadableContentJsonPath;
 
-        private VirtualFileSystem                      _virtualFileSystem;
+        private readonly VirtualFileSystem _virtualFileSystem;
         private AvaloniaList<DownloadableContentModel> _downloadableContents = new();
         private AvaloniaList<DownloadableContentModel> _views = new();
         private AvaloniaList<DownloadableContentModel> _selectedDownloadableContents = new();
 
         private string _search;
-        private ulong _titleId;
-        private string _titleName;
+        private readonly ulong _titleId;
 
-        private static readonly DownloadableContentJsonSerializerContext SerializerContext = new(JsonHelper.GetDefaultSerializerOptions());
+        private static readonly DownloadableContentJsonSerializerContext _serializerContext = new(JsonHelper.GetDefaultSerializerOptions());
 
         public AvaloniaList<DownloadableContentModel> DownloadableContents
         {
@@ -90,18 +90,17 @@ namespace Ryujinx.Ava.UI.ViewModels
             get => string.Format(LocaleManager.Instance[LocaleKeys.DlcWindowHeading], DownloadableContents.Count);
         }
 
-        public DownloadableContentManagerViewModel(VirtualFileSystem virtualFileSystem, ulong titleId, string titleName)
+        public DownloadableContentManagerViewModel(VirtualFileSystem virtualFileSystem, ulong titleId)
         {
             _virtualFileSystem = virtualFileSystem;
 
-            _titleId   = titleId;
-            _titleName = titleName;
+            _titleId = titleId;
 
             _downloadableContentJsonPath = Path.Combine(AppDataManager.GamesDirPath, titleId.ToString("x16"), "dlc.json");
 
             try
             {
-                _downloadableContentContainerList = JsonHelper.DeserializeFromFile(_downloadableContentJsonPath, SerializerContext.ListDownloadableContentContainer);
+                _downloadableContentContainerList = JsonHelper.DeserializeFromFile(_downloadableContentJsonPath, _serializerContext.ListDownloadableContentContainer);
             }
             catch
             {
@@ -132,7 +131,7 @@ namespace Ryujinx.Ava.UI.ViewModels
 
                         Nca nca = TryOpenNca(ncaFile.Get.AsStorage(), downloadableContentContainer.ContainerPath);
                         if (nca != null)
-                        {   
+                        {
                             var content = new DownloadableContentModel(nca.Header.TitleId.ToString("X16"),
                                 downloadableContentContainer.ContainerPath,
                                 downloadableContentNca.FullPath,
@@ -196,19 +195,19 @@ namespace Ryujinx.Ava.UI.ViewModels
 
         public async void Add()
         {
-            OpenFileDialog dialog = new OpenFileDialog()
+            OpenFileDialog dialog = new()
             {
-                Title         = LocaleManager.Instance[LocaleKeys.SelectDlcDialogTitle],
-                AllowMultiple = true
+                Title = LocaleManager.Instance[LocaleKeys.SelectDlcDialogTitle],
+                AllowMultiple = true,
             };
 
             dialog.Filters.Add(new FileDialogFilter
             {
-                Name       = "NSP",
-                Extensions = { "nsp" }
+                Name = "NSP",
+                Extensions = { "nsp" },
             });
 
-            if (Avalonia.Application.Current.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
+            if (Application.Current.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
             {
                 string[] files = await dialog.ShowAsync(desktop.MainWindow);
 
@@ -231,8 +230,8 @@ namespace Ryujinx.Ava.UI.ViewModels
 
             using FileStream containerFile = File.OpenRead(path);
 
-            PartitionFileSystem partitionFileSystem         = new(containerFile.AsStorage());
-            bool                containsDownloadableContent = false;
+            PartitionFileSystem partitionFileSystem = new(containerFile.AsStorage());
+            bool containsDownloadableContent = false;
 
             _virtualFileSystem.ImportTickets(partitionFileSystem);
 
@@ -313,16 +312,16 @@ namespace Ryujinx.Ava.UI.ViewModels
 
                     container = new DownloadableContentContainer
                     {
-                        ContainerPath              = downloadableContent.ContainerPath,
-                        DownloadableContentNcaList = new List<DownloadableContentNca>()
+                        ContainerPath = downloadableContent.ContainerPath,
+                        DownloadableContentNcaList = new List<DownloadableContentNca>(),
                     };
                 }
 
                 container.DownloadableContentNcaList.Add(new DownloadableContentNca
                 {
-                    Enabled  = downloadableContent.Enabled,
-                    TitleId  = Convert.ToUInt64(downloadableContent.TitleId, 16),
-                    FullPath = downloadableContent.FullPath
+                    Enabled = downloadableContent.Enabled,
+                    TitleId = Convert.ToUInt64(downloadableContent.TitleId, 16),
+                    FullPath = downloadableContent.FullPath,
                 });
             }
 
@@ -331,8 +330,8 @@ namespace Ryujinx.Ava.UI.ViewModels
                 _downloadableContentContainerList.Add(container);
             }
 
-            JsonHelper.SerializeToFile(_downloadableContentJsonPath, _downloadableContentContainerList, SerializerContext.ListDownloadableContentContainer);
+            JsonHelper.SerializeToFile(_downloadableContentJsonPath, _downloadableContentContainerList, _serializerContext.ListDownloadableContentContainer);
         }
 
     }
-}
+}

+ 57 - 45
src/Ryujinx.Ava/UI/ViewModels/MainWindowViewModel.cs

@@ -1,3 +1,4 @@
+using Avalonia;
 using Avalonia.Controls;
 using Avalonia.Controls.ApplicationLifetimes;
 using Avalonia.Input;
@@ -12,6 +13,7 @@ using Ryujinx.Ava.Input;
 using Ryujinx.Ava.UI.Controls;
 using Ryujinx.Ava.UI.Helpers;
 using Ryujinx.Ava.UI.Models;
+using Ryujinx.Ava.UI.Models.Generic;
 using Ryujinx.Ava.UI.Renderer;
 using Ryujinx.Ava.UI.Windows;
 using Ryujinx.Common;
@@ -23,6 +25,7 @@ using Ryujinx.HLE.FileSystem;
 using Ryujinx.HLE.HOS;
 using Ryujinx.HLE.HOS.Services.Account.Acc;
 using Ryujinx.HLE.Ui;
+using Ryujinx.Modules;
 using Ryujinx.Ui.App.Common;
 using Ryujinx.Ui.Common;
 using Ryujinx.Ui.Common.Configuration;
@@ -34,7 +37,10 @@ using System.Collections.ObjectModel;
 using System.IO;
 using System.Threading;
 using System.Threading.Tasks;
-using Path = System.IO.Path;
+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;
 
 namespace Ryujinx.Ava.UI.ViewModels
@@ -89,7 +95,7 @@ namespace Ryujinx.Ava.UI.ViewModels
         private Cursor _cursor;
         private string _title;
         private string _currentEmulatedGamePath;
-        private AutoResetEvent _rendererWaitEvent;
+        private readonly AutoResetEvent _rendererWaitEvent;
         private WindowState _windowState;
         private double _windowWidth;
         private double _windowHeight;
@@ -128,7 +134,7 @@ namespace Ryujinx.Ava.UI.ViewModels
             ApplicationLibrary applicationLibrary,
             VirtualFileSystem virtualFileSystem,
             AccountManager accountManager,
-            Ryujinx.Input.HLE.InputManager inputManager,
+            InputManager inputManager,
             UserChannelPersistence userChannelPersistence,
             LibHacHorizonManager libHacHorizonManager,
             IHostUiHandler uiHandler,
@@ -152,7 +158,7 @@ namespace Ryujinx.Ava.UI.ViewModels
             TopLevel = topLevel;
         }
 
-#region Properties
+        #region Properties
 
         public string SearchText
         {
@@ -177,7 +183,7 @@ namespace Ryujinx.Ava.UI.ViewModels
 
         public bool CanUpdate
         {
-            get => _canUpdate && EnableNonGameRunningControls && Modules.Updater.CanUpdate(false);
+            get => _canUpdate && EnableNonGameRunningControls && Updater.CanUpdate(false);
             set
             {
                 _canUpdate = value;
@@ -343,11 +349,11 @@ namespace Ryujinx.Ava.UI.ViewModels
             }
         }
 
-        public bool OpenUserSaveDirectoryEnabled => !Utilities.IsZeros(SelectedApplication.ControlHolder.ByteSpan) && SelectedApplication.ControlHolder.Value.UserAccountSaveDataSize > 0;
+        public bool OpenUserSaveDirectoryEnabled => !SelectedApplication.ControlHolder.ByteSpan.IsZeros() && SelectedApplication.ControlHolder.Value.UserAccountSaveDataSize > 0;
 
-        public bool OpenDeviceSaveDirectoryEnabled => !Utilities.IsZeros(SelectedApplication.ControlHolder.ByteSpan) && SelectedApplication.ControlHolder.Value.DeviceSaveDataSize > 0;
+        public bool OpenDeviceSaveDirectoryEnabled => !SelectedApplication.ControlHolder.ByteSpan.IsZeros() && SelectedApplication.ControlHolder.Value.DeviceSaveDataSize > 0;
 
-        public bool OpenBcatSaveDirectoryEnabled => !Utilities.IsZeros(SelectedApplication.ControlHolder.ByteSpan) && SelectedApplication.ControlHolder.Value.BcatDeliveryCacheStorageSize > 0;
+        public bool OpenBcatSaveDirectoryEnabled => !SelectedApplication.ControlHolder.ByteSpan.IsZeros() && SelectedApplication.ControlHolder.Value.BcatDeliveryCacheStorageSize > 0;
 
         public string LoadHeading
         {
@@ -888,7 +894,7 @@ namespace Ryujinx.Ava.UI.ViewModels
         public ApplicationLibrary ApplicationLibrary { get; private set; }
         public VirtualFileSystem VirtualFileSystem { get; private set; }
         public AccountManager AccountManager { get; private set; }
-        public Ryujinx.Input.HLE.InputManager InputManager { get; private set; }
+        public InputManager InputManager { get; private set; }
         public UserChannelPersistence UserChannelPersistence { get; private set; }
         public Action<bool> ShowLoading { get; private set; }
         public Action<bool> SwitchToGameControl { get; private set; }
@@ -911,15 +917,16 @@ namespace Ryujinx.Ava.UI.ViewModels
         public bool IsGridLarge => ConfigurationState.Instance.Ui.GridSize == 3;
         public bool IsGridHuge => ConfigurationState.Instance.Ui.GridSize == 4;
 
-#endregion
+        #endregion
 
-#region PrivateMethods
+        #region PrivateMethods
 
         private IComparer<ApplicationData> GetComparer()
         {
             return SortMode switch
             {
-                ApplicationSort.LastPlayed      => new Models.Generic.LastPlayedSortComparer(IsAscending),
+#pragma warning disable IDE0055 // Disable formatting
+                ApplicationSort.LastPlayed      => new LastPlayedSortComparer(IsAscending),
                 ApplicationSort.FileSize        => IsAscending  ? SortExpressionComparer<ApplicationData>.Ascending(app => app.FileSizeBytes)
                                                                 : SortExpressionComparer<ApplicationData>.Descending(app => app.FileSizeBytes),
                 ApplicationSort.TotalTimePlayed => IsAscending  ? SortExpressionComparer<ApplicationData>.Ascending(app => app.TimePlayedNum)
@@ -935,6 +942,7 @@ namespace Ryujinx.Ava.UI.ViewModels
                 ApplicationSort.Path            => IsAscending  ? SortExpressionComparer<ApplicationData>.Ascending(app => app.Path)
                                                                 : SortExpressionComparer<ApplicationData>.Descending(app => app.Path),
                 _ => null,
+#pragma warning restore IDE0055
             };
         }
 
@@ -1023,7 +1031,7 @@ namespace Ryujinx.Ava.UI.ViewModels
 
                                 // Purge Applet Cache.
 
-                                DirectoryInfo miiEditorCacheFolder = new DirectoryInfo(Path.Combine(AppDataManager.GamesDirPath, "0100000000001009", "cache"));
+                                DirectoryInfo miiEditorCacheFolder = new(Path.Combine(AppDataManager.GamesDirPath, "0100000000001009", "cache"));
 
                                 if (miiEditorCacheFolder.Exists)
                                 {
@@ -1044,18 +1052,21 @@ namespace Ryujinx.Ava.UI.ViewModels
                         {
                             RefreshFirmwareStatus();
                         }
-                    }) { Name = "GUI.FirmwareInstallerThread" };
+                    })
+                    {
+                        Name = "GUI.FirmwareInstallerThread",
+                    };
 
                     thread.Start();
                 }
             }
-            catch (LibHac.Common.Keys.MissingKeyException ex)
+            catch (MissingKeyException ex)
             {
-                if (Avalonia.Application.Current.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
+                if (Application.Current.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
                 {
                     Logger.Error?.Print(LogClass.Application, ex.ToString());
 
-                    async void Action() => await UserErrorDialog.ShowUserErrorDialog(UserError.NoKeys, (desktop.MainWindow as MainWindow));
+                    static async void Action() => await UserErrorDialog.ShowUserErrorDialog(UserError.NoKeys);
 
                     Dispatcher.UIThread.Post(Action);
                 }
@@ -1120,7 +1131,7 @@ namespace Ryujinx.Ava.UI.ViewModels
         private void PrepareLoadScreen()
         {
             using MemoryStream stream = new(SelectedIcon);
-            using var gameIconBmp = SixLabors.ImageSharp.Image.Load<Bgra32>(stream);
+            using var gameIconBmp = Image.Load<Bgra32>(stream);
 
             var dominantColor = IconColorPicker.GetFilteredColor(gameIconBmp).ToPixel<Bgra32>();
 
@@ -1175,7 +1186,7 @@ namespace Ryujinx.Ava.UI.ViewModels
             {
                 Dispatcher.UIThread.InvokeAsync(() =>
                 {
-                    Avalonia.Application.Current.Styles.TryGetResource(args.VSyncEnabled
+                    Application.Current.Styles.TryGetResource(args.VSyncEnabled
                         ? "VsyncEnabled"
                         : "VsyncDisabled", out object color);
 
@@ -1204,11 +1215,11 @@ namespace Ryujinx.Ava.UI.ViewModels
             _rendererWaitEvent.Set();
         }
 
-#endregion
+        #endregion
 
-#region PublicMethods
+        #region PublicMethods
 
-        public void SetUIProgressHandlers(Switch emulationContext)
+        public void SetUiProgressHandlers(Switch emulationContext)
         {
             if (emulationContext.Processes.ActiveApplication.DiskCacheLoadState != null)
             {
@@ -1222,17 +1233,17 @@ namespace Ryujinx.Ava.UI.ViewModels
 
         public void LoadConfigurableHotKeys()
         {
-            if (AvaloniaKeyboardMappingHelper.TryGetAvaKey((Ryujinx.Input.Key)ConfigurationState.Instance.Hid.Hotkeys.Value.ShowUi, out var showUiKey))
+            if (AvaloniaKeyboardMappingHelper.TryGetAvaKey((Key)ConfigurationState.Instance.Hid.Hotkeys.Value.ShowUi, out var showUiKey))
             {
                 ShowUiKey = new KeyGesture(showUiKey);
             }
 
-            if (AvaloniaKeyboardMappingHelper.TryGetAvaKey((Ryujinx.Input.Key)ConfigurationState.Instance.Hid.Hotkeys.Value.Screenshot, out var screenshotKey))
+            if (AvaloniaKeyboardMappingHelper.TryGetAvaKey((Key)ConfigurationState.Instance.Hid.Hotkeys.Value.Screenshot, out var screenshotKey))
             {
                 ScreenshotKey = new KeyGesture(screenshotKey);
             }
 
-            if (AvaloniaKeyboardMappingHelper.TryGetAvaKey((Ryujinx.Input.Key)ConfigurationState.Instance.Hid.Hotkeys.Value.Pause, out var pauseKey))
+            if (AvaloniaKeyboardMappingHelper.TryGetAvaKey((Key)ConfigurationState.Instance.Hid.Hotkeys.Value.Pause, out var pauseKey))
             {
                 PauseKey = new KeyGesture(pauseKey);
             }
@@ -1260,12 +1271,12 @@ namespace Ryujinx.Ava.UI.ViewModels
 
         public async void InstallFirmwareFromFile()
         {
-            if (Avalonia.Application.Current.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
+            if (Application.Current.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
             {
                 OpenFileDialog dialog = new() { AllowMultiple = false };
                 dialog.Filters.Add(new FileDialogFilter { Name = LocaleManager.Instance[LocaleKeys.FileDialogAllTypes], Extensions = { "xci", "zip" } });
-                dialog.Filters.Add(new FileDialogFilter { Name = "XCI",                                                 Extensions = { "xci" } });
-                dialog.Filters.Add(new FileDialogFilter { Name = "ZIP",                                                 Extensions = { "zip" } });
+                dialog.Filters.Add(new FileDialogFilter { Name = "XCI", Extensions = { "xci" } });
+                dialog.Filters.Add(new FileDialogFilter { Name = "ZIP", Extensions = { "zip" } });
 
                 string[] file = await dialog.ShowAsync(desktop.MainWindow);
 
@@ -1278,7 +1289,7 @@ namespace Ryujinx.Ava.UI.ViewModels
 
         public async void InstallFirmwareFromFolder()
         {
-            if (Avalonia.Application.Current.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
+            if (Application.Current.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
             {
                 OpenFolderDialog dialog = new();
 
@@ -1327,7 +1338,7 @@ namespace Ryujinx.Ava.UI.ViewModels
             }
         }
 
-        public void ChangeLanguage(object languageCode)
+        public static void ChangeLanguage(object languageCode)
         {
             LocaleManager.Instance.LoadLanguage((string)languageCode);
 
@@ -1342,6 +1353,7 @@ namespace Ryujinx.Ava.UI.ViewModels
         {
             _ = fileType switch
             {
+#pragma warning disable IDE0055 // Disable formatting
                 "NSP"  => ConfigurationState.Instance.Ui.ShownFileTypes.NSP.Value  = !ConfigurationState.Instance.Ui.ShownFileTypes.NSP,
                 "PFS0" => ConfigurationState.Instance.Ui.ShownFileTypes.PFS0.Value = !ConfigurationState.Instance.Ui.ShownFileTypes.PFS0,
                 "XCI"  => ConfigurationState.Instance.Ui.ShownFileTypes.XCI.Value  = !ConfigurationState.Instance.Ui.ShownFileTypes.XCI,
@@ -1349,6 +1361,7 @@ namespace Ryujinx.Ava.UI.ViewModels
                 "NRO"  => ConfigurationState.Instance.Ui.ShownFileTypes.NRO.Value  = !ConfigurationState.Instance.Ui.ShownFileTypes.NRO,
                 "NSO"  => ConfigurationState.Instance.Ui.ShownFileTypes.NSO.Value  = !ConfigurationState.Instance.Ui.ShownFileTypes.NSO,
                     _  => throw new ArgumentOutOfRangeException(fileType),
+#pragma warning restore IDE0055
             };
 
             ConfigurationState.Instance.ToFileFormat().SaveConfig(Program.ConfigurationPath);
@@ -1371,9 +1384,9 @@ namespace Ryujinx.Ava.UI.ViewModels
             {
                 Applications.Clear();
 
-                StatusBarVisible         = true;
+                StatusBarVisible = true;
                 StatusBarProgressMaximum = 0;
-                StatusBarProgressValue   = 0;
+                StatusBarProgressValue = 0;
 
                 LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.StatusBarGamesLoaded, 0, 0);
             });
@@ -1383,11 +1396,11 @@ namespace Ryujinx.Ava.UI.ViewModels
 
         public async void OpenFile()
         {
-            if (Avalonia.Application.Current.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
+            if (Application.Current.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
             {
                 OpenFileDialog dialog = new()
                 {
-                    Title = LocaleManager.Instance[LocaleKeys.OpenFileDialogTitle]
+                    Title = LocaleManager.Instance[LocaleKeys.OpenFileDialogTitle],
                 };
 
                 dialog.Filters.Add(new FileDialogFilter
@@ -1400,16 +1413,18 @@ namespace Ryujinx.Ava.UI.ViewModels
                         "xci",
                         "nca",
                         "nro",
-                        "nso"
-                    }
+                        "nso",
+                    },
                 });
 
+#pragma warning disable IDE0055 // Disable formatting
                 dialog.Filters.Add(new FileDialogFilter { Name = "NSP",  Extensions = { "nsp" } });
                 dialog.Filters.Add(new FileDialogFilter { Name = "PFS0", Extensions = { "pfs0" } });
                 dialog.Filters.Add(new FileDialogFilter { Name = "XCI",  Extensions = { "xci" } });
                 dialog.Filters.Add(new FileDialogFilter { Name = "NCA",  Extensions = { "nca" } });
                 dialog.Filters.Add(new FileDialogFilter { Name = "NRO",  Extensions = { "nro" } });
                 dialog.Filters.Add(new FileDialogFilter { Name = "NSO",  Extensions = { "nso" } });
+#pragma warning restore IDE0055
 
                 string[] files = await dialog.ShowAsync(desktop.MainWindow);
 
@@ -1422,11 +1437,11 @@ namespace Ryujinx.Ava.UI.ViewModels
 
         public async void OpenFolder()
         {
-            if (Avalonia.Application.Current.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
+            if (Application.Current.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
             {
                 OpenFolderDialog dialog = new()
                 {
-                    Title = LocaleManager.Instance[LocaleKeys.OpenFolderDialogTitle]
+                    Title = LocaleManager.Instance[LocaleKeys.OpenFolderDialogTitle],
                 };
 
                 string folder = await dialog.ShowAsync(desktop.MainWindow);
@@ -1458,10 +1473,7 @@ namespace Ryujinx.Ava.UI.ViewModels
 
             Logger.RestartTime();
 
-            if (SelectedIcon == null)
-            {
-                SelectedIcon = ApplicationLibrary.GetApplicationIcon(path);
-            }
+            SelectedIcon ??= ApplicationLibrary.GetApplicationIcon(path);
 
             PrepareLoadScreen();
 
@@ -1495,7 +1507,7 @@ namespace Ryujinx.Ava.UI.ViewModels
                 if (string.IsNullOrWhiteSpace(titleName))
                 {
                     LoadHeading = LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.LoadingHeading, AppHost.Device.Processes.ActiveApplication.Name);
-                    TitleName   = AppHost.Device.Processes.ActiveApplication.Name;
+                    TitleName = AppHost.Device.Processes.ActiveApplication.Name;
                 }
 
                 SwitchToRenderer(startFullscreen);
@@ -1521,7 +1533,7 @@ namespace Ryujinx.Ava.UI.ViewModels
             });
         }
 
-        public void UpdateGameMetadata(string titleId)
+        public static void UpdateGameMetadata(string titleId)
         {
             ApplicationLibrary.LoadAndSaveMetaData(titleId, appMetadata =>
             {
@@ -1675,6 +1687,6 @@ namespace Ryujinx.Ava.UI.ViewModels
             }
         }
 
-#endregion
+        #endregion
     }
 }

+ 1 - 1
src/Ryujinx.Ava/UI/ViewModels/MotionInputViewModel.cs

@@ -90,4 +90,4 @@ namespace Ryujinx.Ava.UI.ViewModels
             }
         }
     }
-}
+}

+ 1 - 1
src/Ryujinx.Ava/UI/ViewModels/RumbleInputViewModel.cs

@@ -24,4 +24,4 @@ namespace Ryujinx.Ava.UI.ViewModels
             }
         }
     }
-}
+}

+ 3 - 4
src/Ryujinx.Ava/UI/ViewModels/SettingsViewModel.cs

@@ -18,7 +18,6 @@ using Ryujinx.HLE.FileSystem;
 using Ryujinx.HLE.HOS.Services.Time.TimeZone;
 using Ryujinx.Ui.Common.Configuration;
 using Ryujinx.Ui.Common.Configuration.System;
-using Silk.NET.Vulkan;
 using System;
 using System.Collections.Generic;
 using System.Collections.ObjectModel;
@@ -248,7 +247,7 @@ namespace Ryujinx.Ava.UI.ViewModels
 
         public AvaloniaList<string> NetworkInterfaceList
         {
-            get => new AvaloniaList<string>(_networkInterfaces.Keys);
+            get => new(_networkInterfaces.Keys);
         }
 
         public KeyboardHotkeys KeyboardHotkeys
@@ -561,7 +560,7 @@ namespace Ryujinx.Ava.UI.ViewModels
             _directoryChanged = false;
         }
 
-        public void RevertIfNotSaved()
+        private static void RevertIfNotSaved()
         {
             Program.ReloadConfig();
         }
@@ -583,4 +582,4 @@ namespace Ryujinx.Ava.UI.ViewModels
             CloseWindow?.Invoke();
         }
     }
-}
+}

+ 30 - 31
src/Ryujinx.Ava/UI/ViewModels/TitleUpdateViewModel.cs

@@ -1,3 +1,4 @@
+using Avalonia;
 using Avalonia.Collections;
 using Avalonia.Controls;
 using Avalonia.Controls.ApplicationLifetimes;
@@ -16,7 +17,6 @@ using Ryujinx.Common.Configuration;
 using Ryujinx.Common.Logging;
 using Ryujinx.Common.Utilities;
 using Ryujinx.HLE.FileSystem;
-using Ryujinx.HLE.HOS;
 using Ryujinx.Ui.App.Common;
 using System;
 using System.Collections.Generic;
@@ -29,17 +29,16 @@ namespace Ryujinx.Ava.UI.ViewModels
 {
     public class TitleUpdateViewModel : BaseModel
     {
-        public TitleUpdateMetadata _titleUpdateWindowData;
-        public readonly string     _titleUpdateJsonPath;
-        private VirtualFileSystem  _virtualFileSystem { get; }
-        private ulong              _titleId           { get; }
-        private string             _titleName         { get; }
+        public TitleUpdateMetadata TitleUpdateWindowData;
+        public readonly string TitleUpdateJsonPath;
+        private VirtualFileSystem VirtualFileSystem { get; }
+        private ulong TitleId { get; }
 
         private AvaloniaList<TitleUpdateModel> _titleUpdates = new();
         private AvaloniaList<object> _views = new();
         private object _selectedUpdate;
 
-        private static readonly TitleUpdateMetadataJsonSerializerContext SerializerContext = new(JsonHelper.GetDefaultSerializerOptions());
+        private static readonly TitleUpdateMetadataJsonSerializerContext _serializerContext = new(JsonHelper.GetDefaultSerializerOptions());
 
         public AvaloniaList<TitleUpdateModel> TitleUpdates
         {
@@ -71,27 +70,26 @@ namespace Ryujinx.Ava.UI.ViewModels
             }
         }
 
-        public TitleUpdateViewModel(VirtualFileSystem virtualFileSystem, ulong titleId, string titleName)
+        public TitleUpdateViewModel(VirtualFileSystem virtualFileSystem, ulong titleId)
         {
-            _virtualFileSystem = virtualFileSystem;
+            VirtualFileSystem = virtualFileSystem;
 
-            _titleId   = titleId;
-            _titleName = titleName;
+            TitleId = titleId;
 
-            _titleUpdateJsonPath = Path.Combine(AppDataManager.GamesDirPath, titleId.ToString("x16"), "updates.json");
+            TitleUpdateJsonPath = Path.Combine(AppDataManager.GamesDirPath, titleId.ToString("x16"), "updates.json");
 
             try
             {
-                _titleUpdateWindowData = JsonHelper.DeserializeFromFile(_titleUpdateJsonPath, SerializerContext.TitleUpdateMetadata);
+                TitleUpdateWindowData = JsonHelper.DeserializeFromFile(TitleUpdateJsonPath, _serializerContext.TitleUpdateMetadata);
             }
             catch
             {
-                Logger.Warning?.Print(LogClass.Application, $"Failed to deserialize title update data for {_titleId} at {_titleUpdateJsonPath}");
+                Logger.Warning?.Print(LogClass.Application, $"Failed to deserialize title update data for {TitleId} at {TitleUpdateJsonPath}");
 
-                _titleUpdateWindowData = new TitleUpdateMetadata
+                TitleUpdateWindowData = new TitleUpdateMetadata
                 {
                     Selected = "",
-                    Paths    = new List<string>()
+                    Paths = new List<string>(),
                 };
 
                 Save();
@@ -102,12 +100,12 @@ namespace Ryujinx.Ava.UI.ViewModels
 
         private void LoadUpdates()
         {
-            foreach (string path in _titleUpdateWindowData.Paths)
+            foreach (string path in TitleUpdateWindowData.Paths)
             {
                 AddUpdate(path);
             }
 
-            TitleUpdateModel selected = TitleUpdates.FirstOrDefault(x => x.Path == _titleUpdateWindowData.Selected, null);
+            TitleUpdateModel selected = TitleUpdates.FirstOrDefault(x => x.Path == TitleUpdateWindowData.Selected, null);
 
             SelectedUpdate = selected;
 
@@ -126,7 +124,8 @@ namespace Ryujinx.Ava.UI.ViewModels
                 {
                     return -1;
                 }
-                else if (string.IsNullOrEmpty(second.Control.DisplayVersionString.ToString()))
+
+                if (string.IsNullOrEmpty(second.Control.DisplayVersionString.ToString()))
                 {
                     return 1;
                 }
@@ -163,7 +162,7 @@ namespace Ryujinx.Ava.UI.ViewModels
 
                 try
                 {
-                    (Nca patchNca, Nca controlNca) = ApplicationLibrary.GetGameUpdateDataFromPartition(_virtualFileSystem, new PartitionFileSystem(file.AsStorage()), _titleId.ToString("x16"), 0);
+                    (Nca patchNca, Nca controlNca) = ApplicationLibrary.GetGameUpdateDataFromPartition(VirtualFileSystem, new PartitionFileSystem(file.AsStorage()), TitleId.ToString("x16"), 0);
 
                     if (controlNca != null && patchNca != null)
                     {
@@ -205,17 +204,17 @@ namespace Ryujinx.Ava.UI.ViewModels
         {
             OpenFileDialog dialog = new()
             {
-                Title         = LocaleManager.Instance[LocaleKeys.SelectUpdateDialogTitle],
-                AllowMultiple = true
+                Title = LocaleManager.Instance[LocaleKeys.SelectUpdateDialogTitle],
+                AllowMultiple = true,
             };
 
             dialog.Filters.Add(new FileDialogFilter
             {
-                Name       = "NSP",
-                Extensions = { "nsp" }
+                Name = "NSP",
+                Extensions = { "nsp" },
             });
 
-            if (Avalonia.Application.Current.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
+            if (Application.Current.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
             {
                 string[] files = await dialog.ShowAsync(desktop.MainWindow);
 
@@ -233,20 +232,20 @@ namespace Ryujinx.Ava.UI.ViewModels
 
         public void Save()
         {
-            _titleUpdateWindowData.Paths.Clear();
-            _titleUpdateWindowData.Selected = "";
+            TitleUpdateWindowData.Paths.Clear();
+            TitleUpdateWindowData.Selected = "";
 
             foreach (TitleUpdateModel update in TitleUpdates)
             {
-                _titleUpdateWindowData.Paths.Add(update.Path);
+                TitleUpdateWindowData.Paths.Add(update.Path);
 
                 if (update == SelectedUpdate)
                 {
-                    _titleUpdateWindowData.Selected = update.Path;
+                    TitleUpdateWindowData.Selected = update.Path;
                 }
             }
 
-            JsonHelper.SerializeToFile(_titleUpdateJsonPath, _titleUpdateWindowData, SerializerContext.TitleUpdateMetadata);
+            JsonHelper.SerializeToFile(TitleUpdateJsonPath, TitleUpdateWindowData, _serializerContext.TitleUpdateMetadata);
         }
     }
-}
+}

+ 77 - 85
src/Ryujinx.Ava/UI/ViewModels/UserFirmwareAvatarSelectorViewModel.cs

@@ -28,7 +28,6 @@ namespace Ryujinx.Ava.UI.ViewModels
         private Color _backgroundColor = Colors.White;
 
         private int _selectedIndex;
-        private byte[] _selectedImage;
 
         public UserFirmwareAvatarSelectorViewModel()
         {
@@ -78,11 +77,7 @@ namespace Ryujinx.Ava.UI.ViewModels
             }
         }
 
-        public byte[] SelectedImage
-        {
-            get => _selectedImage;
-            private set => _selectedImage = value;
-        }
+        public byte[] SelectedImage { get; private set; }
 
         private void LoadImagesFromStore()
         {
@@ -114,34 +109,32 @@ namespace Ryujinx.Ava.UI.ViewModels
 
             if (!string.IsNullOrWhiteSpace(avatarPath))
             {
-                using (IStorage ncaFileStream = new LocalStorage(avatarPath, FileAccess.Read, FileMode.Open))
-                {
-                    Nca nca = new(virtualFileSystem.KeySet, ncaFileStream);
-                    IFileSystem romfs = nca.OpenFileSystem(NcaSectionType.Data, IntegrityCheckLevel.ErrorOnInvalid);
+                using IStorage ncaFileStream = new LocalStorage(avatarPath, FileAccess.Read, FileMode.Open);
+
+                Nca nca = new(virtualFileSystem.KeySet, ncaFileStream);
+                IFileSystem romfs = nca.OpenFileSystem(NcaSectionType.Data, IntegrityCheckLevel.ErrorOnInvalid);
 
-                    foreach (DirectoryEntryEx item in romfs.EnumerateEntries())
+                foreach (DirectoryEntryEx item in romfs.EnumerateEntries())
+                {
+                    // TODO: Parse DatabaseInfo.bin and table.bin files for more accuracy.
+                    if (item.Type == DirectoryEntryType.File && item.FullPath.Contains("chara") && item.FullPath.Contains("szs"))
                     {
-                        // TODO: Parse DatabaseInfo.bin and table.bin files for more accuracy.
-                        if (item.Type == DirectoryEntryType.File && item.FullPath.Contains("chara") && item.FullPath.Contains("szs"))
-                        {
-                            using var file = new UniqueRef<IFile>();
+                        using var file = new UniqueRef<IFile>();
+
+                        romfs.OpenFile(ref file.Ref, ("/" + item.FullPath).ToU8Span(), OpenMode.Read).ThrowIfFailure();
 
-                            romfs.OpenFile(ref file.Ref, ("/" + item.FullPath).ToU8Span(), OpenMode.Read).ThrowIfFailure();
+                        using MemoryStream stream = new();
+                        using MemoryStream streamPng = new();
 
-                            using (MemoryStream stream = new())
-                            using (MemoryStream streamPng = new())
-                            {
-                                file.Get.AsStream().CopyTo(stream);
+                        file.Get.AsStream().CopyTo(stream);
 
-                                stream.Position = 0;
+                        stream.Position = 0;
 
-                                Image avatarImage = Image.LoadPixelData<Rgba32>(DecompressYaz0(stream), 256, 256);
+                        Image avatarImage = Image.LoadPixelData<Rgba32>(DecompressYaz0(stream), 256, 256);
 
-                                avatarImage.SaveAsPng(streamPng);
+                        avatarImage.SaveAsPng(streamPng);
 
-                                _avatarStore.Add(item.FullPath, streamPng.ToArray());
-                            }
-                        }
+                        _avatarStore.Add(item.FullPath, streamPng.ToArray());
                     }
                 }
             }
@@ -149,82 +142,81 @@ namespace Ryujinx.Ava.UI.ViewModels
 
         private static byte[] DecompressYaz0(Stream stream)
         {
-            using (BinaryReader reader = new(stream))
-            {
-                reader.ReadInt32(); // Magic
+            using BinaryReader reader = new(stream);
 
-                uint decodedLength = BinaryPrimitives.ReverseEndianness(reader.ReadUInt32());
+            reader.ReadInt32(); // Magic
 
-                reader.ReadInt64(); // Padding
+            uint decodedLength = BinaryPrimitives.ReverseEndianness(reader.ReadUInt32());
 
-                byte[] input = new byte[stream.Length - stream.Position];
-                stream.Read(input, 0, input.Length);
+            reader.ReadInt64(); // Padding
 
-                uint inputOffset = 0;
+            byte[] input = new byte[stream.Length - stream.Position];
+            stream.Read(input, 0, input.Length);
 
-                byte[] output = new byte[decodedLength];
-                uint outputOffset = 0;
+            uint inputOffset = 0;
 
-                ushort mask = 0;
-                byte header = 0;
+            byte[] output = new byte[decodedLength];
+            uint outputOffset = 0;
 
-                while (outputOffset < decodedLength)
+            ushort mask = 0;
+            byte header = 0;
+
+            while (outputOffset < decodedLength)
+            {
+                if ((mask >>= 1) == 0)
                 {
-                    if ((mask >>= 1) == 0)
+                    header = input[inputOffset++];
+                    mask = 0x80;
+                }
+
+                if ((header & mask) != 0)
+                {
+                    if (outputOffset == output.Length)
                     {
-                        header = input[inputOffset++];
-                        mask = 0x80;
+                        break;
                     }
 
-                    if ((header & mask) != 0)
-                    {
-                        if (outputOffset == output.Length)
-                        {
-                            break;
-                        }
+                    output[outputOffset++] = input[inputOffset++];
+                }
+                else
+                {
+                    byte byte1 = input[inputOffset++];
+                    byte byte2 = input[inputOffset++];
 
-                        output[outputOffset++] = input[inputOffset++];
+                    uint dist = (uint)((byte1 & 0xF) << 8) | byte2;
+                    uint position = outputOffset - (dist + 1);
+
+                    uint length = (uint)byte1 >> 4;
+                    if (length == 0)
+                    {
+                        length = (uint)input[inputOffset++] + 0x12;
                     }
                     else
                     {
-                        byte byte1 = input[inputOffset++];
-                        byte byte2 = input[inputOffset++];
-
-                        uint dist = (uint)((byte1 & 0xF) << 8) | byte2;
-                        uint position = outputOffset - (dist + 1);
-
-                        uint length = (uint)byte1 >> 4;
-                        if (length == 0)
-                        {
-                            length = (uint)input[inputOffset++] + 0x12;
-                        }
-                        else
-                        {
-                            length += 2;
-                        }
-
-                        uint gap = outputOffset - position;
-                        uint nonOverlappingLength = length;
-
-                        if (nonOverlappingLength > gap)
-                        {
-                            nonOverlappingLength = gap;
-                        }
-
-                        Buffer.BlockCopy(output, (int)position, output, (int)outputOffset, (int)nonOverlappingLength);
-                        outputOffset += nonOverlappingLength;
-                        position += nonOverlappingLength;
-                        length -= nonOverlappingLength;
-
-                        while (length-- > 0)
-                        {
-                            output[outputOffset++] = output[position++];
-                        }
+                        length += 2;
+                    }
+
+                    uint gap = outputOffset - position;
+                    uint nonOverlappingLength = length;
+
+                    if (nonOverlappingLength > gap)
+                    {
+                        nonOverlappingLength = gap;
                     }
-                }
 
-                return output;
+                    Buffer.BlockCopy(output, (int)position, output, (int)outputOffset, (int)nonOverlappingLength);
+                    outputOffset += nonOverlappingLength;
+                    position += nonOverlappingLength;
+                    length -= nonOverlappingLength;
+
+                    while (length-- > 0)
+                    {
+                        output[outputOffset++] = output[position++];
+                    }
+                }
             }
+
+            return output;
         }
     }
-}
+}

+ 2 - 2
src/Ryujinx.Ava/UI/ViewModels/UserProfileImageSelectorViewModel.cs

@@ -7,7 +7,7 @@ namespace Ryujinx.Ava.UI.ViewModels
         public bool FirmwareFound
         {
             get => _firmwareFound;
-        
+
             set
             {
                 _firmwareFound = value;
@@ -15,4 +15,4 @@ namespace Ryujinx.Ava.UI.ViewModels
             }
         }
     }
-}
+}

+ 6 - 3
src/Ryujinx.Ava/UI/ViewModels/UserProfileViewModel.cs

@@ -1,7 +1,7 @@
 using Microsoft.IdentityModel.Tokens;
+using Ryujinx.Ava.UI.Models;
 using System;
 using System.Collections.ObjectModel;
-using UserProfile = Ryujinx.Ava.UI.Models.UserProfile;
 
 namespace Ryujinx.Ava.UI.ViewModels
 {
@@ -20,6 +20,9 @@ namespace Ryujinx.Ava.UI.ViewModels
 
         public bool IsEmpty { get; set; }
 
-        public void Dispose() { }
+        public void Dispose()
+        {
+            GC.SuppressFinalize(this);
+        }
     }
-}
+}

+ 11 - 14
src/Ryujinx.Ava/UI/ViewModels/UserSaveManagerViewModel.cs

@@ -15,7 +15,7 @@ namespace Ryujinx.Ava.UI.ViewModels
         private string _search;
         private ObservableCollection<SaveModel> _saves = new();
         private ObservableCollection<SaveModel> _views = new();
-        private AccountManager _accountManager;
+        private readonly AccountManager _accountManager;
 
         public string SaveManagerHeading => LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.SaveManagerHeading, _accountManager.LastOpenedUser.Name, _accountManager.LastOpenedUser.UserId);
 
@@ -102,19 +102,16 @@ namespace Ryujinx.Ava.UI.ViewModels
 
         private IComparer<SaveModel> GetComparer()
         {
-            switch (SortIndex)
+            return SortIndex switch
             {
-                case 0:
-                    return OrderIndex == 0
-                        ? SortExpressionComparer<SaveModel>.Ascending(save => save.Title)
-                        : SortExpressionComparer<SaveModel>.Descending(save => save.Title);
-                case 1:
-                    return OrderIndex == 0
-                        ? SortExpressionComparer<SaveModel>.Ascending(save => save.Size)
-                        : SortExpressionComparer<SaveModel>.Descending(save => save.Size);
-                default:
-                    return null;
-            }
+                0 => OrderIndex == 0
+                    ? SortExpressionComparer<SaveModel>.Ascending(save => save.Title)
+                    : SortExpressionComparer<SaveModel>.Descending(save => save.Title),
+                1 => OrderIndex == 0
+                    ? SortExpressionComparer<SaveModel>.Ascending(save => save.Size)
+                    : SortExpressionComparer<SaveModel>.Descending(save => save.Size),
+                _ => null,
+            };
         }
     }
-}
+}

+ 2 - 2
src/Ryujinx.Ava/UI/Views/Input/ControllerInputView.axaml.cs

@@ -29,7 +29,7 @@ namespace Ryujinx.Ava.UI.Views.Input
 
             foreach (ILogical visual in SettingButtons.GetLogicalDescendants())
             {
-                if (visual is ToggleButton button && !(visual is CheckBox))
+                if (visual is ToggleButton button && visual is not CheckBox)
                 {
                     button.Checked += Button_Checked;
                     button.Unchecked += Button_Unchecked;
@@ -177,4 +177,4 @@ namespace Ryujinx.Ava.UI.Views.Input
             ViewModel.Dispose();
         }
     }
-}
+}

+ 4 - 4
src/Ryujinx.Ava/UI/Views/Input/MotionInputView.axaml.cs

@@ -10,7 +10,7 @@ namespace Ryujinx.Ava.UI.Views.Input
 {
     public partial class MotionInputView : UserControl
     {
-        private MotionInputViewModel _viewModel;
+        private readonly MotionInputViewModel _viewModel;
 
         public MotionInputView()
         {
@@ -30,7 +30,7 @@ namespace Ryujinx.Ava.UI.Views.Input
                 MirrorInput = config.MirrorInput,
                 Sensitivity = config.Sensitivity,
                 GyroDeadzone = config.GyroDeadzone,
-                EnableCemuHookMotion = config.EnableCemuHookMotion
+                EnableCemuHookMotion = config.EnableCemuHookMotion,
             };
 
             InitializeComponent();
@@ -47,7 +47,7 @@ namespace Ryujinx.Ava.UI.Views.Input
                 PrimaryButtonText = LocaleManager.Instance[LocaleKeys.ControllerSettingsSave],
                 SecondaryButtonText = "",
                 CloseButtonText = LocaleManager.Instance[LocaleKeys.ControllerSettingsClose],
-                Content = content
+                Content = content,
             };
             contentDialog.PrimaryButtonClick += (sender, args) =>
             {
@@ -65,4 +65,4 @@ namespace Ryujinx.Ava.UI.Views.Input
             await contentDialog.ShowAsync();
         }
     }
-}
+}

+ 4 - 4
src/Ryujinx.Ava/UI/Views/Input/RumbleInputView.axaml.cs

@@ -10,7 +10,7 @@ namespace Ryujinx.Ava.UI.Views.Input
 {
     public partial class RumbleInputView : UserControl
     {
-        private RumbleInputViewModel _viewModel;
+        private readonly RumbleInputViewModel _viewModel;
 
         public RumbleInputView()
         {
@@ -24,11 +24,11 @@ namespace Ryujinx.Ava.UI.Views.Input
             _viewModel = new RumbleInputViewModel
             {
                 StrongRumble = config.StrongRumble,
-                WeakRumble = config.WeakRumble
+                WeakRumble = config.WeakRumble,
             };
 
             InitializeComponent();
-            
+
             DataContext = _viewModel;
         }
 
@@ -55,4 +55,4 @@ namespace Ryujinx.Ava.UI.Views.Input
             await contentDialog.ShowAsync();
         }
     }
-}
+}

+ 11 - 11
src/Ryujinx.Ava/UI/Views/Main/MainMenuBarView.axaml.cs

@@ -38,26 +38,26 @@ namespace Ryujinx.Ava.UI.Views.Main
         {
             List<CheckBox> checkBoxes = new();
 
-            foreach (var item in Enum.GetValues(typeof (FileTypes)))
+            foreach (var item in Enum.GetValues(typeof(FileTypes)))
             {
-                string fileName = Enum.GetName(typeof (FileTypes), item);
-                checkBoxes.Add(new CheckBox()
+                string fileName = Enum.GetName(typeof(FileTypes), item);
+                checkBoxes.Add(new CheckBox
                 {
                     Content = $".{fileName}",
                     IsChecked = ((FileTypes)item).GetConfigValue(ConfigurationState.Instance.Ui.ShownFileTypes),
-                    Command = MiniCommand.Create(() => ViewModel.ToggleFileType(fileName))
+                    Command = MiniCommand.Create(() => ViewModel.ToggleFileType(fileName)),
                 });
             }
 
             return checkBoxes.ToArray();
         }
 
-        private MenuItem[] GenerateLanguageMenuItems()
+        private static MenuItem[] GenerateLanguageMenuItems()
         {
             List<MenuItem> menuItems = new();
 
             string localePath = "Ryujinx.Ava/Assets/Locales";
-            string localeExt  = ".json";
+            string localeExt = ".json";
 
             string[] localesPath = EmbeddedResources.GetAllAvailableResources(localePath, localeExt);
 
@@ -67,7 +67,7 @@ namespace Ryujinx.Ava.UI.Views.Main
             {
                 string languageCode = Path.GetFileNameWithoutExtension(locale).Split('.').Last();
                 string languageJson = EmbeddedResources.ReadAllText($"{localePath}/{languageCode}{localeExt}");
-                var    strings      = JsonHelper.Deserialize(languageJson, CommonJsonContext.Default.StringDictionary);
+                var strings = JsonHelper.Deserialize(languageJson, CommonJsonContext.Default.StringDictionary);
 
                 if (!strings.TryGetValue("Language", out string languageName))
                 {
@@ -76,11 +76,11 @@ namespace Ryujinx.Ava.UI.Views.Main
 
                 MenuItem menuItem = new()
                 {
-                    Header  = languageName,
+                    Header = languageName,
                     Command = MiniCommand.Create(() =>
                     {
-                        ViewModel.ChangeLanguage(languageCode);
-                    })
+                        MainWindowViewModel.ChangeLanguage(languageCode);
+                    }),
                 };
 
                 menuItems.Add(menuItem);
@@ -236,4 +236,4 @@ namespace Ryujinx.Ava.UI.Views.Main
             Window.Close();
         }
     }
-}
+}

+ 1 - 1
src/Ryujinx.Ava/UI/Views/Main/MainStatusBarView.axaml.cs

@@ -49,4 +49,4 @@ namespace Ryujinx.Ava.UI.Views.Main
             ConfigurationState.Instance.Graphics.AspectRatio.Value = (int)aspectRatio + 1 > Enum.GetNames(typeof(AspectRatio)).Length - 1 ? AspectRatio.Fixed4x3 : aspectRatio + 1;
         }
     }
-}
+}

+ 4 - 4
src/Ryujinx.Ava/UI/Views/Main/MainViewControls.axaml.cs

@@ -12,7 +12,7 @@ namespace Ryujinx.Ava.UI.Views.Main
     public partial class MainViewControls : UserControl
     {
         public MainWindowViewModel ViewModel;
-    
+
         public MainViewControls()
         {
             InitializeComponent();
@@ -37,7 +37,7 @@ namespace Ryujinx.Ava.UI.Views.Main
                 ViewModel.Sort(Enum.Parse<ApplicationSort>(button.Tag.ToString()));
             }
         }
-    
+
         public void Order_Checked(object sender, RoutedEventArgs args)
         {
             if (sender is RadioButton button)
@@ -45,10 +45,10 @@ namespace Ryujinx.Ava.UI.Views.Main
                 ViewModel.Sort(button.Tag.ToString() != "Descending");
             }
         }
-    
+
         private void SearchBox_OnKeyUp(object sender, KeyEventArgs e)
         {
             ViewModel.SearchText = SearchBox.Text;
         }
     }
-}
+}

+ 1 - 1
src/Ryujinx.Ava/UI/Views/Settings/SettingsAudioView.axaml.cs

@@ -9,4 +9,4 @@ namespace Ryujinx.Ava.UI.Views.Settings
             InitializeComponent();
         }
     }
-}
+}

+ 1 - 1
src/Ryujinx.Ava/UI/Views/Settings/SettingsCPUView.axaml.cs

@@ -9,4 +9,4 @@ namespace Ryujinx.Ava.UI.Views.Settings
             InitializeComponent();
         }
     }
-}
+}

+ 1 - 1
src/Ryujinx.Ava/UI/Views/Settings/SettingsGraphicsView.axaml.cs

@@ -9,4 +9,4 @@ namespace Ryujinx.Ava.UI.Views.Settings
             InitializeComponent();
         }
     }
-}
+}

+ 6 - 6
src/Ryujinx.Ava/UI/Views/Settings/SettingsHotkeysView.axaml.cs

@@ -12,12 +12,12 @@ namespace Ryujinx.Ava.UI.Views.Settings
     public partial class SettingsHotkeysView : UserControl
     {
         private ButtonKeyAssigner _currentAssigner;
-        private IGamepadDriver AvaloniaKeyboardDriver;
-    
+        private readonly IGamepadDriver _avaloniaKeyboardDriver;
+
         public SettingsHotkeysView()
         {
             InitializeComponent();
-            AvaloniaKeyboardDriver = new AvaloniaKeyboardDriver(this);
+            _avaloniaKeyboardDriver = new AvaloniaKeyboardDriver(this);
         }
 
         private void MouseClick(object sender, PointerPressedEventArgs e)
@@ -28,7 +28,7 @@ namespace Ryujinx.Ava.UI.Views.Settings
 
             PointerPressed -= MouseClick;
         }
-    
+
         private void Button_Checked(object sender, RoutedEventArgs e)
         {
             if (sender is ToggleButton button)
@@ -46,7 +46,7 @@ namespace Ryujinx.Ava.UI.Views.Settings
 
                     PointerPressed += MouseClick;
 
-                    var keyboard = (IKeyboard)AvaloniaKeyboardDriver.GetGamepad(AvaloniaKeyboardDriver.GamepadsIds[0]);
+                    var keyboard = (IKeyboard)_avaloniaKeyboardDriver.GetGamepad(_avaloniaKeyboardDriver.GamepadsIds[0]);
                     IButtonAssigner assigner = new KeyboardKeyAssigner(keyboard);
 
                     _currentAssigner.GetInputAndAssign(assigner);
@@ -78,4 +78,4 @@ namespace Ryujinx.Ava.UI.Views.Settings
             _currentAssigner = null;
         }
     }
-}
+}

+ 1 - 1
src/Ryujinx.Ava/UI/Views/Settings/SettingsInputView.axaml.cs

@@ -14,4 +14,4 @@ namespace Ryujinx.Ava.UI.Views.Settings
             ControllerSettings.Dispose();
         }
     }
-}
+}

+ 1 - 1
src/Ryujinx.Ava/UI/Views/Settings/SettingsLoggingView.axaml.cs

@@ -9,4 +9,4 @@ namespace Ryujinx.Ava.UI.Views.Settings
             InitializeComponent();
         }
     }
-}
+}

+ 1 - 1
src/Ryujinx.Ava/UI/Views/Settings/SettingsNetworkView.axaml.cs

@@ -9,4 +9,4 @@ namespace Ryujinx.Ava.UI.Views.Settings
             InitializeComponent();
         }
     }
-}
+}

+ 2 - 2
src/Ryujinx.Ava/UI/Views/Settings/SettingsSystemView.axaml.cs

@@ -15,7 +15,7 @@ namespace Ryujinx.Ava.UI.Views.Settings
         public SettingsSystemView()
         {
             InitializeComponent();
-        
+
             FuncMultiValueConverter<string, string> converter = new(parts => string.Format("{0}  {1}   {2}", parts.ToArray()).Trim());
             MultiBinding tzMultiBinding = new() { Converter = converter };
 
@@ -49,4 +49,4 @@ namespace Ryujinx.Ava.UI.Views.Settings
             }
         }
     }
-}
+}

+ 1 - 1
src/Ryujinx.Ava/UI/Views/Settings/SettingsUIView.axaml

@@ -1,5 +1,5 @@
 <UserControl
-    x:Class="Ryujinx.Ava.UI.Views.Settings.SettingsUIView"
+    x:Class="Ryujinx.Ava.UI.Views.Settings.SettingsUiView"
     xmlns="https://github.com/avaloniaui"
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
     xmlns:d="http://schemas.microsoft.com/expression/blend/2008"

+ 10 - 9
src/Ryujinx.Ava/UI/Views/Settings/SettingsUIView.axaml.cs

@@ -1,4 +1,5 @@
-using Avalonia.Controls;
+using Avalonia;
+using Avalonia.Controls;
 using Avalonia.Controls.ApplicationLifetimes;
 using Avalonia.Interactivity;
 using Ryujinx.Ava.Common.Locale;
@@ -9,11 +10,11 @@ using System.Linq;
 
 namespace Ryujinx.Ava.UI.Views.Settings
 {
-    public partial class SettingsUIView : UserControl
+    public partial class SettingsUiView : UserControl
     {
         public SettingsViewModel ViewModel;
 
-        public SettingsUIView()
+        public SettingsUiView()
         {
             InitializeComponent();
         }
@@ -29,7 +30,7 @@ namespace Ryujinx.Ava.UI.Views.Settings
             }
             else
             {
-                if (Avalonia.Application.Current.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
+                if (Application.Current.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
                 {
                     path = await new OpenFolderDialog().ShowAsync(desktop.MainWindow);
 
@@ -60,15 +61,15 @@ namespace Ryujinx.Ava.UI.Views.Settings
 
         public async void BrowseTheme(object sender, RoutedEventArgs e)
         {
-            var dialog = new OpenFileDialog()
+            var dialog = new OpenFileDialog
             {
                 Title = LocaleManager.Instance[LocaleKeys.SettingsSelectThemeFileDialogTitle],
-                AllowMultiple = false
+                AllowMultiple = false,
             };
 
-            dialog.Filters.Add(new FileDialogFilter() { Extensions = { "xaml" }, Name = LocaleManager.Instance[LocaleKeys.SettingsXamlThemeFile] });
+            dialog.Filters.Add(new FileDialogFilter { Extensions = { "xaml" }, Name = LocaleManager.Instance[LocaleKeys.SettingsXamlThemeFile] });
 
-            if (Avalonia.Application.Current.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
+            if (Application.Current.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
             {
                 var file = await dialog.ShowAsync(desktop.MainWindow);
 
@@ -79,4 +80,4 @@ namespace Ryujinx.Ava.UI.Views.Settings
             }
         }
     }
-}
+}

+ 7 - 7
src/Ryujinx.Ava/UI/Views/User/UserEditorView.axaml.cs

@@ -20,7 +20,7 @@ namespace Ryujinx.Ava.UI.Views.User
         private bool _isNewUser;
 
         public TempProfile TempProfile { get; set; }
-        public uint MaxProfileNameLength => 0x20;
+        public static uint MaxProfileNameLength => 0x20;
         public bool IsDeletable => _profile.UserId != AccountManager.DefaultUserId;
 
         public UserEditorView()
@@ -39,17 +39,17 @@ namespace Ryujinx.Ava.UI.Views.User
                 switch (arg.NavigationMode)
                 {
                     case NavigationMode.New:
-                        var args = ((NavigationDialogHost parent, UserProfile profile, bool isNewUser))arg.Parameter;
-                        _isNewUser = args.isNewUser;
-                        _profile = args.profile;
+                        var (parent, profile, isNewUser) = ((NavigationDialogHost parent, UserProfile profile, bool isNewUser))arg.Parameter;
+                        _isNewUser = isNewUser;
+                        _profile = profile;
                         TempProfile = new TempProfile(_profile);
 
-                        _parent = args.parent;
+                        _parent = parent;
                         break;
                 }
 
                 ((ContentDialog)_parent.Parent).Title = $"{LocaleManager.Instance[LocaleKeys.UserProfileWindowTitle]} - " +
-                                                        $"{ (_isNewUser ? LocaleManager.Instance[LocaleKeys.UserEditorTitleCreate] : LocaleManager.Instance[LocaleKeys.UserEditorTitle])}";
+                                                        $"{(_isNewUser ? LocaleManager.Instance[LocaleKeys.UserEditorTitleCreate] : LocaleManager.Instance[LocaleKeys.UserEditorTitle])}";
 
                 DataContext = TempProfile;
 
@@ -162,4 +162,4 @@ namespace Ryujinx.Ava.UI.Views.User
             }
         }
     }
-}
+}

+ 3 - 2
src/Ryujinx.Ava/UI/Views/User/UserFirmwareAvatarSelectorView.axaml.cs

@@ -11,6 +11,7 @@ using SixLabors.ImageSharp.Formats.Png;
 using SixLabors.ImageSharp.PixelFormats;
 using SixLabors.ImageSharp.Processing;
 using System.IO;
+using Image = SixLabors.ImageSharp.Image;
 
 namespace Ryujinx.Ava.UI.Views.User
 {
@@ -70,7 +71,7 @@ namespace Ryujinx.Ava.UI.Views.User
             if (ViewModel.SelectedImage != null)
             {
                 MemoryStream streamJpg = new();
-                SixLabors.ImageSharp.Image avatarImage = SixLabors.ImageSharp.Image.Load(ViewModel.SelectedImage, new PngDecoder());
+                Image avatarImage = Image.Load(ViewModel.SelectedImage, new PngDecoder());
 
                 avatarImage.Mutate(x => x.BackgroundColor(new Rgba32(
                     ViewModel.BackgroundColor.R,
@@ -85,4 +86,4 @@ namespace Ryujinx.Ava.UI.Views.User
             }
         }
     }
-}
+}

+ 9 - 11
src/Ryujinx.Ava/UI/Views/User/UserProfileImageSelectorView.axaml.cs

@@ -67,7 +67,7 @@ namespace Ryujinx.Ava.UI.Views.User
             dialog.Filters.Add(new FileDialogFilter
             {
                 Name = LocaleManager.Instance[LocaleKeys.AllSupportedFormats],
-                Extensions = { "jpg", "jpeg", "png", "bmp" }
+                Extensions = { "jpg", "jpeg", "png", "bmp" },
             });
             dialog.Filters.Add(new FileDialogFilter { Name = "JPEG", Extensions = { "jpg", "jpeg" } });
             dialog.Filters.Add(new FileDialogFilter { Name = "PNG", Extensions = { "png" } });
@@ -108,17 +108,15 @@ namespace Ryujinx.Ava.UI.Views.User
 
         private static byte[] ProcessProfileImage(byte[] buffer)
         {
-            using (Image image = Image.Load(buffer))
-            {
-                image.Mutate(x => x.Resize(256, 256));
+            using Image image = Image.Load(buffer);
 
-                using (MemoryStream streamJpg = new())
-                {
-                    image.SaveAsJpeg(streamJpg);
+            image.Mutate(x => x.Resize(256, 256));
 
-                    return streamJpg.ToArray();
-                }
-            }
+            using MemoryStream streamJpg = new();
+
+            image.SaveAsJpeg(streamJpg);
+
+            return streamJpg.ToArray();
         }
     }
-}
+}

+ 1 - 1
src/Ryujinx.Ava/UI/Views/User/UserRecovererView.axaml.cs

@@ -48,4 +48,4 @@ namespace Ryujinx.Ava.UI.Views.User
             _parent?.RecoverLostAccounts();
         }
     }
-}
+}

+ 10 - 9
src/Ryujinx.Ava/UI/Views/User/UserSaveManagerView.axaml.cs

@@ -18,6 +18,7 @@ using Ryujinx.HLE.HOS.Services.Account.Acc;
 using System;
 using System.Collections.ObjectModel;
 using System.Threading.Tasks;
+using Button = Avalonia.Controls.Button;
 using UserId = LibHac.Fs.UserId;
 
 namespace Ryujinx.Ava.UI.Views.User
@@ -47,12 +48,12 @@ namespace Ryujinx.Ava.UI.Views.User
                 switch (arg.NavigationMode)
                 {
                     case NavigationMode.New:
-                        var args = ((NavigationDialogHost parent, AccountManager accountManager, HorizonClient client, VirtualFileSystem virtualFileSystem))arg.Parameter;
-                        _accountManager = args.accountManager;
-                        _horizonClient = args.client;
-                        _virtualFileSystem = args.virtualFileSystem;
+                        var (parent, accountManager, client, virtualFileSystem) = ((NavigationDialogHost parent, AccountManager accountManager, HorizonClient client, VirtualFileSystem virtualFileSystem))arg.Parameter;
+                        _accountManager = accountManager;
+                        _horizonClient = client;
+                        _virtualFileSystem = virtualFileSystem;
 
-                        _parent = args.parent;
+                        _parent = parent;
                         break;
                 }
 
@@ -94,7 +95,7 @@ namespace Ryujinx.Ava.UI.Views.User
                     var save = saveDataInfo[i];
                     if (save.ProgramId.Value != 0)
                     {
-                        var saveModel = new SaveModel(save, _virtualFileSystem);
+                        var saveModel = new SaveModel(save);
                         saves.Add(saveModel);
                     }
                 }
@@ -114,7 +115,7 @@ namespace Ryujinx.Ava.UI.Views.User
 
         private void OpenLocation(object sender, RoutedEventArgs e)
         {
-            if (sender is Avalonia.Controls.Button button)
+            if (sender is Button button)
             {
                 if (button.DataContext is SaveModel saveModel)
                 {
@@ -125,7 +126,7 @@ namespace Ryujinx.Ava.UI.Views.User
 
         private async void Delete(object sender, RoutedEventArgs e)
         {
-            if (sender is Avalonia.Controls.Button button)
+            if (sender is Button button)
             {
                 if (button.DataContext is SaveModel saveModel)
                 {
@@ -144,4 +145,4 @@ namespace Ryujinx.Ava.UI.Views.User
             }
         }
     }
-}
+}

+ 4 - 3
src/Ryujinx.Ava/UI/Views/User/UserSelectorView.axaml.cs

@@ -5,8 +5,9 @@ using FluentAvalonia.UI.Controls;
 using FluentAvalonia.UI.Navigation;
 using Ryujinx.Ava.Common.Locale;
 using Ryujinx.Ava.UI.Controls;
+using Ryujinx.Ava.UI.Models;
 using Ryujinx.Ava.UI.ViewModels;
-using UserProfile = Ryujinx.Ava.UI.Models.UserProfile;
+using Button = Avalonia.Controls.Button;
 
 namespace Ryujinx.Ava.UI.Views.User
 {
@@ -101,7 +102,7 @@ namespace Ryujinx.Ava.UI.Views.User
 
         private void EditUser(object sender, RoutedEventArgs e)
         {
-            if (sender is Avalonia.Controls.Button button)
+            if (sender is Button button)
             {
                 if (button.DataContext is UserProfile userProfile)
                 {
@@ -125,4 +126,4 @@ namespace Ryujinx.Ava.UI.Views.User
             ((ContentDialog)_parent.Parent).Hide();
         }
     }
-}
+}

+ 6 - 5
src/Ryujinx.Ava/UI/Windows/AboutWindow.axaml.cs

@@ -1,6 +1,7 @@
 using Avalonia.Controls;
 using Avalonia.Input;
 using Avalonia.Interactivity;
+using Avalonia.Layout;
 using Avalonia.Styling;
 using FluentAvalonia.UI.Controls;
 using Ryujinx.Ava.Common.Locale;
@@ -25,17 +26,17 @@ namespace Ryujinx.Ava.UI.Windows
         {
             ContentDialog contentDialog = new()
             {
-                PrimaryButtonText   = "",
+                PrimaryButtonText = "",
                 SecondaryButtonText = "",
-                CloseButtonText     = LocaleManager.Instance[LocaleKeys.UserProfilesClose],
-                Content             = new AboutWindow()
+                CloseButtonText = LocaleManager.Instance[LocaleKeys.UserProfilesClose],
+                Content = new AboutWindow(),
             };
 
             Style closeButton = new(x => x.Name("CloseButton"));
             closeButton.Setters.Add(new Setter(WidthProperty, 80d));
 
             Style closeButtonParent = new(x => x.Name("CommandSpace"));
-            closeButtonParent.Setters.Add(new Setter(HorizontalAlignmentProperty, Avalonia.Layout.HorizontalAlignment.Right));
+            closeButtonParent.Setters.Add(new Setter(HorizontalAlignmentProperty, HorizontalAlignment.Right));
 
             contentDialog.Styles.Add(closeButton);
             contentDialog.Styles.Add(closeButtonParent);
@@ -59,4 +60,4 @@ namespace Ryujinx.Ava.UI.Windows
             }
         }
     }
-}
+}

+ 5 - 4
src/Ryujinx.Ava/UI/Windows/AmiiboWindow.axaml.cs

@@ -9,9 +9,10 @@ namespace Ryujinx.Ava.UI.Windows
     {
         public AmiiboWindow(bool showAll, string lastScannedAmiiboId, string titleId)
         {
-            ViewModel = new AmiiboWindowViewModel(this, lastScannedAmiiboId, titleId);
-
-            ViewModel.ShowAllAmiibo = showAll;
+            ViewModel = new AmiiboWindowViewModel(this, lastScannedAmiiboId, titleId)
+            {
+                ShowAllAmiibo = showAll,
+            };
 
             DataContext = ViewModel;
 
@@ -56,4 +57,4 @@ namespace Ryujinx.Ava.UI.Windows
             Close();
         }
     }
-}
+}

+ 10 - 10
src/Ryujinx.Ava/UI/Windows/CheatWindow.axaml.cs

@@ -1,11 +1,12 @@
-using Avalonia;
-using Avalonia.Collections;
+using Avalonia.Collections;
 using Ryujinx.Ava.Common.Locale;
 using Ryujinx.Ava.UI.Models;
 using Ryujinx.HLE.FileSystem;
 using Ryujinx.HLE.HOS;
 using Ryujinx.Ui.App.Common;
+using System;
 using System.Collections.Generic;
+using System.Globalization;
 using System.IO;
 using System.Linq;
 
@@ -36,16 +37,16 @@ namespace Ryujinx.Ava.UI.Windows
 
             Heading = LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.CheatWindowHeading, titleName, titleId.ToUpper());
             BuildId = ApplicationData.GetApplicationBuildId(virtualFileSystem, titlePath);
-            
+
             InitializeComponent();
 
             string modsBasePath = ModLoader.GetModsBasePath();
             string titleModsPath = ModLoader.GetTitleDir(modsBasePath, titleId);
-            ulong titleIdValue = ulong.Parse(titleId, System.Globalization.NumberStyles.HexNumber);
+            ulong titleIdValue = ulong.Parse(titleId, NumberStyles.HexNumber);
 
             _enabledCheatsPath = Path.Combine(titleModsPath, "cheats", "enabled.txt");
 
-            string[] enabled = { };
+            string[] enabled = Array.Empty<string>();
 
             if (File.Exists(_enabledCheatsPath))
             {
@@ -60,7 +61,6 @@ namespace Ryujinx.Ava.UI.Windows
 
             string currentCheatFile = string.Empty;
             string buildId = string.Empty;
-            string parentPath = string.Empty;
 
             CheatsList currentGroup = null;
 
@@ -69,7 +69,7 @@ namespace Ryujinx.Ava.UI.Windows
                 if (cheat.Path.FullName != currentCheatFile)
                 {
                     currentCheatFile = cheat.Path.FullName;
-                    parentPath = currentCheatFile.Replace(titleModsPath, "");
+                    string parentPath = currentCheatFile.Replace(titleModsPath, "");
 
                     buildId = Path.GetFileNameWithoutExtension(currentCheatFile).ToUpper();
                     currentGroup = new CheatsList(buildId, parentPath);
@@ -89,7 +89,7 @@ namespace Ryujinx.Ava.UI.Windows
             }
 
             DataContext = this;
-            
+
             Title = $"Ryujinx {Program.Version} - " + LocaleManager.Instance[LocaleKeys.CheatWindowTitle];
         }
 
@@ -100,7 +100,7 @@ namespace Ryujinx.Ava.UI.Windows
                 return;
             }
 
-            List<string> enabledCheats = new List<string>();
+            List<string> enabledCheats = new();
 
             foreach (var cheats in LoadedCheats)
             {
@@ -120,4 +120,4 @@ namespace Ryujinx.Ava.UI.Windows
             Close();
         }
     }
-}
+}

+ 4 - 3
src/Ryujinx.Ava/UI/Windows/ContentDialogOverlayWindow.axaml.cs

@@ -1,7 +1,8 @@
-using Avalonia;
 using Avalonia.Controls;
-using Avalonia.Markup.Xaml;
 using Avalonia.Media;
+#if DEBUG
+using Avalonia;
+#endif
 
 namespace Ryujinx.Ava.UI.Windows
 {
@@ -22,4 +23,4 @@ namespace Ryujinx.Ava.UI.Windows
             CanResize = false;
         }
     }
-}
+}

+ 2 - 2
src/Ryujinx.Ava/UI/Windows/DownloadableContentManagerWindow.axaml

@@ -89,8 +89,8 @@
                                 <Grid
                                     Grid.Column="0">
                                     <Grid.ColumnDefinitions>
-                                        <ColumnDefinition Width="*"></ColumnDefinition>
-                                        <ColumnDefinition Width="Auto"></ColumnDefinition>
+                                        <ColumnDefinition Width="*" />
+                                        <ColumnDefinition Width="Auto" />
                                     </Grid.ColumnDefinitions>
                                     <TextBlock
                                         Grid.Column="0"

Unele fișiere nu au fost afișate deoarece prea multe fișiere au fost modificate în acest diff