Refactor settings window UI and theming

Improve theming and layout for the Settings window and related services.

- MaterialSurfaceService: add special material parameters for SettingsWindowBackground (lower alpha, no blur) and avoid hot-switching real backdrops for non-settings windows.
- GlassEffectService: add AdaptiveSettingsWindowTintBrush + ResolveSettingsWindowTintAlpha to provide optional content tinting tied to system material mode.
- SettingsWindowService: refactor theme application into ApplyThemeVariantAndResources, ensure settings window material is applied at show/activate times, and tidy theme/resource application flow.
- SettingsWindow.axaml / .axaml.cs: restructure title bar (separate Grid.Row=0 border) and FANavigationView host, add pane-footer toggle button for :minimal layout, use dynamic corner radius resource, and update toggle/visibility/icon logic and responsive layout code.
- SettingsPages: remove some IconText usages and adjust margins; use DesignCornerRadiusLg for update card corner radius.
- Add NuGet.Config to set local globalPackagesFolder and ignore .nuget/packages in .gitignore.

These changes aim to improve visuals, avoid backdrop overdraw, and make the settings window behavior consistent across themes and layouts.
This commit is contained in:
lincube
2026-05-04 03:19:25 +08:00
parent 3a8516334a
commit 6a30bc6fce
9 changed files with 205 additions and 125 deletions

3
.gitignore vendored
View File

@@ -6,6 +6,9 @@
# dotenv files # dotenv files
.env .env
# Local NuGet global packages (NuGet.Config globalPackagesFolder)
.nuget/packages/
# User-specific files # User-specific files
*.rsuser *.rsuser
*.suo *.suo

View File

