Răsfoiți Sursa

misc: Code cleanup

Evan Husted 1 an în urmă
părinte
comite
281be7ca62

+ 6 - 2
Ryujinx.sln.DotSettings

@@ -3,9 +3,13 @@
 	<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=SuggestVarOrType_005FSimpleTypes/@EntryIndexedValue">WARNING</s:String>
 	<s:String x:Key="/Default/CodeStyle/CSharpVarKeywordUsage/ForOtherTypes/@EntryValue">UseExplicitType</s:String>
 	<s:String x:Key="/Default/CodeStyle/CSharpVarKeywordUsage/ForSimpleTypes/@EntryValue">UseExplicitType</s:String>
-	<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=TypesAndNamespaces/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AaBb"&gt;&lt;ExtraRule Prefix="I" Suffix="" Style="AaBb" /&gt;&lt;/Policy&gt;</s:String>
+	<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=GL/@EntryIndexedValue">GL</s:String>
+	<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=SDL/@EntryIndexedValue">SDL</s:String>
+    <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=SDL/@EntryIndexedValue">OS</s:String>
+    <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=TypesAndNamespaces/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AaBb"&gt;&lt;ExtraRule Prefix="I" Suffix="" Style="AaBb" /&gt;&lt;/Policy&gt;</s:String>
 	<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/UserRules/=a0b4bc4d_002Dd13b_002D4a37_002Db37e_002Dc9c6864e4302/@EntryIndexedValue">&lt;Policy&gt;&lt;Descriptor Staticness="Any" AccessRightKinds="Any" Description="Types and namespaces"&gt;&lt;ElementKinds&gt;&lt;Kind Name="NAMESPACE" /&gt;&lt;Kind Name="CLASS" /&gt;&lt;Kind Name="STRUCT" /&gt;&lt;Kind Name="ENUM" /&gt;&lt;Kind Name="DELEGATE" /&gt;&lt;/ElementKinds&gt;&lt;/Descriptor&gt;&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AaBb"&gt;&lt;ExtraRule Prefix="I" Suffix="" Style="AaBb" /&gt;&lt;/Policy&gt;&lt;/Policy&gt;</s:String>
 	<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EPredefinedNamingRulesToUserRulesUpgrade/@EntryIndexedValue">True</s:Boolean>
+	<s:Boolean x:Key="/Default/UserDictionary/Words/=amiibo/@EntryIndexedValue">True</s:Boolean>
 	<s:Boolean x:Key="/Default/UserDictionary/Words/=ASET/@EntryIndexedValue">True</s:Boolean>
 	<s:Boolean x:Key="/Default/UserDictionary/Words/=Astc/@EntryIndexedValue">True</s:Boolean>
 	<s:Boolean x:Key="/Default/UserDictionary/Words/=Luma/@EntryIndexedValue">True</s:Boolean>
@@ -20,4 +24,4 @@
 	<s:Boolean x:Key="/Default/UserDictionary/Words/=Spirv/@EntryIndexedValue">True</s:Boolean>
 	<s:Boolean x:Key="/Default/UserDictionary/Words/=Srgb/@EntryIndexedValue">True</s:Boolean>
 	<s:Boolean x:Key="/Default/UserDictionary/Words/=Unorm/@EntryIndexedValue">True</s:Boolean>
-</wpf:ResourceDictionary>
+</wpf:ResourceDictionary>

+ 1 - 1
src/Ryujinx.Common/Configuration/AppDataManager.cs

@@ -98,7 +98,7 @@ namespace Ryujinx.Common.Configuration
 
             if (IsPathSymlink(BaseDirPath))
             {
-                Logger.Warning?.Print(LogClass.Application, $"Application data directory is a symlink. This may be unintended.");
+                Logger.Warning?.Print(LogClass.Application, "Application data directory is a symlink. This may be unintended.");
             }
 
             SetupBasePaths();

+ 1 - 2
src/Ryujinx.Common/Logging/Logger.cs

