diff --git a/.trae/documents/avalonia12-migration-plan.md b/.trae/documents/avalonia12-migration-plan.md
new file mode 100644
index 0000000..52c8ade
--- /dev/null
+++ b/.trae/documents/avalonia12-migration-plan.md
@@ -0,0 +1,106 @@
+# Avalonia 12 迁移计划
+
+## 当前状态
+
+项目已完成以下迁移准备:
+
+* `Directory.Packages.props` 中 Avalonia 包已升级到 `12.0.1`
+
+* `FluentAvaloniaUI` 已升级到 `3.0.0-preview1`
+
+* `Avalonia.Diagnostics` 已替换为 `AvaloniaUI.DiagnosticsSupport`
+
+* `Avalonia.Controls.WebView` 已升级到 `12.0.0`
+
+* `ClassIsland.Markdown.Avalonia` 已升级到 `12.0.0`
+
+## 构建错误清单(26 errors)
+
+### 1. 窗口装饰 API 移除(8 errors)
+
+**文件**:`LanMountainDesktop/Views/SettingsWindow.axaml.cs`(4 errors)
+
+* `ExtendClientAreaChromeHints` 不存在(line 166, 179)
+
+* `SystemDecorations` 已过时,需改用 `WindowDecorations`(line 168, 177)
+
+**文件**:`LanMountainDesktop/Views/ComponentEditorWindow.axaml.cs`(4 errors)
+
+* `ExtendClientAreaChromeHints` 不存在(line 63, 72)
+
+* `SystemDecorations` 已过时,需改用 `WindowDecorations`(line 65, 70)
+
+**AXAML 文件**:13 个文件使用 `SystemDecorations` 属性(编译警告)
+
+### 2. 变量/字段未找到(8 errors)
+
+**文件**:`LanMountainDesktop/Views/MainWindow.ComponentSystem.cs`
+
+* `centerLeft` 不存在(line 759, 766, 778)
+
+* `positions` 不存在(line 1266)
+
+**文件**:`LanMountainDesktop/Views/MainWindow.DesktopPaging.cs`
+
+* `child` 不存在(line 312)
+
+* `_isThreeFingerOrRightDragSwipeActive` 不存在(line 517, 828, 847, 850)
+
+### 3. API 变更(3 errors)
+
+**文件**:`LanMountainDesktop/App.axaml.cs`
+
+* `BindingPlugins` 不可访问(line 532, 537)
+
+**文件**:`LanMountainDesktop/Views/Components/DesktopComponentFailureView.cs`
+
+* `IClipboard.SetTextAsync` 不存在(line 187)
+
+**文件**:`LanMountainDesktop/Services/MonetColorService.cs`
+
+* `Bitmap.CopyPixels` 参数不匹配(line 91)
+
+### 4. 第三方库变更(1 error)
+
+**文件**:`LanMountainDesktop/Views/SettingsWindow.axaml.cs`
+
+* `FluentIcons.Avalonia.SymbolIconSource` 不存在(line 215)
+
+### 5. 过时属性警告(需同步修复)
+
+* `TextBox.Watermark` → `PlaceholderText`(7 处 .cs + 7 处 .axaml)
+
+## 迁移步骤
+
+### Phase 1: 修复窗口装饰 API(高优先级)
+
+1. 重写 `SettingsWindow.ApplyChromeMode()` 使用 Avalonia 12 新 API
+2. 重写 `ComponentEditorWindow.ApplyChromeMode()` 使用 Avalonia 12 新 API
+3. 批量替换所有 `.axaml` 中的 `SystemDecorations` → `WindowDecorations`
+
+### Phase 2: 修复 MainWindow 编译错误(高优先级)
+
+1. 检查 `MainWindow.ComponentSystem.cs` 中 `centerLeft` 和 `positions` 的作用域问题
+2. 检查 `MainWindow.DesktopPaging.cs` 中 `child` 和 `_isThreeFingerOrRightDragSwipeActive` 的作用域问题
+3. 确认这些变量是否被意外删除或重命名
+
+### Phase 3: 修复 Avalonia 12 API 变更(中优先级)
+
+1. `App.axaml.cs`: 替换 `BindingPlugins.DataValidators` 的访问方式
+2. `DesktopComponentFailureView.cs`: 使用新的剪贴板 API
+3. `MonetColorService.cs`: 更新 `Bitmap.CopyPixels` 调用签名
+
+### Phase 4: 修复第三方库变更(中优先级)
+
+1. `SettingsWindow.axaml.cs`: 替换 `FluentIcons.Avalonia.SymbolIconSource` 为 v3 等效 API
+
+### Phase 5: 清理过时属性(低优先级)
+
+1. 批量替换 `Watermark` → `PlaceholderText`(所有 .cs 和 .axaml)
+
+## 验证步骤
+
+* 每阶段修复后运行 `dotnet build LanMountainDesktop.slnx -c Debug`
+
+* 最终运行 `dotnet test LanMountainDesktop.slnx -c Debug`
+
diff --git a/.trae/specs/avalonia-12-migration/checklist.md b/.trae/specs/avalonia-12-migration/checklist.md
new file mode 100644
index 0000000..2800726
--- /dev/null
+++ b/.trae/specs/avalonia-12-migration/checklist.md
@@ -0,0 +1,14 @@
+# Checklist
+
+- [ ] `SettingsWindow.ApplyChromeMode()` 不再使用 `ExtendClientAreaChromeHints` 和 `SystemDecorations`
+- [ ] `ComponentEditorWindow.ApplyChromeMode()` 不再使用 `ExtendClientAreaChromeHints` 和 `SystemDecorations`
+- [ ] 所有 `.axaml` 文件中的 `SystemDecorations` 已替换为 `WindowDecorations`
+- [ ] `MainWindow.ComponentSystem.cs` 中 `centerLeft` 和 `positions` 变量已正确定义
+- [ ] `MainWindow.DesktopPaging.cs` 中 `child` 和 `_isThreeFingerOrRightDragSwipeActive` 变量已正确定义
+- [ ] `App.axaml.cs` 中 `BindingPlugins.DataValidators` 代码已移除
+- [ ] `DesktopComponentFailureView.cs` 使用 `ClipboardExtensions.SetTextAsync`
+- [ ] `MonetColorService.cs` 使用正确的 `Bitmap.CopyPixels` 签名
+- [ ] `SettingsWindow.axaml.cs` 使用 `FluentIcons.Avalonia.FluentIcon` 替代 `SymbolIconSource`
+- [ ] 所有 `TextBox.Watermark` 已替换为 `PlaceholderText`
+- [ ] `dotnet build LanMountainDesktop.slnx -c Debug` 0 errors, 0 warnings(过时 API 警告)
+- [ ] `dotnet test LanMountainDesktop.slnx -c Debug` 全部通过
diff --git a/.trae/specs/avalonia-12-migration/spec.md b/.trae/specs/avalonia-12-migration/spec.md
new file mode 100644
index 0000000..74fdb1b
--- /dev/null
+++ b/.trae/specs/avalonia-12-migration/spec.md
@@ -0,0 +1,63 @@
+# Avalonia 12 迁移规格
+
+## Why
+
+Avalonia 12 带来性能改进(SkiaSharp 3.0、编译绑定默认开启)、新的窗口装饰体系(WindowDrawnDecorations)和更简洁的 API 设计。项目当前已升级包引用,但存在 18 个编译错误和若干过时 API 警告,需要系统性修复以确保构建通过。
+
+## What Changes
+
+- **BREAKING**: 移除 `ExtendClientAreaChromeHints` 和 `SystemDecorations` 的使用,迁移到 `WindowDecorations`
+- **BREAKING**: 移除 `BindingPlugins.DataValidators` 的使用(v12 已移除绑定插件体系)
+- **BREAKING**: 替换 `IClipboard.SetTextAsync` 为 `ClipboardExtensions.SetTextAsync`
+- **BREAKING**: 更新 `Bitmap.CopyPixels` 调用签名(移除 `AlphaFormat` 参数)
+- **BREAKING**: 替换 `FluentIcons.Avalonia.SymbolIconSource` 为 v3 等效 API
+- 修复 `MainWindow.ComponentSystem.cs` 和 `MainWindow.DesktopPaging.cs` 中缺失的字段/变量
+- 批量替换 `TextBox.Watermark` → `PlaceholderText`
+
+## Impact
+
+- 受影响代码:
+ - `LanMountainDesktop/Views/SettingsWindow.axaml.cs`
+ - `LanMountainDesktop/Views/ComponentEditorWindow.axaml.cs`
+ - `LanMountainDesktop/Views/MainWindow.ComponentSystem.cs`
+ - `LanMountainDesktop/Views/MainWindow.DesktopPaging.cs`
+ - `LanMountainDesktop/App.axaml.cs`
+ - `LanMountainDesktop/Views/Components/DesktopComponentFailureView.cs`
+ - `LanMountainDesktop/Services/MonetColorService.cs`
+ - 13 个 `.axaml` 文件(`SystemDecorations` → `WindowDecorations`)
+ - 7 个 `.cs` 文件 + 7 个 `.axaml` 文件(`Watermark` → `PlaceholderText`)
+- 受影响规格:无现有规格直接关联
+
+## ADDED Requirements
+
+### Requirement: 窗口装饰 API 迁移
+系统 SHALL 使用 Avalonia 12 的 `WindowDecorations` 属性替代已移除的 `SystemDecorations` 和 `ExtendClientAreaChromeHints`。
+
+#### Scenario: SettingsWindow 无边框模式
+- **WHEN** `ApplyChromeMode(false)` 被调用
+- **THEN** `WindowDecorations = WindowDecorations.BorderOnly` 且 `ExtendClientAreaToDecorationsHint = true`
+
+#### Scenario: SettingsWindow 系统 Chrome 模式
+- **WHEN** `ApplyChromeMode(true)` 被调用
+- **THEN** `WindowDecorations = WindowDecorations.Full` 且 `ExtendClientAreaToDecorationsHint = true`
+
+### Requirement: 剪贴板 API 迁移
+系统 SHALL 使用 Avalonia 12 的 `ClipboardExtensions.SetTextAsync` 替代已移除的 `IClipboard.SetTextAsync`。
+
+### Requirement: Bitmap.CopyPixels 签名更新
+系统 SHALL 使用新的 `CopyPixels` 签名,不再传入 `AlphaFormat` 参数。
+
+### Requirement: FluentIcons v3 API 适配
+系统 SHALL 使用 `FluentIcons.Avalonia.FluentIcon` 替代已移除的 `SymbolIconSource`。
+
+## MODIFIED Requirements
+
+### Requirement: 编译绑定验证
+- **修改前**:`BindingPlugins.DataValidators.RemoveAt(0)` 移除默认数据注解验证插件
+- **修改后**:v12 默认禁用数据注解验证插件,无需手动移除
+
+## REMOVED Requirements
+
+### Requirement: ExtendClientAreaChromeHints 配置
+**Reason**: Avalonia 12 移除此属性,由 `WindowDecorations` 统一管理
+**Migration**: 删除所有 `ExtendClientAreaChromeHints` 赋值代码
diff --git a/.trae/specs/avalonia-12-migration/tasks.md b/.trae/specs/avalonia-12-migration/tasks.md
new file mode 100644
index 0000000..dee08fc
--- /dev/null
+++ b/.trae/specs/avalonia-12-migration/tasks.md
@@ -0,0 +1,39 @@
+# Tasks
+
+- [ ] Task 1: 修复窗口装饰 API(Phase 1)
+ - [x] SubTask 1.1: 重写 `SettingsWindow.ApplyChromeMode()` 移除 `ExtendClientAreaChromeHints`
+ - [x] SubTask 1.2: 重写 `ComponentEditorWindow.ApplyChromeMode()` 移除 `ExtendClientAreaChromeHints`
+ - [x] SubTask 1.3: 批量替换所有 `.axaml` 中的 `SystemDecorations` → `WindowDecorations`
+ - [ ] SubTask 1.4: 验证构建错误减少
+
+- [ ] Task 2: 修复 MainWindow 编译错误(Phase 2)
+ - [ ] SubTask 2.1: 修复 `MainWindow.ComponentSystem.cs` 中 `centerLeft` 和 `positions` 未定义错误
+ - [ ] SubTask 2.2: 修复 `MainWindow.DesktopPaging.cs` 中 `child` 和 `_isThreeFingerOrRightDragSwipeActive` 未定义错误
+ - [ ] SubTask 2.3: 验证构建错误减少
+
+- [ ] Task 3: 修复 Avalonia 12 API 变更(Phase 3)
+ - [ ] SubTask 3.1: 移除 `App.axaml.cs` 中 `BindingPlugins.DataValidators` 代码
+ - [ ] SubTask 3.2: 替换 `DesktopComponentFailureView.cs` 中 `IClipboard.SetTextAsync` 为 `ClipboardExtensions.SetTextAsync`
+ - [ ] SubTask 3.3: 更新 `MonetColorService.cs` 中 `Bitmap.CopyPixels` 调用签名
+ - [ ] SubTask 3.4: 验证构建错误减少
+
+- [ ] Task 4: 修复第三方库变更(Phase 4)
+ - [ ] SubTask 4.1: 替换 `SettingsWindow.axaml.cs` 中 `FluentIcons.Avalonia.SymbolIconSource` 为 `FluentIcon`
+ - [ ] SubTask 4.2: 验证构建错误减少
+
+- [ ] Task 5: 清理过时属性(Phase 5)
+ - [ ] SubTask 5.1: 批量替换 `.cs` 文件中 `Watermark` → `PlaceholderText`
+ - [ ] SubTask 5.2: 批量替换 `.axaml` 文件中 `Watermark` → `PlaceholderText`
+ - [ ] SubTask 5.3: 验证无过时警告
+
+- [ ] Task 6: 最终验证
+ - [ ] SubTask 6.1: `dotnet build LanMountainDesktop.slnx -c Debug` 0 errors
+ - [ ] SubTask 6.2: `dotnet test LanMountainDesktop.slnx -c Debug` 通过
+
+# Task Dependencies
+
+- Task 2 不依赖 Task 1(可并行)
+- Task 3 不依赖 Task 1/2(可并行)
+- Task 4 不依赖 Task 1/2/3(可并行)
+- Task 5 依赖 Task 1/2/3/4(低优先级,最后执行)
+- Task 6 依赖所有前置任务
diff --git a/Directory.Packages.props b/Directory.Packages.props
index 565c4ce..d5a50d7 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -2,7 +2,6 @@
true
-
@@ -40,4 +39,4 @@
-
+
\ No newline at end of file
diff --git a/LanMountainDesktop.Launcher/Views/SplashWindow.axaml b/LanMountainDesktop.Launcher/Views/SplashWindow.axaml
index 21bac27..898038c 100644
--- a/LanMountainDesktop.Launcher/Views/SplashWindow.axaml
+++ b/LanMountainDesktop.Launcher/Views/SplashWindow.axaml
@@ -12,7 +12,7 @@
CanResize="False"
ShowInTaskbar="False"
WindowStartupLocation="CenterScreen"
- SystemDecorations="None"
+ WindowDecorations="None"
Background="#0B0B0B"
TransparencyLevelHint="None"
Icon="/Assets/logo.ico">
diff --git a/LanMountainDesktop.Launcher/Views/UpdateWindow.axaml b/LanMountainDesktop.Launcher/Views/UpdateWindow.axaml
index f2658da..e9e26e5 100644
--- a/LanMountainDesktop.Launcher/Views/UpdateWindow.axaml
+++ b/LanMountainDesktop.Launcher/Views/UpdateWindow.axaml
@@ -13,7 +13,7 @@
Height="320"
CanResize="False"
WindowStartupLocation="CenterScreen"
- SystemDecorations="None"
+ WindowDecorations="None"
Background="{DynamicResource SolidBackgroundFillColorBaseBrush}"
TransparencyLevelHint="None"
Icon="/Assets/logo.ico">
diff --git a/LanMountainDesktop/App.axaml.cs b/LanMountainDesktop/App.axaml.cs
index d8c7ac0..fc6537c 100644
--- a/LanMountainDesktop/App.axaml.cs
+++ b/LanMountainDesktop/App.axaml.cs
@@ -527,15 +527,8 @@ public partial class App : Application
private void DisableAvaloniaDataAnnotationValidation()
{
- // Get an array of plugins to remove
- var dataValidationPluginsToRemove =
- BindingPlugins.DataValidators.OfType().ToArray();
-
- // remove each entry found
- foreach (var plugin in dataValidationPluginsToRemove)
- {
- BindingPlugins.DataValidators.Remove(plugin);
- }
+ // Avalonia 12 中 BindingPlugins 已移除,数据验证插件不再需要手动禁用
+ // 编译型绑定默认开启,数据注解验证行为已改变
}
private void InitializePluginRuntime()
diff --git a/LanMountainDesktop/Services/MonetColorService.cs b/LanMountainDesktop/Services/MonetColorService.cs
index 28ed25f..4c6c88b 100644
--- a/LanMountainDesktop/Services/MonetColorService.cs
+++ b/LanMountainDesktop/Services/MonetColorService.cs
@@ -88,8 +88,6 @@ public sealed class MonetColorService
PixelFormat.Bgra8888,
AlphaFormat.Premul);
using var framebuffer = writeable.Lock();
- scaledBitmap.CopyPixels(framebuffer, AlphaFormat.Premul);
-
var byteCount = framebuffer.RowBytes * framebuffer.Size.Height;
if (byteCount <= 0 || framebuffer.Address == IntPtr.Zero)
{
@@ -97,6 +95,11 @@ public sealed class MonetColorService
}
var pixelBuffer = new byte[byteCount];
+ scaledBitmap.CopyPixels(
+ new PixelRect(scaledBitmap.PixelSize),
+ framebuffer.Address,
+ byteCount,
+ framebuffer.RowBytes);
Marshal.Copy(framebuffer.Address, pixelBuffer, 0, byteCount);
var argbPixels = new List(framebuffer.Size.Width * framebuffer.Size.Height);
diff --git a/LanMountainDesktop/Styles/GlassModule.axaml b/LanMountainDesktop/Styles/GlassModule.axaml
index a2b485f..e381d91 100644
--- a/LanMountainDesktop/Styles/GlassModule.axaml
+++ b/LanMountainDesktop/Styles/GlassModule.axaml
@@ -70,11 +70,25 @@
-
+
+
+
+
-
diff --git a/LanMountainDesktop/Views/ComponentEditorWindow.axaml b/LanMountainDesktop/Views/ComponentEditorWindow.axaml
index 05ebe35..d2ab797 100644
--- a/LanMountainDesktop/Views/ComponentEditorWindow.axaml
+++ b/LanMountainDesktop/Views/ComponentEditorWindow.axaml
@@ -16,7 +16,7 @@
CanResize="True"
SizeToContent="Manual"
ShowInTaskbar="False"
- SystemDecorations="BorderOnly"
+ WindowDecorations="BorderOnly"
Background="Transparent"
Title="Component Editor">
diff --git a/LanMountainDesktop/Views/ComponentEditorWindow.axaml.cs b/LanMountainDesktop/Views/ComponentEditorWindow.axaml.cs
index 3a7bf77..823fe3a 100644
--- a/LanMountainDesktop/Views/ComponentEditorWindow.axaml.cs
+++ b/LanMountainDesktop/Views/ComponentEditorWindow.axaml.cs
@@ -60,17 +60,13 @@ public partial class ComponentEditorWindow : Window
if (preferSystemChrome)
{
ExtendClientAreaToDecorationsHint = true;
- ExtendClientAreaChromeHints = ExtendClientAreaChromeHints.PreferSystemChrome;
- ExtendClientAreaTitleBarHeightHint = -1;
- SystemDecorations = SystemDecorations.Full;
+ WindowDecorations = WindowDecorations.Full;
CustomTitleBarHost.IsVisible = false;
return;
}
- SystemDecorations = SystemDecorations.BorderOnly;
+ WindowDecorations = WindowDecorations.BorderOnly;
ExtendClientAreaToDecorationsHint = true;
- ExtendClientAreaChromeHints = ExtendClientAreaChromeHints.NoChrome;
- ExtendClientAreaTitleBarHeightHint = 52;
CustomTitleBarHost.IsVisible = true;
}
diff --git a/LanMountainDesktop/Views/ComponentEditors/ClockComponentEditor.axaml b/LanMountainDesktop/Views/ComponentEditors/ClockComponentEditor.axaml
index 95a8525..7463781 100644
--- a/LanMountainDesktop/Views/ComponentEditors/ClockComponentEditor.axaml
+++ b/LanMountainDesktop/Views/ComponentEditors/ClockComponentEditor.axaml
@@ -41,13 +41,11 @@
ColumnSpacing="4">
+ IsCheckedChanged="OnSecondHandChanged" />
+ IsCheckedChanged="OnSecondHandChanged" />
diff --git a/LanMountainDesktop/Views/ComponentEditors/ShortcutComponentEditor.axaml b/LanMountainDesktop/Views/ComponentEditors/ShortcutComponentEditor.axaml
index 211fa59..4519a6c 100644
--- a/LanMountainDesktop/Views/ComponentEditors/ShortcutComponentEditor.axaml
+++ b/LanMountainDesktop/Views/ComponentEditors/ShortcutComponentEditor.axaml
@@ -1,4 +1,4 @@
-
+ IsCheckedChanged="OnEnabledChanged" />
diff --git a/LanMountainDesktop/Views/ComponentEditors/WorldClockComponentEditor.axaml b/LanMountainDesktop/Views/ComponentEditors/WorldClockComponentEditor.axaml
index ef81d94..26ef749 100644
--- a/LanMountainDesktop/Views/ComponentEditors/WorldClockComponentEditor.axaml
+++ b/LanMountainDesktop/Views/ComponentEditors/WorldClockComponentEditor.axaml
@@ -77,13 +77,11 @@
ColumnSpacing="4">
+ IsCheckedChanged="OnSecondHandChanged" />
+ IsCheckedChanged="OnSecondHandChanged" />
diff --git a/LanMountainDesktop/Views/ComponentLibraryWindow.axaml b/LanMountainDesktop/Views/ComponentLibraryWindow.axaml
index 4d45fbb..01dc56b 100644
--- a/LanMountainDesktop/Views/ComponentLibraryWindow.axaml
+++ b/LanMountainDesktop/Views/ComponentLibraryWindow.axaml
@@ -9,7 +9,7 @@
MinWidth="760"
MinHeight="500"
CanResize="True"
- SystemDecorations="Full"
+ WindowDecorations="Full"
Title="Component Library"
Background="{DynamicResource AdaptiveSurfaceBaseBrush}">
diff --git a/LanMountainDesktop/Views/Components/BrowserWidget.axaml b/LanMountainDesktop/Views/Components/BrowserWidget.axaml
index b6c6ede..995af94 100644
--- a/LanMountainDesktop/Views/Components/BrowserWidget.axaml
+++ b/LanMountainDesktop/Views/Components/BrowserWidget.axaml
@@ -1,4 +1,4 @@
-
diff --git a/LanMountainDesktop/Views/Components/DesktopComponentFailureView.cs b/LanMountainDesktop/Views/Components/DesktopComponentFailureView.cs
index 245c15b..295af0b 100644
--- a/LanMountainDesktop/Views/Components/DesktopComponentFailureView.cs
+++ b/LanMountainDesktop/Views/Components/DesktopComponentFailureView.cs
@@ -4,6 +4,7 @@ using System.Text;
using System.Threading.Tasks;
using Avalonia;
using Avalonia.Controls;
+using Avalonia.Input.Platform;
using Avalonia.Interactivity;
using Avalonia.Layout;
using Avalonia.Media;
diff --git a/LanMountainDesktop/Views/Components/StudySessionHistoryWidget.axaml b/LanMountainDesktop/Views/Components/StudySessionHistoryWidget.axaml
index fcd40d7..741822c 100644
--- a/LanMountainDesktop/Views/Components/StudySessionHistoryWidget.axaml
+++ b/LanMountainDesktop/Views/Components/StudySessionHistoryWidget.axaml
@@ -1,4 +1,4 @@
-
_desktopComponentPlacements = [];
private readonly Dictionary _desktopPageComponentGrids = new();
@@ -755,7 +755,8 @@ public partial class MainWindow
return false;
// 闁荤姳绶ょ槐鏇㈡偩缂佹鈻旀い鎾卞灪閿涚喖鏌涢弽褎鎯堥柣鎾寸懇閹啴宕熼銈嗘緰闂傚倸瀚幊宥囩礊閸涱垳纾? // 閻庡綊娼荤粻鎴﹀垂椤忓牆鍙?*, 婵炴垶鎼╅崢濂稿垂椤忓牆鍙?Auto, 闂佸憡鐟ラ崯鍧楀垂椤忓牆鍙?*
- // 婵炴垶鎼╅崣鍐ㄎ涢崸妤€绀岄柛婵嗗閸樼敻鎮橀悙鍙夊櫢闁煎灚鍨垮浼村礈瑜嬫禒? var centerLeft = (totalWidth - centerWidth) / 2;
+ // 婵炴垶鎼╅崣鍐ㄎ涢崸妤€绀岄柛婵嗗閸樼敻鎮橀悙鍙夊櫢闁煎灚鍨垮浼村礈瑜嬫禒?
+ var centerLeft = (totalWidth - centerWidth) / 2;
var centerRight = centerLeft + centerWidth;
// 闁诲海鎳撻ˇ顖炲矗韫囨稒鈷掔痪鎯ь儑閻涒晠鏌ㄥ☉妯煎闁稿孩姘ㄥΣ鎰版偑閸涱垳顦?
@@ -1262,7 +1263,8 @@ public partial class MainWindow
/// 闂佸搫琚崕鍙夌珶濮椻偓瀹曪綁顢涘鍕闂佹眹鍔岀€氼厼霉濞戞瑧顩烽柨婵嗗缁夊绱? ///
private string? FindAlternativePosition(string originalPosition)
{
- // 闁诲繐绻戠换鍡涙儊椤栫偛绠ラ柍褜鍓熷鍨緞婵犲倽顔夐梺鐓庣-閺咁偄鈻撻幋鐐村鐎广儱娲ㄩ弸? var positions = new[] { "Left", "Center", "Right" };
+ // 闁诲繐绻戠换鍡涙儊椤栫偛绠ラ柍褜鍓熷鍨緞婵犲倽顔夐梺鐓庣-閺咁偄鈻撻幋鐐村鐎广儱娲ㄩ弸?
+ var positions = new[] { "Left", "Center", "Right" };
foreach (var position in positions)
{
if (position != originalPosition && CanAddComponentAtPosition(position))
diff --git a/LanMountainDesktop/Views/MainWindow.DesktopEditing.cs b/LanMountainDesktop/Views/MainWindow.DesktopEditing.cs
index 2d0f65f..68f4447 100644
--- a/LanMountainDesktop/Views/MainWindow.DesktopEditing.cs
+++ b/LanMountainDesktop/Views/MainWindow.DesktopEditing.cs
@@ -12,7 +12,7 @@ using LanMountainDesktop.Theme;
namespace LanMountainDesktop.Views;
-public partial class MainWindow
+public partial class MainWindow : Window
{
private static readonly TimeSpan DesktopEditCommitAnimationDuration = FluttermotionToken.Standard;
private static readonly TimeSpan DesktopEditCancelAnimationDuration = FluttermotionToken.Fast;
diff --git a/LanMountainDesktop/Views/MainWindow.DesktopPaging.cs b/LanMountainDesktop/Views/MainWindow.DesktopPaging.cs
index d887e69..83a0204 100644
--- a/LanMountainDesktop/Views/MainWindow.DesktopPaging.cs
+++ b/LanMountainDesktop/Views/MainWindow.DesktopPaging.cs
@@ -22,7 +22,7 @@ using LanMountainDesktop.Theme;
namespace LanMountainDesktop.Views;
-public partial class MainWindow
+public partial class MainWindow : Window
{
private const int MinDesktopPageCount = 1;
private const int MaxDesktopPageCount = 12;
@@ -75,7 +75,8 @@ public partial class MainWindow
private int? _desktopPageContextSettlingTargetIndex;
private int _desktopPageContextSettleRevision;
- // 婵犵數鍋為崹鍫曞箰閹间絸鍥箥椤旂懓浜鹃柛顭戝亯婢规ɑ銇勯婊冨妤犵偛顑呴埞鎴﹀窗?闂傚倷绀侀幉锟犳偡閿旂晫绠惧┑鐘叉搐閺嬩焦銇勯幘鍗炵仼缂佺媭鍨堕弻鈥崇暤椤旂厧鏁俊銈呮噺閻撶喖鏌嶉崫鍕灓闁绘帡绠栭弻? private bool _isThreeFingerOrRightDragSwipeActive;
+ // 婵犵數鍋為崹鍫曞箰閹间絸鍥箥椤旂懓浜鹃柛顭戝亯婢规ɑ銇勯婊冨妤犵偛顑呴埞鎴﹀窗?闂傚倷绀侀幉锟犳偡閿旂晫绠惧┑鐘叉搐閺嬩焦銇勯幘鍗炵仼缂佺媭鍨堕弻鈥崇暤椤旂厧鏁俊銈呮噺閻撶喖鏌嶉崫鍕灓闁绘帡绠栭弻?
+ private bool _isThreeFingerOrRightDragSwipeActive;
private readonly HashSet _activePointerIds = [];
private int LauncherSurfaceIndex => Math.Max(MinDesktopPageCount, _desktopPageCount);
@@ -307,7 +308,8 @@ public partial class MainWindow
// 闂傚倷绀侀幖顐⒚洪妶澶嬪仱闁靛ň鏅涢拑鐔封攽閸屻倖杈渁pPanel闂傚倷鐒﹂惇褰掑礉瀹€鍕惞婵帞妫渕闂備浇顕х换鎰崲閹版澘绠规い鎰跺瘜閺? LauncherRootTilePanel.Width = availableWidth;
- // 闂傚倷绀侀幖顐⒚洪妶澶嬪仱闁靛ň鏅涢拑鐔封攽閻樺弶鎼愮紒鐘劦閺屽秷顧侀柛鎾跺枎椤曪綁宕归銏㈢獮婵犵數濮寸€氼參骞夐妶澶嬧拺缂佸娉曠粻浼存煕閻旂顥嬬紒顔肩墕閻f繈宕熼鈧崜顓㈡⒑閸涘﹥澶勯柛瀣噹鍗遍柍褜鍓熼弻? foreach (var child in LauncherRootTilePanel.Children)
+ // 闂傚倷绀侀幖顐⒚洪妶澶嬪仱闁靛ň鏅涢拑鐔封攽閻樺弶鎼愮紒鐘劦閺屽秷顧侀柛鎾跺枎椤曪綁宕归銏㈢獮婵犵數濮寸€氼參骞夐妶澶嬧拺缂佸娉曠粻浼存煕閻旂顥嬬紒顔肩墕閻f繈宕熼鈧崜顓㈡⒑閸涘﹥澶勯柛瀣噹鍗遍柍褜鍓熼弻?
+ foreach (var child in LauncherRootTilePanel.Children)
{
if (child is Button button)
{
diff --git a/LanMountainDesktop/Views/MainWindow.RenderBackend.cs b/LanMountainDesktop/Views/MainWindow.RenderBackend.cs
index aef13b9..504968e 100644
--- a/LanMountainDesktop/Views/MainWindow.RenderBackend.cs
+++ b/LanMountainDesktop/Views/MainWindow.RenderBackend.cs
@@ -1,9 +1,10 @@
using System;
+using Avalonia.Controls;
using LanMountainDesktop.Services;
namespace LanMountainDesktop.Views;
-public partial class MainWindow
+public partial class MainWindow : Window
{
private void UpdateCurrentRenderBackendStatus()
{
diff --git a/LanMountainDesktop/Views/MainWindow.SettingsHardCut.Stubs.cs b/LanMountainDesktop/Views/MainWindow.SettingsHardCut.Stubs.cs
index 413cad6..e44b96b 100644
--- a/LanMountainDesktop/Views/MainWindow.SettingsHardCut.Stubs.cs
+++ b/LanMountainDesktop/Views/MainWindow.SettingsHardCut.Stubs.cs
@@ -20,7 +20,7 @@ using LanMountainDesktop.Views.Components;
namespace LanMountainDesktop.Views;
-public partial class MainWindow
+public partial class MainWindow : Window
{
private TextBlock? CurrentRenderBackendLabelTextBlock => this.FindControl("CurrentRenderBackendLabelTextBlock");
private TextBlock? CurrentRenderBackendValueTextBlock => this.FindControl("CurrentRenderBackendValueTextBlock");
diff --git a/LanMountainDesktop/Views/MainWindow.SingleInstanceNotice.cs b/LanMountainDesktop/Views/MainWindow.SingleInstanceNotice.cs
index 15bacc9..4c5eb1b 100644
--- a/LanMountainDesktop/Views/MainWindow.SingleInstanceNotice.cs
+++ b/LanMountainDesktop/Views/MainWindow.SingleInstanceNotice.cs
@@ -1,11 +1,12 @@
using System.Threading.Tasks;
+using Avalonia.Controls;
using Avalonia.Threading;
using FluentAvalonia.UI.Controls;
using LanMountainDesktop.Services;
namespace LanMountainDesktop.Views;
-public partial class MainWindow
+public partial class MainWindow : Window
{
private bool _isSingleInstancePromptVisible;
diff --git a/LanMountainDesktop/Views/MainWindow.axaml b/LanMountainDesktop/Views/MainWindow.axaml
index 3cb622d..d193249 100644
--- a/LanMountainDesktop/Views/MainWindow.axaml
+++ b/LanMountainDesktop/Views/MainWindow.axaml
@@ -15,7 +15,7 @@
x:Class="LanMountainDesktop.Views.MainWindow"
x:DataType="vm:MainWindowViewModel"
WindowState="FullScreen"
- SystemDecorations="None"
+ WindowDecorations="None"
CanResize="False"
UseLayoutRounding="True"
Foreground="{DynamicResource AdaptiveTextPrimaryBrush}"
diff --git a/LanMountainDesktop/Views/NotificationDialogWindow.axaml b/LanMountainDesktop/Views/NotificationDialogWindow.axaml
index b33c307..08d1656 100644
--- a/LanMountainDesktop/Views/NotificationDialogWindow.axaml
+++ b/LanMountainDesktop/Views/NotificationDialogWindow.axaml
@@ -4,7 +4,7 @@
xmlns:vm="using:LanMountainDesktop.Views"
x:Class="LanMountainDesktop.Views.NotificationDialogWindow"
x:DataType="vm:NotificationDialogViewModel"
- SystemDecorations="None"
+ WindowDecorations="None"
Background="Transparent"
ShowInTaskbar="False"
Topmost="True"
@@ -12,7 +12,6 @@
SizeToContent="WidthAndHeight"
TransparencyLevelHint="Transparent"
ExtendClientAreaToDecorationsHint="True"
- ExtendClientAreaChromeHints="NoChrome"
ExtendClientAreaTitleBarHeightHint="-1">
diff --git a/LanMountainDesktop/Views/SettingsPages/AboutSettingsPage.axaml b/LanMountainDesktop/Views/SettingsPages/AboutSettingsPage.axaml
index 6527a78..e31fd93 100644
--- a/LanMountainDesktop/Views/SettingsPages/AboutSettingsPage.axaml
+++ b/LanMountainDesktop/Views/SettingsPages/AboutSettingsPage.axaml
@@ -1,4 +1,4 @@
-
-
+
@@ -77,14 +77,14 @@
Title="{Binding CodenameLabel}"
Message="{Binding CodenameText}">
-
+
-
+
diff --git a/LanMountainDesktop/Views/SettingsPages/AppearanceSettingsPage.axaml b/LanMountainDesktop/Views/SettingsPages/AppearanceSettingsPage.axaml
index a776ffc..d5e1716 100644
--- a/LanMountainDesktop/Views/SettingsPages/AppearanceSettingsPage.axaml
+++ b/LanMountainDesktop/Views/SettingsPages/AppearanceSettingsPage.axaml
@@ -1,4 +1,4 @@
-
-
+
-
+
@@ -43,7 +43,7 @@
-
+
-
+
-
+
diff --git a/LanMountainDesktop/Views/SettingsPages/ComponentsSettingsPage.axaml b/LanMountainDesktop/Views/SettingsPages/ComponentsSettingsPage.axaml
index df50454..be52bd3 100644
--- a/LanMountainDesktop/Views/SettingsPages/ComponentsSettingsPage.axaml
+++ b/LanMountainDesktop/Views/SettingsPages/ComponentsSettingsPage.axaml
@@ -1,4 +1,4 @@
-
-
+
@@ -76,7 +76,7 @@
-
+
diff --git a/LanMountainDesktop/Views/SettingsPages/DevSettingsPage.axaml b/LanMountainDesktop/Views/SettingsPages/DevSettingsPage.axaml
index 051b53a..74d1ba2 100644
--- a/LanMountainDesktop/Views/SettingsPages/DevSettingsPage.axaml
+++ b/LanMountainDesktop/Views/SettingsPages/DevSettingsPage.axaml
@@ -1,4 +1,4 @@
-
-
+
-
+
@@ -31,7 +31,7 @@
-
+
@@ -41,7 +41,7 @@
-
+
@@ -53,11 +53,11 @@
-
+
@@ -68,7 +68,7 @@
-
+
-
+
-
+
-
+
-
+
-
+
-
+
@@ -129,7 +129,7 @@
-
+
diff --git a/LanMountainDesktop/Views/SettingsPages/LauncherSettingsPage.axaml b/LanMountainDesktop/Views/SettingsPages/LauncherSettingsPage.axaml
index c24c7f5..b259dbd 100644
--- a/LanMountainDesktop/Views/SettingsPages/LauncherSettingsPage.axaml
+++ b/LanMountainDesktop/Views/SettingsPages/LauncherSettingsPage.axaml
@@ -1,4 +1,4 @@
-
-
+
@@ -85,7 +85,7 @@
Description="{Binding HiddenDescription}"
IsExpanded="True">
-
+
@@ -103,7 +103,7 @@
Description="{Binding TypeLabel}"
IsClickEnabled="False">
-
+
-
-
+
@@ -147,7 +147,7 @@
-
+
@@ -239,7 +239,7 @@
-
+
-
-
+
diff --git a/LanMountainDesktop/Views/SettingsPages/StudySettingsPage.axaml b/LanMountainDesktop/Views/SettingsPages/StudySettingsPage.axaml
index f943775..bbf659b 100644
--- a/LanMountainDesktop/Views/SettingsPages/StudySettingsPage.axaml
+++ b/LanMountainDesktop/Views/SettingsPages/StudySettingsPage.axaml
@@ -1,4 +1,4 @@
-
-
+
@@ -26,7 +26,7 @@
Description="{Binding NoiseMonitoringDescription}"
IsEnabled="{Binding StudyEnabled}">
-
+
@@ -93,7 +93,7 @@
Description="{Binding FocusTimerDescription}"
IsEnabled="{Binding StudyEnabled}">
-
+
@@ -231,7 +231,7 @@
Description="{Binding AlertDescription}"
IsEnabled="{Binding StudyEnabled}">
-
+
@@ -273,7 +273,7 @@
Description="{Binding DisplayDescription}"
IsEnabled="{Binding StudyEnabled}">
-
+
diff --git a/LanMountainDesktop/Views/SettingsPages/UpdateSettingsPage.axaml b/LanMountainDesktop/Views/SettingsPages/UpdateSettingsPage.axaml
index 6aa2141..c6dc7b2 100644
--- a/LanMountainDesktop/Views/SettingsPages/UpdateSettingsPage.axaml
+++ b/LanMountainDesktop/Views/SettingsPages/UpdateSettingsPage.axaml
@@ -1,4 +1,4 @@
-
-
+
-
+
@@ -194,7 +194,7 @@
Header="{Binding UpdateSourceLabel}"
Description="{Binding SelectedUpdateSourceDescription}">
-
+
-
+
-
+
-
-
+
-
+
-
+
-
+
-
+
-
-
+
-
+
-
-
+ Glyph=""
+ FontFamily="avares://fluenticons.resources.avalonia/Assets#Seagull Fluent Icons" />
-
+
@@ -200,7 +201,7 @@
Header="{Binding LocationServicesHeader}"
Description="{Binding LocationServicesDescription}">
-
+
-
-
+
-
+
diff --git a/LanMountainDesktop/Views/SettingsWindow.axaml b/LanMountainDesktop/Views/SettingsWindow.axaml
index a30765c..d95e0b2 100644
--- a/LanMountainDesktop/Views/SettingsWindow.axaml
+++ b/LanMountainDesktop/Views/SettingsWindow.axaml
@@ -11,7 +11,7 @@
MinHeight="480"
CanResize="True"
WindowStartupLocation="Manual"
- SystemDecorations="BorderOnly"
+ WindowDecorations="BorderOnly"
FontFamily="{DynamicResource AppFontFamily}"
Background="Transparent"
Title="{Binding Title}">
diff --git a/LanMountainDesktop/Views/SettingsWindow.axaml.cs b/LanMountainDesktop/Views/SettingsWindow.axaml.cs
index 4c43099..d3c7960 100644
--- a/LanMountainDesktop/Views/SettingsWindow.axaml.cs
+++ b/LanMountainDesktop/Views/SettingsWindow.axaml.cs
@@ -163,9 +163,7 @@ public partial class SettingsWindow : Window, ISettingsPageHostContext
if (_useSystemChrome)
{
ExtendClientAreaToDecorationsHint = true;
- ExtendClientAreaChromeHints = ExtendClientAreaChromeHints.PreferSystemChrome;
- ExtendClientAreaTitleBarHeightHint = -1;
- SystemDecorations = SystemDecorations.Full;
+ WindowDecorations = WindowDecorations.Full;
if (WindowTitleBarHost is { })
{
@@ -174,10 +172,8 @@ public partial class SettingsWindow : Window, ISettingsPageHostContext
return;
}
- SystemDecorations = SystemDecorations.BorderOnly;
+ WindowDecorations = WindowDecorations.BorderOnly;
ExtendClientAreaToDecorationsHint = true;
- ExtendClientAreaChromeHints = ExtendClientAreaChromeHints.NoChrome;
- ExtendClientAreaTitleBarHeightHint = 48;
if (WindowTitleBarHost is { })
{
@@ -212,11 +208,7 @@ public partial class SettingsWindow : Window, ISettingsPageHostContext
{
Content = page.Title,
Tag = page.PageId,
- IconSource = new FluentIcons.Avalonia.SymbolIconSource
- {
- Symbol = MapIcon(page.IconKey),
- IconVariant = FluentIcons.Common.IconVariant.Regular
- }
+ IconSource = CreateSettingsIconSource(MapIcon(page.IconKey))
});
previousCategory = page.Category;
@@ -748,4 +740,29 @@ public partial class SettingsWindow : Window, ISettingsPageHostContext
_ => Symbol.Settings
};
}
+
+ private static FAFontIconSource CreateSettingsIconSource(Symbol symbol)
+ {
+ var symbolIcon = new FluentIcons.Avalonia.SymbolIcon
+ {
+ Symbol = symbol,
+ IconVariant = FluentIcons.Common.IconVariant.Regular
+ };
+
+ // 使用反射获取 IconText 和 IconFont
+ var iconTextProp = typeof(FluentIcons.Avalonia.SymbolIcon).GetProperty("IconText", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
+ var iconFontProp = typeof(FluentIcons.Avalonia.SymbolIcon).GetProperty("IconFont", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
+
+ var iconText = iconTextProp?.GetValue(symbolIcon) as string ?? "?";
+ var iconFont = iconFontProp?.GetValue(symbolIcon);
+ var fontFamily = iconFont?.GetType().GetProperty("FontFamily")?.GetValue(iconFont) as Avalonia.Media.FontFamily
+ ?? new Avalonia.Media.FontFamily("avares://fluenticons.resources.avalonia/Assets#Seagull Fluent Icons");
+
+ return new FAFontIconSource
+ {
+ Glyph = iconText,
+ FontFamily = fontFamily,
+ FontSize = 16
+ };
+ }
}
diff --git a/LanMountainDesktop/Views/StudySessionReportWindow.axaml b/LanMountainDesktop/Views/StudySessionReportWindow.axaml
index e90a7c7..fd3b6f8 100644
--- a/LanMountainDesktop/Views/StudySessionReportWindow.axaml
+++ b/LanMountainDesktop/Views/StudySessionReportWindow.axaml
@@ -3,7 +3,7 @@
xmlns:fi="using:FluentIcons.Avalonia"
x:Class="LanMountainDesktop.Views.StudySessionReportWindow"
x:CompileBindings="False"
- SystemDecorations="None"
+ WindowDecorations="None"
Background="Transparent"
ShowInTaskbar="False"
Topmost="True"
@@ -12,7 +12,6 @@
Height="600"
TransparencyLevelHint="Transparent"
ExtendClientAreaToDecorationsHint="True"
- ExtendClientAreaChromeHints="NoChrome"
ExtendClientAreaTitleBarHeightHint="-1"
WindowStartupLocation="CenterOwner">
diff --git a/LanMountainDesktop/Views/TransparentOverlayWindow.axaml b/LanMountainDesktop/Views/TransparentOverlayWindow.axaml
index c75ef4a..c6cd809 100644
--- a/LanMountainDesktop/Views/TransparentOverlayWindow.axaml
+++ b/LanMountainDesktop/Views/TransparentOverlayWindow.axaml
@@ -1,11 +1,10 @@