@@ -353,6 +353,26 @@ internal sealed class MaterialSurfaceService : IMaterialSurfaceService
MaterialSurfaceRole role, MaterialSurfaceRole role,
bool isNightMode) bool isNightMode)
{ {
// Settings 根层(如 RootGrid叠在 Transparent + Mica/Acrylic 上:过高 alpha 会完全盖住系统 backdrop。
// 保持非 None 下较低 alphaNone 仍用不透明白底等价。BlurRadius=0由 DWM 提供模糊)。
if (role == MaterialSurfaceRole.SettingsWindowBackground)
{
return materialMode switch
{
ThemeAppearanceValues.MaterialAcrylic => (
0.20,
0.14,
isNightMode ? (byte)0x8E : (byte)0x96,
0),
ThemeAppearanceValues.MaterialMica => (
0.14,
0.08,
isNightMode ? (byte)0x9E : (byte)0xA6,
0),
_ => (0.08, 0.05, (byte)0xFF, 0)
};
}
var isOverlay = role is MaterialSurfaceRole.DockBackground or MaterialSurfaceRole.StatusBarBackground or MaterialSurfaceRole.OverlayPanel; var isOverlay = role is MaterialSurfaceRole.DockBackground or MaterialSurfaceRole.StatusBarBackground or MaterialSurfaceRole.OverlayPanel;
return materialMode switch return materialMode switch
{ {
@@ -491,7 +511,8 @@ internal sealed class AppearanceThemeService : IAppearanceThemeService, IDisposa
// Avoid hot-switching real backdrops on already-visible windows. This has been // Avoid hot-switching real backdrops on already-visible windows. This has been
// a stability hotspot when users flip theme source/material at runtime. // a stability hotspot when users flip theme source/material at runtime.
if (window.IsVisible) // SettingsWindowBackground 是唯一需要材质与资源同步热切换的宿主角色;其它窗口仍保持「仅创建时」应用以降低风险。
if (window.IsVisible && role != MaterialSurfaceRole.SettingsWindowBackground)
{ {
return; return;
} }

View File

@@ -69,6 +69,15 @@ public static class GlassEffectService
resources["AdaptiveWindowBackgroundBrush"] = new SolidColorBrush(windowSurface.BackgroundColor); resources["AdaptiveWindowBackgroundBrush"] = new SolidColorBrush(windowSurface.BackgroundColor);
resources["AdaptiveWindowBorderBrush"] = new SolidColorBrush(windowSurface.BorderColor); resources["AdaptiveWindowBorderBrush"] = new SolidColorBrush(windowSurface.BorderColor);
resources["AdaptiveSettingsWindowBackgroundBrush"] = new SolidColorBrush(settingsWindowSurface.BackgroundColor); resources["AdaptiveSettingsWindowBackgroundBrush"] = new SolidColorBrush(settingsWindowSurface.BackgroundColor);
// 可选:叠在内容区上的可读性 tint半透明不改变 AdaptiveSettingsWindowBackgroundBrush 的语义权重,供 P1 绑定内容层。
var settingsTintBase = settingsWindowSurface.BackgroundColor;
var settingsTintAlpha = ResolveSettingsWindowTintAlpha(context);
resources["AdaptiveSettingsWindowTintBrush"] = new SolidColorBrush(
Color.FromArgb(
settingsTintAlpha,
settingsTintBase.R,
settingsTintBase.G,
settingsTintBase.B));
resources["AdaptiveSettingsWindowBorderBrush"] = new SolidColorBrush(settingsWindowSurface.BorderColor); resources["AdaptiveSettingsWindowBorderBrush"] = new SolidColorBrush(settingsWindowSurface.BorderColor);
resources["AdaptiveDockBackgroundBrush"] = new SolidColorBrush(dockSurface.BackgroundColor); resources["AdaptiveDockBackgroundBrush"] = new SolidColorBrush(dockSurface.BackgroundColor);
resources["AdaptiveDockBorderBrush"] = new SolidColorBrush(dockSurface.BorderColor); resources["AdaptiveDockBorderBrush"] = new SolidColorBrush(dockSurface.BorderColor);
@@ -100,4 +109,16 @@ public static class GlassEffectService
resources["AdaptiveDesktopComponentHostOpacity"] = desktopComponentSurface.Opacity; resources["AdaptiveDesktopComponentHostOpacity"] = desktopComponentSurface.Opacity;
resources["AdaptiveStatusBarComponentHostOpacity"] = statusBarComponentSurface.Opacity; resources["AdaptiveStatusBarComponentHostOpacity"] = statusBarComponentSurface.Opacity;
} }
/// <summary>可选内容叠层 alpha与设置窗表面色相一致None 为 0 避免重复染色。</summary>
private static byte ResolveSettingsWindowTintAlpha(ThemeColorContext context)
{
var mode = ThemeAppearanceValues.NormalizeSystemMaterialMode(context.SystemMaterialMode);
return mode switch
{
ThemeAppearanceValues.MaterialAcrylic => context.IsNightMode ? (byte)0x58 : (byte)0x4C,
ThemeAppearanceValues.MaterialMica => context.IsNightMode ? (byte)0x50 : (byte)0x44,
_ => (byte)0x00
};
}
} }

View File