@@ -212,9 +212,7 @@ namespace Ryujinx.Common.Logging
             foreach (var log in logs)
             {
                 if (log.HasValue)
-                {
                     levels.Add(log.Value.Level);
-                }
             }
 
             return levels;
@@ -233,6 +231,7 @@ namespace Ryujinx.Common.Logging
                 case LogLevel.AccessLog : AccessLog = enabled ? new Log(LogLevel.AccessLog) : new Log?(); break;
                 case LogLevel.Stub      : Stub      = enabled ? new Log(LogLevel.Stub)      : new Log?(); break;
                 case LogLevel.Trace     : Trace     = enabled ? new Log(LogLevel.Trace)     : new Log?(); break;
+                case LogLevel.Notice    : break;
                 default: throw new ArgumentException("Unknown Log Level", nameof(logLevel));
 #pragma warning restore IDE0055
             }

+ 1 - 1
src/Ryujinx.Cpu/Jit/MemoryManagerHostTracked.cs

@@ -469,7 +469,7 @@ namespace Ryujinx.Cpu.Jit
         {
             if (size == 0)
             {
-                return Enumerable.Empty<MemoryRange>();
+                return [];
             }
 
             return GetPhysicalRegionsImpl(va, size);

+ 2 - 2
src/Ryujinx/App.axaml

@@ -12,6 +12,6 @@
     </Application.Resources>
     <Application.Styles>
         <sty:FluentAvaloniaTheme PreferSystemTheme="False" />
-        <StyleInclude Source="/Assets/Styles/Styles.xaml"/>
+        <StyleInclude Source="/Assets/Styles/Styles.xaml" />
     </Application.Styles>
-</Application>
+</Application>

+ 3 - 9
src/Ryujinx/App.axaml.cs

@@ -66,11 +66,6 @@ namespace Ryujinx.Ava
             }
         }
 
-        private void CustomThemeChanged_Event(object sender, ReactiveEventArgs<bool> e)
-        {
-            ApplyConfiguredTheme();
-        }
-
         private void ShowRestartDialog()
         {
             _ = Dispatcher.UIThread.InvokeAsync(async () =>
@@ -93,11 +88,10 @@ namespace Ryujinx.Ava
                 }
             });
         }
+        
+        private void CustomThemeChanged_Event(object _, ReactiveEventArgs<bool> __) => ApplyConfiguredTheme();
 
