Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/UniGetUI.Avalonia/Assets/Styles/Styles.Windows.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@
<SolidColorBrush x:Key="StatusErrorForeground" Color="#ef9a9a"/>
<!-- Setting warning subtext -->
<SolidColorBrush x:Key="SettingWarningTextForeground" Color="#ffc107"/>
<!-- Operation log output text -->
<SolidColorBrush x:Key="LogOutputVerboseForeground" Color="#9D9D9D"/>
</ResourceDictionary>
<ResourceDictionary x:Key="Light">
<!-- Settings cards -->
Expand Down Expand Up @@ -76,6 +78,8 @@
<SolidColorBrush x:Key="StatusErrorForeground" Color="#c62828"/>
<!-- Setting warning subtext -->
<SolidColorBrush x:Key="SettingWarningTextForeground" Color="#a05c00"/>
<!-- Operation log output text -->
<SolidColorBrush x:Key="LogOutputVerboseForeground" Color="#5C5C5C"/>
</ResourceDictionary>
</ResourceDictionary.ThemeDictionaries>
</ResourceDictionary>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
using System.Collections.ObjectModel;
using Avalonia;
using Avalonia.Media;
using Avalonia.Styling;
using Avalonia.Threading;
using CommunityToolkit.Mvvm.ComponentModel;
using UniGetUI.Avalonia.ViewModels.Pages.LogPages;
Expand All @@ -12,12 +14,17 @@ public partial class OperationOutputViewModel : ObservableObject
[ObservableProperty] private string _title = "";
public ObservableCollection<LogLineItem> OutputLines { get; } = new();

private static readonly IBrush _errorBrush = new SolidColorBrush(Color.Parse("#FF6B6B"));
private static readonly IBrush _debugBrush = new SolidColorBrush(Color.Parse("#888888"));
private static readonly IBrush _normalBrush = Brushes.White;
private readonly IBrush _errorBrush;
private readonly IBrush _debugBrush;
private readonly IBrush _normalBrush;

public OperationOutputViewModel(AbstractOperation operation)
{
var theme = Application.Current?.ActualThemeVariant ?? ThemeVariant.Default;
_errorBrush = LookupBrush("StatusErrorForeground", theme, new SolidColorBrush(Color.Parse("#c62828")));
_debugBrush = LookupBrush("LogOutputVerboseForeground", theme, new SolidColorBrush(Color.Parse("#767676")));
_normalBrush = LookupBrush("SystemControlForegroundBaseHighBrush", theme, Brushes.White);

Title = operation.Metadata.Title;

foreach (var (text, type) in operation.GetOutput())
Expand All @@ -27,6 +34,13 @@ public OperationOutputViewModel(AbstractOperation operation)
Dispatcher.UIThread.Post(() => OutputLines.Add(MakeLine(ev.Item1, ev.Item2)));
}

private static IBrush LookupBrush(string key, ThemeVariant theme, IBrush fallback)
{
if (Application.Current?.TryGetResource(key, theme, out var resource) == true && resource is IBrush brush)
return brush;
return fallback;
}

private LogLineItem MakeLine(string text, AbstractOperation.LineType type)
{
IBrush brush = type switch
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,6 @@ private static MenuItem Item(string translationKey, string svgName, bool enabled
Path = $"avares://UniGetUI.Avalonia/Assets/Symbols/{svgName}",
Width = 16,
Height = 16,
Foreground = Brushes.White,
},
};

Expand Down
19 changes: 19 additions & 0 deletions src/UniGetUI.Avalonia/Views/Controls/InfoBar.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,25 @@
xmlns:controls="using:UniGetUI.Avalonia.Views.Controls"
x:DataType="vm:InfoBarViewModel">

<UserControl.Styles>
<Style Selector="Border.severity-success">
<Setter Property="Background" Value="{DynamicResource StatusSuccessBackground}"/>
<Setter Property="BorderBrush" Value="{DynamicResource StatusSuccessBorderBrush}"/>
</Style>
<Style Selector="Border.severity-error">
<Setter Property="Background" Value="{DynamicResource StatusErrorBackground}"/>
<Setter Property="BorderBrush" Value="{DynamicResource StatusErrorBorderBrush}"/>
</Style>
<Style Selector="Border.severity-warning">
<Setter Property="Background" Value="{DynamicResource WarningBannerBackground}"/>
<Setter Property="BorderBrush" Value="{DynamicResource WarningBannerBorderBrush}"/>
</Style>
<Style Selector="Border.severity-info">
<Setter Property="Background" Value="{DynamicResource StatusInfoBackground}"/>
<Setter Property="BorderBrush" Value="{DynamicResource StatusInfoBorderBrush}"/>
</Style>
</UserControl.Styles>