@@ -71,7 +71,7 @@ internal sealed class SettingsWindowService : ISettingsWindowService
_window ??= CreateWindow(); _window ??= CreateWindow();
var appearanceSnapshot = _appearanceThemeService.GetCurrent(); var appearanceSnapshot = _appearanceThemeService.GetCurrent();
_window.ApplyChromeMode(appearanceSnapshot.UseSystemChrome); _window.ApplyChromeMode(appearanceSnapshot.UseSystemChrome);
ApplyTheme(_window); ApplyThemeVariantAndResources(_window);
var targetPageId = request.PageId ?? _window.ViewModel.CurrentPageId; var targetPageId = request.PageId ?? _window.ViewModel.CurrentPageId;
_window.ReloadPages(targetPageId); _window.ReloadPages(targetPageId);
@@ -79,6 +79,7 @@ internal sealed class SettingsWindowService : ISettingsWindowService
if (!_window.IsVisible) if (!_window.IsVisible)
{ {
CenterWindow(_window, request); CenterWindow(_window, request);
_appearanceThemeService.ApplyWindowMaterial(_window, MaterialSurfaceRole.SettingsWindowBackground);
_window.Show(); _window.Show();
NotifyStateChanged(); NotifyStateChanged();
CenterWindowLater(_window, request); CenterWindowLater(_window, request);
@@ -90,6 +91,7 @@ internal sealed class SettingsWindowService : ISettingsWindowService
_window.WindowState = WindowState.Normal; _window.WindowState = WindowState.Normal;
} }
_appearanceThemeService.ApplyWindowMaterial(_window, MaterialSurfaceRole.SettingsWindowBackground);
_window.Activate(); _window.Activate();
} }
@@ -113,7 +115,6 @@ internal sealed class SettingsWindowService : ISettingsWindowService
_pageRegistry, _pageRegistry,
_hostApplicationLifecycle, _hostApplicationLifecycle,
useSystemChrome); useSystemChrome);
ApplyTheme(window);
window.ShowInTaskbar = true; window.ShowInTaskbar = true;
window.Closed += (_, _) => window.Closed += (_, _) =>
{ {
@@ -285,13 +286,23 @@ internal sealed class SettingsWindowService : ISettingsWindowService
}, DispatcherPriority.Background); }, DispatcherPriority.Background);
} }
private void ApplyTheme(SettingsWindow window) private static void ApplyThemeVariantAndResources(SettingsWindow window, IAppearanceThemeService appearanceThemeService)
{ {
var appearanceSnapshot = _appearanceThemeService.GetCurrent(); var appearanceSnapshot = appearanceThemeService.GetCurrent();
window.RequestedThemeVariant = appearanceSnapshot.IsNightMode window.RequestedThemeVariant = appearanceSnapshot.IsNightMode
? ThemeVariant.Dark ? ThemeVariant.Dark
: ThemeVariant.Light; : ThemeVariant.Light;
_appearanceThemeService.ApplyThemeResources(window.Resources); appearanceThemeService.ApplyThemeResources(window.Resources);
}
private void ApplyThemeVariantAndResources(SettingsWindow window)
{
ApplyThemeVariantAndResources(window, _appearanceThemeService);
}
private void ApplyTheme(SettingsWindow window)
{
ApplyThemeVariantAndResources(window, _appearanceThemeService);
_appearanceThemeService.ApplyWindowMaterial(window, MaterialSurfaceRole.SettingsWindowBackground); _appearanceThemeService.ApplyWindowMaterial(window, MaterialSurfaceRole.SettingsWindowBackground);
} }

View File

@@ -1,7 +1,6 @@
<UserControl xmlns="https://github.com/avaloniaui" <UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="using:LanMountainDesktop.ViewModels" xmlns:vm="using:LanMountainDesktop.ViewModels"
xmlns:controls="using:LanMountainDesktop.Controls"
xmlns:ui="using:FluentAvalonia.UI.Controls" xmlns:ui="using:FluentAvalonia.UI.Controls"
xmlns:fi="using:FluentIcons.Avalonia" xmlns:fi="using:FluentIcons.Avalonia"
xmlns:symbol="using:FluentIcons.Common" xmlns:symbol="using:FluentIcons.Common"
@@ -52,10 +51,6 @@
</Grid> </Grid>
</Border> </Border>
<controls:IconText Icon="Apps"
Text="{Binding AppearanceHeader}"
Margin="0,0,0,4" />
<ui:FASettingsExpander Classes="settings-expander-card" <ui:FASettingsExpander Classes="settings-expander-card"
Header="{Binding AppearanceHeader}" Header="{Binding AppearanceHeader}"
Description="{Binding AppearanceDescription}" Description="{Binding AppearanceDescription}"
@@ -76,11 +71,8 @@
</ui:FASettingsExpanderItem> </ui:FASettingsExpanderItem>
</ui:FASettingsExpander> </ui:FASettingsExpander>
<controls:IconText Icon="Apps"
Text="{Binding HiddenHeader}"
Margin="0,24,0,4" />
<ui:FASettingsExpander Classes="settings-expander-card" <ui:FASettingsExpander Classes="settings-expander-card"
Margin="0,24,0,14"
Header="{Binding HiddenHeader}" Header="{Binding HiddenHeader}"
Description="{Binding HiddenDescription}" Description="{Binding HiddenDescription}"
IsExpanded="True"> IsExpanded="True">