-        private void ThemeChanged_Event(object sender, ReactiveEventArgs<string> e)
-        {
-            ApplyConfiguredTheme();
-        }
+        private void ThemeChanged_Event(object _, ReactiveEventArgs<string> __) => ApplyConfiguredTheme();
 
         public void ApplyConfiguredTheme()
         {

+ 2 - 3
src/Ryujinx/AppHost.cs

@@ -57,7 +57,6 @@ 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;
 
 namespace Ryujinx.Ava
 {
@@ -130,7 +129,7 @@ namespace Ryujinx.Ava
         public ContentManager ContentManager { get; }
         public NpadManager NpadManager { get; }
         public TouchScreenManager TouchScreenManager { get; }
-        public Switch Device { get; set; }
+        public HLE.Switch Device { get; set; }
 
         public int Width { get; private set; }
         public int Height { get; private set; }
@@ -849,7 +848,7 @@ namespace Ryujinx.Ava
             // Initialize Configuration.
             var memoryConfiguration = ConfigurationState.Instance.System.DramSize.Value;
 
-            Device = new Switch(new HLEConfiguration(
+            Device = new HLE.Switch(new HLEConfiguration(
                 VirtualFileSystem,
                 _viewModel.LibHacHorizonManager,
                 ContentManager,

+ 8 - 5
src/Ryujinx/Common/Locale/LocaleManager.cs

@@ -99,6 +99,9 @@ namespace Ryujinx.Ava.Common.Locale
                 _ => false
             };
 
+        public static string FormatDynamicValue(LocaleKeys key, params object[] values) 
+            => Instance.UpdateAndGetDynamicValue(key, values);
+
         public string UpdateAndGetDynamicValue(LocaleKeys key, params object[] values)
         {
             _dynamicValues[key] = values;
@@ -127,9 +130,9 @@ namespace Ryujinx.Ava.Common.Locale
                 _localeLanguageCode = languageCode;
             }
 
-            foreach (var item in locale)
+            foreach ((LocaleKeys key, string val) in locale)
             {
-                _localeStrings[item.Key] = item.Value;
+                _localeStrings[key] = val;
             }
 
             OnPropertyChanged("Item");
@@ -150,11 +153,11 @@ namespace Ryujinx.Ava.Common.Locale
 
             var strings = JsonHelper.Deserialize(languageJson, CommonJsonContext.Default.StringDictionary);
 
-            foreach (var item in strings)
+            foreach ((string key, string val) in strings)
             {
-                if (Enum.TryParse<LocaleKeys>(item.Key, out var key))
+                if (Enum.TryParse<LocaleKeys>(key, out var localeKey))
                 {
-                    localeStrings[key] = item.Value;
+                    localeStrings[localeKey] = val;
                 }
             }
 

+ 22 - 16
src/Ryujinx/Program.cs

@@ -1,7 +1,7 @@
-using ARMeilleure;
 using Avalonia;
 using Avalonia.Threading;
 using DiscordRPC;
+using Gommon;
 using Projektanker.Icons.Avalonia;
 using Projektanker.Icons.Avalonia.FontAwesome;
 using Projektanker.Icons.Avalonia.MaterialDesign;
@@ -23,6 +23,7 @@ using Ryujinx.UI.Common.Helper;
 using Ryujinx.UI.Common.SystemInfo;
 using System;
 using System.IO;
+using System.Linq;
 using System.Runtime.InteropServices;
 using System.Threading.Tasks;
 
@@ -103,8 +104,9 @@ namespace Ryujinx.Ava
             Console.Title = $"Ryujinx Console {Version}";
 
             // 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.UnhandledException += (sender, e) 
+                => ProcessUnhandledException(sender, e.ExceptionObject as Exception, e.IsTerminating);
+            AppDomain.CurrentDomain.ProcessExit += (_, _) => Exit();
 
             // Setup base data directory.
             AppDataManager.Initialize(CommandLineState.BaseDirPathArg);
@@ -189,7 +191,7 @@ namespace Ryujinx.Ava
                 }
             }
 
-            UseHardwareAcceleration = ConfigurationState.Instance.EnableHardwareAcceleration.Value;
+            UseHardwareAcceleration = ConfigurationState.Instance.EnableHardwareAcceleration;
 
             // Check if graphics backend was overridden
             if (CommandLineState.OverrideGraphicsBackend is not null)
@@ -226,7 +228,13 @@ namespace Ryujinx.Ava
             Logger.Notice.Print(LogClass.Application, $"Ryujinx Version: {Version}");
             SystemInfo.Gather().Print();
 
-            Logger.Notice.Print(LogClass.Application, $"Logs Enabled: {(Logger.GetEnabledLevels().Count == 0 ? "<None>" : string.Join(", ", Logger.GetEnabledLevels()))}");
+            var enabledLogLevels = Logger.GetEnabledLevels().ToArray();
+
+            Logger.Notice.Print(LogClass.Application, $"Logs Enabled: {
+                (enabledLogLevels.Length is 0
+                    ? "<None>" 
+                    : enabledLogLevels.JoinToString(", "))
+            }");
 
             Logger.Notice.Print(LogClass.Application,
                 AppDataManager.Mode == AppDataManager.LaunchMode.Custom
@@ -234,21 +242,19 @@ namespace Ryujinx.Ava
                     : $"Launch Mode: {AppDataManager.Mode}");
         }
 
-        private static void ProcessUnhandledException(Exception ex, bool isTerminating)
+        private static void ProcessUnhandledException(object sender, Exception ex, bool isTerminating)
         {
+            Logger.Log log = Logger.Error ?? Logger.Notice;
             string message = $"Unhandled exception caught: {ex}";
-
-            Logger.Error?.PrintMsg(LogClass.Application, message);
-
-            if (Logger.Error == null)
-            {
-                Logger.Notice.PrintMsg(LogClass.Application, message);
-            }
-
+            
+            // ReSharper disable once ConstantConditionalAccessQualifier
+            if (sender?.GetType()?.AsPrettyString() is {} senderName)
+                log.Print(LogClass.Application, message, senderName);
+            else
+                log.PrintMsg(LogClass.Application, message);
+            
             if (isTerminating)
-            {
                 Exit();
-            }
         }
 
         public static void Exit()

+ 6 - 10
src/Ryujinx/UI/Applet/AvaHostUIHandler.cs

@@ -31,15 +31,11 @@ namespace Ryujinx.Ava.UI.Applet
         public bool DisplayMessageDialog(ControllerAppletUIArgs args)
         {
             ManualResetEvent dialogCloseEvent = new(false);
-
-            bool ignoreApplet = ConfigurationState.Instance.IgnoreApplet;
+            
             bool okPressed = false;
 
-            if (ignoreApplet)
-            {
-
+            if (ConfigurationState.Instance.IgnoreApplet)
                 return false;
-            }
 
             Dispatcher.UIThread.InvokeAsync(async () =>
             {
@@ -74,9 +70,9 @@ namespace Ryujinx.Ava.UI.Applet
                     UserResult response = await ContentDialogHelper.ShowDeferredContentDialog(_parent,
                        title,
                        message,
-                       "",
+                       string.Empty,
                        LocaleManager.Instance[LocaleKeys.DialogOpenSettingsWindowLabel],
-                       "",
+                       string.Empty,
                        LocaleManager.Instance[LocaleKeys.SettingsButtonClose],
                        (int)Symbol.Important,
                        deferEvent,
@@ -179,12 +175,12 @@ namespace Ryujinx.Ava.UI.Applet
                     {
                         Title = title,
                         WindowStartupLocation = WindowStartupLocation.CenterScreen,
-                        Width = 400,
+                        Width = 400
                     };
 
                     object response = await msgDialog.Run();
 
-                    if (response != null && buttons != null && buttons.Length > 1 && (int)response != buttons.Length - 1)
+                    if (response != null && buttons is { Length: > 1 } && (int)response != buttons.Length - 1)
                     {
                         showDetails = true;
                     }

+ 15 - 9
src/Ryujinx/UI/Applet/AvaloniaDynamicTextInputHandler.cs

@@ -24,10 +24,13 @@ namespace Ryujinx.Ava.UI.Applet
         public AvaloniaDynamicTextInputHandler(MainWindow parent)
         {
             _parent = parent;
-
-            (_parent.InputManager.KeyboardDriver as AvaloniaKeyboardDriver).KeyPressed += AvaloniaDynamicTextInputHandler_KeyPressed;
-            (_parent.InputManager.KeyboardDriver as AvaloniaKeyboardDriver).KeyRelease += AvaloniaDynamicTextInputHandler_KeyRelease;
-            (_parent.InputManager.KeyboardDriver as AvaloniaKeyboardDriver).TextInput += AvaloniaDynamicTextInputHandler_TextInput;
+            
+            if (_parent.InputManager.KeyboardDriver is AvaloniaKeyboardDriver avaloniaKeyboardDriver)
+            {
+                avaloniaKeyboardDriver.KeyPressed += AvaloniaDynamicTextInputHandler_KeyPressed;
+                avaloniaKeyboardDriver.KeyRelease += AvaloniaDynamicTextInputHandler_KeyRelease;
+                avaloniaKeyboardDriver.TextInput += AvaloniaDynamicTextInputHandler_TextInput;
+            }
 
             _hiddenTextBox = _parent.HiddenTextBox;
 
@@ -44,7 +47,7 @@ namespace Ryujinx.Ava.UI.Applet
             TextChangedEvent?.Invoke(text ?? string.Empty, _hiddenTextBox.SelectionStart, _hiddenTextBox.SelectionEnd, false);
         }
 
-        private void SelectionChanged(int selection)
+        private void SelectionChanged(int _)
         {
             TextChangedEvent?.Invoke(_hiddenTextBox.Text ?? string.Empty, _hiddenTextBox.SelectionStart, _hiddenTextBox.SelectionEnd, false);
         }
@@ -112,10 +115,13 @@ namespace Ryujinx.Ava.UI.Applet
 
         public void Dispose()
         {
-            (_parent.InputManager.KeyboardDriver as AvaloniaKeyboardDriver).KeyPressed -= AvaloniaDynamicTextInputHandler_KeyPressed;
-            (_parent.InputManager.KeyboardDriver as AvaloniaKeyboardDriver).KeyRelease -= AvaloniaDynamicTextInputHandler_KeyRelease;
-            (_parent.InputManager.KeyboardDriver as AvaloniaKeyboardDriver).TextInput -= AvaloniaDynamicTextInputHandler_TextInput;
-
+            if (_parent.InputManager.KeyboardDriver is AvaloniaKeyboardDriver avaloniaKeyboardDriver)
+            {
+                avaloniaKeyboardDriver.KeyPressed -= AvaloniaDynamicTextInputHandler_KeyPressed;
+                avaloniaKeyboardDriver.KeyRelease -= AvaloniaDynamicTextInputHandler_KeyRelease;
+                avaloniaKeyboardDriver.TextInput -= AvaloniaDynamicTextInputHandler_TextInput;
+            }
+            
             _textChangedSubscription?.Dispose();
             _selectionStartChangedSubscription?.Dispose();
             _selectionEndtextChangedSubscription?.Dispose();

+ 17 - 22
src/Ryujinx/UI/Controls/NavigationDialogHost.axaml.cs

@@ -47,42 +47,37 @@ namespace Ryujinx.Ava.UI.Controls
             LoadProfiles();
 
             if (contentManager.GetCurrentFirmwareVersion() != null)
-            {
-                Task.Run(() =>
-                {
-                    UserFirmwareAvatarSelectorViewModel.PreloadAvatars(contentManager, virtualFileSystem);
-                });
-            }
+                Task.Run(() => UserFirmwareAvatarSelectorViewModel.PreloadAvatars(contentManager, virtualFileSystem));
+            
             InitializeComponent();
         }
 
         public void GoBack()
         {
             if (ContentFrame.BackStack.Count > 0)
-            {
                 ContentFrame.GoBack();
-            }
 
             LoadProfiles();
         }
 
-        public void Navigate(Type sourcePageType, object parameter)
-        {
-            ContentFrame.Navigate(sourcePageType, parameter);
-        }
+        public void Navigate(Type sourcePageType, object parameter) 
+            => ContentFrame.Navigate(sourcePageType, parameter);
 
-        public static async Task Show(AccountManager ownerAccountManager, ContentManager ownerContentManager,
-            VirtualFileSystem ownerVirtualFileSystem, HorizonClient ownerHorizonClient)
+        public static async Task Show(
+            AccountManager ownerAccountManager, 
+            ContentManager ownerContentManager,
+            VirtualFileSystem ownerVirtualFileSystem, 
+            HorizonClient ownerHorizonClient)
         {
             var content = new NavigationDialogHost(ownerAccountManager, ownerContentManager, ownerVirtualFileSystem, ownerHorizonClient);
             ContentDialog contentDialog = new()
             {
                 Title = LocaleManager.Instance[LocaleKeys.UserProfileWindowTitle],
-                PrimaryButtonText = "",
-                SecondaryButtonText = "",
-                CloseButtonText = "",
+                PrimaryButtonText = string.Empty,
+                SecondaryButtonText = string.Empty,
+                CloseButtonText = string.Empty,
                 Content = content,
-                Padding = new Thickness(0),
+                Padding = new Thickness(0)
             };
 
             contentDialog.Closed += (_, _) => content.ViewModel.Dispose();
@@ -160,14 +155,14 @@ namespace Ryujinx.Ava.UI.Controls
 
                 if (profile == null)
                 {
+                    Dispatcher.UIThread.Post(Action);
+                    
+                    return;
+                    
                     static async void Action()
                     {
                         await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance[LocaleKeys.DialogUserProfileDeletionWarningMessage]);
                     }
-
-                    Dispatcher.UIThread.Post(Action);
-
-                    return;
                 }
 
                 AccountManager.OpenUser(profile.UserId);

+ 1 - 1
src/Ryujinx/UI/Helpers/ContentDialogHelper.cs

@@ -42,7 +42,7 @@ namespace Ryujinx.Ava.UI.Helpers
                 PrimaryButtonCommand = MiniCommand.Create(() =>
                 {
                     result = primaryButtonResult;
-                }),
+                })
             };
 
             contentDialog.SecondaryButtonCommand = MiniCommand.Create(() =>

+ 2 - 1
src/Ryujinx/UI/Helpers/LoggerAdapter.cs

@@ -1,5 +1,6 @@
 using Avalonia.Logging;
 using Avalonia.Utilities;
+using Gommon;
 using Ryujinx.Common.Logging;
 using System;
 using System.Text;
@@ -90,7 +91,7 @@ namespace Ryujinx.Ava.UI.Helpers
             if (source != null)
             {
                 result.Append(" (");
-                result.Append(source.GetType().Name);
+                result.Append(source.GetType().AsFullNamePrettyString());
                 result.Append(" #");
                 result.Append(source.GetHashCode());
                 result.Append(')');

+ 1 - 1
src/Ryujinx/UI/Helpers/OffscreenTextBox.cs

@@ -35,7 +35,7 @@ namespace Ryujinx.Ava.UI.Helpers
             {
                 Text = text,
                 Source = this,
-                RoutedEvent = TextInputEvent,
+                RoutedEvent = TextInputEvent
             });
         }
     }

+ 6 - 14
src/Ryujinx/UI/Helpers/TimeZoneConverter.cs

@@ -9,20 +9,12 @@ namespace Ryujinx.Ava.UI.Helpers
     {
         public static TimeZoneConverter Instance = new();
 
-        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
-        {
-            if (value == null)
-            {
-                return null;
-            }
+        public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
+            => value is TimeZone timeZone 
+                ? $"{timeZone.UtcDifference}  {timeZone.Location}   {timeZone.Abbreviation}" 
+                : null;
 
-            var timeZone = (TimeZone)value;
-            return string.Format("{0}  {1}   {2}", timeZone.UtcDifference, timeZone.Location, timeZone.Abbreviation);
-        }
-
-        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
-        {
-            throw new NotImplementedException();
-        }
+        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 
+            => throw new NotImplementedException();
     }
 }

+ 33 - 39
src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs

@@ -3,12 +3,12 @@ using Avalonia.Controls;
 using Avalonia.Controls.ApplicationLifetimes;
 using Avalonia.Input;
 using Avalonia.Media;
+using Avalonia.Media.Imaging;
 using Avalonia.Platform.Storage;
 using Avalonia.Threading;
 using DynamicData;
 using DynamicData.Binding;
 using FluentAvalonia.UI.Controls;
-using Gommon;
 using LibHac.Common;
 using Ryujinx.Ava.Common;
 using Ryujinx.Ava.Common.Locale;
@@ -41,6 +41,7 @@ using System.Collections.ObjectModel;
 using System.Globalization;
 using System.IO;
 using System.Linq;
+using System.Reflection;
 using System.Threading;
 using System.Threading.Tasks;
 using Key = Ryujinx.Input.Key;
@@ -113,6 +114,9 @@ namespace Ryujinx.Ava.UI.ViewModels
         public ApplicationData ListSelectedApplication;
         public ApplicationData GridSelectedApplication;
 
+        public static readonly Bitmap IconBitmap =
+            new(Assembly.GetAssembly(typeof(ConfigurationState))!.GetManifestResourceStream("Ryujinx.UI.Common.Resources.Logo_Ryujinx.png")!);
+
         public MainWindow Window { get; init; }
 
         internal AppHost AppHost { get; set; }
@@ -179,16 +183,14 @@ namespace Ryujinx.Ava.UI.ViewModels
 
                 _searchTimer?.Dispose();
 
-                _searchTimer = new Timer(TimerCallback, null, 1000, 0);
-            }
-        }
-
-        private void TimerCallback(object obj)
-        {
-            RefreshView();
+                _searchTimer = new Timer(_ =>
+                {
+                    RefreshView();
 
-            _searchTimer.Dispose();
-            _searchTimer = null;
+                    _searchTimer.Dispose();
+                    _searchTimer = null;
+                }, null, 1000, 0);
+            }
         }
 
         public bool CanUpdate
