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 @@ -