View File

@@ -10,7 +10,7 @@
<Style Selector="Border.update-status-card"> <Style Selector="Border.update-status-card">
<Setter Property="Padding" Value="24" /> <Setter Property="Padding" Value="24" />
<Setter Property="Margin" Value="0,0,0,18" /> <Setter Property="Margin" Value="0,0,0,18" />
<Setter Property="CornerRadius" Value="24" /> <Setter Property="CornerRadius" Value="{DynamicResource DesignCornerRadiusLg}" />
<Setter Property="Background" Value="{DynamicResource AdaptiveSurfaceRaisedBrush}" /> <Setter Property="Background" Value="{DynamicResource AdaptiveSurfaceRaisedBrush}" />
<Setter Property="BorderBrush" Value="{DynamicResource AdaptiveGlassPanelBorderBrush}" /> <Setter Property="BorderBrush" Value="{DynamicResource AdaptiveGlassPanelBorderBrush}" />
<Setter Property="BorderThickness" Value="1" /> <Setter Property="BorderThickness" Value="1" />

View File

@@ -40,10 +40,108 @@
Classes="settings-scope" Classes="settings-scope"
Background="{DynamicResource AdaptiveSettingsWindowBackgroundBrush}" Background="{DynamicResource AdaptiveSettingsWindowBackgroundBrush}"
RowDefinitions="Auto,*"> RowDefinitions="Auto,*">
<!-- 顶栏布局对齐 SecRandom折叠/品牌/标题)+ 中(透明拖窗区)+ 右(重启 / Windows caption 占位) --> <!-- ClassIsland SettingsWindowNew声明顺序为先 FANavigationViewGrid.Row=1再顶栏 BorderGrid.Row=0Row 仍为 0=标题栏、1=导航宿主,最终叠放不变。 -->
<Border x:Name="WindowTitleBarHost"
Height="48" <ui:FANavigationView x:Name="RootNavigationView"
Grid.Row="1"
Margin="0"
Background="Transparent" Background="Transparent"
PaneDisplayMode="Auto"
OpenPaneLength="283"
IsSettingsVisible="False"
IsBackButtonVisible="False"
SelectionChanged="OnNavigationSelectionChanged">
<ui:FANavigationView.PaneFooter>
<!-- 仅在 :minimalIsPaneToggleButtonVisible=False时由代码显示与模板内 pane-toggle-button 一致,不用顶栏备胎 -->
<StackPanel Orientation="Vertical">
<Button x:Name="PaneFooterToggleButton"
Classes="pane-toggle-button"
Margin="0,-8,0,0"
MinWidth="40"
Width="48"
VerticalAlignment="Bottom"
Click="OnPaneFooterToggleClick">
<Grid>
<fi:FluentIcon x:Name="PaneFooterToggleButtonIcon"
Icon="Navigation"
IconVariant="Regular"
FontSize="16"
Foreground="{DynamicResource TextFillColorPrimaryBrush}" />
</Grid>
</Button>
</StackPanel>
</ui:FANavigationView.PaneFooter>
<ui:FANavigationView.Styles>
<Style Selector="ui|FANavigationView#RootNavigationView:minimal">
<Setter Property="IsPaneToggleButtonVisible" Value="False"/>
</Style>
</ui:FANavigationView.Styles>
<ui:FANavigationView.Resources>
<SolidColorBrush x:Key="NavigationViewContentBackground" Color="Transparent" />
<SolidColorBrush x:Key="NavigationViewContentGridBorderBrush" Color="Transparent" />
</ui:FANavigationView.Resources>
<Grid x:Name="SettingsContentGrid"
ColumnDefinitions="*,Auto"
ColumnSpacing="20"
Margin="12,0,16,16">
<Grid Grid.Column="0"
RowDefinitions="Auto,*">
<Grid x:Name="PageTitleContainer"
Grid.Row="0"
Classes="page-title-container"
IsVisible="{Binding IsPageTitleVisible}">
<TextBlock x:Name="PageTitleTextBlock"
Classes="page-title-text"
Text="{Binding CurrentPageTitle}" />
</Grid>
<ui:FAFrame x:Name="ContentFrame"
Grid.Row="1" />
</Grid>
<Border x:Name="DrawerBorder"
Grid.Column="1"
Width="296"
Background="{DynamicResource AdaptiveSurfaceRaisedBrush}"
BorderBrush="{DynamicResource AdaptiveGlassPanelBorderBrush}"
BorderThickness="1"
CornerRadius="{DynamicResource DesignCornerRadiusMd}"
Padding="20"
BoxShadow="0 8 24 #14000000"
IsVisible="{Binding IsDrawerOpen}">
<Grid RowDefinitions="Auto,*"
RowSpacing="16">
<Grid ColumnDefinitions="*,Auto">
<TextBlock x:Name="DrawerTitleTextBlock"
FontSize="16"
FontWeight="SemiBold"
Text="{Binding DrawerTitle}" />
<Button Grid.Column="1"
Width="32"
Height="32"
Padding="0"
Background="Transparent"
BorderThickness="0"
Click="OnCloseDrawerClick">
<fi:FluentIcon Icon="Dismiss"
IconVariant="Regular" />
</Button>
</Grid>
<ContentControl x:Name="DrawerContentHost"
Grid.Row="1" />
</Grid>
</Border>
</Grid>
</ui:FANavigationView>
<Border x:Name="WindowTitleBarHost"
Grid.Row="0"
Height="48"
Background="{DynamicResource SolidBackgroundFillColorBaseBrush}"
BorderBrush="{DynamicResource AdaptiveSettingsWindowBorderBrush}" BorderBrush="{DynamicResource AdaptiveSettingsWindowBorderBrush}"
BorderThickness="0,0,0,1"> BorderThickness="0,0,0,1">
<Grid ColumnDefinitions="Auto,*,Auto" <Grid ColumnDefinitions="Auto,*,Auto"
@@ -53,26 +151,11 @@
Margin="8,0,8,0" Margin="8,0,8,0"
Spacing="8" Spacing="8"
VerticalAlignment="Center"> VerticalAlignment="Center">
<Button x:Name="TogglePaneButton"
Classes="pane-toggle-button"
Margin="-7,-8,-8,-8"
MinWidth="40"
Width="48"
VerticalAlignment="Center"
IsVisible="{Binding !#RootNavigationView.IsPaneToggleButtonVisible}"
Click="OnTogglePaneButtonClick">
<Grid>
<fi:FluentIcon x:Name="TogglePaneButtonIcon"
Icon="Navigation"
IconVariant="Regular"
FontSize="16" />
</Grid>
</Button>
<fi:FluentIcon x:Name="WindowBrandIcon" <fi:FluentIcon x:Name="WindowBrandIcon"
Margin="0,0,0,0"
Icon="Settings" Icon="Settings"
IconVariant="Filled" IconVariant="Filled"
FontSize="18"
Foreground="{DynamicResource TextFillColorPrimaryBrush}"
IsHitTestVisible="False" IsHitTestVisible="False"
VerticalAlignment="Center" /> VerticalAlignment="Center" />
@@ -81,6 +164,7 @@
FontWeight="SemiBold" FontWeight="SemiBold"
Margin="8,0,0,0" Margin="8,0,0,0"
VerticalAlignment="Center" VerticalAlignment="Center"
Foreground="{DynamicResource TextFillColorPrimaryBrush}"
IsHitTestVisible="False" IsHitTestVisible="False"
Text="{Binding Title}" /> Text="{Binding Title}" />
</StackPanel> </StackPanel>
@@ -119,80 +203,5 @@
</StackPanel> </StackPanel>
</Grid> </Grid>
</Border> </Border>
<ui:FANavigationView x:Name="RootNavigationView"
Grid.Row="1"
Margin="0"
Background="Transparent"
PaneDisplayMode="Auto"
OpenPaneLength="283"
IsSettingsVisible="False"
IsBackButtonVisible="False"
SelectionChanged="OnNavigationSelectionChanged">
<ui:FANavigationView.Styles>
<Style Selector="ui|FANavigationView#RootNavigationView:minimal">
<Setter Property="IsPaneToggleButtonVisible" Value="False"/>
</Style>
</ui:FANavigationView.Styles>
<ui:FANavigationView.Resources>
<SolidColorBrush x:Key="NavigationViewContentBackground" Color="Transparent" />
<SolidColorBrush x:Key="NavigationViewContentGridBorderBrush" Color="Transparent" />
</ui:FANavigationView.Resources>
<Grid x:Name="SettingsContentGrid"
ColumnDefinitions="*,Auto"
ColumnSpacing="20"
Margin="12,0,16,16">
<Grid Grid.Column="0"
RowDefinitions="Auto,*">
<Grid x:Name="PageTitleContainer"
Grid.Row="0"
Classes="page-title-container"
IsVisible="{Binding IsPageTitleVisible}">
<TextBlock x:Name="PageTitleTextBlock"
Classes="page-title-text"
Text="{Binding CurrentPageTitle}" />
</Grid>
<ui:FAFrame x:Name="ContentFrame"
Grid.Row="1" />
</Grid>
<Border x:Name="DrawerBorder"
Grid.Column="1"
Width="296"
Background="{DynamicResource AdaptiveSurfaceRaisedBrush}"
BorderBrush="{DynamicResource AdaptiveGlassPanelBorderBrush}"
BorderThickness="1"
CornerRadius="16"
Padding="20"
BoxShadow="0 8 24 #14000000"
IsVisible="{Binding IsDrawerOpen}">
<Grid RowDefinitions="Auto,*"
RowSpacing="16">
<Grid ColumnDefinitions="*,Auto">
<TextBlock x:Name="DrawerTitleTextBlock"
FontSize="16"
FontWeight="SemiBold"
Text="{Binding DrawerTitle}" />
<Button Grid.Column="1"
Width="32"
Height="32"
Padding="0"
Background="Transparent"
BorderThickness="0"
Click="OnCloseDrawerClick">
<fi:FluentIcon Icon="Dismiss"
IconVariant="Regular" />
</Button>
</Grid>
<ContentControl x:Name="DrawerContentHost"
Grid.Row="1" />
</Grid>
</Border>
</Grid>
</ui:FANavigationView>
</Grid> </Grid>
</faWindowing:FAAppWindow> </faWindowing:FAAppWindow>

