Skip to content

Commit

Permalink
Refactor dark mode
Browse files Browse the repository at this point in the history
  • Loading branch information
Tyrrrz committed May 15, 2024
1 parent bf98eb1 commit 03218e8
Show file tree
Hide file tree
Showing 18 changed files with 228 additions and 343 deletions.
6 changes: 3 additions & 3 deletions LightBulb.Core.Tests/LightBulb.Core.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,12 @@

<ItemGroup>
<PackageReference Include="coverlet.collector" Version="6.0.2" PrivateAssets="all" />
<PackageReference Include="CSharpier.MsBuild" Version="0.28.1" PrivateAssets="all" />
<PackageReference Include="CSharpier.MsBuild" Version="0.28.2" PrivateAssets="all" />
<PackageReference Include="FluentAssertions" Version="6.12.0" />
<PackageReference Include="GitHubActionsTestLogger" Version="2.3.3" PrivateAssets="all" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.9.0" />
<PackageReference Include="xunit" Version="2.7.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.5.8" PrivateAssets="all" />
<PackageReference Include="xunit" Version="2.8.0" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.0" PrivateAssets="all" />
</ItemGroup>

<ItemGroup>
Expand Down
2 changes: 1 addition & 1 deletion LightBulb.Core/LightBulb.Core.csproj
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<ItemGroup>
<PackageReference Include="CSharpier.MsBuild" Version="0.28.1" PrivateAssets="all" />
<PackageReference Include="CSharpier.MsBuild" Version="0.28.2" PrivateAssets="all" />
<PackageReference Include="JsonExtensions" Version="1.2.0" />
</ItemGroup>

Expand Down
2 changes: 1 addition & 1 deletion LightBulb.PlatformInterop/LightBulb.PlatformInterop.csproj
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<ItemGroup>
<PackageReference Include="CSharpier.MsBuild" Version="0.28.1" PrivateAssets="all" />
<PackageReference Include="CSharpier.MsBuild" Version="0.28.2" PrivateAssets="all" />
</ItemGroup>

</Project>
106 changes: 37 additions & 69 deletions LightBulb/App.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -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">
<Application.DataTemplates>
<framework:ViewManager />
</Application.DataTemplates>

<Application.Styles>
<Style>
<Style.Resources>
<ResourceDictionary>
<!-- Fix bug with initialization of MaterialPaperBrush using MaterialThemeBase -->
<SolidColorBrush x:Key="MaterialPaperBrush" Color="#FF0000"></SolidColorBrush>
</ResourceDictionary>
</Style.Resources>
</Style>

<materialStyles:MaterialThemeBase />
<!-- This theme is used as a stub to pre-load default resources, the actual colors are set through code -->
<materialStyles:MaterialTheme
BaseTheme="Light"
PrimaryColor="Grey"
SecondaryColor="DeepOrange" />
<materialIcons:MaterialIconStyles />
<dialogHostAvalonia:DialogHostStyles />

<!-- Combo box -->
<Style Selector="ComboBox">
<Setter Property="FontSize" Value="14" />

<Style Selector="^ /template/ Panel#PART_RootPanel">
<Setter Property="Height" Value="22" />
</Style>

<Style Selector="^ /template/ ToggleButton">
<Style Selector="^:checked, ^:unchecked">
<Setter Property="Margin" Value="0" />
<Setter Property="CornerRadius" Value="0" />

<Style Selector="^ ContentPresenter#contentPresenter">
<Setter Property="Margin" Value="12,8" />
</Style>
</Style>
</Style>
</Style>

<!-- Dialog host -->
<Style Selector="dialogHostAvalonia|DialogHost">
<Setter Property="DialogMargin" Value="0" />
Expand Down Expand Up @@ -81,61 +94,18 @@
</Style>
</Style>

<!-- Apply Slider Accent class, since Material doesn't do it itself -->
<Style Selector="Slider.accent">
<Style Selector="^ Border#PART_InactiveState">
<Setter Property="Background" Value="{DynamicResource MaterialSecondaryMidBrush}" />
</Style>
<Style Selector="^ Border#PART_Indicator">
<Setter Property="Background" Value="{DynamicResource MaterialSecondaryMidBrush}" />
</Style>
<Style Selector="^ Border#PART_HoverEffect">
<Setter Property="Background" Value="{DynamicResource MaterialSecondaryMidBrush}" />
</Style>

<Style Selector="^ Border#PART_ThumbGrip">
<Setter Property="Background" Value="{DynamicResource MaterialSecondaryMidBrush}" />
</Style>
</Style>

<!-- Text box -->
<Style Selector="TextBox">
<Setter Property="FontSize" Value="14" />
</Style>

<!-- Apply TextBox Accent class, since material doesn't do it itself -->
<Style Selector="TextBox.accent">
<Setter Property="SelectionBrush" Value="{DynamicResource MaterialSecondaryMidBrush}" />
<Setter Property="SelectionForegroundBrush" Value="{DynamicResource MaterialSecondaryForegroundBrush}" />
<Setter Property="CaretBrush" Value="{DynamicResource MaterialSecondaryMidBrush}" />
<Style Selector="^ materialControls|MaterialUnderline">
<Setter Property="ActiveBrush" Value="{DynamicResource MaterialSecondaryMidBrush}" />
</Style>
</Style>

<!-- Toggle button -->
<Style Selector="ToggleButton">
<Setter Property="TextElement.FontWeight" Value="Medium" />
</Style>

