mirror of
				https://github.com/ryujinx-mirror/ryujinx.git
				synced 2025-11-04 08:18:58 -06:00 
			
		
		
		
	Add the "Auto" theme option in setting (#6611)
* Add "Follow OS theme" option * Update App.axaml.cs * Add "Follow OS theme" option * Update App.axaml.cs * Remove `this` * Remove annotation for nullable reference * Change into switch expression to make it concise * Change comments to XML docs * Update en_US.json * Fix icons in About dialog do not response to "auto" theme The theme icons seemingly use Dark variant event when the OS theme is light. In addition, I added ThemeManager common to make it accessible for both App and AboutWindow * Newline at the end * newline moment * Update ThemeManager.cs * bait to switch to lf * change to lf * temp. revert * Add back ThemeManager.cs common, pls pass the format check * I found the mistake: should have put `ThemeManager.OnThemeChanged();` in try block Finally solve the formatting check * test formatting * Update App.axaml.cs * Ok i seem to forget to add version lol * Fix info CA1816
This commit is contained in:
		@@ -1,8 +1,10 @@
 | 
			
		||||
using Avalonia;
 | 
			
		||||
using Avalonia.Controls.ApplicationLifetimes;
 | 
			
		||||
using Avalonia.Markup.Xaml;
 | 
			
		||||
using Avalonia.Platform;
 | 
			
		||||
using Avalonia.Styling;
 | 
			
		||||
using Avalonia.Threading;
 | 
			
		||||
using Ryujinx.Ava.Common;
 | 
			
		||||
using Ryujinx.Ava.Common.Locale;
 | 
			
		||||
using Ryujinx.Ava.UI.Helpers;
 | 
			
		||||
using Ryujinx.Ava.UI.Windows;
 | 
			
		||||
@@ -84,7 +86,7 @@ namespace Ryujinx.Ava
 | 
			
		||||
            ApplyConfiguredTheme();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void ApplyConfiguredTheme()
 | 
			
		||||
        public void ApplyConfiguredTheme()
 | 
			
		||||
        {
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
@@ -92,13 +94,18 @@ namespace Ryujinx.Ava
 | 
			
		||||
 | 
			
		||||
                if (string.IsNullOrWhiteSpace(baseStyle))
 | 
			
		||||
                {
 | 
			
		||||
                    ConfigurationState.Instance.UI.BaseStyle.Value = "Dark";
 | 
			
		||||
                    ConfigurationState.Instance.UI.BaseStyle.Value = "Auto";
 | 
			
		||||
 | 
			
		||||
                    baseStyle = ConfigurationState.Instance.UI.BaseStyle;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                ThemeVariant systemTheme = DetectSystemTheme();
 | 
			
		||||
 | 
			
		||||
                ThemeManager.OnThemeChanged();
 | 
			
		||||
 | 
			
		||||
                RequestedThemeVariant = baseStyle switch
 | 
			
		||||
                {
 | 
			
		||||
                    "Auto" => systemTheme,
 | 
			
		||||
                    "Light" => ThemeVariant.Light,
 | 
			
		||||
                    "Dark" => ThemeVariant.Dark,
 | 
			
		||||
                    _ => ThemeVariant.Default,
 | 
			
		||||
@@ -111,5 +118,28 @@ namespace Ryujinx.Ava
 | 
			
		||||
                ShowRestartDialog();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Converts a PlatformThemeVariant value to the corresponding ThemeVariant value.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public static ThemeVariant ConvertThemeVariant(PlatformThemeVariant platformThemeVariant) =>
 | 
			
		||||
            platformThemeVariant switch
 | 
			
		||||
            {
 | 
			
		||||
                PlatformThemeVariant.Dark => ThemeVariant.Dark,
 | 
			
		||||
                PlatformThemeVariant.Light => ThemeVariant.Light,
 | 
			
		||||
                _ => ThemeVariant.Default,
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
        public static ThemeVariant DetectSystemTheme()
 | 
			
		||||
        {
 | 
			
		||||
            if (Application.Current is App app)
 | 
			
		||||
            {
 | 
			
		||||
                var colorValues = app.PlatformSettings.GetColorValues();
 | 
			
		||||
 | 
			
		||||
                return ConvertThemeVariant(colorValues.ThemeVariant);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return ThemeVariant.Default;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -404,6 +404,7 @@
 | 
			
		||||
  "GameListContextMenuToggleFavorite": "Toggle Favorite",
 | 
			
		||||
  "GameListContextMenuToggleFavoriteToolTip": "Toggle Favorite status of Game",
 | 
			
		||||
  "SettingsTabGeneralTheme": "Theme:",
 | 
			
		||||
  "SettingsTabGeneralThemeAuto": "Auto",
 | 
			
		||||
  "SettingsTabGeneralThemeDark": "Dark",
 | 
			
		||||
  "SettingsTabGeneralThemeLight": "Light",
 | 
			
		||||
  "ControllerSettingsConfigureGeneral": "Configure",
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										14
									
								
								src/Ryujinx/Common/ThemeManager.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								src/Ryujinx/Common/ThemeManager.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,14 @@
 | 
			
		||||
using System;
 | 
			
		||||
 | 
			
		||||
namespace Ryujinx.Ava.Common
 | 
			
		||||
{
 | 
			
		||||
    public static class ThemeManager
 | 
			
		||||
    {
 | 
			
		||||
        public static event EventHandler ThemeChanged;
 | 
			
		||||
 | 
			
		||||
        public static void OnThemeChanged()
 | 
			
		||||
        {
 | 
			
		||||
            ThemeChanged?.Invoke(null, EventArgs.Empty);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,6 +1,8 @@
 | 
			
		||||
using Avalonia.Media.Imaging;
 | 
			
		||||
using Avalonia.Platform;
 | 
			
		||||
using Avalonia.Styling;
 | 
			
		||||
using Avalonia.Threading;
 | 
			
		||||
using Ryujinx.Ava.Common;
 | 
			
		||||
using Ryujinx.Ava.Common.Locale;
 | 
			
		||||
using Ryujinx.Common.Utilities;
 | 
			
		||||
using Ryujinx.UI.Common.Configuration;
 | 
			
		||||
@@ -11,7 +13,7 @@ using System.Threading.Tasks;
 | 
			
		||||
 | 
			
		||||
namespace Ryujinx.Ava.UI.ViewModels
 | 
			
		||||
{
 | 
			
		||||
    public class AboutWindowViewModel : BaseModel
 | 
			
		||||
    public class AboutWindowViewModel : BaseModel, IDisposable
 | 
			
		||||
    {
 | 
			
		||||
        private Bitmap _githubLogo;
 | 
			
		||||
        private Bitmap _discordLogo;
 | 
			
		||||
@@ -86,23 +88,39 @@ namespace Ryujinx.Ava.UI.ViewModels
 | 
			
		||||
        public AboutWindowViewModel()
 | 
			
		||||
        {
 | 
			
		||||
            Version = Program.Version;
 | 
			
		||||
 | 
			
		||||
            if (ConfigurationState.Instance.UI.BaseStyle.Value == "Light")
 | 
			
		||||
            {
 | 
			
		||||
                GithubLogo = new Bitmap(AssetLoader.Open(new Uri("resm:Ryujinx.UI.Common.Resources.Logo_GitHub_Light.png?assembly=Ryujinx.UI.Common")));
 | 
			
		||||
                DiscordLogo = new Bitmap(AssetLoader.Open(new Uri("resm:Ryujinx.UI.Common.Resources.Logo_Discord_Light.png?assembly=Ryujinx.UI.Common")));
 | 
			
		||||
                PatreonLogo = new Bitmap(AssetLoader.Open(new Uri("resm:Ryujinx.UI.Common.Resources.Logo_Patreon_Light.png?assembly=Ryujinx.UI.Common")));
 | 
			
		||||
                TwitterLogo = new Bitmap(AssetLoader.Open(new Uri("resm:Ryujinx.UI.Common.Resources.Logo_Twitter_Light.png?assembly=Ryujinx.UI.Common")));
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                GithubLogo = new Bitmap(AssetLoader.Open(new Uri("resm:Ryujinx.UI.Common.Resources.Logo_GitHub_Dark.png?assembly=Ryujinx.UI.Common")));
 | 
			
		||||
                DiscordLogo = new Bitmap(AssetLoader.Open(new Uri("resm:Ryujinx.UI.Common.Resources.Logo_Discord_Dark.png?assembly=Ryujinx.UI.Common")));
 | 
			
		||||
                PatreonLogo = new Bitmap(AssetLoader.Open(new Uri("resm:Ryujinx.UI.Common.Resources.Logo_Patreon_Dark.png?assembly=Ryujinx.UI.Common")));
 | 
			
		||||
                TwitterLogo = new Bitmap(AssetLoader.Open(new Uri("resm:Ryujinx.UI.Common.Resources.Logo_Twitter_Dark.png?assembly=Ryujinx.UI.Common")));
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            UpdateLogoTheme(ConfigurationState.Instance.UI.BaseStyle.Value);
 | 
			
		||||
            Dispatcher.UIThread.InvokeAsync(DownloadPatronsJson);
 | 
			
		||||
 | 
			
		||||
            ThemeManager.ThemeChanged += ThemeManager_ThemeChanged;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void ThemeManager_ThemeChanged(object sender, EventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            Dispatcher.UIThread.Post(() => UpdateLogoTheme(ConfigurationState.Instance.UI.BaseStyle.Value));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void UpdateLogoTheme(string theme)
 | 
			
		||||
        {
 | 
			
		||||
            bool isDarkTheme = theme == "Dark" || (theme == "Auto" && App.DetectSystemTheme() == ThemeVariant.Dark);
 | 
			
		||||
 | 
			
		||||
            string basePath = "resm:Ryujinx.UI.Common.Resources.";
 | 
			
		||||
            string themeSuffix = isDarkTheme ? "Dark.png" : "Light.png";
 | 
			
		||||
 | 
			
		||||
            GithubLogo = LoadBitmap($"{basePath}Logo_GitHub_{themeSuffix}?assembly=Ryujinx.UI.Common");
 | 
			
		||||
            DiscordLogo = LoadBitmap($"{basePath}Logo_Discord_{themeSuffix}?assembly=Ryujinx.UI.Common");
 | 
			
		||||
            PatreonLogo = LoadBitmap($"{basePath}Logo_Patreon_{themeSuffix}?assembly=Ryujinx.UI.Common");
 | 
			
		||||
            TwitterLogo = LoadBitmap($"{basePath}Logo_Twitter_{themeSuffix}?assembly=Ryujinx.UI.Common");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private Bitmap LoadBitmap(string uri)
 | 
			
		||||
        {
 | 
			
		||||
            return new Bitmap(Avalonia.Platform.AssetLoader.Open(new Uri(uri)));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void Dispose()
 | 
			
		||||
        {
 | 
			
		||||
            ThemeManager.ThemeChanged -= ThemeManager_ThemeChanged;
 | 
			
		||||
            GC.SuppressFinalize(this);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private async Task DownloadPatronsJson()
 | 
			
		||||
 
 | 
			
		||||
@@ -397,7 +397,13 @@ namespace Ryujinx.Ava.UI.ViewModels
 | 
			
		||||
            GameDirectories.Clear();
 | 
			
		||||
            GameDirectories.AddRange(config.UI.GameDirs.Value);
 | 
			
		||||
 | 
			
		||||
            BaseStyleIndex = config.UI.BaseStyle == "Light" ? 0 : 1;
 | 
			
		||||
            BaseStyleIndex = config.UI.BaseStyle.Value switch
 | 
			
		||||
            {
 | 
			
		||||
                "Auto" => 0,
 | 
			
		||||
                "Light" => 1,
 | 
			
		||||
                "Dark" => 2,
 | 
			
		||||
                _ => 0
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            // Input
 | 
			
		||||
            EnableDockedMode = config.System.EnableDockedMode;
 | 
			
		||||
@@ -486,7 +492,13 @@ namespace Ryujinx.Ava.UI.ViewModels
 | 
			
		||||
                config.UI.GameDirs.Value = gameDirs;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            config.UI.BaseStyle.Value = BaseStyleIndex == 0 ? "Light" : "Dark";
 | 
			
		||||
            config.UI.BaseStyle.Value = BaseStyleIndex switch
 | 
			
		||||
            {
 | 
			
		||||
                0 => "Auto",
 | 
			
		||||
                1 => "Light",
 | 
			
		||||
                2 => "Dark",
 | 
			
		||||
                _ => "Auto"
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            // Input
 | 
			
		||||
            config.System.EnableDockedMode.Value = EnableDockedMode;
 | 
			
		||||
 
 | 
			
		||||
@@ -65,6 +65,9 @@
 | 
			
		||||
                        <ComboBox SelectedIndex="{Binding BaseStyleIndex}"
 | 
			
		||||
                                  HorizontalContentAlignment="Left"
 | 
			
		||||
                                  MinWidth="100">
 | 
			
		||||
                            <ComboBoxItem>
 | 
			
		||||
                                <TextBlock Text="{locale:Locale SettingsTabGeneralThemeAuto}" />
 | 
			
		||||
                            </ComboBoxItem>
 | 
			
		||||
                            <ComboBoxItem>
 | 
			
		||||
                                <TextBlock Text="{locale:Locale SettingsTabGeneralThemeLight}" />
 | 
			
		||||
                            </ComboBoxItem>
 | 
			
		||||
 
 | 
			
		||||
@@ -2,6 +2,7 @@ using Avalonia;
 | 
			
		||||
using Avalonia.Controls;
 | 
			
		||||
using Avalonia.Controls.Primitives;
 | 
			
		||||
using Avalonia.Interactivity;
 | 
			
		||||
using Avalonia.Platform;
 | 
			
		||||
using Avalonia.Threading;
 | 
			
		||||
using FluentAvalonia.UI.Controls;
 | 
			
		||||
using Ryujinx.Ava.Common;
 | 
			
		||||
@@ -92,6 +93,29 @@ namespace Ryujinx.Ava.UI.Windows
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Event handler for detecting OS theme change when using "Follow OS theme" option
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        private void OnPlatformColorValuesChanged(object sender, PlatformColorValues e)
 | 
			
		||||
        {
 | 
			
		||||
            if (Application.Current is App app)
 | 
			
		||||
            {
 | 
			
		||||
                app.ApplyConfiguredTheme();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        protected override void OnClosed(EventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            base.OnClosed(e);
 | 
			
		||||
            if (PlatformSettings != null)
 | 
			
		||||
            {
 | 
			
		||||
                /// <summary>
 | 
			
		||||
                /// Unsubscribe to the ColorValuesChanged event
 | 
			
		||||
                /// </summary>
 | 
			
		||||
                PlatformSettings.ColorValuesChanged -= OnPlatformColorValuesChanged;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            base.OnApplyTemplate(e);
 | 
			
		||||
@@ -390,6 +414,11 @@ namespace Ryujinx.Ava.UI.Windows
 | 
			
		||||
 | 
			
		||||
            Initialize();
 | 
			
		||||
 | 
			
		||||
            /// <summary>
 | 
			
		||||
            /// Subscribe to the ColorValuesChanged event
 | 
			
		||||
            /// </summary>
 | 
			
		||||
            PlatformSettings.ColorValuesChanged += OnPlatformColorValuesChanged;
 | 
			
		||||
 | 
			
		||||
            ViewModel.Initialize(
 | 
			
		||||
                ContentManager,
 | 
			
		||||
                StorageProvider,
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user