View File

@@ -87,7 +87,8 @@ public partial class SettingsWindow : FAAppWindow, ISettingsPageHostContext
SyncPendingRestartState(); SyncPendingRestartState();
SyncTitleText(); SyncTitleText();
UpdateChromeMetrics(); UpdateChromeMetrics();
UpdatePaneToggleIcon(); UpdatePaneFooterToggleVisibility();
UpdatePaneFooterToggleIcon();
UpdateResponsiveLayout(); UpdateResponsiveLayout();
RequestResponsiveLayoutRefresh(); RequestResponsiveLayoutRefresh();
} }
@@ -104,6 +105,7 @@ public partial class SettingsWindow : FAAppWindow, ISettingsPageHostContext
CloseDrawer(); CloseDrawer();
RebuildNavigationItems(); RebuildNavigationItems();
NavigateTo(pageId ?? ViewModel.Pages.FirstOrDefault()?.PageId); NavigateTo(pageId ?? ViewModel.Pages.FirstOrDefault()?.PageId);
UpdatePaneFooterToggleVisibility();
} }
public void RebuildAndNavigateToDevPage() public void RebuildAndNavigateToDevPage()
@@ -266,6 +268,7 @@ public partial class SettingsWindow : FAAppWindow, ISettingsPageHostContext
ViewModel.IsPageTitleVisible = !descriptor.HidePageTitle; ViewModel.IsPageTitleVisible = !descriptor.HidePageTitle;
TrySelectNavigationItem(descriptor.PageId); TrySelectNavigationItem(descriptor.PageId);
SyncTitleText(); SyncTitleText();
UpdatePaneFooterToggleVisibility();
UpdateResponsiveLayout(); UpdateResponsiveLayout();
RequestResponsiveLayoutRefresh(); RequestResponsiveLayoutRefresh();
if (!string.Equals(previousPageId, descriptor.PageId, StringComparison.OrdinalIgnoreCase)) if (!string.Equals(previousPageId, descriptor.PageId, StringComparison.OrdinalIgnoreCase))
@@ -523,7 +526,7 @@ public partial class SettingsWindow : FAAppWindow, ISettingsPageHostContext
} }
} }
private void OnTogglePaneButtonClick(object? sender, Avalonia.Interactivity.RoutedEventArgs e) private void OnPaneFooterToggleClick(object? sender, Avalonia.Interactivity.RoutedEventArgs e)
{ {
_ = sender; _ = sender;
_ = e; _ = e;
@@ -533,7 +536,7 @@ public partial class SettingsWindow : FAAppWindow, ISettingsPageHostContext
} }
RootNavigationView.IsPaneOpen = !RootNavigationView.IsPaneOpen; RootNavigationView.IsPaneOpen = !RootNavigationView.IsPaneOpen;
UpdatePaneToggleIcon(); UpdatePaneFooterToggleIcon();
UpdateResponsiveLayout(); UpdateResponsiveLayout();
RequestResponsiveLayoutRefresh(); RequestResponsiveLayoutRefresh();
} }
@@ -544,13 +547,33 @@ public partial class SettingsWindow : FAAppWindow, ISettingsPageHostContext
if (e.Property == FANavigationView.IsPaneOpenProperty || if (e.Property == FANavigationView.IsPaneOpenProperty ||
e.Property == FANavigationView.OpenPaneLengthProperty || e.Property == FANavigationView.OpenPaneLengthProperty ||
e.Property == FANavigationView.PaneDisplayModeProperty) e.Property == FANavigationView.PaneDisplayModeProperty ||
e.Property == FANavigationView.IsPaneToggleButtonVisibleProperty)
{ {
UpdatePaneToggleIcon(); if (e.Property == FANavigationView.IsPaneToggleButtonVisibleProperty)
{
UpdatePaneFooterToggleVisibility();
}
UpdatePaneFooterToggleIcon();
RequestResponsiveLayoutRefresh(); RequestResponsiveLayoutRefresh();
} }
} }
/// <summary>
/// 仅在 <c>:minimal</c><see cref="FANavigationView.IsPaneToggleButtonVisible"/> 为 false时显示侧栏底部备胎按钮。
/// 根 DataContext 为 ViewModel 时,对 <c>#RootNavigationView</c> 的绑定易失效,故用代码同步可见性。
/// </summary>
private void UpdatePaneFooterToggleVisibility()
{
if (PaneFooterToggleButton is null || RootNavigationView is null)
{
return;
}
PaneFooterToggleButton.IsVisible = !RootNavigationView.IsPaneToggleButtonVisible;
}
private void RequestResponsiveLayoutRefresh() private void RequestResponsiveLayoutRefresh()
{ {
if (_isResponsiveRefreshPending) if (_isResponsiveRefreshPending)
@@ -580,14 +603,14 @@ public partial class SettingsWindow : FAAppWindow, ISettingsPageHostContext
: compactPaneWidth; : compactPaneWidth;
} }
private void UpdatePaneToggleIcon() private void UpdatePaneFooterToggleIcon()
{ {
if (TogglePaneButtonIcon is null || RootNavigationView is null) if (PaneFooterToggleButtonIcon is null || RootNavigationView is null)
{ {
return; return;
} }
TogglePaneButtonIcon.Icon = RootNavigationView.IsPaneOpen PaneFooterToggleButtonIcon.Icon = RootNavigationView.IsPaneOpen
? FluentIcons.Common.Icon.LineHorizontal3 ? FluentIcons.Common.Icon.LineHorizontal3
: FluentIcons.Common.Icon.Navigation; : FluentIcons.Common.Icon.Navigation;
} }
@@ -604,8 +627,6 @@ public partial class SettingsWindow : FAAppWindow, ISettingsPageHostContext
} }
if (WindowTitleBarHost is null || if (WindowTitleBarHost is null ||
TogglePaneButton is null ||
TogglePaneButtonIcon is null ||
WindowBrandIcon is null || WindowBrandIcon is null ||
WindowTitleTextBlock is null || WindowTitleTextBlock is null ||
RestartNowButton is null || RestartNowButton is null ||
@@ -622,8 +643,6 @@ public partial class SettingsWindow : FAAppWindow, ISettingsPageHostContext
var layoutScale = Math.Clamp(Math.Min(width / 1120d, height / 760d), 0.90, 1.18); var layoutScale = Math.Clamp(Math.Min(width / 1120d, height / 760d), 0.90, 1.18);
const double titleBarHeight = 48d; const double titleBarHeight = 48d;
var titleBarButtonWidth = Math.Clamp(40d * layoutScale, 36d, 48d);
var titleBarButtonHeight = Math.Clamp(32d * layoutScale, 30d, 38d);
var titleFontSize = Math.Clamp(12d * layoutScale, 11d, 14d); var titleFontSize = Math.Clamp(12d * layoutScale, 11d, 14d);
var titleBarIconSize = Math.Clamp(16d * layoutScale, 15d, 20d); var titleBarIconSize = Math.Clamp(16d * layoutScale, 15d, 20d);
var drawerTitleFontSize = Math.Clamp(16d * layoutScale, 14d, 20d); var drawerTitleFontSize = Math.Clamp(16d * layoutScale, 14d, 20d);
@@ -634,9 +653,6 @@ public partial class SettingsWindow : FAAppWindow, ISettingsPageHostContext
WindowTitleBarHost.Height = titleBarHeight; WindowTitleBarHost.Height = titleBarHeight;
TogglePaneButton.Width = titleBarButtonWidth;
TogglePaneButton.Height = titleBarButtonHeight;
TogglePaneButtonIcon.FontSize = titleBarIconSize;
WindowBrandIcon.FontSize = titleBarIconSize + 2; WindowBrandIcon.FontSize = titleBarIconSize + 2;
WindowTitleTextBlock.FontSize = titleFontSize; WindowTitleTextBlock.FontSize = titleFontSize;

7
NuGet.Config Normal file
View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<config>
<!-- 相对本文件:包落在仓库目录下,与仓库同盘(本机 D:),避免依赖 C:\Temp\cursor-sandbox-cache 等易损路径 -->
<add key="globalPackagesFolder" value=".nuget/packages" />
</config>
</configuration>