@@ -978,29 +980,26 @@ namespace Ryujinx.Ava.UI.ViewModels
 
         #region PrivateMethods
 
-        private IComparer<ApplicationData> GetComparer()
-        {
-            return SortMode switch
+        private static IComparer<ApplicationData> CreateComparer(bool ascending, Func<ApplicationData, IComparable> selector) =>
+            ascending
+                ? SortExpressionComparer<ApplicationData>.Ascending(selector)
+                : SortExpressionComparer<ApplicationData>.Descending(selector);
+
+        private IComparer<ApplicationData> GetComparer() 
+            => SortMode switch
             {
 #pragma warning disable IDE0055 // Disable formatting
-                ApplicationSort.Title           => IsAscending ? SortExpressionComparer<ApplicationData>.Ascending(app => app.Name)
-                                                               : SortExpressionComparer<ApplicationData>.Descending(app => app.Name),
-                ApplicationSort.Developer       => IsAscending ? SortExpressionComparer<ApplicationData>.Ascending(app => app.Developer)
-                                                               : SortExpressionComparer<ApplicationData>.Descending(app => app.Developer),
+                ApplicationSort.Title           => CreateComparer(IsAscending, app => app.Name),
+                ApplicationSort.Developer       => CreateComparer(IsAscending, app => app.Developer),
                 ApplicationSort.LastPlayed      => new LastPlayedSortComparer(IsAscending),
                 ApplicationSort.TotalTimePlayed => new TimePlayedSortComparer(IsAscending),
-                ApplicationSort.FileType        => IsAscending ? SortExpressionComparer<ApplicationData>.Ascending(app => app.FileExtension)
-                                                               : SortExpressionComparer<ApplicationData>.Descending(app => app.FileExtension),
-                ApplicationSort.FileSize        => IsAscending ? SortExpressionComparer<ApplicationData>.Ascending(app => app.FileSize)
-                                                               : SortExpressionComparer<ApplicationData>.Descending(app => app.FileSize),
-                ApplicationSort.Path            => IsAscending ? SortExpressionComparer<ApplicationData>.Ascending(app => app.Path)
-                                                               : SortExpressionComparer<ApplicationData>.Descending(app => app.Path),
-                ApplicationSort.Favorite        => IsAscending ? SortExpressionComparer<ApplicationData>.Ascending(app => new AppListFavoriteComparable(app))
-                                                                : SortExpressionComparer<ApplicationData>.Descending(app => new AppListFavoriteComparable(app)),
+                ApplicationSort.FileType        => CreateComparer(IsAscending, app => app.FileExtension),
+                ApplicationSort.FileSize        => CreateComparer(IsAscending, app => app.FileSize),
+                ApplicationSort.Path            => CreateComparer(IsAscending, app => app.Path),
+                ApplicationSort.Favorite        => CreateComparer(IsAscending, app => new AppListFavoriteComparable(app)),
                 _ => null,
 #pragma warning restore IDE0055
             };
-        }
 
         public void RefreshView()
         {
@@ -1125,7 +1124,7 @@ namespace Ryujinx.Ava.UI.ViewModels
             }
             catch (MissingKeyException ex)
             {
-                if (Application.Current.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
+                if (Application.Current?.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime)
                 {
                     Logger.Error?.Print(LogClass.Application, ex.ToString());
 
@@ -1260,8 +1259,10 @@ namespace Ryujinx.Ava.UI.ViewModels
                     GameStatusText = args.GameStatus;
                     VolumeStatusText = args.VolumeStatus;
                     FifoStatusText = args.FifoStatus;
-                    ShaderCountText = args.ShaderCount > 0 ? $"Compiling shaders: {args.ShaderCount}" : string.Empty;
-                    ShowRightmostSeparator = !ShaderCountText.IsNullOrEmpty();
+                    
+                    ShaderCountText = (ShowRightmostSeparator = args.ShaderCount > 0) 
+                        ? $"{LocaleManager.Instance[LocaleKeys.CompilingShaders]}: {args.ShaderCount}" 
+                        : string.Empty;
 
                     ShowStatusSeparator = true;
                 });
@@ -1641,8 +1642,7 @@ namespace Ryujinx.Ava.UI.ViewModels
             gameThread.Start();
         }
 
