mirror of
https://github.com/Artemis-RGB/Artemis
synced 2026-11-09 18:36:27 +00:00
UI - Add a monochrome tray icon option
- New "Monochrome tray icon" toggle under General settings - Shows a black or white icon matching the light or dark mode of the system tray - On Windows the color follows the taskbar (Windows mode), which can differ from the app mode - On Linux the color follows the system's light or dark mode - On macOS the icon is a template icon, so the menu bar colors it itself - Icons come in 16 to 256px, including the sizes used for high-DPI tray scaling Based on the idea and work in #867 by ArthurGamerHD.
This commit is contained in:
1 parent
5ddd50b4a8
commit
7574ad4ad6
13 files changed
+157
-3
No files matched your search
@@ -14,7 +14,7 @@
|
||||
|
||||
<TrayIcon.Icons>
|
||||
<TrayIcons>
|
||||
<TrayIcon Icon="avares://Artemis.UI/Assets/Images/Logo/application.ico" ToolTipText="Artemis" Command="{CompiledBinding OpenScreen}">
|
||||
<TrayIcon Icon="{CompiledBinding TrayIcon}" ToolTipText="Artemis" Command="{CompiledBinding OpenScreen}">
|
||||
<TrayIcon.Menu>
|
||||
<NativeMenu>
|
||||
<NativeMenuItem Header="Home" Command="{CompiledBinding OpenScreen}" CommandParameter="home" />
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
<TrayIcon.Icons>
|
||||
<TrayIcons>
|
||||
<TrayIcon Icon="avares://Artemis.UI/Assets/Images/Logo/application.ico" ToolTipText="Artemis" Command="{CompiledBinding OpenScreen}">
|
||||
<TrayIcon Icon="{CompiledBinding TrayIcon}" MacOSProperties.IsTemplateIcon="{CompiledBinding MonochromeTrayIcon}" ToolTipText="Artemis" Command="{CompiledBinding OpenScreen}">
|
||||
<TrayIcon.Menu>
|
||||
<NativeMenu>
|
||||
<NativeMenuItem Header="Home" Command="{CompiledBinding OpenScreen}" CommandParameter="home" />
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
<TrayIcon.Icons>
|
||||
<TrayIcons>
|
||||
<TrayIcon Icon="avares://Artemis.UI/Assets/Images/Logo/application.ico" ToolTipText="Artemis" Command="{CompiledBinding OpenScreen}">
|
||||
<TrayIcon Icon="{CompiledBinding TrayIcon}" ToolTipText="Artemis" Command="{CompiledBinding OpenScreen}">
|
||||
<TrayIcon.Menu>
|
||||
<NativeMenu>
|
||||
<NativeMenuItem Header="Home" Command="{CompiledBinding OpenScreen}" CommandParameter="home" />
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using Artemis.Core.Providers;
|
||||
using Artemis.Core.Services;
|
||||
using Artemis.UI.Services.Tray;
|
||||
using Artemis.UI.Services.Updating;
|
||||
using Artemis.UI.Shared.Providers;
|
||||
using Artemis.UI.Windows.Providers;
|
||||
@@ -25,5 +26,6 @@ public static class UIContainerExtensions
|
||||
container.Register<InputProvider, WindowsInputProvider>(serviceKey: WindowsInputProvider.Id);
|
||||
container.Register<IUpdateNotificationProvider, WindowsUpdateNotificationProvider>();
|
||||
container.Register<IProtocolProvider, ProtocolProvider>();
|
||||
container.Register<ITrayThemeProvider, WindowsTrayThemeProvider>(Reuse.Singleton);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
using System;
|
||||
using Artemis.UI.Services.Tray;
|
||||
using Microsoft.Win32;
|
||||
using Serilog;
|
||||
|
||||
namespace Artemis.UI.Windows.Providers;
|
||||
|
||||
/// <summary>
|
||||
/// Provides the light or dark mode of the Windows taskbar, which can differ from the app mode Avalonia reports.
|
||||
/// </summary>
|
||||
public class WindowsTrayThemeProvider : ITrayThemeProvider
|
||||
{
|
||||
private const string PersonalizeKey = @"Software\Microsoft\Windows\CurrentVersion\Themes\Personalize";
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="WindowsTrayThemeProvider" /> class.
|
||||
/// </summary>
|
||||
public WindowsTrayThemeProvider(ILogger logger)
|
||||
{
|
||||
try
|
||||
{
|
||||
SystemEvents.UserPreferenceChanged += SystemEventsOnUserPreferenceChanged;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
logger.Warning(e, "Could not subscribe to system events, the tray icon won't follow changes to the taskbar color");
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool IsTrayDark
|
||||
{
|
||||
get
|
||||
{
|
||||
// Versions of Windows without the setting only have a dark taskbar
|
||||
using RegistryKey? key = Registry.CurrentUser.OpenSubKey(PersonalizeKey);
|
||||
return key?.GetValue("SystemUsesLightTheme") is not 1;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public event EventHandler? TrayThemeChanged;
|
||||
|
||||
private void SystemEventsOnUserPreferenceChanged(object sender, UserPreferenceChangedEventArgs e)
|
||||
{
|
||||
if (e.Category == UserPreferenceCategory.General)
|
||||
TrayThemeChanged?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 115 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 115 KiB |
@@ -4,6 +4,7 @@ using Artemis.UI.DryIoc.InstanceProviders;
|
||||
using Artemis.UI.Screens.Device.Layout.LayoutProviders;
|
||||
using Artemis.UI.Screens.VisualScripting;
|
||||
using Artemis.UI.Services.Interfaces;
|
||||
using Artemis.UI.Services.Tray;
|
||||
using Artemis.UI.Services.Updating;
|
||||
using Artemis.UI.Shared;
|
||||
using Artemis.UI.Shared.Services.NodeEditor;
|
||||
@@ -33,6 +34,7 @@ public static class ContainerExtensions
|
||||
container.Register<NodeScriptWindowViewModelBase, NodeScriptWindowViewModel>(Reuse.Singleton);
|
||||
container.Register<IPropertyVmFactory, PropertyVmFactory>(Reuse.Singleton);
|
||||
container.Register<IUpdateNotificationProvider, BasicUpdateNotificationProvider>();
|
||||
container.Register<ITrayThemeProvider, BasicTrayThemeProvider>(Reuse.Singleton);
|
||||
|
||||
container.RegisterMany(thisAssembly, type => type.IsAssignableTo<IArtemisUIService>(), Reuse.Singleton);
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ using Artemis.Core.Services;
|
||||
using Artemis.UI.Models;
|
||||
using Artemis.UI.Screens.Sidebar;
|
||||
using Artemis.UI.Services.Interfaces;
|
||||
using Artemis.UI.Services.Tray;
|
||||
using Artemis.UI.Services.Updating;
|
||||
using Artemis.UI.Shared;
|
||||
using Artemis.UI.Shared.Routing;
|
||||
@@ -16,6 +17,7 @@ using Artemis.WebClient.Workshop.Services;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.ApplicationLifetimes;
|
||||
using Avalonia.Platform;
|
||||
using Avalonia.Threading;
|
||||
using ReactiveUI;
|
||||
using Serilog;
|
||||
@@ -34,6 +36,11 @@ public class RootViewModel : RoutableHostScreen<RoutableScreen>, IMainWindowProv
|
||||
private readonly IUpdateService _updateService;
|
||||
private readonly IWindowService _windowService;
|
||||
private readonly ObservableAsPropertyHelper<ViewModelBase?> _titleBarViewModel;
|
||||
private readonly PluginSetting<bool> _monochromeTrayIcon;
|
||||
private readonly ITrayThemeProvider _trayThemeProvider;
|
||||
private WindowIcon? _coloredTrayIcon;
|
||||
private WindowIcon? _blackTrayIcon;
|
||||
private WindowIcon? _whiteTrayIcon;
|
||||
|
||||
public RootViewModel(ILogger logger,
|
||||
IRouter router,
|
||||
@@ -45,6 +52,7 @@ public class RootViewModel : RoutableHostScreen<RoutableScreen>, IMainWindowProv
|
||||
IDebugService debugService,
|
||||
IUpdateService updateService,
|
||||
IWorkshopService workshopService,
|
||||
ITrayThemeProvider trayThemeProvider,
|
||||
SidebarViewModel sidebarViewModel,
|
||||
DefaultTitleBarViewModel defaultTitleBarViewModel)
|
||||
{
|
||||
@@ -60,8 +68,17 @@ public class RootViewModel : RoutableHostScreen<RoutableScreen>, IMainWindowProv
|
||||
_debugService = debugService;
|
||||
_updateService = updateService;
|
||||
_defaultTitleBarViewModel = defaultTitleBarViewModel;
|
||||
_trayThemeProvider = trayThemeProvider;
|
||||
_lifeTime = (IClassicDesktopStyleApplicationLifetime) Application.Current!.ApplicationLifetime!;
|
||||
|
||||
_monochromeTrayIcon = settingsService.GetSetting("UI.MonochromeTrayIcon", false);
|
||||
_monochromeTrayIcon.SettingChanged += (_, _) =>
|
||||
{
|
||||
this.RaisePropertyChanged(nameof(MonochromeTrayIcon));
|
||||
this.RaisePropertyChanged(nameof(TrayIcon));
|
||||
};
|
||||
_trayThemeProvider.TrayThemeChanged += (_, _) => Dispatcher.UIThread.Post(() => this.RaisePropertyChanged(nameof(TrayIcon)));
|
||||
|
||||
router.SetRoot(this);
|
||||
mainWindowService.ConfigureMainWindowProvider(this);
|
||||
|
||||
@@ -117,6 +134,26 @@ public class RootViewModel : RoutableHostScreen<RoutableScreen>, IMainWindowProv
|
||||
public ReactiveCommand<Unit, Unit> Exit { get; }
|
||||
|
||||
public ViewModelBase? TitleBarViewModel => _titleBarViewModel.Value;
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the tray icon is black or white rather than colored.
|
||||
/// </summary>
|
||||
public bool MonochromeTrayIcon => _monochromeTrayIcon.Value;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the tray icon, in black or white to match the system tray when <see cref="MonochromeTrayIcon" /> is enabled.
|
||||
/// </summary>
|
||||
public WindowIcon TrayIcon
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!_monochromeTrayIcon.Value)
|
||||
return _coloredTrayIcon ??= LoadTrayIcon("application");
|
||||
return _trayThemeProvider.IsTrayDark
|
||||
? _whiteTrayIcon ??= LoadTrayIcon("application-monochrome-white")
|
||||
: _blackTrayIcon ??= LoadTrayIcon("application-monochrome-black");
|
||||
}
|
||||
}
|
||||
public static PluginSetting<WindowSize?>? WindowSizeSetting { get; private set; }
|
||||
|
||||
public void GoBack()
|
||||
@@ -188,6 +225,11 @@ public class RootViewModel : RoutableHostScreen<RoutableScreen>, IMainWindowProv
|
||||
|
||||
#region Implementation of IMainWindowProvider
|
||||
|
||||
private static WindowIcon LoadTrayIcon(string name)
|
||||
{
|
||||
return new WindowIcon(AssetLoader.Open(new Uri($"avares://Artemis.UI/Assets/Images/Logo/{name}.ico")));
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool IsMainWindowOpen => _lifeTime.MainWindow != null;
|
||||
|
||||
|
||||
@@ -71,6 +71,19 @@
|
||||
</Grid>
|
||||
<Border Classes="card-separator" IsVisible="{CompiledBinding IsWindows11}"/>
|
||||
|
||||
<Grid RowDefinitions="*,*" ColumnDefinitions="*,Auto">
|
||||
<StackPanel Grid.Column="0">
|
||||
<TextBlock>Monochrome tray icon</TextBlock>
|
||||
<TextBlock Classes="subtitle" TextWrapping="Wrap">
|
||||
Show a black or white icon in the system tray instead of the colored one, matching your light or dark mode.
|
||||
</TextBlock>
|
||||
</StackPanel>
|
||||
<StackPanel Grid.Row="0" Grid.Column="1" VerticalAlignment="Center">
|
||||
<ToggleSwitch IsChecked="{CompiledBinding UIMonochromeTrayIcon.Value}" OnContent="Yes" OffContent="No" MinWidth="0" Margin="0 -10" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
<Border Classes="card-separator" />
|
||||
|
||||
<Grid RowDefinitions="*,*" ColumnDefinitions="*,Auto">
|
||||
<StackPanel Grid.Column="0">
|
||||
<TextBlock>Startup delay</TextBlock>
|
||||
|
||||
@@ -159,6 +159,7 @@ public class GeneralTabViewModel : RoutableScreen
|
||||
public PluginSetting<int> UIAutoRunDelay => _settingsService.GetSetting("UI.AutoRunDelay", 15);
|
||||
public PluginSetting<bool> UIShowOnStartup => _settingsService.GetSetting("UI.ShowOnStartup", true);
|
||||
public PluginSetting<bool> EnableMica => _settingsService.GetSetting("UI.EnableMica", true);
|
||||
public PluginSetting<bool> UIMonochromeTrayIcon => _settingsService.GetSetting("UI.MonochromeTrayIcon", false);
|
||||
public PluginSetting<bool> UICheckForUpdates => _settingsService.GetSetting("UI.Updating.AutoCheck", true);
|
||||
public PluginSetting<bool> WorkshopShowNotifications => _settingsService.GetSetting("Workshop.ShowNotifications", true);
|
||||
public PluginSetting<bool> UIAutoUpdate => _settingsService.GetSetting("UI.Updating.AutoInstall", true);
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
using System;
|
||||
using Avalonia;
|
||||
using Avalonia.Platform;
|
||||
|
||||
namespace Artemis.UI.Services.Tray;
|
||||
|
||||
/// <summary>
|
||||
/// Provides the light or dark mode of the system tray based on the light or dark mode of the operating system.
|
||||
/// </summary>
|
||||
public class BasicTrayThemeProvider : ITrayThemeProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="BasicTrayThemeProvider" /> class.
|
||||
/// </summary>
|
||||
public BasicTrayThemeProvider()
|
||||
{
|
||||
if (Application.Current?.PlatformSettings is { } platformSettings)
|
||||
platformSettings.ColorValuesChanged += (_, _) => TrayThemeChanged?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool IsTrayDark => Application.Current?.PlatformSettings?.GetColorValues().ThemeVariant != PlatformThemeVariant.Light;
|
||||
|
||||
/// <inheritdoc />
|
||||
public event EventHandler? TrayThemeChanged;
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
using System;
|
||||
|
||||
namespace Artemis.UI.Services.Tray;
|
||||
|
||||
/// <summary>
|
||||
/// Provides the light or dark mode of the system tray.
|
||||
/// </summary>
|
||||
public interface ITrayThemeProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the system tray has a dark background.
|
||||
/// </summary>
|
||||
bool IsTrayDark { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Occurs when the background of the system tray may have changed, possibly on a background thread.
|
||||
/// </summary>
|
||||
event EventHandler? TrayThemeChanged;
|
||||
}
|
||||
Reference in new issue
Block a user