mirror of
https://github.com/wwiinnddyy/LanMountainDesktop.git
synced 2026-06-22 17:24:27 +08:00
Compare commits
1 Commits
edf3d82cc9
...
v0.8.7.2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7a70476ce8 |
@@ -38,15 +38,6 @@ public static class AppearanceCornerRadiusTokenFactory
|
|||||||
Xl: new CornerRadius(40),
|
Xl: new CornerRadius(40),
|
||||||
Island: new CornerRadius(44),
|
Island: new CornerRadius(44),
|
||||||
Component: new CornerRadius(32)),
|
Component: new CornerRadius(32)),
|
||||||
GlobalAppearanceSettings.CornerRadiusStyleFluent => new AppearanceCornerRadiusTokens(
|
|
||||||
Micro: new CornerRadius(2),
|
|
||||||
Xs: new CornerRadius(4),
|
|
||||||
Sm: new CornerRadius(4),
|
|
||||||
Md: new CornerRadius(8),
|
|
||||||
Lg: new CornerRadius(8),
|
|
||||||
Xl: new CornerRadius(12),
|
|
||||||
Island: new CornerRadius(16),
|
|
||||||
Component: new CornerRadius(8)),
|
|
||||||
// Balanced (default)
|
// Balanced (default)
|
||||||
_ => new AppearanceCornerRadiusTokens(
|
_ => new AppearanceCornerRadiusTokens(
|
||||||
Micro: new CornerRadius(6),
|
Micro: new CornerRadius(6),
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ public static class GlobalAppearanceSettings
|
|||||||
public const string CornerRadiusStyleBalanced = "Balanced";
|
public const string CornerRadiusStyleBalanced = "Balanced";
|
||||||
public const string CornerRadiusStyleRounded = "Rounded";
|
public const string CornerRadiusStyleRounded = "Rounded";
|
||||||
public const string CornerRadiusStyleOpen = "Open";
|
public const string CornerRadiusStyleOpen = "Open";
|
||||||
public const string CornerRadiusStyleFluent = "Fluent";
|
|
||||||
public const string DefaultCornerRadiusStyle = CornerRadiusStyleBalanced;
|
public const string DefaultCornerRadiusStyle = CornerRadiusStyleBalanced;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -44,11 +43,6 @@ public static class GlobalAppearanceSettings
|
|||||||
return CornerRadiusStyleOpen;
|
return CornerRadiusStyleOpen;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (string.Equals(trimmed, CornerRadiusStyleFluent, StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
return CornerRadiusStyleFluent;
|
|
||||||
}
|
|
||||||
|
|
||||||
return DefaultCornerRadiusStyle;
|
return DefaultCornerRadiusStyle;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -57,8 +51,7 @@ public static class GlobalAppearanceSettings
|
|||||||
CornerRadiusStyleSharp,
|
CornerRadiusStyleSharp,
|
||||||
CornerRadiusStyleBalanced,
|
CornerRadiusStyleBalanced,
|
||||||
CornerRadiusStyleRounded,
|
CornerRadiusStyleRounded,
|
||||||
CornerRadiusStyleOpen,
|
CornerRadiusStyleOpen
|
||||||
CornerRadiusStyleFluent
|
|
||||||
];
|
];
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ public sealed class CornerRadiusStyleTests
|
|||||||
[InlineData("Balanced", "Balanced")]
|
[InlineData("Balanced", "Balanced")]
|
||||||
[InlineData("Rounded", "Rounded")]
|
[InlineData("Rounded", "Rounded")]
|
||||||
[InlineData("Open", "Open")]
|
[InlineData("Open", "Open")]
|
||||||
[InlineData("Fluent", "Fluent")]
|
|
||||||
[InlineData("Unknown", "Balanced")]
|
[InlineData("Unknown", "Balanced")]
|
||||||
[InlineData(null, "Balanced")]
|
[InlineData(null, "Balanced")]
|
||||||
public void NormalizeCornerRadiusStyle_ReturnsValidStyleOrDefault(string? input, string expected)
|
public void NormalizeCornerRadiusStyle_ReturnsValidStyleOrDefault(string? input, string expected)
|
||||||
@@ -21,23 +20,6 @@ public sealed class CornerRadiusStyleTests
|
|||||||
Assert.Equal(expected, GlobalAppearanceSettings.NormalizeCornerRadiusStyle(input));
|
Assert.Equal(expected, GlobalAppearanceSettings.NormalizeCornerRadiusStyle(input));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public void FluentStyle_ReturnsFluentDesignSystemValues()
|
|
||||||
{
|
|
||||||
var tokens = LanMountainDesktop.Appearance.AppearanceCornerRadiusTokenFactory.Create(
|
|
||||||
GlobalAppearanceSettings.CornerRadiusStyleFluent);
|
|
||||||
|
|
||||||
// Microsoft Fluent Design System: ControlCornerRadius = 4px, OverlayCornerRadius = 8px
|
|
||||||
Assert.Equal(new CornerRadius(2), tokens.Micro);
|
|
||||||
Assert.Equal(new CornerRadius(4), tokens.Xs);
|
|
||||||
Assert.Equal(new CornerRadius(4), tokens.Sm);
|
|
||||||
Assert.Equal(new CornerRadius(8), tokens.Md);
|
|
||||||
Assert.Equal(new CornerRadius(8), tokens.Lg);
|
|
||||||
Assert.Equal(new CornerRadius(12), tokens.Xl);
|
|
||||||
Assert.Equal(new CornerRadius(16), tokens.Island);
|
|
||||||
Assert.Equal(new CornerRadius(8), tokens.Component);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void PluginAppearanceContext_ResolveCornerRadius_ReturnsFixedTokenValues()
|
public void PluginAppearanceContext_ResolveCornerRadius_ReturnsFixedTokenValues()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
using LanMountainDesktop.Models;
|
using LanMountainDesktop.Models;
|
||||||
@@ -82,9 +82,7 @@ public sealed class AppSettingsService
|
|||||||
}
|
}
|
||||||
|
|
||||||
var json = JsonSerializer.Serialize(snapshotToPersist, SerializerOptions);
|
var json = JsonSerializer.Serialize(snapshotToPersist, SerializerOptions);
|
||||||
var tempPath = $"{_settingsPath}.{Guid.NewGuid():N}.tmp";
|
File.WriteAllText(_settingsPath, json);
|
||||||
File.WriteAllText(tempPath, json);
|
|
||||||
File.Move(tempPath, _settingsPath, overwrite: true);
|
|
||||||
|
|
||||||
var writeTimeUtc = File.Exists(_settingsPath)
|
var writeTimeUtc = File.Exists(_settingsPath)
|
||||||
? File.GetLastWriteTimeUtc(_settingsPath)
|
? File.GetLastWriteTimeUtc(_settingsPath)
|
||||||
|
|||||||
@@ -57,9 +57,7 @@ public sealed class ClockAirAppSettingsStore
|
|||||||
Directory.CreateDirectory(directory);
|
Directory.CreateDirectory(directory);
|
||||||
}
|
}
|
||||||
|
|
||||||
var tempPath = $"{_settingsPath}.{Guid.NewGuid():N}.tmp";
|
File.WriteAllText(_settingsPath, JsonSerializer.Serialize(normalized, SerializerOptions));
|
||||||
File.WriteAllText(tempPath, JsonSerializer.Serialize(normalized, SerializerOptions));
|
|
||||||
File.Move(tempPath, _settingsPath, overwrite: true);
|
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -100,9 +100,8 @@ internal sealed class FusedDesktopLayoutService : IFusedDesktopLayoutService
|
|||||||
Directory.CreateDirectory(directory);
|
Directory.CreateDirectory(directory);
|
||||||
}
|
}
|
||||||
|
|
||||||
var tempPath = $"{ConfigFilePath}.{Guid.NewGuid():N}.tmp";
|
var json = JsonSerializer.Serialize(snapshot, JsonOptions);
|
||||||
File.WriteAllText(tempPath, JsonSerializer.Serialize(snapshot, JsonOptions));
|
File.WriteAllText(ConfigFilePath, json);
|
||||||
File.Move(tempPath, ConfigFilePath, overwrite: true);
|
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -197,9 +197,7 @@ public sealed class LauncherSettingsService
|
|||||||
}
|
}
|
||||||
|
|
||||||
var json = JsonSerializer.Serialize(snapshot, SerializerOptions);
|
var json = JsonSerializer.Serialize(snapshot, SerializerOptions);
|
||||||
var tempPath = $"{_settingsPath}.{Guid.NewGuid():N}.tmp";
|
File.WriteAllText(_settingsPath, json);
|
||||||
File.WriteAllText(tempPath, json);
|
|
||||||
File.Move(tempPath, _settingsPath, overwrite: true);
|
|
||||||
|
|
||||||
return File.Exists(_settingsPath)
|
return File.Exists(_settingsPath)
|
||||||
? File.GetLastWriteTimeUtc(_settingsPath)
|
? File.GetLastWriteTimeUtc(_settingsPath)
|
||||||
|
|||||||
@@ -358,9 +358,7 @@ internal sealed class SettingsService : ISettingsService
|
|||||||
Directory.CreateDirectory(directory);
|
Directory.CreateDirectory(directory);
|
||||||
}
|
}
|
||||||
|
|
||||||
var tempPath = $"{_pluginSettingsPath}.{Guid.NewGuid():N}.tmp";
|
File.WriteAllText(_pluginSettingsPath, JsonSerializer.Serialize(document, SerializerOptions));
|
||||||
File.WriteAllText(tempPath, JsonSerializer.Serialize(document, SerializerOptions));
|
|
||||||
File.Move(tempPath, _pluginSettingsPath, overwrite: true);
|
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -440,9 +440,7 @@ public sealed class ZhiJiaoHubCacheService : IDisposable
|
|||||||
}
|
}
|
||||||
|
|
||||||
Directory.CreateDirectory(Path.GetDirectoryName(_manifestPath)!);
|
Directory.CreateDirectory(Path.GetDirectoryName(_manifestPath)!);
|
||||||
var tempPath = $"{_manifestPath}.{Guid.NewGuid():N}.tmp";
|
File.WriteAllText(_manifestPath, JsonSerializer.Serialize(manifest, JsonOptions));
|
||||||
File.WriteAllText(tempPath, JsonSerializer.Serialize(manifest, JsonOptions));
|
|
||||||
File.Move(tempPath, _manifestPath, overwrite: true);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -471,9 +469,7 @@ public sealed class ZhiJiaoHubCacheService : IDisposable
|
|||||||
manifest.Entries[source] = new CacheEntry(images, DateTimeOffset.UtcNow);
|
manifest.Entries[source] = new CacheEntry(images, DateTimeOffset.UtcNow);
|
||||||
|
|
||||||
Directory.CreateDirectory(Path.GetDirectoryName(_manifestPath)!);
|
Directory.CreateDirectory(Path.GetDirectoryName(_manifestPath)!);
|
||||||
var tempPath = $"{_manifestPath}.{Guid.NewGuid():N}.tmp";
|
File.WriteAllText(_manifestPath, JsonSerializer.Serialize(manifest, JsonOptions));
|
||||||
File.WriteAllText(tempPath, JsonSerializer.Serialize(manifest, JsonOptions));
|
|
||||||
File.Move(tempPath, _manifestPath, overwrite: true);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
<TextBlock x:Name="ConditionTextBlock" Text="Loading" FontSize="16" FontWeight="SemiBold" TextTrimming="CharacterEllipsis" />
|
<TextBlock x:Name="ConditionTextBlock" Text="Loading" FontSize="16" FontWeight="SemiBold" TextTrimming="CharacterEllipsis" />
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
<components:WeatherIconView x:Name="MainIcon" Grid.Column="1" Width="56" Height="56" Margin="0,0,10,0" />
|
<components:WeatherIconView x:Name="MainIcon" Grid.Column="1" Width="56" Height="56" Margin="0,0,10,0" />
|
||||||
<TextBlock x:Name="TemperatureTextBlock" Grid.Column="2" Text="--°" FontSize="56" FontWeight="Bold" VerticalAlignment="Center" ClipToBounds="False" Padding="0,2,0,0" />
|
<TextBlock x:Name="TemperatureTextBlock" Grid.Column="2" Text="--°" FontSize="56" FontWeight="Bold" VerticalAlignment="Center" />
|
||||||
</Grid>
|
</Grid>
|
||||||
<UniformGrid x:Name="MetricGrid" Grid.Row="1" Rows="1" Columns="3" />
|
<UniformGrid x:Name="MetricGrid" Grid.Row="1" Rows="1" Columns="3" />
|
||||||
<Border Grid.Row="2" Background="{DynamicResource SurfaceColor}" CornerRadius="{DynamicResource DesignCornerRadiusMd}" Padding="10,8">
|
<Border Grid.Row="2" Background="{DynamicResource SurfaceColor}" CornerRadius="{DynamicResource DesignCornerRadiusMd}" Padding="10,8">
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ public partial class ExtendedWeatherWidget : WeatherWidgetBase
|
|||||||
var inner = (StackPanel)panel.Child!;
|
var inner = (StackPanel)panel.Child!;
|
||||||
inner.Children.Add(new TextBlock { Text = FormatTime(item.Time), Foreground = Brush(CurrentPalette.TextSecondary), FontSize = 10, TextAlignment = Avalonia.Media.TextAlignment.Center, HorizontalAlignment = Avalonia.Layout.HorizontalAlignment.Center });
|
inner.Children.Add(new TextBlock { Text = FormatTime(item.Time), Foreground = Brush(CurrentPalette.TextSecondary), FontSize = 10, TextAlignment = Avalonia.Media.TextAlignment.Center, HorizontalAlignment = Avalonia.Layout.HorizontalAlignment.Center });
|
||||||
inner.Children.Add(new WeatherIconView { Width = 26, Height = 26, Source = WeatherIconAssetResolver.LoadIcon(CurrentVisualStyleId, item.WeatherCode, item.WeatherText) });
|
inner.Children.Add(new WeatherIconView { Width = 26, Height = 26, Source = WeatherIconAssetResolver.LoadIcon(CurrentVisualStyleId, item.WeatherCode, item.WeatherText) });
|
||||||
inner.Children.Add(new TextBlock { Text = FormatTemperature(item.TemperatureC), Foreground = Brush(CurrentPalette.TextPrimary), FontWeight = Avalonia.Media.FontWeight.SemiBold, TextAlignment = Avalonia.Media.TextAlignment.Center, HorizontalAlignment = Avalonia.Layout.HorizontalAlignment.Center, FontSize = 12, ClipToBounds = false });
|
inner.Children.Add(new TextBlock { Text = FormatTemperature(item.TemperatureC), Foreground = Brush(CurrentPalette.TextPrimary), FontWeight = Avalonia.Media.FontWeight.SemiBold, TextAlignment = Avalonia.Media.TextAlignment.Center, HorizontalAlignment = Avalonia.Layout.HorizontalAlignment.Center, FontSize = 12 });
|
||||||
HourlyGrid.Children.Add(panel);
|
HourlyGrid.Children.Add(panel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -111,7 +111,7 @@ public partial class ExtendedWeatherWidget : WeatherWidgetBase
|
|||||||
var inner = (StackPanel)panel.Child!;
|
var inner = (StackPanel)panel.Child!;
|
||||||
inner.Children.Add(new TextBlock { Text = ResolveDayLabel(item.Date), Foreground = Brush(CurrentPalette.TextSecondary), FontSize = 10, TextAlignment = Avalonia.Media.TextAlignment.Center, HorizontalAlignment = Avalonia.Layout.HorizontalAlignment.Center });
|
inner.Children.Add(new TextBlock { Text = ResolveDayLabel(item.Date), Foreground = Brush(CurrentPalette.TextSecondary), FontSize = 10, TextAlignment = Avalonia.Media.TextAlignment.Center, HorizontalAlignment = Avalonia.Layout.HorizontalAlignment.Center });
|
||||||
inner.Children.Add(new WeatherIconView { Width = 26, Height = 26, Source = WeatherIconAssetResolver.LoadIcon(CurrentVisualStyleId, item.DayWeatherCode, item.DayWeatherText) });
|
inner.Children.Add(new WeatherIconView { Width = 26, Height = 26, Source = WeatherIconAssetResolver.LoadIcon(CurrentVisualStyleId, item.DayWeatherCode, item.DayWeatherText) });
|
||||||
inner.Children.Add(new TextBlock { Text = $"{FormatTemperature(item.HighTemperatureC)} / {FormatTemperature(item.LowTemperatureC)}", Foreground = Brush(CurrentPalette.TextPrimary), FontWeight = Avalonia.Media.FontWeight.SemiBold, TextAlignment = Avalonia.Media.TextAlignment.Center, HorizontalAlignment = Avalonia.Layout.HorizontalAlignment.Center, FontSize = 11, ClipToBounds = false });
|
inner.Children.Add(new TextBlock { Text = $"{FormatTemperature(item.HighTemperatureC)} / {FormatTemperature(item.LowTemperatureC)}", Foreground = Brush(CurrentPalette.TextPrimary), FontWeight = Avalonia.Media.FontWeight.SemiBold, TextAlignment = Avalonia.Media.TextAlignment.Center, HorizontalAlignment = Avalonia.Layout.HorizontalAlignment.Center, FontSize = 11 });
|
||||||
DailyGrid.Children.Add(panel);
|
DailyGrid.Children.Add(panel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
<Border x:Name="OverlayBorder" />
|
<Border x:Name="OverlayBorder" />
|
||||||
<Grid x:Name="ContentGrid" RowDefinitions="Auto,*" Margin="18,14" RowSpacing="12">
|
<Grid x:Name="ContentGrid" RowDefinitions="Auto,*" Margin="18,14" RowSpacing="12">
|
||||||
<Grid ColumnDefinitions="Auto,*,Auto,Auto" VerticalAlignment="Center">
|
<Grid ColumnDefinitions="Auto,*,Auto,Auto" VerticalAlignment="Center">
|
||||||
<TextBlock x:Name="TemperatureTextBlock" Text="--°" FontSize="42" FontWeight="Bold" VerticalAlignment="Center" ClipToBounds="False" Padding="0,1,0,0" />
|
<TextBlock x:Name="TemperatureTextBlock" Text="--°" FontSize="42" FontWeight="Bold" VerticalAlignment="Center" />
|
||||||
<StackPanel Grid.Column="1" Margin="12,0,0,0" VerticalAlignment="Center">
|
<StackPanel Grid.Column="1" Margin="12,0,0,0" VerticalAlignment="Center">
|
||||||
<TextBlock x:Name="ConditionTextBlock" Text="Loading" FontSize="15" FontWeight="SemiBold" TextTrimming="CharacterEllipsis" />
|
<TextBlock x:Name="ConditionTextBlock" Text="Loading" FontSize="15" FontWeight="SemiBold" TextTrimming="CharacterEllipsis" />
|
||||||
<TextBlock x:Name="LocationTextBlock" Text="Weather" FontSize="12" FontWeight="Medium" Opacity="0.72" TextTrimming="CharacterEllipsis" />
|
<TextBlock x:Name="LocationTextBlock" Text="Weather" FontSize="12" FontWeight="Medium" Opacity="0.72" TextTrimming="CharacterEllipsis" />
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ public partial class HourlyWeatherWidget : WeatherWidgetBase
|
|||||||
var inner = (StackPanel)panel.Child!;
|
var inner = (StackPanel)panel.Child!;
|
||||||
inner.Children.Add(new TextBlock { Text = item.Label, FontSize = 10, Foreground = Brush(CurrentPalette.TextSecondary), HorizontalAlignment = Avalonia.Layout.HorizontalAlignment.Center, TextAlignment = Avalonia.Media.TextAlignment.Center });
|
inner.Children.Add(new TextBlock { Text = item.Label, FontSize = 10, Foreground = Brush(CurrentPalette.TextSecondary), HorizontalAlignment = Avalonia.Layout.HorizontalAlignment.Center, TextAlignment = Avalonia.Media.TextAlignment.Center });
|
||||||
inner.Children.Add(new WeatherIconView { Width = 24, Height = 24, Source = WeatherIconAssetResolver.LoadIcon(CurrentVisualStyleId, item.WeatherCode, item.WeatherText) });
|
inner.Children.Add(new WeatherIconView { Width = 24, Height = 24, Source = WeatherIconAssetResolver.LoadIcon(CurrentVisualStyleId, item.WeatherCode, item.WeatherText) });
|
||||||
inner.Children.Add(new TextBlock { Text = item.Value, FontWeight = Avalonia.Media.FontWeight.SemiBold, Foreground = Brush(CurrentPalette.TextPrimary), HorizontalAlignment = Avalonia.Layout.HorizontalAlignment.Center, FontSize = 11, TextAlignment = Avalonia.Media.TextAlignment.Center, ClipToBounds = false });
|
inner.Children.Add(new TextBlock { Text = item.Value, FontWeight = Avalonia.Media.FontWeight.SemiBold, Foreground = Brush(CurrentPalette.TextPrimary), HorizontalAlignment = Avalonia.Layout.HorizontalAlignment.Center, FontSize = 11, TextAlignment = Avalonia.Media.TextAlignment.Center });
|
||||||
return panel;
|
return panel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
<Grid x:Name="ContentGrid" ColumnDefinitions="1.2*,1.6*" Margin="18,14" ColumnSpacing="14">
|
<Grid x:Name="ContentGrid" ColumnDefinitions="1.2*,1.6*" Margin="18,14" ColumnSpacing="14">
|
||||||
<StackPanel VerticalAlignment="Center" Spacing="6">
|
<StackPanel VerticalAlignment="Center" Spacing="6">
|
||||||
<components:WeatherIconView x:Name="MainIcon" Width="64" Height="64" HorizontalAlignment="Left" />
|
<components:WeatherIconView x:Name="MainIcon" Width="64" Height="64" HorizontalAlignment="Left" />
|
||||||
<TextBlock x:Name="TemperatureTextBlock" Text="--°" FontSize="42" FontWeight="Bold" ClipToBounds="False" Padding="0,1,0,0" />
|
<TextBlock x:Name="TemperatureTextBlock" Text="--°" FontSize="42" FontWeight="Bold" />
|
||||||
<TextBlock x:Name="ConditionTextBlock" Text="Loading" FontSize="15" FontWeight="SemiBold" TextTrimming="CharacterEllipsis" />
|
<TextBlock x:Name="ConditionTextBlock" Text="Loading" FontSize="15" FontWeight="SemiBold" TextTrimming="CharacterEllipsis" />
|
||||||
<TextBlock x:Name="LocationTextBlock" Text="Weather" FontSize="12" FontWeight="Medium" Opacity="0.72" TextTrimming="CharacterEllipsis" />
|
<TextBlock x:Name="LocationTextBlock" Text="Weather" FontSize="12" FontWeight="Medium" Opacity="0.72" TextTrimming="CharacterEllipsis" />
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
|||||||
@@ -66,9 +66,9 @@ public partial class MultiDayWeatherWidget : WeatherWidgetBase
|
|||||||
row.Children.Add(new WeatherIconView { Width = 24, Height = 24, Source = WeatherIconAssetResolver.LoadIcon(CurrentVisualStyleId, item.DayWeatherCode, item.DayWeatherText), VerticalAlignment = Avalonia.Layout.VerticalAlignment.Center });
|
row.Children.Add(new WeatherIconView { Width = 24, Height = 24, Source = WeatherIconAssetResolver.LoadIcon(CurrentVisualStyleId, item.DayWeatherCode, item.DayWeatherText), VerticalAlignment = Avalonia.Layout.VerticalAlignment.Center });
|
||||||
row.Children.Add(new TextBlock { Text = ResolveDayLabel(item.Date), Foreground = Brush(CurrentPalette.TextPrimary), FontWeight = Avalonia.Media.FontWeight.SemiBold, TextTrimming = Avalonia.Media.TextTrimming.CharacterEllipsis, VerticalAlignment = Avalonia.Layout.VerticalAlignment.Center, FontSize = 12 });
|
row.Children.Add(new TextBlock { Text = ResolveDayLabel(item.Date), Foreground = Brush(CurrentPalette.TextPrimary), FontWeight = Avalonia.Media.FontWeight.SemiBold, TextTrimming = Avalonia.Media.TextTrimming.CharacterEllipsis, VerticalAlignment = Avalonia.Layout.VerticalAlignment.Center, FontSize = 12 });
|
||||||
Grid.SetColumn(row.Children[^1], 1);
|
Grid.SetColumn(row.Children[^1], 1);
|
||||||
row.Children.Add(new TextBlock { Text = FormatTemperature(item.HighTemperatureC), Foreground = Brush(CurrentPalette.TextPrimary), FontWeight = Avalonia.Media.FontWeight.SemiBold, VerticalAlignment = Avalonia.Layout.VerticalAlignment.Center, FontSize = 12, ClipToBounds = false });
|
row.Children.Add(new TextBlock { Text = FormatTemperature(item.HighTemperatureC), Foreground = Brush(CurrentPalette.TextPrimary), FontWeight = Avalonia.Media.FontWeight.SemiBold, VerticalAlignment = Avalonia.Layout.VerticalAlignment.Center, FontSize = 12 });
|
||||||
Grid.SetColumn(row.Children[^1], 2);
|
Grid.SetColumn(row.Children[^1], 2);
|
||||||
row.Children.Add(new TextBlock { Text = FormatTemperature(item.LowTemperatureC), Foreground = Brush(CurrentPalette.TextSecondary), FontWeight = Avalonia.Media.FontWeight.Medium, VerticalAlignment = Avalonia.Layout.VerticalAlignment.Center, FontSize = 12, ClipToBounds = false });
|
row.Children.Add(new TextBlock { Text = FormatTemperature(item.LowTemperatureC), Foreground = Brush(CurrentPalette.TextSecondary), FontWeight = Avalonia.Media.FontWeight.Medium, VerticalAlignment = Avalonia.Layout.VerticalAlignment.Center, FontSize = 12 });
|
||||||
Grid.SetColumn(row.Children[^1], 3);
|
Grid.SetColumn(row.Children[^1], 3);
|
||||||
|
|
||||||
rowPanel.Children.Add(row);
|
rowPanel.Children.Add(row);
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
</StackPanel>
|
</StackPanel>
|
||||||
<StackPanel Grid.Column="1" VerticalAlignment="Center" HorizontalAlignment="Right" Spacing="1">
|
<StackPanel Grid.Column="1" VerticalAlignment="Center" HorizontalAlignment="Right" Spacing="1">
|
||||||
<components:WeatherIconView x:Name="MainIcon" Width="44" Height="44" HorizontalAlignment="Right" />
|
<components:WeatherIconView x:Name="MainIcon" Width="44" Height="44" HorizontalAlignment="Right" />
|
||||||
<TextBlock x:Name="TemperatureTextBlock" Text="--°" FontSize="20" FontWeight="SemiBold" HorizontalAlignment="Right" ClipToBounds="False" />
|
<TextBlock x:Name="TemperatureTextBlock" Text="--°" FontSize="20" FontWeight="SemiBold" HorizontalAlignment="Right" />
|
||||||
<TextBlock x:Name="ConditionTextBlock" Text="Loading" FontSize="11" FontWeight="Medium" HorizontalAlignment="Right" TextTrimming="CharacterEllipsis" MaxWidth="100" Opacity="0.82" />
|
<TextBlock x:Name="ConditionTextBlock" Text="Loading" FontSize="11" FontWeight="Medium" HorizontalAlignment="Right" TextTrimming="CharacterEllipsis" MaxWidth="100" Opacity="0.82" />
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
<Grid x:Name="ContentGrid" RowDefinitions="*,Auto" Margin="20,16,20,14">
|
<Grid x:Name="ContentGrid" RowDefinitions="*,Auto" Margin="20,16,20,14">
|
||||||
<Grid ColumnDefinitions="*,Auto">
|
<Grid ColumnDefinitions="*,Auto">
|
||||||
<StackPanel VerticalAlignment="Center" Spacing="4">
|
<StackPanel VerticalAlignment="Center" Spacing="4">
|
||||||
<TextBlock x:Name="TemperatureTextBlock" Text="--°" FontSize="72" FontWeight="Bold" ClipToBounds="False" Padding="0,2,0,0" />
|
<TextBlock x:Name="TemperatureTextBlock" Text="--°" FontSize="72" FontWeight="Bold" />
|
||||||
<TextBlock x:Name="ConditionTextBlock" Text="Loading" FontSize="18" FontWeight="SemiBold" TextTrimming="CharacterEllipsis" />
|
<TextBlock x:Name="ConditionTextBlock" Text="Loading" FontSize="18" FontWeight="SemiBold" TextTrimming="CharacterEllipsis" />
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
<components:WeatherIconView x:Name="MainIcon" Grid.Column="1" Width="72" Height="72" HorizontalAlignment="Right" VerticalAlignment="Center" Margin="0,0,0,4" />
|
<components:WeatherIconView x:Name="MainIcon" Grid.Column="1" Width="72" Height="72" HorizontalAlignment="Right" VerticalAlignment="Center" Margin="0,0,0,4" />
|
||||||
|
|||||||
@@ -10,11 +10,9 @@ using Avalonia.Threading;
|
|||||||
using Avalonia.VisualTree;
|
using Avalonia.VisualTree;
|
||||||
using FluentAvalonia.UI.Controls;
|
using FluentAvalonia.UI.Controls;
|
||||||
using FluentAvalonia.UI.Windowing;
|
using FluentAvalonia.UI.Windowing;
|
||||||
using LanMountainDesktop.Appearance;
|
|
||||||
using LanMountainDesktop.PluginSdk;
|
using LanMountainDesktop.PluginSdk;
|
||||||
using LanMountainDesktop.Services;
|
using LanMountainDesktop.Services;
|
||||||
using LanMountainDesktop.Services.Settings;
|
using LanMountainDesktop.Services.Settings;
|
||||||
using LanMountainDesktop.Settings.Core;
|
|
||||||
using LanMountainDesktop.ViewModels;
|
using LanMountainDesktop.ViewModels;
|
||||||
using Symbol = FluentIcons.Common.Symbol;
|
using Symbol = FluentIcons.Common.Symbol;
|
||||||
|
|
||||||
@@ -71,7 +69,6 @@ public partial class SettingsWindow : FAAppWindow, ISettingsPageHostContext
|
|||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
SetValue(Window.IconProperty, _appLogoService.CreateWindowIcon());
|
SetValue(Window.IconProperty, _appLogoService.CreateWindowIcon());
|
||||||
ApplyChromeMode(useSystemChrome);
|
ApplyChromeMode(useSystemChrome);
|
||||||
ApplyFluentCornerRadius();
|
|
||||||
|
|
||||||
if (RootNavigationView is not null)
|
if (RootNavigationView is not null)
|
||||||
{
|
{
|
||||||
@@ -801,30 +798,6 @@ public partial class SettingsWindow : FAAppWindow, ISettingsPageHostContext
|
|||||||
TelemetryServices.Usage?.TrackSettingsWindowClosed("SettingsWindow.OnClosed", ViewModel.CurrentPageId);
|
TelemetryServices.Usage?.TrackSettingsWindowClosed("SettingsWindow.OnClosed", ViewModel.CurrentPageId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Override global corner radius tokens on the settings window root grid
|
|
||||||
/// so all child controls use Microsoft Fluent Design System values,
|
|
||||||
/// independent of the user's global corner radius preference.
|
|
||||||
/// </summary>
|
|
||||||
private void ApplyFluentCornerRadius()
|
|
||||||
{
|
|
||||||
if (RootGrid is null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var tokens = AppearanceCornerRadiusTokenFactory.Create(
|
|
||||||
GlobalAppearanceSettings.CornerRadiusStyleFluent);
|
|
||||||
RootGrid.Resources["DesignCornerRadiusMicro"] = tokens.Micro;
|
|
||||||
RootGrid.Resources["DesignCornerRadiusXs"] = tokens.Xs;
|
|
||||||
RootGrid.Resources["DesignCornerRadiusSm"] = tokens.Sm;
|
|
||||||
RootGrid.Resources["DesignCornerRadiusMd"] = tokens.Md;
|
|
||||||
RootGrid.Resources["DesignCornerRadiusLg"] = tokens.Lg;
|
|
||||||
RootGrid.Resources["DesignCornerRadiusXl"] = tokens.Xl;
|
|
||||||
RootGrid.Resources["DesignCornerRadiusIsland"] = tokens.Island;
|
|
||||||
RootGrid.Resources["DesignCornerRadiusComponent"] = tokens.Component;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnTitleBarDragZonePointerPressed(object? sender, PointerPressedEventArgs e)
|
private void OnTitleBarDragZonePointerPressed(object? sender, PointerPressedEventArgs e)
|
||||||
{
|
{
|
||||||
_ = sender;
|
_ = sender;
|
||||||
|
|||||||
@@ -4,13 +4,11 @@
|
|||||||
|
|
||||||
为了确保桌面组件在不同尺寸、缩放比例下都能保持视觉一致性和美感,阑山桌面采用了 **固定圆角风格预设 (Fixed Corner Radius Styles)**,全面参考小米澎湃OS (Xiaomi HyperOS) 的设计语言。
|
为了确保桌面组件在不同尺寸、缩放比例下都能保持视觉一致性和美感,阑山桌面采用了 **固定圆角风格预设 (Fixed Corner Radius Styles)**,全面参考小米澎湃OS (Xiaomi HyperOS) 的设计语言。
|
||||||
|
|
||||||
此外,阑山桌面引入了 **Fluent** 预设,遵循 Microsoft Fluent Design System 规范。设置窗口始终使用 Fluent 圆角,独立于用户选择的全局圆角风格。
|
|
||||||
|
|
||||||
所有的组件和容器必须使用统一的资源键,禁止在 XAML 或代码中使用硬编码的像素值。
|
所有的组件和容器必须使用统一的资源键,禁止在 XAML 或代码中使用硬编码的像素值。
|
||||||
|
|
||||||
## 预设风格 (Preset Styles)
|
## 预设风格 (Preset Styles)
|
||||||
|
|
||||||
用户可以在设置中选择以下五种风格之一。系统会自动根据选中的风格动态映射全局圆角 Token。
|
用户可以在设置中选择以下四种风格之一。系统会自动根据选中的风格动态映射全局圆角 Token。
|
||||||
|
|
||||||
| 风格 (ID) | 名称 (Local) | 组件圆角 (Component) | 设计语义 |
|
| 风格 (ID) | 名称 (Local) | 组件圆角 (Component) | 设计语义 |
|
||||||
| :--- | :--- | :--- | :--- |
|
| :--- | :--- | :--- | :--- |
|
||||||
@@ -18,33 +16,21 @@
|
|||||||
| **Balanced** | 平衡 | 24px | **默认值**。和谐、自然、普适 |
|
| **Balanced** | 平衡 | 24px | **默认值**。和谐、自然、普适 |
|
||||||
| **Rounded** | 圆润 | 28px | 保守、柔和、亲切 |
|
| **Rounded** | 圆润 | 28px | 保守、柔和、亲切 |
|
||||||
| **Open** | 开放 | 32px | 现代、沉浸、夸张 |
|
| **Open** | 开放 | 32px | 现代、沉浸、夸张 |
|
||||||
| **Fluent** | Fluent | 8px | Microsoft Fluent Design System。标准、规范、一致 |
|
|
||||||
|
|
||||||
## Token 阶梯映射 (Token Step Mapping)
|
## Token 阶梯映射 (Token Step Mapping)
|
||||||
|
|
||||||
每个风格都定义了一套完整的圆角阶梯,以确保在大容器包裹小元素时满足 **圆角嵌套一致性 (Nesting Consistency)**。
|
每个风格都定义了一套完整的圆角阶梯,以确保在大容器包裹小元素时满足 **圆角嵌套一致性 (Nesting Consistency)**。
|
||||||
|
|
||||||
| Token | Sharp | Balanced | Rounded | Open | Fluent | 典型场景 |
|
| Token | Sharp | Balanced | Rounded | Open | 典型场景 |
|
||||||
| :--- | :--- | :--- | :--- | :--- | :--- | :--- |
|
| :--- | :--- | :--- | :--- | :--- | :--- |
|
||||||
| **Micro** | 4px | 6px | 8px | 10px | 2px | 小图标容器、角标 (Badge) |
|
| **Micro** | 4px | 6px | 8px | 10px | 小图标容器、角标 (Badge) |
|
||||||
| **Xs** | 8px | 12px | 14px | 16px | 4px | 小标签 (Tag)、输入框 |
|
| **Xs** | 8px | 12px | 14px | 16px | 小标签 (Tag)、输入框 |
|
||||||
| **Sm** | 10px | 14px | 16px | 20px | 4px | 普通按钮、搜索栏、复选框 |
|
| **Sm** | 10px | 14px | 16px | 20px | 普通按钮、搜索栏、复选框 |
|
||||||
| **Md** | 14px | 20px | 24px | 28px | 8px | 悬浮菜单、小提示框、子卡片 |
|
| **Md** | 14px | 20px | 24px | 28px | 悬浮菜单、小提示框、子卡片 |
|
||||||
| **Lg** | 20px | 28px | 32px | 36px | 8px | 普通面板、对话框内容区 |
|
| **Lg** | 20px | 28px | 32px | 36px | 普通面板、对话框内容区 |
|
||||||
| **Xl** | 24px | 32px | 36px | 40px | 12px | 大尺寸容器、设置中心页面 |
|
| **Xl** | 24px | 32px | 36px | 40px | 大尺寸容器、设置中心页面 |
|
||||||
| **Island** | 28px | 36px | 40px | 44px | 16px | 任务栏、全局大悬浮容器 |
|
| **Island** | 28px | 36px | 40px | 44px | 任务栏、全局大悬浮容器 |
|
||||||
| **Component** | **20px** | **24px** | **28px** | **32px** | **8px** | **所有桌面组件 (Widget) 的主边框** |
|
| **Component** | **20px** | **24px** | **28px** | **32px** | **所有桌面组件 (Widget) 的主边框** |
|
||||||
|
|
||||||
## Fluent Design System 参考 (Fluent Reference)
|
|
||||||
|
|
||||||
Fluent 预设的核心值来源于 Microsoft 官方规范:
|
|
||||||
|
|
||||||
- **ControlCornerRadius = 4px**:用于标准持久 UI 元素(按钮、复选框、输入框等)
|
|
||||||
- **OverlayCornerRadius = 8px**:用于临时覆盖 UI 元素(对话框、浮出菜单等)
|
|
||||||
|
|
||||||
> [!IMPORTANT]
|
|
||||||
> **设置窗口强制约束**:
|
|
||||||
> 设置窗口 (`SettingsWindow`) 始终使用 Fluent 圆角 Token,不受用户全局圆角设置影响。这确保设置 UI 作为标准 Windows 应用窗口与 Fluent Design 一致。
|
|
||||||
|
|
||||||
## 开发准则 (Implementation Rules)
|
## 开发准则 (Implementation Rules)
|
||||||
|
|
||||||
|
|||||||
@@ -1,269 +0,0 @@
|
|||||||
# Git 提交分析报告
|
|
||||||
|
|
||||||
## 📋 提交基本信息
|
|
||||||
|
|
||||||
| 属性 | 值 |
|
|
||||||
|------|-----|
|
|
||||||
| **完整哈希** | `7a70476ce8093ea6000f25fba7ba404d4f3e8f3c` |
|
|
||||||
| **短哈希** | `7a70476` |
|
|
||||||
| **作者** | lincube <lincube3@hotmail.com> |
|
|
||||||
| **提交日期** | 2026-05-19 |
|
|
||||||
| **提交时间** | 07:55:21 |
|
|
||||||
| **时区** | +0800 |
|
|
||||||
| **提交类型** | 🟡 合并提交 (Merge Commit) |
|
|
||||||
| **关联 PR** | #11 |
|
|
||||||
|
|
||||||
## 📝 提交信息摘要
|
|
||||||
|
|
||||||
```
|
|
||||||
合并对设置系统的更新 (#11)
|
|
||||||
```
|
|
||||||
|
|
||||||
**详细提交说明**:
|
|
||||||
|
|
||||||
本次合并包含了对设置系统的全面更新和改进,主要涉及以下子提交:
|
|
||||||
|
|
||||||
1. **Add Windows system chrome patchers (Harmony)** - 使用 Harmony 修补器添加 Windows 系统 chrome 切换支持
|
|
||||||
2. **Refactor settings window UI and theming** - 重构设置窗口 UI 和主题
|
|
||||||
3. **Add localization and localize settings pages** - 添加本地化和多语言支持
|
|
||||||
4. **Redesign settings window with fluent shell & search** - 使用 Fluent Shell 重新设计设置窗口并添加搜索功能
|
|
||||||
5. **Add OOBE startup presentation and settings merge** - 添加 OOBE 启动演示和设置合并功能
|
|
||||||
6. **Move whiteboard persistence to file storage** - 将白板持久化迁移到文件存储
|
|
||||||
7. **Introduce render gate and chart caching** - 引入渲染门控和图表缓存机制
|
|
||||||
8. **Use MaterialColorSnapshot in appearance flow** - 在外观流程中使用 MaterialColorSnapshot
|
|
||||||
9. **Add material color services, plugin DTOs, and tests** - 添加材质颜色服务、插件 DTO 和测试
|
|
||||||
10. **Add CODE_WIKI and update localization** - 添加 CODE_WIKI 文档和更新本地化
|
|
||||||
11. **Add Data settings page and storage scanner** - 添加数据设置页面和存储扫描器
|
|
||||||
12. **Add IPC backoff/retries and safer disposal** - 添加 IPC 退避/重试和更安全的资源释放
|
|
||||||
13. **Add preview controls and settings UI tweaks** - 添加预览控件和设置 UI 调整
|
|
||||||
14. **Add install checkpoint/resume and DDSS workflows** - 添加安装检查点/恢复和 DDSS 工作流
|
|
||||||
|
|
||||||
## 📊 变更统计
|
|
||||||
|
|
||||||
| 统计项 | 数值 |
|
|
||||||
|--------|------|
|
|
||||||
| **变更文件总数** | 904 个文件 |
|
|
||||||
| **新增代码行数** | +78,048 行 |
|
|
||||||
| **删除代码行数** | -18,362 行 |
|
|
||||||
| **净增代码行数** | +59,686 行 |
|
|
||||||
|
|
||||||
## 📂 详细变更分析(按文件类型分组)
|
|
||||||
|
|
||||||
### 1. 核心代码文件 (.cs)
|
|
||||||
|
|
||||||
#### LanMountainDesktop 核心项目
|
|
||||||
| 文件路径 | 类型 | 变更说明 |
|
|
||||||
|----------|------|----------|
|
|
||||||
| `LanMountainDesktop/Program.cs` | 修改 | 添加 Windows chrome 修补器加载逻辑 |
|
|
||||||
| `LanMountainDesktop/ViewModels/SettingsViewModels.cs` | 修改 | 重构设置视图模型,添加新属性和本地化支持 |
|
|
||||||
| `LanMountainDesktop/ViewModels/WallpaperSettingsPageViewModel.cs` | 修改 | 添加材质颜色和壁纸设置 |
|
|
||||||
| `LanMountainDesktop/ViewModels/UpdateSettingsPageViewModel.cs` | 修改 | 更新设置页面视图模型 |
|
|
||||||
| `LanMountainDesktop/Views/SettingsWindow.axaml` | 修改 | Fluent Shell 设置窗口重构,添加自定义标题栏 |
|
|
||||||
| `LanMountainDesktop/Views/SettingsWindow.axaml.cs` | 修改 | 设置窗口代码重构,添加搜索功能 |
|
|
||||||
| `LanMountainDesktop/Views/TransparentOverlayWindow.axaml` | 修改 | 透明覆盖窗口大幅重构 |
|
|
||||||
| `LanMountainDesktop/Services/LocalizationService.cs` | 修改 | 本地化服务更新 |
|
|
||||||
| `LanMountainDesktop/Services/SettingsSearchService.cs` | 新增 | 设置搜索服务(搜索索引、导航、结果高亮) |
|
|
||||||
| `LanMountainDesktop/Services/MaterialSurfaceService.cs` | 修改 | 添加特殊材质参数和窗口材质处理 |
|
|
||||||
| `LanMountainDesktop/Services/GlassEffectService.cs` | 修改 | 添加自适应设置窗口调色笔刷 |
|
|
||||||
| `LanMountainDesktop/Services/SettingsWindowService.cs` | 修改 | 重构主题应用逻辑 |
|
|
||||||
| `LanMountainDesktop/Services/AppearanceThemeService.cs` | 修改 | 依赖 MaterialColorService,更新外观主题处理 |
|
|
||||||
| `LanMountainDesktop/Services/WindowMaterialService.cs` | 修改 | 窗口材质服务和自动材质模式支持 |
|
|
||||||
| `LanMountainDesktop/Services/DataStorageService.cs` | 新增 | 数据存储服务(扫描、磁盘信息、清理操作) |
|
|
||||||
| `LanMountainDesktop/Services/WallpaperColorPipeline.cs` | 新增 | 壁纸颜色管道服务 |
|
|
||||||
| `LanMountainDesktop/Services/Launch/LauncherWindowsStartupService.cs` | 新增 | 启动器 Windows 启动服务 |
|
|
||||||
| `LanMountainDesktop/Services/HostAppSettingsOobeMerger.cs` | 新增 | Host 应用设置 OOBE 合并服务 |
|
|
||||||
| `LanMountainDesktop/Services/UpdateEngineService.cs` | 修改 | 添加检查点加载/保存/恢复逻辑 |
|
|
||||||
| `LanMountainDesktop/Services/IPC/...` | 多文件 | 添加重试逻辑、退避策略、更安全的资源释放 |
|
|
||||||
|
|
||||||
#### 视图模型 (ViewModels)
|
|
||||||
| 文件路径 | 变更说明 |
|
|
||||||
|----------|----------|
|
|
||||||
| `NotificationSettingsPageViewModel.cs` | 添加本地化支持 |
|
|
||||||
| `DevSettingsPageViewModel.cs` | 添加本地化支持 |
|
|
||||||
| `AboutSettingsPageViewModel.cs` | 添加本地化支持 |
|
|
||||||
| `StatusBarSettingsPageViewModel.cs` | 添加本地化支持 |
|
|
||||||
| `MaterialColorSettingsPageViewModel.cs` | 新增材质颜色设置视图模型 |
|
|
||||||
| `DataSettingsPageViewModel.cs` | 新增数据设置视图模型 |
|
|
||||||
| `GeneralSettingsPageViewModel.cs` | 更新通用设置视图模型 |
|
|
||||||
| `AppearanceSettingsPageViewModel.cs` | 更新外观设置视图模型 |
|
|
||||||
| `ComponentsSettingsPageViewModel.cs` | 添加预览控件和实时预览支持 |
|
|
||||||
|
|
||||||
#### 设置页面视图 (Views)
|
|
||||||
| 文件路径 | 变更说明 |
|
|
||||||
|----------|----------|
|
|
||||||
| `NotificationSettingsPage.axaml` | 更新通知设置页面 |
|
|
||||||
| `UpdateSettingsPage.axaml` | 大幅重构更新设置页面(530 行变更) |
|
|
||||||
| `WeatherSettingsPage.axaml` | 更新天气设置页面 |
|
|
||||||
| `GeneralSettingsPage.axaml` | 更新通用设置页面 |
|
|
||||||
| `LauncherSettingsPage.axaml` | 更新启动器设置页面 |
|
|
||||||
| `MaterialColorSettingsPage.axaml` | 新增材质颜色设置页面 |
|
|
||||||
| `MaterialColorSettingsPage.axaml.cs` | 新增材质颜色设置代码 |
|
|
||||||
| `DataSettingsPage.axaml` | 新增数据设置页面 |
|
|
||||||
| `DataSettingsPage.axaml.cs` | 新增数据设置代码 |
|
|
||||||
| `StatusBarSettingsPage.axaml` | 更新状态栏设置页面 |
|
|
||||||
| `WallpaperSettingsPage.axaml` | 更新壁纸设置页面 |
|
|
||||||
|
|
||||||
### 2. 第三方库集成
|
|
||||||
|
|
||||||
#### DotNetCampus.InkCanvas 墨迹画布库(重大新增)
|
|
||||||
|
|
||||||
本次合并添加了完整的 **DotNetCampus.InkCanvas** 库,这是一个功能完整的墨迹/手写画布解决方案:
|
|
||||||
|
|
||||||
| 子项目 | 文件数 | 主要功能 |
|
|
||||||
|--------|--------|----------|
|
|
||||||
| **DotNetCampus.AvaloniaInkCanvas** | 多个 | Avalonia 平台的墨迹画布实现 |
|
|
||||||
| **DotNetCampus.InkCanvas.InkCore** | 30+ | 核心墨迹处理算法和接口 |
|
|
||||||
| **DotNetCampus.InkCanvas.SkiaInk** | 多个 | Skia 渲染引擎的墨迹实现 |
|
|
||||||
|
|
||||||
**主要功能**:
|
|
||||||
- 墨迹绘制和渲染(Stroke rendering)
|
|
||||||
- 橡皮擦功能(Eraser modes)
|
|
||||||
- 点抽稀算法(Drop point algorithm)
|
|
||||||
- 墨迹序列化格式(Ink Serialized Format)
|
|
||||||
- 多平台支持(Skia, WPF, Avalonia)
|
|
||||||
|
|
||||||
**涉及的核心文件**:
|
|
||||||
```
|
|
||||||
ThirdParty/DotNetCampus.InkCanvas/src/
|
|
||||||
├── DotNetCampus.AvaloniaInkCanvas/
|
|
||||||
│ ├── API/InkCanvas.cs
|
|
||||||
│ ├── Caching/InkBitmapCache.cs
|
|
||||||
│ ├── Core/AvaloniaSkiaInkCanvas.cs
|
|
||||||
│ └── Erasing/PointPathEraserManager.cs
|
|
||||||
├── DotNetCampus.InkCanvas.InkCore/
|
|
||||||
│ ├── Inking/Interactives/InkingModeInputDispatcher.cs
|
|
||||||
│ ├── InkSerializedFormat/InkSerializer.cs
|
|
||||||
│ └── System/Windows/Ink/Stroke.cs
|
|
||||||
└── DotNetCampus.InkCanvas.SkiaInk/
|
|
||||||
├── Settings/SkInkCanvasSettings.cs
|
|
||||||
└── Utils/SkiaExtension.cs
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3. 脚本和工具文件
|
|
||||||
|
|
||||||
#### 分析脚本(新增)
|
|
||||||
| 文件 | 用途 |
|
|
||||||
|------|------|
|
|
||||||
| `parse_git_log.py` | 解析 Git HEAD 日志文件 |
|
|
||||||
| `scripts/Analyze-GitCommits.ps1` | PowerShell 提交分析脚本 |
|
|
||||||
| `scripts/GitCommitAnalyzer.cs` | C# 提交分析器 |
|
|
||||||
| `scripts/analyze_commits.ps1` | 提交分析 PowerShell 脚本 |
|
|
||||||
| `scripts/analyze_commits.py` | Python 提交分析脚本 |
|
|
||||||
| `scripts/analyze_git_commits.py` | Git 提交分析 Python 脚本 |
|
|
||||||
| `scripts/generate_commit_docs.py` | 生成提交 Markdown 文档 |
|
|
||||||
| `scripts/generate_commit_reports.py` | 生成提交报告 |
|
|
||||||
|
|
||||||
#### 构建和发布脚本
|
|
||||||
| 文件 | 变更说明 |
|
|
||||||
|------|----------|
|
|
||||||
| `LanMountainDesktop/scripts/package.ps1` | 包脚本更新 |
|
|
||||||
| `LanMountainDesktop/scripts/Optimize-PublishPayload.ps1` | 新增优化发布脚本(203 行) |
|
|
||||||
|
|
||||||
### 4. 文档文件
|
|
||||||
|
|
||||||
| 文件 | 变更 | 说明 |
|
|
||||||
|------|------|------|
|
|
||||||
| `docs/ARCHITECTURE.md` | +34 行 | 架构文档更新 |
|
|
||||||
| `docs/LAUNCHER.md` | +2 行 | 启动器文档更新 |
|
|
||||||
| `docs/LAUNCHER_COORDINATOR.md` | +11 行 | 启动器协调器文档 |
|
|
||||||
| `docs/PLUGIN_SDK_V5_MIGRATION.md` | +14 行 | 插件 SDK v5 迁移文档 |
|
|
||||||
| `docs/VISUAL_SPEC.md` | +8 行 | 视觉规范文档 |
|
|
||||||
| `docs/ai/CODEBASE_MAP.md` | +1 行 | 代码库地图更新 |
|
|
||||||
| `docs/ai/SETTINGS_WINDOW_DESIGN.md` | +48 行 | 设置窗口设计文档(新增) |
|
|
||||||
| `docs/auto_commit_md/20260518_93758fc0.md` | +321 行 | 自动提交分析文档 |
|
|
||||||
| `SECURITY_AUDIT_REPORT.md` | +196 行 | 安全审计报告(新增) |
|
|
||||||
| `CODE_WIKI.md` | 新增 | 综合代码维基文档 |
|
|
||||||
| `design.md` | +2 行 | 设计文档更新 |
|
|
||||||
|
|
||||||
### 5. 配置文件
|
|
||||||
|
|
||||||
| 文件 | 变更说明 |
|
|
||||||
|------|----------|
|
|
||||||
| `NuGet.Config` | +7 行,新增本地 NuGet 包文件夹配置 |
|
|
||||||
| `LanMountainDesktop/HostApp.csproj` | 添加 Lib.Harmony.Thin 包引用 |
|
|
||||||
| `LanMountainDesktop/LanMountainDesktop.csproj` | 添加 PostHog 包更新到 2.6.0 |
|
|
||||||
| `LanMountainDesktop/plugins/PluginLoader.cs` | +61 行,插件加载器更新 |
|
|
||||||
| `LanMountainDesktop/plugins/PluginRuntimeService.cs` | +38 行,新增插件运行时服务 |
|
|
||||||
|
|
||||||
### 6. Mockup 和原型文件
|
|
||||||
|
|
||||||
| 文件 | 说明 |
|
|
||||||
|------|------|
|
|
||||||
| `mocks/class-schedule-mock.html` | +459 行,课程表 Mockup |
|
|
||||||
| `mocks/weather-widget-mock.html` | +209 行,天气组件 Mockup |
|
|
||||||
| `mockup-noise-level.html` | +898 行,噪音级别 Mockup |
|
|
||||||
|
|
||||||
## 🔍 代码审查要点
|
|
||||||
|
|
||||||
### ✅ 优点
|
|
||||||
|
|
||||||
1. **功能完整性**:此次合并涵盖了设置系统的多个重要方面,包括 UI 改进、本地化、搜索功能、数据管理等,是一个全面的更新。
|
|
||||||
|
|
||||||
2. **代码质量**:
|
|
||||||
- 添加了大量的单元测试
|
|
||||||
- 引入了渲染门控机制,避免不必要的重绘,提升性能
|
|
||||||
- 使用 MaterialColorSnapshot 作为统一的数据源,简化了主题管理
|
|
||||||
|
|
||||||
3. **第三方库集成**:
|
|
||||||
- 引入 DotNetCampus.InkCanvas 库,提供了完整的墨迹画布功能
|
|
||||||
- 使用 Harmony 进行系统级修补,提供了更灵活的系统集成方式
|
|
||||||
|
|
||||||
4. **安全性**:
|
|
||||||
- 添加了安全审计报告
|
|
||||||
- 改进了 IPC 通信的健壮性(退避、重试、资源释放)
|
|
||||||
|
|
||||||
5. **用户体验**:
|
|
||||||
- Fluent Shell 设计语言的应用,使设置窗口更加现代化
|
|
||||||
- 添加了设置搜索功能,提升了可访问性
|
|
||||||
- 数据存储管理功能让用户可以更好地管理应用空间
|
|
||||||
|
|
||||||
### ⚠️ 需要注意的点
|
|
||||||
|
|
||||||
1. **合并提交风险**:
|
|
||||||
- 这是一个大型合并提交(904 个文件),增加了代码审查的难度
|
|
||||||
- 建议:未来考虑拆分为更小的、功能明确的合并请求
|
|
||||||
|
|
||||||
2. **二进制文件**:
|
|
||||||
- `diff.txt` 是二进制文件(303KB),可能是补丁或差异文件
|
|
||||||
- 建议:检查 .gitattributes 确保二进制文件处理正确
|
|
||||||
|
|
||||||
3. **大量文件变更**:
|
|
||||||
- 78,048 行新增代码是一次性引入的,虽然功能完整,但风险集中
|
|
||||||
- 建议:确保有足够的测试覆盖,特别是对新集成的 DotNetCampus.InkCanvas 库
|
|
||||||
|
|
||||||
4. **本地化工作量**:
|
|
||||||
- 添加了多个语言的本地化字符串
|
|
||||||
- 建议:验证所有新增字符串的翻译准确性和一致性
|
|
||||||
|
|
||||||
5. **性能考虑**:
|
|
||||||
- 透明覆盖窗口有 1,258 行代码变更,需要特别关注渲染性能
|
|
||||||
- 建议:进行性能测试,特别是在不同硬件配置下
|
|
||||||
|
|
||||||
6. **依赖管理**:
|
|
||||||
- 添加了新的第三方库依赖
|
|
||||||
- 建议:评估库的维护状态和长期支持情况
|
|
||||||
|
|
||||||
### 📌 建议后续行动
|
|
||||||
|
|
||||||
1. **测试覆盖**:确保对新功能有充分的单元测试和集成测试
|
|
||||||
2. **文档更新**:更新用户文档以反映新的设置选项和功能
|
|
||||||
3. **性能监控**:部署后监控应用性能,特别是启动时间和内存使用
|
|
||||||
4. **用户体验反馈**:收集用户对新设置界面和搜索功能的反馈
|
|
||||||
5. **版本发布说明**:准备详细的发布说明,记录所有新增功能和重大变更
|
|
||||||
|
|
||||||
## 📈 影响范围评估
|
|
||||||
|
|
||||||
| 影响领域 | 评级 | 说明 |
|
|
||||||
|----------|------|------|
|
|
||||||
| **用户体验** | 🟢 高正面 | Fluent Shell 设计、搜索功能、本地化 |
|
|
||||||
| **系统性能** | 🟢 正面 | 渲染门控、图表缓存、IPC 优化 |
|
|
||||||
| **代码架构** | 🟢 正面 | MaterialColorSnapshot 统一数据源 |
|
|
||||||
| **功能完整性** | 🟢 正面 | InkCanvas 集成、数据管理 |
|
|
||||||
| **安全性** | 🟢 正面 | IPC 健壮性改进、安全审计 |
|
|
||||||
| **维护成本** | 🟡 中性 | 新增第三方库依赖需要维护 |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
*此报告由自动提交分析工具生成*
|
|
||||||
*生成时间: 2026-05-19 10:30:00*
|
|
||||||
*工具版本: Git Commit Analyzer v1.0*
|
|
||||||
@@ -1,259 +0,0 @@
|
|||||||
# Git 提交分析报告
|
|
||||||
|
|
||||||
## 📋 提交基本信息
|
|
||||||
|
|
||||||
| 属性 | 值 |
|
|
||||||
|------|-----|
|
|
||||||
| **完整哈希** | `ac8ee8dc5467d51cc09ad614aac2c783a6c5dad5` |
|
|
||||||
| **短哈希** | `ac8ee8d` |
|
|
||||||
| **作者** | lincube <lincube3@hotmail.com> |
|
|
||||||
| **提交日期** | 2026-05-23 |
|
|
||||||
| **提交时间** | 02:49:01 |
|
|
||||||
| **时区** | +0800 |
|
|
||||||
| **提交类型** | 🟢 常规提交 |
|
|
||||||
|
|
||||||
## 📝 提交信息摘要
|
|
||||||
|
|
||||||
```
|
|
||||||
changed.优化了天气组件
|
|
||||||
```
|
|
||||||
|
|
||||||
**详细分析**:
|
|
||||||
|
|
||||||
本次提交主要针对天气组件进行了 UI 优化,重点解决了文本显示被截断的问题。通过调整 `ClipToBounds` 属性和添加适当的 `Padding`,改善了天气组件在各种分辨率下的文本可见性。
|
|
||||||
|
|
||||||
## 📊 变更统计
|
|
||||||
|
|
||||||
| 统计项 | 数值 |
|
|
||||||
|--------|------|
|
|
||||||
| **变更文件总数** | 15 个文件 |
|
|
||||||
| **新增代码行数** | +301 行 |
|
|
||||||
| **删除代码行数** | -19 行 |
|
|
||||||
| **净增代码行数** | +282 行 |
|
|
||||||
|
|
||||||
### 变更文件类型分布
|
|
||||||
|
|
||||||
| 文件类型 | 文件数量 | 说明 |
|
|
||||||
|----------|----------|------|
|
|
||||||
| **C# 服务文件** | 6 个 | 后端服务逻辑 |
|
|
||||||
| **XAML 视图文件** | 6 个 | UI 组件定义 |
|
|
||||||
| **XAML.CS 代码文件** | 4 个 | 视图代码逻辑 |
|
|
||||||
| **文档文件** | 1 个 | 自动生成的分析文档 |
|
|
||||||
|
|
||||||
## 📂 详细变更分析
|
|
||||||
|
|
||||||
### 1. 服务层文件变更 (Services)
|
|
||||||
|
|
||||||
#### LanMountainDesktop/Services/AppSettingsService.cs
|
|
||||||
- **变更类型**: 修改
|
|
||||||
- **变更行数**: ±6 行
|
|
||||||
- **变更说明**: 更新应用设置服务,可能涉及天气相关配置的调整
|
|
||||||
|
|
||||||
#### LanMountainDesktop/Services/FusedDesktopLayoutService.cs
|
|
||||||
- **变更类型**: 修改
|
|
||||||
- **变更行数**: ±5 行
|
|
||||||
- **变更说明**: 融合桌面布局服务更新
|
|
||||||
|
|
||||||
#### LanMountainDesktop/Services/LauncherSettingsService.cs
|
|
||||||
- **变更类型**: 修改
|
|
||||||
- **变更行数**: ±4 行
|
|
||||||
- **变更说明**: 启动器设置服务更新
|
|
||||||
|
|
||||||
#### LanMountainDesktop/Services/Settings/SettingsService.cs
|
|
||||||
- **变更类型**: 修改
|
|
||||||
- **变更行数**: ±4 行
|
|
||||||
- **变更说明**: 通用设置服务更新
|
|
||||||
|
|
||||||
#### LanMountainDesktop/Services/ZhiJiaoHubCacheService.cs
|
|
||||||
- **变更类型**: 修改
|
|
||||||
- **变更行数**: ±8 行
|
|
||||||
- **变更说明**: 智慧教育缓存服务更新(变更较大)
|
|
||||||
|
|
||||||
### 2. ClockAirApp 相关文件
|
|
||||||
|
|
||||||
#### LanMountainDesktop/ClockAirApp/ClockAirAppSettingsStore.cs
|
|
||||||
- **变更类型**: 修改
|
|
||||||
- **变更行数**: ±4 行
|
|
||||||
- **变更说明**: 时钟应用设置存储更新
|
|
||||||
|
|
||||||
### 3. 天气组件核心变更 (Weather Widgets) 🔥
|
|
||||||
|
|
||||||
这是本次提交的核心变更区域,涉及多个天气组件的 UI 优化:
|
|
||||||
|
|
||||||
#### ExtendedWeatherWidget 扩展天气组件
|
|
||||||
| 文件 | 变更类型 | 变更说明 |
|
|
||||||
|------|----------|----------|
|
|
||||||
| `Views/Components/ExtendedWeatherWidget.axaml` | 修改 | 添加 `ClipToBounds="False"` |
|
|
||||||
| `Views/Components/ExtendedWeatherWidget.axaml.cs` | 修改 | 动态生成 TextBlock 时添加 `ClipToBounds = false` |
|
|
||||||
|
|
||||||
**关键代码变更**:
|
|
||||||
```csharp
|
|
||||||
// ExtendedWeatherWidget.axaml.cs
|
|
||||||
// 变更前
|
|
||||||
inner.Children.Add(new TextBlock { ... });
|
|
||||||
|
|
||||||
// 变更后
|
|
||||||
inner.Children.Add(new TextBlock {
|
|
||||||
Text = item.Value,
|
|
||||||
ClipToBounds = false // 允许文本溢出显示
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
#### HourlyWeatherWidget 小时天气组件
|
|
||||||
| 文件 | 变更类型 | 变更说明 |
|
|
||||||
|------|----------|----------|
|
|
||||||
| `Views/Components/HourlyWeatherWidget.axaml` | 修改 | 添加 `ClipToBounds="False"` |
|
|
||||||
| `Views/Components/HourlyWeatherWidget.axaml.cs` | 修改 | 添加 `ClipToBounds = false` |
|
|
||||||
|
|
||||||
#### MultiDayWeatherWidget 多日天气组件
|
|
||||||
| 文件 | 变更类型 | 变更说明 |
|
|
||||||
|------|----------|----------|
|
|
||||||
| `Views/Components/MultiDayWeatherWidget.axaml` | 修改 | 添加 `ClipToBounds="False" Padding="0,1,0,0"` |
|
|
||||||
| `Views/Components/MultiDayWeatherWidget.axaml.cs` | 修改 | 多处 TextBlock 添加 `ClipToBounds = false` |
|
|
||||||
|
|
||||||
**关键 UI 调整**:
|
|
||||||
```xml
|
|
||||||
<!-- MultiDayWeatherWidget.axaml -->
|
|
||||||
<!-- 变更前 -->
|
|
||||||
<TextBlock x:Name="TemperatureTextBlock" Text="--°" FontSize="42" FontWeight="Bold" />
|
|
||||||
|
|
||||||
<!-- 变更后 -->
|
|
||||||
<TextBlock x:Name="TemperatureTextBlock" Text="--°" FontSize="42" FontWeight="Bold"
|
|
||||||
ClipToBounds="False" Padding="0,1,0,0" />
|
|
||||||
```
|
|
||||||
|
|
||||||
**代码层变更**:
|
|
||||||
```csharp
|
|
||||||
// 多处高低温 TextBlock 添加了 ClipToBounds = false
|
|
||||||
new TextBlock {
|
|
||||||
Text = FormatTemperature(item.HighTemperatureC),
|
|
||||||
ClipToBounds = false // 允许温度值完整显示
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
#### WeatherClockWidget 天气时钟组件
|
|
||||||
| 文件 | 变更类型 | 变更说明 |
|
|
||||||
|------|----------|----------|
|
|
||||||
| `Views/Components/WeatherClockWidget.axaml` | 修改 | 温度文本块添加 `ClipToBounds="False"` |
|
|
||||||
|
|
||||||
#### WeatherWidget 主天气组件
|
|
||||||
| 文件 | 变更类型 | 变更说明 |
|
|
||||||
|------|----------|----------|
|
|
||||||
| `Views/Components/WeatherWidget.axaml` | 修改 | 温度文本块添加 `ClipToBounds="False" Padding="0,2,0,0"` |
|
|
||||||
|
|
||||||
**WeatherWidget 详细变更**:
|
|
||||||
```xml
|
|
||||||
<!-- 变更前 -->
|
|
||||||
<TextBlock x:Name="TemperatureTextBlock" Text="--°" FontSize="72" FontWeight="Bold" />
|
|
||||||
|
|
||||||
<!-- 变更后 -->
|
|
||||||
<TextBlock x:Name="TemperatureTextBlock" Text="--°" FontSize="72" FontWeight="Bold"
|
|
||||||
ClipToBounds="False" Padding="0,2,0,0" />
|
|
||||||
```
|
|
||||||
- 添加了 `ClipToBounds="False"` 以允许文本溢出显示
|
|
||||||
- 添加了 `Padding="0,2,0,0"` 调整文本垂直位置,避免上下被截断
|
|
||||||
|
|
||||||
### 4. 文档变更
|
|
||||||
|
|
||||||
#### docs/auto_commit_md/20260519_7a70476.md
|
|
||||||
- **变更类型**: 新增
|
|
||||||
- **变更行数**: +269 行
|
|
||||||
- **变更说明**: 自动生成的历史提交分析文档
|
|
||||||
|
|
||||||
## 🔍 代码审查要点
|
|
||||||
|
|
||||||
### ✅ 优点
|
|
||||||
|
|
||||||
1. **UI 修复明确**:
|
|
||||||
- 清楚地识别了文本截断问题
|
|
||||||
- 使用 `ClipToBounds="False"` 是解决文本溢出显示的标准做法
|
|
||||||
- 添加适当的 `Padding` 调整了文本位置,避免被边框裁切
|
|
||||||
|
|
||||||
2. **一致性处理**:
|
|
||||||
- 在所有相关天气组件中都应用了相同的修复策略
|
|
||||||
- 保持了 UI 调整的一致性,包括 XAML 和 C# 代码
|
|
||||||
|
|
||||||
3. **性能考虑**:
|
|
||||||
- `ClipToBounds="False"` 的使用是局部的、针对性的
|
|
||||||
- 不会对整体渲染性能产生显著影响
|
|
||||||
|
|
||||||
4. **向后兼容**:
|
|
||||||
- 修改仅影响文本显示方式,不影响数据逻辑
|
|
||||||
- 用户不会感知到底层数据的变化
|
|
||||||
|
|
||||||
### ⚠️ 需要注意的点
|
|
||||||
|
|
||||||
1. **字体渲染差异**:
|
|
||||||
- `Padding` 值(0,1,0,0 或 0,2,0,0)可能需要根据不同字体进行微调
|
|
||||||
- 建议在不同字体、不同 DPI 设置下测试显示效果
|
|
||||||
|
|
||||||
2. **文本溢出风险**:
|
|
||||||
- 虽然允许文本溢出,但需要确保有足够的容器空间
|
|
||||||
- 极端情况下文本可能仍然会被父容器裁切
|
|
||||||
|
|
||||||
3. **多语言支持**:
|
|
||||||
- 不同的语言文本长度不同,需要确保各种语言的文本都能正确显示
|
|
||||||
- 建议测试中文、英文、日文等多种语言的天气描述文本
|
|
||||||
|
|
||||||
4. **动态内容**:
|
|
||||||
- 温度值在不同单位(°C/°F)下长度可能不同
|
|
||||||
- 需要测试各种温度值的显示效果
|
|
||||||
|
|
||||||
### 📌 建议后续行动
|
|
||||||
|
|
||||||
1. **UI 测试**:在多种分辨率和 DPI 设置下测试天气组件
|
|
||||||
2. **多语言测试**:确保各种语言环境下文本显示正常
|
|
||||||
3. **边界测试**:测试温度值在极端情况下的显示(如 -40°C 或 50°C)
|
|
||||||
4. **性能监控**:监控修改后的渲染性能,确保没有性能退化
|
|
||||||
|
|
||||||
## 📈 技术分析
|
|
||||||
|
|
||||||
### 变更的技术背景
|
|
||||||
|
|
||||||
在 Avalonia UI 框架中,`ClipToBounds` 属性默认值为 `true`,这会导致子元素在超出容器边界时被裁切。对于天气组件中的温度文本、天气描述等动态内容,这种裁切会导致文本显示不完整。
|
|
||||||
|
|
||||||
### 解决方案的有效性
|
|
||||||
|
|
||||||
| 解决方案 | 效果 | 风险 |
|
|
||||||
|----------|------|------|
|
|
||||||
| `ClipToBounds="False"` | ✅ 允许文本完整显示 | ⚠️ 可能溢出到其他元素 |
|
|
||||||
| `Padding="0,2,0,0"` | ✅ 调整文本位置 | ⚠️ 需要精确调整数值 |
|
|
||||||
|
|
||||||
### 相关设计模式
|
|
||||||
|
|
||||||
本次修改涉及以下 UI 设计考虑:
|
|
||||||
- **溢出处理**:在固定尺寸容器中显示动态内容
|
|
||||||
- **对齐策略**:通过 Padding 微调元素位置
|
|
||||||
- **层级管理**:避免文本溢出影响其他 UI 元素
|
|
||||||
|
|
||||||
## 📊 影响范围评估
|
|
||||||
|
|
||||||
| 影响领域 | 评级 | 说明 |
|
|
||||||
|----------|------|------|
|
|
||||||
| **用户体验** | 🟢 正面 | 修复了文本截断问题,提升可读性 |
|
|
||||||
| **系统性能** | 🟢 无影响 | UI 属性调整,无性能影响 |
|
|
||||||
| **代码维护性** | 🟢 正面 | 统一了天气组件的文本显示处理方式 |
|
|
||||||
| **兼容性** | 🟢 正面 | 向后兼容,无破坏性变更 |
|
|
||||||
| **测试覆盖率** | 🟡 需补充 | 建议增加 UI 显示测试用例 |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📋 总结
|
|
||||||
|
|
||||||
本次提交 `ac8ee8d` 主要解决了天气组件的文本显示问题,通过在所有相关组件中添加 `ClipToBounds="False"` 和适当的 `Padding`,确保了温度、天气描述等文本能够完整显示。
|
|
||||||
|
|
||||||
**关键成果**:
|
|
||||||
- ✅ 修复了 5 个天气组件的文本截断问题
|
|
||||||
- ✅ 保持了一致的 UI 处理方式
|
|
||||||
- ✅ 代码变更精确、风险低
|
|
||||||
|
|
||||||
**建议关注**:
|
|
||||||
- 多语言文本显示效果
|
|
||||||
- 不同 DPI 下的字体渲染
|
|
||||||
- 极端温度值的显示
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
*此报告由自动提交分析工具生成*
|
|
||||||
*生成时间: 2026-05-23*
|
|
||||||
*工具版本: Git Commit Analyzer v1.0*
|
|
||||||
Reference in New Issue
Block a user