From e795e9964e0961f1b77555bef62ca83e2d033854 Mon Sep 17 00:00:00 2001 From: lincube Date: Fri, 10 Apr 2026 12:20:05 +0800 Subject: [PATCH] =?UTF-8?q?feat.=E5=A2=9E=E5=8A=A0=E4=BA=86=E6=97=A0.net10?= =?UTF-8?q?=E7=9A=84=E5=AE=89=E8=A3=85=E5=8C=85=E7=89=88=E6=9C=AC=EF=BC=8C?= =?UTF-8?q?=E5=AE=9E=E9=AA=8C=E6=80=A7=E7=9A=84=E4=BF=AE=E6=94=B9=E4=BA=86?= =?UTF-8?q?=E8=9E=8D=E5=90=88=E6=A1=8C=E9=9D=A2=E8=AE=BE=E7=BD=AE=E4=B8=8B?= =?UTF-8?q?=E7=9A=84=E7=BB=84=E4=BB=B6=E5=BA=93=E6=A0=B7=E5=BC=8F=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/release.yml | 52 ++- .../fused-desktop-library-redesign/spec.md | 100 ++++++ .../fused-desktop-library-redesign/tasks.md | 35 ++ .../ComponentLibraryWindowViewModel.cs | 16 + .../Views/ComponentLibraryWindow.axaml.cs | 1 + .../FusedDesktopComponentLibraryControl.axaml | 316 ++++++++++-------- ...sedDesktopComponentLibraryControl.axaml.cs | 66 +++- .../FusedDesktopComponentLibraryWindow.axaml | 32 +- ...usedDesktopComponentLibraryWindow.axaml.cs | 20 ++ .../installer/LanMountainDesktop.iss | 71 +++- 10 files changed, 531 insertions(+), 178 deletions(-) create mode 100644 .trae/specs/fused-desktop-library-redesign/spec.md create mode 100644 .trae/specs/fused-desktop-library-redesign/tasks.md diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 6f7c1c5..cf45623 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -66,8 +66,19 @@ jobs: strategy: fail-fast: false matrix: - arch: [x64, x86] - name: Build_Windows_${{ matrix.arch }} + include: + # 完整版(自包含 .NET 运行时) + - arch: x64 + self_contained: true + suffix: '' + - arch: x86 + self_contained: true + suffix: '' + # 轻盈版(框架依赖,仅 x64) + - arch: x64 + self_contained: false + suffix: '-lite' + name: Build_Windows_${{ matrix.arch }}${{ matrix.suffix }} steps: - name: Checkout @@ -95,13 +106,16 @@ jobs: - name: Publish run: | + $selfContained = "${{ matrix.self_contained }}" -eq "true" + $publishDir = if ($selfContained) { "publish/windows-${{ matrix.arch }}" } else { "publish/windows-${{ matrix.arch }}-lite" } + dotnet publish LanMountainDesktop/LanMountainDesktop.csproj ` -c Release ` - -o ./publish/windows-${{ matrix.arch }} ` - --self-contained ` + -o ./$publishDir ` + --self-contained:$selfContained ` -r win-${{ matrix.arch }} ` -p:PublishSingleFile=false ` - -p:SelfContained=true ` + -p:SelfContained=$selfContained ` -p:DebugType=none ` -p:DebugSymbols=false ` -p:PublishTrimmed=false ` @@ -110,6 +124,9 @@ jobs: -p:AssemblyVersion=${{ needs.prepare.outputs.assembly_version }} ` -p:FileVersion=${{ needs.prepare.outputs.assembly_version }} ` -p:InformationalVersion=${{ needs.prepare.outputs.informational_version }} + + Write-Host "Published to: $publishDir" + Write-Host "Self-contained: $selfContained" shell: pwsh - name: Install Inno Setup @@ -120,7 +137,9 @@ jobs: run: | $version = "${{ needs.prepare.outputs.version }}" $arch = "${{ matrix.arch }}" - $publishDir = "publish\windows-$arch" + $selfContained = "${{ matrix.self_contained }}" -eq "true" + $suffix = "${{ matrix.suffix }}" + $publishDir = if ($selfContained) { "publish\windows-$arch" } else { "publish\windows-$arch-lite" } $installerScript = "LanMountainDesktop\installer\LanMountainDesktop.iss" $outputDir = "build-installer" @@ -187,6 +206,8 @@ jobs: "/DPublishDir=$publishDir", "/DMyOutputDir=$outputDir", "/DMyAppArch=$arch", + "/DMyAppSuffix=$suffix", + "/DIsSelfContained=$selfContained", $installerScript ) @@ -213,7 +234,7 @@ jobs: - name: Upload Installer uses: actions/upload-artifact@v4 with: - name: release-windows-${{ matrix.arch }} + name: release-windows-${{ matrix.arch }}${{ matrix.suffix }} path: build-installer/*.exe if-no-files-found: error retention-days: 30 @@ -548,19 +569,22 @@ jobs: artifacts: "release-files/**" body: | ## Release ${{ needs.prepare.outputs.version }} - + ### Windows - - **LanMountainDesktop-Setup-{version}-x64.exe** - 64-bit installer - - **LanMountainDesktop-Setup-{version}-x86.exe** - 32-bit installer - + - **LanMountainDesktop-Setup-{version}-x64.exe** - 64-bit installer (完整版,包含 .NET 运行时) + - **LanMountainDesktop-Setup-{version}-x64-lite.exe** - 64-bit installer (轻量版,需安装 .NET 10 Runtime) + - **LanMountainDesktop-Setup-{version}-x86.exe** - 32-bit installer (完整版,包含 .NET 运行时) + + > **轻量版说明**:轻量版不包含 .NET 运行时,体积更小。首次运行前需安装 [.NET 10 Desktop Runtime](https://dotnet.microsoft.com/download/dotnet/10.0)。 + Installation: Double-click the .exe file and follow the wizard. - + ### Linux - **LanMountainDesktop-{version}-linux-x64.deb** - Debian package (x64) - + ### macOS - **LanMountainDesktop-{version}-macos-x64.dmg** - Intel processor - **LanMountainDesktop-{version}-macos-arm64.dmg** - Apple Silicon (M1/M2/M3) - + See commits for changes. token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.trae/specs/fused-desktop-library-redesign/spec.md b/.trae/specs/fused-desktop-library-redesign/spec.md new file mode 100644 index 0000000..161211c --- /dev/null +++ b/.trae/specs/fused-desktop-library-redesign/spec.md @@ -0,0 +1,100 @@ +# 融合桌面组件库窗口重设计规格 + +## Why +当前融合桌面组件库窗口(FusedDesktopComponentLibraryWindow)的UI设计较为基础,与Windows 11小组件编辑面板相比,缺乏现代化的交互体验和视觉层次。用户需要一个更直观、更美观的界面来浏览和添加组件到系统桌面(负一屏)。 + +参考Windows 11小组件编辑面板的设计特点: +- 左侧分类列表,右侧选中组件的详细预览 +- 大型组件预览区域,让用户清楚看到组件效果 +- 底部明显的"添加"操作按钮 +- 简洁的关闭按钮(X)在右上角 +- 深色主题配合毛玻璃效果 + +## What Changes +- **重新设计窗口布局**:从左右分栏(分类列表+组件网格)改为左侧面板+右侧预览区的布局 +- **添加组件详情预览区**:选中组件后右侧显示大尺寸预览和组件信息 +- **优化关闭按钮**:使用标准的X图标按钮,不使用圆形样式 +- **添加底部操作栏**:包含"添加到桌面"主操作按钮和"查找更多组件"链接 +- **复用阑山桌面组件库分类**:使用相同的分类ID、图标和本地化文本 +- **移除搜索功能**:参考Windows 11设计,暂不提供搜索 + +## Impact +- 受影响文件: + - `LanMountainDesktop/Views/FusedDesktopComponentLibraryWindow.axaml` + - `LanMountainDesktop/Views/FusedDesktopComponentLibraryWindow.axaml.cs` + - `LanMountainDesktop/Views/FusedDesktopComponentLibraryControl.axaml` + - `LanMountainDesktop/Views/FusedDesktopComponentLibraryControl.axaml.cs` + - `LanMountainDesktop/ViewModels/ComponentLibraryWindowViewModel.cs`(可能需要添加新属性) + +## ADDED Requirements + +### Requirement: 窗口布局重设计 +系统应提供一个类似于Windows 11小组件编辑面板的组件库窗口。 + +#### Scenario: 窗口整体结构 +- **GIVEN** 用户从托盘菜单打开融合桌面组件库 +- **WHEN** 窗口显示时 +- **THEN** 窗口应呈现: + - 顶部标题栏:左侧显示"添加小组件"标题,右侧有关闭按钮(X) + - 左侧面板:分类列表(复用阑山桌面组件库的分类和图标) + - 右侧主区域:选中组件的大尺寸预览 + 组件信息 + 添加按钮 + - 底部:"查找更多组件"链接 + +#### Scenario: 分类列表交互 +- **GIVEN** 左侧显示组件分类列表 +- **WHEN** 用户点击某个分类 +- **THEN** 右侧应显示该分类下的第一个组件的预览 +- **AND** 分类项应有选中状态视觉反馈 +- **AND** 分类图标和名称应与阑山桌面组件库保持一致 + +#### Scenario: 组件预览区 +- **GIVEN** 用户选中一个组件 +- **WHEN** 预览区显示时 +- **THEN** 应显示: + - 组件标题(大字号) + - 大尺寸组件预览图(接近实际尺寸) + - 组件描述/功能说明 + - 底部"添加到桌面"按钮 + +#### Scenario: 添加组件操作 +- **GIVEN** 用户查看组件预览 +- **WHEN** 用户点击"添加到桌面"按钮 +- **THEN** 组件应被添加到系统桌面(负一屏)中央 +- **AND** 窗口应关闭 + +#### Scenario: 关闭按钮样式 +- **GIVEN** 窗口标题栏有关闭按钮 +- **THEN** 关闭按钮应使用标准的X图标 +- **AND** 不使用圆形背景或特殊样式 +- **AND** 使用 `DesignCornerRadiusSm` 动态资源 + +#### Scenario: 查找更多组件链接 +- **GIVEN** 窗口底部显示"查找更多组件"链接 +- **WHEN** 用户点击该链接 +- **THEN** 应打开设置窗口的插件目录页面(后续将改为插件市场) + +## MODIFIED Requirements + +### Requirement: 组件列表展示 +原实现使用网格展示所有组件,新实现改为: +- 左侧列表仅显示分类(复用阑山桌面组件库的分类ID和图标映射) +- 右侧预览区一次只显示一个组件的详细信息 +- ~~移除搜索功能~~(根据Windows 11设计,暂不提供搜索) + +### Requirement: 关闭按钮圆角规范 +原实现关闭按钮使用硬编码 `CornerRadius="18"`,应改为使用动态资源 `DesignCornerRadiusSm`。 + +### Requirement: 分类图标复用 +分类图标映射应与阑山桌面组件库保持一致: +- Clock -> Symbol.Clock +- Date -> Symbol.CalendarDate +- Weather -> Symbol.WeatherSunny +- Board -> Symbol.Edit +- Media -> Symbol.Play +- Info -> Symbol.Info +- Calculator -> Symbol.Calculator +- Study -> Symbol.Hourglass +- 其他 -> Symbol.Apps + +## REMOVED Requirements +- ~~搜索功能~~:根据Windows 11小组件面板设计,暂不提供搜索功能 diff --git a/.trae/specs/fused-desktop-library-redesign/tasks.md b/.trae/specs/fused-desktop-library-redesign/tasks.md new file mode 100644 index 0000000..0bb8301 --- /dev/null +++ b/.trae/specs/fused-desktop-library-redesign/tasks.md @@ -0,0 +1,35 @@ +# Tasks + +- [x] Task 1: 修改 FusedDesktopComponentLibraryWindow.axaml 窗口布局 + - [x] SubTask 1.1: 重新设计标题栏,使用标准X关闭按钮,移除圆形样式,使用 DesignCornerRadiusSm + - [x] SubTask 1.2: 调整窗口整体布局为左侧面板+右侧预览区 + - [x] SubTask 1.3: 添加底部"查找更多组件"链接区域 + +- [x] Task 2: 修改 FusedDesktopComponentLibraryControl.axaml 控件布局 + - [x] SubTask 2.1: 重新设计左侧面板:仅保留分类列表(移除搜索框) + - [x] SubTask 2.2: 重新设计右侧预览区:组件标题 + 大尺寸预览 + 描述 + 添加按钮 + - [x] SubTask 2.3: 优化分类列表项样式,添加选中状态视觉反馈 + - [x] SubTask 2.4: 复用阑山桌面组件库的分类图标映射 + +- [x] Task 3: 更新 ViewModel 支持新交互模式 + - [x] SubTask 3.1: 在 ComponentLibraryWindowViewModel 中添加 SelectedComponent 属性 + - [x] SubTask 3.2: 添加组件描述属性支持 + +- [x] Task 4: 更新 FusedDesktopComponentLibraryControl.axaml.cs 代码逻辑 + - [x] SubTask 4.1: 修改分类选择逻辑,选中分类时显示该分类第一个组件 + - [x] SubTask 4.2: 添加组件选中逻辑 + - [x] SubTask 4.3: 移除搜索相关代码 + - [x] SubTask 4.4: 复用阑山桌面组件库的分类图标和本地化方法 + - [x] SubTask 4.5: 添加"查找更多组件"链接点击处理(打开设置窗口插件目录) + +- [x] Task 5: 验证和测试 + - [x] SubTask 5.1: 验证关闭按钮使用动态圆角资源 DesignCornerRadiusSm + - [x] SubTask 5.2: 验证窗口布局符合Windows 11小组件面板风格 + - [x] SubTask 5.3: 验证分类图标与阑山桌面组件库一致 + - [x] SubTask 5.4: 验证组件添加功能正常工作 + - [x] SubTask 5.5: 验证"查找更多组件"链接能打开设置窗口 + +# Task Dependencies +- Task 3 依赖于 Task 1 和 Task 2 的UI设计确定 +- Task 4 依赖于 Task 3 的ViewModel更新 +- Task 5 依赖于所有前置任务完成 diff --git a/LanMountainDesktop/ViewModels/ComponentLibraryWindowViewModel.cs b/LanMountainDesktop/ViewModels/ComponentLibraryWindowViewModel.cs index 2168f58..9f3aeab 100644 --- a/LanMountainDesktop/ViewModels/ComponentLibraryWindowViewModel.cs +++ b/LanMountainDesktop/ViewModels/ComponentLibraryWindowViewModel.cs @@ -10,6 +10,7 @@ namespace LanMountainDesktop.ViewModels; public sealed class ComponentLibraryWindowViewModel : ViewModelBase { private string _title = "Widgets"; + private ComponentLibraryItemViewModel? _selectedComponent; public string Title { @@ -20,6 +21,12 @@ public sealed class ComponentLibraryWindowViewModel : ViewModelBase public ObservableCollection Categories { get; } = []; public ObservableCollection Components { get; } = []; + + public ComponentLibraryItemViewModel? SelectedComponent + { + get => _selectedComponent; + set => SetProperty(ref _selectedComponent, value); + } } public sealed class ComponentLibraryCategoryViewModel @@ -51,6 +58,7 @@ public sealed class ComponentLibraryItemViewModel private readonly string _loadingPreviewText; private readonly string _previewUnavailableText; private string _displayName; + private string? _description; private ComponentPreviewKey _previewKey; private ComponentPreviewImageEntry? _previewImageEntry; private ComponentPreviewImageState _previewState; @@ -61,12 +69,14 @@ public sealed class ComponentLibraryItemViewModel string componentId, string displayName, ComponentPreviewKey previewKey, + string? description = null, string loadingPreviewText = "Loading preview...", string previewUnavailableText = "Preview unavailable", ComponentPreviewImageEntry? previewImageEntry = null) { ComponentId = componentId; _displayName = displayName; + _description = description; _previewKey = previewKey; _loadingPreviewText = loadingPreviewText; _previewUnavailableText = previewUnavailableText; @@ -82,6 +92,12 @@ public sealed class ComponentLibraryItemViewModel set => SetProperty(ref _displayName, value); } + public string? Description + { + get => _description; + set => SetProperty(ref _description, value); + } + public ComponentPreviewKey PreviewKey { get => _previewKey; diff --git a/LanMountainDesktop/Views/ComponentLibraryWindow.axaml.cs b/LanMountainDesktop/Views/ComponentLibraryWindow.axaml.cs index 428bc29..c991c36 100644 --- a/LanMountainDesktop/Views/ComponentLibraryWindow.axaml.cs +++ b/LanMountainDesktop/Views/ComponentLibraryWindow.axaml.cs @@ -94,6 +94,7 @@ public partial class ComponentLibraryWindow : Window entry.ComponentId, displayName, previewKey, + description: null, _localize?.Invoke("component_library.preview.loading", "Loading preview...") ?? "Loading preview...", _localize?.Invoke("component_library.preview.unavailable", "Preview unavailable") ?? "Preview unavailable", previewEntry); diff --git a/LanMountainDesktop/Views/FusedDesktopComponentLibraryControl.axaml b/LanMountainDesktop/Views/FusedDesktopComponentLibraryControl.axaml index 454d232..b44f8aa 100644 --- a/LanMountainDesktop/Views/FusedDesktopComponentLibraryControl.axaml +++ b/LanMountainDesktop/Views/FusedDesktopComponentLibraryControl.axaml @@ -2,159 +2,203 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:vm="using:LanMountainDesktop.ViewModels" xmlns:fi="using:FluentIcons.Avalonia" + xmlns:converters="using:Avalonia.Data.Converters" x:Class="LanMountainDesktop.Views.FusedDesktopComponentLibraryControl" x:DataType="vm:ComponentLibraryWindowViewModel"> - - + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - + Padding="12"> + + + + + + + + + + + + - + - - - - - - - + Padding="24"> + + + + + - - - - - - - - + + + + + - - - - - - - + + + + + + + - - - - - - - - - - - - + + + + - - - - + Text="{Binding SelectedComponent.PreviewStatusText}"/> + + - - - - + + + + + + + + + + + + + + + + + + diff --git a/LanMountainDesktop/Views/FusedDesktopComponentLibraryControl.axaml.cs b/LanMountainDesktop/Views/FusedDesktopComponentLibraryControl.axaml.cs index 507836f..89b0e10 100644 --- a/LanMountainDesktop/Views/FusedDesktopComponentLibraryControl.axaml.cs +++ b/LanMountainDesktop/Views/FusedDesktopComponentLibraryControl.axaml.cs @@ -39,7 +39,9 @@ public partial class FusedDesktopComponentLibraryControl : UserControl LoadRegistry(); LoadCategories(); - SearchBox.KeyUp += (s, e) => FilterComponents(); + + // 为 ListBoxItem 添加 category-item 样式类 + CategoryListBox.ContainerPrepared += OnCategoryListBoxContainerPrepared; // 默认选择第一个分类 if (_viewModel.Categories.Count > 0) @@ -48,6 +50,14 @@ public partial class FusedDesktopComponentLibraryControl : UserControl } } + private void OnCategoryListBoxContainerPrepared(object? sender, ContainerPreparedEventArgs e) + { + if (e.Container is ListBoxItem listBoxItem) + { + listBoxItem.Classes.Add("category-item"); + } + } + private void LoadRegistry() { var pluginRuntimeService = (Application.Current as App)?.PluginRuntimeService; @@ -65,7 +75,6 @@ public partial class FusedDesktopComponentLibraryControl : UserControl private void LoadCategories() { _viewModel.Categories.Clear(); - _viewModel.Components.Clear(); // 添加"全部组件"分类 _viewModel.Categories.Add(new ComponentLibraryCategoryViewModel( @@ -130,10 +139,11 @@ public partial class FusedDesktopComponentLibraryControl : UserControl definition.Id, definition.DisplayName, previewKey, + description: null, "正在加载预览...", "预览不可用", previewEntry); - + if (mainWindow is not null && (previewEntry is null || previewEntry.State == ComponentPreviewImageState.Pending)) { mainWindow.RequestDetachedLibraryPreview(previewKey); @@ -158,25 +168,49 @@ public partial class FusedDesktopComponentLibraryControl : UserControl private void OnCategorySelectionChanged(object? sender, SelectionChangedEventArgs e) { - FilterComponents(); + UpdateSelectedComponent(); } - private void FilterComponents() + private void UpdateSelectedComponent() { - var selectedCategory = (CategoryListBox.SelectedItem as ComponentLibraryCategoryViewModel)?.Id; - var searchText = SearchBox.Text?.ToLower() ?? ""; - - var filtered = _allDefinitions.Where(d => + var selectedCategory = CategoryListBox.SelectedItem as ComponentLibraryCategoryViewModel; + if (selectedCategory is null) { - var matchesCategory = selectedCategory == "all" || string.Equals(d.Category, selectedCategory, StringComparison.OrdinalIgnoreCase); - var matchesSearch = string.IsNullOrEmpty(searchText) || d.DisplayName.ToLower().Contains(searchText) || d.Id.ToLower().Contains(searchText); - return matchesCategory && matchesSearch; - }); + _viewModel.SelectedComponent = null; + return; + } - _viewModel.Components.Clear(); - foreach (var def in filtered) + // 获取该分类下的组件列表 + IEnumerable filtered; + if (selectedCategory.Id == "all") { - _viewModel.Components.Add(CreateComponentItem(def)); + filtered = _allDefinitions.OrderBy(d => d.DisplayName); + } + else + { + filtered = _allDefinitions + .Where(d => string.Equals(d.Category, selectedCategory.Id, StringComparison.OrdinalIgnoreCase)) + .OrderBy(d => d.DisplayName); + } + + // 选择该分类下的第一个组件作为默认选中 + var firstComponent = filtered.FirstOrDefault(); + if (firstComponent is not null) + { + // 查找或创建对应的 ViewModel + var existingComponent = selectedCategory.Components.FirstOrDefault(c => c.ComponentId == firstComponent.Id); + if (existingComponent is not null) + { + _viewModel.SelectedComponent = existingComponent; + } + else + { + _viewModel.SelectedComponent = CreateComponentItem(firstComponent); + } + } + else + { + _viewModel.SelectedComponent = null; } } diff --git a/LanMountainDesktop/Views/FusedDesktopComponentLibraryWindow.axaml b/LanMountainDesktop/Views/FusedDesktopComponentLibraryWindow.axaml index 77980b9..e258077 100644 --- a/LanMountainDesktop/Views/FusedDesktopComponentLibraryWindow.axaml +++ b/LanMountainDesktop/Views/FusedDesktopComponentLibraryWindow.axaml @@ -12,21 +12,21 @@ ExtendClientAreaTitleBarHeightHint="-1" Background="Transparent" TransparencyLevelHint="Mica" - Title="融合桌面组件库"> - + Title="添加小组件"> + - - + + - @@ -35,23 +35,35 @@ FontSize="13" Foreground="{DynamicResource AdaptiveTextPrimaryBrush}" /> - + - + + + + + + diff --git a/LanMountainDesktop/Views/FusedDesktopComponentLibraryWindow.axaml.cs b/LanMountainDesktop/Views/FusedDesktopComponentLibraryWindow.axaml.cs index 8f34fec..a31f94c 100644 --- a/LanMountainDesktop/Views/FusedDesktopComponentLibraryWindow.axaml.cs +++ b/LanMountainDesktop/Views/FusedDesktopComponentLibraryWindow.axaml.cs @@ -102,6 +102,26 @@ public partial class FusedDesktopComponentLibraryWindow : Window { Close(); } + + /// + /// 查找更多组件链接点击处理 - 打开设置窗口的插件目录页面 + /// + private void OnFindMoreComponentsClick(object? sender, RoutedEventArgs e) + { + // 关闭当前窗口 + Close(); + + // 打开设置窗口并导航到插件目录页面 + if (Application.Current is App app && app.SettingsWindowService is { } settingsWindowService) + { + var mainWindow = (Application.Current?.ApplicationLifetime as IClassicDesktopStyleApplicationLifetime)?.MainWindow as MainWindow; + var request = new SettingsWindowOpenRequest( + Source: "FusedDesktopComponentLibrary", + Owner: mainWindow, + PageId: "plugin-catalog"); + settingsWindowService.Open(request); + } + } protected override void OnClosed(EventArgs e) { diff --git a/LanMountainDesktop/installer/LanMountainDesktop.iss b/LanMountainDesktop/installer/LanMountainDesktop.iss index 0d21918..d648e6f 100644 --- a/LanMountainDesktop/installer/LanMountainDesktop.iss +++ b/LanMountainDesktop/installer/LanMountainDesktop.iss @@ -20,6 +20,14 @@ #define MyAppArch "x64" #endif +#ifndef MyAppSuffix + #define MyAppSuffix "" +#endif + +#ifndef IsSelfContained + #define IsSelfContained "true" +#endif + [Setup] AppId={#MyAppId} AppName={#MyAppName} @@ -34,7 +42,7 @@ LanguageDetectionMethod=uilanguage DefaultGroupName={cm:AppShortcutName} UninstallDisplayIcon={app}\{#MyAppExeName} OutputDir={#MyOutputDir} -OutputBaseFilename={#MyAppName}-Setup-{#MyAppVersion}-{#MyAppArch} +OutputBaseFilename={#MyAppName}-Setup-{#MyAppVersion}-{#MyAppArch}{#MyAppSuffix} Compression=lzma2/ultra64 SolidCompression=yes WizardStyle=modern @@ -93,7 +101,17 @@ chinesesimplified.UpgradeCleanupMissingUninstaller=安装程序发现了现有 english.UpgradeCleanupFailedPrefix=Setup could not remove the existing installation automatically. Error code: chinesesimplified.UpgradeCleanupFailedPrefix=安装程序无法自动移除现有安装。错误代码: english.UpgradeCleanupFailedSuffix=Please close LanMountainDesktop, uninstall the current version manually, and then run this installer again. -chinesesimplified.UpgradeCleanupFailedSuffix=请关闭 LanMountainDesktop,手动卸载当前版本,然后重新运行此安装程序。 +chinesesimplified.UpgradeCleanupFailedSuffix=请关闭 LanMountain Desktop,手动卸载当前版本,然后重新运行此安装程序。 +english.DotNetRuntimeMissingTitle=.NET Desktop Runtime Required +chinesesimplified.DotNetRuntimeMissingTitle=需要 .NET Desktop Runtime +english.DotNetRuntimeMissingMessage=This application requires .NET 10.0 Desktop Runtime to run. +chinesesimplified.DotNetRuntimeMissingMessage=此应用程序需要 .NET 10.0 Desktop Runtime 才能运行。 +english.DotNetRuntimeMissingAction=Click "Yes" to open the official download page. Install it first, then run this installer again. +chinesesimplified.DotNetRuntimeMissingAction=单击"是"打开官方下载页面。请先完成安装,然后重新运行此安装程序。 +english.DotNetRuntimeOpenFailedMessage=Unable to open the download page automatically. +chinesesimplified.DotNetRuntimeOpenFailedMessage=无法自动打开下载页面。 +english.DotNetRuntimeOpenFailedAction=Please open this URL manually: +chinesesimplified.DotNetRuntimeOpenFailedAction=请手动打开以下链接: [Tasks] Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}" @@ -127,6 +145,7 @@ const UninstallRegSubkey = 'Software\Microsoft\Windows\CurrentVersion\Uninstall\{#MyAppRegistryId}_is1'; WebView2RuntimeKeyPath = 'SOFTWARE\Microsoft\EdgeUpdate\Clients\{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}'; WebView2RuntimeDownloadUrl = 'https://go.microsoft.com/fwlink/p/?LinkId=2124703'; + DotNetRuntimeDownloadUrl = 'https://dotnet.microsoft.com/download/dotnet/10.0'; UpgradeChoiceInPlace = 0; UpgradeChoiceRelocate = 1; @@ -435,10 +454,58 @@ begin RegQueryStringValue(HKCU32, WebView2RuntimeKeyPath, 'pv', VersionValue); end; +function IsDotNetDesktopRuntimeInstalled(): Boolean; +var + RuntimePath: String; +begin + Result := False; + + RuntimePath := ExpandConstant('{commonpf64}\dotnet\shared\Microsoft.WindowsDesktop.App'); + if DirExists(RuntimePath) then + begin + Result := True; + exit; + end; + + RuntimePath := ExpandConstant('{commonpf}\dotnet\shared\Microsoft.WindowsDesktop.App'); + if DirExists(RuntimePath) then + begin + Result := True; + exit; + end; +end; + function InitializeSetup(): Boolean; var ErrorCode: Integer; + IsSelfContainedBuild: Boolean; begin + IsSelfContainedBuild := ('{#IsSelfContained}' = 'true'); + + if not IsSelfContainedBuild then + begin + if not IsDotNetDesktopRuntimeInstalled() then + begin + if MsgBox( + CustomMessage('DotNetRuntimeMissingMessage') + #13#10#13#10 + + CustomMessage('DotNetRuntimeMissingAction'), + mbConfirmation, + MB_YESNO) = IDYES then + begin + if not ShellExec('open', DotNetRuntimeDownloadUrl, '', '', SW_SHOWNORMAL, ewNoWait, ErrorCode) then + begin + MsgBox( + CustomMessage('DotNetRuntimeOpenFailedMessage') + #13#10 + + CustomMessage('DotNetRuntimeOpenFailedAction') + #13#10 + DotNetRuntimeDownloadUrl, + mbError, + MB_OK); + end; + end; + Result := False; + exit; + end; + end; + if IsWebView2RuntimeInstalled() then begin Result := True;