-        public void SwitchToRenderer(bool startFullscreen)
-        {
+        public void SwitchToRenderer(bool startFullscreen) =>
             Dispatcher.UIThread.Post(() =>
             {
                 SwitchToGameControl(startFullscreen);
@@ -1651,15 +1651,9 @@ namespace Ryujinx.Ava.UI.ViewModels
 
                 RendererHostControl.Focus();
             });
-        }
 
-        public static void UpdateGameMetadata(string titleId)
-        {
-            ApplicationLibrary.LoadAndSaveMetaData(titleId, appMetadata =>
-            {
-                appMetadata.UpdatePostGame();
-            });
-        }
+        public static void UpdateGameMetadata(string titleId) 
+            => ApplicationLibrary.LoadAndSaveMetaData(titleId, appMetadata => appMetadata.UpdatePostGame());
 
         public void RefreshFirmwareStatus()
         {

+ 5 - 5
src/Ryujinx/UI/ViewModels/SettingsViewModel.cs

@@ -287,11 +287,11 @@ namespace Ryujinx.Ava.UI.ViewModels
 
         public SettingsViewModel()
         {
-            GameDirectories = new AvaloniaList<string>();
-            AutoloadDirectories = new AvaloniaList<string>();
-            TimeZones = new AvaloniaList<TimeZone>();
-            AvailableGpus = new ObservableCollection<ComboBoxItem>();
-            _validTzRegions = new List<string>();
+            GameDirectories = [];
+            AutoloadDirectories = [];
+            TimeZones = [];
+            AvailableGpus = [];
+            _validTzRegions = [];
             _networkInterfaces = new Dictionary<string, string>();
 
             Task.Run(CheckSoundBackends);

+ 4 - 13
src/Ryujinx/UI/Windows/IconColorPicker.cs

@@ -21,10 +21,10 @@ namespace Ryujinx.Ava.UI.Windows
 
         private readonly struct PaletteColor(int qck, byte r, byte g, byte b)
         {
-            public int Qck { get; } = qck;
-            public byte R { get; } = r;
-            public byte G { get; } = g;
-            public byte B { get; } = b;
+            public int Qck => qck;
+            public byte R => r;
+            public byte G => g;
+            public byte B => b;
         }
 
         public static SKColor GetFilteredColor(SKBitmap image)
@@ -54,15 +54,6 @@ namespace Ryujinx.Ava.UI.Windows
 
             var buffer = GetBuffer(image);
 
-            int w = image.Width;
-            int w8 = w << 8;
-            int h8 = image.Height << 8;
-
-#pragma warning disable IDE0059 // Unnecessary assignment
-            int xStep = w8 / ColorsPerLine;
-            int yStep = h8 / ColorsPerLine;
-#pragma warning restore IDE0059
-
             int i = 0;
             int maxHitCount = 0;