<!-- Combo box -->
<Style Selector="ComboBox">
<Style Selector="^ /template/ Panel#PART_RootPanel">
<Setter Property="Height" Value="22" />
</Style>
</Style>

<!-- Apply ComboBox Accent class, since material doesn't do it itself -->
<Style Selector="ComboBox.accent">
<Style Selector="^ materialControls|MaterialUnderline">
<Setter Property="ActiveBrush" Value="{DynamicResource MaterialSecondaryMidBrush}" />
</Style>
</Style>

<!-- Toggle switch -->
<Style Selector="ToggleSwitch">
<!-- Apply custom style for disabled toggles, because Material's default is bad.-->
<!-- Tracked in https://github.com/AvaloniaCommunity/Material.Avalonia/issues/379 -->
<Setter Property="materialAssists:ToggleSwitchAssist.SwitchThumbOffBackground" Value="{DynamicResource ToggleBackgroundBrush}" />
</Style>

Expand All @@ -150,6 +120,15 @@

<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.ThemeDictionaries>
<ResourceDictionary x:Key="Default">
<SolidColorBrush x:Key="ToggleBackgroundBrush" Color="#FFFFFF" />
</ResourceDictionary>
<ResourceDictionary x:Key="Dark">
<SolidColorBrush x:Key="ToggleBackgroundBrush" Color="#8E8E8E" />
</ResourceDictionary>
</ResourceDictionary.ThemeDictionaries>

<!-- Text box -->
<ControlTheme
x:Key="CompactTextBox"
Expand All @@ -162,24 +141,13 @@
<Style Selector="^ /template/ Panel#PART_TextFieldPanel">
<Setter Property="MinHeight" Value="0" />
</Style>

<Style Selector="^ /template/ Panel#PART_TextContainer">
<Setter Property="Margin" Value="0" />
</Style>
</Style>
</Styles>
</ControlTheme>
<ResourceDictionary.ThemeDictionaries>
<ResourceDictionary x:Key="Light">
<!-- Custom style for disabled toggles -->
<SolidColorBrush x:Key="ToggleBackgroundBrush" Color="#FFFFFF"></SolidColorBrush>
<sys:Boolean x:Key="UseAccentControls">false</sys:Boolean>
</ResourceDictionary>
<ResourceDictionary x:Key="Dark">
<!-- Custom style for disabled toggles -->
<SolidColorBrush x:Key="ToggleBackgroundBrush" Color="#8E8E8E"></SolidColorBrush>
<sys:Boolean x:Key="UseAccentControls">true</sys:Boolean>
</ResourceDictionary>
</ResourceDictionary.ThemeDictionaries>
</ResourceDictionary>
</Application.Resources>

Expand Down
109 changes: 50 additions & 59 deletions LightBulb/App.axaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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()
{
Expand Down Expand Up @@ -58,30 +57,29 @@ public App()
services.AddTransient<SettingsTabViewModelBase, LocationSettingsTabViewModel>();

_services = services.BuildServiceProvider(true);
_mainViewModel = _services.GetRequiredService<ViewModelManager>().CreateMainViewModel();
_settingsService = _services.GetRequiredService<SettingsService>();
_mainViewModel = _services.GetRequiredService<ViewModelManager>().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],
Expand All @@ -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<MaterialThemeBase>().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<MaterialThemeBase>().CurrentTheme = Theme.Create(
Theme.Dark,
Color.Parse("#202222"),
Color.Parse("#F9A825")
);
}
else
{
RequestedThemeVariant = Avalonia.Styling.ThemeVariant.Light;
this.LocateMaterialTheme<MaterialThemeBase>().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)
Expand Down
8 changes: 8 additions & 0 deletions LightBulb/Framework/ThemeVariant.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace LightBulb.Framework;

public enum ThemeVariant
{
System,
Light,
Dark
}
8 changes: 4 additions & 4 deletions LightBulb/LightBulb.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,14 @@
<PackageReference Include="Avalonia" Version="11.0.10" />
<PackageReference Include="Avalonia.Desktop" Version="11.0.10" />
<PackageReference Include="Avalonia.Diagnostics" Version="11.0.10" Condition="'$(Configuration)' == 'Debug'" />
<PackageReference Include="Avalonia.Xaml.Behaviors" Version="11.0.10.6" />
<PackageReference Include="Avalonia.Xaml.Behaviors" Version="11.0.10.9" />
<PackageReference Include="Cogwheel" Version="2.0.4" />
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.2.2" />
<PackageReference Include="CSharpier.MsBuild" Version="0.28.1" PrivateAssets="all" />
<PackageReference Include="CSharpier.MsBuild" Version="0.28.2" PrivateAssets="all" />
<PackageReference Include="Deorcify" Version="1.0.2" PrivateAssets="all" />
<PackageReference Include="DialogHost.Avalonia" Version="0.7.7" />
<PackageReference Include="DotnetRuntimeBootstrapper" Version="2.5.3" PrivateAssets="all" Condition="$([MSBuild]::IsOsPlatform('Windows'))" />
<PackageReference Include="Material.Avalonia" Version="3.6.0" />
<PackageReference Include="DotnetRuntimeBootstrapper" Version="2.5.4" PrivateAssets="all" Condition="$([MSBuild]::IsOsPlatform('Windows'))" />
<PackageReference Include="Material.Avalonia" Version="3.5.0" />
<PackageReference Include="Material.Icons.Avalonia" Version="2.1.9" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.0" />
<PackageReference Include="Onova" Version="2.6.11" />
Expand Down
Loading

0 comments on commit 03218e8

Please sign in to comment.