diff --git a/LightBulb/App.axaml b/LightBulb/App.axaml index 80eb446..13df945 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 a9dbce0..10f1f12 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 4c826f6..c13291a 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 0000000..82d71c5 --- /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 f33cce7..c99f795 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 4f8b2d0..059306f 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 3968500..531e899 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 989f41f..ad06e36 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 b897a8c..87df660 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 a97a14b..22a0d90 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 621f466..d1db410 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 7a55f83..86edeb4 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 7777ecf..2c81dd7 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 d896487..0d8b759 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">