From bf98eb1c47f847962fa40d7a51d6015fad47156a Mon Sep 17 00:00:00 2001 From: LilithSilver <84940819+LilithSilver@users.noreply.github.com> Date: Tue, 14 May 2024 11:30:17 -0700 Subject: [PATCH] Dark mode (#299) --- LightBulb/App.axaml | 100 ++++++++++++++---- LightBulb/App.axaml.cs | 64 +++++++++-- LightBulb/LightBulb.csproj | 2 +- LightBulb/Models/ThemeMode.cs | 22 ++++ LightBulb/Services/SettingsService.cs | 3 + .../Settings/AdvancedSettingsTabViewModel.cs | 13 ++- LightBulb/ViewModels/MainViewModel.cs | 3 - .../Views/Components/DashboardView.axaml | 53 ++++++++-- .../Settings/AdvancedSettingsTabView.axaml | 41 +++++-- .../ApplicationWhitelistSettingsTabView.axaml | 6 +- .../Settings/GeneralSettingsTabView.axaml | 36 ++++--- .../Settings/LocationSettingsTabView.axaml | 21 ++-- LightBulb/Views/Controls/HotKeyTextBox.axaml | 3 +- LightBulb/Views/MainView.axaml | 5 +- 14 files changed, 299 insertions(+), 73 deletions(-) create mode 100644 LightBulb/Models/ThemeMode.cs diff --git a/LightBulb/App.axaml b/LightBulb/App.axaml index 80eb4467..13df9456 100644 --- a/LightBulb/App.axaml +++ b/LightBulb/App.axaml @@ -4,13 +4,15 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:dialogHostAvalonia="clr-namespace:DialogHostAvalonia;assembly=DialogHost.Avalonia" xmlns:framework="clr-namespace:LightBulb.Framework" + xmlns:sys="using:System" xmlns:materialAssists="clr-namespace:Material.Styles.Assists;assembly=Material.Styles" + xmlns:materialControls="clr-namespace:Material.Styles.Controls;assembly=Material.Styles" xmlns:materialIcons="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia" - xmlns:materialStyles="clr-namespace:Material.Styles.Themes;assembly=Material.Styles" - RequestedThemeVariant="Light"> + xmlns:materialStyles="clr-namespace:Material.Styles.Themes;assembly=Material.Styles"> + + + + + + + + + + + + + + + + + + + + + @@ -104,25 +149,38 @@ - - - - - - + - - - + + + + + + + false + + + + + true + + + diff --git a/LightBulb/App.axaml.cs b/LightBulb/App.axaml.cs index a9dbce0a..10f1f123 100644 --- a/LightBulb/App.axaml.cs +++ b/LightBulb/App.axaml.cs @@ -5,8 +5,10 @@ using Avalonia.Controls.ApplicationLifetimes; using Avalonia.Markup.Xaml; using Avalonia.Media; +using Avalonia.Platform; using Avalonia.Threading; using LightBulb.Framework; +using LightBulb.Models; using LightBulb.Services; using LightBulb.Utils; using LightBulb.Utils.Extensions; @@ -26,6 +28,7 @@ public class App : Application, IDisposable private readonly ServiceProvider _services; private readonly MainViewModel _mainViewModel; + private readonly SettingsService _settingsService; public App() { @@ -56,6 +59,22 @@ public App() _services = services.BuildServiceProvider(true); _mainViewModel = _services.GetRequiredService().CreateMainViewModel(); + _settingsService = _services.GetRequiredService(); + + // Load settings + _settingsService.Load(); + + _settingsService.WatchProperty( + o => o.Theme, + () => + { + if (PlatformSettings is IPlatformSettings settings) + { + SetupTheme(settings.GetColorValues()); + } + }, + false + ); } public override void Initialize() @@ -95,12 +114,45 @@ public override void OnFrameworkInitializationCompleted() base.OnFrameworkInitializationCompleted(); - // Set custom theme colors - this.LocateMaterialTheme().CurrentTheme = Theme.Create( - Theme.Light, - Color.Parse("#343838"), - Color.Parse("#F9A825") - ); + if (PlatformSettings is IPlatformSettings settings) + { + settings.ColorValuesChanged += PlatformSettings_ColorValuesChanged; + SetupTheme(settings.GetColorValues()); + } + } + + private void PlatformSettings_ColorValuesChanged(object? sender, PlatformColorValues colors) + { + SetupTheme(colors); + } + + private void SetupTheme(PlatformColorValues colors) + { + var themeMode = _settingsService.Theme; + if (themeMode == ThemeMode.System) + { + themeMode = + colors.ThemeVariant == PlatformThemeVariant.Dark ? ThemeMode.Dark : ThemeMode.Light; + } + + if (themeMode == ThemeMode.Dark) + { + RequestedThemeVariant = Avalonia.Styling.ThemeVariant.Dark; + this.LocateMaterialTheme().CurrentTheme = Theme.Create( + Theme.Dark, + Color.Parse("#202222"), + Color.Parse("#F9A825") + ); + } + else + { + RequestedThemeVariant = Avalonia.Styling.ThemeVariant.Light; + this.LocateMaterialTheme().CurrentTheme = Theme.Create( + Theme.Light, + Color.Parse("#343838"), + Color.Parse("#F9A825") + ); + } } private void TrayIcon_OnClicked(object? sender, EventArgs args) => this.TryFocusMainWindow(); diff --git a/LightBulb/LightBulb.csproj b/LightBulb/LightBulb.csproj index 4c826f6c..c13291ae 100644 --- a/LightBulb/LightBulb.csproj +++ b/LightBulb/LightBulb.csproj @@ -26,7 +26,7 @@ - + diff --git a/LightBulb/Models/ThemeMode.cs b/LightBulb/Models/ThemeMode.cs new file mode 100644 index 00000000..82d71c55 --- /dev/null +++ b/LightBulb/Models/ThemeMode.cs @@ -0,0 +1,22 @@ +namespace LightBulb.Models; + +/// +/// Describes the application's theme mode. +/// +public enum ThemeMode +{ + /// + /// Use the light theme + /// + Light, + + /// + /// Use the dark theme + /// + Dark, + + /// + /// Use whichever theme is specified by system settings + /// + System +} diff --git a/LightBulb/Services/SettingsService.cs b/LightBulb/Services/SettingsService.cs index f33cce70..c99f7957 100644 --- a/LightBulb/Services/SettingsService.cs +++ b/LightBulb/Services/SettingsService.cs @@ -88,6 +88,9 @@ public partial class SettingsService() : SettingsBase(GetFilePath()) [property: JsonIgnore] // comes from registry private bool _isAutoStartEnabled; + [ObservableProperty] + private ThemeMode _theme = ThemeMode.System; + [ObservableProperty] private bool _isAutoUpdateEnabled = true; diff --git a/LightBulb/ViewModels/Components/Settings/AdvancedSettingsTabViewModel.cs b/LightBulb/ViewModels/Components/Settings/AdvancedSettingsTabViewModel.cs index 4f8b2d04..059306f7 100644 --- a/LightBulb/ViewModels/Components/Settings/AdvancedSettingsTabViewModel.cs +++ b/LightBulb/ViewModels/Components/Settings/AdvancedSettingsTabViewModel.cs @@ -1,4 +1,7 @@ -using LightBulb.Services; +using System; +using System.Collections.Generic; +using LightBulb.Models; +using LightBulb.Services; namespace LightBulb.ViewModels.Components.Settings; @@ -11,6 +14,14 @@ public bool IsAutoStartEnabled set => SettingsService.IsAutoStartEnabled = value; } + public IReadOnlyList ThemeArray { get; } = Enum.GetValues(); + + public ThemeMode Theme + { + get => SettingsService.Theme; + set => SettingsService.Theme = value; + } + public bool IsAutoUpdateEnabled { get => SettingsService.IsAutoUpdateEnabled; diff --git a/LightBulb/ViewModels/MainViewModel.cs b/LightBulb/ViewModels/MainViewModel.cs index 39685004..531e8994 100644 --- a/LightBulb/ViewModels/MainViewModel.cs +++ b/LightBulb/ViewModels/MainViewModel.cs @@ -143,9 +143,6 @@ Click LEARN MORE to find ways that you can help. [RelayCommand] private async Task InitializeAsync() { - // Load settings - settingsService.Load(); - await FinalizePendingUpdateAsync(); await ShowGammaRangePromptAsync(); await ShowFirstTimeExperienceMessageAsync(); diff --git a/LightBulb/Views/Components/DashboardView.axaml b/LightBulb/Views/Components/DashboardView.axaml index 989f41f6..ad06e365 100644 --- a/LightBulb/Views/Components/DashboardView.axaml +++ b/LightBulb/Views/Components/DashboardView.axaml @@ -12,6 +12,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -57,14 +90,14 @@ Height="180" EndAngle="{Binding SunsetStart, Converter={x:Static converters:TimeOnlyToDegreesDoubleConverter.Instance}}" StartAngle="{Binding SunriseEnd, Converter={x:Static converters:TimeOnlyToDegreesDoubleConverter.Instance}}" - Stroke="#8AC0FF" + Stroke="{DynamicResource SundialDayBorderBrush}" StrokeThickness="28" /> @@ -73,14 +106,14 @@ Height="180" EndAngle="{Binding SunriseEnd, Converter={x:Static converters:TimeOnlyToDegreesDoubleConverter.Instance}}" StartAngle="{Binding SunriseStart, Converter={x:Static converters:TimeOnlyToDegreesDoubleConverter.Instance}}" - Stroke="#FFC766" + Stroke="{DynamicResource SundialSunriseBorderBrush}" StrokeThickness="28" /> @@ -89,14 +122,14 @@ Height="180" EndAngle="{Binding SunsetEnd, Converter={x:Static converters:TimeOnlyToDegreesDoubleConverter.Instance}}" StartAngle="{Binding SunsetStart, Converter={x:Static converters:TimeOnlyToDegreesDoubleConverter.Instance}}" - Stroke="#FFC766" + Stroke="{DynamicResource SundialSunsetBorderBrush}" StrokeThickness="28" /> @@ -104,13 +137,13 @@ Width="180" Height="180" Angle="{Binding Instant.TimeOfDay.TotalDays, Converter={x:Static converters:FractionToDegreesConverter.Instance}}" - Fill="#FF7733" + Fill="{DynamicResource SundialMarkerBorderBrush}" Size="28" /> diff --git a/LightBulb/Views/Components/Settings/AdvancedSettingsTabView.axaml b/LightBulb/Views/Components/Settings/AdvancedSettingsTabView.axaml index b897a8cb..87df660e 100644 --- a/LightBulb/Views/Components/Settings/AdvancedSettingsTabView.axaml +++ b/LightBulb/Views/Components/Settings/AdvancedSettingsTabView.axaml @@ -18,11 +18,33 @@ HorizontalAlignment="Right" VerticalAlignment="Center" DockPanel.Dock="Right" - IsChecked="{Binding IsAutoStartEnabled}" /> + IsChecked="{Binding IsAutoStartEnabled}" + Classes.accent="{DynamicResource UseAccentControls}" /> + + + + + + + + + + + + + - + + IsChecked="{Binding IsAutoUpdateEnabled}" + Classes.accent="{DynamicResource UseAccentControls}" /> @@ -44,7 +67,8 @@ HorizontalAlignment="Right" VerticalAlignment="Center" DockPanel.Dock="Right" - IsChecked="{Binding IsDefaultToDayConfigurationEnabled}" /> + IsChecked="{Binding IsDefaultToDayConfigurationEnabled}" + Classes.accent="{DynamicResource UseAccentControls}" /> @@ -57,7 +81,8 @@ HorizontalAlignment="Right" VerticalAlignment="Center" DockPanel.Dock="Right" - IsChecked="{Binding IsPauseWhenFullScreenEnabled}" /> + IsChecked="{Binding IsPauseWhenFullScreenEnabled}" + Classes.accent="{DynamicResource UseAccentControls}" /> @@ -70,7 +95,8 @@ HorizontalAlignment="Right" VerticalAlignment="Center" DockPanel.Dock="Right" - IsChecked="{Binding IsConfigurationSmoothingEnabled}" /> + IsChecked="{Binding IsConfigurationSmoothingEnabled}" + Classes.accent="{DynamicResource UseAccentControls}" /> @@ -83,7 +109,8 @@ HorizontalAlignment="Right" VerticalAlignment="Center" DockPanel.Dock="Right" - IsChecked="{Binding IsGammaPollingEnabled}" /> + IsChecked="{Binding IsGammaPollingEnabled}" + Classes.accent="{DynamicResource UseAccentControls}" /> \ No newline at end of file diff --git a/LightBulb/Views/Components/Settings/ApplicationWhitelistSettingsTabView.axaml b/LightBulb/Views/Components/Settings/ApplicationWhitelistSettingsTabView.axaml index a97a14bd..22a0d902 100644 --- a/LightBulb/Views/Components/Settings/ApplicationWhitelistSettingsTabView.axaml +++ b/LightBulb/Views/Components/Settings/ApplicationWhitelistSettingsTabView.axaml @@ -42,7 +42,8 @@ HorizontalAlignment="Right" VerticalAlignment="Center" IsChecked="{Binding IsApplicationWhitelistEnabled}" - ToolTip.Tip="Pause LightBulb when one of the selected applications is in the foreground" /> + ToolTip.Tip="Pause LightBulb when one of the selected applications is in the foreground" + Classes.accent="{DynamicResource UseAccentControls}" /> @@ -69,7 +70,8 @@ + IsHitTestVisible="False" + Classes.accent="{DynamicResource UseAccentControls}"/> diff --git a/LightBulb/Views/Components/Settings/GeneralSettingsTabView.axaml b/LightBulb/Views/Components/Settings/GeneralSettingsTabView.axaml index 621f4668..d1db4102 100644 --- a/LightBulb/Views/Components/Settings/GeneralSettingsTabView.axaml +++ b/LightBulb/Views/Components/Settings/GeneralSettingsTabView.axaml @@ -17,7 +17,8 @@ MinWidth="24" HorizontalAlignment="Right" DockPanel.Dock="Right" - Theme="{DynamicResource CompactTextBox}"> + Theme="{DynamicResource CompactTextBox}" + Classes.accent="{DynamicResource UseAccentControls}"> @@ -31,7 +32,8 @@ Minimum="2500" SmallChange="100" TickFrequency="20" - Value="{Binding DayTemperature}" /> + Value="{Binding DayTemperature}" + Classes.accent="{DynamicResource UseAccentControls}" /> @@ -40,7 +42,8 @@ MinWidth="24" HorizontalAlignment="Right" DockPanel.Dock="Right" - Theme="{DynamicResource CompactTextBox}"> + Theme="{DynamicResource CompactTextBox}" + Classes.accent="{DynamicResource UseAccentControls}"> @@ -54,7 +57,8 @@ Minimum="2500" SmallChange="100" TickFrequency="20" - Value="{Binding NightTemperature}" /> + Value="{Binding NightTemperature}" + Classes.accent="{DynamicResource UseAccentControls}" /> @@ -76,7 +80,8 @@ MinWidth="24" HorizontalAlignment="Right" DockPanel.Dock="Right" - Theme="{DynamicResource CompactTextBox}"> + Theme="{DynamicResource CompactTextBox}" + Classes.accent="{DynamicResource UseAccentControls}"> @@ -90,7 +95,8 @@ Minimum="0.1" SmallChange="0.01" TickFrequency="0.01" - Value="{Binding DayBrightness}" /> + Value="{Binding DayBrightness}" + Classes.accent="{DynamicResource UseAccentControls}" /> @@ -112,7 +118,8 @@ MinWidth="24" HorizontalAlignment="Right" DockPanel.Dock="Right" - Theme="{DynamicResource CompactTextBox}"> + Theme="{DynamicResource CompactTextBox}" + Classes.accent="{DynamicResource UseAccentControls}"> @@ -126,7 +133,8 @@ Minimum="0.1" SmallChange="0.01" TickFrequency="0.01" - Value="{Binding NightBrightness}" /> + Value="{Binding NightBrightness}" + Classes.accent="{DynamicResource UseAccentControls}" /> @@ -135,7 +143,8 @@ MinWidth="48" HorizontalAlignment="Right" DockPanel.Dock="Right" - Theme="{DynamicResource CompactTextBox}"> + Theme="{DynamicResource CompactTextBox}" + Classes.accent="{DynamicResource UseAccentControls}"> @@ -147,7 +156,8 @@ Maximum="3" Minimum="0" SmallChange="0.08" - Value="{Binding ConfigurationTransitionDuration, Converter={x:Static converters:TimeSpanToHoursDoubleConverter.Instance}}" /> + Value="{Binding ConfigurationTransitionDuration, Converter={x:Static converters:TimeSpanToHoursDoubleConverter.Instance}}" + Classes.accent="{DynamicResource UseAccentControls}" /> @@ -156,7 +166,8 @@ MinWidth="24" HorizontalAlignment="Right" DockPanel.Dock="Right" - Theme="{DynamicResource CompactTextBox}"> + Theme="{DynamicResource CompactTextBox}" + Classes.accent="{DynamicResource UseAccentControls}"> @@ -168,6 +179,7 @@ Maximum="1" Minimum="0" SmallChange="0.01" - Value="{Binding ConfigurationTransitionOffset}" /> + Value="{Binding ConfigurationTransitionOffset}" + Classes.accent="{DynamicResource UseAccentControls}" /> \ No newline at end of file diff --git a/LightBulb/Views/Components/Settings/LocationSettingsTabView.axaml b/LightBulb/Views/Components/Settings/LocationSettingsTabView.axaml index 7a55f835..86edeb4c 100644 --- a/LightBulb/Views/Components/Settings/LocationSettingsTabView.axaml +++ b/LightBulb/Views/Components/Settings/LocationSettingsTabView.axaml @@ -18,13 +18,15 @@ Content="Manual" DockPanel.Dock="Left" IsChecked="{Binding IsManualSunriseSunsetEnabled}" - ToolTip.Tip="Configure sunrise and sunset manually" /> + ToolTip.Tip="Configure sunrise and sunset manually" + Classes.accent="{DynamicResource UseAccentControls}" /> + ToolTip.Tip="Configure your location and use it to automatically calculate the sunrise and sunset times" + Classes.accent="{DynamicResource UseAccentControls}" /> @@ -39,7 +41,8 @@ MinWidth="24" HorizontalAlignment="Right" DockPanel.Dock="Right" - Theme="{DynamicResource CompactTextBox}"> + Theme="{DynamicResource CompactTextBox}" + Classes.accent="{DynamicResource UseAccentControls}"> @@ -51,7 +54,8 @@ Maximum="23.99999" Minimum="0" SmallChange="0.25" - Value="{Binding ManualSunrise, Converter={x:Static converters:TimeOnlyToHoursDoubleConverter.Instance}}" /> + Value="{Binding ManualSunrise, Converter={x:Static converters:TimeOnlyToHoursDoubleConverter.Instance}}" + Classes.accent="{DynamicResource UseAccentControls}" /> @@ -60,7 +64,8 @@ MinWidth="24" HorizontalAlignment="Right" DockPanel.Dock="Right" - Theme="{DynamicResource CompactTextBox}"> + Theme="{DynamicResource CompactTextBox}" + Classes.accent="{DynamicResource UseAccentControls}"> @@ -72,7 +77,8 @@ Maximum="23.99999" Minimum="0" SmallChange="0.25" - Value="{Binding ManualSunset, Converter={x:Static converters:TimeOnlyToHoursDoubleConverter.Instance}}" /> + Value="{Binding ManualSunset, Converter={x:Static converters:TimeOnlyToHoursDoubleConverter.Instance}}" + Classes.accent="{DynamicResource UseAccentControls}" /> @@ -104,7 +110,8 @@ VerticalAlignment="Center" IsEnabled="{Binding !IsBusy}" Text="{Binding LocationQuery}" - Theme="{DynamicResource CompactTextBox}"> + Theme="{DynamicResource CompactTextBox}" + Classes.accent="{DynamicResource UseAccentControls}"> diff --git a/LightBulb/Views/Controls/HotKeyTextBox.axaml b/LightBulb/Views/Controls/HotKeyTextBox.axaml index 7777ecf9..2c81dd70 100644 --- a/LightBulb/Views/Controls/HotKeyTextBox.axaml +++ b/LightBulb/Views/Controls/HotKeyTextBox.axaml @@ -8,5 +8,6 @@ IsUndoEnabled="False" Text="{Binding $parent[UserControl].HotKey, Mode=OneWay}" TextAlignment="Center" - Theme="{DynamicResource CompactTextBox}" /> + Theme="{DynamicResource CompactTextBox}" + Classes.accent="{DynamicResource UseAccentControls}" /> diff --git a/LightBulb/Views/MainView.axaml b/LightBulb/Views/MainView.axaml index d896487b..0d8b759e 100644 --- a/LightBulb/Views/MainView.axaml +++ b/LightBulb/Views/MainView.axaml @@ -35,6 +35,7 @@ Background="{DynamicResource MaterialPrimaryMidBrush}" PointerPressed="HeaderBorder_OnPointerPressed"> + + ToolTip.Tip="Toggle LightBulb on/off" + Classes="primary">