From 2a1c09ae393b94d32e2d4d5bff2906506acdd0cd Mon Sep 17 00:00:00 2001 From: lincube Date: Sat, 21 Mar 2026 13:08:20 +0800 Subject: [PATCH] 0.7.2 --- .github/workflows/build.yml | 28 + .../remove-video-wallpaper-feature/design.md | 578 ----------------- .../remove-video-wallpaper-feature/spec.md | 206 ------ .../remove-video-wallpaper-feature/tasks.md | 600 ------------------ .../LanMountainDesktop.PluginSdk.csproj | 16 +- LanMountainDesktop.PluginSdk/README.md | 21 + .../LanMountainDesktop.PluginSdk.props | 14 + .../LanMountainDesktop.PluginSdk.targets | 51 ++ .../LanMountainDesktop.PluginTemplate.csproj | 25 + LanMountainDesktop.PluginTemplate/README.md | 17 + .../content/.template.config/template.json | 55 ++ .../LanMountainDesktop.PluginTemplate.csproj | 19 + .../content/Localization/en-US.json | 2 + .../content/Localization/zh-CN.json | 2 + .../content/Plugin.cs | 15 + .../content/README.md | 24 + .../content/plugin.json | 10 + ...LanMountainDesktop.Shared.Contracts.csproj | 12 + LanMountainDesktop.Shared.Contracts/README.md | 16 + LanMountainDesktop.slnx | 1 + PRODUCT_BRIEF.md | 57 +- README.md | 8 + scripts/Pack-PluginPackages.ps1 | 57 ++ 23 files changed, 398 insertions(+), 1436 deletions(-) delete mode 100644 LanMontainDesktop/.trae/specs/remove-video-wallpaper-feature/design.md delete mode 100644 LanMontainDesktop/.trae/specs/remove-video-wallpaper-feature/spec.md delete mode 100644 LanMontainDesktop/.trae/specs/remove-video-wallpaper-feature/tasks.md create mode 100644 LanMountainDesktop.PluginSdk/README.md create mode 100644 LanMountainDesktop.PluginSdk/buildTransitive/LanMountainDesktop.PluginSdk.props create mode 100644 LanMountainDesktop.PluginSdk/buildTransitive/LanMountainDesktop.PluginSdk.targets create mode 100644 LanMountainDesktop.PluginTemplate/LanMountainDesktop.PluginTemplate.csproj create mode 100644 LanMountainDesktop.PluginTemplate/README.md create mode 100644 LanMountainDesktop.PluginTemplate/content/.template.config/template.json create mode 100644 LanMountainDesktop.PluginTemplate/content/LanMountainDesktop.PluginTemplate.csproj create mode 100644 LanMountainDesktop.PluginTemplate/content/Localization/en-US.json create mode 100644 LanMountainDesktop.PluginTemplate/content/Localization/zh-CN.json create mode 100644 LanMountainDesktop.PluginTemplate/content/Plugin.cs create mode 100644 LanMountainDesktop.PluginTemplate/content/README.md create mode 100644 LanMountainDesktop.PluginTemplate/content/plugin.json create mode 100644 LanMountainDesktop.Shared.Contracts/README.md create mode 100644 scripts/Pack-PluginPackages.ps1 diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 1c08ff3..4409015 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -113,3 +113,31 @@ jobs: path: | LanMountainDesktop/bin/Release/ retention-days: 7 + + pack-plugin-packages: + runs-on: ubuntu-latest + name: Pack_Plugin_Packages + + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + submodules: recursive + + - name: Setup .NET + uses: actions/setup-dotnet@v4 + with: + dotnet-version: ${{ env.DOTNET_VERSION }} + + - name: Pack SDK and template packages + shell: pwsh + run: .\scripts\Pack-PluginPackages.ps1 -Configuration Release -OutputPath .\artifacts\nuget + + - name: Upload plugin package artifacts + uses: actions/upload-artifact@v4 + with: + name: plugin-packages + path: artifacts/nuget/*.nupkg + if-no-files-found: error + retention-days: 14 diff --git a/LanMontainDesktop/.trae/specs/remove-video-wallpaper-feature/design.md b/LanMontainDesktop/.trae/specs/remove-video-wallpaper-feature/design.md deleted file mode 100644 index 67a8a5c..0000000 --- a/LanMontainDesktop/.trae/specs/remove-video-wallpaper-feature/design.md +++ /dev/null @@ -1,578 +0,0 @@ -# 移除视频壁纸功能 - 技术设计文档 - -## 1. 概述 - -### 1.1 设计目标 - -本设计文档描述如何从 LanMountainDesktop 项目中完全移除视频壁纸功能,包括: -- 移除 LibVLC 相关依赖 -- 清理主窗口中的视频壁纸代码 -- 简化壁纸设置页面 -- 清理本地化资源 - -### 1.2 技术约束 - -- 保持现有图片壁纸和纯色壁纸功能完整 -- 确保应用构建和运行正常 -- 不引入新的外部依赖 - ---- - -## 2. 架构变更 - -### 2.1 变更概览图 - -``` -┌─────────────────────────────────────────────────────────────────┐ -│ 变更前架构 │ -├─────────────────────────────────────────────────────────────────┤ -│ MainWindow │ -│ ├── DesktopWallpaperLayer (背景层) │ -│ │ ├── DesktopWallpaperImageLayer (图片层) │ -│ │ ├── DesktopVideoWallpaperImage (视频海报层) │ -│ │ └── DesktopVideoWallpaperView (VLC视频播放层) │ -│ ├── _libVlc, _videoWallpaperPlayer, _videoWallpaperMedia │ -│ └── StartVideoWallpaper(), StopVideoWallpaper() │ -│ │ -│ WallpaperSettingsPage │ -│ ├── 类型选择: Image | Video | SolidColor │ -│ └── 视频预览区域 │ -└─────────────────────────────────────────────────────────────────┘ - -┌─────────────────────────────────────────────────────────────────┐ -│ 变更后架构 │ -├─────────────────────────────────────────────────────────────────┤ -│ MainWindow │ -│ ├── DesktopWallpaperLayer (背景层) │ -│ │ └── DesktopWallpaperImageLayer (图片层) │ -│ └── (移除所有视频相关字段和方法) │ -│ │ -│ WallpaperSettingsPage │ -│ ├── 类型选择: Image | SolidColor │ -│ └── (移除视频预览区域) │ -└─────────────────────────────────────────────────────────────────┘ -``` - -### 2.2 组件变更清单 - -| 组件 | 变更类型 | 说明 | -|------|----------|------| -| LanMountainDesktop.csproj | 修改 | 移除 LibVLC 包引用 | -| MainWindow.axaml | 修改 | 移除视频控件和命名空间 | -| MainWindow.axaml.cs | 修改 | 移除视频相关字段和清理代码 | -| MainWindow.SettingsHardCut.Stubs.cs | 修改 | 移除视频壁纸方法 | -| AppearanceThemeService.cs | 修改 | 移除视频种子提取器 | -| WallpaperSettingsPage.axaml | 修改 | 移除视频类型UI | -| WallpaperSettingsPageViewModel.cs | 修改 | 移除视频相关属性 | -| SettingsContracts.cs | 修改 | 移除 Video 枚举值 | -| SettingsDomainServices.cs | 修改 | 移除视频扩展名检测 | -| zh-CN.json | 修改 | 移除视频相关本地化文本 | - ---- - -## 3. 详细设计 - -### 3.1 项目依赖变更 (LanMountainDesktop.csproj) - -#### 3.1.1 移除的包引用 - -```xml - - - - -``` - -#### 3.1.2 变更影响 - -- 减少约 100MB+ 的依赖包大小 -- 简化构建和发布流程 -- 移除平台特定的原生库依赖 - ---- - -### 3.2 主窗口 XAML 变更 (MainWindow.axaml) - -#### 3.2.1 移除命名空间声明 - -```xml - -xmlns:vlc="clr-namespace:LibVLCSharp.Avalonia;assembly=LibVLCSharp.Avalonia" -``` - -#### 3.2.2 移除视频壁纸控件 - -移除以下控件(约第126-137行): - -```xml - - - - - -``` - ---- - -### 3.3 主窗口代码变更 (MainWindow.axaml.cs) - -#### 3.3.1 移除 using 声明 - -```csharp -// 移除以下 using(如果存在) -using LibVLCSharp.Shared; -using LibVLCSharp.Avalonia; -``` - -#### 3.3.2 移除静态字段 - -```csharp -// 移除以下字段(约第68-71行) -private static readonly HashSet SupportedVideoExtensions = new(StringComparer.OrdinalIgnoreCase) -{ - ".mp4", ".mkv", ".webm", ".avi", ".mov", ".m4v" -}; -``` - -#### 3.3.3 移除实例字段 - -```csharp -// 移除以下字段(约第123-146行) -private Bitmap? _videoWallpaperPosterBitmap; -private string? _videoWallpaperPosterPath; -private string? _wallpaperVideoPath; -private LibVLC? _libVlc; -private MediaPlayer? _videoWallpaperPlayer; -private Media? _videoWallpaperMedia; -private readonly object _desktopVideoFrameSync = new(); -private MediaPlayer.LibVLCVideoLockCb? _desktopVideoLockCallback; -private MediaPlayer.LibVLCVideoUnlockCb? _desktopVideoUnlockCallback; -private MediaPlayer.LibVLCVideoDisplayCb? _desktopVideoDisplayCallback; -private DispatcherTimer? _desktopVideoFrameRefreshTimer; -private IntPtr _desktopVideoFrameBufferPtr; -private byte[]? _desktopVideoStagingBuffer; -private WriteableBitmap? _desktopVideoBitmap; -private int _desktopVideoFrameWidth; -private int _desktopVideoFrameHeight; -private int _desktopVideoFramePitch; -private int _desktopVideoFrameBufferSize; -private int _desktopVideoFrameDirtyFlag; -``` - -#### 3.3.4 修改 OnClosed 方法 - -移除视频相关清理代码(约第336-350行): - -```csharp -// 移除以下代码行 -StopVideoWallpaper(); -_videoWallpaperMedia?.Dispose(); -_videoWallpaperMedia = null; -_videoWallpaperPlayer?.Dispose(); -_videoWallpaperPlayer = null; -_desktopVideoFrameRefreshTimer?.Stop(); -_desktopVideoFrameRefreshTimer = null; -_videoWallpaperPosterBitmap?.Dispose(); -_videoWallpaperPosterBitmap = null; -_videoWallpaperPosterPath = null; -_libVlc?.Dispose(); -_libVlc = null; -``` - ---- - -### 3.4 主窗口 Stub 方法变更 (MainWindow.SettingsHardCut.Stubs.cs) - -#### 3.4.1 移除 using 声明 - -```csharp -// 移除以下 using(第19-20行) -using LibVLCSharp.Shared; -using LibVLCSharp.Avalonia; -``` - -#### 3.4.2 移除方法 - -移除以下完整方法: - -| 方法名 | 行号范围 | 说明 | -|--------|----------|------| -| `StartVideoWallpaper` | 337-383 | 启动视频壁纸播放 | -| `StopVideoWallpaper` | 385-395 | 停止视频壁纸播放 | -| `TryCaptureVideoWallpaperPosterFrame` | 666-751 | 捕获视频海报帧 | -| `ApplyVideoWallpaperPosterVisibility` | 647-664 | 控制视频海报可见性 | - -#### 3.4.3 修改 UpdateWallpaperDisplay 方法 - -简化为仅处理图片壁纸: - -```csharp -private void UpdateWallpaperDisplay() -{ - // 移除视频分支,仅保留图片处理 - StopVideoWallpaper(); // 移除此调用 - ApplyWallpaperBrush(); -} -``` - -修改后: - -```csharp -private void UpdateWallpaperDisplay() -{ - ApplyWallpaperBrush(); -} -``` - -#### 3.4.4 修改 ApplyWallpaperBrush 方法 - -移除所有 `ApplyVideoWallpaperPosterVisibility` 调用: - -```csharp -// 移除以下调用 -ApplyVideoWallpaperPosterVisibility(showPoster: false); -ApplyVideoWallpaperPosterVisibility(showPoster: _videoWallpaperPosterBitmap is not null); -``` - -#### 3.4.5 修改 SetWallpaperState 方法 - -移除视频类型处理分支(约第238-247行): - -```csharp -// 移除以下代码块 -var requestedTypeIsVideo = string.Equals(_wallpaperType, "Video", StringComparison.OrdinalIgnoreCase); -if (SupportedVideoExtensions.Contains(extension) || requestedTypeIsVideo) -{ - _wallpaperMediaType = WallpaperMediaType.Video; - _wallpaperVideoPath = _wallpaperPath; - _wallpaperDisplayState = File.Exists(_wallpaperPath) - ? WallpaperDisplayState.CurrentValidWallpaper - : WallpaperDisplayState.TemporarilyUnavailable; - return; -} -``` - ---- - -### 3.5 外观主题服务变更 (AppearanceThemeService.cs) - -#### 3.5.1 移除接口和类 - -移除以下代码(约第92-184行): - -```csharp -// 移除接口 -internal interface IVideoWallpaperSeedExtractor -{ - IReadOnlyList ExtractSeedCandidates(string videoPath, MonetColorService monetColorService); -} - -// 移除实现类 -internal sealed class LibVlcVideoWallpaperSeedExtractor : IVideoWallpaperSeedExtractor -{ - // ... 整个类实现 -} -``` - ---- - -### 3.6 壁纸设置页面 XAML 变更 (WallpaperSettingsPage.axaml) - -#### 3.6.1 移除视频预览区域 - -移除以下代码(约第29-44行): - -```xml - - - - - - -``` - -#### 3.6.2 移除视频模式提示文本 - -移除以下代码(约第150-154行): - -```xml - -``` - -#### 3.6.3 修改填充方式设置可见性绑定 - -```xml - -IsVisible="{Binding IsImageOrVideo}" - - -IsVisible="{Binding IsImage}" -``` - ---- - -### 3.7 壁纸设置 ViewModel 变更 (WallpaperSettingsPageViewModel.cs) - -#### 3.7.1 移除属性 - -```csharp -// 移除以下属性 -[ObservableProperty] -private bool _isImageOrVideo; - -[ObservableProperty] -private bool _isVideo; - -[ObservableProperty] -private string _videoModeHintText = string.Empty; -``` - -#### 3.7.2 修改 CreateWallpaperTypes 方法 - -```csharp -// 修改前 -private IReadOnlyList CreateWallpaperTypes() -{ - return - [ - new SelectionOption("Image", L("settings.wallpaper.type.image", "Image")), - new SelectionOption("Video", L("settings.wallpaper.type.video", "Video")), - new SelectionOption("SolidColor", L("settings.wallpaper.type.solid_color", "Solid Color")) - ]; -} - -// 修改后 -private IReadOnlyList CreateWallpaperTypes() -{ - return - [ - new SelectionOption("Image", L("settings.wallpaper.type.image", "Image")), - new SelectionOption("SolidColor", L("settings.wallpaper.type.solid_color", "Solid Color")) - ]; -} -``` - -#### 3.7.3 修改 UpdateVisibility 方法 - -移除 IsVideo 和 IsImageOrVideo 的赋值: - -```csharp -// 移除以下行 -IsVideo = SelectedWallpaperType?.Value == "Video"; -IsImageOrVideo = SelectedWallpaperType?.Value is "Image" or "Video"; -``` - -#### 3.7.4 修改 RefreshLocalizedText 方法 - -```csharp -// 移除以下行 -VideoModeHintText = L("settings.wallpaper.video_mode", "Video wallpaper uses automatic fill mode."); -``` - ---- - -### 3.8 设置契约变更 (SettingsContracts.cs) - -#### 3.8.1 修改 WallpaperMediaType 枚举 - -```csharp -// 修改前 -public enum WallpaperMediaType -{ - None, - Image, - Video -} - -// 修改后 -public enum WallpaperMediaType -{ - None, - Image -} -``` - ---- - -### 3.9 设置域服务变更 (SettingsDomainServices.cs) - -#### 3.9.1 移除视频扩展名集合 - -```csharp -// 移除以下字段(约第150-153行) -private static readonly HashSet VideoExtensions = new(StringComparer.OrdinalIgnoreCase) -{ - ".mp4", ".mkv", ".webm", ".avi", ".mov", ".m4v" -}; -``` - -#### 3.9.2 修改 DetectMediaType 方法 - -```csharp -// 修改前 -public WallpaperMediaType DetectMediaType(string? path) -{ - if (string.IsNullOrWhiteSpace(path)) - { - return WallpaperMediaType.None; - } - - var extension = Path.GetExtension(path.Trim()); - if (string.IsNullOrWhiteSpace(extension)) - { - return WallpaperMediaType.None; - } - - if (ImageExtensions.Contains(extension)) - { - return WallpaperMediaType.Image; - } - - if (VideoExtensions.Contains(extension)) - { - return WallpaperMediaType.Video; - } - - return WallpaperMediaType.None; -} - -// 修改后 -public WallpaperMediaType DetectMediaType(string? path) -{ - if (string.IsNullOrWhiteSpace(path)) - { - return WallpaperMediaType.None; - } - - var extension = Path.GetExtension(path.Trim()); - if (string.IsNullOrWhiteSpace(extension)) - { - return WallpaperMediaType.None; - } - - if (ImageExtensions.Contains(extension)) - { - return WallpaperMediaType.Image; - } - - return WallpaperMediaType.None; -} -``` - ---- - -### 3.10 本地化文件变更 (zh-CN.json) - -#### 3.10.1 移除的本地化键 - -```json -// 移除以下键值对 -"settings.wallpaper.type.video": "视频", -"settings.wallpaper.video_applied": "视频壁纸已应用。", -"settings.wallpaper.video_mode": "视频壁纸使用自动填充模式。", -"settings.wallpaper.video_restored": "已恢复保存的视频壁纸。", -"settings.wallpaper.video_not_found": "未找到视频壁纸文件。", -"settings.wallpaper.video_player_unavailable": "视频播放器不可用。", -"settings.wallpaper.video_play_failed_format": "播放视频壁纸失败:{0}" -``` - -#### 3.10.2 修改描述文本 - -```json -// 修改前 -"settings.wallpaper.description": "选择图片或视频后可立即设为应用窗口壁纸。", - -// 修改后 -"settings.wallpaper.description": "选择图片后可立即设为应用窗口壁纸。", -``` - ---- - -## 4. 数据模型变更 - -### 4.1 WallpaperMediaType 枚举简化 - -``` -变更前: None | Image | Video -变更后: None | Image -``` - -### 4.2 设置存储兼容性 - -现有用户设置中如果包含 `Type: "Video"` 的壁纸配置: -- 应用将无法识别该类型 -- 将回退到纯色背景 -- 用户需要重新选择图片壁纸 - ---- - -## 5. 风险评估 - -### 5.1 潜在风险 - -| 风险 | 影响 | 缓解措施 | -|------|------|----------| -| 现有视频壁纸用户设置失效 | 中 | 应用会自动回退到纯色背景 | -| 遗漏的视频相关代码引用 | 低 | 编译器会报告未定义类型错误 | -| 本地化键遗漏 | 低 | 运行时会显示键名而非翻译文本 | - -### 5.2 回滚策略 - -如需回滚,可通过 Git 恢复以下文件: -- LanMountainDesktop.csproj -- MainWindow.axaml / .axaml.cs -- MainWindow.SettingsHardCut.Stubs.cs -- AppearanceThemeService.cs -- WallpaperSettingsPage.axaml -- WallpaperSettingsPageViewModel.cs -- SettingsContracts.cs -- SettingsDomainServices.cs -- zh-CN.json - ---- - -## 6. 验证清单 - -### 6.1 编译验证 - -- [ ] 项目编译无错误 -- [ ] 无 LibVLC 相关类型引用警告 -- [ ] 无未使用变量警告 - -### 6.2 功能验证 - -- [ ] 应用正常启动 -- [ ] 图片壁纸正常显示 -- [ ] 纯色壁纸正常显示 -- [ ] 壁纸设置页面正常打开 -- [ ] 类型选择器仅显示"图片"和"纯色" -- [ ] 壁纸导入功能正常工作 - -### 6.3 清理验证 - -- [ ] 无 LibVLC 相关 DLL 在输出目录 -- [ ] 无视频相关本地化文本残留 -- [ ] 无视频相关 UI 控件残留 diff --git a/LanMontainDesktop/.trae/specs/remove-video-wallpaper-feature/spec.md b/LanMontainDesktop/.trae/specs/remove-video-wallpaper-feature/spec.md deleted file mode 100644 index d5cb620..0000000 --- a/LanMontainDesktop/.trae/specs/remove-video-wallpaper-feature/spec.md +++ /dev/null @@ -1,206 +0,0 @@ -# 移除视频壁纸功能规格说明书 - -## Why - -当前 LanMountainDesktop 项目包含视频壁纸功能,该功能引入了以下复杂性和依赖: -1. 引入了 LibVLCSharp.Avalonia、VideoLAN.LibVLC.Windows、VideoLAN.LibVLC.Mac 等重型依赖 -2. 在主窗口中残留大量视频壁纸相关代码和字段 -3. 在设置页面中保留了视频类型选择器和相关 UI 元素 -4. 在本地化文件中保留了视频壁纸相关文本 -5. 增加了应用复杂度和维护成本 - -用户决定移除该功能以简化代码库。 - -## What Changes - -- 移除 LibVLCSharp.Avalonia 及 VideoLAN.LibVLC.* NuGet 依赖 -- 移除 AppearanceThemeService.cs 中的 LibVlcVideoWallpaperSeedExtractor 类和 IVideoWallpaperSeedExtractor 接口 -- 移除 MainWindow.axaml.cs 中的视频壁纸相关字段和清理代码 -- 移除 MainWindow.SettingsHardCut.Stubs.cs 中的视频壁纸相关方法 -- 移除 MainWindow.axaml 中的 DesktopVideoWallpaperImage 和 DesktopVideoWallpaperView 控件 -- 移除 WallpaperSettingsPage.axaml 中的视频类型选择器和视频模式提示 -- 移除 WallpaperSettingsPageViewModel.cs 中的 IsVideo、VideoModeHintText 等属性 -- 移除 SettingsContracts.cs 中 WallpaperMediaType 枚举的 Video 值 -- 移除 SettingsDomainServices.cs 中 WallpaperMediaService 类的视频扩展名检测逻辑 -- 移除本地化文件中的视频壁纸相关文本 - -## Impact - -### Affected specs -- 壁纸设置功能规格 -- 主窗口桌面层规格 - -### Affected code -- `LanMountainDesktop.csproj` - NuGet 依赖配置 -- `Services/AppearanceThemeService.cs` - 视频壁纸种子提取器 -- `Views/MainWindow.axaml.cs` - 主窗口字段和清理逻辑 -- `Views/MainWindow.SettingsHardCut.Stubs.cs` - 视频壁纸控制方法 -- `Views/MainWindow.axaml` - 视频壁纸 UI 控件 -- `Views/SettingsPages/WallpaperSettingsPage.axaml` - 壁纸设置页面 UI -- `ViewModels/WallpaperSettingsPageViewModel.cs` - 壁纸设置 ViewModel -- `Services/Settings/SettingsContracts.cs` - 壁纸媒体类型枚举 -- `Services/Settings/SettingsDomainServices.cs` - 壁纸媒体服务 -- `Localization/zh-CN.json` - 本地化文本 - ---- - -## REMOVED Requirements - -### Requirement: 视频壁纸播放功能 - -**Reason**: 用户决定移除视频壁纸功能以简化代码库,减少重型依赖 - -**Migration**: -- 用户如需动态壁纸,可使用静态图片壁纸替代 -- 现有视频壁纸设置将被重置为纯色背景 - -#### Scenario: 视频壁纸播放 -- **GIVEN** 用户选择了视频文件作为壁纸 -- **WHEN** 系统检测到视频格式 -- **THEN** 系统不再支持视频壁纸播放 -- **AND THEN** 系统提示用户该文件类型不受支持 - -### Requirement: LibVLC 依赖 - -**Reason**: 移除视频壁纸功能后不再需要 LibVLC 库 - -**Migration**: 从项目依赖中移除以下包: -- LibVLCSharp.Avalonia -- VideoLAN.LibVLC.Windows -- VideoLAN.LibVLC.Mac - -### Requirement: 视频壁纸种子提取 - -**Reason**: 移除视频壁纸功能后不再需要从视频中提取颜色种子 - -**Migration**: 移除 `LibVlcVideoWallpaperSeedExtractor` 类和 `IVideoWallpaperSeedExtractor` 接口 - -### Requirement: 视频壁纸 UI 控件 - -**Reason**: 移除视频壁纸功能后不再需要视频显示控件 - -**Migration**: 移除 `DesktopVideoWallpaperImage` 和 `DesktopVideoWallpaperView` 控件 - -### Requirement: 视频类型选择器 - -**Reason**: 移除视频壁纸功能后不再需要视频类型选项 - -**Migration**: 从壁纸类型选择器中移除"视频"选项 - ---- - -## MODIFIED Requirements - -### Requirement: 壁纸媒体类型检测 - -**当前**: 支持检测 None、Image、Video 三种类型 - -**修改后**: 仅支持检测 None、Image 两种类型 - -#### Scenario: 检测媒体类型 -- **WHEN** 用户选择壁纸文件 -- **THEN** 系统仅检测图片格式(.png, .jpg, .jpeg, .bmp, .gif, .webp) -- **AND THEN** 视频格式文件将被识别为不受支持的类型 - -### Requirement: 壁纸类型选项 - -**当前**: 提供图片、视频、纯色三种类型选项 - -**修改后**: 仅提供图片、纯色两种类型选项 - -#### Scenario: 壁纸类型选择 -- **WHEN** 用户打开壁纸设置页面 -- **THEN** 类型选择器仅显示"图片"和"纯色"选项 -- **AND THEN** "视频"选项不再显示 - -### Requirement: 壁纸设置页面预览 - -**当前**: 根据类型显示图片预览、视频预览或纯色预览 - -**修改后**: 根据类型显示图片预览或纯色预览 - -#### Scenario: 预览显示 -- **WHEN** 用户选择壁纸类型 -- **THEN** 系统仅显示图片预览或纯色预览 -- **AND THEN** 视频预览区域不再显示 - -### Requirement: 主窗口壁纸显示 - -**当前**: 支持显示静态图片壁纸和视频壁纸 - -**修改后**: 仅支持显示静态图片壁纸 - -#### Scenario: 壁纸显示更新 -- **WHEN** 用户应用新壁纸 -- **THEN** 系统仅处理静态图片壁纸显示 -- **AND THEN** 视频壁纸播放逻辑不再执行 - ---- - -## ADDED Requirements - -### Requirement: 清理残留代码 - -系统 SHALL 完全移除视频壁纸功能相关的所有代码和资源。 - -#### Scenario: 主窗口字段清理 -- **WHEN** 执行代码清理 -- **THEN** 移除以下字段: - - `_videoWallpaperPosterBitmap` - - `_videoWallpaperPosterPath` - - `_libVlc` - - `_videoWallpaperPlayer` - - `_videoWallpaperMedia` - - `_wallpaperVideoPath` - -#### Scenario: 主窗口方法清理 -- **WHEN** 执行代码清理 -- **THEN** 移除以下方法: - - `StartVideoWallpaper` - - `StopVideoWallpaper` - - `TryCaptureVideoWallpaperPosterFrame` - - `ApplyVideoWallpaperPosterVisibility` - - `UpdateWallpaperDisplay` 中的视频处理分支 - -#### Scenario: ViewModel 属性清理 -- **WHEN** 执行代码清理 -- **THEN** 移除以下属性: - - `IsVideo` - - `VideoModeHintText` - - `IsImageOrVideo`(改为 `IsImage`) - -#### Scenario: 本地化文本清理 -- **WHEN** 执行代码清理 -- **THEN** 移除以下本地化键: - - `settings.wallpaper.type.video` - - `settings.wallpaper.video_applied` - - `settings.wallpaper.video_mode` - - `settings.wallpaper.video_restored` - - `settings.wallpaper.video_not_found` - - `settings.wallpaper.video_player_unavailable` - - `settings.wallpaper.video_play_failed_format` - -### Requirement: 依赖项清理 - -系统 SHALL 从项目文件中移除 LibVLC 相关 NuGet 包引用。 - -#### Scenario: NuGet 包移除 -- **WHEN** 执行依赖清理 -- **THEN** 移除以下包引用: - - `LibVLCSharp.Avalonia` - - `VideoLAN.LibVLC.Windows` - - `VideoLAN.LibVLC.Mac` - -### Requirement: 构建验证 - -系统 SHALL 在移除视频壁纸功能后保持正常构建和运行。 - -#### Scenario: 构建成功 -- **WHEN** 执行项目构建 -- **THEN** 构建成功无错误 -- **AND THEN** 所有现有测试通过 - -#### Scenario: 应用启动 -- **WHEN** 启动应用程序 -- **THEN** 应用正常启动 -- **AND THEN** 壁纸设置功能正常工作(仅支持图片和纯色) diff --git a/LanMontainDesktop/.trae/specs/remove-video-wallpaper-feature/tasks.md b/LanMontainDesktop/.trae/specs/remove-video-wallpaper-feature/tasks.md deleted file mode 100644 index 3eb0e79..0000000 --- a/LanMontainDesktop/.trae/specs/remove-video-wallpaper-feature/tasks.md +++ /dev/null @@ -1,600 +0,0 @@ -# 移除视频壁纸功能 - 编码任务清单 - -## 任务概览 - -本文档将技术设计分解为可执行的编码任务,按依赖关系排序执行。 - ---- - -## 任务 1: 移除项目依赖 - -**优先级**: P0 (最高) -**依赖**: 无 -**预估工作量**: 5 分钟 - -### 描述 - -从项目文件中移除 LibVLC 相关的 NuGet 包引用。 - -### 输入 - -- `LanMountainDesktop/LanMountainDesktop.csproj` - -### 输出 - -- 修改后的 `LanMountainDesktop.csproj`,移除以下包引用: - - `LibVLCSharp.Avalonia` - - `VideoLAN.LibVLC.Windows` - - `VideoLAN.LibVLC.Mac` - -### 验收标准 - -- [ ] 项目文件中不再包含 LibVLC 相关包引用 -- [ ] 执行 `dotnet restore` 成功 - -### 执行提示 - -``` -编辑 LanMountainDesktop.csproj,移除以下 PackageReference 节点: -1. -2. -3. -``` - ---- - -## 任务 2: 移除主窗口 XAML 视频控件 - -**优先级**: P0 -**依赖**: 任务 1 -**预估工作量**: 10 分钟 - -### 描述 - -从 MainWindow.axaml 中移除视频壁纸相关的 XAML 控件和命名空间声明。 - -### 输入 - -- `LanMountainDesktop/Views/MainWindow.axaml` - -### 输出 - -- 移除 LibVLC 命名空间声明 -- 移除 `DesktopVideoWallpaperImage` 控件 -- 移除 `DesktopVideoWallpaperView` 控件 - -### 验收标准 - -- [ ] XAML 中无 `xmlns:vlc` 命名空间 -- [ ] XAML 中无 `DesktopVideoWallpaperImage` 元素 -- [ ] XAML 中无 `DesktopVideoWallpaperView` 元素 - -### 执行提示 - -``` -编辑 MainWindow.axaml: -1. 移除第 9 行: xmlns:vlc="clr-namespace:LibVLCSharp.Avalonia;assembly=LibVLCSharp.Avalonia" -2. 移除第 126-131 行: -3. 移除第 133-137 行: -``` - ---- - -## 任务 3: 移除主窗口代码视频字段 - -**优先级**: P0 -**依赖**: 任务 1 -**预估工作量**: 15 分钟 - -### 描述 - -从 MainWindow.axaml.cs 中移除视频壁纸相关的字段声明。 - -### 输入 - -- `LanMountainDesktop/Views/MainWindow.axaml.cs` - -### 输出 - -- 移除 `SupportedVideoExtensions` 静态字段 -- 移除所有视频相关实例字段 - -### 验收标准 - -- [ ] 无 `SupportedVideoExtensions` 字段 -- [ ] 无 `_videoWallpaperPosterBitmap` 字段 -- [ ] 无 `_videoWallpaperPosterPath` 字段 -- [ ] 无 `_wallpaperVideoPath` 字段 -- [ ] 无 `_libVlc` 字段 -- [ ] 无 `_videoWallpaperPlayer` 字段 -- [ ] 无 `_videoWallpaperMedia` 字段 -- [ ] 无 `_desktopVideoFrameSync` 及相关视频帧处理字段 - -### 执行提示 - -``` -编辑 MainWindow.axaml.cs: -1. 移除第 68-71 行的 SupportedVideoExtensions 定义 -2. 移除第 123-146 行的所有视频相关字段 -``` - ---- - -## 任务 4: 移除主窗口 OnClosed 清理代码 - -**优先级**: P0 -**依赖**: 任务 3 -**预估工作量**: 5 分钟 - -### 描述 - -从 MainWindow.axaml.cs 的 OnClosed 方法中移除视频相关清理代码。 - -### 输入 - -- `LanMountainDesktop/Views/MainWindow.axaml.cs` (OnClosed 方法) - -### 输出 - -- 简化的 OnClosed 方法,无视频清理逻辑 - -### 验收标准 - -- [ ] OnClosed 方法中无 `StopVideoWallpaper()` 调用 -- [ ] OnClosed 方法中无 `_videoWallpaperMedia` 相关清理 -- [ ] OnClosed 方法中无 `_videoWallpaperPlayer` 相关清理 -- [ ] OnClosed 方法中无 `_libVlc` 相关清理 - -### 执行提示 - -``` -编辑 MainWindow.axaml.cs 的 OnClosed 方法,移除以下代码行: -- StopVideoWallpaper(); -- _videoWallpaperMedia?.Dispose(); _videoWallpaperMedia = null; -- _videoWallpaperPlayer?.Dispose(); _videoWallpaperPlayer = null; -- _desktopVideoFrameRefreshTimer?.Stop(); _desktopVideoFrameRefreshTimer = null; -- _videoWallpaperPosterBitmap?.Dispose(); _videoWallpaperPosterBitmap = null; -- _videoWallpaperPosterPath = null; -- _libVlc?.Dispose(); _libVlc = null; -``` - ---- - -## 任务 5: 移除主窗口 Stub 方法 - -**优先级**: P0 -**依赖**: 任务 1 -**预估工作量**: 20 分钟 - -### 描述 - -从 MainWindow.SettingsHardCut.Stubs.cs 中移除视频壁纸相关方法和 using 声明。 - -### 输入 - -- `LanMountainDesktop/Views/MainWindow.SettingsHardCut.Stubs.cs` - -### 输出 - -- 移除 LibVLC using 声明 -- 移除 `StartVideoWallpaper` 方法 -- 移除 `StopVideoWallpaper` 方法 -- 移除 `TryCaptureVideoWallpaperPosterFrame` 方法 -- 移除 `ApplyVideoWallpaperPosterVisibility` 方法 - -### 验收标准 - -- [ ] 无 `using LibVLCSharp.Shared;` -- [ ] 无 `using LibVLCSharp.Avalonia;` -- [ ] 无 `StartVideoWallpaper` 方法定义 -- [ ] 无 `StopVideoWallpaper` 方法定义 -- [ ] 无 `TryCaptureVideoWallpaperPosterFrame` 方法定义 -- [ ] 无 `ApplyVideoWallpaperPosterVisibility` 方法定义 - -### 执行提示 - -``` -编辑 MainWindow.SettingsHardCut.Stubs.cs: -1. 移除第 19-20 行的 using 声明 -2. 移除 StartVideoWallpaper 方法(第 337-383 行) -3. 移除 StopVideoWallpaper 方法(第 385-395 行) -4. 移除 ApplyVideoWallpaperPosterVisibility 方法(第 647-664 行) -5. 移除 TryCaptureVideoWallpaperPosterFrame 方法(第 666-751 行) -``` - ---- - -## 任务 6: 简化壁纸状态处理逻辑 - -**优先级**: P0 -**依赖**: 任务 5 -**预估工作量**: 15 分钟 - -### 描述 - -修改 MainWindow.SettingsHardCut.Stubs.cs 中的壁纸状态处理方法,移除视频类型分支。 - -### 输入 - -- `LanMountainDesktop/Views/MainWindow.SettingsHardCut.Stubs.cs` - -### 输出 - -- 简化的 `SetWallpaperState` 方法 -- 简化的 `UpdateWallpaperDisplay` 方法 -- 简化的 `ApplyWallpaperBrush` 方法 - -### 验收标准 - -- [ ] `SetWallpaperState` 中无视频类型检测分支 -- [ ] `SetWallpaperState` 中无 `_wallpaperVideoPath` 赋值 -- [ ] `UpdateWallpaperDisplay` 中无 `StopVideoWallpaper()` 调用 -- [ ] `ApplyWallpaperBrush` 中无 `ApplyVideoWallpaperPosterVisibility` 调用 - -### 执行提示 - -``` -编辑 MainWindow.SettingsHardCut.Stubs.cs: - -1. SetWallpaperState 方法: - - 移除 requestedTypeIsVideo 变量定义 - - 移除视频类型检测 if 块(SupportedVideoExtensions.Contains 检查) - -2. UpdateWallpaperDisplay 方法: - - 移除视频类型分支,仅保留 ApplyWallpaperBrush() 调用 - -3. ApplyWallpaperBrush 方法: - - 移除所有 ApplyVideoWallpaperPosterVisibility 调用 -``` - ---- - -## 任务 7: 移除外观主题服务视频提取器 - -**优先级**: P1 -**依赖**: 任务 1 -**预估工作量**: 10 分钟 - -### 描述 - -从 AppearanceThemeService.cs 中移除视频壁纸种子提取器接口和实现类。 - -### 输入 - -- `LanMountainDesktop/Services/AppearanceThemeService.cs` - -### 输出 - -- 移除 `IVideoWallpaperSeedExtractor` 接口 -- 移除 `LibVlcVideoWallpaperSeedExtractor` 类 - -### 验收标准 - -- [ ] 无 `IVideoWallpaperSeedExtractor` 接口定义 -- [ ] 无 `LibVlcVideoWallpaperSeedExtractor` 类定义 - -### 执行提示 - -``` -编辑 AppearanceThemeService.cs: -移除第 92-184 行的接口和类定义: -- IVideoWallpaperSeedExtractor 接口 -- LibVlcVideoWallpaperSeedExtractor 类 -``` - ---- - -## 任务 8: 简化壁纸设置页面 XAML - -**优先级**: P1 -**依赖**: 无 -**预估工作量**: 10 分钟 - -### 描述 - -从 WallpaperSettingsPage.axaml 中移除视频预览区域和相关 UI 元素。 - -### 输入 - -- `LanMountainDesktop/Views/SettingsPages/WallpaperSettingsPage.axaml` - -### 输出 - -- 移除视频预览 Border 区域 -- 移除视频模式提示 TextBlock -- 修改填充方式可见性绑定 - -### 验收标准 - -- [ ] 无视频预览 Border(IsVisible="{Binding IsVideo}") -- [ ] 无 VideoModeHintText 绑定的 TextBlock -- [ ] 填充方式设置绑定改为 `IsVisible="{Binding IsImage}"` - -### 执行提示 - -``` -编辑 WallpaperSettingsPage.axaml: -1. 移除第 29-44 行的视频预览 Border -2. 移除第 150-154 行的视频模式提示 TextBlock -3. 修改第 132 行: IsVisible="{Binding IsImageOrVideo}" 改为 IsVisible="{Binding IsImage}" -``` - ---- - -## 任务 9: 简化壁纸设置 ViewModel - -**优先级**: P1 -**依赖**: 任务 8 -**预估工作量**: 15 分钟 - -### 描述 - -从 WallpaperSettingsPageViewModel.cs 中移除视频相关属性和方法逻辑。 - -### 输入 - -- `LanMountainDesktop/ViewModels/WallpaperSettingsPageViewModel.cs` - -### 输出 - -- 移除 `_isImageOrVideo`、`_isVideo`、`_videoModeHintText` 属性 -- 修改 `CreateWallpaperTypes` 方法 -- 修改 `UpdateVisibility` 方法 -- 修改 `RefreshLocalizedText` 方法 - -### 验收标准 - -- [ ] 无 `IsImageOrVideo` 属性 -- [ ] 无 `IsVideo` 属性 -- [ ] 无 `VideoModeHintText` 属性 -- [ ] `CreateWallpaperTypes` 仅返回 Image 和 SolidColor 选项 -- [ ] `UpdateVisibility` 中无 IsVideo、IsImageOrVideo 赋值 -- [ ] `RefreshLocalizedText` 中无 VideoModeHintText 赋值 - -### 执行提示 - -``` -编辑 WallpaperSettingsPageViewModel.cs: -1. 移除第 76-77 行的 _isImageOrVideo 字段和属性 -2. 移除第 85-86 行的 _isVideo 字段和属性 -3. 移除第 94-95 行的 _videoModeHintText 字段和属性 -4. 修改 CreateWallpaperTypes 方法,移除 Video 选项 -5. 修改 UpdateVisibility 方法,移除 IsVideo 和 IsImageOrVideo 赋值 -6. 修改 RefreshLocalizedText 方法,移除 VideoModeHintText 赋值 -``` - ---- - -## 任务 10: 简化壁纸媒体类型枚举 - -**优先级**: P1 -**依赖**: 无 -**预估工作量**: 5 分钟 - -### 描述 - -从 SettingsContracts.cs 中移除 WallpaperMediaType 枚举的 Video 值。 - -### 输入 - -- `LanMountainDesktop/Services/Settings/SettingsContracts.cs` - -### 输出 - -- 简化的 `WallpaperMediaType` 枚举 - -### 验收标准 - -- [ ] `WallpaperMediaType` 枚举仅包含 `None` 和 `Image` - -### 执行提示 - -``` -编辑 SettingsContracts.cs: -修改第 11-16 行的枚举定义: -public enum WallpaperMediaType -{ - None, - Image -} -``` - ---- - -## 任务 11: 简化壁纸媒体服务 - -**优先级**: P1 -**依赖**: 任务 10 -**预估工作量**: 10 分钟 - -### 描述 - -从 SettingsDomainServices.cs 中移除视频扩展名检测逻辑。 - -### 输入 - -- `LanMountainDesktop/Services/Settings/SettingsDomainServices.cs` - -### 输出 - -- 移除 `VideoExtensions` 字段 -- 简化 `DetectMediaType` 方法 - -### 验收标准 - -- [ ] 无 `VideoExtensions` 字段定义 -- [ ] `DetectMediaType` 方法中无视频扩展名检测逻辑 - -### 执行提示 - -``` -编辑 SettingsDomainServices.cs: -1. 移除第 150-153 行的 VideoExtensions 字段定义 -2. 修改 DetectMediaType 方法,移除视频检测分支 -``` - ---- - -## 任务 12: 清理本地化文件 - -**优先级**: P2 -**依赖**: 无 -**预估工作量**: 5 分钟 - -### 描述 - -从 zh-CN.json 中移除视频壁纸相关的本地化文本。 - -### 输入 - -- `LanMountainDesktop/Localization/zh-CN.json` - -### 输出 - -- 移除视频相关本地化键 -- 修改壁纸描述文本 - -### 验收标准 - -- [ ] 无 `settings.wallpaper.type.video` 键 -- [ ] 无 `settings.wallpaper.video_applied` 键 -- [ ] 无 `settings.wallpaper.video_mode` 键 -- [ ] 无 `settings.wallpaper.video_restored` 键 -- [ ] 无 `settings.wallpaper.video_not_found` 键 -- [ ] 无 `settings.wallpaper.video_player_unavailable` 键 -- [ ] 无 `settings.wallpaper.video_play_failed_format` 键 -- [ ] `settings.wallpaper.description` 文本已更新 - -### 执行提示 - -``` -编辑 zh-CN.json: -1. 移除以下键值对: - - "settings.wallpaper.type.video" - - "settings.wallpaper.video_applied" - - "settings.wallpaper.video_mode" - - "settings.wallpaper.video_restored" - - "settings.wallpaper.video_not_found" - - "settings.wallpaper.video_player_unavailable" - - "settings.wallpaper.video_play_failed_format" - -2. 修改描述文本: - "settings.wallpaper.description": "选择图片后可立即设为应用窗口壁纸。" -``` - ---- - -## 任务 13: 构建验证 - -**优先级**: P0 -**依赖**: 任务 1-12 全部完成 -**预估工作量**: 10 分钟 - -### 描述 - -验证项目在移除视频壁纸功能后能够正常构建。 - -### 输入 - -- 整个项目 - -### 输出 - -- 构建成功确认 - -### 验收标准 - -- [ ] `dotnet build` 执行成功,无编译错误 -- [ ] 无 LibVLC 相关类型未定义错误 -- [ ] 无未使用变量警告(或已处理) - -### 执行提示 - -``` -在项目根目录执行: -dotnet build LanMountainDesktop/LanMountainDesktop.csproj - -检查输出: -- 确认无编译错误 -- 确认无 LibVLC 相关类型引用错误 -``` - ---- - -## 任务 14: 功能验证 - -**优先级**: P0 -**依赖**: 任务 13 -**预估工作量**: 15 分钟 - -### 描述 - -验证应用在移除视频壁纸功能后核心功能正常工作。 - -### 输入 - -- 构建后的应用 - -### 输出 - -- 功能验证报告 - -### 验收标准 - -- [ ] 应用正常启动 -- [ ] 图片壁纸正常显示 -- [ ] 纯色壁纸正常显示 -- [ ] 壁纸设置页面正常打开 -- [ ] 类型选择器仅显示"图片"和"纯色"选项 -- [ ] 壁纸导入功能正常工作 - -### 执行提示 - -``` -运行应用: -dotnet run --project LanMountainDesktop/LanMountainDesktop.csproj - -手动验证: -1. 应用启动无崩溃 -2. 打开设置 -> 壁纸页面 -3. 确认类型选择器仅有"图片"和"纯色" -4. 测试选择图片壁纸 -5. 测试选择纯色壁纸 -``` - ---- - -## 任务依赖关系图 - -``` -任务 1 (移除依赖) - ├── 任务 2 (XAML控件) - ├── 任务 3 (代码字段) - │ └── 任务 4 (OnClosed清理) - ├── 任务 5 (Stub方法) - │ └── 任务 6 (状态处理逻辑) - └── 任务 7 (主题服务) - -任务 8 (设置页面XAML) - └── 任务 9 (设置ViewModel) - -任务 10 (枚举简化) - └── 任务 11 (媒体服务) - -任务 12 (本地化) - 独立 - -任务 13 (构建验证) - 依赖所有任务 - └── 任务 14 (功能验证) -``` - ---- - -## 执行顺序建议 - -按以下顺序执行可确保依赖关系正确: - -1. **第一批** (可并行): 任务 1, 任务 8, 任务 10, 任务 12 -2. **第二批** (可并行): 任务 2, 任务 3, 任务 5, 任务 7, 任务 9, 任务 11 -3. **第三批** (可并行): 任务 4, 任务 6 -4. **第四批**: 任务 13 -5. **第五批**: 任务 14 diff --git a/LanMountainDesktop.PluginSdk/LanMountainDesktop.PluginSdk.csproj b/LanMountainDesktop.PluginSdk/LanMountainDesktop.PluginSdk.csproj index d3dc722..292fb62 100644 --- a/LanMountainDesktop.PluginSdk/LanMountainDesktop.PluginSdk.csproj +++ b/LanMountainDesktop.PluginSdk/LanMountainDesktop.PluginSdk.csproj @@ -4,7 +4,15 @@ net10.0 enable enable - 3.0.0 + 4.0.0 + LanMountainDesktop.PluginSdk + true + LanMountainDesktop + Official plugin SDK for LanMountainDesktop, including plugin manifest contracts, runtime interfaces, and registration extensions. + LanMountainDesktop;Plugin;SDK;Avalonia + README.md + https://github.com/wwiinnddyy/LanMountainDesktop + git @@ -15,4 +23,10 @@ + + + + + + diff --git a/LanMountainDesktop.PluginSdk/README.md b/LanMountainDesktop.PluginSdk/README.md new file mode 100644 index 0000000..4717217 --- /dev/null +++ b/LanMountainDesktop.PluginSdk/README.md @@ -0,0 +1,21 @@ +# LanMountainDesktop.PluginSdk + +Official SDK package for LanMountainDesktop plugins. + +## Includes + +- `IPlugin`/`PluginBase` entry abstractions +- `PluginManifest` and shared contract declarations +- desktop component registration extensions +- plugin runtime context and host service abstractions +- build-transitive packaging targets for `.laapp` output + +## Quick Start + +```xml + + + +``` + +Create `plugin.json` in your plugin project root, then run `dotnet build` to produce both build output and a `.laapp` package. diff --git a/LanMountainDesktop.PluginSdk/buildTransitive/LanMountainDesktop.PluginSdk.props b/LanMountainDesktop.PluginSdk/buildTransitive/LanMountainDesktop.PluginSdk.props new file mode 100644 index 0000000..753846f --- /dev/null +++ b/LanMountainDesktop.PluginSdk/buildTransitive/LanMountainDesktop.PluginSdk.props @@ -0,0 +1,14 @@ + + + plugin.json + .laapp + $(MSBuildProjectDirectory)\ + + true + false + + + + + + diff --git a/LanMountainDesktop.PluginSdk/buildTransitive/LanMountainDesktop.PluginSdk.targets b/LanMountainDesktop.PluginSdk/buildTransitive/LanMountainDesktop.PluginSdk.targets new file mode 100644 index 0000000..53b88b2 --- /dev/null +++ b/LanMountainDesktop.PluginSdk/buildTransitive/LanMountainDesktop.PluginSdk.targets @@ -0,0 +1,51 @@ + + + + + + + + <_LanMountainPluginBuildOutputDirectory>$(LanMountainPluginBuildOutputDirectory) + <_LanMountainPluginBuildOutputDirectory Condition="'$(_LanMountainPluginBuildOutputDirectory)' == ''">$(TargetDir) + <_LanMountainPluginBuildOutputDirectory Condition="'$(_LanMountainPluginBuildOutputDirectory)' == ''">$(MSBuildProjectDirectory)\$(OutputPath) + <_LanMountainPluginAssemblyName>$(LanMountainPluginAssemblyName) + <_LanMountainPluginAssemblyName Condition="'$(_LanMountainPluginAssemblyName)' == '' and '$(AssemblyName)' != ''">$(AssemblyName) + <_LanMountainPluginAssemblyName Condition="'$(_LanMountainPluginAssemblyName)' == ''">$(MSBuildProjectName) + <_LanMountainPluginPackageVersion>$(LanMountainPluginPackageVersion) + <_LanMountainPluginPackageVersion Condition="'$(_LanMountainPluginPackageVersion)' == '' and '$(Version)' != ''">$(Version) + <_LanMountainPluginPackageVersion Condition="'$(_LanMountainPluginPackageVersion)' == ''">1.0.0 + <_LanMountainPluginPackageOutputDirectory>$(LanMountainPluginPackageOutputDirectory) + <_LanMountainPluginPackageOutputDirectory Condition="'$(_LanMountainPluginPackageOutputDirectory)' == ''">$(MSBuildProjectDirectory)\ + <_LanMountainPluginPackageFileName>$(LanMountainPluginPackageFileName) + <_LanMountainPluginPackageFileName Condition="'$(_LanMountainPluginPackageFileName)' == ''">$(_LanMountainPluginAssemblyName).$(_LanMountainPluginPackageVersion)$(LanMountainPluginPackageExtension) + <_LanMountainPluginPackagePath>$(LanMountainPluginPackagePath) + <_LanMountainPluginPackagePath Condition="'$(_LanMountainPluginPackagePath)' == ''">$(_LanMountainPluginPackageOutputDirectory)$(_LanMountainPluginPackageFileName) + <_LanMountainPluginManifestOutputPath>$(_LanMountainPluginBuildOutputDirectory)$(LanMountainPluginManifestFileName) + <_LanMountainPluginDepsPath>$(ProjectDepsFilePath) + + + + + + + + + + + + + + diff --git a/LanMountainDesktop.PluginTemplate/LanMountainDesktop.PluginTemplate.csproj b/LanMountainDesktop.PluginTemplate/LanMountainDesktop.PluginTemplate.csproj new file mode 100644 index 0000000..328de1b --- /dev/null +++ b/LanMountainDesktop.PluginTemplate/LanMountainDesktop.PluginTemplate.csproj @@ -0,0 +1,25 @@ + + + net10.0 + $(NoWarn);NU5128 + false + LanMountainDesktop.PluginTemplate + 1.0.0 + LanMountainDesktop + Official dotnet new template package for LanMountainDesktop plugins. + LanMountainDesktop;Plugin;Template;dotnet-new + Template + README.md + https://github.com/wwiinnddyy/LanMountainDesktop + git + false + true + true + + + + + + + + diff --git a/LanMountainDesktop.PluginTemplate/README.md b/LanMountainDesktop.PluginTemplate/README.md new file mode 100644 index 0000000..8a58ce2 --- /dev/null +++ b/LanMountainDesktop.PluginTemplate/README.md @@ -0,0 +1,17 @@ +# LanMountainDesktop.PluginTemplate + +Official `dotnet new` template package for LanMountainDesktop plugins. + +## Install + +```powershell +dotnet new install LanMountainDesktop.PluginTemplate +``` + +## Create a plugin + +```powershell +dotnet new lmd-plugin -n YourPluginName +``` + +The generated project references `LanMountainDesktop.PluginSdk` and produces a `.laapp` package automatically when built. diff --git a/LanMountainDesktop.PluginTemplate/content/.template.config/template.json b/LanMountainDesktop.PluginTemplate/content/.template.config/template.json new file mode 100644 index 0000000..936c3e4 --- /dev/null +++ b/LanMountainDesktop.PluginTemplate/content/.template.config/template.json @@ -0,0 +1,55 @@ +{ + "$schema": "http://json.schemastore.org/template", + "author": "LanMountainDesktop", + "classifications": [ + "LanMountainDesktop", + "Plugin", + "Desktop" + ], + "name": "LanMountainDesktop Plugin", + "identity": "LanMountainDesktop.PluginTemplate.CSharp", + "shortName": "lmd-plugin", + "sourceName": "LanMountainDesktop.PluginTemplate", + "preferNameDirectory": true, + "tags": { + "type": "project", + "language": "C#" + }, + "symbols": { + "pluginId": { + "type": "parameter", + "datatype": "text", + "defaultValue": "LanMountainDesktop.PluginTemplate", + "description": "Plugin manifest id.", + "replaces": "__PLUGIN_ID__" + }, + "pluginAuthor": { + "type": "parameter", + "datatype": "text", + "defaultValue": "Your Name", + "description": "Plugin author.", + "replaces": "__PLUGIN_AUTHOR__" + }, + "pluginName": { + "type": "parameter", + "datatype": "text", + "defaultValue": "LanMountain Plugin Template", + "description": "Display name shown in plugin manifest.", + "replaces": "__PLUGIN_NAME__" + }, + "pluginDescription": { + "type": "parameter", + "datatype": "text", + "defaultValue": "Plugin generated from the official LanMountainDesktop template.", + "description": "Plugin description shown in plugin manifest.", + "replaces": "__PLUGIN_DESCRIPTION__" + }, + "pluginSdkVersion": { + "type": "parameter", + "datatype": "text", + "defaultValue": "4.0.0", + "description": "LanMountainDesktop.PluginSdk package version.", + "replaces": "__PLUGIN_SDK_VERSION__" + } + } +} diff --git a/LanMountainDesktop.PluginTemplate/content/LanMountainDesktop.PluginTemplate.csproj b/LanMountainDesktop.PluginTemplate/content/LanMountainDesktop.PluginTemplate.csproj new file mode 100644 index 0000000..b763a85 --- /dev/null +++ b/LanMountainDesktop.PluginTemplate/content/LanMountainDesktop.PluginTemplate.csproj @@ -0,0 +1,19 @@ + + + net10.0 + enable + enable + 1.0.0 + true + $(Version) + + + + + + + + + + + diff --git a/LanMountainDesktop.PluginTemplate/content/Localization/en-US.json b/LanMountainDesktop.PluginTemplate/content/Localization/en-US.json new file mode 100644 index 0000000..2c63c08 --- /dev/null +++ b/LanMountainDesktop.PluginTemplate/content/Localization/en-US.json @@ -0,0 +1,2 @@ +{ +} diff --git a/LanMountainDesktop.PluginTemplate/content/Localization/zh-CN.json b/LanMountainDesktop.PluginTemplate/content/Localization/zh-CN.json new file mode 100644 index 0000000..2c63c08 --- /dev/null +++ b/LanMountainDesktop.PluginTemplate/content/Localization/zh-CN.json @@ -0,0 +1,2 @@ +{ +} diff --git a/LanMountainDesktop.PluginTemplate/content/Plugin.cs b/LanMountainDesktop.PluginTemplate/content/Plugin.cs new file mode 100644 index 0000000..fe100eb --- /dev/null +++ b/LanMountainDesktop.PluginTemplate/content/Plugin.cs @@ -0,0 +1,15 @@ +using LanMountainDesktop.PluginSdk; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; + +namespace LanMountainDesktop.PluginTemplate; + +[PluginEntrance] +public sealed class Plugin : PluginBase +{ + public override void Initialize(HostBuilderContext context, IServiceCollection services) + { + _ = context; + _ = services; + } +} diff --git a/LanMountainDesktop.PluginTemplate/content/README.md b/LanMountainDesktop.PluginTemplate/content/README.md new file mode 100644 index 0000000..0a9bd45 --- /dev/null +++ b/LanMountainDesktop.PluginTemplate/content/README.md @@ -0,0 +1,24 @@ +# __PLUGIN_NAME__ + +Official-style plugin scaffold generated for LanMountainDesktop. + +## Build + +```powershell +dotnet build -c Release +``` + +`LanMountainDesktop.PluginSdk` build targets will generate: + +- plugin output files under `bin///` +- a `.laapp` package in the project root + +## Manifest + +Update `plugin.json` fields as needed before release: + +- `id` +- `name` +- `description` +- `author` +- `version` diff --git a/LanMountainDesktop.PluginTemplate/content/plugin.json b/LanMountainDesktop.PluginTemplate/content/plugin.json new file mode 100644 index 0000000..5de5e7d --- /dev/null +++ b/LanMountainDesktop.PluginTemplate/content/plugin.json @@ -0,0 +1,10 @@ +{ + "id": "__PLUGIN_ID__", + "name": "__PLUGIN_NAME__", + "description": "__PLUGIN_DESCRIPTION__", + "author": "__PLUGIN_AUTHOR__", + "version": "1.0.0", + "apiVersion": "4.0.0", + "entranceAssembly": "LanMountainDesktop.PluginTemplate.dll", + "sharedContracts": [] +} diff --git a/LanMountainDesktop.Shared.Contracts/LanMountainDesktop.Shared.Contracts.csproj b/LanMountainDesktop.Shared.Contracts/LanMountainDesktop.Shared.Contracts.csproj index d23bea9..c44b5dd 100644 --- a/LanMountainDesktop.Shared.Contracts/LanMountainDesktop.Shared.Contracts.csproj +++ b/LanMountainDesktop.Shared.Contracts/LanMountainDesktop.Shared.Contracts.csproj @@ -3,8 +3,20 @@ net10.0 enable enable + 1.0.0 + LanMountainDesktop.Shared.Contracts + true + LanMountainDesktop + Shared contracts used by LanMountainDesktop host and plugins for cross-boundary communication. + LanMountainDesktop;Plugin;SharedContracts;Avalonia + README.md + https://github.com/wwiinnddyy/LanMountainDesktop + git + + + diff --git a/LanMountainDesktop.Shared.Contracts/README.md b/LanMountainDesktop.Shared.Contracts/README.md new file mode 100644 index 0000000..d2f94b3 --- /dev/null +++ b/LanMountainDesktop.Shared.Contracts/README.md @@ -0,0 +1,16 @@ +# LanMountainDesktop.Shared.Contracts + +Shared contracts package for LanMountainDesktop host and plugin ecosystems. + +## Includes + +- cross-boundary records used by host/runtime and plugins +- contract types intended for stable shared communication + +## Usage + +```xml + + + +``` diff --git a/LanMountainDesktop.slnx b/LanMountainDesktop.slnx index 61bb691..acef7e8 100644 --- a/LanMountainDesktop.slnx +++ b/LanMountainDesktop.slnx @@ -6,6 +6,7 @@ + diff --git a/PRODUCT_BRIEF.md b/PRODUCT_BRIEF.md index cb33428..4f91e17 100644 --- a/PRODUCT_BRIEF.md +++ b/PRODUCT_BRIEF.md @@ -4,7 +4,7 @@ - **学生群体**:大学生、研究生、备考人员 - **办公用户**:白领、远程工作者 -- **效率爱好者**:工具控、桌面美化爱好者 +- **桌面美化爱好者**:追求个性化桌面布局与视觉体验的用户 ## 2. 使用场景 @@ -32,60 +32,15 @@ | 信息分散,需打开多个应用 | 桌面聚合展示天气、日历、新闻等信息 | | 桌面单调,缺乏个性化 | 丰富的组件和主题自由定制 | | 学习管理不便 | 课程表、自习监测专为学生设计 | +| 功能单一,需安装多个独立应用 | 一个应用整合考试看板、噪音监测等多种功能 | | 功能无法满足个性需求 | 插件系统支持无限扩展 | -## 5. 竞品对比分析 +## 5. 产品进度 -### 5.1 产品定位差异 - -| 产品 | 定位 | 主要场景 | 目标用户 | -|-----|------|---------|---------| -| **阑山桌面** | 个人桌面信息聚合与效率工具 | 个人学习、办公、信息获取 | 学生、办公人员、个人用户 | -| **希沃桌面** | 教室大屏教学系统 | 课堂教学、多媒体展示 | 中小学教师、学校 | -| **鸿合鸿U** | 交互式教学系统 | 课堂授课、教学管理 | 教师、教育机构 | -| **鸿合 Lesson+** | AI 备授课软件 | 备课、授课、互动、评价 | 教师 | -| **Classworks** | 教学资源与课堂管理 | 课堂互动、学情分析 | 教师、学校 | - -### 5.2 功能对比 - -| 功能维度 | 阑山桌面 | 希沃/鸿合系列 | -|---------|---------|--------------| -| **核心功能** | 桌面组件、信息展示、效率工具 | 教学白板、课件展示、课堂互动 | -| **组件/工具** | 时钟、天气、日历、新闻、课程表 | 学科工具、白板批注、思维导图 | -| **插件扩展** | ✅ 支持第三方插件 | ❌ 封闭系统 | -| **跨平台** | ✅ Windows/Linux/macOS | ❌ 主要 Windows | -| **硬件依赖** | 无,纯软件 | 需配合交互大屏/白板 | -| **AI 功能** | 暂无 | 鸿合 Lesson+ 集成教学大模型 | -| **课堂互动** | 不支持 | 多屏互动、学生端连接 | -| **教学资源** | 无内置 | 丰富的学科资源库 | -| **使用场景** | 个人电脑桌面 | 教室大屏教学 | -| **部署方式** | 个人安装 | 学校/机构批量部署 | - -### 5.3 竞争优势 - -| 优势 | 说明 | -|-----|------| -| **个人用户导向** | 专注个人效率,无需专用硬件 | -| **开放生态** | 插件系统支持功能无限扩展 | -| **跨平台支持** | 支持三大主流操作系统 | -| **轻量灵活** | 纯软件方案,部署成本低 | -| **隐私保护** | 本地数据存储,不上传个人信息 | - -### 5.4 竞争劣势 - -| 劣势 | 说明 | -|-----|------| -| **非教学专用** | 缺乏专业教学工具和资源 | -| **无课堂互动** | 不支持学生端连接和课堂互动 | -| **无 AI 功能** | 暂不具备 AI 辅助教学能力 | -| **品牌认知** | 教育市场知名度低于希沃/鸿合 | - -## 6. 产品进度 - -- **当前版本**:v1.0.0(插件 API 3.0.0) -- **开发状态**:核心功能已完成,进入优化迭代阶段 +- **当前版本**:v0.7.0(插件 API 3.0.0) +- **开发状态**:核心功能开发中,预计 v1.0 正式发布 - **用户统计**:通过 PostHog 收集匿名数据(具体数据需后台查看) --- -**一句话总结**:阑山桌面是一款面向个人用户的可定制桌面工具,与希沃、鸿合等教育大屏系统不同,专注个人学习办公场景,通过组件化设计和插件生态提供轻量、开放、跨平台的桌面信息聚合方案。 +**一句话总结**:阑山桌面是一款面向个人用户的可定制桌面工具,专注个人学习办公场景,通过组件化设计和插件生态提供轻量、开放、跨平台的桌面信息聚合方案。 diff --git a/README.md b/README.md index 8be2891..89d8176 100644 --- a/README.md +++ b/README.md @@ -35,6 +35,14 @@ This repository does not own: - Appearance model: `IPluginAppearanceContext`, `PluginAppearanceSnapshot`, `PluginCornerRadiusTokens`, `PluginCornerRadiusPreset` - Component registration model: `AddPluginDesktopComponent(PluginDesktopComponentOptions options)` +## Plugin Package Surfaces + +- `LanMountainDesktop.PluginSdk`: official plugin SDK package (includes `buildTransitive` default `.laapp` packaging targets) +- `LanMountainDesktop.Shared.Contracts`: shared contract package for host/plugin boundaries +- `LanMountainDesktop.PluginTemplate`: official `dotnet new` template package (`shortName`: `lmd-plugin`) + +Use `scripts/Pack-PluginPackages.ps1` to generate local-feed packages for CI or workspace integration tests. + ## Workspace Market Resolution For local market debugging, the host resolves workspace files from the sibling repository path (`..\\LanAirApp`) instead of reading the in-repo mirror folder. diff --git a/scripts/Pack-PluginPackages.ps1 b/scripts/Pack-PluginPackages.ps1 new file mode 100644 index 0000000..906a690 --- /dev/null +++ b/scripts/Pack-PluginPackages.ps1 @@ -0,0 +1,57 @@ +[CmdletBinding()] +param( + [string]$OutputPath, + [string]$Configuration = "Release", + [string]$Version, + [string]$NuGetPackagesPath +) + +Set-StrictMode -Version Latest +$ErrorActionPreference = "Stop" + +$repoRoot = Split-Path -Parent $PSScriptRoot +if ([string]::IsNullOrWhiteSpace($OutputPath)) { + $OutputPath = Join-Path $repoRoot "artifacts\nuget" +} +if ([string]::IsNullOrWhiteSpace($NuGetPackagesPath)) { + $NuGetPackagesPath = Join-Path $repoRoot ".nuget\packages" +} + +$resolvedOutputPath = [System.IO.Path]::GetFullPath($OutputPath) +New-Item -ItemType Directory -Force -Path $resolvedOutputPath | Out-Null +$resolvedNuGetPackagesPath = [System.IO.Path]::GetFullPath($NuGetPackagesPath) +New-Item -ItemType Directory -Force -Path $resolvedNuGetPackagesPath | Out-Null +$env:NUGET_PACKAGES = $resolvedNuGetPackagesPath + +$projects = @( + "LanMountainDesktop.Shared.Contracts\LanMountainDesktop.Shared.Contracts.csproj", + "LanMountainDesktop.PluginSdk\LanMountainDesktop.PluginSdk.csproj", + "LanMountainDesktop.PluginTemplate\LanMountainDesktop.PluginTemplate.csproj" +) + +$versionArgs = @() +if (-not [string]::IsNullOrWhiteSpace($Version)) { + $versionArgs += "-p:Version=$Version" +} + +foreach ($project in $projects) { + $projectPath = Join-Path $repoRoot $project + if (-not (Test-Path -Path $projectPath)) { + throw "Project '$projectPath' was not found." + } + + Write-Host "Packing $project..." + $args = @( + "pack", + $projectPath, + "-c", $Configuration, + "-o", $resolvedOutputPath + ) + $versionArgs + + & dotnet @args + if ($LASTEXITCODE -ne 0) { + throw "dotnet pack failed for '$projectPath' with exit code $LASTEXITCODE." + } +} + +Write-Host "Plugin packages generated to '$resolvedOutputPath'."