diff --git a/LightBulb.Core.Tests/LightBulb.Core.Tests.csproj b/LightBulb.Core.Tests/LightBulb.Core.Tests.csproj
index b829b6d..ba4c9c8 100644
--- a/LightBulb.Core.Tests/LightBulb.Core.Tests.csproj
+++ b/LightBulb.Core.Tests/LightBulb.Core.Tests.csproj
@@ -11,12 +11,12 @@
-
+
-
-
+
+
diff --git a/LightBulb.Core/LightBulb.Core.csproj b/LightBulb.Core/LightBulb.Core.csproj
index 9cb25d0..35a9f20 100644
--- a/LightBulb.Core/LightBulb.Core.csproj
+++ b/LightBulb.Core/LightBulb.Core.csproj
@@ -1,7 +1,7 @@
-
+
diff --git a/LightBulb.PlatformInterop/LightBulb.PlatformInterop.csproj b/LightBulb.PlatformInterop/LightBulb.PlatformInterop.csproj
index 5e9e81f..a37e6f7 100644
--- a/LightBulb.PlatformInterop/LightBulb.PlatformInterop.csproj
+++ b/LightBulb.PlatformInterop/LightBulb.PlatformInterop.csproj
@@ -1,7 +1,7 @@
-
+
\ No newline at end of file
diff --git a/LightBulb/App.axaml b/LightBulb/App.axaml
index 13df945..820c0ee 100644
--- a/LightBulb/App.axaml
+++ b/LightBulb/App.axaml
@@ -4,29 +4,42 @@
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">
+ xmlns:materialStyles="clr-namespace:Material.Styles.Themes;assembly=Material.Styles"
+ ActualThemeVariantChanged="Application_OnActualThemeVariantChanged">
-
-
-
-
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -150,6 +120,15 @@
+
+
+
+
+
+
+
+
+
+
-
-
-
-
- false
-
-
-
-
- true
-
-
diff --git a/LightBulb/App.axaml.cs b/LightBulb/App.axaml.cs
index 10f1f12..4adbe50 100644
--- a/LightBulb/App.axaml.cs
+++ b/LightBulb/App.axaml.cs
@@ -8,7 +8,6 @@
using Avalonia.Platform;
using Avalonia.Threading;
using LightBulb.Framework;
-using LightBulb.Models;
using LightBulb.Services;
using LightBulb.Utils;
using LightBulb.Utils.Extensions;
@@ -27,8 +26,8 @@ public class App : Application, IDisposable
private readonly DisposableCollector _eventRoot = new();
private readonly ServiceProvider _services;
- private readonly MainViewModel _mainViewModel;
private readonly SettingsService _settingsService;
+ private readonly MainViewModel _mainViewModel;
public App()
{
@@ -58,30 +57,29 @@ public App()
services.AddTransient();
_services = services.BuildServiceProvider(true);
- _mainViewModel = _services.GetRequiredService().CreateMainViewModel();
_settingsService = _services.GetRequiredService();
+ _mainViewModel = _services.GetRequiredService().CreateMainViewModel();
- // Load settings
- _settingsService.Load();
-
- _settingsService.WatchProperty(
- o => o.Theme,
- () =>
- {
- if (PlatformSettings is IPlatformSettings settings)
+ // Re-initialize the theme when the user changes it
+ _eventRoot.Add(
+ _settingsService.WatchProperty(
+ o => o.Theme,
+ () =>
{
- SetupTheme(settings.GetColorValues());
- }
- },
- false
+ RequestedThemeVariant = _settingsService.Theme switch
+ {
+ ThemeVariant.Light => Avalonia.Styling.ThemeVariant.Light,
+ ThemeVariant.Dark => Avalonia.Styling.ThemeVariant.Dark,
+ _ => Avalonia.Styling.ThemeVariant.Default
+ };
+
+ InitializeTheme();
+ },
+ false
+ )
);
- }
- public override void Initialize()
- {
- AvaloniaXamlLoader.Load(this);
-
- // Tray icon does not support binding so we use this hack to update its tooltip
+ // Tray icon does not support binding so we use this hack to synchronize its tooltip
_eventRoot.Add(
_mainViewModel.Dashboard.WatchProperties(
[o => o.IsActive, o => o.CurrentConfiguration],
@@ -102,59 +100,52 @@ public override void Initialize()
if (TrayIcon.GetIcons(this)?.FirstOrDefault() is { } trayIcon)
trayIcon.ToolTipText = tooltip;
});
- }
+ },
+ false
)
);
}
- public override void OnFrameworkInitializationCompleted()
+ public override void Initialize()
{
- if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktopLifetime)
- desktopLifetime.MainWindow = new MainView { DataContext = _mainViewModel };
-
- base.OnFrameworkInitializationCompleted();
+ base.Initialize();
- if (PlatformSettings is IPlatformSettings settings)
- {
- settings.ColorValuesChanged += PlatformSettings_ColorValuesChanged;
- SetupTheme(settings.GetColorValues());
- }
+ AvaloniaXamlLoader.Load(this);
}
- private void PlatformSettings_ColorValuesChanged(object? sender, PlatformColorValues colors)
+ private void InitializeTheme()
{
- SetupTheme(colors);
+ var actualTheme = RequestedThemeVariant?.Key switch
+ {
+ "Light" => PlatformThemeVariant.Light,
+ "Dark" => PlatformThemeVariant.Dark,
+ _ => PlatformSettings?.GetColorValues().ThemeVariant ?? PlatformThemeVariant.Light
+ };
+
+ this.LocateMaterialTheme().CurrentTheme =
+ actualTheme == PlatformThemeVariant.Light
+ ? Theme.Create(Theme.Light, Color.Parse("#343838"), Color.Parse("#F9A825"))
+ : Theme.Create(Theme.Dark, Color.Parse("#E8E8E8"), Color.Parse("#F9A825"));
}
- private void SetupTheme(PlatformColorValues colors)
+ public override void OnFrameworkInitializationCompleted()
{
- var themeMode = _settingsService.Theme;
- if (themeMode == ThemeMode.System)
- {
- themeMode =
- colors.ThemeVariant == PlatformThemeVariant.Dark ? ThemeMode.Dark : ThemeMode.Light;
- }
+ if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktopLifetime)
+ desktopLifetime.MainWindow = new MainView { DataContext = _mainViewModel };
- 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")
- );
- }
+ base.OnFrameworkInitializationCompleted();
+
+ // Set up custom theme colors
+ InitializeTheme();
+
+ // Load settings
+ _settingsService.Load();
}
+ private void Application_OnActualThemeVariantChanged(object? sender, EventArgs args) =>
+ // Re-initialize the theme when the system theme changes
+ InitializeTheme();
+
private void TrayIcon_OnClicked(object? sender, EventArgs args) => this.TryFocusMainWindow();
private void ShowSettingsMenuItem_OnClick(object? sender, EventArgs args)
diff --git a/LightBulb/Framework/ThemeVariant.cs b/LightBulb/Framework/ThemeVariant.cs
new file mode 100644
index 0000000..4a062ad
--- /dev/null
+++ b/LightBulb/Framework/ThemeVariant.cs
@@ -0,0 +1,8 @@
+namespace LightBulb.Framework;
+
+public enum ThemeVariant
+{
+ System,
+ Light,
+ Dark
+}
diff --git a/LightBulb/LightBulb.csproj b/LightBulb/LightBulb.csproj
index c13291a..00c8e75 100644
--- a/LightBulb/LightBulb.csproj
+++ b/LightBulb/LightBulb.csproj
@@ -19,14 +19,14 @@
-
+
-
+
-
-
+
+
diff --git a/LightBulb/Models/ThemeMode.cs b/LightBulb/Models/ThemeMode.cs
deleted file mode 100644
index 82d71c5..0000000
--- a/LightBulb/Models/ThemeMode.cs
+++ /dev/null
@@ -1,22 +0,0 @@
-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 c99f795..e85a80b 100644
--- a/LightBulb/Services/SettingsService.cs
+++ b/LightBulb/Services/SettingsService.cs
@@ -5,6 +5,7 @@
using Cogwheel;
using CommunityToolkit.Mvvm.ComponentModel;
using LightBulb.Core;
+using LightBulb.Framework;
using LightBulb.Models;
using LightBulb.PlatformInterop;
using LightBulb.Utils;
@@ -85,11 +86,11 @@ public partial class SettingsService() : SettingsBase(GetFilePath())
// Advanced
[ObservableProperty]
- [property: JsonIgnore] // comes from registry
- private bool _isAutoStartEnabled;
+ private ThemeVariant _theme;
[ObservableProperty]
- private ThemeMode _theme = ThemeMode.System;
+ [property: JsonIgnore] // comes from registry
+ private bool _isAutoStartEnabled;
[ObservableProperty]
private bool _isAutoUpdateEnabled = true;
diff --git a/LightBulb/ViewModels/Components/Settings/AdvancedSettingsTabViewModel.cs b/LightBulb/ViewModels/Components/Settings/AdvancedSettingsTabViewModel.cs
index 059306f..7cb85f9 100644
--- a/LightBulb/ViewModels/Components/Settings/AdvancedSettingsTabViewModel.cs
+++ b/LightBulb/ViewModels/Components/Settings/AdvancedSettingsTabViewModel.cs
@@ -1,6 +1,6 @@
using System;
using System.Collections.Generic;
-using LightBulb.Models;
+using LightBulb.Framework;
using LightBulb.Services;
namespace LightBulb.ViewModels.Components.Settings;
@@ -8,20 +8,20 @@ namespace LightBulb.ViewModels.Components.Settings;
public class AdvancedSettingsTabViewModel(SettingsService settingsService)
: SettingsTabViewModelBase(settingsService, 2, "Advanced")
{
- public bool IsAutoStartEnabled
- {
- get => SettingsService.IsAutoStartEnabled;
- set => SettingsService.IsAutoStartEnabled = value;
- }
-
- public IReadOnlyList ThemeArray { get; } = Enum.GetValues();
+ public IReadOnlyList AvailableThemes { get; } = Enum.GetValues();
- public ThemeMode Theme
+ public ThemeVariant Theme
{
get => SettingsService.Theme;
set => SettingsService.Theme = value;
}
+ public bool IsAutoStartEnabled
+ {
+ get => SettingsService.IsAutoStartEnabled;
+ set => SettingsService.IsAutoStartEnabled = value;
+ }
+
public bool IsAutoUpdateEnabled
{
get => SettingsService.IsAutoUpdateEnabled;
diff --git a/LightBulb/Views/Components/DashboardView.axaml b/LightBulb/Views/Components/DashboardView.axaml
index ad06e36..349bab7 100644
--- a/LightBulb/Views/Components/DashboardView.axaml
+++ b/LightBulb/Views/Components/DashboardView.axaml
@@ -12,39 +12,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+ ItemsSource="{Binding AvailableThemes}"
+ SelectedItem="{Binding Theme}" />
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
-
-
-
+
+
+
-
-
-
+
+
+
-
-
-
+
+
+
-
-
-
+
+
+
-
-
-
+
+
+
\ No newline at end of file
diff --git a/LightBulb/Views/Components/Settings/ApplicationWhitelistSettingsTabView.axaml b/LightBulb/Views/Components/Settings/ApplicationWhitelistSettingsTabView.axaml
index 22a0d90..a97a14b 100644
--- a/LightBulb/Views/Components/Settings/ApplicationWhitelistSettingsTabView.axaml
+++ b/LightBulb/Views/Components/Settings/ApplicationWhitelistSettingsTabView.axaml
@@ -42,8 +42,7 @@
HorizontalAlignment="Right"
VerticalAlignment="Center"
IsChecked="{Binding IsApplicationWhitelistEnabled}"
- ToolTip.Tip="Pause LightBulb when one of the selected applications is in the foreground"
- Classes.accent="{DynamicResource UseAccentControls}" />
+ ToolTip.Tip="Pause LightBulb when one of the selected applications is in the foreground" />
@@ -70,8 +69,7 @@
+ IsHitTestVisible="False" />
diff --git a/LightBulb/Views/Components/Settings/GeneralSettingsTabView.axaml b/LightBulb/Views/Components/Settings/GeneralSettingsTabView.axaml
index d1db410..621f466 100644
--- a/LightBulb/Views/Components/Settings/GeneralSettingsTabView.axaml
+++ b/LightBulb/Views/Components/Settings/GeneralSettingsTabView.axaml
@@ -17,8 +17,7 @@
MinWidth="24"
HorizontalAlignment="Right"
DockPanel.Dock="Right"
- Theme="{DynamicResource CompactTextBox}"
- Classes.accent="{DynamicResource UseAccentControls}">
+ Theme="{DynamicResource CompactTextBox}">
@@ -32,8 +31,7 @@
Minimum="2500"
SmallChange="100"
TickFrequency="20"
- Value="{Binding DayTemperature}"
- Classes.accent="{DynamicResource UseAccentControls}" />
+ Value="{Binding DayTemperature}" />
@@ -42,8 +40,7 @@
MinWidth="24"
HorizontalAlignment="Right"
DockPanel.Dock="Right"
- Theme="{DynamicResource CompactTextBox}"
- Classes.accent="{DynamicResource UseAccentControls}">
+ Theme="{DynamicResource CompactTextBox}">
@@ -57,8 +54,7 @@
Minimum="2500"
SmallChange="100"
TickFrequency="20"
- Value="{Binding NightTemperature}"
- Classes.accent="{DynamicResource UseAccentControls}" />
+ Value="{Binding NightTemperature}" />
@@ -80,8 +76,7 @@
MinWidth="24"
HorizontalAlignment="Right"
DockPanel.Dock="Right"
- Theme="{DynamicResource CompactTextBox}"
- Classes.accent="{DynamicResource UseAccentControls}">
+ Theme="{DynamicResource CompactTextBox}">
@@ -95,8 +90,7 @@
Minimum="0.1"
SmallChange="0.01"
TickFrequency="0.01"
- Value="{Binding DayBrightness}"
- Classes.accent="{DynamicResource UseAccentControls}" />
+ Value="{Binding DayBrightness}" />
@@ -118,8 +112,7 @@
MinWidth="24"
HorizontalAlignment="Right"
DockPanel.Dock="Right"
- Theme="{DynamicResource CompactTextBox}"
- Classes.accent="{DynamicResource UseAccentControls}">
+ Theme="{DynamicResource CompactTextBox}">
@@ -133,8 +126,7 @@
Minimum="0.1"
SmallChange="0.01"
TickFrequency="0.01"
- Value="{Binding NightBrightness}"
- Classes.accent="{DynamicResource UseAccentControls}" />
+ Value="{Binding NightBrightness}" />
@@ -143,8 +135,7 @@
MinWidth="48"
HorizontalAlignment="Right"
DockPanel.Dock="Right"
- Theme="{DynamicResource CompactTextBox}"
- Classes.accent="{DynamicResource UseAccentControls}">
+ Theme="{DynamicResource CompactTextBox}">
@@ -156,8 +147,7 @@
Maximum="3"
Minimum="0"
SmallChange="0.08"
- Value="{Binding ConfigurationTransitionDuration, Converter={x:Static converters:TimeSpanToHoursDoubleConverter.Instance}}"
- Classes.accent="{DynamicResource UseAccentControls}" />
+ Value="{Binding ConfigurationTransitionDuration, Converter={x:Static converters:TimeSpanToHoursDoubleConverter.Instance}}" />
@@ -166,8 +156,7 @@
MinWidth="24"
HorizontalAlignment="Right"
DockPanel.Dock="Right"
- Theme="{DynamicResource CompactTextBox}"
- Classes.accent="{DynamicResource UseAccentControls}">
+ Theme="{DynamicResource CompactTextBox}">
@@ -179,7 +168,6 @@
Maximum="1"
Minimum="0"
SmallChange="0.01"
- Value="{Binding ConfigurationTransitionOffset}"
- Classes.accent="{DynamicResource UseAccentControls}" />
+ Value="{Binding ConfigurationTransitionOffset}" />
\ No newline at end of file
diff --git a/LightBulb/Views/Components/Settings/LocationSettingsTabView.axaml b/LightBulb/Views/Components/Settings/LocationSettingsTabView.axaml
index 86edeb4..7a55f83 100644
--- a/LightBulb/Views/Components/Settings/LocationSettingsTabView.axaml
+++ b/LightBulb/Views/Components/Settings/LocationSettingsTabView.axaml
@@ -18,15 +18,13 @@
Content="Manual"
DockPanel.Dock="Left"
IsChecked="{Binding IsManualSunriseSunsetEnabled}"
- ToolTip.Tip="Configure sunrise and sunset manually"
- Classes.accent="{DynamicResource UseAccentControls}" />
+ ToolTip.Tip="Configure sunrise and sunset manually" />
+ ToolTip.Tip="Configure your location and use it to automatically calculate the sunrise and sunset times" />
@@ -41,8 +39,7 @@
MinWidth="24"
HorizontalAlignment="Right"
DockPanel.Dock="Right"
- Theme="{DynamicResource CompactTextBox}"
- Classes.accent="{DynamicResource UseAccentControls}">
+ Theme="{DynamicResource CompactTextBox}">
@@ -54,8 +51,7 @@
Maximum="23.99999"
Minimum="0"
SmallChange="0.25"
- Value="{Binding ManualSunrise, Converter={x:Static converters:TimeOnlyToHoursDoubleConverter.Instance}}"
- Classes.accent="{DynamicResource UseAccentControls}" />
+ Value="{Binding ManualSunrise, Converter={x:Static converters:TimeOnlyToHoursDoubleConverter.Instance}}" />
@@ -64,8 +60,7 @@
MinWidth="24"
HorizontalAlignment="Right"
DockPanel.Dock="Right"
- Theme="{DynamicResource CompactTextBox}"
- Classes.accent="{DynamicResource UseAccentControls}">
+ Theme="{DynamicResource CompactTextBox}">
@@ -77,8 +72,7 @@
Maximum="23.99999"
Minimum="0"
SmallChange="0.25"
- Value="{Binding ManualSunset, Converter={x:Static converters:TimeOnlyToHoursDoubleConverter.Instance}}"
- Classes.accent="{DynamicResource UseAccentControls}" />
+ Value="{Binding ManualSunset, Converter={x:Static converters:TimeOnlyToHoursDoubleConverter.Instance}}" />
@@ -110,8 +104,7 @@
VerticalAlignment="Center"
IsEnabled="{Binding !IsBusy}"
Text="{Binding LocationQuery}"
- Theme="{DynamicResource CompactTextBox}"
- Classes.accent="{DynamicResource UseAccentControls}">
+ Theme="{DynamicResource CompactTextBox}">
diff --git a/LightBulb/Views/Controls/HotKeyTextBox.axaml b/LightBulb/Views/Controls/HotKeyTextBox.axaml
index 2c81dd7..7777ecf 100644
--- a/LightBulb/Views/Controls/HotKeyTextBox.axaml
+++ b/LightBulb/Views/Controls/HotKeyTextBox.axaml
@@ -8,6 +8,5 @@
IsUndoEnabled="False"
Text="{Binding $parent[UserControl].HotKey, Mode=OneWay}"
TextAlignment="Center"
- Theme="{DynamicResource CompactTextBox}"
- Classes.accent="{DynamicResource UseAccentControls}" />
+ Theme="{DynamicResource CompactTextBox}" />
diff --git a/LightBulb/Views/Dialogs/SettingsView.axaml b/LightBulb/Views/Dialogs/SettingsView.axaml
index 9412346..05facd5 100644
--- a/LightBulb/Views/Dialogs/SettingsView.axaml
+++ b/LightBulb/Views/Dialogs/SettingsView.axaml
@@ -16,8 +16,8 @@
-
+ Background="{DynamicResource MaterialDarkBackgroundBrush}">
+
@@ -45,11 +45,13 @@
-
+
diff --git a/LightBulb/Views/MainView.axaml b/LightBulb/Views/MainView.axaml
index 0d8b759..c137fd9 100644
--- a/LightBulb/Views/MainView.axaml
+++ b/LightBulb/Views/MainView.axaml
@@ -21,7 +21,10 @@
-
+
-
+ ToolTip.Tip="Toggle LightBulb on/off">
@@ -68,7 +71,7 @@
Margin="8,1,0,0"
VerticalAlignment="Center"
FontSize="16"
- Foreground="{DynamicResource MaterialPrimaryMidForegroundBrush}">
+ Foreground="{DynamicResource MaterialDarkForegroundBrush}">