<Border x:Name="BodyBorder"
IsVisible="{Binding IsOpen}"
BorderThickness="0,1,0,1"
Expand Down
44 changes: 11 additions & 33 deletions src/UniGetUI.Avalonia/Views/Controls/InfoBar.axaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,14 @@ private void OnViewModelPropertyChanged(object? sender, System.ComponentModel.Pr

private void ApplySeverity(InfoBarSeverity severity)
{
// Update strip colour
// Background + border: swap a single CSS class — DynamicResource in the style
// handles theme changes automatically without any event subscription.
BodyBorder.Classes.Set("severity-success", severity == InfoBarSeverity.Success);
BodyBorder.Classes.Set("severity-error", severity == InfoBarSeverity.Error);
BodyBorder.Classes.Set("severity-warning", severity == InfoBarSeverity.Warning);
BodyBorder.Classes.Set("severity-info", severity == InfoBarSeverity.Informational);

// Strip colour (solid, not theme-sensitive)
var stripColor = severity switch
{
InfoBarSeverity.Warning => Color.Parse("#F7A800"),
Expand All @@ -53,29 +60,7 @@ private void ApplySeverity(InfoBarSeverity severity)
};
SeverityStrip.Background = new SolidColorBrush(stripColor);

// Update body background/border from theme resources
string bgKey = severity switch
{
InfoBarSeverity.Warning => "WarningBannerBackground",
InfoBarSeverity.Error => "StatusErrorBackground",
InfoBarSeverity.Success => "StatusSuccessBackground",
_ => "StatusInfoBackground",
};
string borderKey = severity switch
{
InfoBarSeverity.Warning => "WarningBannerBorderBrush",
InfoBarSeverity.Error => "StatusErrorBorderBrush",
InfoBarSeverity.Success => "StatusSuccessBorderBrush",
_ => "StatusInfoBorderBrush",
};

var theme = Application.Current?.ActualThemeVariant;
if (Application.Current?.TryGetResource(bgKey, theme, out var bg) == true && bg is IBrush bgBrush)
BodyBorder.Background = bgBrush;
if (Application.Current?.TryGetResource(borderKey, theme, out var border) == true && border is IBrush borderBrush)
BodyBorder.BorderBrush = borderBrush;

// Update icon
// Icon shape
SeverityIcon.Data = Geometry.Parse(severity switch
{
InfoBarSeverity.Warning => WarningPath,
Expand All @@ -84,14 +69,7 @@ private void ApplySeverity(InfoBarSeverity severity)
_ => InfoPath,
});

// Icon foreground
var iconColor = severity switch
{
InfoBarSeverity.Warning => Color.Parse("#F7A800"),
InfoBarSeverity.Error => Color.Parse("#C42B1C"),
InfoBarSeverity.Success => Color.Parse("#107C10"),
_ => Color.Parse("#0078D4"),
};
SeverityIcon.Foreground = new SolidColorBrush(iconColor);
// Icon foreground (solid, not theme-sensitive)
SeverityIcon.Foreground = new SolidColorBrush(stripColor);
}
}
37 changes: 35 additions & 2 deletions src/UniGetUI.Avalonia/Views/Controls/SvgIcon.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@
using Avalonia;
using Avalonia.Automation;
using Avalonia.Controls;
using Avalonia.Data;
using Avalonia.Media;
using Avalonia.Platform;
using Avalonia.Styling;

namespace UniGetUI.Avalonia.Views.Controls;

Expand Down Expand Up @@ -35,6 +37,7 @@ public string? Path
set => SetValue(PathProperty, value);
}

private IBrush? _localForeground;
public IBrush? Foreground
{
get => GetValue(ForegroundProperty);
Expand All @@ -50,13 +53,35 @@ static SvgIcon()
AffectsMeasure<SvgIcon>(PathProperty);
}

protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
{
base.OnAttachedToVisualTree(e);
if (Application.Current is { } app)
app.ActualThemeVariantChanged += OnThemeChanged;
}

protected override void OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs e)
{
base.OnDetachedFromVisualTree(e);
if (Application.Current is { } app)
app.ActualThemeVariantChanged -= OnThemeChanged;
}

protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
{
base.OnPropertyChanged(change);
if (change.Property == PathProperty)
if (change.Property == ForegroundProperty)
{
_localForeground = change.Priority < BindingPriority.Style
? change.NewValue as IBrush
: null;
}
else if (change.Property == PathProperty)
LoadSvg(change.NewValue as string);
}

private void OnThemeChanged(object? sender, EventArgs e) => InvalidateVisual();

private void LoadSvg(string? uri)
{
_geometries.Clear();
Expand Down Expand Up @@ -134,6 +159,14 @@ private void LoadSvg(string? uri)
InvalidateVisual();
}

private static readonly IBrush _darkFg = new SolidColorBrush(Color.Parse("#E8E8E8"));
private static readonly IBrush _lightFg = new SolidColorBrush(Color.Parse("#1E1E1E"));

private static IBrush LookupThemeForeground() =>
Application.Current?.ActualThemeVariant == ThemeVariant.Dark
? _darkFg
: _lightFg;

protected override Size MeasureOverride(Size availableSize)
{
double w = double.IsInfinity(availableSize.Width) ? _viewBoxWidth : availableSize.Width;
Expand All @@ -145,7 +178,7 @@ public override void Render(DrawingContext context)
{
if (_geometries.Count == 0) return;

IBrush brush = Foreground ?? Brushes.Black;
IBrush brush = _localForeground ?? LookupThemeForeground();

double scaleX = Bounds.Width / _viewBoxWidth;
double scaleY = Bounds.Height / _viewBoxHeight;
Expand Down
2 changes: 1 addition & 1 deletion src/UniGetUI.Avalonia/Views/MainWindow.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@
<StackPanel Orientation="Horizontal" Spacing="4">
<controls:SvgIcon Path="{Binding IconPath}"
Width="12" Height="12"
Foreground="White"/>
Foreground="{DynamicResource AppIconForeground}"/>
<TextBlock Text="{Binding Label}"
FontSize="10"
Opacity="0.8"/>
Expand Down
Loading