diff --git a/src/Snap.Hutao/Snap.Hutao/Core/Windowing/Theme.cs b/src/Snap.Hutao/Snap.Hutao/Core/Windowing/Theme.cs new file mode 100644 index 00000000..2bf0a655 --- /dev/null +++ b/src/Snap.Hutao/Snap.Hutao/Core/Windowing/Theme.cs @@ -0,0 +1,17 @@ +// Copyright (c) DGP Studio. All rights reserved. +// Licensed under the MIT license. + +namespace Snap.Hutao.Core.Windowing; + +[Localization] +internal enum Theme +{ + [LocalizationKey(nameof(SH.CoreWindowThemeLight))] + Light, + + [LocalizationKey(nameof(SH.CoreWindowThemeDark))] + Dark, + + [LocalizationKey(nameof(SH.CoreWindowThemeSystem))] + System, +} diff --git a/src/Snap.Hutao/Snap.Hutao/Core/Windowing/WindowController.cs b/src/Snap.Hutao/Snap.Hutao/Core/Windowing/WindowController.cs index 5b4bada8..2ae9afd4 100644 --- a/src/Snap.Hutao/Snap.Hutao/Core/Windowing/WindowController.cs +++ b/src/Snap.Hutao/Snap.Hutao/Core/Windowing/WindowController.cs @@ -129,6 +129,13 @@ internal sealed class WindowController UpdateSystemBackdrop(options.BackdropType); } } + else if (e.PropertyName is nameof(AppOptions.Theme)) + { + if (sender is AppOptions options) + { + UpdateTheme(options.Theme); + } + } } private void OnWindowClosed(object sender, WindowEventArgs args) @@ -170,6 +177,16 @@ internal sealed class WindowController }; } + private void UpdateTheme(Theme theme) + { + ((FrameworkElement)window.Content).RequestedTheme = theme switch + { + Theme.Light => ElementTheme.Light, + Theme.Dark => ElementTheme.Dark, + _ => ElementTheme.Default, + }; + } + private void UpdateTitleButtonColor() { AppWindowTitleBar appTitleBar = window.AppWindow.TitleBar; diff --git a/src/Snap.Hutao/Snap.Hutao/Model/Entity/SettingEntry.Constant.cs b/src/Snap.Hutao/Snap.Hutao/Model/Entity/SettingEntry.Constant.cs index 9b70a6db..7cc988e7 100644 --- a/src/Snap.Hutao/Snap.Hutao/Model/Entity/SettingEntry.Constant.cs +++ b/src/Snap.Hutao/Snap.Hutao/Model/Entity/SettingEntry.Constant.cs @@ -13,6 +13,7 @@ internal sealed partial class SettingEntry public const string Culture = "Culture"; public const string SystemBackdropType = "SystemBackdropType"; + public const string Theme = "Theme"; public const string BackgroundImageType = "BackgroundImageType"; public const string AnnouncementRegion = "AnnouncementRegion"; diff --git a/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.en.resx b/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.en.resx index 06220390..4c03eb10 100644 --- a/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.en.resx +++ b/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.en.resx @@ -60,45 +60,45 @@ : and then encoded with base64 encoding. --> - + - + - - - - + + + + - - + + - - + + - - - - + + + + - + - + @@ -186,6 +186,15 @@ No WebView2 Runtime detected + + Dark + + + Light + + + System + Export diff --git a/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.resx b/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.resx index 2450ca89..eead6b9d 100644 --- a/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.resx +++ b/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.resx @@ -189,6 +189,15 @@ [{0}] 热键 [{1}] 注册失败 + + 深色 + + + 浅色 + + + 跟随系统 + 导出 @@ -2627,6 +2636,12 @@ 评价软件 + + 更改窗体的颜色主题 + + + 颜色主题 + 贡献翻译 diff --git a/src/Snap.Hutao/Snap.Hutao/Service/AppOptions.cs b/src/Snap.Hutao/Snap.Hutao/Service/AppOptions.cs index 34a082be..839e5488 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/AppOptions.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/AppOptions.cs @@ -16,6 +16,7 @@ internal sealed partial class AppOptions : DbStoreOptions { private bool? isEmptyHistoryWishVisible; private BackdropType? backdropType; + private Theme? theme; private BackgroundImageType? backgroundImageType; private Region? region; private string? geetestCustomCompositeUrl; @@ -34,6 +35,14 @@ internal sealed partial class AppOptions : DbStoreOptions set => SetOption(ref backdropType, SettingEntry.SystemBackdropType, value, EnumToStringOrEmpty); } + public List> Themes { get; } = CollectionsNameValue.FromEnum(theme => theme.GetLocalizedDescription()); + + public Theme Theme + { + get => GetOption(ref theme, SettingEntry.Theme, EnumParse, Theme.System).Value; + set => SetOption(ref theme, SettingEntry.Theme, value, EnumToStringOrEmpty); + } + public List> BackgroundImageTypes { get; } = CollectionsNameValue.FromEnum(type => type.GetLocalizedDescription()); public BackgroundImageType BackgroundImageType diff --git a/src/Snap.Hutao/Snap.Hutao/View/Page/SettingPage.xaml b/src/Snap.Hutao/Snap.Hutao/View/Page/SettingPage.xaml index ff1dd372..77115d0d 100644 --- a/src/Snap.Hutao/Snap.Hutao/View/Page/SettingPage.xaml +++ b/src/Snap.Hutao/Snap.Hutao/View/Page/SettingPage.xaml @@ -314,6 +314,17 @@ SelectedItem="{Binding SelectedBackdropType, Mode=TwoWay}"/> + + + + + ? selectedBackdropType; + private NameValue? selectedTheme; private NameValue? selectedBackgroundImageType; private NameValue? selectedCulture; private NameValue? selectedRegion; @@ -94,6 +95,18 @@ internal sealed partial class SettingViewModel : Abstraction.ViewModel } } + public NameValue? SelectedTheme + { + get => selectedTheme ??= AppOptions.Themes.Single(t => t.Value == AppOptions.Theme); + set + { + if (SetProperty(ref selectedTheme, value) && value is not null) + { + AppOptions.Theme = value.Value; + } + } + } + public NameValue? SelectedBackgroundImageType { get => selectedBackgroundImageType ??= AppOptions.BackgroundImageTypes.Single(t => t.Value == AppOptions.BackgroundImageType);