mirror of
https://github.com/wwiinnddyy/LanMountainDesktop.git
synced 2026-06-20 23:54:26 +08:00
Compare commits
1 Commits
Avalonia12
...
v0.8.6
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
abfa64b3d7 |
106
.trae/documents/avalonia12-migration-plan.md
Normal file
106
.trae/documents/avalonia12-migration-plan.md
Normal file
@@ -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`
|
||||
|
||||
21
.trae/specs/avalonia-12-migration/checklist.md
Normal file
21
.trae/specs/avalonia-12-migration/checklist.md
Normal file
@@ -0,0 +1,21 @@
|
||||
# Checklist
|
||||
|
||||
- [x] `Directory.Packages.props` contains the Avalonia 12 dependency baseline.
|
||||
- [x] Main host references `Avalonia.Controls.WebView`.
|
||||
- [x] Source no longer references `WebView.Avalonia`, `AvaloniaWebView`, or `.UseDesktopWebView()`.
|
||||
- [x] `BrowserWidget` uses `NativeWebView.Source`, `Navigate`, `Refresh()`, `NavigationStarted`, and `EnvironmentRequested`.
|
||||
- [x] WebView blanking navigates to `about:blank`.
|
||||
- [x] Plugin SDK package version is `5.0.0`.
|
||||
- [x] `PluginSdkInfo.ApiVersion` is `5.0.0`.
|
||||
- [x] Plugin template package version default is `5.0.0`.
|
||||
- [x] Plugin template manifest `apiVersion` is `5.0.0`.
|
||||
- [x] Launcher data location config resolution cannot recurse through `ResolveDataRoot()`.
|
||||
- [x] `OobeStateServiceTests` pass.
|
||||
- [x] `dotnet build LanMountainDesktop.slnx -c Debug` has 0 errors.
|
||||
- [x] `dotnet test LanMountainDesktop.slnx -c Debug` completes without a test host stack overflow.
|
||||
- [ ] Windows host smoke test completed.
|
||||
- [ ] Windows Launcher smoke test completed.
|
||||
- [ ] Settings window FluentAvalonia 3 smoke test completed.
|
||||
- [ ] Component editor Material smoke test completed.
|
||||
- [ ] BrowserWidget navigation/refresh/page activation smoke test completed.
|
||||
- [ ] WebView2 missing-runtime diagnostic smoke test completed.
|
||||
49
.trae/specs/avalonia-12-migration/spec.md
Normal file
49
.trae/specs/avalonia-12-migration/spec.md
Normal file
@@ -0,0 +1,49 @@
|
||||
# Avalonia 12 Full Stack Migration
|
||||
|
||||
## Summary
|
||||
|
||||
LanMountainDesktop has moved its desktop stack to the Avalonia 12 baseline. The migration covers the main host, Launcher, Plugin SDK, plugin runtime loading policy, official WebView usage, ClassIsland Markdown, FluentAvalonia, FluentIcons, and Material-related dependencies.
|
||||
|
||||
## Requirements
|
||||
|
||||
### Requirement: Centralized Avalonia 12 dependency baseline
|
||||
|
||||
The solution SHALL use central package management for direct Avalonia-facing projects and keep the core UI dependency baseline on Avalonia `12.0.1`.
|
||||
|
||||
Required package baseline:
|
||||
|
||||
- `Avalonia*` `12.0.1`
|
||||
- `Avalonia.Controls.WebView` `12.0.0`
|
||||
- `ClassIsland.Markdown.Avalonia` `12.0.0`
|
||||
- `FluentAvaloniaUI` `3.0.0-preview1`
|
||||
- `FluentIcons.Avalonia` `2.1.325`
|
||||
- `Material.Avalonia` `3.16.0`
|
||||
- `Material.Icons.Avalonia` `3.0.2`
|
||||
|
||||
### Requirement: Official WebView
|
||||
|
||||
The host SHALL use `Avalonia.Controls.NativeWebView` for the browser widget and SHALL NOT reference `WebView.Avalonia`, `AvaloniaWebView`, or `.UseDesktopWebView()`.
|
||||
|
||||
Windows WebView2 user data configuration SHALL be supplied through `EnvironmentRequested` using `WindowsWebView2EnvironmentRequestedEventArgs.UserDataFolder`.
|
||||
|
||||
### Requirement: Plugin SDK v5
|
||||
|
||||
The Plugin SDK API baseline SHALL be `5.0.0`. SDK v4 plugins are treated as incompatible until rebuilt.
|
||||
|
||||
The SDK SHALL keep the existing public UI extension shape, including `SettingsPageBase` and Avalonia `Control` based desktop components.
|
||||
|
||||
### Requirement: Launcher data location stability
|
||||
|
||||
Launcher data location configuration SHALL be read from a fixed bootstrap Launcher data directory so resolving the selected data root cannot recursively require resolving itself.
|
||||
|
||||
### Requirement: OOBE state compatibility
|
||||
|
||||
The Launcher SHALL read current OOBE state from the resolved `Launcher/state` directory and SHALL continue to migrate the legacy `.launcher/state/first_run_completed` marker.
|
||||
|
||||
## Acceptance
|
||||
|
||||
- `dotnet build LanMountainDesktop.slnx -c Debug` completes with 0 errors.
|
||||
- `OobeStateServiceTests` pass.
|
||||
- Full `dotnet test LanMountainDesktop.slnx -c Debug` no longer aborts from `DataLocationResolver` recursion.
|
||||
- Plugin template defaults to SDK package version `5.0.0` and manifest `apiVersion` `5.0.0`.
|
||||
- Current developer documentation points to SDK v5 and Avalonia 12.
|
||||
18
.trae/specs/avalonia-12-migration/tasks.md
Normal file
18
.trae/specs/avalonia-12-migration/tasks.md
Normal file
@@ -0,0 +1,18 @@
|
||||
# Tasks
|
||||
|
||||
- [x] Centralize Avalonia 12 package versions in `Directory.Packages.props`.
|
||||
- [x] Move the host, Launcher, Plugin SDK, DesktopHost, Shared.Contracts, and Avalonia-facing projects onto central package versions.
|
||||
- [x] Replace third-party `WebView.Avalonia` usage with official `NativeWebView`.
|
||||
- [x] Configure WebView2 user data through `EnvironmentRequested`.
|
||||
- [x] Move FluentAvalonia usages to the FA3 control names and package baseline.
|
||||
- [x] Move FluentIcons usage to `FluentIcons.Avalonia` and remove the old `.Fluent` package.
|
||||
- [x] Update Plugin SDK package version and API baseline to `5.0.0`.
|
||||
- [x] Update plugin runtime shared assembly policy for Avalonia 12 / FluentAvalonia / FluentIcons / Material.
|
||||
- [x] Fix Avalonia 12 compile breaks in window chrome, binding plugin access, clipboard, bitmap copy, and icon source usage.
|
||||
- [x] Fix Launcher data location recursion by using a fixed bootstrap config path.
|
||||
- [x] Fix OOBE state tests and legacy marker compatibility.
|
||||
- [x] Update PluginTemplate defaults to SDK v5.
|
||||
- [x] Add SDK v5 migration documentation.
|
||||
- [x] Update current docs from SDK v4 / Avalonia 11 examples to SDK v5 / Avalonia 12.
|
||||
- [x] Run full solution tests and record any remaining non-upgrade failures.
|
||||
- [ ] Perform Windows manual smoke test for host, Launcher, settings, component editor, BrowserWidget, and WebView2 missing-runtime handling.
|
||||
@@ -74,7 +74,7 @@ dotnet test LanMountainDesktop.slnx -c Debug
|
||||
- SDK 公共 API 以 `LanMountainDesktop.PluginSdk/` 为准
|
||||
- 共享契约以 `LanMountainDesktop.Shared.Contracts/` 为准
|
||||
- market 数据来源默认是兄弟仓库 `..\\LanAirApp`
|
||||
- 迁移或 breaking change 优先同步 `docs/PLUGIN_SDK_V4_MIGRATION.md`
|
||||
- 迁移或 breaking change 优先同步 `docs/PLUGIN_SDK_V5_MIGRATION.md`
|
||||
|
||||
### 设置与主题
|
||||
|
||||
@@ -91,6 +91,6 @@ dotnet test LanMountainDesktop.slnx -c Debug
|
||||
- 视觉规范:`docs/VISUAL_SPEC.md`
|
||||
- 圆角规范:`docs/CORNER_RADIUS_SPEC.md`
|
||||
- 生态边界:`docs/ECOSYSTEM_BOUNDARIES.md`
|
||||
- SDK v4 迁移:`docs/PLUGIN_SDK_V4_MIGRATION.md`
|
||||
- SDK v5 迁移:`docs/PLUGIN_SDK_V5_MIGRATION.md`
|
||||
|
||||
如果多个文档都提到同一件事,以 `docs/ai/DOC_SOURCES.md` 列出的权威来源为准。
|
||||
|
||||
42
Directory.Packages.props
Normal file
42
Directory.Packages.props
Normal file
@@ -0,0 +1,42 @@
|
||||
<Project>
|
||||
<PropertyGroup>
|
||||
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageVersion Include="Avalonia" Version="12.0.1" />
|
||||
<PackageVersion Include="Avalonia.Controls.WebView" Version="12.0.0" />
|
||||
<PackageVersion Include="Avalonia.Desktop" Version="12.0.1" />
|
||||
<PackageVersion Include="Avalonia.Fonts.Inter" Version="12.0.1" />
|
||||
<PackageVersion Include="Avalonia.Themes.Fluent" Version="12.0.1" />
|
||||
<PackageVersion Include="AvaloniaUI.DiagnosticsSupport" Version="2.2.1" />
|
||||
<PackageVersion Include="ClassIsland.Markdown.Avalonia" Version="12.0.0" />
|
||||
<PackageVersion Include="CommunityToolkit.Mvvm" Version="8.2.1" />
|
||||
<PackageVersion Include="dotnetCampus.Ipc" Version="2.0.0-alpha434" />
|
||||
<PackageVersion Include="DotNetCampus.AvaloniaInkCanvas" Version="1.0.1" />
|
||||
<PackageVersion Include="Downloader" Version="4.1.1" />
|
||||
<PackageVersion Include="FluentAvaloniaUI" Version="3.0.0-preview1" />
|
||||
<PackageVersion Include="FluentIcons.Avalonia" Version="2.1.325" />
|
||||
<PackageVersion Include="Material.Avalonia" Version="3.16.0" />
|
||||
<PackageVersion Include="MaterialColorUtilities" Version="0.3.0" />
|
||||
<PackageVersion Include="Material.Icons.Avalonia" Version="3.0.2" />
|
||||
<PackageVersion Include="Microsoft.Data.Sqlite" Version="10.0.0" />
|
||||
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="10.0.0" />
|
||||
<PackageVersion Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="10.0.0" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Hosting.Abstractions" Version="10.0.0" />
|
||||
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.14.1" />
|
||||
<PackageVersion Include="MudTools.OfficeInterop" Version="2.0.8" />
|
||||
<PackageVersion Include="MudTools.OfficeInterop.Excel" Version="2.0.8" />
|
||||
<PackageVersion Include="MudTools.OfficeInterop.PowerPoint" Version="2.0.8" />
|
||||
<PackageVersion Include="MudTools.OfficeInterop.Word" Version="2.0.8" />
|
||||
<PackageVersion Include="PortAudioSharp2" Version="1.0.6" />
|
||||
<PackageVersion Include="PostHog" Version="2.4.0" />
|
||||
<PackageVersion Include="Sentry" Version="4.0.0" />
|
||||
<PackageVersion Include="System.Drawing.Common" Version="10.0.0" />
|
||||
<PackageVersion Include="System.Runtime.WindowsRuntime" Version="4.7.0" />
|
||||
<PackageVersion Include="Tmds.DBus.Protocol" Version="0.92.0" />
|
||||
<PackageVersion Include="xunit" Version="2.9.3" />
|
||||
<PackageVersion Include="xunit.runner.visualstudio" Version="2.8.2" />
|
||||
<PackageVersion Include="YamlDotNet" Version="16.3.0" />
|
||||
<PackageVersion Include="log4net" Version="3.3.0" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -5,7 +5,7 @@
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Avalonia" Version="11.3.12" />
|
||||
<PackageReference Include="Avalonia" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\LanMountainDesktop.PluginSdk\LanMountainDesktop.PluginSdk.csproj" />
|
||||
|
||||
@@ -22,16 +22,14 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Avalonia" Version="11.3.12" />
|
||||
<PackageReference Include="Avalonia.Desktop" Version="11.3.12" />
|
||||
<PackageReference Include="FluentAvaloniaUI" Version="2.5.0" />
|
||||
<PackageReference Include="FluentIcons.Avalonia" Version="1.1.250403001" />
|
||||
<PackageReference Include="Avalonia.Fonts.Inter" Version="11.3.12" />
|
||||
<PackageReference Include="Tmds.DBus.Protocol" Version="0.92.0" />
|
||||
<!-- Markdown.Avalonia 支持 (兼容 Avalonia 11.x) -->
|
||||
<PackageReference Include="Markdown.Avalonia" Version="11.0.3-a1" />
|
||||
<!-- MVVM 支持 -->
|
||||
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.4.0" />
|
||||
<PackageReference Include="Avalonia" />
|
||||
<PackageReference Include="Avalonia.Desktop" />
|
||||
<PackageReference Include="FluentAvaloniaUI" />
|
||||
<PackageReference Include="FluentIcons.Avalonia" />
|
||||
<PackageReference Include="Avalonia.Fonts.Inter" />
|
||||
<PackageReference Include="ClassIsland.Markdown.Avalonia" />
|
||||
<PackageReference Include="CommunityToolkit.Mvvm" />
|
||||
<PackageReference Include="Tmds.DBus.Protocol" />
|
||||
</ItemGroup>
|
||||
|
||||
<!-- 资源文件 -->
|
||||
|
||||
@@ -32,6 +32,11 @@ internal sealed class DataLocationResolver
|
||||
/// </summary>
|
||||
public string DefaultPortableDataPath => Path.Combine(_appRoot, "AppData");
|
||||
|
||||
private string ResolveBootstrapLauncherDataPath()
|
||||
{
|
||||
return Path.Combine(_defaultSystemDataPath, LauncherFolderName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检查是否允许便携模式(应用目录是否可写)
|
||||
/// </summary>
|
||||
@@ -56,6 +61,11 @@ internal sealed class DataLocationResolver
|
||||
public string ResolveDataRoot()
|
||||
{
|
||||
var config = LoadConfig();
|
||||
return ResolveDataRoot(config);
|
||||
}
|
||||
|
||||
private string ResolveDataRoot(DataLocationConfig? config)
|
||||
{
|
||||
if (config is null)
|
||||
{
|
||||
return _defaultSystemDataPath;
|
||||
@@ -65,7 +75,7 @@ internal sealed class DataLocationResolver
|
||||
{
|
||||
var portablePath = !string.IsNullOrWhiteSpace(config.PortableDataPath)
|
||||
? config.PortableDataPath
|
||||
: _defaultSystemDataPath;
|
||||
: DefaultPortableDataPath;
|
||||
return Path.GetFullPath(portablePath);
|
||||
}
|
||||
|
||||
@@ -95,7 +105,7 @@ internal sealed class DataLocationResolver
|
||||
/// </summary>
|
||||
public string ResolveConfigPath()
|
||||
{
|
||||
return Path.Combine(ResolveLauncherDataPath(), ConfigFileName);
|
||||
return Path.Combine(ResolveBootstrapLauncherDataPath(), ConfigFileName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -153,7 +163,7 @@ internal sealed class DataLocationResolver
|
||||
{
|
||||
try
|
||||
{
|
||||
var launcherPath = ResolveLauncherDataPath();
|
||||
var launcherPath = ResolveBootstrapLauncherDataPath();
|
||||
Directory.CreateDirectory(launcherPath);
|
||||
|
||||
var configPath = ResolveConfigPath();
|
||||
@@ -184,8 +194,9 @@ internal sealed class DataLocationResolver
|
||||
// 先创建目录结构
|
||||
try
|
||||
{
|
||||
Directory.CreateDirectory(ResolveLauncherDataPath());
|
||||
Directory.CreateDirectory(ResolveDesktopDataPath());
|
||||
var resolvedDataRoot = ResolveDataRoot(config);
|
||||
Directory.CreateDirectory(Path.Combine(resolvedDataRoot, LauncherFolderName));
|
||||
Directory.CreateDirectory(Path.Combine(resolvedDataRoot, DesktopFolderName));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
@@ -9,6 +9,7 @@ internal sealed class OobeStateService
|
||||
|
||||
private readonly string _stateDirectory;
|
||||
private readonly string _statePath;
|
||||
private readonly string _legacyStatePath;
|
||||
private readonly string _legacyMarkerPath;
|
||||
private readonly LauncherExecutionSnapshot _executionSnapshot;
|
||||
|
||||
@@ -25,7 +26,13 @@ internal sealed class OobeStateService
|
||||
: Path.GetFullPath(stateRootOverride);
|
||||
_stateDirectory = Path.Combine(stateRoot, "Launcher", "state");
|
||||
_statePath = Path.Combine(_stateDirectory, "oobe-state.json");
|
||||
_legacyMarkerPath = Path.Combine(_stateDirectory, "first_run_completed");
|
||||
|
||||
var legacyRoot = string.IsNullOrWhiteSpace(stateRootOverride)
|
||||
? Path.GetFullPath(appRoot)
|
||||
: Path.GetFullPath(stateRootOverride);
|
||||
var legacyStateDirectory = Path.Combine(legacyRoot, ".launcher", "state");
|
||||
_legacyStatePath = Path.Combine(legacyStateDirectory, "oobe-state.json");
|
||||
_legacyMarkerPath = Path.Combine(legacyStateDirectory, "first_run_completed");
|
||||
}
|
||||
|
||||
public OobeLaunchDecision Evaluate(CommandContext context)
|
||||
@@ -100,14 +107,12 @@ internal sealed class OobeStateService
|
||||
var migratedLegacyMarker = false;
|
||||
if (File.Exists(_statePath))
|
||||
{
|
||||
using var stream = File.OpenRead(_statePath);
|
||||
var state = JsonSerializer.Deserialize(stream, AppJsonContext.Default.OobeStateFile);
|
||||
if (state is null || state.SchemaVersion <= 0 || string.IsNullOrWhiteSpace(state.CompletedAtUtc))
|
||||
{
|
||||
return BuildUnavailableDecision(context, "OOBE state file is invalid.");
|
||||
}
|
||||
return EvaluateStateFile(context, _statePath, migratedLegacyState: false);
|
||||
}
|
||||
|
||||
return BuildDecision(context, OobeStateStatus.Completed, shouldShowOobe: false, migratedLegacyMarker: false);
|
||||
if (File.Exists(_legacyStatePath))
|
||||
{
|
||||
return EvaluateStateFile(context, _legacyStatePath, migratedLegacyState: false);
|
||||
}
|
||||
|
||||
if (File.Exists(_legacyMarkerPath))
|
||||
@@ -140,6 +145,18 @@ internal sealed class OobeStateService
|
||||
return result.Success;
|
||||
}
|
||||
|
||||
private OobeLaunchDecision EvaluateStateFile(CommandContext context, string statePath, bool migratedLegacyState)
|
||||
{
|
||||
using var stream = File.OpenRead(statePath);
|
||||
var state = JsonSerializer.Deserialize(stream, AppJsonContext.Default.OobeStateFile);
|
||||
if (state is null || state.SchemaVersion <= 0 || string.IsNullOrWhiteSpace(state.CompletedAtUtc))
|
||||
{
|
||||
return BuildUnavailableDecision(context, "OOBE state file is invalid.");
|
||||
}
|
||||
|
||||
return BuildDecision(context, OobeStateStatus.Completed, shouldShowOobe: false, migratedLegacyMarker: migratedLegacyState);
|
||||
}
|
||||
|
||||
private void TryDeleteLegacyMarker()
|
||||
{
|
||||
try
|
||||
|
||||
@@ -3,13 +3,13 @@
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:views="clr-namespace:LanMountainDesktop.Launcher.Views"
|
||||
xmlns:ui="using:FluentAvalonia.UI.Controls"
|
||||
xmlns:fi="using:FluentIcons.Avalonia"
|
||||
mc:Ignorable="d"
|
||||
d:DesignWidth="520"
|
||||
d:DesignHeight="480"
|
||||
x:Class="LanMountainDesktop.Launcher.Views.DataLocationPromptWindow"
|
||||
x:DataType="views:DataLocationPromptWindow"
|
||||
Title="选择数据保存位置"
|
||||
Title="Choose Data Location"
|
||||
Width="520"
|
||||
Height="480"
|
||||
CanResize="False"
|
||||
@@ -24,12 +24,13 @@
|
||||
</Grid.RenderTransform>
|
||||
<Grid Margin="36" RowDefinitions="Auto,*,Auto">
|
||||
<StackPanel Grid.Row="0" Spacing="8" Margin="0,0,0,20">
|
||||
<TextBlock Text="选择数据保存位置"
|
||||
<TextBlock Text="Choose Data Location"
|
||||
FontSize="22"
|
||||
FontWeight="SemiBold"
|
||||
Foreground="{DynamicResource TextFillColorPrimaryBrush}" />
|
||||
<TextBlock Text="决定将应用数据保存在哪里,可随时在设置中更改"
|
||||
<TextBlock Text="Choose where launcher and desktop data should be stored. You can change this later in settings."
|
||||
FontSize="13"
|
||||
TextWrapping="Wrap"
|
||||
Foreground="{DynamicResource TextFillColorSecondaryBrush}" />
|
||||
</StackPanel>
|
||||
|
||||
@@ -41,15 +42,15 @@
|
||||
IsVisible="False">
|
||||
<StackPanel Spacing="4">
|
||||
<StackPanel Orientation="Horizontal" Spacing="6">
|
||||
<ui:SymbolIcon Symbol="Important"
|
||||
<fi:SymbolIcon Symbol="Important"
|
||||
FontSize="16"
|
||||
Foreground="{DynamicResource SystemFillColorCriticalBrush}" />
|
||||
<TextBlock Text="无法保存到应用目录"
|
||||
<TextBlock Text="App folder is not writable"
|
||||
FontWeight="SemiBold"
|
||||
FontSize="13"
|
||||
Foreground="{DynamicResource SystemFillColorCriticalBrush}" />
|
||||
</StackPanel>
|
||||
<TextBlock Text="当前安装目录需要管理员权限才能写入,数据将自动保存到系统用户目录。"
|
||||
<TextBlock Text="The current install directory requires elevated permissions. Data will be stored in the system user profile instead."
|
||||
FontSize="12"
|
||||
TextWrapping="Wrap"
|
||||
Foreground="{DynamicResource SystemFillColorCriticalBrush}" />
|
||||
@@ -70,11 +71,11 @@
|
||||
GroupName="DataLocation"
|
||||
IsChecked="True" />
|
||||
<StackPanel Grid.Column="1" Spacing="4">
|
||||
<TextBlock Text="保存在系统用户目录(推荐)"
|
||||
<TextBlock Text="Store in the system user profile (Recommended)"
|
||||
FontSize="14"
|
||||
FontWeight="SemiBold"
|
||||
Foreground="{DynamicResource TextFillColorPrimaryBrush}" />
|
||||
<TextBlock Text="数据与当前 Windows 用户绑定,重装应用或更新后数据不会丢失"
|
||||
<TextBlock Text="Data stays tied to the current Windows user and remains intact across app reinstalls and updates."
|
||||
FontSize="12"
|
||||
TextWrapping="Wrap"
|
||||
Foreground="{DynamicResource TextFillColorSecondaryBrush}" />
|
||||
@@ -101,11 +102,11 @@
|
||||
GroupName="DataLocation"
|
||||
IsEnabled="False" />
|
||||
<StackPanel Grid.Column="1" Spacing="4">
|
||||
<TextBlock Text="保存在应用安装目录"
|
||||
<TextBlock Text="Store next to the app"
|
||||
FontSize="14"
|
||||
FontWeight="SemiBold"
|
||||
Foreground="{DynamicResource TextFillColorPrimaryBrush}" />
|
||||
<TextBlock Text="便于携带,可随应用文件夹整体移动到其他电脑"
|
||||
<TextBlock Text="Useful for portable installs. The whole app folder can be moved to another machine together with its data."
|
||||
FontSize="12"
|
||||
TextWrapping="Wrap"
|
||||
Foreground="{DynamicResource TextFillColorSecondaryBrush}" />
|
||||
@@ -124,7 +125,7 @@
|
||||
Padding="12,10"
|
||||
IsVisible="False">
|
||||
<StackPanel Orientation="Horizontal" Spacing="6">
|
||||
<ui:SymbolIcon Symbol="Message"
|
||||
<fi:SymbolIcon Symbol="Info"
|
||||
FontSize="16"
|
||||
Foreground="{DynamicResource SystemFillColorSuccessBrush}" />
|
||||
<TextBlock x:Name="MigrationInfoText"
|
||||
@@ -141,11 +142,11 @@
|
||||
Spacing="10"
|
||||
Margin="0,20,0,0">
|
||||
<Button x:Name="CancelButton"
|
||||
Content="取消"
|
||||
Content="Cancel"
|
||||
Theme="{DynamicResource ButtonTheme}"
|
||||
IsVisible="False" />
|
||||
<Button x:Name="ConfirmButton"
|
||||
Content="确认"
|
||||
Content="Confirm"
|
||||
Theme="{DynamicResource AccentButtonTheme}" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
|
||||
@@ -48,14 +48,12 @@ internal partial class DataLocationPromptWindow : Window
|
||||
|
||||
if (systemRadio is not null)
|
||||
{
|
||||
systemRadio.Checked += OnSelectionChanged;
|
||||
systemRadio.Unchecked += OnSelectionChanged;
|
||||
systemRadio.IsCheckedChanged += OnSelectionChanged;
|
||||
}
|
||||
|
||||
if (portableRadio is not null)
|
||||
{
|
||||
portableRadio.Checked += OnSelectionChanged;
|
||||
portableRadio.Unchecked += OnSelectionChanged;
|
||||
portableRadio.IsCheckedChanged += OnSelectionChanged;
|
||||
}
|
||||
|
||||
if (confirmButton is not null)
|
||||
@@ -108,7 +106,7 @@ internal partial class DataLocationPromptWindow : Window
|
||||
|
||||
if (migrationInfoText is not null && hasExistingData)
|
||||
{
|
||||
migrationInfoText.Text = "检测到系统用户目录已有应用数据。如果选择保存在应用安装目录,将自动迁移现有数据。";
|
||||
migrationInfoText.Text = "Existing system data was detected. Choosing portable mode will migrate the current data automatically.";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
CanResize="False"
|
||||
ShowInTaskbar="False"
|
||||
WindowStartupLocation="CenterScreen"
|
||||
SystemDecorations="None"
|
||||
WindowDecorations="None"
|
||||
Background="#0B0B0B"
|
||||
TransparencyLevelHint="None"
|
||||
Icon="/Assets/logo.ico">
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
Height="320"
|
||||
CanResize="False"
|
||||
WindowStartupLocation="CenterScreen"
|
||||
SystemDecorations="None"
|
||||
WindowDecorations="None"
|
||||
Background="{DynamicResource SolidBackgroundFillColorBaseBrush}"
|
||||
TransparencyLevelHint="None"
|
||||
Icon="/Assets/logo.ico">
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Version>1.0.0</Version>
|
||||
<Version>5.0.0</Version>
|
||||
<PackageId>LanMountainDesktop.PluginIsolation.Contracts</PackageId>
|
||||
<IsPackable>true</IsPackable>
|
||||
<Authors>LanMountainDesktop</Authors>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Version>1.0.0</Version>
|
||||
<Version>5.0.0</Version>
|
||||
<PackageId>LanMountainDesktop.PluginIsolation.Ipc</PackageId>
|
||||
<IsPackable>true</IsPackable>
|
||||
<Authors>LanMountainDesktop</Authors>
|
||||
@@ -17,7 +17,7 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="dotnetCampus.Ipc" Version="2.0.0-alpha434" />
|
||||
<PackageReference Include="dotnetCampus.Ipc" />
|
||||
<ProjectReference Include="..\LanMountainDesktop.PluginIsolation.Contracts\LanMountainDesktop.PluginIsolation.Contracts.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<Version>4.0.2</Version>
|
||||
<Version>5.0.0</Version>
|
||||
<PackageId>LanMountainDesktop.PluginSdk</PackageId>
|
||||
<IsPackable>true</IsPackable>
|
||||
<Authors>LanMountainDesktop</Authors>
|
||||
@@ -19,13 +19,12 @@
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Remove="_build_verify_*\**\*.cs" />
|
||||
<PackageReference Include="Avalonia" Version="11.3.12" />
|
||||
<PackageReference Include="FluentAvaloniaUI" Version="2.5.0" ExcludeAssets="runtime" />
|
||||
<PackageReference Include="FluentIcons.Avalonia" Version="2.0.320" ExcludeAssets="runtime" />
|
||||
<PackageReference Include="FluentIcons.Avalonia.Fluent" Version="2.0.320" ExcludeAssets="runtime" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="10.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="10.0.0" />
|
||||
<PackageReference Include="dotnetCampus.Ipc" Version="2.0.0-alpha434" />
|
||||
<PackageReference Include="Avalonia" />
|
||||
<PackageReference Include="FluentAvaloniaUI" ExcludeAssets="runtime" />
|
||||
<PackageReference Include="FluentIcons.Avalonia" ExcludeAssets="runtime" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" />
|
||||
<PackageReference Include="dotnetCampus.Ipc" />
|
||||
<ProjectReference Include="..\LanMountainDesktop.PluginIsolation.Contracts\LanMountainDesktop.PluginIsolation.Contracts.csproj" />
|
||||
<ProjectReference Include="..\LanMountainDesktop.Shared.Contracts\LanMountainDesktop.Shared.Contracts.csproj" />
|
||||
<ProjectReference Include="..\LanMountainDesktop.Shared.IPC\LanMountainDesktop.Shared.IPC.csproj" />
|
||||
|
||||
@@ -2,7 +2,7 @@ namespace LanMountainDesktop.PluginSdk;
|
||||
|
||||
public static class PluginSdkInfo
|
||||
{
|
||||
public const string ApiVersion = "4.0.2";
|
||||
public const string ApiVersion = "5.0.0";
|
||||
public const string ManifestFileName = "plugin.json";
|
||||
public const string PackageFileExtension = ".laapp";
|
||||
public const string DataDirectoryName = "Data";
|
||||
|
||||
@@ -16,7 +16,7 @@ Official SDK package for LanMountainDesktop plugins.
|
||||
|
||||
```xml
|
||||
<ItemGroup>
|
||||
<PackageReference Include="LanMountainDesktop.PluginSdk" Version="4.0.1" />
|
||||
<PackageReference Include="LanMountainDesktop.PluginSdk" Version="5.0.0" />
|
||||
</ItemGroup>
|
||||
```
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
"pluginSdkVersion": {
|
||||
"type": "parameter",
|
||||
"datatype": "text",
|
||||
"defaultValue": "4.0.2",
|
||||
"defaultValue": "5.0.0",
|
||||
"description": "LanMountainDesktop.PluginSdk package version.",
|
||||
"replaces": "__PLUGIN_SDK_VERSION__"
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"description": "__PLUGIN_DESCRIPTION__",
|
||||
"author": "__PLUGIN_AUTHOR__",
|
||||
"version": "1.0.0",
|
||||
"apiVersion": "4.0.2",
|
||||
"apiVersion": "5.0.0",
|
||||
"entranceAssembly": "LanMountainDesktop.PluginTemplate.dll",
|
||||
"sharedContracts": [],
|
||||
"runtime": {
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Version>0.0.0-dev</Version>
|
||||
<Version>5.0.0</Version>
|
||||
<PackageId>LanMountainDesktop.Shared.Contracts</PackageId>
|
||||
<IsPackable>true</IsPackable>
|
||||
<Authors>LanMountainDesktop</Authors>
|
||||
@@ -17,7 +17,7 @@
|
||||
<Copyright>Copyright (c) LanMountainDesktop Contributors</Copyright>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Avalonia" Version="11.3.12" />
|
||||
<PackageReference Include="Avalonia" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="README.md" Pack="true" PackagePath="\" />
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Version>1.0.0</Version>
|
||||
<Version>5.0.0</Version>
|
||||
<PackageId>LanMountainDesktop.Shared.IPC</PackageId>
|
||||
<IsPackable>true</IsPackable>
|
||||
<Authors>LanMountainDesktop</Authors>
|
||||
@@ -17,8 +17,8 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="dotnetCampus.Ipc" Version="2.0.0-alpha434" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="10.0.0" />
|
||||
<PackageReference Include="dotnetCampus.Ipc" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" />
|
||||
<ProjectReference Include="..\LanMountainDesktop.Shared.Contracts\LanMountainDesktop.Shared.Contracts.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
using System.Text.Json;
|
||||
using LanMountainDesktop.Models;
|
||||
using LanMountainDesktop.Services;
|
||||
using Xunit;
|
||||
@@ -34,10 +33,14 @@ public sealed class ComponentSettingsServiceTests
|
||||
Assert.Equal("Sweep", snapshot.DesktopClockSecondHandMode);
|
||||
Assert.Single(snapshot.ImportedClassSchedules);
|
||||
|
||||
using var document = JsonDocument.Parse(File.ReadAllText(sandbox.SettingsPath));
|
||||
Assert.True(document.RootElement.TryGetProperty("defaultSettings", out var defaultSettings));
|
||||
Assert.Equal("Sweep", defaultSettings.GetProperty("desktopClockSecondHandMode").GetString());
|
||||
Assert.False(document.RootElement.TryGetProperty("DesktopClockSecondHandMode", out _));
|
||||
Assert.True(File.Exists(sandbox.DatabasePath));
|
||||
Assert.False(File.Exists(sandbox.SettingsPath));
|
||||
Assert.True(File.Exists(sandbox.SettingsBackupPath));
|
||||
|
||||
ComponentSettingsService.ResetCacheForTests();
|
||||
var reloadedService = sandbox.CreateService();
|
||||
var reloaded = reloadedService.Load();
|
||||
Assert.Equal("Sweep", reloaded.DesktopClockSecondHandMode);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -72,11 +75,16 @@ public sealed class ComponentSettingsServiceTests
|
||||
Assert.Equal("Sweep", snapshot.DesktopClockSecondHandMode);
|
||||
Assert.True(pluginSettings.SampleFlag);
|
||||
|
||||
using var document = JsonDocument.Parse(File.ReadAllText(sandbox.SettingsPath));
|
||||
Assert.True(document.RootElement.TryGetProperty("instanceSettings", out var instanceSettings));
|
||||
Assert.True(instanceSettings.TryGetProperty("DesktopClock::clock-2x2", out var clockSettings));
|
||||
Assert.Equal("Sweep", clockSettings.GetProperty("desktopClockSecondHandMode").GetString());
|
||||
Assert.False(document.RootElement.TryGetProperty("InstanceSettings", out _));
|
||||
Assert.True(File.Exists(sandbox.DatabasePath));
|
||||
Assert.False(File.Exists(sandbox.SettingsPath));
|
||||
Assert.True(File.Exists(sandbox.SettingsBackupPath));
|
||||
|
||||
ComponentSettingsService.ResetCacheForTests();
|
||||
var reloadedService = sandbox.CreateService();
|
||||
var reloadedSnapshot = reloadedService.LoadForComponent("DesktopClock", "clock-2x2");
|
||||
var reloadedPluginSettings = reloadedService.LoadPluginSettings<SamplePluginSettings>("DesktopClock", "clock-2x2");
|
||||
Assert.Equal("Sweep", reloadedSnapshot.DesktopClockSecondHandMode);
|
||||
Assert.True(reloadedPluginSettings.SampleFlag);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -132,12 +140,7 @@ public sealed class ComponentSettingsServiceTests
|
||||
Assert.True(pluginSettings.SampleFlag);
|
||||
Assert.Equal("schedule-settings", pluginSettings.Title);
|
||||
|
||||
using var document = JsonDocument.Parse(File.ReadAllText(sandbox.SettingsPath));
|
||||
Assert.True(document.RootElement.TryGetProperty("instanceSettings", out var instanceSettings));
|
||||
Assert.True(instanceSettings.TryGetProperty("DesktopClock::clock-2x2", out _));
|
||||
Assert.True(instanceSettings.TryGetProperty("DesktopClassSchedule::class-schedule-2x2", out _));
|
||||
Assert.True(document.RootElement.TryGetProperty("pluginSettings", out var pluginSettingsNode));
|
||||
Assert.True(pluginSettingsNode.TryGetProperty("DesktopClassSchedule::class-schedule-2x2", out _));
|
||||
Assert.True(File.Exists(sandbox.DatabasePath));
|
||||
}
|
||||
|
||||
private sealed class ComponentSettingsSandbox : IDisposable
|
||||
@@ -155,6 +158,10 @@ public sealed class ComponentSettingsServiceTests
|
||||
|
||||
public string SettingsPath => Path.Combine(_directoryPath, "component-settings.json");
|
||||
|
||||
public string SettingsBackupPath => $"{SettingsPath}.migrated.bak";
|
||||
|
||||
public string DatabasePath => Path.Combine(_directoryPath, "component-state.db");
|
||||
|
||||
public ComponentSettingsService CreateService()
|
||||
{
|
||||
return new ComponentSettingsService(_directoryPath);
|
||||
|
||||
@@ -8,9 +8,9 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.1" />
|
||||
<PackageReference Include="xunit" Version="2.9.3" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2">
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" />
|
||||
<PackageReference Include="xunit" />
|
||||
<PackageReference Include="xunit.runner.visualstudio">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
|
||||
@@ -118,7 +118,7 @@ public sealed class OobeStateServiceTests : IDisposable
|
||||
executionSnapshot: executionSnapshot ?? new LauncherExecutionSnapshot(false, "tester", "S-1-5-test"));
|
||||
}
|
||||
|
||||
private string GetStatePath() => Path.Combine(_tempRoot, ".launcher", "state", "oobe-state.json");
|
||||
private string GetStatePath() => Path.Combine(_tempRoot, "Launcher", "state", "oobe-state.json");
|
||||
|
||||
private string GetLegacyMarkerPath() => Path.Combine(_tempRoot, ".launcher", "state", "first_run_completed");
|
||||
}
|
||||
|
||||
@@ -14,7 +14,6 @@ using Avalonia.Media;
|
||||
using Avalonia.Platform;
|
||||
using Avalonia.Styling;
|
||||
using Avalonia.Threading;
|
||||
using AvaloniaWebView;
|
||||
using LanMountainDesktop.ComponentSystem;
|
||||
using LanMountainDesktop.DesktopHost;
|
||||
using LanMountainDesktop.Models;
|
||||
@@ -78,7 +77,6 @@ public partial class App : Application
|
||||
private TransparentOverlayWindow? _transparentOverlayWindow;
|
||||
private FusedDesktopComponentLibraryWindow? _fusedComponentLibraryWindow;
|
||||
private bool _mainWindowClosed;
|
||||
private bool _uiUnhandledExceptionHooked;
|
||||
private DesktopShellHost? _desktopShellHost;
|
||||
private PublicIpcHostService? _publicIpcHostService;
|
||||
private LoadingStateManager? _loadingStateManager;
|
||||
@@ -194,8 +192,6 @@ public partial class App : Application
|
||||
return;
|
||||
}
|
||||
|
||||
ConfigureWebViewUserDataFolder();
|
||||
AvaloniaWebViewBuilder.Initialize(default);
|
||||
ApplyThemeFromSettings();
|
||||
ApplyCurrentCultureFromSettings();
|
||||
EnsureSettingsWindowService();
|
||||
@@ -212,8 +208,7 @@ public partial class App : Application
|
||||
}
|
||||
|
||||
AppLogger.Info("App", "Framework initialization completed.");
|
||||
|
||||
RegisterUiUnhandledExceptionGuard();
|
||||
|
||||
LinuxDesktopEntryInstaller.EnsureInstalled();
|
||||
InitializePublicIpc();
|
||||
CurrentSingleInstanceService?.StartActivationListener(ActivateMainWindow);
|
||||
@@ -532,43 +527,8 @@ public partial class App : Application
|
||||
|
||||
private void DisableAvaloniaDataAnnotationValidation()
|
||||
{
|
||||
// Get an array of plugins to remove
|
||||
var dataValidationPluginsToRemove =
|
||||
BindingPlugins.DataValidators.OfType<DataAnnotationsValidationPlugin>().ToArray();
|
||||
|
||||
// remove each entry found
|
||||
foreach (var plugin in dataValidationPluginsToRemove)
|
||||
{
|
||||
BindingPlugins.DataValidators.Remove(plugin);
|
||||
}
|
||||
}
|
||||
|
||||
private static void ConfigureWebViewUserDataFolder()
|
||||
{
|
||||
if (!OperatingSystem.IsWindows())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const string userDataFolderEnvVar = "WEBVIEW2_USER_DATA_FOLDER";
|
||||
try
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(Environment.GetEnvironmentVariable(userDataFolderEnvVar)))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var userDataFolder = WebView2RuntimeProbe.ResolveUserDataFolder();
|
||||
Environment.SetEnvironmentVariable(
|
||||
userDataFolderEnvVar,
|
||||
userDataFolder,
|
||||
EnvironmentVariableTarget.Process);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// Keep startup resilient if user profile folders are unavailable.
|
||||
AppLogger.Warn("WebView2", "Failed to configure WebView2 user data folder.", ex);
|
||||
}
|
||||
// Avalonia 12 中 BindingPlugins 已移除,数据验证插件不再需要手动禁用
|
||||
// 编译型绑定默认开启,数据注解验证行为已改变
|
||||
}
|
||||
|
||||
private void InitializePluginRuntime()
|
||||
@@ -1178,43 +1138,6 @@ public partial class App : Application
|
||||
_appearanceThemeService.ApplyThemeResources(Resources);
|
||||
}
|
||||
|
||||
private void RegisterUiUnhandledExceptionGuard()
|
||||
{
|
||||
if (_uiUnhandledExceptionHooked)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Dispatcher.UIThread.UnhandledException += OnUiThreadUnhandledException;
|
||||
_uiUnhandledExceptionHooked = true;
|
||||
}
|
||||
|
||||
private void OnUiThreadUnhandledException(object? sender, DispatcherUnhandledExceptionEventArgs e)
|
||||
{
|
||||
if (!IsKnownWebViewStartupException(e.Exception))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
e.Handled = true;
|
||||
AppLogger.Warn(
|
||||
"WebView2",
|
||||
"Suppressed a known WebView startup exception from AvaloniaWebView.Navigate to keep the host process alive.",
|
||||
e.Exception);
|
||||
}
|
||||
|
||||
private static bool IsKnownWebViewStartupException(Exception exception)
|
||||
{
|
||||
if (exception is not NullReferenceException)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var stackTrace = exception.StackTrace ?? string.Empty;
|
||||
return stackTrace.Contains("AvaloniaWebView.WebView.Navigate", StringComparison.Ordinal) &&
|
||||
stackTrace.Contains("AvaloniaWebView.WebView.OnAttachedToVisualTree", StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
private void ReleaseSingleInstanceAfterExit(string source)
|
||||
{
|
||||
if (_singleInstanceReleased)
|
||||
@@ -1959,4 +1882,3 @@ public partial class App : Application
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -108,7 +108,7 @@ public partial class SettingsOptionCard : UserControl
|
||||
"Info" => Symbol.Info,
|
||||
"ArrowSync" => Symbol.ArrowSync,
|
||||
"Alert" => Symbol.Alert,
|
||||
"Bell" => Symbol.Alert, // Bell也映射到Alert图标
|
||||
"Bell" => Symbol.AlertOn,
|
||||
_ => Symbol.Settings
|
||||
};
|
||||
}
|
||||
|
||||
@@ -92,6 +92,7 @@ public partial class SettingsSectionCard : UserControl
|
||||
"PuzzlePiece" => Symbol.PuzzlePiece,
|
||||
"Info" => Symbol.Info,
|
||||
"ArrowSync" => Symbol.ArrowSync,
|
||||
"Bell" => Symbol.AlertOn,
|
||||
_ => Symbol.Settings
|
||||
};
|
||||
}
|
||||
|
||||
@@ -41,44 +41,42 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Avalonia" Version="11.3.12" />
|
||||
<PackageReference Include="Avalonia.Desktop" Version="11.3.12" />
|
||||
<PackageReference Include="Avalonia.Themes.Fluent" Version="11.3.12" />
|
||||
<PackageReference Include="Avalonia.Fonts.Inter" Version="11.3.12" />
|
||||
<!--Condition below is needed to remove Avalonia.Diagnostics package from build output in Release configuration.-->
|
||||
<PackageReference Include="Avalonia.Diagnostics" Version="11.3.12">
|
||||
<PackageReference Include="Avalonia" />
|
||||
<PackageReference Include="Avalonia.Controls.WebView" />
|
||||
<PackageReference Include="Avalonia.Desktop" />
|
||||
<PackageReference Include="Avalonia.Themes.Fluent" />
|
||||
<PackageReference Include="Avalonia.Fonts.Inter" />
|
||||
<!--Condition below is needed to remove developer tools support from build output in Release configuration.-->
|
||||
<PackageReference Include="AvaloniaUI.DiagnosticsSupport">
|
||||
<IncludeAssets Condition="'$(Configuration)' != 'Debug'">None</IncludeAssets>
|
||||
<PrivateAssets Condition="'$(Configuration)' != 'Debug'">All</PrivateAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.2.1" />
|
||||
<PackageReference Include="DotNetCampus.AvaloniaInkCanvas" Version="1.0.1" />
|
||||
<PackageReference Include="Downloader" Version="4.1.1" />
|
||||
<PackageReference Include="FluentAvaloniaUI" Version="2.5.0" />
|
||||
<PackageReference Include="FluentIcons.Avalonia" Version="2.0.320" />
|
||||
<PackageReference Include="FluentIcons.Avalonia.Fluent" Version="2.0.320" />
|
||||
<PackageReference Include="Material.Avalonia" Version="3.13.4" />
|
||||
<PackageReference Include="Material.Icons.Avalonia" Version="2.4.1" />
|
||||
<PackageReference Include="ClassIsland.Markdown.Avalonia" Version="11.0.3.4" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="10.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="10.0.0" />
|
||||
<PackageReference Include="Microsoft.Data.Sqlite" Version="10.0.0" />
|
||||
<PackageReference Include="MudTools.OfficeInterop" Version="2.0.8" />
|
||||
<PackageReference Include="MudTools.OfficeInterop.Word" Version="2.0.8" />
|
||||
<PackageReference Include="MudTools.OfficeInterop.Excel" Version="2.0.8" />
|
||||
<PackageReference Include="MudTools.OfficeInterop.PowerPoint" Version="2.0.8" />
|
||||
<PackageReference Include="CommunityToolkit.Mvvm" />
|
||||
<PackageReference Include="DotNetCampus.AvaloniaInkCanvas" />
|
||||
<PackageReference Include="Downloader" />
|
||||
<PackageReference Include="FluentAvaloniaUI" />
|
||||
<PackageReference Include="FluentIcons.Avalonia" />
|
||||
<PackageReference Include="Material.Avalonia" />
|
||||
<PackageReference Include="Material.Icons.Avalonia" />
|
||||
<PackageReference Include="ClassIsland.Markdown.Avalonia" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" />
|
||||
<PackageReference Include="Microsoft.Data.Sqlite" />
|
||||
<PackageReference Include="MudTools.OfficeInterop" />
|
||||
<PackageReference Include="MudTools.OfficeInterop.Word" />
|
||||
<PackageReference Include="MudTools.OfficeInterop.Excel" />
|
||||
<PackageReference Include="MudTools.OfficeInterop.PowerPoint" />
|
||||
|
||||
<PackageReference Include="PortAudioSharp2" Version="1.0.6" />
|
||||
<PackageReference Include="MaterialColorUtilities" Version="0.3.0" />
|
||||
<PackageReference Include="PostHog" Version="2.4.0" />
|
||||
<PackageReference Include="Sentry" Version="4.0.0" />
|
||||
<PackageReference Include="System.Runtime.WindowsRuntime" Version="4.7.0" />
|
||||
<PackageReference Include="System.Drawing.Common" Version="10.0.0" />
|
||||
<PackageReference Include="PortAudioSharp2" />
|
||||
<PackageReference Include="MaterialColorUtilities" />
|
||||
<PackageReference Include="PostHog" />
|
||||
<PackageReference Include="Sentry" />
|
||||
<PackageReference Include="System.Runtime.WindowsRuntime" />
|
||||
<PackageReference Include="System.Drawing.Common" />
|
||||
|
||||
<PackageReference Include="WebView.Avalonia" Version="11.0.0.1" />
|
||||
<PackageReference Include="WebView.Avalonia.Desktop" Version="11.0.0.1" />
|
||||
<PackageReference Include="YamlDotNet" Version="16.3.0" />
|
||||
<PackageReference Include="Tmds.DBus.Protocol" Version="0.92.0" />
|
||||
<PackageReference Include="log4net" Version="3.3.0" />
|
||||
<PackageReference Include="YamlDotNet" />
|
||||
<PackageReference Include="Tmds.DBus.Protocol" />
|
||||
<PackageReference Include="log4net" />
|
||||
</ItemGroup>
|
||||
|
||||
<!-- Launcher 构建目标已移除 - Launcher 现在是独立应用,由 CI/CD 单独构建 -->
|
||||
|
||||
@@ -3,7 +3,6 @@ using System.Diagnostics;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Avalonia;
|
||||
using Avalonia.WebView.Desktop;
|
||||
using LanMountainDesktop.DesktopHost;
|
||||
using LanMountainDesktop.Models;
|
||||
using LanMountainDesktop.Plugins;
|
||||
@@ -111,7 +110,6 @@ public sealed class Program
|
||||
{
|
||||
var builder = AppBuilder.Configure<App>()
|
||||
.UsePlatformDetect()
|
||||
.UseDesktopWebView()
|
||||
.WithInterFont()
|
||||
.LogToTrace();
|
||||
|
||||
|
||||
@@ -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<uint>(framebuffer.Size.Width * framebuffer.Size.Height);
|
||||
|
||||
@@ -65,7 +65,7 @@ public interface INotificationService
|
||||
{
|
||||
void Show(NotificationContent content);
|
||||
|
||||
Task<ContentDialogResult> ShowDialogAsync(NotificationContent content);
|
||||
Task<FAContentDialogResult> ShowDialogAsync(NotificationContent content);
|
||||
|
||||
void ShowInfo(string title, string? message = null,
|
||||
NotificationPosition position = NotificationPosition.TopRight);
|
||||
@@ -79,17 +79,17 @@ public interface INotificationService
|
||||
void ShowError(string title, string? message = null,
|
||||
NotificationPosition position = NotificationPosition.TopRight);
|
||||
|
||||
Task<ContentDialogResult> ShowDialogInfoAsync(string title, string? message = null,
|
||||
string? primaryButtonText = "确定", string? closeButtonText = "取消");
|
||||
Task<FAContentDialogResult> ShowDialogInfoAsync(string title, string? message = null,
|
||||
string? primaryButtonText = "OK", string? closeButtonText = "Cancel");
|
||||
|
||||
Task<ContentDialogResult> ShowDialogSuccessAsync(string title, string? message = null,
|
||||
string? primaryButtonText = "确定", string? closeButtonText = "取消");
|
||||
Task<FAContentDialogResult> ShowDialogSuccessAsync(string title, string? message = null,
|
||||
string? primaryButtonText = "OK", string? closeButtonText = "Cancel");
|
||||
|
||||
Task<ContentDialogResult> ShowDialogWarningAsync(string title, string? message = null,
|
||||
string? primaryButtonText = "确定", string? closeButtonText = "取消");
|
||||
Task<FAContentDialogResult> ShowDialogWarningAsync(string title, string? message = null,
|
||||
string? primaryButtonText = "OK", string? closeButtonText = "Cancel");
|
||||
|
||||
Task<ContentDialogResult> ShowDialogErrorAsync(string title, string? message = null,
|
||||
string? primaryButtonText = "确定", string? closeButtonText = "取消");
|
||||
Task<FAContentDialogResult> ShowDialogErrorAsync(string title, string? message = null,
|
||||
string? primaryButtonText = "OK", string? closeButtonText = "Cancel");
|
||||
}
|
||||
|
||||
internal sealed class NotificationService : INotificationService
|
||||
@@ -105,20 +105,17 @@ internal sealed class NotificationService : INotificationService
|
||||
|
||||
public void Show(NotificationContent content)
|
||||
{
|
||||
// 检查通知开关是否启用
|
||||
if (!IsNotificationEnabled())
|
||||
{
|
||||
return; // 通知已禁用,不显示
|
||||
return;
|
||||
}
|
||||
|
||||
// If it's a dialog notification (center position), show as dialog window
|
||||
if (content.IsDialogNotification)
|
||||
{
|
||||
Dispatcher.UIThread.Post(() => ShowDialogWindow(content), DispatcherPriority.Normal);
|
||||
return;
|
||||
}
|
||||
|
||||
// Otherwise, show as toast notification
|
||||
Dispatcher.UIThread.Post(() => ShowCore(content), DispatcherPriority.Normal);
|
||||
}
|
||||
|
||||
@@ -153,37 +150,35 @@ internal sealed class NotificationService : INotificationService
|
||||
});
|
||||
}
|
||||
|
||||
public async Task<ContentDialogResult> ShowDialogAsync(NotificationContent content)
|
||||
public async Task<FAContentDialogResult> ShowDialogAsync(NotificationContent content)
|
||||
{
|
||||
// 检查通知开关是否启用
|
||||
if (!IsNotificationEnabled())
|
||||
{
|
||||
return ContentDialogResult.None; // 通知已禁用,不显示
|
||||
return FAContentDialogResult.None;
|
||||
}
|
||||
|
||||
return await Dispatcher.UIThread.InvokeAsync(() => ShowDialogCoreAsync(content));
|
||||
}
|
||||
|
||||
private async Task<ContentDialogResult> ShowDialogCoreAsync(NotificationContent content)
|
||||
private async Task<FAContentDialogResult> ShowDialogCoreAsync(NotificationContent content)
|
||||
{
|
||||
// Get the main window as the dialog host
|
||||
var mainWindow = GetMainWindow();
|
||||
if (mainWindow is null)
|
||||
{
|
||||
AppLogger.Warn("Notification", "Cannot show dialog notification: main window not found");
|
||||
return ContentDialogResult.None;
|
||||
return FAContentDialogResult.None;
|
||||
}
|
||||
|
||||
var dialog = new ContentDialog
|
||||
var dialog = new FAContentDialog
|
||||
{
|
||||
Title = content.Title,
|
||||
Content = content.Message ?? string.Empty,
|
||||
PrimaryButtonText = content.PrimaryButtonText,
|
||||
SecondaryButtonText = content.SecondaryButtonText,
|
||||
CloseButtonText = content.CloseButtonText,
|
||||
DefaultButton = !string.IsNullOrEmpty(content.PrimaryButtonText) ? ContentDialogButton.Primary :
|
||||
!string.IsNullOrEmpty(content.SecondaryButtonText) ? ContentDialogButton.Secondary :
|
||||
ContentDialogButton.Close
|
||||
DefaultButton = !string.IsNullOrEmpty(content.PrimaryButtonText) ? FAContentDialogButton.Primary :
|
||||
!string.IsNullOrEmpty(content.SecondaryButtonText) ? FAContentDialogButton.Secondary :
|
||||
FAContentDialogButton.Close
|
||||
};
|
||||
|
||||
var result = await dialog.ShowAsync(mainWindow);
|
||||
@@ -191,10 +186,10 @@ internal sealed class NotificationService : INotificationService
|
||||
// Execute callbacks based on result
|
||||
switch (result)
|
||||
{
|
||||
case ContentDialogResult.Primary:
|
||||
case FAContentDialogResult.Primary:
|
||||
content.OnPrimaryButtonClick?.Invoke();
|
||||
break;
|
||||
case ContentDialogResult.Secondary:
|
||||
case FAContentDialogResult.Secondary:
|
||||
content.OnSecondaryButtonClick?.Invoke();
|
||||
break;
|
||||
}
|
||||
@@ -206,14 +201,13 @@ internal sealed class NotificationService : INotificationService
|
||||
{
|
||||
try
|
||||
{
|
||||
// 从全局设置服务中读取通知开关状态
|
||||
var settingsFacade = HostSettingsFacadeProvider.GetOrCreate();
|
||||
var snapshot = settingsFacade.Settings.LoadSnapshot<AppSettingsSnapshot>(PluginSdk.SettingsScope.App);
|
||||
return snapshot.NotificationEnabled;
|
||||
}
|
||||
catch
|
||||
{
|
||||
// 如果读取失败,默认启用通知
|
||||
// 濠电姷顣介埀顒€鍟块埀顒€缍婇幃妯诲緞鐏炴儳鐝伴柣鐘叉处瑜板啰寰婇崹顕呯唵闁诡垱澹嗙花鍧楁偡濞嗘瑧鐣甸柡浣哥Т閻f繈宕熼鐐殿偧闂佽崵濮抽梽宥夊磹閺囥垹绠氶幖娣妽閸嬨劑鏌曟繛鐐澒闁稿鎸搁~婵囨綇閳轰礁缁?
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -286,8 +280,8 @@ internal sealed class NotificationService : INotificationService
|
||||
Show(new NotificationContent(title, message, Severity: NotificationSeverity.Error, Position: position));
|
||||
}
|
||||
|
||||
public Task<ContentDialogResult> ShowDialogInfoAsync(string title, string? message = null,
|
||||
string? primaryButtonText = "确定", string? closeButtonText = "取消")
|
||||
public Task<FAContentDialogResult> ShowDialogInfoAsync(string title, string? message = null,
|
||||
string? primaryButtonText = "OK", string? closeButtonText = "Cancel")
|
||||
{
|
||||
return ShowDialogAsync(new NotificationContent(
|
||||
title,
|
||||
@@ -298,8 +292,8 @@ internal sealed class NotificationService : INotificationService
|
||||
CloseButtonText: closeButtonText));
|
||||
}
|
||||
|
||||
public Task<ContentDialogResult> ShowDialogSuccessAsync(string title, string? message = null,
|
||||
string? primaryButtonText = "确定", string? closeButtonText = "取消")
|
||||
public Task<FAContentDialogResult> ShowDialogSuccessAsync(string title, string? message = null,
|
||||
string? primaryButtonText = "OK", string? closeButtonText = "Cancel")
|
||||
{
|
||||
return ShowDialogAsync(new NotificationContent(
|
||||
title,
|
||||
@@ -310,8 +304,8 @@ internal sealed class NotificationService : INotificationService
|
||||
CloseButtonText: closeButtonText));
|
||||
}
|
||||
|
||||
public Task<ContentDialogResult> ShowDialogWarningAsync(string title, string? message = null,
|
||||
string? primaryButtonText = "确定", string? closeButtonText = "取消")
|
||||
public Task<FAContentDialogResult> ShowDialogWarningAsync(string title, string? message = null,
|
||||
string? primaryButtonText = "OK", string? closeButtonText = "Cancel")
|
||||
{
|
||||
return ShowDialogAsync(new NotificationContent(
|
||||
title,
|
||||
@@ -322,8 +316,8 @@ internal sealed class NotificationService : INotificationService
|
||||
CloseButtonText: closeButtonText));
|
||||
}
|
||||
|
||||
public Task<ContentDialogResult> ShowDialogErrorAsync(string title, string? message = null,
|
||||
string? primaryButtonText = "确定", string? closeButtonText = "取消")
|
||||
public Task<FAContentDialogResult> ShowDialogErrorAsync(string title, string? message = null,
|
||||
string? primaryButtonText = "OK", string? closeButtonText = "Cancel")
|
||||
{
|
||||
return ShowDialogAsync(new NotificationContent(
|
||||
title,
|
||||
@@ -357,7 +351,7 @@ internal sealed class NotificationWindowManager
|
||||
var position = viewModel.Position;
|
||||
var windows = _windowsByPosition[position];
|
||||
|
||||
// 从设置中读取最大通知数量
|
||||
// 濠电偛顕慨鏉戭潩閿曞偆鏁婇柡鍥╁Х绾剧偓銇勯弮鈧Σ鎺楀储椤掑嫭鍋i柛銉憾閸ゆ瑧鎲搁弶鎸庡枠鐎殿喚鏁婚崺鈧い鎺嶇缁剁偟鎲搁弮鍫濈劦妞ゆ帊鐒﹂惃鎴︽煟閹垮嫮绡€鐎殿噮鍋呯€靛ジ寮堕幋鐑嗕画
|
||||
var maxNotifications = GetMaxNotificationsPerPosition();
|
||||
|
||||
if (windows.Count >= maxNotifications)
|
||||
@@ -395,14 +389,13 @@ internal sealed class NotificationWindowManager
|
||||
{
|
||||
try
|
||||
{
|
||||
// 从全局设置服务中读取最大通知数量
|
||||
// 濠电偛顕慨瀛橆殽閹间礁鐭楅煫鍥ㄦ磻濞岊亪鏌嶈閸撴盯骞忕€n喖绀堢憸蹇涘几閸岀偞鐓涢柛顐g箘瀛濇繝娈垮枤閸犳劗绮欐径鎰垫晣闁宠棄妫楀▓娲⒑閸涘﹦鎳勯柣妤侇殔閵嗘帡鎳滈棃娑氱獮閻熸粍妫冮崺鈧い鎺嶇劍閻ㄦ垿鏌i幙鍕瘈鐎殿噮鍋呯€靛ジ寮堕幋鐑嗕画
|
||||
var settingsFacade = HostSettingsFacadeProvider.GetOrCreate();
|
||||
var snapshot = settingsFacade.Settings.LoadSnapshot<AppSettingsSnapshot>(PluginSdk.SettingsScope.App);
|
||||
return snapshot.NotificationMaxPerPosition > 0 ? snapshot.NotificationMaxPerPosition : 5;
|
||||
}
|
||||
catch
|
||||
{
|
||||
// 如果读取失败,返回默认值
|
||||
return 5;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ public static class WebView2RuntimeProbe
|
||||
|
||||
public static WebView2RuntimeAvailability GetAvailability()
|
||||
{
|
||||
if (!OperatingSystem.IsWindows())
|
||||
if (OperatingSystem.IsMacOS())
|
||||
{
|
||||
return new WebView2RuntimeAvailability(
|
||||
IsAvailable: true,
|
||||
@@ -27,6 +27,14 @@ public static class WebView2RuntimeProbe
|
||||
Message: string.Empty);
|
||||
}
|
||||
|
||||
if (!OperatingSystem.IsWindows())
|
||||
{
|
||||
return new WebView2RuntimeAvailability(
|
||||
IsAvailable: false,
|
||||
Version: null,
|
||||
Message: "Embedded browser is currently unavailable on this platform.");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var version = TryGetVersionFromWebView2Api();
|
||||
|
||||
@@ -70,11 +70,25 @@
|
||||
<Setter Property="Foreground" Value="{DynamicResource AdaptiveTextPrimaryBrush}" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="ui|NumberBox">
|
||||
<Setter Property="Background" Value="{DynamicResource AdaptiveButtonBackgroundBrush}" />
|
||||
<Setter Property="BorderThickness" Value="1" />
|
||||
<Setter Property="BorderBrush" Value="{DynamicResource AdaptiveButtonBorderBrush}" />
|
||||
<Setter Property="Foreground" Value="{DynamicResource AdaptiveTextPrimaryBrush}" />
|
||||
<Style Selector="ui|FANumberBox">
|
||||
<Setter Property="Background" Value="Transparent" />
|
||||
<Setter Property="BorderBrush" Value="{DynamicResource ControlStrokeColorDefaultBrush}" />
|
||||
<Setter Property="CornerRadius" Value="{DynamicResource DesignCornerRadiusMd}" />
|
||||
<Setter Property="Foreground" Value="{DynamicResource TextFillColorPrimaryBrush}" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="ui|FANumberBox /template/ Button#PART_SpinUp">
|
||||
<Setter Property="Margin" Value="0" />
|
||||
<Setter Property="CornerRadius" Value="4,4,0,0" />
|
||||
<Setter Property="Background" Value="Transparent" />
|
||||
<Setter Property="Foreground" Value="{DynamicResource TextFillColorPrimaryBrush}" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="ui|FANumberBox /template/ Button#PART_SpinDown">
|
||||
<Setter Property="Margin" Value="0" />
|
||||
<Setter Property="CornerRadius" Value="0,0,4,4" />
|
||||
<Setter Property="Background" Value="Transparent" />
|
||||
<Setter Property="Foreground" Value="{DynamicResource TextFillColorPrimaryBrush}" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="CheckBox">
|
||||
@@ -125,7 +139,7 @@
|
||||
<Setter Property="Background" Value="{DynamicResource AdaptiveNavItemSelectedBackgroundBrush}" />
|
||||
</Style>
|
||||
|
||||
<Style Selector=".settings-scope ui|NumberBox">
|
||||
<Style Selector=".settings-scope ui|FANumberBox">
|
||||
<Setter Property="CornerRadius" Value="{DynamicResource DesignCornerRadiusSm}" />
|
||||
<Setter Property="MinHeight" Value="34" />
|
||||
</Style>
|
||||
@@ -152,7 +166,7 @@
|
||||
<Setter Property="Background" Value="{DynamicResource AdaptiveNavItemSelectedBackgroundBrush}" />
|
||||
</Style>
|
||||
|
||||
<Style Selector=".settings-scope ui|NavigationView, .settings-scope ui|NavigationViewItem, .settings-scope ui|SettingsExpander, .settings-scope ui|InfoBar, .settings-scope ListBoxItem">
|
||||
<Style Selector=".settings-scope ui|FANavigationView, .settings-scope ui|FANavigationViewItem, .settings-scope ui|FASettingsExpander, .settings-scope ui|FAInfoBar, .settings-scope ListBoxItem">
|
||||
<Setter Property="Foreground" Value="{DynamicResource AdaptiveTextPrimaryBrush}" />
|
||||
</Style>
|
||||
|
||||
@@ -169,9 +183,9 @@
|
||||
</Style>
|
||||
|
||||
<!--
|
||||
半透明表面样式类
|
||||
注意:这些样式使用纯色半透明画刷模拟玻璃效果,并非真正的 Mica/Acrylic 模糊材质。
|
||||
真正的 Mica/Acrylic 效果仅通过 WindowTransparencyLevel 在独立窗口上应用。
|
||||
鍗婇€忔槑琛ㄩ潰鏍峰紡绫?
|
||||
娉ㄦ剰锛氳繖浜涙牱寮忎娇鐢ㄧ函鑹插崐閫忔槑鐢诲埛妯℃嫙鐜荤拑鏁堟灉锛屽苟闈炵湡姝g殑 Mica/Acrylic 妯$硦鏉愯川銆?
|
||||
鐪熸鐨?Mica/Acrylic 鏁堟灉浠呴€氳繃 WindowTransparencyLevel 鍦ㄧ嫭绔嬬獥鍙d笂搴旂敤銆?
|
||||
-->
|
||||
|
||||
<Style Selector="Border.surface-translucent-panel">
|
||||
@@ -221,7 +235,7 @@
|
||||
<Setter Property="Opacity" Value="{DynamicResource AdaptiveGlassOverlayOpacity}" />
|
||||
</Style>
|
||||
|
||||
<!-- 向后兼容的旧样式类(已弃用) -->
|
||||
<!-- 鍚戝悗鍏煎鐨勬棫鏍峰紡绫伙紙宸插純鐢級 -->
|
||||
<Style Selector="Border.glass-panel">
|
||||
<Setter Property="Background" Value="{DynamicResource AdaptiveGlassPanelBackgroundBrush}" />
|
||||
<Setter Property="BorderBrush" Value="{DynamicResource AdaptiveGlassPanelBorderBrush}" />
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<Styles xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:ui="using:FluentAvalonia.UI.Controls"
|
||||
xmlns:fi="using:FluentIcons.Avalonia.Fluent">
|
||||
xmlns:fi="using:FluentIcons.Avalonia">
|
||||
|
||||
<Styles.Resources>
|
||||
<x:Double x:Key="PaneToggleButtonWidth">40</x:Double>
|
||||
@@ -115,7 +115,7 @@
|
||||
<Setter Property="Background" Value="{DynamicResource SubtleFillColorTertiaryBrush}" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="ui|NavigationView.settings-navigation-view">
|
||||
<Style Selector="ui|FANavigationView.settings-navigation-view">
|
||||
<Setter Property="Transitions">
|
||||
<Transitions>
|
||||
<DoubleTransition Property="Opacity" Duration="0:0:0.2" Easing="0.05,0.75,0.10,1.00" />
|
||||
@@ -123,7 +123,7 @@
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style Selector="ui|NavigationView.settings-navigation-view /template/ Border#NavigationViewBorder">
|
||||
<Style Selector="ui|FANavigationView.settings-navigation-view /template/ Border#NavigationViewBorder">
|
||||
<Setter Property="Transitions">
|
||||
<Transitions>
|
||||
<BrushTransition Property="Background" Duration="0:0:0.167" Easing="0.05,0.75,0.10,1.00" />
|
||||
@@ -131,7 +131,7 @@
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style Selector="ui|NavigationViewItem.settings-nav-item">
|
||||
<Style Selector="ui|FANavigationViewItem.settings-nav-item">
|
||||
<Setter Property="Transitions">
|
||||
<Transitions>
|
||||
<BrushTransition Property="Background" Duration="0:0:0.083" Easing="0.05,0.75,0.10,1.00" />
|
||||
@@ -140,11 +140,11 @@
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style Selector="ui|NavigationViewItem.settings-nav-item:pointerover">
|
||||
<Style Selector="ui|FANavigationViewItem.settings-nav-item:pointerover">
|
||||
<Setter Property="RenderTransform" Value="scale(1.01)" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="ui|NavigationViewItem.settings-nav-item:pressed">
|
||||
<Style Selector="ui|FANavigationViewItem.settings-nav-item:pressed">
|
||||
<Setter Property="RenderTransform" Value="scale(0.99)" />
|
||||
</Style>
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<Styles xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:ui="using:FluentAvalonia.UI.Controls"
|
||||
xmlns:fi="using:FluentIcons.Avalonia.Fluent"
|
||||
xmlns:fi="using:FluentIcons.Avalonia"
|
||||
xmlns:behaviors="using:LanMountainDesktop.Behaviors">
|
||||
|
||||
<Style Selector="StackPanel.settings-page-container">
|
||||
@@ -162,59 +162,59 @@
|
||||
<Setter Property="ColumnSpacing" Value="12" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="ui|SettingsExpander">
|
||||
<Style Selector="ui|FASettingsExpander">
|
||||
<Setter Property="HorizontalAlignment" Value="Stretch" />
|
||||
<Setter Property="MinWidth" Value="0" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="ui|SettingsExpander ComboBox, ui|SettingsExpander TextBox, ui|SettingsExpander NumericUpDown">
|
||||
<Style Selector="ui|FASettingsExpander ComboBox, ui|FASettingsExpander TextBox, ui|FASettingsExpander NumericUpDown">
|
||||
<Setter Property="HorizontalAlignment" Value="Left" />
|
||||
<Setter Property="MinWidth" Value="0" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="ui|SettingsExpanderItem ComboBox, ui|SettingsExpanderItem TextBox, ui|SettingsExpanderItem NumericUpDown">
|
||||
<Style Selector="ui|FASettingsExpanderItem ComboBox, ui|FASettingsExpanderItem TextBox, ui|FASettingsExpanderItem NumericUpDown">
|
||||
<Setter Property="HorizontalAlignment" Value="Stretch" />
|
||||
<Setter Property="MinWidth" Value="0" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="ui|SettingsExpander ToggleSwitch, ui|SettingsExpanderItem ToggleSwitch">
|
||||
<Style Selector="ui|FASettingsExpander ToggleSwitch, ui|FASettingsExpanderItem ToggleSwitch">
|
||||
<Setter Property="HorizontalAlignment" Value="Left" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="ui|SettingsExpander.settings-expander-card">
|
||||
<Style Selector="ui|FASettingsExpander.settings-expander-card">
|
||||
<Setter Property="Margin" Value="0,0,0,14" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="ui|SettingsExpander.settings-expander-card /template/ ContentPresenter#FooterContentPresenter">
|
||||
<Style Selector="ui|FASettingsExpander.settings-expander-card /template/ ContentPresenter#FooterContentPresenter">
|
||||
<Setter Property="Margin" Value="0,6,0,2" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="ui|SettingsExpander.settings-expander-card /template/ ContentPresenter#ContentPresenter">
|
||||
<Style Selector="ui|FASettingsExpander.settings-expander-card /template/ ContentPresenter#ContentPresenter">
|
||||
<Setter Property="Margin" Value="0,14,0,0" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="ui|SettingsExpander.settings-expander-card ComboBox, .settings-section-card ComboBox, .settings-option-card ComboBox">
|
||||
<Style Selector="ui|FASettingsExpander.settings-expander-card ComboBox, .settings-section-card ComboBox, .settings-option-card ComboBox">
|
||||
<Setter Property="MinWidth" Value="220" />
|
||||
<Setter Property="HorizontalAlignment" Value="Stretch" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="ui|SettingsExpander.settings-expander-card TextBox, .settings-section-card TextBox, .settings-option-card TextBox">
|
||||
<Style Selector="ui|FASettingsExpander.settings-expander-card TextBox, .settings-section-card TextBox, .settings-option-card TextBox">
|
||||
<Setter Property="HorizontalAlignment" Value="Stretch" />
|
||||
<Setter Property="MinHeight" Value="38" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="ui|SettingsExpander.settings-expander-card NumericUpDown, .settings-section-card NumericUpDown, .settings-option-card NumericUpDown">
|
||||
<Style Selector="ui|FASettingsExpander.settings-expander-card NumericUpDown, .settings-section-card NumericUpDown, .settings-option-card NumericUpDown">
|
||||
<Setter Property="HorizontalAlignment" Value="Stretch" />
|
||||
<Setter Property="MinHeight" Value="38" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="ui|SettingsExpander.settings-expander-card ToggleSwitch, .settings-option-card ToggleSwitch, .settings-list-item ToggleSwitch">
|
||||
<Style Selector="ui|FASettingsExpander.settings-expander-card ToggleSwitch, .settings-option-card ToggleSwitch, .settings-list-item ToggleSwitch">
|
||||
<Setter Property="VerticalAlignment" Value="Center" />
|
||||
<Setter Property="OnContent" Value="{x:Null}" />
|
||||
<Setter Property="OffContent" Value="{x:Null}" />
|
||||
</Style>
|
||||
|
||||
<Style Selector=".settings-section-card Button, .settings-option-card Button, .settings-list-item Button, ui|SettingsExpander.settings-expander-card Button">
|
||||
<Style Selector=".settings-section-card Button, .settings-option-card Button, .settings-list-item Button, ui|FASettingsExpander.settings-expander-card Button">
|
||||
<Setter Property="MinHeight" Value="36" />
|
||||
<Setter Property="Padding" Value="14,8" />
|
||||
</Style>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:fa="clr-namespace:FluentIcons.Avalonia.Fluent;assembly=FluentIcons.Avalonia.Fluent"
|
||||
xmlns:fa="clr-namespace:FluentIcons.Avalonia;assembly=FluentIcons.Avalonia"
|
||||
xmlns:mi="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
|
||||
xmlns:themes="clr-namespace:Material.Styles.Themes;assembly=Material.Styles"
|
||||
mc:Ignorable="d"
|
||||
@@ -16,7 +16,7 @@
|
||||
CanResize="True"
|
||||
SizeToContent="Manual"
|
||||
ShowInTaskbar="False"
|
||||
SystemDecorations="BorderOnly"
|
||||
WindowDecorations="BorderOnly"
|
||||
Background="Transparent"
|
||||
Title="Component Editor">
|
||||
<Window.Resources>
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -41,13 +41,11 @@
|
||||
ColumnSpacing="4">
|
||||
<ToggleButton x:Name="TickRadioButton"
|
||||
Classes="component-editor-segmented-choice"
|
||||
Checked="OnSecondHandChanged"
|
||||
Unchecked="OnSecondHandChanged" />
|
||||
IsCheckedChanged="OnSecondHandChanged" />
|
||||
<ToggleButton x:Name="SweepRadioButton"
|
||||
Grid.Column="1"
|
||||
Classes="component-editor-segmented-choice"
|
||||
Checked="OnSecondHandChanged"
|
||||
Unchecked="OnSecondHandChanged" />
|
||||
IsCheckedChanged="OnSecondHandChanged" />
|
||||
</Grid>
|
||||
</Border>
|
||||
</StackPanel>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:vm="using:LanMountainDesktop.ViewModels"
|
||||
x:Class="LanMountainDesktop.Views.ComponentEditors.ShortcutComponentEditor"
|
||||
@@ -20,7 +20,7 @@
|
||||
<Grid ColumnDefinitions="*,Auto">
|
||||
<TextBox Text="{Binding TargetPath}"
|
||||
IsReadOnly="True"
|
||||
Watermark="{Binding TargetPathPlaceholder}"
|
||||
PlaceholderText="{Binding TargetPathPlaceholder}"
|
||||
Grid.Column="0" />
|
||||
<Button Content="{Binding BrowseButtonText}"
|
||||
Click="OnBrowseClick"
|
||||
|
||||
@@ -21,8 +21,7 @@
|
||||
<ToggleSwitch x:Name="EnabledToggleSwitch"
|
||||
Grid.Column="1"
|
||||
VerticalAlignment="Center"
|
||||
Checked="OnEnabledChanged"
|
||||
Unchecked="OnEnabledChanged" />
|
||||
IsCheckedChanged="OnEnabledChanged" />
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
|
||||
@@ -77,13 +77,11 @@
|
||||
ColumnSpacing="4">
|
||||
<ToggleButton x:Name="TickRadioButton"
|
||||
Classes="component-editor-segmented-choice"
|
||||
Checked="OnSecondHandChanged"
|
||||
Unchecked="OnSecondHandChanged" />
|
||||
IsCheckedChanged="OnSecondHandChanged" />
|
||||
<ToggleButton x:Name="SweepRadioButton"
|
||||
Grid.Column="1"
|
||||
Classes="component-editor-segmented-choice"
|
||||
Checked="OnSecondHandChanged"
|
||||
Unchecked="OnSecondHandChanged" />
|
||||
IsCheckedChanged="OnSecondHandChanged" />
|
||||
</Grid>
|
||||
</Border>
|
||||
</StackPanel>
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
MinWidth="760"
|
||||
MinHeight="500"
|
||||
CanResize="True"
|
||||
SystemDecorations="Full"
|
||||
WindowDecorations="Full"
|
||||
Title="Component Library"
|
||||
Background="{DynamicResource AdaptiveSurfaceBaseBrush}">
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
@@ -75,7 +75,7 @@
|
||||
Grid.Column="1"
|
||||
VerticalContentAlignment="Center"
|
||||
HorizontalContentAlignment="Left"
|
||||
Watermark="https://example.com"
|
||||
PlaceholderText="https://example.com"
|
||||
Text="https://www.bing.com"
|
||||
KeyDown="OnAddressTextBoxKeyDown" />
|
||||
|
||||
|
||||
@@ -4,11 +4,10 @@ using Avalonia.Controls;
|
||||
using Avalonia.Input;
|
||||
using Avalonia.Interactivity;
|
||||
using Avalonia.Media;
|
||||
using Avalonia.Platform;
|
||||
using Avalonia.Styling;
|
||||
using AvaloniaWebView;
|
||||
using LanMountainDesktop.ComponentSystem;
|
||||
using LanMountainDesktop.Services;
|
||||
using WebViewCore.Events;
|
||||
|
||||
namespace LanMountainDesktop.Views.Components;
|
||||
|
||||
@@ -28,7 +27,7 @@ public partial class BrowserWidget : UserControl, IDesktopComponentWidget,
|
||||
private bool _isEditMode;
|
||||
private bool _isWebViewActive = true;
|
||||
private bool _isWebViewFaulted;
|
||||
private WebView? _browserWebView;
|
||||
private NativeWebView? _browserWebView;
|
||||
private readonly WebView2RuntimeAvailability _runtimeAvailability;
|
||||
private bool _isDisposed;
|
||||
|
||||
@@ -78,7 +77,8 @@ public partial class BrowserWidget : UserControl, IDesktopComponentWidget,
|
||||
|
||||
if (_browserWebView is not null)
|
||||
{
|
||||
_browserWebView.NavigationStarting -= OnBrowserWebViewNavigationStarting;
|
||||
_browserWebView.NavigationStarted -= OnBrowserWebViewNavigationStarting;
|
||||
_browserWebView.EnvironmentRequested -= OnBrowserWebViewEnvironmentRequested;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -294,15 +294,32 @@ public partial class BrowserWidget : UserControl, IDesktopComponentWidget,
|
||||
}
|
||||
}
|
||||
|
||||
private void OnBrowserWebViewNavigationStarting(object? sender, WebViewUrlLoadingEventArg e)
|
||||
private void OnBrowserWebViewNavigationStarting(object? sender, WebViewNavigationStartingEventArgs e)
|
||||
{
|
||||
if (e.Url is null)
|
||||
if (e.Request is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_lastKnownUri = e.Url;
|
||||
AddressTextBox.Text = e.Url.ToString();
|
||||
_lastKnownUri = e.Request;
|
||||
AddressTextBox.Text = e.Request.ToString();
|
||||
}
|
||||
|
||||
private void OnBrowserWebViewEnvironmentRequested(object? sender, WebViewEnvironmentRequestedEventArgs e)
|
||||
{
|
||||
if (e is not WindowsWebView2EnvironmentRequestedEventArgs windowsArgs)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
windowsArgs.UserDataFolder = WebView2RuntimeProbe.ResolveUserDataFolder();
|
||||
}
|
||||
catch (Exception ex) when (!UiExceptionGuard.IsFatalException(ex))
|
||||
{
|
||||
AppLogger.Warn("WebView2", "Failed to configure the WebView2 user data folder for BrowserWidget.", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateWebViewActiveState()
|
||||
@@ -358,6 +375,7 @@ public partial class BrowserWidget : UserControl, IDesktopComponentWidget,
|
||||
GoButton.IsEnabled = true;
|
||||
AddressTextBox.IsEnabled = true;
|
||||
UnavailableOverlay.IsVisible = false;
|
||||
TryNavigate(_lastKnownUri, "ActivateWebView");
|
||||
}
|
||||
|
||||
private void DeactivateWebView(bool clearUrl)
|
||||
@@ -383,8 +401,7 @@ public partial class BrowserWidget : UserControl, IDesktopComponentWidget,
|
||||
|
||||
try
|
||||
{
|
||||
_browserWebView.Reload();
|
||||
return true;
|
||||
return _browserWebView.Refresh();
|
||||
}
|
||||
catch (Exception ex) when (!UiExceptionGuard.IsFatalException(ex))
|
||||
{
|
||||
@@ -402,7 +419,7 @@ public partial class BrowserWidget : UserControl, IDesktopComponentWidget,
|
||||
|
||||
try
|
||||
{
|
||||
_browserWebView.Url = uri;
|
||||
_browserWebView.Navigate(uri);
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex) when (!UiExceptionGuard.IsFatalException(ex))
|
||||
@@ -421,7 +438,7 @@ public partial class BrowserWidget : UserControl, IDesktopComponentWidget,
|
||||
|
||||
try
|
||||
{
|
||||
_browserWebView.Url = null;
|
||||
_browserWebView.Navigate(new Uri("about:blank"));
|
||||
}
|
||||
catch
|
||||
{
|
||||
@@ -466,12 +483,14 @@ public partial class BrowserWidget : UserControl, IDesktopComponentWidget,
|
||||
return;
|
||||
}
|
||||
|
||||
_browserWebView = new WebView
|
||||
_browserWebView = new NativeWebView
|
||||
{
|
||||
Source = new Uri("about:blank"),
|
||||
IsVisible = false,
|
||||
IsHitTestVisible = false
|
||||
};
|
||||
_browserWebView.NavigationStarting += OnBrowserWebViewNavigationStarting;
|
||||
_browserWebView.NavigationStarted += OnBrowserWebViewNavigationStarting;
|
||||
_browserWebView.EnvironmentRequested += OnBrowserWebViewEnvironmentRequested;
|
||||
WebViewPresenter.Children.Insert(0, _browserWebView);
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:fi="using:FluentIcons.Avalonia.Fluent"
|
||||
xmlns:fi="using:FluentIcons.Avalonia"
|
||||
xmlns:symbol="using:FluentIcons.Common"
|
||||
x:Class="LanMountainDesktop.Views.Components.NotificationBoxWidget">
|
||||
|
||||
@@ -9,18 +9,18 @@
|
||||
Background="Transparent"
|
||||
ClipToBounds="True">
|
||||
<Grid>
|
||||
<!-- 主卡片 -->
|
||||
<!-- 涓诲崱鐗?-->
|
||||
<Border x:Name="CardBorder"
|
||||
Background="#FCFCFD"
|
||||
CornerRadius="{DynamicResource DesignCornerRadiusComponent}"
|
||||
Padding="12,10">
|
||||
<Grid RowDefinitions="Auto,*,Auto">
|
||||
<!-- 头部 -->
|
||||
<!-- 澶撮儴 -->
|
||||
<Grid Grid.Row="0" ColumnDefinitions="*,Auto">
|
||||
<StackPanel Orientation="Horizontal" Spacing="6" VerticalAlignment="Center">
|
||||
<fi:SymbolIcon x:Name="HeaderIcon" Symbol="{x:Static symbol:Symbol.MailInbox}" FontSize="16" />
|
||||
<TextBlock x:Name="HeaderTextBlock"
|
||||
Text="消息盒子"
|
||||
Text="娑堟伅鐩掑瓙"
|
||||
FontSize="15"
|
||||
FontWeight="SemiBold" />
|
||||
<Border x:Name="UnreadBadge"
|
||||
@@ -46,24 +46,24 @@
|
||||
</Button>
|
||||
</Grid>
|
||||
|
||||
<!-- 通知列表 -->
|
||||
<!-- 閫氱煡鍒楄〃 -->
|
||||
<ScrollViewer Grid.Row="1"
|
||||
Margin="0,8,0,0"
|
||||
VerticalScrollBarVisibility="Auto">
|
||||
<StackPanel x:Name="NotificationListPanel" Spacing="6" />
|
||||
</ScrollViewer>
|
||||
|
||||
<!-- 空状态 -->
|
||||
<!-- 绌虹姸鎬?-->
|
||||
<TextBlock x:Name="EmptyStateText"
|
||||
Grid.Row="1"
|
||||
Text="暂无通知"
|
||||
Text="鏆傛棤閫氱煡"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Foreground="#8B95A5"
|
||||
FontSize="13"
|
||||
IsVisible="False" />
|
||||
|
||||
<!-- 隐私模式遮罩 -->
|
||||
<!-- 闅愮妯″紡閬僵 -->
|
||||
<Border x:Name="PrivacyOverlay"
|
||||
Grid.Row="1"
|
||||
Background="{DynamicResource SolidBackgroundFillColorBaseBrush}"
|
||||
@@ -73,13 +73,13 @@
|
||||
VerticalAlignment="Center"
|
||||
Spacing="6">
|
||||
<fi:SymbolIcon Symbol="{x:Static symbol:Symbol.EyeOff}" FontSize="24" Foreground="#8B95A5" />
|
||||
<TextBlock Text="您有新的通知"
|
||||
<TextBlock Text="鎮ㄦ湁鏂扮殑閫氱煡"
|
||||
Foreground="#8B95A5"
|
||||
FontSize="12" />
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
||||
<!-- 底部状态 -->
|
||||
<!-- 搴曢儴鐘舵€?-->
|
||||
<TextBlock x:Name="StatusTextBlock"
|
||||
Grid.Row="2"
|
||||
FontSize="11"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
@@ -72,7 +72,7 @@
|
||||
TextWrapping="Wrap" />
|
||||
<TextBox x:Name="DialogRenameTextBox"
|
||||
IsVisible="False"
|
||||
Watermark="Enter session name"
|
||||
PlaceholderText="Enter session name"
|
||||
MinWidth="120"
|
||||
VerticalContentAlignment="Center" />
|
||||
<Grid ColumnDefinitions="*,*"
|
||||
|
||||
@@ -577,7 +577,7 @@ public partial class StudySessionHistoryWidget : UserControl, IDesktopComponentW
|
||||
CultureInfo.InvariantCulture,
|
||||
L("study.session_history.dialog.rename_message", "Set a new name for \"{0}\"."),
|
||||
label);
|
||||
DialogRenameTextBox.Watermark = L("study.session_history.rename_placeholder", "Enter session name");
|
||||
DialogRenameTextBox.PlaceholderText = L("study.session_history.rename_placeholder", "Enter session name");
|
||||
if (string.IsNullOrWhiteSpace(DialogRenameTextBox.Text))
|
||||
{
|
||||
DialogRenameTextBox.Text = label;
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
x:Class="LanMountainDesktop.Views.DesktopWidgetWindow"
|
||||
Title="Desktop Component"
|
||||
ShowInTaskbar="False"
|
||||
SystemDecorations="None"
|
||||
WindowDecorations="None"
|
||||
Background="Transparent"
|
||||
Topmost="False"
|
||||
SizeToContent="WidthAndHeight"
|
||||
|
||||
@@ -2,13 +2,13 @@
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:vm="using:LanMountainDesktop.ViewModels"
|
||||
xmlns:ui="using:FluentAvalonia.UI.Controls"
|
||||
xmlns:fi="using:FluentIcons.Avalonia.Fluent"
|
||||
xmlns:fi="using:FluentIcons.Avalonia"
|
||||
xmlns:converters="using:Avalonia.Data.Converters"
|
||||
x:Class="LanMountainDesktop.Views.FusedDesktopComponentLibraryControl"
|
||||
x:DataType="vm:ComponentLibraryWindowViewModel">
|
||||
|
||||
<UserControl.Styles>
|
||||
<!-- 分类列表项样式 - 遵循 Fluent NavigationView 风格 -->
|
||||
<!-- 闂備礁鎲$敮鎺懳涘☉姘仏妞ゆ劧绠戠粈鍡樹繆閵堝懎顏ラ柍褜鍓欓崯顖炲Φ閸曨厽鍠嗛柛鏇ㄥ幖椤ュ酣鎮?- 闂傚倷绶¢崜鐔奉焽瑜旈獮?Fluent NavigationView 濠碉紕鍋涢鍛偓娑掓櫊閹?-->
|
||||
<Style Selector="ListBoxItem.category-item">
|
||||
<Setter Property="Padding" Value="0"/>
|
||||
<Setter Property="Margin" Value="0,2"/>
|
||||
@@ -30,7 +30,7 @@
|
||||
<Setter Property="Background" Value="{DynamicResource SubtleFillColorTertiaryBrush}"/>
|
||||
</Style>
|
||||
|
||||
<!-- 分类项图标和文字 -->
|
||||
<!-- 闂備礁鎲$敮鎺懳涘☉姘仏妞ゆ劧绲绘禍婊堟煟閻斿搫顣肩紒鍌氱墦閺屸€愁吋閸涱喗鎮欓梺纭呮腹閸楀啿顕i鍕倞鐟滃繘骞?-->
|
||||
<Style Selector="ListBoxItem.category-item fi|FluentIcon.category-icon">
|
||||
<Setter Property="Foreground" Value="{DynamicResource AdaptiveTextPrimaryBrush}"/>
|
||||
</Style>
|
||||
@@ -50,11 +50,11 @@
|
||||
<Grid ColumnDefinitions="Auto,*"
|
||||
ColumnSpacing="0"
|
||||
Margin="0">
|
||||
<!-- 左侧导航列 - 分类列表 + 底部"查找更多组件" -->
|
||||
<!-- 闁诲骸缍婂鑽ょ磽濮樿泛鐤鹃柛鎾茶閸嬫挻鎷呴崘顭戞闂佺硶鏅涢幊妯虹暦?- 闂備礁鎲$敮鎺懳涘☉姘仏妞ゆ劧绠戠粈鍡樹繆閵堝懎顏ラ柍?+ 闂佸湱鍘ч悺銊ッ洪悢鐓庣??闂備礁鎼悮顐﹀磿閸欏鐝舵慨妞诲亾鐎殿喗鎸冲鍫曞箣椤撶啿鏌ょ紓鍌氬€风粈浣衡偓姘间簻閳? -->
|
||||
<Border Width="280"
|
||||
Background="Transparent">
|
||||
<Grid RowDefinitions="*,Auto">
|
||||
<!-- 分类列表 -->
|
||||
<!-- 闂備礁鎲$敮鎺懳涘☉姘仏妞ゆ劧绠戠粈鍡樹繆閵堝懎顏ラ柍?-->
|
||||
<ListBox x:Name="CategoryListBox"
|
||||
Grid.Row="0"
|
||||
Background="Transparent"
|
||||
@@ -81,7 +81,7 @@
|
||||
</ListBox.ItemTemplate>
|
||||
</ListBox>
|
||||
|
||||
<!-- 底部"查找更多组件" - 在左侧导航列底部 -->
|
||||
<!-- 闂佸湱鍘ч悺銊ッ洪悢鐓庣??闂備礁鎼悮顐﹀磿閸欏鐝舵慨妞诲亾鐎殿喗鎸冲鍫曞箣椤撶啿鏌ょ紓鍌氬€风粈浣衡偓姘间簻閳? - 闂備線娼荤拹鐔煎礉鐏炲墽鈻曢煫鍥ㄦ⒒閻熷湱鎲稿澶樻晪闂侇剙绉甸崵瀣亜韫囨挸顏╅柣蹇旂懇楠炴牜鈧稒蓱缁€瀣煕?-->
|
||||
<StackPanel Grid.Row="1"
|
||||
Margin="12,8,8,12">
|
||||
<Border Height="1"
|
||||
@@ -93,42 +93,42 @@
|
||||
Click="OnFindMoreComponentsClick">
|
||||
<StackPanel Orientation="Horizontal" Spacing="6">
|
||||
<fi:FluentIcon Icon="Globe" IconVariant="Regular" FontSize="14"/>
|
||||
<TextBlock Text="查找更多组件"/>
|
||||
<TextBlock Text="Find More Components"/>
|
||||
</StackPanel>
|
||||
</Button>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
<!-- 右侧内容区与左侧的分隔线 -->
|
||||
<!-- 闂備礁鎲¢悷銉╁储閺嶎厼鐤鹃柛顐f礀缁€鍐煕濞戝崬寮鹃柛鐔锋喘閺屾盯寮介浣碘偓鍐磼濡も偓閼活垶顢欒箛娑欐櫆闁圭瀛╅悵鐑芥⒑濮瑰洤濡奸悗姘煎墴瀹曡鎯旈妸锔规寗闂佸搫鍟崐绋库枔?-->
|
||||
<Border Grid.Column="1"
|
||||
Width="1"
|
||||
HorizontalAlignment="Left"
|
||||
Background="{DynamicResource AdaptiveGlassPanelBorderBrush}"
|
||||
Opacity="0.5"/>
|
||||
|
||||
<!-- 组件预览区 (右侧) -->
|
||||
<!-- 缂傚倸鍊风粈浣衡偓姘间簻閳诲酣濮€閳藉懐鐭楅梺鍛婃处閸n喖顭囬弮鍫熺厱?(闂備礁鎲¢悷銉╁储閺嶎厼鐤? -->
|
||||
<ScrollViewer Grid.Column="1"
|
||||
VerticalScrollBarVisibility="Auto"
|
||||
HorizontalScrollBarVisibility="Disabled">
|
||||
<StackPanel Margin="16,8,12,8"
|
||||
Spacing="0">
|
||||
|
||||
<!-- 有选中组件时的显示 -->
|
||||
<!-- 闂備礁鎼悧鍡浰囬悽绋跨劦妞ゆ巻鍋撴い锔诲櫍閹虫瑩骞嬮悩鐢碉紲闂佸憡娲︽禍婵嬵敃娴犲鐓涢柛鎰╁妼椤h櫕绻涢崼鐔风伌鐎殿喕鍗冲畷婊嗩槹濞?-->
|
||||
<Panel IsVisible="{Binding SelectedComponent, Converter={x:Static converters:ObjectConverters.IsNotNull}}">
|
||||
|
||||
<!-- 组件展示面板 - 有独立背景色,与窗口背景形成层级分界 -->
|
||||
<!-- 缂傚倸鍊风粈浣衡偓姘间簻閳诲酣濮€椤厽鍕冮梺鍝勬川婵増绂掑☉銏♀拻闁割偅绋戦悘顏呯節?- 闂備礁鎼悧鍡浰囨潏鈹惧亾濮樼厧骞樼紒顔规櫇閳ь剨缍嗛崢濂稿礈瑜版帗鐓涢柛婊€绀侀悘銉ヮ熆閻熷府韬柡浣哥Ф娴狅箓鎳栭埡鍐╁枦缂傚倷鐒﹂崝鏍€冮崨鑸汗婵炴垯鍨洪崵鍕倶閻愰潧浜鹃柣婵愬灣閹叉悂鎳滈鈧悘顏堟煕閵婏附鐨戝ù鐙呯畵瀹曟帒顭ㄩ崼銏犵闂備礁鎲$敮鎺懳涘☉銏犵柧?-->
|
||||
<Border Classes="surface-translucent-panel"
|
||||
CornerRadius="{DynamicResource DesignCornerRadiusLg}"
|
||||
Padding="20">
|
||||
<StackPanel Spacing="16">
|
||||
<!-- 组件标题 -->
|
||||
<!-- 缂傚倸鍊风粈浣衡偓姘间簻閳诲酣濮€閵堝懎鍞ㄩ梺鎼炲労閸擄箓寮?-->
|
||||
<TextBlock FontSize="28"
|
||||
FontWeight="SemiBold"
|
||||
Foreground="{DynamicResource AdaptiveTextPrimaryBrush}"
|
||||
Text="{Binding SelectedComponent.DisplayName}"/>
|
||||
|
||||
<!-- 固定大小的预览卡片 -->
|
||||
<!-- 闂備焦鎮堕崕閬嶅箹椤愶附鍋╅柣鎰靛墮缁剁偟鎲稿澶嬪剭妞ゆ帒瀚崕宥夋煕閺囥劌鐏遍柡鍡樻礋閹嘲鈻庤箛鏇烆暫閻庤娲熸禍鍫曞箖?-->
|
||||
<Border CornerRadius="{DynamicResource DesignCornerRadiusSm}"
|
||||
Background="{DynamicResource AdaptiveSurfaceBaseBrush}"
|
||||
BorderBrush="{DynamicResource AdaptiveGlassPanelBorderBrush}"
|
||||
@@ -137,7 +137,7 @@
|
||||
Height="300"
|
||||
HorizontalAlignment="Center">
|
||||
<Grid Margin="16">
|
||||
<!-- 预览图片 -->
|
||||
<!-- 濠碘槅鍋呭妯尖偓姘煎灦閿濈偛顓兼径濠勫€為梺鍛婃寙閸愮偓姣?-->
|
||||
<Image Source="{Binding SelectedComponent.PreviewBitmap}"
|
||||
Stretch="Uniform"
|
||||
HorizontalAlignment="Center"
|
||||
@@ -145,7 +145,7 @@
|
||||
RenderOptions.BitmapInterpolationMode="HighQuality"
|
||||
IsVisible="{Binding SelectedComponent.IsPreviewReady}"/>
|
||||
|
||||
<!-- 加载中状态 -->
|
||||
<!-- 闂備礁鎲″缁樻叏閹灐褰掑炊閵娧€鏋栧銈嗘尵婵鐟ч梻?-->
|
||||
<Border IsVisible="{Binding SelectedComponent.IsPreviewPending}"
|
||||
Background="{DynamicResource AdaptiveSurfaceBaseBrush}">
|
||||
<StackPanel HorizontalAlignment="Center"
|
||||
@@ -161,7 +161,7 @@
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
||||
<!-- 失败状态 -->
|
||||
<!-- 濠电姰鍨洪崕鑲╁垝閸撗勫枂闁挎洖鍊归崑鎰版煠閸濄儺鏆柛?-->
|
||||
<Border IsVisible="{Binding SelectedComponent.IsPreviewFailed}"
|
||||
Background="{DynamicResource AdaptiveSurfaceBaseBrush}">
|
||||
<StackPanel HorizontalAlignment="Center"
|
||||
@@ -188,7 +188,7 @@
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
<!-- "添加小组件"按钮 - 在面板内居中,使用主题强调色 -->
|
||||
<!-- "婵犵數鍎戠紞鈧い鏇嗗嫭鍙忛柣鎰悁閻掑﹪鐓崶銊︾闁活厼顑呴湁?闂備礁婀遍…鍫ニ囬悽绋跨?- 闂備線娼荤拹鐔煎礉閹存繍鐒藉ù鍏兼綑缁狙囨煕椤垵鏋涢柡浣哥埣閹﹢鎮欓崣澶婃闂佺厧鐏氶崹鍧楀极瀹ュ洣娌柣鎾崇岸閺嬪繘姊哄ú缁樺▏闁告柨顑囬埀顒勬涧閺堫剟鏁嶉幇顑╃喖宕崟顓犵暢闂佽崵濮撮鍛村疮閾忣偆鐝?-->
|
||||
<Button HorizontalAlignment="Center"
|
||||
Classes="accent"
|
||||
Padding="24,10"
|
||||
@@ -196,14 +196,14 @@
|
||||
Click="OnAddComponentClick">
|
||||
<StackPanel Orientation="Horizontal" Spacing="8">
|
||||
<fi:FluentIcon Icon="Add" IconVariant="Regular" FontSize="16"/>
|
||||
<TextBlock Text="添加小组件" FontWeight="SemiBold"/>
|
||||
<TextBlock Text="Add Component" FontWeight="SemiBold"/>
|
||||
</StackPanel>
|
||||
</Button>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
</Panel>
|
||||
|
||||
<!-- 空状态 -->
|
||||
<!-- 缂傚倷绀侀惌浣糕枍閿濆棙鍙忛柟闂寸缁?-->
|
||||
<Grid IsVisible="{Binding SelectedComponent, Converter={x:Static converters:ObjectConverters.IsNull}}"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
@@ -218,7 +218,7 @@
|
||||
<TextBlock HorizontalAlignment="Center"
|
||||
FontSize="16"
|
||||
Foreground="{DynamicResource AdaptiveTextSecondaryBrush}"
|
||||
Text="请从左侧选择一个组件"/>
|
||||
Text="Select a component to view its details."/>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
|
||||
@@ -1,24 +1,24 @@
|
||||
<Window xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:controls="using:LanMountainDesktop.Views"
|
||||
xmlns:fi="using:FluentIcons.Avalonia.Fluent"
|
||||
xmlns:fi="using:FluentIcons.Avalonia"
|
||||
x:Class="LanMountainDesktop.Views.FusedDesktopComponentLibraryWindow"
|
||||
Width="860" Height="620"
|
||||
MinWidth="600" MinHeight="500"
|
||||
Width="860"
|
||||
Height="620"
|
||||
MinWidth="600"
|
||||
MinHeight="500"
|
||||
CanResize="True"
|
||||
WindowStartupLocation="CenterScreen"
|
||||
SystemDecorations="BorderOnly"
|
||||
WindowDecorations="BorderOnly"
|
||||
ExtendClientAreaToDecorationsHint="True"
|
||||
ExtendClientAreaChromeHints="NoChrome"
|
||||
ExtendClientAreaTitleBarHeightHint="48"
|
||||
Background="Transparent"
|
||||
Title="添加小组件">
|
||||
Title="Add Component">
|
||||
|
||||
<Grid x:Name="RootGrid"
|
||||
Classes="settings-scope"
|
||||
Background="{DynamicResource AdaptiveSettingsWindowBackgroundBrush}"
|
||||
RowDefinitions="Auto,*">
|
||||
<!-- 自定义标题栏 - 与 SettingsWindow 风格一致 -->
|
||||
<Border x:Name="WindowTitleBarHost"
|
||||
Height="48"
|
||||
Padding="12,0,12,0"
|
||||
@@ -41,14 +41,14 @@
|
||||
FontSize="12"
|
||||
FontWeight="SemiBold"
|
||||
IsHitTestVisible="False"
|
||||
Text="添加小组件" />
|
||||
Text="Add Component" />
|
||||
|
||||
<TextBlock Grid.Column="2"
|
||||
FontSize="12"
|
||||
Opacity="0.6"
|
||||
IsHitTestVisible="False"
|
||||
VerticalAlignment="Center"
|
||||
Text="将精美组件放置在您的系统桌面上(负一屏)" />
|
||||
Text="Browse available widgets and add them to the current fused desktop layout." />
|
||||
|
||||
<Button x:Name="CloseWindowButton"
|
||||
Grid.Column="3"
|
||||
@@ -65,7 +65,6 @@
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
<!-- 组件库控件 -->
|
||||
<controls:FusedDesktopComponentLibraryControl x:Name="LibraryControl"
|
||||
Grid.Row="1"
|
||||
Margin="12,8,16,8" />
|
||||
|
||||
@@ -16,7 +16,7 @@ using LanMountainDesktop.Services;
|
||||
|
||||
namespace LanMountainDesktop.Views;
|
||||
|
||||
public partial class MainWindow
|
||||
public partial class MainWindow : Window
|
||||
{
|
||||
private const double PreviewRenderCellSizeMin = 42;
|
||||
private const double PreviewRenderCellSizeMax = 112;
|
||||
|
||||
@@ -28,7 +28,7 @@ using SymbolIcon = FluentIcons.Avalonia.SymbolIcon;
|
||||
|
||||
namespace LanMountainDesktop.Views;
|
||||
|
||||
public partial class MainWindow
|
||||
public partial class MainWindow : Window
|
||||
{
|
||||
private readonly List<DesktopComponentPlacementSnapshot> _desktopComponentPlacements = [];
|
||||
private readonly Dictionary<int, Grid> _desktopPageComponentGrids = new();
|
||||
@@ -390,12 +390,10 @@ public partial class MainWindow
|
||||
|
||||
if (OperatingSystem.IsWindows())
|
||||
{
|
||||
// Windows: 使用 SlideToShutDown 滑动关机界面
|
||||
_powerService.ShowNativePowerUI(PowerAction.Shutdown);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Linux: 二次确认对话框
|
||||
await ShowPowerConfirmDialogAsync(L("power.shutdown_confirm_title", "Shutdown"),
|
||||
L("power.shutdown_confirm_message", "Are you sure you want to shut down this computer?"),
|
||||
() => _powerService.ShutdownAsync());
|
||||
@@ -408,8 +406,6 @@ public partial class MainWindow
|
||||
_ = e;
|
||||
ClosePopupIfOpen();
|
||||
|
||||
// 所有平台:统一使用二次确认对话框
|
||||
// Note: SlideToShutDown.exe 只支持关机,不支持重启
|
||||
await ShowPowerConfirmDialogAsync(L("power.restart_confirm_title", "Restart"),
|
||||
L("power.restart_confirm_message", "Are you sure you want to restart this computer?"),
|
||||
() => _powerService.RestartAsync());
|
||||
@@ -449,7 +445,7 @@ public partial class MainWindow
|
||||
{
|
||||
try
|
||||
{
|
||||
var dialog = new ContentDialog
|
||||
var dialog = new FAContentDialog
|
||||
{
|
||||
Title = title,
|
||||
Content = message,
|
||||
@@ -458,7 +454,7 @@ public partial class MainWindow
|
||||
};
|
||||
|
||||
var result = await dialog.ShowAsync(this);
|
||||
if (result == ContentDialogResult.Primary)
|
||||
if (result == FAContentDialogResult.Primary)
|
||||
{
|
||||
await action();
|
||||
}
|
||||
@@ -744,49 +740,42 @@ public partial class MainWindow
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检测状态栏组件是否会发生碰撞
|
||||
/// </summary>
|
||||
/// 濠碘槅鍋€閸嬫挻绻涢弶鎴剳濠殿喗鎮傞獮鈧ù锝呮贡閸╁绱撴担绋款仹婵炲棎鍨藉浼搭敍濮橆厼鍓ㄦ繛鏉戝悑閼规崘銇愰崒鐐村仺闁绘柧璀﹀楣冩煙? /// </summary>
|
||||
private bool WouldComponentsCollide()
|
||||
{
|
||||
if (TopStatusBarHost is null)
|
||||
return false;
|
||||
|
||||
// 获取各区域当前占用的宽度
|
||||
var leftWidth = GetLeftPanelOccupiedWidth();
|
||||
var centerWidth = GetCenterPanelOccupiedWidth();
|
||||
var rightWidth = GetRightPanelOccupiedWidth();
|
||||
|
||||
// 获取状态栏总宽度
|
||||
var totalWidth = TopStatusBarHost.Bounds.Width;
|
||||
if (totalWidth <= 0)
|
||||
return false;
|
||||
|
||||
// 计算中间区域的实际位置
|
||||
// 左列是 *, 中列是 Auto, 右列是 *
|
||||
// 中间区域居中显示
|
||||
// 闁荤姳绶ょ槐鏇㈡偩缂佹鈻旀い鎾卞灪閿涚喖鏌涢弽褎鎯堥柣鎾寸懇閹啴宕熼銈嗘緰闂傚倸瀚幊宥囩礊閸涱垳纾? // 閻庡綊娼荤粻鎴﹀垂椤忓牆鍙?*, 婵炴垶鎼╅崢濂稿垂椤忓牆鍙?Auto, 闂佸憡鐟ラ崯鍧楀垂椤忓牆鍙?*
|
||||
// 婵炴垶鎼╅崣鍐ㄎ涢崸妤€绀岄柛婵嗗閸樼敻鎮橀悙鍙夊櫢闁煎灚鍨垮浼村礈瑜嬫禒?
|
||||
var centerLeft = (totalWidth - centerWidth) / 2;
|
||||
var centerRight = centerLeft + centerWidth;
|
||||
|
||||
// 安全间距(像素)
|
||||
// 闁诲海鎳撻ˇ顖炲矗韫囨稒鈷掔痪鎯ь儑閻涒晠鏌ㄥ☉妯煎闁稿孩姘ㄥΣ鎰版偑閸涱垳顦?
|
||||
const double safetyMargin = 20;
|
||||
|
||||
// 检测左侧组件是否会与中间区域碰撞
|
||||
// 左侧组件右边界 = leftWidth
|
||||
// 中间区域左边界 = centerLeft
|
||||
// 濠碘槅鍋€閸嬫挻绻涢弶鎴剰濞戞柨绻戠粭鐔活槾缂侇喖绉电粋鎺楁嚋閸倣锕傛煕濮樺墽绱扮紒杈╁缁嬪鎯斿┑濠傚箑闂傚倸鍊瑰娆戜焊椤栫偛鏄ラ柣鏂捐濞奸箖鏌? // 閻庡綊娼荤紓姘跺疾閸撲胶纾奸柛鏇ㄤ簼椤愪粙鏌涘▎蹇曟瀮缂佹梻鍠栭幃?= leftWidth
|
||||
// 婵炴垶鎼╅崣鍐ㄎ涢崸妤€绀岄柛婵嗗閸樼數鈧綊娼荤粻鎺旂博閻斿吋鍋?= centerLeft
|
||||
if (leftWidth + safetyMargin > centerLeft)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// 检测右侧组件是否会与中间区域碰撞
|
||||
// 右侧组件左边界 = totalWidth - rightWidth
|
||||
// 中间区域右边界 = centerRight
|
||||
// 濠碘槅鍋€閸嬫挻绻涢弶鎴剰鐟滄澘鎲$粭鐔活槾缂侇喖绉电粋鎺楁嚋閸倣锕傛煕濮樺墽绱扮紒杈╁缁嬪鎯斿┑濠傚箑闂傚倸鍊瑰娆戜焊椤栫偛鏄ラ柣鏂捐濞奸箖鏌? // 闂佸憡鐟ラ崢鏍疾閸撲胶纾奸柛鏇ㄤ簼椤愮晫鈧綊娼荤粻鎺旂博閻斿吋鍋?= totalWidth - rightWidth
|
||||
// 婵炴垶鎼╅崣鍐ㄎ涢崸妤€绀岄柛婵嗗閸樼敻鏌涘▎蹇曟瀮缂佹梻鍠栭幃?= centerRight
|
||||
if (totalWidth - rightWidth - safetyMargin < centerRight)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// 检测中间区域是否会与左右两侧碰撞(中间区域过宽)
|
||||
if (centerLeft < leftWidth + safetyMargin ||
|
||||
centerRight > totalWidth - rightWidth - safetyMargin)
|
||||
{
|
||||
@@ -797,8 +786,7 @@ public partial class MainWindow
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取左侧面板占用的宽度(包括间距)
|
||||
/// </summary>
|
||||
/// 闂佸吋鍎抽崲鑼躲亹閸パ屽晠闁挎梹瀵у▍鐘绘⒒閸稑鐏繝銏★耿瀹曪繝鎮╅崹顐f闂佹眹鍔岀€氼剟顢欓弮鈧幆鏃堟晜閼测晝顦╅梺鍛婄墪閹冲繒鈧凹鍙冨鑽ゅ鐎n剛宕洪梺? /// </summary>
|
||||
private double GetLeftPanelOccupiedWidth()
|
||||
{
|
||||
if (TopStatusLeftPanel is null)
|
||||
@@ -817,8 +805,7 @@ public partial class MainWindow
|
||||
}
|
||||
}
|
||||
|
||||
// 添加间距
|
||||
if (visibleCount > 1)
|
||||
// 濠电儑缍€椤曆勬叏閻愮儤鈷掔痪鎯ь儑閻? if (visibleCount > 1)
|
||||
{
|
||||
width += spacing * (visibleCount - 1);
|
||||
}
|
||||
@@ -827,8 +814,7 @@ public partial class MainWindow
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取中间面板占用的宽度(包括间距)
|
||||
/// </summary>
|
||||
/// 闂佸吋鍎抽崲鑼躲亹閸ャ劎鈻旀い鎾卞灪閿涚喖姊婚崼娑樼仾婵犮垺锕㈠畷锟犳偐閸偅娈㈤梺姹囧妼鐎氼剟顢欓弮鈧幆鏃堟晜閼测晝顦╅梺鍛婄墪閹冲繒鈧凹鍙冨鑽ゅ鐎n剛宕洪梺? /// </summary>
|
||||
private double GetCenterPanelOccupiedWidth()
|
||||
{
|
||||
if (TopStatusCenterPanel is null)
|
||||
@@ -847,8 +833,7 @@ public partial class MainWindow
|
||||
}
|
||||
}
|
||||
|
||||
// 添加间距
|
||||
if (visibleCount > 1)
|
||||
// 濠电儑缍€椤曆勬叏閻愮儤鈷掔痪鎯ь儑閻? if (visibleCount > 1)
|
||||
{
|
||||
width += spacing * (visibleCount - 1);
|
||||
}
|
||||
@@ -857,8 +842,7 @@ public partial class MainWindow
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取右侧面板占用的宽度(包括间距)
|
||||
/// </summary>
|
||||
/// 闂佸吋鍎抽崲鑼躲亹閸ヮ剙鐭楅柛蹇撴噺濞呯娀姊婚崼娑樼仾婵犮垺锕㈠畷锟犳偐閸偅娈㈤梺姹囧妼鐎氼剟顢欓弮鈧幆鏃堟晜閼测晝顦╅梺鍛婄墪閹冲繒鈧凹鍙冨鑽ゅ鐎n剛宕洪梺? /// </summary>
|
||||
private double GetRightPanelOccupiedWidth()
|
||||
{
|
||||
if (TopStatusRightPanel is null)
|
||||
@@ -877,8 +861,7 @@ public partial class MainWindow
|
||||
}
|
||||
}
|
||||
|
||||
// 添加间距
|
||||
if (visibleCount > 1)
|
||||
// 濠电儑缍€椤曆勬叏閻愮儤鈷掔痪鎯ь儑閻? if (visibleCount > 1)
|
||||
{
|
||||
width += spacing * (visibleCount - 1);
|
||||
}
|
||||
@@ -887,25 +870,19 @@ public partial class MainWindow
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检查是否可以在指定位置添加组件
|
||||
/// </summary>
|
||||
/// 濠碘槅鍋€閸嬫捇鏌$仦璇插姕婵″弶鎮傚畷銉╂晝閳ь剝銇愰崣澶岊浄闁靛鍎查煬顒勬煙缁嬫寧鎼愰柣锝囧亾閹峰懎顓奸崶鈺傜€┑鐑囩秬椤曆勬叏閻愮數纾奸柛鏇ㄤ簼椤? /// </summary>
|
||||
private bool CanAddComponentAtPosition(string position)
|
||||
{
|
||||
// 先临时显示组件以计算宽度
|
||||
var wouldCollide = WouldComponentsCollide();
|
||||
if (!wouldCollide)
|
||||
return true;
|
||||
|
||||
// 如果会发生碰撞,检查是否是因为目标位置导致的
|
||||
// 获取当前各区域宽度
|
||||
var leftWidth = GetLeftPanelOccupiedWidth();
|
||||
var centerWidth = GetCenterPanelOccupiedWidth();
|
||||
var rightWidth = GetRightPanelOccupiedWidth();
|
||||
|
||||
// 估算新组件的宽度(基于当前单元格大小)
|
||||
var estimatedNewComponentWidth = _currentDesktopCellSize > 0 ? _currentDesktopCellSize * 2 : 120;
|
||||
|
||||
// 根据目标位置检查添加后是否会碰撞
|
||||
return position switch
|
||||
{
|
||||
"Left" => CanAddToLeft(leftWidth, centerWidth, rightWidth, estimatedNewComponentWidth),
|
||||
@@ -924,7 +901,7 @@ public partial class MainWindow
|
||||
if (totalWidth <= 0)
|
||||
return true;
|
||||
|
||||
var newLeftWidth = leftWidth + newWidth + TopStatusLeftPanel?.Spacing ?? 6;
|
||||
var newLeftWidth = leftWidth + newWidth + (TopStatusLeftPanel?.Spacing ?? 6);
|
||||
var centerLeft = (totalWidth - centerWidth) / 2;
|
||||
|
||||
const double safetyMargin = 20;
|
||||
@@ -940,7 +917,7 @@ public partial class MainWindow
|
||||
if (totalWidth <= 0)
|
||||
return true;
|
||||
|
||||
var newCenterWidth = centerWidth + newWidth + TopStatusCenterPanel?.Spacing ?? 6;
|
||||
var newCenterWidth = centerWidth + newWidth + (TopStatusCenterPanel?.Spacing ?? 6);
|
||||
var centerLeft = (totalWidth - newCenterWidth) / 2;
|
||||
var centerRight = centerLeft + newCenterWidth;
|
||||
|
||||
@@ -958,7 +935,7 @@ public partial class MainWindow
|
||||
if (totalWidth <= 0)
|
||||
return true;
|
||||
|
||||
var newRightWidth = rightWidth + newWidth + TopStatusRightPanel?.Spacing ?? 6;
|
||||
var newRightWidth = rightWidth + newWidth + (TopStatusRightPanel?.Spacing ?? 6);
|
||||
var centerRight = (totalWidth + centerWidth) / 2;
|
||||
|
||||
const double safetyMargin = 20;
|
||||
@@ -970,7 +947,6 @@ public partial class MainWindow
|
||||
var showClock = _topStatusComponentIds.Contains(BuiltInComponentIds.Clock);
|
||||
var hasVisibleTopStatusComponent = false;
|
||||
|
||||
// 先隐藏所有时钟控件
|
||||
if (ClockWidgetLeft is not null)
|
||||
ClockWidgetLeft.IsVisible = false;
|
||||
if (ClockWidgetCenter is not null)
|
||||
@@ -978,7 +954,6 @@ public partial class MainWindow
|
||||
if (ClockWidgetRight is not null)
|
||||
ClockWidgetRight.IsVisible = false;
|
||||
|
||||
// 先隐藏所有文字胶囊控件
|
||||
if (TextCapsuleWidgetLeft is not null)
|
||||
TextCapsuleWidgetLeft.IsVisible = false;
|
||||
if (TextCapsuleWidgetCenter is not null)
|
||||
@@ -986,7 +961,6 @@ public partial class MainWindow
|
||||
if (TextCapsuleWidgetRight is not null)
|
||||
TextCapsuleWidgetRight.IsVisible = false;
|
||||
|
||||
// 先隐藏所有网速控件
|
||||
if (NetworkSpeedWidgetLeft is not null)
|
||||
NetworkSpeedWidgetLeft.IsVisible = false;
|
||||
if (NetworkSpeedWidgetCenter is not null)
|
||||
@@ -994,7 +968,6 @@ public partial class MainWindow
|
||||
if (NetworkSpeedWidgetRight is not null)
|
||||
NetworkSpeedWidgetRight.IsVisible = false;
|
||||
|
||||
// 根据位置设置显示对应的时钟控件(带碰撞检测)
|
||||
if (showClock)
|
||||
{
|
||||
var targetPosition = _clockPosition;
|
||||
@@ -1019,7 +992,6 @@ public partial class MainWindow
|
||||
}
|
||||
else
|
||||
{
|
||||
// 如果目标位置无法添加,尝试其他位置
|
||||
var alternativePosition = FindAlternativePosition(targetPosition);
|
||||
if (alternativePosition is not null)
|
||||
{
|
||||
@@ -1041,8 +1013,7 @@ public partial class MainWindow
|
||||
}
|
||||
}
|
||||
|
||||
// 根据位置设置显示对应的文字胶囊控件(带碰撞检测)
|
||||
if (_showTextCapsule)
|
||||
// 闂佸搫绉烽~澶婄暤娴h濯寸€广儱娲ㄩ弸鍌炴偣娴g鈷旈柣銈呮瀵即宕滆娴犳盯鎮楅悽鍨殌缂併劍鐓¢幆鍐礋椤掍胶鈧噣鎮楀☉娆樻畽闁稿繐鐭傚畷鑸电節閸愩劋绮繛瀵稿Ь椤旀劗妲愬▎鎴炴殰闁挎梻铏庡楣冩煙閸撗冧沪妞ゃ儱鎳庨湁閻庯絽澧庣粈? if (_showTextCapsule)
|
||||
{
|
||||
var targetPosition = _textCapsulePosition;
|
||||
var canAdd = CanAddComponentAtPosition(targetPosition);
|
||||
@@ -1066,7 +1037,6 @@ public partial class MainWindow
|
||||
}
|
||||
else
|
||||
{
|
||||
// 如果目标位置无法添加,尝试其他位置
|
||||
var alternativePosition = FindAlternativePosition(targetPosition);
|
||||
if (alternativePosition is not null)
|
||||
{
|
||||
@@ -1088,7 +1058,6 @@ public partial class MainWindow
|
||||
}
|
||||
}
|
||||
|
||||
// 根据位置设置显示对应的网速控件(带碰撞检测)
|
||||
if (_showNetworkSpeed)
|
||||
{
|
||||
var targetPosition = _networkSpeedPosition;
|
||||
@@ -1113,7 +1082,6 @@ public partial class MainWindow
|
||||
}
|
||||
else
|
||||
{
|
||||
// 如果目标位置无法添加,尝试其他位置
|
||||
var alternativePosition = FindAlternativePosition(targetPosition);
|
||||
if (alternativePosition is not null)
|
||||
{
|
||||
@@ -1140,7 +1108,6 @@ public partial class MainWindow
|
||||
TopStatusBarHost.IsVisible = hasVisibleTopStatusComponent;
|
||||
}
|
||||
|
||||
// 延迟检查碰撞并调整
|
||||
Dispatcher.UIThread.Post(async () =>
|
||||
{
|
||||
await System.Threading.Tasks.Task.Delay(50);
|
||||
@@ -1149,22 +1116,18 @@ public partial class MainWindow
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 当组件发生碰撞时,自动调整位置
|
||||
/// </summary>
|
||||
/// 閻熸粎澧楅幐鍓у垝瀹ュ棛顩烽悹鍝勬惈缁叉椽鏌i姀銏犳灁妞ゎ偒鍋婇獮姗€鎮欑€涙﹩妲梺鎸庣☉閻線宕靛鍫濈闁靛鍔庡▓鍫曟煛娴h櫣绡€缂傚秴鎳愮槐? /// </summary>
|
||||
private void AdjustComponentsIfColliding()
|
||||
{
|
||||
if (!WouldComponentsCollide())
|
||||
return;
|
||||
|
||||
// 获取当前可见的组件
|
||||
var leftComponents = GetVisibleLeftComponents();
|
||||
var centerComponents = GetVisibleCenterComponents();
|
||||
var rightComponents = GetVisibleRightComponents();
|
||||
|
||||
// 优先保留时钟,调整文字胶囊位置
|
||||
if (TextCapsuleWidgetLeft?.IsVisible == true && WouldComponentsCollide())
|
||||
{
|
||||
// 尝试将左侧文字胶囊移到中间
|
||||
if (CanAddComponentAtPosition("Center"))
|
||||
{
|
||||
TextCapsuleWidgetLeft.IsVisible = false;
|
||||
@@ -1172,7 +1135,6 @@ public partial class MainWindow
|
||||
TextCapsuleWidgetCenter.SetTransparentBackground(_textCapsuleTransparentBackground);
|
||||
TextCapsuleWidgetCenter.SetText(_textCapsuleContent);
|
||||
}
|
||||
// 或者移到右侧
|
||||
else if (CanAddComponentAtPosition("Right"))
|
||||
{
|
||||
TextCapsuleWidgetLeft.IsVisible = false;
|
||||
@@ -1180,7 +1142,6 @@ public partial class MainWindow
|
||||
TextCapsuleWidgetRight.SetTransparentBackground(_textCapsuleTransparentBackground);
|
||||
TextCapsuleWidgetRight.SetText(_textCapsuleContent);
|
||||
}
|
||||
// 如果都无法添加,则隐藏文字胶囊
|
||||
else
|
||||
{
|
||||
TextCapsuleWidgetLeft.IsVisible = false;
|
||||
@@ -1189,7 +1150,6 @@ public partial class MainWindow
|
||||
|
||||
if (TextCapsuleWidgetRight?.IsVisible == true && WouldComponentsCollide())
|
||||
{
|
||||
// 尝试将右侧文字胶囊移到中间
|
||||
if (CanAddComponentAtPosition("Center"))
|
||||
{
|
||||
TextCapsuleWidgetRight.IsVisible = false;
|
||||
@@ -1197,7 +1157,6 @@ public partial class MainWindow
|
||||
TextCapsuleWidgetCenter.SetTransparentBackground(_textCapsuleTransparentBackground);
|
||||
TextCapsuleWidgetCenter.SetText(_textCapsuleContent);
|
||||
}
|
||||
// 或者移到左侧
|
||||
else if (CanAddComponentAtPosition("Left"))
|
||||
{
|
||||
TextCapsuleWidgetRight.IsVisible = false;
|
||||
@@ -1205,7 +1164,6 @@ public partial class MainWindow
|
||||
TextCapsuleWidgetLeft.SetTransparentBackground(_textCapsuleTransparentBackground);
|
||||
TextCapsuleWidgetLeft.SetText(_textCapsuleContent);
|
||||
}
|
||||
// 如果都无法添加,则隐藏文字胶囊
|
||||
else
|
||||
{
|
||||
TextCapsuleWidgetRight.IsVisible = false;
|
||||
@@ -1214,7 +1172,6 @@ public partial class MainWindow
|
||||
|
||||
if (TextCapsuleWidgetCenter?.IsVisible == true && WouldComponentsCollide())
|
||||
{
|
||||
// 尝试将中间文字胶囊移到左侧
|
||||
if (CanAddComponentAtPosition("Left"))
|
||||
{
|
||||
TextCapsuleWidgetCenter.IsVisible = false;
|
||||
@@ -1222,7 +1179,6 @@ public partial class MainWindow
|
||||
TextCapsuleWidgetLeft.SetTransparentBackground(_textCapsuleTransparentBackground);
|
||||
TextCapsuleWidgetLeft.SetText(_textCapsuleContent);
|
||||
}
|
||||
// 或者移到右侧
|
||||
else if (CanAddComponentAtPosition("Right"))
|
||||
{
|
||||
TextCapsuleWidgetCenter.IsVisible = false;
|
||||
@@ -1230,17 +1186,14 @@ public partial class MainWindow
|
||||
TextCapsuleWidgetRight.SetTransparentBackground(_textCapsuleTransparentBackground);
|
||||
TextCapsuleWidgetRight.SetText(_textCapsuleContent);
|
||||
}
|
||||
// 如果都无法添加,则隐藏文字胶囊
|
||||
else
|
||||
{
|
||||
TextCapsuleWidgetCenter.IsVisible = false;
|
||||
}
|
||||
}
|
||||
|
||||
// 调整网速组件位置(优先级:时钟 > 文字胶囊 > 网速)
|
||||
if (NetworkSpeedWidgetLeft?.IsVisible == true && WouldComponentsCollide())
|
||||
{
|
||||
// 尝试将左侧网速移到中间
|
||||
if (CanAddComponentAtPosition("Center"))
|
||||
{
|
||||
NetworkSpeedWidgetLeft.IsVisible = false;
|
||||
@@ -1248,7 +1201,6 @@ public partial class MainWindow
|
||||
NetworkSpeedWidgetCenter.SetTransparentBackground(_networkSpeedTransparentBackground);
|
||||
NetworkSpeedWidgetCenter.SetDisplayMode(_networkSpeedDisplayMode);
|
||||
}
|
||||
// 或者移到右侧
|
||||
else if (CanAddComponentAtPosition("Right"))
|
||||
{
|
||||
NetworkSpeedWidgetLeft.IsVisible = false;
|
||||
@@ -1256,7 +1208,6 @@ public partial class MainWindow
|
||||
NetworkSpeedWidgetRight.SetTransparentBackground(_networkSpeedTransparentBackground);
|
||||
NetworkSpeedWidgetRight.SetDisplayMode(_networkSpeedDisplayMode);
|
||||
}
|
||||
// 如果都无法添加,则隐藏网速
|
||||
else
|
||||
{
|
||||
NetworkSpeedWidgetLeft.IsVisible = false;
|
||||
@@ -1265,7 +1216,6 @@ public partial class MainWindow
|
||||
|
||||
if (NetworkSpeedWidgetRight?.IsVisible == true && WouldComponentsCollide())
|
||||
{
|
||||
// 尝试将右侧网速移到中间
|
||||
if (CanAddComponentAtPosition("Center"))
|
||||
{
|
||||
NetworkSpeedWidgetRight.IsVisible = false;
|
||||
@@ -1273,7 +1223,6 @@ public partial class MainWindow
|
||||
NetworkSpeedWidgetCenter.SetTransparentBackground(_networkSpeedTransparentBackground);
|
||||
NetworkSpeedWidgetCenter.SetDisplayMode(_networkSpeedDisplayMode);
|
||||
}
|
||||
// 或者移到左侧
|
||||
else if (CanAddComponentAtPosition("Left"))
|
||||
{
|
||||
NetworkSpeedWidgetRight.IsVisible = false;
|
||||
@@ -1281,7 +1230,6 @@ public partial class MainWindow
|
||||
NetworkSpeedWidgetLeft.SetTransparentBackground(_networkSpeedTransparentBackground);
|
||||
NetworkSpeedWidgetLeft.SetDisplayMode(_networkSpeedDisplayMode);
|
||||
}
|
||||
// 如果都无法添加,则隐藏网速
|
||||
else
|
||||
{
|
||||
NetworkSpeedWidgetRight.IsVisible = false;
|
||||
@@ -1290,7 +1238,6 @@ public partial class MainWindow
|
||||
|
||||
if (NetworkSpeedWidgetCenter?.IsVisible == true && WouldComponentsCollide())
|
||||
{
|
||||
// 尝试将中间网速移到左侧
|
||||
if (CanAddComponentAtPosition("Left"))
|
||||
{
|
||||
NetworkSpeedWidgetCenter.IsVisible = false;
|
||||
@@ -1298,7 +1245,6 @@ public partial class MainWindow
|
||||
NetworkSpeedWidgetLeft.SetTransparentBackground(_networkSpeedTransparentBackground);
|
||||
NetworkSpeedWidgetLeft.SetDisplayMode(_networkSpeedDisplayMode);
|
||||
}
|
||||
// 或者移到右侧
|
||||
else if (CanAddComponentAtPosition("Right"))
|
||||
{
|
||||
NetworkSpeedWidgetCenter.IsVisible = false;
|
||||
@@ -1306,7 +1252,6 @@ public partial class MainWindow
|
||||
NetworkSpeedWidgetRight.SetTransparentBackground(_networkSpeedTransparentBackground);
|
||||
NetworkSpeedWidgetRight.SetDisplayMode(_networkSpeedDisplayMode);
|
||||
}
|
||||
// 如果都无法添加,则隐藏网速
|
||||
else
|
||||
{
|
||||
NetworkSpeedWidgetCenter.IsVisible = false;
|
||||
@@ -1315,11 +1260,10 @@ public partial class MainWindow
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找可用的替代位置
|
||||
/// </summary>
|
||||
/// 闂佸搫琚崕鍙夌珶濮椻偓瀹曪綁顢涘鍕闂佹眹鍔岀€氼厼霉濞戞瑧顩烽柨婵嗗缁夊绱? /// </summary>
|
||||
private string? FindAlternativePosition(string originalPosition)
|
||||
{
|
||||
// 尝试所有可能的位置
|
||||
// 闁诲繐绻戠换鍡涙儊椤栫偛绠ラ柍褜鍓熷鍨緞婵犲倽顔夐梺鐓庣-閺咁偄鈻撻幋鐐村鐎广儱娲ㄩ弸?
|
||||
var positions = new[] { "Left", "Center", "Right" };
|
||||
foreach (var position in positions)
|
||||
{
|
||||
@@ -1332,8 +1276,7 @@ public partial class MainWindow
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取左侧可见组件列表
|
||||
/// </summary>
|
||||
/// 闂佸吋鍎抽崲鑼躲亹閸パ屽晠闁挎梹瀵у▍鐘绘煕濞嗘ê鐏ユい顐㈡缁辨帡宕熼鍜佸仺闂佸憡甯楅〃澶愬Υ? /// </summary>
|
||||
private List<Control> GetVisibleLeftComponents()
|
||||
{
|
||||
var result = new List<Control>();
|
||||
@@ -1348,8 +1291,7 @@ public partial class MainWindow
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取中间可见组件列表
|
||||
/// </summary>
|
||||
/// 闂佸吋鍎抽崲鑼躲亹閸ャ劎鈻旀い鎾卞灪閿涚喖鏌涘▎妯虹仴妞ゎ偄妫涚槐鎺楀礋椤忓拋鍋ㄩ梺鍛婂笚椤ㄥ濡? /// </summary>
|
||||
private List<Control> GetVisibleCenterComponents()
|
||||
{
|
||||
var result = new List<Control>();
|
||||
@@ -1364,8 +1306,7 @@ public partial class MainWindow
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取右侧可见组件列表
|
||||
/// </summary>
|
||||
/// 闂佸吋鍎抽崲鑼躲亹閸ヮ剙鐭楅柛蹇撴噺濞呯娀鏌涘▎妯虹仴妞ゎ偄妫涚槐鎺楀礋椤忓拋鍋ㄩ梺鍛婂笚椤ㄥ濡? /// </summary>
|
||||
private List<Control> GetVisibleRightComponents()
|
||||
{
|
||||
var result = new List<Control>();
|
||||
@@ -1833,17 +1774,17 @@ public partial class MainWindow
|
||||
return;
|
||||
}
|
||||
|
||||
var dialog = new ContentDialog
|
||||
var dialog = new FAContentDialog
|
||||
{
|
||||
Title = L("desktop.delete_page_confirm.title", "确认删除页面"),
|
||||
Content = L("desktop.delete_page_confirm.message", "确定要删除当前页面吗?\n\n此操作将删除当前页面上的所有组件,且无法撤销。"),
|
||||
PrimaryButtonText = L("desktop.delete_page_confirm.close", "取消"),
|
||||
SecondaryButtonText = L("desktop.delete_page_confirm.primary", "删除"),
|
||||
DefaultButton = ContentDialogButton.Primary
|
||||
Title = L("desktop.delete_page_confirm.title", "Delete desktop page"),
|
||||
Content = L("desktop.delete_page_confirm.message", "This will permanently remove the current desktop page and all widgets placed on it.\n\nThis action cannot be undone."),
|
||||
PrimaryButtonText = L("desktop.delete_page_confirm.close", "Cancel"),
|
||||
SecondaryButtonText = L("desktop.delete_page_confirm.primary", "Delete"),
|
||||
DefaultButton = FAContentDialogButton.Primary
|
||||
};
|
||||
|
||||
var result = await dialog.ShowAsync(this);
|
||||
if (result == ContentDialogResult.Secondary)
|
||||
if (result == FAContentDialogResult.Secondary)
|
||||
{
|
||||
DeleteCurrentDesktopPage();
|
||||
}
|
||||
@@ -3938,7 +3879,7 @@ public partial class MainWindow
|
||||
}
|
||||
|
||||
var point = e.GetPosition(ComponentLibraryWindow);
|
||||
if (point.Y > 40) // 閺嶅洭顣介弽蹇涚彯鎼达妇瀹虫稉?0px
|
||||
if (point.Y > 40) // 闂傚倷绀侀幖顐ょ矓閺夋嚚娲敇椤兘鍋撻崒娑氼浄閻庯綆浜滈崬銊╂椤愩垺澶勭紒瀣崄閵囨劙顢涢悙鑼啇闁哄鐗婇崕鎶姐€呴鍕€电痪顓炴噺閻濐亞绱?0px
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,7 @@ public partial class MainWindow
|
||||
private int? _desktopPageContextSettlingTargetIndex;
|
||||
private int _desktopPageContextSettleRevision;
|
||||
|
||||
// 三指滑动/右键拖动相关
|
||||
// 婵犵數鍋為崹鍫曞箰閹间絸鍥箥椤旂懓浜鹃柛顭戝亯婢规ɑ銇勯婊冨妤犵偛顑呴埞鎴﹀窗?闂傚倷绀侀幉锟犳偡閿旂晫绠惧┑鐘叉搐閺嬩焦銇勯幘鍗炵仼缂佺媭鍨堕弻鈥崇暤椤旂厧鏁俊銈呮噺閻撶喖鏌嶉崫鍕灓闁绘帡绠栭弻?
|
||||
private bool _isThreeFingerOrRightDragSwipeActive;
|
||||
private readonly HashSet<int> _activePointerIds = [];
|
||||
|
||||
@@ -264,7 +264,6 @@ public partial class MainWindow
|
||||
Grid.SetColumn(LauncherPagePanel, 1);
|
||||
Grid.SetRow(LauncherPagePanel, 0);
|
||||
|
||||
// 为启动台添加安全边距以确保圆角不被裁剪
|
||||
var launcherMargin = Math.Clamp(gridMetrics.CellSize * 0.15, 6, 16);
|
||||
LauncherPagePanel.Margin = new Thickness(launcherMargin);
|
||||
LauncherPagePanel.Width = Math.Max(1, pageWidth - launcherMargin * 2);
|
||||
@@ -272,7 +271,7 @@ public partial class MainWindow
|
||||
LauncherPagePanel.MaxWidth = pageWidth - launcherMargin * 2;
|
||||
LauncherPagePanel.MaxHeight = pageHeight - launcherMargin * 2;
|
||||
|
||||
// 更新启动台图标布局
|
||||
// 闂傚倷绀侀幖顐⒚洪妶澶嬪仱闁靛ň鏅涢拑鐔封攽閻樺弶鎼愰悷娆欓檮閵囧嫰寮介妸銊ヮ棟閻炴氨鍠栧娲川婵犲嫭鍣┑鐘灪閿氶棁澶嬫叏濡炶浜鹃悗娈垮枙缁瑥鐣烽幆閭︽Ь濡炪倕绻戦幐鎶藉箖濮椻偓閹瑩鍩℃担宄邦棜
|
||||
UpdateLauncherTileLayout();
|
||||
|
||||
_desktopSurfacePageWidth = pageWidth;
|
||||
@@ -287,38 +286,29 @@ public partial class MainWindow
|
||||
return;
|
||||
}
|
||||
|
||||
// 获取启动台面板的实际可用宽度(减去Padding)
|
||||
var availableWidth = Math.Max(1, LauncherPagePanel.Bounds.Width - 36); // 18px padding on each side
|
||||
var availableHeight = Math.Max(1, LauncherPagePanel.Bounds.Height - 100); // 预留标题空间
|
||||
var availableHeight = Math.Max(1, LauncherPagePanel.Bounds.Height - 100); // 婵犵妲呴崑鍛熆濡皷鍋撳鐓庢珝鐎殿喗濞婇崺鈧い鎺戝閻撴稓鈧箍鍎遍幊蹇涘窗濡眹浜滈柨婵嗘处濞呮洜绱掗鍊熷閻撱倖銇勮箛鎾村珔缂?
|
||||
|
||||
if (availableWidth <= 1 || availableHeight <= 1)
|
||||
{
|
||||
// 如果尺寸还未计算,使用默认值
|
||||
availableWidth = 600;
|
||||
// 婵犵數濮烽。浠嬪焵椤掆偓閸熷潡鍩€椤掆偓缂嶅﹪骞冨Ο璇茬窞閻忕偠鍋愰崜銊╂⒑閸涘﹦绠撻悗姘卞厴瀹曠敻鎮㈤悡搴i獓闂佸啿鎼导鎺楀箣濠垫捁鈧寧銇勯幘璺盒e┑顖氥偢閺屻劌鈽夊Ο渚紑闂佸搫妫崜鐔煎蓟閵娿儮妲堟俊顖欒濞堫厽绻濋悽闈涗粶婵炲樊鍙冮獮鍐╃鐎n€晠鏌嶉崫鍕殭缂佹绻濋弻锝夋偐闁秵顎栭梺绋匡攻濞茬喖宕洪埀? availableWidth = 600;
|
||||
availableHeight = 400;
|
||||
}
|
||||
|
||||
// 计算最佳图标尺寸
|
||||
// 目标:每行显示4-8个图标,根据屏幕宽度调整
|
||||
// 闂備浇宕垫慨宕囨閵堝洦顫曢柡鍥ュ灪閸嬧晛鈹戦悩瀹犲閻庢艾顦甸弻宥堫檨闁告挻宀搁獮蹇涘川閺夋垹顦ㄩ梺鍛婄懃椤﹂亶銆呴銏♀拺闁告繂瀚瓭濠电偛鐪伴崐婵嗩嚕娴兼潙纾兼繝褎鍎虫禍? // 闂傚倷鑳堕崕鐢稿疾閳哄懎绐楁俊銈呮噺閸嬪鏌ㄥ┑鍡╂Ч闁哄拋鍓氶幈銊ヮ潨閸℃绠诲┑鈥崇湴閸旀垿骞冪捄琛℃婵☆垳绮幏鍗炩攽閳藉棗鐏犳い锕佷含閸?-8婵犵數鍋為崹鍫曞箹閳哄倻顩叉繝濠傚幘閻熼偊娼ㄩ柍褜鍓欓锝嗙鐎n亞鍊炴俊鐐差儏濞寸兘藝椤曗偓濮婃椽宕崟顓夈儲銇勯銏╂Ц闁伙絽鐏氶幏鍛姜閻楀牆濯伴梻濠庡亜濞诧箓骞愭ィ鍐炬晩閹兼番鍔嶉崐鐢电棯椤撶偞鍣烘い銉ヮ樀閹鎮烽幍顕嗙礊闂佺懓顨庨崑濠傜暦濮椻偓閸╋繝宕掑☉鍗炴櫔
|
||||
const int minColumns = 4;
|
||||
const int maxColumns = 8;
|
||||
const double targetAspectRatio = 1.2; // 图标宽高比
|
||||
|
||||
// 计算每列可以显示的图标数量
|
||||
const double targetAspectRatio = 1.2; // 闂傚倷鐒﹂幃鍫曞磿閹惰棄纾婚柟鍓х帛閸嬪鏌ㄥ┑鍡樼闁稿鎹囬弻鍛槈濮樿京鍘梻浣虹帛缁诲秹宕伴弽顒夋毎?
|
||||
var optimalColumnCount = Math.Clamp((int)Math.Floor(availableWidth / 120), minColumns, maxColumns);
|
||||
|
||||
// 根据列数计算图标尺寸
|
||||
var tileWidth = Math.Floor(availableWidth / optimalColumnCount) - 12; // 12px spacing
|
||||
var tileHeight = Math.Min(tileWidth / targetAspectRatio, availableHeight / 4); // 至少显示4行
|
||||
|
||||
// 确保最小尺寸
|
||||
tileWidth = Math.Max(tileWidth, 100);
|
||||
var tileHeight = Math.Min(tileWidth / targetAspectRatio, availableHeight / 4); // 闂傚倷鑳堕崢褔宕查弻銉ョ柈闁秆勵殕閸庡秵銇勯弽顐粶闁告瑥锕弻娑㈠箻濡炵偓顦风紒?闂?
|
||||
// 缂傚倷鑳堕搹搴ㄥ矗鎼淬劌绐楅柡鍥╁У瀹曞弶鎱ㄥΟ鎸庣【閻庢艾顦甸弻宥堫檨闁告挻绋掔粋宥咁潰瀹€鈧悿鈧梺瑙勫劤閻°劑锝為崨瀛樼厽? tileWidth = Math.Max(tileWidth, 100);
|
||||
tileHeight = Math.Max(tileHeight, 80);
|
||||
|
||||
// 更新WrapPanel的Item尺寸
|
||||
LauncherRootTilePanel.Width = availableWidth;
|
||||
// 闂傚倷绀侀幖顐⒚洪妶澶嬪仱闁靛ň鏅涢拑鐔封攽閸屻倖杈渁pPanel闂傚倷鐒﹂惇褰掑礉瀹€鍕惞婵帞妫渕闂備浇顕х换鎰崲閹版澘绠规い鎰跺瘜閺? LauncherRootTilePanel.Width = availableWidth;
|
||||
|
||||
// 更新所有子元素的尺寸
|
||||
// 闂傚倷绀侀幖顐⒚洪妶澶嬪仱闁靛ň鏅涢拑鐔封攽閻樺弶鎼愮紒鐘劦閺屽秷顧侀柛鎾跺枎椤曪綁宕归銏㈢獮婵犵數濮寸€氼參骞夐妶澶嬧拺缂佸娉曠粻浼存煕閻旂顥嬬紒顔肩墕閻f繈宕熼鈧崜顓㈡⒑閸涘﹥澶勯柛瀣噹鍗遍柍褜鍓熼弻?
|
||||
foreach (var child in LauncherRootTilePanel.Children)
|
||||
{
|
||||
if (child is Button button)
|
||||
@@ -487,7 +477,7 @@ public partial class MainWindow
|
||||
return;
|
||||
}
|
||||
|
||||
// 如果在组件编辑模式下点击空白区域,取消选中(组件或启动台图标)
|
||||
// 婵犵數濮烽。浠嬪焵椤掆偓閸熷潡鍩€椤掆偓缂嶅﹪骞冨Ο璇茬窞闁归偊鍓氬畵宥夋⒑闂堟丹娑㈠川椤栨粌甯掓繝鐢靛仜椤曨厽鎱ㄧ€涙ɑ娅犻幖杈剧稻椤洘銇勮箛鎾村櫤缂傚秴娲弻鐔衡偓鐢告櫜鏉╃懓霉閿濆懎顥忛柛銈嗘礋閻擃偊宕惰閹癸綁鏌i悢鍛婂磳闁哄矉缍侀獮鍥敊閽樺鐣梻浣规偠閸娿倝宕板鍗炲灊婵鍩栭幆鐐烘偡濞嗗繐顏村ù鐘讳憾濮婃椽宕ㄦ繝鍕吂闂佸湱鈷堥崑濠囧箖閳ユ枼鏋庨柟鎯х摠濞呮牠鏌h箛鏇炰哗婵☆偄瀚濠囧箰鎼达絿顔曢梺鐟扮摠缁诲嫭鏅堕敃鍌涚厓鐟滄粓宕滃▎鎾嶅洭顢氶埀顒勫箠濞嗘挸绠i柨鏃囧Г濞呮牠姊洪崜鎻掍簴闁搞劌顭烽幆宀€鈧綆鈧垹缍婇幃鈺呭传閸曨厼甯块梻浣规偠閸斿﹪宕濋幋婵堟殾闁靛鏅╅弫宥嗘叏濮楀棗鍔俊銈呮噺閻撴洘绻涢崱妯哄缂佽泛寮剁换娑氣偓娑欙公閼拌法鈧鍠曠划娆忕暦閼告妲归幖杈剧秵濡?
|
||||
if (_isComponentLibraryOpen &&
|
||||
(_selectedDesktopComponentHost is not null || _selectedLauncherTileButton is not null))
|
||||
{
|
||||
@@ -504,7 +494,6 @@ public partial class MainWindow
|
||||
return;
|
||||
}
|
||||
|
||||
// 检查三指滑动功能是否启用
|
||||
var appSnapshot = _settingsFacade.Settings.LoadSnapshot<AppSettingsSnapshot>(SettingsScope.App);
|
||||
var isThreeFingerSwipeEnabled = appSnapshot.EnableThreeFingerSwipe;
|
||||
|
||||
@@ -513,23 +502,20 @@ public partial class MainWindow
|
||||
var isRightButtonPressed = currentPoint.Properties.IsRightButtonPressed;
|
||||
var isLeftButtonPressed = currentPoint.Properties.IsLeftButtonPressed;
|
||||
|
||||
// 处理三指滑动/右键拖动模式
|
||||
// 婵犵數濮伴崹鐓庘枖濞戞埃鍋撳鐓庢珝妤犵偛鍟换婵嬪礃椤忎焦鐏冨┑鐘灱濞夋盯顢栭崨瀛樺剨閻熸瑥瀚弧鈧繝鐢靛Т閸燁偊鎮橀妷銉㈡斀?闂傚倷绀侀幉锟犳偡閿旂晫绠惧┑鐘叉搐閺嬩焦銇勯幘鍗炵仼缂佺媭鍨堕弻鈥崇暤椤旂厧鏁俊銈勬缁诲棙銇勯弽銊d粶闁稿鎸搁悾鐑藉炊閳哄﹥鏁?
|
||||
if (isThreeFingerSwipeEnabled)
|
||||
{
|
||||
// 跟踪活跃指针
|
||||
if (isLeftButtonPressed || isRightButtonPressed)
|
||||
{
|
||||
_activePointerIds.Add(pointerId);
|
||||
}
|
||||
|
||||
// 判断是否是三指滑动或右键拖动
|
||||
var isThreeFinger = _activePointerIds.Count >= 3;
|
||||
var isRightDrag = isRightButtonPressed;
|
||||
|
||||
if (isThreeFinger || isRightDrag)
|
||||
{
|
||||
// 三指/右键拖动模式:跳过所有组件交互检查,直接开始滑动
|
||||
ClearDesktopPageContextSettle(refreshContext: false);
|
||||
// 婵犵數鍋為崹鍫曞箰閹间絸鍥箥椤旂懓浜?闂傚倷绀侀幉锟犳偡閿旂晫绠惧┑鐘叉搐閺嬩焦銇勯幘鍗炵仼缂佺媭鍨堕弻鈥崇暤椤旂厧鏁俊銈勬缁诲棙銇勯弽銊d粶闁稿鎸搁悾鐑藉炊閳哄﹥鏁ら梻鍌欑劍鐎笛呯矙閹烘挾鈹嶆繛宸簼閸婂鏌ㄩ弮鍥撳ù婧垮€濋弻娑㈠Ψ閿濆懎顬堝銈忕稻閻擄繝寮婚敓鐘查唶婵犲灚鍔栨缂傚倷绶¢崰鏍矓閻㈢數鐭夐柟鐑橆殔鐎氬鏌涢…鎴濅簻闁衡偓椤撶喓绠鹃悗娑欘焽閻鎮介娑辨疁閽樼喖鏌涘☉娆愮稇闁藉啰鍠栭弻鏇熷緞濡櫣浠紓浣插亾濠㈣埖鍔栭悡鐔兼煃鏉炴媽鍏岄柟鐣屽█閹粙顢涘☉娆戠▏濡炪倖娲╃紞渚€宕洪埀顒併亜閹哄秶鍔嶉柛娆忕箻閹鏁愭惔鈥茬敖闂佽鐏氶崝鎴﹀蓟? ClearDesktopPageContextSettle(refreshContext: false);
|
||||
_isThreeFingerOrRightDragSwipeActive = true;
|
||||
_isDesktopSwipeActive = true;
|
||||
_isDesktopSwipeDirectionLocked = false;
|
||||
@@ -540,14 +526,12 @@ public partial class MainWindow
|
||||
_desktopSwipeLastTimestamp = Stopwatch.GetTimestamp();
|
||||
_desktopSwipeBaseOffset = -_currentDesktopSurfaceIndex * _desktopSurfacePageWidth;
|
||||
|
||||
// 标记事件已处理,防止组件响应
|
||||
e.Handled = true;
|
||||
// 闂傚倷绀侀幖顐ょ矓閺夋嚚娲煛閸滀焦鏅╅梺鎼炲劘閸斿酣銆呴弻銉﹀€甸柨婵嗗€瑰▍鍡樸亜閹邦喗娅曢柍褜鍓涢幊鎾诲箟闄囬妵鎰板礃椤斻垹娲崺锟犲川椤旈棿鍝楅梻浣虹《濡插懘宕㈤崜褏鐭嗗鑸靛姈閳锋帡鏌涢幇鈺佸缂佺嫏鍕╀簻闁圭儤鎸鹃妴鎺旂磼鏉堛劌娴€规洜鍠栭、鏃堝椽娴i晲缂撻梻鍌欑閹诧紕鎹㈤崒婊呯煋閻庡灚鐡曟慨? e.Handled = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// 原有单指滑动逻辑
|
||||
if (IsInteractivePointerSource(e.Source))
|
||||
// 闂傚倷绀侀幉锟犫€﹂崶顒€绐楅柟閭﹀墾閼板灝銆掑锝呬壕閻庤娲╃换婵嗩嚕閹绢喗鍋勫瀣閳诲本绻濋悽闈浶㈤柨鏇樺劦瀹曞綊宕归锝呭伎闂佸啿鎼幊蹇涙倿婵犳碍鐓涢柛鏇ㄥ亞缁犳娊鎮? if (IsInteractivePointerSource(e.Source))
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -811,7 +795,6 @@ public partial class MainWindow
|
||||
|
||||
private void OnDesktopPagesPointerReleased(object? sender, PointerReleasedEventArgs e)
|
||||
{
|
||||
// 清理活跃指针
|
||||
var pointerId = e.Pointer?.Id ?? 0;
|
||||
_activePointerIds.Remove(pointerId);
|
||||
|
||||
@@ -823,7 +806,6 @@ public partial class MainWindow
|
||||
|
||||
private void OnDesktopPagesPointerCaptureLost(object? sender, PointerCaptureLostEventArgs e)
|
||||
{
|
||||
// 清理活跃指针
|
||||
var pointerId = e.Pointer?.Id ?? 0;
|
||||
_activePointerIds.Remove(pointerId);
|
||||
|
||||
@@ -898,13 +880,12 @@ public partial class MainWindow
|
||||
var hasDistanceIntent = absDeltaX >= distanceThreshold && absDeltaX > absDeltaY * 1.05;
|
||||
var hasVelocityIntent = Math.Abs(_desktopSwipeVelocityX) >= velocityThreshold;
|
||||
|
||||
// 检查:三指/右键拖动 && 在第一页 && 向右滑动
|
||||
// 濠电姷顣藉Σ鍛村磻閳ь剟鏌涚€n偅宕岄柡宀嬬磿娴狅妇鎷犻幓鎺懶ョ紓鍌欐祰娴滎剚鏅跺Δ鍐煓濠㈣泛顑呯欢鐐烘倵閿濆簼绨芥俊?闂傚倷绀侀幉锟犳偡閿旂晫绠惧┑鐘叉搐閺嬩焦銇勯幘鍗炵仼缂佺媭鍨堕弻鈥崇暤椤旂厧鏁?&& 闂傚倷绶氬鑽ゆ嫻閻旂厧绀夐幖鎼厛閺佸嫰鏌涢妷锝呭闁崇粯妫冮弻宥堫檨闁告挻宀告俊?&& 闂傚倷绀侀幉锛勫枈瀹ュ鍨傚ù锝呭暔娴滃湱绱掔€n偒鍎ラ柣鎾卞劦閺岀喓鈧稒顭囩粻鎾舵偖?
|
||||
if (wasThreeFingerOrRightDrag &&
|
||||
_currentDesktopSurfaceIndex == 0 &&
|
||||
deltaX > 0 && // 向右滑动
|
||||
deltaX > 0 && // 闂傚倷绀侀幉锛勫枈瀹ュ鍨傚ù锝呭暔娴滃湱绱掔€n偒鍎ラ柣鎾卞劦閺岀喓鈧稒顭囩粻鎾舵偖?
|
||||
(hasDistanceIntent || hasVelocityIntent))
|
||||
{
|
||||
// 最小化到 Windows 桌面
|
||||
if (Application.Current is App app)
|
||||
{
|
||||
app.HideMainWindowToTray(this, "ThreeFingerOrRightDragSwipe");
|
||||
@@ -998,8 +979,7 @@ public partial class MainWindow
|
||||
string.Empty));
|
||||
}
|
||||
|
||||
// 在图标渲染完成后,应用布局计算
|
||||
Dispatcher.UIThread.Post(() => UpdateLauncherTileLayout(), DispatcherPriority.Background);
|
||||
// 闂傚倷绶氬鑽ゆ嫻閻旂厧绀夐悘鐐电叓閻熼偊娼ㄩ柍褜鍓欓锝嗙鐎n亞鍊為梺闈涱煬閻撳牆煤椤掑嫭鈷戦柛婵嗗濠€浼存煙閸涘﹥鍊愰柟顕€绠栭、妤呭礋椤愩値鍚呴梻浣哥秺閸嬪﹪宕滃璺虹9闁汇垹鎲¢悡銉︾箾閹寸儐鐒鹃悗姘缁辨帡濡搁敂鎯у绩闂佽鍠曠划娆愪繆閹间礁唯鐟滄粍瀵煎畝鍕厽闊洦娲栨禍褰掓煕鐎n偅宕岄柟顔款潐缁楃喐绻濋崟顓ㄧ吹闂? Dispatcher.UIThread.Post(() => UpdateLauncherTileLayout(), DispatcherPriority.Background);
|
||||
}
|
||||
|
||||
private Button CreateLauncherFolderTile(StartMenuFolderNode folder)
|
||||
@@ -1063,8 +1043,7 @@ public partial class MainWindow
|
||||
BorderThickness = new Thickness(0),
|
||||
Margin = new Thickness(0, 0, 12, 12),
|
||||
CornerRadius = new CornerRadius(20),
|
||||
Child = panel
|
||||
// 不设置固定 Width 和 Height,由 UpdateLauncherTileLayout 动态设置
|
||||
Child = panel,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1145,11 +1124,8 @@ public partial class MainWindow
|
||||
BorderBrush = Brushes.Transparent,
|
||||
CornerRadius = new CornerRadius(20),
|
||||
Padding = new Thickness(10),
|
||||
Content = content
|
||||
// 不设置固定 Width 和 Height,由 UpdateLauncherTileLayout 动态设置
|
||||
Content = content,
|
||||
};
|
||||
|
||||
// 根据设置决定是否显示背景
|
||||
if (_showLauncherTileBackground)
|
||||
{
|
||||
button.Classes.Add("glass-panel");
|
||||
@@ -1415,7 +1391,7 @@ public partial class MainWindow
|
||||
: fileName;
|
||||
}
|
||||
|
||||
private SettingsExpanderItem CreateLauncherHiddenItemRow(LauncherHiddenItemView hiddenItem)
|
||||
private FASettingsExpanderItem CreateLauncherHiddenItemRow(LauncherHiddenItemView hiddenItem)
|
||||
{
|
||||
var typeText = hiddenItem.Kind == LauncherEntryKind.Folder
|
||||
? L("settings.launcher.hidden_type_folder", "Folder")
|
||||
@@ -1430,7 +1406,7 @@ public partial class MainWindow
|
||||
BorderThickness = new Thickness(0),
|
||||
Tag = new LauncherHiddenItemToken(hiddenItem.Kind, hiddenItem.Key)
|
||||
};
|
||||
restoreButton.Content = new FluentIcons.Avalonia.Fluent.SymbolIcon
|
||||
restoreButton.Content = new FluentIcons.Avalonia.SymbolIcon
|
||||
{
|
||||
Symbol = FluentIcons.Common.Symbol.Eye,
|
||||
IconVariant = FluentIcons.Common.IconVariant.Regular,
|
||||
@@ -1441,7 +1417,7 @@ public partial class MainWindow
|
||||
ToolTip.SetTip(restoreButton, L("settings.launcher.restore_button", "Unhide"));
|
||||
restoreButton.Click += OnRestoreLauncherHiddenItemClick;
|
||||
|
||||
return new SettingsExpanderItem
|
||||
return new FASettingsExpanderItem
|
||||
{
|
||||
Content = hiddenItem.DisplayName,
|
||||
Description = typeText,
|
||||
@@ -1451,23 +1427,17 @@ public partial class MainWindow
|
||||
};
|
||||
}
|
||||
|
||||
private IconSource CreateLauncherHiddenItemIconSource(LauncherHiddenItemView hiddenItem)
|
||||
private FAIconSource? CreateLauncherHiddenItemIconSource(LauncherHiddenItemView hiddenItem)
|
||||
{
|
||||
if (hiddenItem.IconBitmap is not null)
|
||||
{
|
||||
return new ImageIconSource
|
||||
return new FAImageIconSource
|
||||
{
|
||||
Source = hiddenItem.IconBitmap
|
||||
};
|
||||
}
|
||||
|
||||
return new FluentIcons.Avalonia.Fluent.SymbolIconSource
|
||||
{
|
||||
Symbol = hiddenItem.Kind == LauncherEntryKind.Folder
|
||||
? FluentIcons.Common.Symbol.Folder
|
||||
: FluentIcons.Common.Symbol.Apps,
|
||||
IconVariant = FluentIcons.Common.IconVariant.Regular
|
||||
};
|
||||
return null;
|
||||
}
|
||||
|
||||
private void OnRestoreLauncherHiddenItemClick(object? sender, RoutedEventArgs e)
|
||||
@@ -1696,7 +1666,7 @@ public partial class MainWindow
|
||||
Content = content
|
||||
};
|
||||
|
||||
// 根据设置决定是否显示背景
|
||||
// 闂傚倷绀侀幖顐ょ矓閻戞枻缍栧璺猴功閺嗐倕霉閿濆洤鍔嬪┑顖氥偢閺屾盯骞樺Δ鈧幊蹇涙倵椤撱垺鈷戦柛娑橈工婵洭鏌涢悢閿嬪仴闁诡喚鍋撻妶锝夊礃閵娿儱鎸ゆ俊鐐€栭悧妤冨枈瀹ュ纾垮┑鐘叉处閻撴盯鏌涢弴銊ヤ簻闁抽攱妫冮弻鏇㈠炊閵娿儱鎽甸梺纭呮珪椤ㄥ牊绂掗敃鍌涘€锋い鎺戝€哥拋?
|
||||
if (_showLauncherTileBackground)
|
||||
{
|
||||
button.Classes.Add("glass-panel");
|
||||
@@ -1775,7 +1745,7 @@ public partial class MainWindow
|
||||
Content = content
|
||||
};
|
||||
|
||||
// 根据设置决定是否显示背景
|
||||
// 闂傚倷绀侀幖顐ょ矓閻戞枻缍栧璺猴功閺嗐倕霉閿濆洤鍔嬪┑顖氥偢閺屾盯骞樺Δ鈧幊蹇涙倵椤撱垺鈷戦柛娑橈工婵洭鏌涢悢閿嬪仴闁诡喚鍋撻妶锝夊礃閵娿儱鎸ゆ俊鐐€栭悧妤冨枈瀹ュ纾垮┑鐘叉处閻撴盯鏌涢弴銊ヤ簻闁抽攱妫冮弻鏇㈠炊閵娿儱鎽甸梺纭呮珪椤ㄥ牊绂掗敃鍌涘€锋い鎺戝€哥拋?
|
||||
if (_showLauncherTileBackground)
|
||||
{
|
||||
button.Classes.Add("glass-panel");
|
||||
|
||||
@@ -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()
|
||||
{
|
||||
|
||||
@@ -20,13 +20,13 @@ using LanMountainDesktop.Views.Components;
|
||||
|
||||
namespace LanMountainDesktop.Views;
|
||||
|
||||
public partial class MainWindow
|
||||
public partial class MainWindow : Window
|
||||
{
|
||||
private TextBlock? CurrentRenderBackendLabelTextBlock => this.FindControl<TextBlock>("CurrentRenderBackendLabelTextBlock");
|
||||
private TextBlock? CurrentRenderBackendValueTextBlock => this.FindControl<TextBlock>("CurrentRenderBackendValueTextBlock");
|
||||
private TextBlock? CurrentRenderBackendImplementationTextBlock => this.FindControl<TextBlock>("CurrentRenderBackendImplementationTextBlock");
|
||||
private ComboBox? TimeZoneComboBox => this.FindControl<ComboBox>("TimeZoneComboBox");
|
||||
private SettingsExpander? LauncherHiddenItemsSettingsExpander => this.FindControl<SettingsExpander>("LauncherHiddenItemsSettingsExpander");
|
||||
private FASettingsExpander? LauncherHiddenItemsSettingsExpander => this.FindControl<FASettingsExpander>("LauncherHiddenItemsSettingsExpander");
|
||||
private TextBlock? LauncherHiddenItemsEmptyTextBlock => this.FindControl<TextBlock>("LauncherHiddenItemsEmptyTextBlock");
|
||||
|
||||
private void OnSettingsChanged(object? sender, SettingsChangedEvent e)
|
||||
@@ -38,13 +38,12 @@ public partial class MainWindow
|
||||
return;
|
||||
}
|
||||
|
||||
// 组件实例范围的设置变更不应触发整个桌面重新加载(比如翻页保存图片索引)
|
||||
if (e.Scope == SettingsScope.ComponentInstance)
|
||||
// 缁勪欢瀹炰緥鑼冨洿鐨勮缃彉鏇翠笉搴旇Е鍙戞暣涓闈㈤噸鏂板姞杞斤紙姣斿缈婚〉淇濆瓨鍥剧墖绱㈠紩锛? if (e.Scope == SettingsScope.ComponentInstance)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// 启动台设置变化时,重新渲染启动台图标
|
||||
// 鍚姩鍙拌缃彉鍖栨椂锛岄噸鏂版覆鏌撳惎鍔ㄥ彴鍥炬爣
|
||||
if (e.Scope == SettingsScope.Launcher && e.ChangedKeys is { Count: > 0 })
|
||||
{
|
||||
var changedKeys = e.ChangedKeys.ToArray();
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -38,14 +39,14 @@ public partial class MainWindow
|
||||
|
||||
try
|
||||
{
|
||||
var dialog = new ContentDialog
|
||||
var dialog = new FAContentDialog
|
||||
{
|
||||
Title = L("single_instance.notice.title", "应用已经运行"),
|
||||
Title = L("single_instance.notice.title", "Already running"),
|
||||
Content = L(
|
||||
"single_instance.notice.description",
|
||||
"应用已经运行,无需多次点击打开。"),
|
||||
PrimaryButtonText = L("single_instance.notice.button", "确定"),
|
||||
DefaultButton = ContentDialogButton.Primary
|
||||
"LanMountainDesktop is already running. The existing window will stay active, so no new instance was started."),
|
||||
PrimaryButtonText = L("single_instance.notice.button", "OK"),
|
||||
DefaultButton = FAContentDialogButton.Primary
|
||||
};
|
||||
|
||||
await dialog.ShowAsync(this);
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
xmlns:vm="using:LanMountainDesktop.ViewModels"
|
||||
xmlns:ui="using:FluentAvalonia.UI.Controls"
|
||||
xmlns:fi="using:FluentIcons.Avalonia"
|
||||
xmlns:ic="using:FluentIcons.Avalonia.Fluent"
|
||||
xmlns:ic="using:FluentIcons.Avalonia"
|
||||
xmlns:mi="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
|
||||
xmlns:comp="using:LanMountainDesktop.Views.Components"
|
||||
|
||||
@@ -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}"
|
||||
@@ -236,7 +236,7 @@
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
<!-- 状态栏阴影层 - macOS 风格的完整阴影带 -->
|
||||
<!-- 鐘舵€佹爮闃村奖灞?- macOS 椋庢牸鐨勫畬鏁撮槾褰卞甫 -->
|
||||
<Border x:Name="StatusBarOverlay"
|
||||
Grid.Row="0"
|
||||
Grid.Column="0"
|
||||
@@ -265,7 +265,7 @@
|
||||
Padding="4"
|
||||
ZIndex="2">
|
||||
<Grid ColumnDefinitions="*,Auto,*">
|
||||
<!-- 左侧状态栏组件 -->
|
||||
<!-- 宸︿晶鐘舵€佹爮缁勪欢 -->
|
||||
<StackPanel x:Name="TopStatusLeftPanel"
|
||||
Grid.Column="0"
|
||||
Orientation="Horizontal"
|
||||
@@ -281,7 +281,7 @@
|
||||
IsVisible="False"
|
||||
Margin="0" />
|
||||
</StackPanel>
|
||||
<!-- 中间状态栏组件 -->
|
||||
<!-- 涓棿鐘舵€佹爮缁勪欢 -->
|
||||
<StackPanel x:Name="TopStatusCenterPanel"
|
||||
Grid.Column="1"
|
||||
Orientation="Horizontal"
|
||||
@@ -297,7 +297,7 @@
|
||||
IsVisible="False"
|
||||
Margin="0" />
|
||||
</StackPanel>
|
||||
<!-- 右侧状态栏组件 -->
|
||||
<!-- 鍙充晶鐘舵€佹爮缁勪欢 -->
|
||||
<StackPanel x:Name="TopStatusRightPanel"
|
||||
Grid.Column="2"
|
||||
Orientation="Horizontal"
|
||||
|
||||
@@ -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">
|
||||
|
||||
<Border x:Name="DialogCard"
|
||||
|
||||
@@ -9,7 +9,6 @@ using Avalonia.Styling;
|
||||
using Avalonia.Threading;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using FluentIcons.Avalonia;
|
||||
using FluentIcons.Avalonia.Fluent;
|
||||
using LanMountainDesktop.Services;
|
||||
|
||||
namespace LanMountainDesktop.Views;
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
xmlns:controls="using:LanMountainDesktop.Controls"
|
||||
x:Class="LanMountainDesktop.Views.NotificationWindow"
|
||||
x:DataType="vm:NotificationViewModel"
|
||||
SystemDecorations="None"
|
||||
WindowDecorations="None"
|
||||
Background="Transparent"
|
||||
ShowInTaskbar="False"
|
||||
Topmost="True"
|
||||
@@ -13,7 +13,6 @@
|
||||
SizeToContent="WidthAndHeight"
|
||||
TransparencyLevelHint="Transparent"
|
||||
ExtendClientAreaToDecorationsHint="True"
|
||||
ExtendClientAreaChromeHints="NoChrome"
|
||||
ExtendClientAreaTitleBarHeightHint="-1">
|
||||
|
||||
<Window.Styles>
|
||||
|
||||
@@ -1,19 +1,27 @@
|
||||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:vm="using:LanMountainDesktop.ViewModels"
|
||||
xmlns:controls="using:LanMountainDesktop.Controls"
|
||||
xmlns:ui="using:FluentAvalonia.UI.Controls"
|
||||
xmlns:fi="using:FluentIcons.Avalonia.Fluent"
|
||||
xmlns:fi="using:FluentIcons.Avalonia"
|
||||
x:Class="LanMountainDesktop.Views.SettingsPages.AboutSettingsPage"
|
||||
x:DataType="vm:AboutSettingsPageViewModel">
|
||||
<UserControl.Resources>
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.ThemeDictionaries>
|
||||
<ResourceDictionary x:Key="Default">
|
||||
<ImageBrush x:Key="AboutBannerBrush" Source="/Assets/about_banner_light.png" Stretch="Uniform" AlignmentX="Center" AlignmentY="Center" />
|
||||
<ImageBrush x:Key="AboutBannerBrush"
|
||||
Source="/Assets/about_banner_light.png"
|
||||
Stretch="Uniform"
|
||||
AlignmentX="Center"
|
||||
AlignmentY="Center" />
|
||||
</ResourceDictionary>
|
||||
<ResourceDictionary x:Key="Dark">
|
||||
<ImageBrush x:Key="AboutBannerBrush" Source="/Assets/about_banner_dark.png" Stretch="Uniform" AlignmentX="Center" AlignmentY="Center" />
|
||||
<ImageBrush x:Key="AboutBannerBrush"
|
||||
Source="/Assets/about_banner_dark.png"
|
||||
Stretch="Uniform"
|
||||
AlignmentX="Center"
|
||||
AlignmentY="Center" />
|
||||
</ResourceDictionary>
|
||||
</ResourceDictionary.ThemeDictionaries>
|
||||
</ResourceDictionary>
|
||||
@@ -36,7 +44,7 @@
|
||||
<Setter Property="HorizontalAlignment" Value="Stretch" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="ui|InfoBar.about-static-info">
|
||||
<Style Selector="ui|FAInfoBar.about-static-info">
|
||||
<Setter Property="IsOpen" Value="True" />
|
||||
<Setter Property="IsClosable" Value="False" />
|
||||
<Setter Property="Severity" Value="Informational" />
|
||||
@@ -57,30 +65,29 @@
|
||||
<TextBlock Classes="settings-subsection-title"
|
||||
Text="{Binding AppInfoHeader}" />
|
||||
|
||||
<ui:InfoBar Classes="about-static-info"
|
||||
Title="{Binding VersionLabel}"
|
||||
Message="{Binding VersionText}">
|
||||
<ui:InfoBar.IconSource>
|
||||
<fi:SymbolIconSource Symbol="Info" />
|
||||
</ui:InfoBar.IconSource>
|
||||
</ui:InfoBar>
|
||||
<ui:FAInfoBar Classes="about-static-info"
|
||||
Title="{Binding VersionLabel}"
|
||||
Message="{Binding VersionText}">
|
||||
<ui:FAInfoBar.IconSource>
|
||||
<ui:FAFontIconSource Glyph="󰊈" FontFamily="avares://fluenticons.resources.avalonia/Assets#Seagull Fluent Icons" />
|
||||
</ui:FAInfoBar.IconSource>
|
||||
</ui:FAInfoBar>
|
||||
|
||||
<ui:InfoBar Classes="about-static-info"
|
||||
Title="{Binding CodenameLabel}"
|
||||
Message="{Binding CodenameText}">
|
||||
<ui:InfoBar.IconSource>
|
||||
<fi:SymbolIconSource Symbol="Bookmark" />
|
||||
</ui:InfoBar.IconSource>
|
||||
</ui:InfoBar>
|
||||
<ui:FAInfoBar Classes="about-static-info"
|
||||
Title="{Binding CodenameLabel}"
|
||||
Message="{Binding CodenameText}">
|
||||
<ui:FAInfoBar.IconSource>
|
||||
<ui:FAFontIconSource Glyph="󱏐" FontFamily="avares://fluenticons.resources.avalonia/Assets#Seagull Fluent Icons" />
|
||||
</ui:FAInfoBar.IconSource>
|
||||
</ui:FAInfoBar>
|
||||
|
||||
<!-- 版权声明 - 放在渲染显示前面 -->
|
||||
<ui:SettingsExpander Header="版权声明"
|
||||
IsExpanded="True">
|
||||
<ui:SettingsExpander.IconSource>
|
||||
<fi:SymbolIconSource Symbol="Document" />
|
||||
</ui:SettingsExpander.IconSource>
|
||||
<ui:SettingsExpanderItem>
|
||||
<ui:SettingsExpanderItem.Footer>
|
||||
<ui:FASettingsExpander Header="Project resources"
|
||||
IsExpanded="True">
|
||||
<ui:FASettingsExpander.IconSource>
|
||||
<ui:FAFontIconSource Glyph="󰊬" FontFamily="avares://fluenticons.resources.avalonia/Assets#Seagull Fluent Icons" />
|
||||
</ui:FASettingsExpander.IconSource>
|
||||
<ui:FASettingsExpanderItem>
|
||||
<ui:FASettingsExpanderItem.Footer>
|
||||
<WrapPanel>
|
||||
<WrapPanel.Styles>
|
||||
<Style Selector="HyperlinkButton">
|
||||
@@ -89,18 +96,18 @@
|
||||
</Style>
|
||||
</WrapPanel.Styles>
|
||||
<HyperlinkButton NavigateUri="https://github.com/wwiinnddyy/LanMountainDesktop">
|
||||
<TextBlock Text="GitHub 仓库" />
|
||||
<TextBlock Text="GitHub Repository" />
|
||||
</HyperlinkButton>
|
||||
<HyperlinkButton NavigateUri="https://github.com/wwiinnddyy/LanMountainDesktop/issues">
|
||||
<TextBlock Text="问题反馈" />
|
||||
<TextBlock Text="Issue Tracker" />
|
||||
</HyperlinkButton>
|
||||
</WrapPanel>
|
||||
</ui:SettingsExpanderItem.Footer>
|
||||
</ui:FASettingsExpanderItem.Footer>
|
||||
<TextBlock>
|
||||
<Run Text="Copyright (c) 2024-" /><Run Text="2025" /> Lincube
|
||||
</TextBlock>
|
||||
</ui:SettingsExpanderItem>
|
||||
</ui:SettingsExpander>
|
||||
</ui:FASettingsExpanderItem>
|
||||
</ui:FASettingsExpander>
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
</UserControl>
|
||||
|
||||
@@ -74,6 +74,9 @@ public partial class AboutSettingsPage : SettingsPageBase
|
||||
|
||||
private void OnAboutHeroCardPointerPressed(object? sender, PointerPressedEventArgs e)
|
||||
{
|
||||
_ = sender;
|
||||
_ = e;
|
||||
|
||||
var now = DateTime.UtcNow;
|
||||
var elapsed = now - _lastHeroCardClickTime;
|
||||
|
||||
@@ -111,25 +114,23 @@ public partial class AboutSettingsPage : SettingsPageBase
|
||||
}
|
||||
else if (remaining <= 2)
|
||||
{
|
||||
Debug.WriteLine($"[AboutSettingsPage] 再点击 {remaining} 次即可启用开发者模式。");
|
||||
Debug.WriteLine($"[AboutSettingsPage] {remaining} tap(s) remaining before developer mode unlocks.");
|
||||
}
|
||||
}
|
||||
|
||||
private async void PromptEnableDevMode(ISettingsFacadeService settingsFacade)
|
||||
{
|
||||
var dialog = new ContentDialog
|
||||
var dialog = new FAContentDialog
|
||||
{
|
||||
Title = "启用开发者模式",
|
||||
Content = "开发者模式提供了插件调试、热重载等高级功能,仅供开发和调试用途。\n\n" +
|
||||
"请注意:开发者不对以非开发用途使用此功能造成的任何后果负责,也不接受以非开发用途使用时产生的 Bug 反馈。\n\n" +
|
||||
"确定要启用开发者模式吗?",
|
||||
PrimaryButtonText = "启用",
|
||||
CloseButtonText = "取消",
|
||||
DefaultButton = ContentDialogButton.Close
|
||||
Title = "Enable developer mode",
|
||||
Content = "Developer mode exposes experimental settings, diagnostics, and local plugin debugging options.\n\nUse it only when you are actively testing or troubleshooting the desktop host.",
|
||||
PrimaryButtonText = "Enable",
|
||||
CloseButtonText = "Not now",
|
||||
DefaultButton = FAContentDialogButton.Close
|
||||
};
|
||||
|
||||
var result = await dialog.ShowAsync();
|
||||
if (result != ContentDialogResult.Primary)
|
||||
if (result != FAContentDialogResult.Primary)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:vm="using:LanMountainDesktop.ViewModels"
|
||||
xmlns:controls="using:LanMountainDesktop.Controls"
|
||||
xmlns:ui="using:FluentAvalonia.UI.Controls"
|
||||
xmlns:fi="using:FluentIcons.Avalonia.Fluent"
|
||||
xmlns:fi="using:FluentIcons.Avalonia"
|
||||
x:Class="LanMountainDesktop.Views.SettingsPages.AppearanceSettingsPage"
|
||||
x:DataType="vm:AppearanceSettingsPageViewModel">
|
||||
<ScrollViewer VerticalScrollBarVisibility="Auto">
|
||||
@@ -13,12 +13,12 @@
|
||||
Text="{Binding ThemeHeader}"
|
||||
Margin="0,0,0,4" />
|
||||
|
||||
<ui:SettingsExpander Header="{Binding ThemeModeLabel}"
|
||||
<ui:FASettingsExpander Header="{Binding ThemeModeLabel}"
|
||||
Description="{Binding ThemeModeDescription}">
|
||||
<ui:SettingsExpander.IconSource>
|
||||
<fi:SymbolIconSource Symbol="WeatherMoon" />
|
||||
</ui:SettingsExpander.IconSource>
|
||||
<ui:SettingsExpander.Footer>
|
||||
<ui:FASettingsExpander.IconSource>
|
||||
<ui:FAFontIconSource Glyph="󰔄" FontFamily="avares://fluenticons.resources.avalonia/Assets#Seagull Fluent Icons" />
|
||||
</ui:FASettingsExpander.IconSource>
|
||||
<ui:FASettingsExpander.Footer>
|
||||
<ComboBox Width="200"
|
||||
ItemsSource="{Binding ThemeModeOptions}"
|
||||
SelectedItem="{Binding SelectedThemeMode}">
|
||||
@@ -28,24 +28,24 @@
|
||||
</DataTemplate>
|
||||
</ComboBox.ItemTemplate>
|
||||
</ComboBox>
|
||||
</ui:SettingsExpander.Footer>
|
||||
</ui:SettingsExpander>
|
||||
</ui:FASettingsExpander.Footer>
|
||||
</ui:FASettingsExpander>
|
||||
|
||||
<ui:SettingsExpander Header="{Binding UseSystemChromeLabel}">
|
||||
<ui:SettingsExpander.IconSource>
|
||||
<fi:SymbolIconSource Symbol="Window" />
|
||||
</ui:SettingsExpander.IconSource>
|
||||
<ui:SettingsExpander.Footer>
|
||||
<ui:FASettingsExpander Header="{Binding UseSystemChromeLabel}">
|
||||
<ui:FASettingsExpander.IconSource>
|
||||
<ui:FAFontIconSource Glyph="󰤈" FontFamily="avares://fluenticons.resources.avalonia/Assets#Seagull Fluent Icons" />
|
||||
</ui:FASettingsExpander.IconSource>
|
||||
<ui:FASettingsExpander.Footer>
|
||||
<ToggleSwitch IsChecked="{Binding UseSystemChrome}" />
|
||||
</ui:SettingsExpander.Footer>
|
||||
</ui:SettingsExpander>
|
||||
</ui:FASettingsExpander.Footer>
|
||||
</ui:FASettingsExpander>
|
||||
|
||||
<ui:SettingsExpander Header="{Binding ThemeColorModeLabel}"
|
||||
<ui:FASettingsExpander Header="{Binding ThemeColorModeLabel}"
|
||||
Description="{Binding ThemeColorSourceDescription}">
|
||||
<ui:SettingsExpander.IconSource>
|
||||
<fi:SymbolIconSource Symbol="PaintBrush" />
|
||||
</ui:SettingsExpander.IconSource>
|
||||
<ui:SettingsExpander.Footer>
|
||||
<ui:FASettingsExpander.IconSource>
|
||||
<ui:FAFontIconSource Glyph="󰅼" FontFamily="avares://fluenticons.resources.avalonia/Assets#Seagull Fluent Icons" />
|
||||
</ui:FASettingsExpander.IconSource>
|
||||
<ui:FASettingsExpander.Footer>
|
||||
<ComboBox Width="240"
|
||||
ItemsSource="{Binding ThemeColorModes}"
|
||||
SelectedItem="{Binding SelectedThemeColorMode}">
|
||||
@@ -55,15 +55,15 @@
|
||||
</DataTemplate>
|
||||
</ComboBox.ItemTemplate>
|
||||
</ComboBox>
|
||||
</ui:SettingsExpander.Footer>
|
||||
</ui:SettingsExpander>
|
||||
</ui:FASettingsExpander.Footer>
|
||||
</ui:FASettingsExpander>
|
||||
|
||||
<ui:SettingsExpander Header="{Binding SystemMaterialLabel}"
|
||||
<ui:FASettingsExpander Header="{Binding SystemMaterialLabel}"
|
||||
Description="{Binding SystemMaterialDescription}">
|
||||
<ui:SettingsExpander.IconSource>
|
||||
<fi:SymbolIconSource Symbol="WindowDevTools" />
|
||||
</ui:SettingsExpander.IconSource>
|
||||
<ui:SettingsExpander.Footer>
|
||||
<ui:FASettingsExpander.IconSource>
|
||||
<ui:FAFontIconSource Glyph="󱩈" FontFamily="avares://fluenticons.resources.avalonia/Assets#Seagull Fluent Icons" />
|
||||
</ui:FASettingsExpander.IconSource>
|
||||
<ui:FASettingsExpander.Footer>
|
||||
<ComboBox Width="220"
|
||||
ItemsSource="{Binding SystemMaterialModes}"
|
||||
SelectedItem="{Binding SelectedSystemMaterialMode}">
|
||||
@@ -73,15 +73,15 @@
|
||||
</DataTemplate>
|
||||
</ComboBox.ItemTemplate>
|
||||
</ComboBox>
|
||||
</ui:SettingsExpander.Footer>
|
||||
</ui:SettingsExpander>
|
||||
</ui:FASettingsExpander.Footer>
|
||||
</ui:FASettingsExpander>
|
||||
|
||||
<ui:SettingsExpander Header="{Binding ThemeColorLabel}"
|
||||
<ui:FASettingsExpander Header="{Binding ThemeColorLabel}"
|
||||
Description="{Binding ThemeColorSourceDescription}">
|
||||
<ui:SettingsExpander.IconSource>
|
||||
<fi:SymbolIconSource Symbol="Color" />
|
||||
</ui:SettingsExpander.IconSource>
|
||||
<ui:SettingsExpanderItem>
|
||||
<ui:FASettingsExpander.IconSource>
|
||||
<ui:FAFontIconSource Glyph="󰢈" FontFamily="avares://fluenticons.resources.avalonia/Assets#Seagull Fluent Icons" />
|
||||
</ui:FASettingsExpander.IconSource>
|
||||
<ui:FASettingsExpanderItem>
|
||||
<StackPanel Spacing="12">
|
||||
<StackPanel Orientation="Horizontal"
|
||||
Spacing="12"
|
||||
@@ -257,8 +257,8 @@
|
||||
</Button>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</ui:SettingsExpanderItem>
|
||||
</ui:SettingsExpander>
|
||||
</ui:FASettingsExpanderItem>
|
||||
</ui:FASettingsExpander>
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
</UserControl>
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:vm="using:LanMountainDesktop.ViewModels"
|
||||
xmlns:controls="using:LanMountainDesktop.Controls"
|
||||
xmlns:ui="using:FluentAvalonia.UI.Controls"
|
||||
xmlns:fi="using:FluentIcons.Avalonia.Fluent"
|
||||
xmlns:fi="using:FluentIcons.Avalonia"
|
||||
x:Class="LanMountainDesktop.Views.SettingsPages.ComponentsSettingsPage"
|
||||
x:DataType="vm:ComponentsSettingsPageViewModel">
|
||||
<ScrollViewer VerticalScrollBarVisibility="Auto">
|
||||
@@ -12,12 +12,12 @@
|
||||
Text="{Binding ComponentsHeader}"
|
||||
Margin="0,0,0,4" />
|
||||
|
||||
<ui:SettingsExpander Header="{Binding ComponentsHeader}"
|
||||
<ui:FASettingsExpander Header="{Binding ComponentsHeader}"
|
||||
IsExpanded="True">
|
||||
<ui:SettingsExpander.IconSource>
|
||||
<fi:SymbolIconSource Symbol="Apps" />
|
||||
</ui:SettingsExpander.IconSource>
|
||||
<ui:SettingsExpanderItem>
|
||||
<ui:FASettingsExpander.IconSource>
|
||||
<ui:FAFontIconSource Glyph="󰀤" FontFamily="avares://fluenticons.resources.avalonia/Assets#Seagull Fluent Icons" />
|
||||
</ui:FASettingsExpander.IconSource>
|
||||
<ui:FASettingsExpanderItem>
|
||||
<Grid ColumnDefinitions="Auto,*,Auto" ColumnSpacing="16">
|
||||
<TextBlock Text="{Binding ShortSideCellsLabel}"
|
||||
VerticalAlignment="Center" />
|
||||
@@ -33,8 +33,8 @@
|
||||
VerticalAlignment="Center"
|
||||
HorizontalAlignment="Right" />
|
||||
</Grid>
|
||||
</ui:SettingsExpanderItem>
|
||||
<ui:SettingsExpanderItem>
|
||||
</ui:FASettingsExpanderItem>
|
||||
<ui:FASettingsExpanderItem>
|
||||
<Grid ColumnDefinitions="Auto,*,Auto" ColumnSpacing="16">
|
||||
<TextBlock Text="{Binding EdgeInsetPercentLabel}"
|
||||
VerticalAlignment="Center" />
|
||||
@@ -50,8 +50,8 @@
|
||||
VerticalAlignment="Center"
|
||||
HorizontalAlignment="Right" />
|
||||
</Grid>
|
||||
</ui:SettingsExpanderItem>
|
||||
<ui:SettingsExpanderItem>
|
||||
</ui:FASettingsExpanderItem>
|
||||
<ui:FASettingsExpanderItem>
|
||||
<Grid ColumnDefinitions="Auto,*">
|
||||
<TextBlock Text="{Binding SpacingPresetLabel}"
|
||||
VerticalAlignment="Center" />
|
||||
@@ -66,19 +66,19 @@
|
||||
</ComboBox.ItemTemplate>
|
||||
</ComboBox>
|
||||
</Grid>
|
||||
</ui:SettingsExpanderItem>
|
||||
</ui:SettingsExpander>
|
||||
</ui:FASettingsExpanderItem>
|
||||
</ui:FASettingsExpander>
|
||||
|
||||
<controls:IconText Icon="ShapeOrganic"
|
||||
Text="{Binding ComponentRadiusHeader}"
|
||||
Margin="0,12,0,4" />
|
||||
|
||||
<ui:SettingsExpander Header="{Binding CornerRadiusStyleLabel}"
|
||||
<ui:FASettingsExpander Header="{Binding CornerRadiusStyleLabel}"
|
||||
Description="{Binding CornerRadiusStyleDescription}">
|
||||
<ui:SettingsExpander.IconSource>
|
||||
<fi:SymbolIconSource Symbol="ShapeOrganic" />
|
||||
</ui:SettingsExpander.IconSource>
|
||||
<ui:SettingsExpander.Footer>
|
||||
<ui:FASettingsExpander.IconSource>
|
||||
<ui:FAFontIconSource Glyph="󰿨" FontFamily="avares://fluenticons.resources.avalonia/Assets#Seagull Fluent Icons" />
|
||||
</ui:FASettingsExpander.IconSource>
|
||||
<ui:FASettingsExpander.Footer>
|
||||
<StackPanel Orientation="Horizontal" Spacing="8">
|
||||
<ComboBox Width="200"
|
||||
ItemsSource="{Binding CornerRadiusStyleOptions}"
|
||||
@@ -93,8 +93,8 @@
|
||||
<fi:SymbolIcon Symbol="QuestionCircle" />
|
||||
</Button>
|
||||
</StackPanel>
|
||||
</ui:SettingsExpander.Footer>
|
||||
</ui:SettingsExpander>
|
||||
</ui:FASettingsExpander.Footer>
|
||||
</ui:FASettingsExpander>
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
</UserControl>
|
||||
|
||||
@@ -1,84 +1,92 @@
|
||||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:vm="using:LanMountainDesktop.ViewModels"
|
||||
xmlns:ui="using:FluentAvalonia.UI.Controls"
|
||||
xmlns:fi="using:FluentIcons.Avalonia.Fluent"
|
||||
xmlns:fi="using:FluentIcons.Avalonia"
|
||||
x:Class="LanMountainDesktop.Views.SettingsPages.DevSettingsPage"
|
||||
x:DataType="vm:DevSettingsPageViewModel">
|
||||
<ScrollViewer VerticalScrollBarVisibility="Auto">
|
||||
<StackPanel Classes="settings-page-container settings-page-animated">
|
||||
|
||||
<ui:InfoBar IsOpen="True"
|
||||
<ui:FAInfoBar IsOpen="True"
|
||||
IsClosable="False"
|
||||
Severity="Warning"
|
||||
Title="开发者模式"
|
||||
Message="开发者模式仅供开发和调试用途。开发者不对以非开发用途使用此功能造成的任何后果负责。"
|
||||
Margin="0,0,0,16" />
|
||||
Title="Preview and developer features"
|
||||
Message="These options are intended for debugging, diagnostics, and local plugin development."
|
||||
Margin="0,0,0,16">
|
||||
<ui:FAInfoBar.IconSource>
|
||||
<ui:FAFontIconSource Glyph="󰊈" FontFamily="avares://fluenticons.resources.avalonia/Assets#Seagull Fluent Icons" />
|
||||
</ui:FAInfoBar.IconSource>
|
||||
</ui:FAInfoBar>
|
||||
|
||||
<ui:SettingsExpander Header="启用开发者模式"
|
||||
Description="启用后可使用插件调试、开发者插件路径等高级功能">
|
||||
<ui:SettingsExpander.IconSource>
|
||||
<fi:SymbolIconSource Symbol="DeveloperBoard" />
|
||||
</ui:SettingsExpander.IconSource>
|
||||
<ui:SettingsExpander.Footer>
|
||||
<ui:FASettingsExpander Header="Developer mode"
|
||||
Description="Enable developer-focused startup helpers and diagnostics.">
|
||||
<ui:FASettingsExpander.IconSource>
|
||||
<ui:FAFontIconSource Glyph="󰆬" FontFamily="avares://fluenticons.resources.avalonia/Assets#Seagull Fluent Icons" />
|
||||
</ui:FASettingsExpander.IconSource>
|
||||
<ui:FASettingsExpander.Footer>
|
||||
<ToggleSwitch IsChecked="{Binding IsDevModeEnabled}" />
|
||||
</ui:SettingsExpander.Footer>
|
||||
</ui:SettingsExpander>
|
||||
</ui:FASettingsExpander.Footer>
|
||||
</ui:FASettingsExpander>
|
||||
|
||||
<ui:SettingsExpander Header="启用三指滑动"
|
||||
Description="使用三根手指或鼠标右键拖动自由滑动页面,在第一页向右滑动可回到 Windows 桌面(实验性功能)">
|
||||
<ui:SettingsExpander.IconSource>
|
||||
<fi:SymbolIconSource Symbol="Gesture" />
|
||||
</ui:SettingsExpander.IconSource>
|
||||
<ui:SettingsExpander.Footer>
|
||||
<ui:FASettingsExpander Header="Three-finger desktop swipe"
|
||||
Description="Enable desktop page switching gestures when the current platform supports them.">
|
||||
<ui:FASettingsExpander.IconSource>
|
||||
<ui:FAFontIconSource Glyph="󰋼" FontFamily="avares://fluenticons.resources.avalonia/Assets#Seagull Fluent Icons" />
|
||||
</ui:FASettingsExpander.IconSource>
|
||||
<ui:FASettingsExpander.Footer>
|
||||
<ToggleSwitch IsChecked="{Binding EnableThreeFingerSwipe}" />
|
||||
</ui:SettingsExpander.Footer>
|
||||
</ui:SettingsExpander>
|
||||
</ui:FASettingsExpander.Footer>
|
||||
</ui:FASettingsExpander>
|
||||
|
||||
<ui:SettingsExpander Header="启用融合桌面"
|
||||
Description="允许将组件放置在 Windows 系统桌面上(实验性功能,重启后生效)">
|
||||
<ui:SettingsExpander.IconSource>
|
||||
<fi:SymbolIconSource Symbol="Apps" />
|
||||
</ui:SettingsExpander.IconSource>
|
||||
<ui:SettingsExpander.Footer>
|
||||
<ui:FASettingsExpander Header="Fused desktop experience"
|
||||
Description="Enable the fused desktop shell and its related experimental entry points.">
|
||||
<ui:FASettingsExpander.IconSource>
|
||||
<ui:FAFontIconSource Glyph="󰆨" FontFamily="avares://fluenticons.resources.avalonia/Assets#Seagull Fluent Icons" />
|
||||
</ui:FASettingsExpander.IconSource>
|
||||
<ui:FASettingsExpander.Footer>
|
||||
<ToggleSwitch IsChecked="{Binding EnableFusedDesktop}" />
|
||||
</ui:SettingsExpander.Footer>
|
||||
</ui:SettingsExpander>
|
||||
</ui:FASettingsExpander.Footer>
|
||||
</ui:FASettingsExpander>
|
||||
|
||||
<Separator Classes="settings-separator" />
|
||||
|
||||
<ui:SettingsExpander Header="开发者插件路径"
|
||||
Description="指定开发中的插件目录路径,无需打包即可直接加载。多个路径用分号分隔。">
|
||||
<ui:SettingsExpander.IconSource>
|
||||
<fi:SymbolIconSource Symbol="FolderLink" />
|
||||
</ui:SettingsExpander.IconSource>
|
||||
<ui:SettingsExpanderItem>
|
||||
<ui:FASettingsExpander Header="Development plugin path"
|
||||
Description="Load a local plugin output directory for iterative debugging without packaging.">
|
||||
<ui:FASettingsExpander.IconSource>
|
||||
<ui:FAFontIconSource Glyph="󰈼" FontFamily="avares://fluenticons.resources.avalonia/Assets#Seagull Fluent Icons" />
|
||||
</ui:FASettingsExpander.IconSource>
|
||||
<ui:FASettingsExpanderItem>
|
||||
<TextBox Text="{Binding DevPluginPath}"
|
||||
Watermark="C:\path\to\plugin\bin\Debug\net10.0"
|
||||
PlaceholderText="C:\path\to\plugin\bin\Debug\net10.0"
|
||||
Width="360"
|
||||
MinWidth="200" />
|
||||
</ui:SettingsExpanderItem>
|
||||
</ui:SettingsExpander>
|
||||
</ui:FASettingsExpanderItem>
|
||||
</ui:FASettingsExpander>
|
||||
|
||||
<Separator Classes="settings-separator" />
|
||||
|
||||
<ui:SettingsExpander Header="命令行参数"
|
||||
Description="也可以通过命令行参数或环境变量指定开发者插件路径">
|
||||
<ui:SettingsExpander.IconSource>
|
||||
<fi:SymbolIconSource Symbol="WindowConsole" />
|
||||
</ui:SettingsExpander.IconSource>
|
||||
<ui:SettingsExpanderItem>
|
||||
<StackPanel Margin="0,8,0,0" Spacing="8">
|
||||
<TextBlock Text="命令行参数:" FontWeight="SemiBold" />
|
||||
<ui:FASettingsExpander Header="Developer startup arguments"
|
||||
Description="Use these launch arguments or environment variables to start the app in development scenarios.">
|
||||
<ui:FASettingsExpander.IconSource>
|
||||
<ui:FAFontIconSource Glyph="󱤰" FontFamily="avares://fluenticons.resources.avalonia/Assets#Seagull Fluent Icons" />
|
||||
</ui:FASettingsExpander.IconSource>
|
||||
<ui:FASettingsExpanderItem>
|
||||
<StackPanel Margin="0,8,0,0"
|
||||
Spacing="8">
|
||||
<TextBlock Text="Command-line arguments:"
|
||||
FontWeight="SemiBold" />
|
||||
<Border Background="{DynamicResource ControlFillColorDefaultBrush}"
|
||||
CornerRadius="8"
|
||||
Padding="12,8">
|
||||
<TextBlock FontFamily="Cascadia Code, Consolas, monospace"
|
||||
FontSize="12"
|
||||
Text="--dev-plugin <path> 或 -dp <path>"
|
||||
Text="--dev-plugin <path> or -dp <path>"
|
||||
TextWrapping="Wrap" />
|
||||
</Border>
|
||||
<TextBlock Text="环境变量:" FontWeight="SemiBold" Margin="0,8,0,0" />
|
||||
|
||||
<TextBlock Text="Environment variables:"
|
||||
FontWeight="SemiBold"
|
||||
Margin="0,8,0,0" />
|
||||
<Border Background="{DynamicResource ControlFillColorDefaultBrush}"
|
||||
CornerRadius="8"
|
||||
Padding="12,8">
|
||||
@@ -87,23 +95,25 @@
|
||||
Text="LMD_DEV_PLUGIN=<path>"
|
||||
TextWrapping="Wrap" />
|
||||
</Border>
|
||||
<TextBlock Text="其他参数:" FontWeight="SemiBold" Margin="0,8,0,0" />
|
||||
|
||||
<TextBlock Text="Other arguments:"
|
||||
FontWeight="SemiBold"
|
||||
Margin="0,8,0,0" />
|
||||
<Border Background="{DynamicResource ControlFillColorDefaultBrush}"
|
||||
CornerRadius="8"
|
||||
Padding="12,8">
|
||||
<StackPanel Spacing="4">
|
||||
<TextBlock FontFamily="Cascadia Code, Consolas, monospace"
|
||||
FontSize="12"
|
||||
Text="--dev-mode / -dev 启用开发者模式" />
|
||||
Text="--dev-mode / -dev Enable developer mode startup helpers." />
|
||||
<TextBlock FontFamily="Cascadia Code, Consolas, monospace"
|
||||
FontSize="12"
|
||||
Text="--hot-reload / -hr 启用热重载(预留)" />
|
||||
Text="--hot-reload / -hr Enable hot reload for development builds." />
|
||||
</StackPanel>
|
||||
</Border>
|
||||
</StackPanel>
|
||||
</ui:SettingsExpanderItem>
|
||||
</ui:SettingsExpander>
|
||||
|
||||
</ui:FASettingsExpanderItem>
|
||||
</ui:FASettingsExpander>
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
</UserControl>
|
||||
|
||||
@@ -6,7 +6,7 @@ namespace LanMountainDesktop.Views.SettingsPages;
|
||||
|
||||
[SettingsPageInfo(
|
||||
"dev",
|
||||
"开发者",
|
||||
"Developer",
|
||||
SettingsPageCategory.Dev,
|
||||
IconKey = "DeveloperBoard",
|
||||
SortOrder = 0,
|
||||
|
||||
@@ -1,23 +1,22 @@
|
||||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:vm="using:LanMountainDesktop.ViewModels"
|
||||
xmlns:controls="using:LanMountainDesktop.Controls"
|
||||
xmlns:ui="using:FluentAvalonia.UI.Controls"
|
||||
xmlns:fi="using:FluentIcons.Avalonia.Fluent"
|
||||
xmlns:fi="using:FluentIcons.Avalonia"
|
||||
x:Class="LanMountainDesktop.Views.SettingsPages.GeneralSettingsPage"
|
||||
x:DataType="vm:GeneralSettingsPageViewModel">
|
||||
<ScrollViewer VerticalScrollBarVisibility="Auto">
|
||||
<StackPanel Classes="settings-page-container settings-page-animated">
|
||||
|
||||
<controls:IconText Icon="Globe"
|
||||
Text="{Binding BasicHeader}"
|
||||
Margin="0,0,0,4" />
|
||||
|
||||
<ui:SettingsExpander Header="{Binding LanguageHeader}">
|
||||
<ui:SettingsExpander.IconSource>
|
||||
<fi:SymbolIconSource Symbol="Settings" />
|
||||
</ui:SettingsExpander.IconSource>
|
||||
<ui:SettingsExpander.Footer>
|
||||
<ui:FASettingsExpander Header="{Binding LanguageHeader}">
|
||||
<ui:FASettingsExpander.IconSource>
|
||||
<ui:FAFontIconSource Glyph="󰐄" FontFamily="avares://fluenticons.resources.avalonia/Assets#Seagull Fluent Icons" />
|
||||
</ui:FASettingsExpander.IconSource>
|
||||
<ui:FASettingsExpander.Footer>
|
||||
<ComboBox Width="220"
|
||||
ItemsSource="{Binding Languages}"
|
||||
SelectedItem="{Binding SelectedLanguage}">
|
||||
@@ -27,15 +26,15 @@
|
||||
</DataTemplate>
|
||||
</ComboBox.ItemTemplate>
|
||||
</ComboBox>
|
||||
</ui:SettingsExpander.Footer>
|
||||
</ui:SettingsExpander>
|
||||
</ui:FASettingsExpander.Footer>
|
||||
</ui:FASettingsExpander>
|
||||
|
||||
<ui:SettingsExpander Header="{Binding TimeZoneHeader}"
|
||||
<ui:FASettingsExpander Header="{Binding TimeZoneHeader}"
|
||||
Description="{Binding TimeZoneDescription}">
|
||||
<ui:SettingsExpander.IconSource>
|
||||
<fi:SymbolIconSource Symbol="Clock" />
|
||||
</ui:SettingsExpander.IconSource>
|
||||
<ui:SettingsExpander.Footer>
|
||||
<ui:FASettingsExpander.IconSource>
|
||||
<ui:FAFontIconSource Glyph="󰅨" FontFamily="avares://fluenticons.resources.avalonia/Assets#Seagull Fluent Icons" />
|
||||
</ui:FASettingsExpander.IconSource>
|
||||
<ui:FASettingsExpander.Footer>
|
||||
<ComboBox Width="240"
|
||||
ItemsSource="{Binding TimeZones}"
|
||||
SelectedItem="{Binding SelectedTimeZone}">
|
||||
@@ -45,14 +44,14 @@
|
||||
</DataTemplate>
|
||||
</ComboBox.ItemTemplate>
|
||||
</ComboBox>
|
||||
</ui:SettingsExpander.Footer>
|
||||
</ui:SettingsExpander>
|
||||
</ui:FASettingsExpander.Footer>
|
||||
</ui:FASettingsExpander>
|
||||
|
||||
<ui:SettingsExpander Header="{Binding PreviewHeader}">
|
||||
<ui:SettingsExpander.IconSource>
|
||||
<fi:SymbolIconSource Symbol="Calendar" />
|
||||
</ui:SettingsExpander.IconSource>
|
||||
<ui:SettingsExpanderItem>
|
||||
<ui:FASettingsExpander Header="{Binding PreviewHeader}">
|
||||
<ui:FASettingsExpander.IconSource>
|
||||
<ui:FAFontIconSource Glyph="󱲀" FontFamily="avares://fluenticons.resources.avalonia/Assets#Seagull Fluent Icons" />
|
||||
</ui:FASettingsExpander.IconSource>
|
||||
<ui:FASettingsExpanderItem>
|
||||
<Grid ColumnDefinitions="Auto,*"
|
||||
ColumnSpacing="16"
|
||||
RowDefinitions="Auto,Auto"
|
||||
@@ -70,8 +69,8 @@
|
||||
Opacity="0.82"
|
||||
Text="{Binding PreviewDateText}" />
|
||||
</Grid>
|
||||
</ui:SettingsExpanderItem>
|
||||
</ui:SettingsExpander>
|
||||
</ui:FASettingsExpanderItem>
|
||||
</ui:FASettingsExpander>
|
||||
|
||||
<Separator Classes="settings-separator" />
|
||||
|
||||
@@ -79,13 +78,13 @@
|
||||
Text="{Binding RuntimeHeader}"
|
||||
Margin="0,0,0,4" />
|
||||
|
||||
<ui:SettingsExpander Header="{Binding RenderModeHeader}"
|
||||
<ui:FASettingsExpander Header="{Binding RenderModeHeader}"
|
||||
Description="{Binding RuntimeDescription}"
|
||||
IsExpanded="True">
|
||||
<ui:SettingsExpander.IconSource>
|
||||
<fi:SymbolIconSource Symbol="DeveloperBoard" />
|
||||
</ui:SettingsExpander.IconSource>
|
||||
<ui:SettingsExpander.Footer>
|
||||
<ui:FASettingsExpander.IconSource>
|
||||
<ui:FAFontIconSource Glyph="󰤈" FontFamily="avares://fluenticons.resources.avalonia/Assets#Seagull Fluent Icons" />
|
||||
</ui:FASettingsExpander.IconSource>
|
||||
<ui:FASettingsExpander.Footer>
|
||||
<ComboBox Width="220"
|
||||
ItemsSource="{Binding RenderModes}"
|
||||
SelectedItem="{Binding SelectedRenderMode}">
|
||||
@@ -95,48 +94,47 @@
|
||||
</DataTemplate>
|
||||
</ComboBox.ItemTemplate>
|
||||
</ComboBox>
|
||||
</ui:SettingsExpander.Footer>
|
||||
<ui:SettingsExpanderItem>
|
||||
</ui:FASettingsExpander.Footer>
|
||||
<ui:FASettingsExpanderItem>
|
||||
<TextBlock Text="{Binding RenderModeRestartMessage}"
|
||||
Opacity="0.7"
|
||||
FontSize="12"
|
||||
TextWrapping="Wrap" />
|
||||
</ui:SettingsExpanderItem>
|
||||
</ui:SettingsExpander>
|
||||
</ui:FASettingsExpanderItem>
|
||||
</ui:FASettingsExpander>
|
||||
|
||||
<ui:SettingsExpander Header="淡入淡出效果"
|
||||
<ui:FASettingsExpander Header="Fade startup transition"
|
||||
Description="{Binding FadeTransitionDescription}"
|
||||
IsVisible="{Binding IsSlideTransitionAvailable}">
|
||||
<ui:SettingsExpander.IconSource>
|
||||
<fi:SymbolIconSource Symbol="ArrowUpload" />
|
||||
</ui:SettingsExpander.IconSource>
|
||||
<ui:SettingsExpander.Footer>
|
||||
<ui:FASettingsExpander.IconSource>
|
||||
<ui:FAFontIconSource Glyph="󱩈" FontFamily="avares://fluenticons.resources.avalonia/Assets#Seagull Fluent Icons" />
|
||||
</ui:FASettingsExpander.IconSource>
|
||||
<ui:FASettingsExpander.Footer>
|
||||
<ToggleSwitch IsChecked="{Binding EnableFadeTransition}"
|
||||
IsEnabled="{Binding IsFadeTransitionToggleEnabled}" />
|
||||
</ui:SettingsExpander.Footer>
|
||||
</ui:SettingsExpander>
|
||||
</ui:FASettingsExpander.Footer>
|
||||
</ui:FASettingsExpander>
|
||||
|
||||
<ui:SettingsExpander Header="启动滑入滑出效果"
|
||||
Description="启用后,启动和恢复时从屏幕右侧边缘滑入或滑出,仅 Windows 可用。"
|
||||
<ui:FASettingsExpander Header="Slide startup transition"
|
||||
Description="Use a slide-in startup transition on supported Windows builds. This option disables the fade transition."
|
||||
IsVisible="{Binding IsSlideTransitionAvailable}">
|
||||
<ui:SettingsExpander.IconSource>
|
||||
<fi:SymbolIconSource Symbol="ArrowRight" />
|
||||
</ui:SettingsExpander.IconSource>
|
||||
<ui:SettingsExpander.Footer>
|
||||
<ui:FASettingsExpander.IconSource>
|
||||
<ui:FAFontIconSource Glyph="󰣨" FontFamily="avares://fluenticons.resources.avalonia/Assets#Seagull Fluent Icons" />
|
||||
</ui:FASettingsExpander.IconSource>
|
||||
<ui:FASettingsExpander.Footer>
|
||||
<ToggleSwitch IsChecked="{Binding EnableSlideTransition}" />
|
||||
</ui:SettingsExpander.Footer>
|
||||
</ui:SettingsExpander>
|
||||
</ui:FASettingsExpander.Footer>
|
||||
</ui:FASettingsExpander>
|
||||
|
||||
<ui:SettingsExpander Header="桌面主窗口在任务栏显示图标"
|
||||
Description="仅控制桌面主窗口在系统任务栏中的图标显示,不影响设置窗口。">
|
||||
<ui:SettingsExpander.IconSource>
|
||||
<fi:SymbolIconSource Symbol="Window" />
|
||||
</ui:SettingsExpander.IconSource>
|
||||
<ui:SettingsExpander.Footer>
|
||||
<ui:FASettingsExpander Header="Show in taskbar"
|
||||
Description="Keep the main window visible in the taskbar while the desktop host is running.">
|
||||
<ui:FASettingsExpander.IconSource>
|
||||
<ui:FAFontIconSource Glyph="󱯠" FontFamily="avares://fluenticons.resources.avalonia/Assets#Seagull Fluent Icons" />
|
||||
</ui:FASettingsExpander.IconSource>
|
||||
<ui:FASettingsExpander.Footer>
|
||||
<ToggleSwitch IsChecked="{Binding ShowInTaskbar}" />
|
||||
</ui:SettingsExpander.Footer>
|
||||
</ui:SettingsExpander>
|
||||
|
||||
</ui:FASettingsExpander.Footer>
|
||||
</ui:FASettingsExpander>
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
</UserControl>
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:vm="using:LanMountainDesktop.ViewModels"
|
||||
xmlns:controls="using:LanMountainDesktop.Controls"
|
||||
xmlns:ui="using:FluentAvalonia.UI.Controls"
|
||||
xmlns:fi="using:FluentIcons.Avalonia.Fluent"
|
||||
xmlns:fi="using:FluentIcons.Avalonia"
|
||||
xmlns:symbol="using:FluentIcons.Common"
|
||||
x:Class="LanMountainDesktop.Views.SettingsPages.LauncherSettingsPage"
|
||||
x:DataType="vm:LauncherSettingsPageViewModel">
|
||||
@@ -56,14 +56,14 @@
|
||||
Text="{Binding AppearanceHeader}"
|
||||
Margin="0,0,0,4" />
|
||||
|
||||
<ui:SettingsExpander Classes="settings-expander-card"
|
||||
<ui:FASettingsExpander Classes="settings-expander-card"
|
||||
Header="{Binding AppearanceHeader}"
|
||||
Description="{Binding AppearanceDescription}"
|
||||
IsExpanded="True">
|
||||
<ui:SettingsExpander.IconSource>
|
||||
<fi:SymbolIconSource Symbol="{x:Static symbol:Symbol.Apps}" />
|
||||
</ui:SettingsExpander.IconSource>
|
||||
<ui:SettingsExpanderItem>
|
||||
<ui:FASettingsExpander.IconSource>
|
||||
<ui:FAFontIconSource Glyph="󰢈" FontFamily="avares://fluenticons.resources.avalonia/Assets#Seagull Fluent Icons" />
|
||||
</ui:FASettingsExpander.IconSource>
|
||||
<ui:FASettingsExpanderItem>
|
||||
<Grid ColumnDefinitions="*,Auto">
|
||||
<StackPanel Spacing="2">
|
||||
<TextBlock Text="{Binding ShowTileBackgroundHeader}" />
|
||||
@@ -73,21 +73,21 @@
|
||||
<ToggleSwitch Grid.Column="1"
|
||||
IsChecked="{Binding ShowTileBackground}" />
|
||||
</Grid>
|
||||
</ui:SettingsExpanderItem>
|
||||
</ui:SettingsExpander>
|
||||
</ui:FASettingsExpanderItem>
|
||||
</ui:FASettingsExpander>
|
||||
|
||||
<controls:IconText Icon="Apps"
|
||||
Text="{Binding HiddenHeader}"
|
||||
Margin="0,24,0,4" />
|
||||
|
||||
<ui:SettingsExpander Classes="settings-expander-card"
|
||||
<ui:FASettingsExpander Classes="settings-expander-card"
|
||||
Header="{Binding HiddenHeader}"
|
||||
Description="{Binding HiddenDescription}"
|
||||
IsExpanded="True">
|
||||
<ui:SettingsExpander.IconSource>
|
||||
<fi:SymbolIconSource Symbol="Apps" />
|
||||
</ui:SettingsExpander.IconSource>
|
||||
<ui:SettingsExpanderItem>
|
||||
<ui:FASettingsExpander.IconSource>
|
||||
<ui:FAFontIconSource Glyph="󱲀" FontFamily="avares://fluenticons.resources.avalonia/Assets#Seagull Fluent Icons" />
|
||||
</ui:FASettingsExpander.IconSource>
|
||||
<ui:FASettingsExpanderItem>
|
||||
<StackPanel Spacing="8">
|
||||
<TextBlock Classes="settings-item-description"
|
||||
IsVisible="{Binding IsHiddenItemsEmpty}"
|
||||
@@ -99,24 +99,24 @@
|
||||
IsVisible="{Binding HasHiddenItems}">
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate x:DataType="vm:LauncherHiddenItemViewModel">
|
||||
<ui:SettingsExpanderItem Content="{Binding DisplayName}"
|
||||
<ui:FASettingsExpanderItem Content="{Binding DisplayName}"
|
||||
Description="{Binding TypeLabel}"
|
||||
IsClickEnabled="False">
|
||||
<ui:SettingsExpanderItem.IconSource>
|
||||
<fi:SymbolIconSource Symbol="{Binding IconSymbol}" />
|
||||
</ui:SettingsExpanderItem.IconSource>
|
||||
<ui:SettingsExpanderItem.Footer>
|
||||
<ui:FASettingsExpanderItem.IconSource>
|
||||
<ui:FAFontIconSource Glyph="󱧼" FontFamily="avares://fluenticons.resources.avalonia/Assets#Seagull Fluent Icons" />
|
||||
</ui:FASettingsExpanderItem.IconSource>
|
||||
<ui:FASettingsExpanderItem.Footer>
|
||||
<Button Command="{Binding RestoreCommand}"
|
||||
Content="{Binding RestoreButtonText}"
|
||||
VerticalAlignment="Center" />
|
||||
</ui:SettingsExpanderItem.Footer>
|
||||
</ui:SettingsExpanderItem>
|
||||
</ui:FASettingsExpanderItem.Footer>
|
||||
</ui:FASettingsExpanderItem>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
</StackPanel>
|
||||
</ui:SettingsExpanderItem>
|
||||
</ui:SettingsExpander>
|
||||
</ui:FASettingsExpanderItem>
|
||||
</ui:FASettingsExpander>
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
</UserControl>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
xmlns:vm="using:LanMountainDesktop.ViewModels"
|
||||
xmlns:controls="using:LanMountainDesktop.Controls"
|
||||
xmlns:ui="using:FluentAvalonia.UI.Controls"
|
||||
xmlns:fi="using:FluentIcons.Avalonia.Fluent"
|
||||
xmlns:fi="using:FluentIcons.Avalonia"
|
||||
x:Class="LanMountainDesktop.Views.SettingsPages.NotificationSettingsPage"
|
||||
x:DataType="vm:NotificationSettingsPageViewModel">
|
||||
<ScrollViewer VerticalScrollBarVisibility="Auto">
|
||||
@@ -13,15 +13,15 @@
|
||||
Text="{Binding NotificationHeader}"
|
||||
Margin="0,0,0,4" />
|
||||
|
||||
<ui:SettingsExpander Header="{Binding EnableNotificationHeader}"
|
||||
<ui:FASettingsExpander Header="{Binding EnableNotificationHeader}"
|
||||
Description="{Binding EnableNotificationDescription}">
|
||||
<ui:SettingsExpander.IconSource>
|
||||
<fi:SymbolIconSource Symbol="Alert" />
|
||||
</ui:SettingsExpander.IconSource>
|
||||
<ui:SettingsExpander.Footer>
|
||||
<ui:FASettingsExpander.IconSource>
|
||||
<ui:FAFontIconSource Glyph="󰀘" FontFamily="avares://fluenticons.resources.avalonia/Assets#Seagull Fluent Icons" />
|
||||
</ui:FASettingsExpander.IconSource>
|
||||
<ui:FASettingsExpander.Footer>
|
||||
<ToggleSwitch IsChecked="{Binding IsNotificationEnabled}" />
|
||||
</ui:SettingsExpander.Footer>
|
||||
</ui:SettingsExpander>
|
||||
</ui:FASettingsExpander.Footer>
|
||||
</ui:FASettingsExpander>
|
||||
|
||||
<Separator Classes="settings-separator" />
|
||||
|
||||
@@ -29,39 +29,39 @@
|
||||
Text="{Binding BehaviorHeader}"
|
||||
Margin="0,0,0,4" />
|
||||
|
||||
<ui:SettingsExpander Header="{Binding HoverPauseHeader}"
|
||||
<ui:FASettingsExpander Header="{Binding HoverPauseHeader}"
|
||||
Description="{Binding HoverPauseDescription}">
|
||||
<ui:SettingsExpander.IconSource>
|
||||
<fi:SymbolIconSource Symbol="CursorHover" />
|
||||
</ui:SettingsExpander.IconSource>
|
||||
<ui:SettingsExpander.Footer>
|
||||
<ui:FASettingsExpander.IconSource>
|
||||
<ui:FAFontIconSource Glyph="󰙬" FontFamily="avares://fluenticons.resources.avalonia/Assets#Seagull Fluent Icons" />
|
||||
</ui:FASettingsExpander.IconSource>
|
||||
<ui:FASettingsExpander.Footer>
|
||||
<ToggleSwitch IsChecked="{Binding IsHoverPauseEnabled}" />
|
||||
</ui:SettingsExpander.Footer>
|
||||
</ui:SettingsExpander>
|
||||
</ui:FASettingsExpander.Footer>
|
||||
</ui:FASettingsExpander>
|
||||
|
||||
<ui:SettingsExpander Header="{Binding ClickCloseHeader}"
|
||||
<ui:FASettingsExpander Header="{Binding ClickCloseHeader}"
|
||||
Description="{Binding ClickCloseDescription}">
|
||||
<ui:SettingsExpander.IconSource>
|
||||
<fi:SymbolIconSource Symbol="CursorClick" />
|
||||
</ui:SettingsExpander.IconSource>
|
||||
<ui:SettingsExpander.Footer>
|
||||
<ui:FASettingsExpander.IconSource>
|
||||
<ui:FAFontIconSource Glyph="󰅈" FontFamily="avares://fluenticons.resources.avalonia/Assets#Seagull Fluent Icons" />
|
||||
</ui:FASettingsExpander.IconSource>
|
||||
<ui:FASettingsExpander.Footer>
|
||||
<ToggleSwitch IsChecked="{Binding IsClickCloseEnabled}" />
|
||||
</ui:SettingsExpander.Footer>
|
||||
</ui:SettingsExpander>
|
||||
</ui:FASettingsExpander.Footer>
|
||||
</ui:FASettingsExpander>
|
||||
|
||||
<ui:SettingsExpander Header="{Binding MaxNotificationsHeader}"
|
||||
<ui:FASettingsExpander Header="{Binding MaxNotificationsHeader}"
|
||||
Description="{Binding MaxNotificationsDescription}">
|
||||
<ui:SettingsExpander.IconSource>
|
||||
<fi:SymbolIconSource Symbol="NumberSymbol" />
|
||||
</ui:SettingsExpander.IconSource>
|
||||
<ui:SettingsExpander.Footer>
|
||||
<ui:NumberBox Value="{Binding MaxNotificationsPerPosition}"
|
||||
<ui:FASettingsExpander.IconSource>
|
||||
<ui:FAFontIconSource Glyph="󰀐" FontFamily="avares://fluenticons.resources.avalonia/Assets#Seagull Fluent Icons" />
|
||||
</ui:FASettingsExpander.IconSource>
|
||||
<ui:FASettingsExpander.Footer>
|
||||
<ui:FANumberBox Value="{Binding MaxNotificationsPerPosition}"
|
||||
Minimum="1"
|
||||
Maximum="10"
|
||||
Width="100"
|
||||
SpinButtonPlacementMode="Inline" />
|
||||
</ui:SettingsExpander.Footer>
|
||||
</ui:SettingsExpander>
|
||||
</ui:FASettingsExpander.Footer>
|
||||
</ui:FASettingsExpander>
|
||||
|
||||
<Separator Classes="settings-separator" />
|
||||
|
||||
@@ -69,12 +69,12 @@
|
||||
Text="{Binding TestHeader}"
|
||||
Margin="0,0,0,4" />
|
||||
|
||||
<ui:SettingsExpander Header="{Binding TestNotificationHeader}"
|
||||
<ui:FASettingsExpander Header="{Binding TestNotificationHeader}"
|
||||
Description="{Binding TestNotificationDescription}">
|
||||
<ui:SettingsExpander.IconSource>
|
||||
<fi:SymbolIconSource Symbol="Beaker" />
|
||||
</ui:SettingsExpander.IconSource>
|
||||
<ui:SettingsExpander.Footer>
|
||||
<ui:FASettingsExpander.IconSource>
|
||||
<ui:FAFontIconSource Glyph="󰏼" FontFamily="avares://fluenticons.resources.avalonia/Assets#Seagull Fluent Icons" />
|
||||
</ui:FASettingsExpander.IconSource>
|
||||
<ui:FASettingsExpander.Footer>
|
||||
<StackPanel Orientation="Horizontal" Spacing="8">
|
||||
<ComboBox Width="120"
|
||||
ItemsSource="{Binding TestPositions}"
|
||||
@@ -94,7 +94,7 @@
|
||||
</DataTemplate>
|
||||
</ComboBox.ItemTemplate>
|
||||
</ComboBox>
|
||||
<ui:NumberBox Width="100"
|
||||
<ui:FANumberBox Width="100"
|
||||
Minimum="1"
|
||||
Maximum="30"
|
||||
SpinButtonPlacementMode="Inline"
|
||||
@@ -104,8 +104,8 @@
|
||||
<fi:SymbolIcon Symbol="Send" FontSize="16" />
|
||||
</Button>
|
||||
</StackPanel>
|
||||
</ui:SettingsExpander.Footer>
|
||||
</ui:SettingsExpander>
|
||||
</ui:FASettingsExpander.Footer>
|
||||
</ui:FASettingsExpander>
|
||||
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
xmlns:vm="using:LanMountainDesktop.ViewModels"
|
||||
xmlns:mdxaml="https://github.com/whistyun/Markdown.Avalonia"
|
||||
xmlns:helpers="using:LanMountainDesktop.Helpers"
|
||||
xmlns:fi="using:FluentIcons.Avalonia.Fluent"
|
||||
xmlns:fi="using:FluentIcons.Avalonia"
|
||||
x:Class="LanMountainDesktop.Views.SettingsPages.PluginCatalogDetailDrawer"
|
||||
x:DataType="vm:PluginCatalogDetailViewModel">
|
||||
<ScrollViewer VerticalScrollBarVisibility="Auto">
|
||||
|
||||
@@ -1,32 +1,32 @@
|
||||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:vm="using:LanMountainDesktop.ViewModels"
|
||||
xmlns:ui="using:FluentAvalonia.UI.Controls"
|
||||
xmlns:fi="using:FluentIcons.Avalonia.Fluent"
|
||||
xmlns:fi="using:FluentIcons.Avalonia"
|
||||
x:Class="LanMountainDesktop.Views.SettingsPages.PluginCatalogSettingsPage"
|
||||
x:Name="Root"
|
||||
x:DataType="vm:PluginCatalogSettingsPageViewModel">
|
||||
<ScrollViewer VerticalScrollBarVisibility="Auto">
|
||||
<StackPanel Classes="settings-page-container settings-page-animated">
|
||||
<ui:SettingsExpander Header="{Binding RefreshButtonText}"
|
||||
<ui:FASettingsExpander Header="{Binding RefreshButtonText}"
|
||||
Description="{Binding StatusMessage}">
|
||||
<ui:SettingsExpander.IconSource>
|
||||
<fi:SymbolIconSource Symbol="ShoppingBag" />
|
||||
</ui:SettingsExpander.IconSource>
|
||||
<ui:SettingsExpander.Footer>
|
||||
<ui:FASettingsExpander.IconSource>
|
||||
<ui:FAFontIconSource Glyph="󱗨" FontFamily="avares://fluenticons.resources.avalonia/Assets#Seagull Fluent Icons" />
|
||||
</ui:FASettingsExpander.IconSource>
|
||||
<ui:FASettingsExpander.Footer>
|
||||
<Grid ColumnDefinitions="*,Auto"
|
||||
ColumnSpacing="12">
|
||||
<TextBox x:Name="SearchTextBox"
|
||||
Text="{Binding SearchText}"
|
||||
Watermark="{Binding SearchPlaceholder}"
|
||||
PlaceholderText="{Binding SearchPlaceholder}"
|
||||
Focusable="True"
|
||||
IsTabStop="True" />
|
||||
<Button Grid.Column="1"
|
||||
Command="{Binding RefreshCommand}"
|
||||
Content="{Binding RefreshButtonText}" />
|
||||
</Grid>
|
||||
</ui:SettingsExpander.Footer>
|
||||
</ui:SettingsExpander>
|
||||
</ui:FASettingsExpander.Footer>
|
||||
</ui:FASettingsExpander>
|
||||
|
||||
<TextBlock Classes="settings-item-description"
|
||||
IsVisible="{Binding ShowEmptyState}"
|
||||
|
||||
@@ -1,24 +1,24 @@
|
||||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:vm="using:LanMountainDesktop.ViewModels"
|
||||
xmlns:controls="using:LanMountainDesktop.Controls"
|
||||
xmlns:ui="using:FluentAvalonia.UI.Controls"
|
||||
xmlns:fi="using:FluentIcons.Avalonia.Fluent"
|
||||
xmlns:fi="using:FluentIcons.Avalonia"
|
||||
x:Class="LanMountainDesktop.Views.SettingsPages.PluginsSettingsPage"
|
||||
x:Name="Root"
|
||||
x:DataType="vm:PluginsSettingsPageViewModel">
|
||||
<ScrollViewer VerticalScrollBarVisibility="Auto">
|
||||
<StackPanel Classes="settings-page-container settings-page-animated">
|
||||
<ui:SettingsExpander Header="{Binding RefreshButtonText}"
|
||||
<ui:FASettingsExpander Header="{Binding RefreshButtonText}"
|
||||
Description="{Binding StatusMessage}">
|
||||
<ui:SettingsExpander.IconSource>
|
||||
<fi:SymbolIconSource Symbol="ArrowSync" />
|
||||
</ui:SettingsExpander.IconSource>
|
||||
<ui:SettingsExpander.Footer>
|
||||
<ui:FASettingsExpander.IconSource>
|
||||
<ui:FAFontIconSource Glyph="󰛼" FontFamily="avares://fluenticons.resources.avalonia/Assets#Seagull Fluent Icons" />
|
||||
</ui:FASettingsExpander.IconSource>
|
||||
<ui:FASettingsExpander.Footer>
|
||||
<Button Command="{Binding RefreshCommand}"
|
||||
Content="{Binding RefreshButtonText}" />
|
||||
</ui:SettingsExpander.Footer>
|
||||
</ui:SettingsExpander>
|
||||
</ui:FASettingsExpander.Footer>
|
||||
</ui:FASettingsExpander>
|
||||
|
||||
<Separator Classes="settings-separator" />
|
||||
|
||||
@@ -29,17 +29,17 @@
|
||||
<ItemsControl ItemsSource="{Binding InstalledPlugins}">
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate x:DataType="vm:InstalledPluginItemViewModel">
|
||||
<ui:SettingsExpander>
|
||||
<ui:SettingsExpander.IconSource>
|
||||
<fi:SymbolIconSource Symbol="PuzzleCube" />
|
||||
</ui:SettingsExpander.IconSource>
|
||||
<ui:SettingsExpander.Header>
|
||||
<ui:FASettingsExpander>
|
||||
<ui:FASettingsExpander.IconSource>
|
||||
<ui:FAFontIconSource Glyph="󲣔" FontFamily="avares://fluenticons.resources.avalonia/Assets#Seagull Fluent Icons" />
|
||||
</ui:FASettingsExpander.IconSource>
|
||||
<ui:FASettingsExpander.Header>
|
||||
<StackPanel>
|
||||
<TextBlock FontWeight="SemiBold" Text="{Binding Name}" />
|
||||
<TextBlock Opacity="0.76" FontSize="12" Text="{Binding Description}" />
|
||||
</StackPanel>
|
||||
</ui:SettingsExpander.Header>
|
||||
<ui:SettingsExpander.Footer>
|
||||
</ui:FASettingsExpander.Header>
|
||||
<ui:FASettingsExpander.Footer>
|
||||
<StackPanel Orientation="Horizontal" Spacing="8">
|
||||
<ToggleSwitch IsChecked="{Binding IsEnabled}"
|
||||
Command="{Binding #Root.DataContext.TogglePluginCommand}"
|
||||
@@ -48,8 +48,8 @@
|
||||
CommandParameter="{Binding}"
|
||||
Content="{Binding #Root.DataContext.DeleteButtonText}" />
|
||||
</StackPanel>
|
||||
</ui:SettingsExpander.Footer>
|
||||
</ui:SettingsExpander>
|
||||
</ui:FASettingsExpander.Footer>
|
||||
</ui:FASettingsExpander>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
xmlns:vm="using:LanMountainDesktop.ViewModels"
|
||||
xmlns:mdxaml="https://github.com/whistyun/Markdown.Avalonia"
|
||||
xmlns:helpers="using:LanMountainDesktop.Helpers"
|
||||
xmlns:fi="using:FluentIcons.Avalonia.Fluent"
|
||||
xmlns:fi="using:FluentIcons.Avalonia"
|
||||
x:Class="LanMountainDesktop.Views.SettingsPages.PrivacyPolicyDrawer"
|
||||
x:DataType="vm:PrivacyPolicyViewModel">
|
||||
<ScrollViewer VerticalScrollBarVisibility="Auto">
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:vm="using:LanMountainDesktop.ViewModels"
|
||||
xmlns:controls="using:LanMountainDesktop.Controls"
|
||||
xmlns:ui="using:FluentAvalonia.UI.Controls"
|
||||
xmlns:fi="using:FluentIcons.Avalonia.Fluent"
|
||||
xmlns:fi="using:FluentIcons.Avalonia"
|
||||
x:Class="LanMountainDesktop.Views.SettingsPages.PrivacySettingsPage"
|
||||
x:DataType="vm:PrivacySettingsPageViewModel">
|
||||
<ScrollViewer VerticalScrollBarVisibility="Auto">
|
||||
@@ -12,25 +12,25 @@
|
||||
Text="{Binding PrivacyHeader}"
|
||||
Margin="0,0,0,4" />
|
||||
|
||||
<ui:SettingsExpander Header="{Binding CrashUploadHeader}"
|
||||
<ui:FASettingsExpander Header="{Binding CrashUploadHeader}"
|
||||
Description="{Binding CrashUploadDescription}">
|
||||
<ui:SettingsExpander.IconSource>
|
||||
<fi:SymbolIconSource Symbol="ShieldDismiss" />
|
||||
</ui:SettingsExpander.IconSource>
|
||||
<ui:SettingsExpander.Footer>
|
||||
<ui:FASettingsExpander.IconSource>
|
||||
<ui:FAFontIconSource Glyph="󰶜" FontFamily="avares://fluenticons.resources.avalonia/Assets#Seagull Fluent Icons" />
|
||||
</ui:FASettingsExpander.IconSource>
|
||||
<ui:FASettingsExpander.Footer>
|
||||
<ToggleSwitch IsChecked="{Binding UploadAnonymousCrashData}" />
|
||||
</ui:SettingsExpander.Footer>
|
||||
</ui:SettingsExpander>
|
||||
</ui:FASettingsExpander.Footer>
|
||||
</ui:FASettingsExpander>
|
||||
|
||||
<ui:SettingsExpander Header="{Binding UsageUploadHeader}"
|
||||
<ui:FASettingsExpander Header="{Binding UsageUploadHeader}"
|
||||
Description="{Binding UsageUploadDescription}">
|
||||
<ui:SettingsExpander.IconSource>
|
||||
<fi:SymbolIconSource Symbol="Info" />
|
||||
</ui:SettingsExpander.IconSource>
|
||||
<ui:SettingsExpander.Footer>
|
||||
<ui:FASettingsExpander.IconSource>
|
||||
<ui:FAFontIconSource Glyph="󰞤" FontFamily="avares://fluenticons.resources.avalonia/Assets#Seagull Fluent Icons" />
|
||||
</ui:FASettingsExpander.IconSource>
|
||||
<ui:FASettingsExpander.Footer>
|
||||
<ToggleSwitch IsChecked="{Binding UploadAnonymousUsageData}" />
|
||||
</ui:SettingsExpander.Footer>
|
||||
</ui:SettingsExpander>
|
||||
</ui:FASettingsExpander.Footer>
|
||||
</ui:FASettingsExpander>
|
||||
|
||||
<Border Background="{DynamicResource CardBackgroundFillColorDefaultBrush}"
|
||||
CornerRadius="8"
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:vm="using:LanMountainDesktop.ViewModels"
|
||||
xmlns:controls="using:LanMountainDesktop.Controls"
|
||||
xmlns:ui="using:FluentAvalonia.UI.Controls"
|
||||
xmlns:fi="using:FluentIcons.Avalonia.Fluent"
|
||||
xmlns:fi="using:FluentIcons.Avalonia"
|
||||
x:Class="LanMountainDesktop.Views.SettingsPages.StatusBarSettingsPage"
|
||||
x:DataType="vm:StatusBarSettingsPageViewModel">
|
||||
<ScrollViewer VerticalScrollBarVisibility="Auto">
|
||||
@@ -12,15 +12,15 @@
|
||||
Text="{Binding ComponentsHeader}"
|
||||
Margin="0,0,0,4" />
|
||||
|
||||
<ui:SettingsExpander Header="{Binding ClockHeader}"
|
||||
<ui:FASettingsExpander Header="{Binding ClockHeader}"
|
||||
Description="{Binding ClockDescription}">
|
||||
<ui:SettingsExpander.IconSource>
|
||||
<fi:SymbolIconSource Symbol="Clock" />
|
||||
</ui:SettingsExpander.IconSource>
|
||||
<ui:SettingsExpander.Footer>
|
||||
<ui:FASettingsExpander.IconSource>
|
||||
<ui:FAFontIconSource Glyph="󰅨" FontFamily="avares://fluenticons.resources.avalonia/Assets#Seagull Fluent Icons" />
|
||||
</ui:FASettingsExpander.IconSource>
|
||||
<ui:FASettingsExpander.Footer>
|
||||
<ToggleSwitch IsChecked="{Binding ShowClock}" />
|
||||
</ui:SettingsExpander.Footer>
|
||||
<ui:SettingsExpanderItem>
|
||||
</ui:FASettingsExpander.Footer>
|
||||
<ui:FASettingsExpanderItem>
|
||||
<Grid ColumnDefinitions="Auto,*"
|
||||
ColumnSpacing="16">
|
||||
<TextBlock Text="{Binding ClockFormatLabel}"
|
||||
@@ -37,8 +37,8 @@
|
||||
</ComboBox.ItemTemplate>
|
||||
</ComboBox>
|
||||
</Grid>
|
||||
</ui:SettingsExpanderItem>
|
||||
<ui:SettingsExpanderItem>
|
||||
</ui:FASettingsExpanderItem>
|
||||
<ui:FASettingsExpanderItem>
|
||||
<Grid ColumnDefinitions="*,Auto"
|
||||
ColumnSpacing="16">
|
||||
<StackPanel Spacing="2">
|
||||
@@ -51,8 +51,8 @@
|
||||
IsChecked="{Binding ClockTransparentBackground}"
|
||||
VerticalAlignment="Center" />
|
||||
</Grid>
|
||||
</ui:SettingsExpanderItem>
|
||||
<ui:SettingsExpanderItem>
|
||||
</ui:FASettingsExpanderItem>
|
||||
<ui:FASettingsExpanderItem>
|
||||
<Grid ColumnDefinitions="Auto,*"
|
||||
ColumnSpacing="16">
|
||||
<TextBlock Text="{Binding ClockPositionLabel}"
|
||||
@@ -69,8 +69,8 @@
|
||||
</ComboBox.ItemTemplate>
|
||||
</ComboBox>
|
||||
</Grid>
|
||||
</ui:SettingsExpanderItem>
|
||||
<ui:SettingsExpanderItem>
|
||||
</ui:FASettingsExpanderItem>
|
||||
<ui:FASettingsExpanderItem>
|
||||
<Grid ColumnDefinitions="Auto,*"
|
||||
ColumnSpacing="16">
|
||||
<TextBlock Text="{Binding ClockFontSizeLabel}"
|
||||
@@ -87,18 +87,18 @@
|
||||
</ComboBox.ItemTemplate>
|
||||
</ComboBox>
|
||||
</Grid>
|
||||
</ui:SettingsExpanderItem>
|
||||
</ui:SettingsExpander>
|
||||
</ui:FASettingsExpanderItem>
|
||||
</ui:FASettingsExpander>
|
||||
|
||||
<ui:SettingsExpander Header="{Binding TextCapsuleHeader}"
|
||||
<ui:FASettingsExpander Header="{Binding TextCapsuleHeader}"
|
||||
Description="{Binding TextCapsuleDescription}">
|
||||
<ui:SettingsExpander.IconSource>
|
||||
<fi:SymbolIconSource Symbol="TextQuote" />
|
||||
</ui:SettingsExpander.IconSource>
|
||||
<ui:SettingsExpander.Footer>
|
||||
<ui:FASettingsExpander.IconSource>
|
||||
<ui:FAFontIconSource Glyph="󰟰" FontFamily="avares://fluenticons.resources.avalonia/Assets#Seagull Fluent Icons" />
|
||||
</ui:FASettingsExpander.IconSource>
|
||||
<ui:FASettingsExpander.Footer>
|
||||
<ToggleSwitch IsChecked="{Binding ShowTextCapsule}" />
|
||||
</ui:SettingsExpander.Footer>
|
||||
<ui:SettingsExpanderItem>
|
||||
</ui:FASettingsExpander.Footer>
|
||||
<ui:FASettingsExpanderItem>
|
||||
<Grid ColumnDefinitions="Auto,*"
|
||||
ColumnSpacing="16">
|
||||
<TextBlock Text="{Binding TextCapsuleContentLabel}"
|
||||
@@ -110,10 +110,10 @@
|
||||
Height="100"
|
||||
IsEnabled="{Binding ShowTextCapsule}"
|
||||
Text="{Binding TextCapsuleContent}"
|
||||
Watermark="Enter Markdown text..." />
|
||||
PlaceholderText="Enter Markdown text..." />
|
||||
</Grid>
|
||||
</ui:SettingsExpanderItem>
|
||||
<ui:SettingsExpanderItem>
|
||||
</ui:FASettingsExpanderItem>
|
||||
<ui:FASettingsExpanderItem>
|
||||
<Grid ColumnDefinitions="Auto,*"
|
||||
ColumnSpacing="16">
|
||||
<TextBlock Text="{Binding TextCapsulePositionLabel}"
|
||||
@@ -130,8 +130,8 @@
|
||||
</ComboBox.ItemTemplate>
|
||||
</ComboBox>
|
||||
</Grid>
|
||||
</ui:SettingsExpanderItem>
|
||||
<ui:SettingsExpanderItem>
|
||||
</ui:FASettingsExpanderItem>
|
||||
<ui:FASettingsExpanderItem>
|
||||
<Grid ColumnDefinitions="*,Auto"
|
||||
ColumnSpacing="16">
|
||||
<TextBlock Text="{Binding TextCapsuleTransparentBackgroundLabel}"
|
||||
@@ -141,18 +141,18 @@
|
||||
IsEnabled="{Binding ShowTextCapsule}"
|
||||
VerticalAlignment="Center" />
|
||||
</Grid>
|
||||
</ui:SettingsExpanderItem>
|
||||
</ui:SettingsExpander>
|
||||
</ui:FASettingsExpanderItem>
|
||||
</ui:FASettingsExpander>
|
||||
|
||||
<ui:SettingsExpander Header="{Binding NetworkSpeedHeader}"
|
||||
<ui:FASettingsExpander Header="{Binding NetworkSpeedHeader}"
|
||||
Description="{Binding NetworkSpeedDescription}">
|
||||
<ui:SettingsExpander.IconSource>
|
||||
<fi:SymbolIconSource Symbol="ArrowBidirectionalUpDown" />
|
||||
</ui:SettingsExpander.IconSource>
|
||||
<ui:SettingsExpander.Footer>
|
||||
<ui:FASettingsExpander.IconSource>
|
||||
<ui:FAFontIconSource Glyph="󰆠" FontFamily="avares://fluenticons.resources.avalonia/Assets#Seagull Fluent Icons" />
|
||||
</ui:FASettingsExpander.IconSource>
|
||||
<ui:FASettingsExpander.Footer>
|
||||
<ToggleSwitch IsChecked="{Binding ShowNetworkSpeed}" />
|
||||
</ui:SettingsExpander.Footer>
|
||||
<ui:SettingsExpanderItem>
|
||||
</ui:FASettingsExpander.Footer>
|
||||
<ui:FASettingsExpanderItem>
|
||||
<Grid ColumnDefinitions="Auto,*"
|
||||
ColumnSpacing="16">
|
||||
<TextBlock Text="{Binding NetworkSpeedPositionLabel}"
|
||||
@@ -169,8 +169,8 @@
|
||||
</ComboBox.ItemTemplate>
|
||||
</ComboBox>
|
||||
</Grid>
|
||||
</ui:SettingsExpanderItem>
|
||||
<ui:SettingsExpanderItem>
|
||||
</ui:FASettingsExpanderItem>
|
||||
<ui:FASettingsExpanderItem>
|
||||
<Grid ColumnDefinitions="Auto,*"
|
||||
ColumnSpacing="16">
|
||||
<TextBlock Text="{Binding NetworkSpeedDisplayModeLabel}"
|
||||
@@ -187,8 +187,8 @@
|
||||
</ComboBox.ItemTemplate>
|
||||
</ComboBox>
|
||||
</Grid>
|
||||
</ui:SettingsExpanderItem>
|
||||
<ui:SettingsExpanderItem>
|
||||
</ui:FASettingsExpanderItem>
|
||||
<ui:FASettingsExpanderItem>
|
||||
<Grid ColumnDefinitions="*,Auto"
|
||||
ColumnSpacing="16">
|
||||
<TextBlock Text="{Binding NetworkSpeedTransparentBackgroundLabel}"
|
||||
@@ -198,8 +198,8 @@
|
||||
IsEnabled="{Binding ShowNetworkSpeed}"
|
||||
VerticalAlignment="Center" />
|
||||
</Grid>
|
||||
</ui:SettingsExpanderItem>
|
||||
<ui:SettingsExpanderItem>
|
||||
</ui:FASettingsExpanderItem>
|
||||
<ui:FASettingsExpanderItem>
|
||||
<Grid ColumnDefinitions="*,Auto"
|
||||
ColumnSpacing="16">
|
||||
<TextBlock Text="{Binding ShowNetworkTypeIconLabel}"
|
||||
@@ -209,8 +209,8 @@
|
||||
IsEnabled="{Binding ShowNetworkSpeed}"
|
||||
VerticalAlignment="Center" />
|
||||
</Grid>
|
||||
</ui:SettingsExpanderItem>
|
||||
<ui:SettingsExpanderItem>
|
||||
</ui:FASettingsExpanderItem>
|
||||
<ui:FASettingsExpanderItem>
|
||||
<Grid ColumnDefinitions="Auto,*"
|
||||
ColumnSpacing="16">
|
||||
<TextBlock Text="{Binding NetworkSpeedFontSizeLabel}"
|
||||
@@ -227,8 +227,8 @@
|
||||
</ComboBox.ItemTemplate>
|
||||
</ComboBox>
|
||||
</Grid>
|
||||
</ui:SettingsExpanderItem>
|
||||
</ui:SettingsExpander>
|
||||
</ui:FASettingsExpanderItem>
|
||||
</ui:FASettingsExpander>
|
||||
|
||||
<Separator Classes="settings-separator" />
|
||||
|
||||
@@ -236,12 +236,12 @@
|
||||
Text="{Binding SpacingHeader}"
|
||||
Margin="0,0,0,4" />
|
||||
|
||||
<ui:SettingsExpander Header="{Binding SpacingHeader}"
|
||||
<ui:FASettingsExpander Header="{Binding SpacingHeader}"
|
||||
Description="{Binding SpacingDescription}">
|
||||
<ui:SettingsExpander.IconSource>
|
||||
<fi:SymbolIconSource Symbol="Apps" />
|
||||
</ui:SettingsExpander.IconSource>
|
||||
<ui:SettingsExpander.Footer>
|
||||
<ui:FASettingsExpander.IconSource>
|
||||
<ui:FAFontIconSource Glyph="󰋘" FontFamily="avares://fluenticons.resources.avalonia/Assets#Seagull Fluent Icons" />
|
||||
</ui:FASettingsExpander.IconSource>
|
||||
<ui:FASettingsExpander.Footer>
|
||||
<ComboBox Width="180"
|
||||
ItemsSource="{Binding SpacingModes}"
|
||||
SelectedItem="{Binding SelectedSpacingMode}">
|
||||
@@ -251,13 +251,13 @@
|
||||
</DataTemplate>
|
||||
</ComboBox.ItemTemplate>
|
||||
</ComboBox>
|
||||
</ui:SettingsExpander.Footer>
|
||||
<ui:SettingsExpanderItem IsVisible="{Binding IsCustomSpacingVisible}">
|
||||
</ui:FASettingsExpander.Footer>
|
||||
<ui:FASettingsExpanderItem IsVisible="{Binding IsCustomSpacingVisible}">
|
||||
<Grid ColumnDefinitions="Auto,*"
|
||||
ColumnSpacing="16">
|
||||
<TextBlock Text="{Binding CustomSpacingLabel}"
|
||||
VerticalAlignment="Center" />
|
||||
<ui:NumberBox Grid.Column="1"
|
||||
<ui:FANumberBox Grid.Column="1"
|
||||
Width="160"
|
||||
Minimum="0"
|
||||
Maximum="30"
|
||||
@@ -266,8 +266,8 @@
|
||||
SpinButtonPlacementMode="Inline"
|
||||
Value="{Binding CustomSpacingPercent}" />
|
||||
</Grid>
|
||||
</ui:SettingsExpanderItem>
|
||||
</ui:SettingsExpander>
|
||||
</ui:FASettingsExpanderItem>
|
||||
</ui:FASettingsExpander>
|
||||
|
||||
<Separator Classes="settings-separator" />
|
||||
|
||||
@@ -275,15 +275,15 @@
|
||||
Text="{Binding StatusBarShadowHeader}"
|
||||
Margin="0,0,0,4" />
|
||||
|
||||
<ui:SettingsExpander Header="{Binding StatusBarShadowHeader}"
|
||||
<ui:FASettingsExpander Header="{Binding StatusBarShadowHeader}"
|
||||
Description="{Binding StatusBarShadowDescription}">
|
||||
<ui:SettingsExpander.IconSource>
|
||||
<fi:SymbolIconSource Symbol="Square" />
|
||||
</ui:SettingsExpander.IconSource>
|
||||
<ui:SettingsExpander.Footer>
|
||||
<ui:FASettingsExpander.IconSource>
|
||||
<ui:FAFontIconSource Glyph="󱩈" FontFamily="avares://fluenticons.resources.avalonia/Assets#Seagull Fluent Icons" />
|
||||
</ui:FASettingsExpander.IconSource>
|
||||
<ui:FASettingsExpander.Footer>
|
||||
<ToggleSwitch IsChecked="{Binding StatusBarShadowEnabled}" />
|
||||
</ui:SettingsExpander.Footer>
|
||||
<ui:SettingsExpanderItem>
|
||||
</ui:FASettingsExpander.Footer>
|
||||
<ui:FASettingsExpanderItem>
|
||||
<Grid ColumnDefinitions="Auto,*"
|
||||
ColumnSpacing="16">
|
||||
<TextBlock Text="{Binding StatusBarShadowColorLabel}"
|
||||
@@ -302,8 +302,8 @@
|
||||
</Button.Flyout>
|
||||
</Button>
|
||||
</Grid>
|
||||
</ui:SettingsExpanderItem>
|
||||
<ui:SettingsExpanderItem>
|
||||
</ui:FASettingsExpanderItem>
|
||||
<ui:FASettingsExpanderItem>
|
||||
<Grid ColumnDefinitions="Auto,*"
|
||||
ColumnSpacing="16">
|
||||
<TextBlock Text="{Binding StatusBarShadowOpacityLabel}"
|
||||
@@ -315,8 +315,8 @@
|
||||
IsEnabled="{Binding StatusBarShadowEnabled}"
|
||||
Value="{Binding StatusBarShadowOpacity}" />
|
||||
</Grid>
|
||||
</ui:SettingsExpanderItem>
|
||||
</ui:SettingsExpander>
|
||||
</ui:FASettingsExpanderItem>
|
||||
</ui:FASettingsExpander>
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
</UserControl>
|
||||
|
||||
@@ -1,36 +1,36 @@
|
||||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:vm="using:LanMountainDesktop.ViewModels"
|
||||
xmlns:ui="using:FluentAvalonia.UI.Controls"
|
||||
xmlns:fi="using:FluentIcons.Avalonia.Fluent"
|
||||
xmlns:fi="using:FluentIcons.Avalonia"
|
||||
x:Class="LanMountainDesktop.Views.SettingsPages.StudySettingsPage"
|
||||
x:DataType="vm:StudySettingsPageViewModel">
|
||||
<ScrollViewer VerticalScrollBarVisibility="Auto">
|
||||
<StackPanel Classes="settings-page-container settings-page-animated">
|
||||
|
||||
<!-- 总开关 -->
|
||||
<ui:SettingsExpander Classes="settings-expander-card"
|
||||
<!-- 閹绱戦崗?-->
|
||||
<ui:FASettingsExpander Classes="settings-expander-card"
|
||||
Header="{Binding MasterSwitchHeader}"
|
||||
Description="{Binding MasterSwitchDescription}">
|
||||
<ui:SettingsExpander.IconSource>
|
||||
<fi:SymbolIconSource Symbol="DataHistogram" />
|
||||
</ui:SettingsExpander.IconSource>
|
||||
<ui:SettingsExpander.Footer>
|
||||
<ui:FASettingsExpander.IconSource>
|
||||
<ui:FAFontIconSource Glyph="󲀔" FontFamily="avares://fluenticons.resources.avalonia/Assets#Seagull Fluent Icons" />
|
||||
</ui:FASettingsExpander.IconSource>
|
||||
<ui:FASettingsExpander.Footer>
|
||||
<ToggleSwitch IsChecked="{Binding StudyEnabled}" />
|
||||
</ui:SettingsExpander.Footer>
|
||||
</ui:SettingsExpander>
|
||||
</ui:FASettingsExpander.Footer>
|
||||
</ui:FASettingsExpander>
|
||||
|
||||
<!-- 噪音监测设置 -->
|
||||
<ui:SettingsExpander Classes="settings-expander-card"
|
||||
<!-- 閸n亪鐓堕惄鎴炵ゴ鐠佸墽鐤?-->
|
||||
<ui:FASettingsExpander Classes="settings-expander-card"
|
||||
Header="{Binding NoiseMonitoringHeader}"
|
||||
Description="{Binding NoiseMonitoringDescription}"
|
||||
IsEnabled="{Binding StudyEnabled}">
|
||||
<ui:SettingsExpander.IconSource>
|
||||
<fi:SymbolIconSource Symbol="Mic" />
|
||||
</ui:SettingsExpander.IconSource>
|
||||
<ui:FASettingsExpander.IconSource>
|
||||
<ui:FAFontIconSource Glyph="󰀘" FontFamily="avares://fluenticons.resources.avalonia/Assets#Seagull Fluent Icons" />
|
||||
</ui:FASettingsExpander.IconSource>
|
||||
|
||||
<!-- 采集频率 -->
|
||||
<ui:SettingsExpanderItem>
|
||||
<!-- 闁插洭娉︽0鎴犲芳 -->
|
||||
<ui:FASettingsExpanderItem>
|
||||
<StackPanel Spacing="8">
|
||||
<Grid ColumnDefinitions="*,Auto" ColumnSpacing="16">
|
||||
<StackPanel Classes="settings-item">
|
||||
@@ -52,10 +52,10 @@
|
||||
TickFrequency="20"
|
||||
IsSnapToTickEnabled="True" />
|
||||
</StackPanel>
|
||||
</ui:SettingsExpanderItem>
|
||||
</ui:FASettingsExpanderItem>
|
||||
|
||||
<!-- 噪音敏感度 -->
|
||||
<ui:SettingsExpanderItem>
|
||||
<!-- 閸n亪鐓堕弫蹇斿妳鎼?-->
|
||||
<ui:FASettingsExpanderItem>
|
||||
<StackPanel Spacing="8">
|
||||
<Grid ColumnDefinitions="*,Auto" ColumnSpacing="16">
|
||||
<StackPanel Classes="settings-item">
|
||||
@@ -77,27 +77,27 @@
|
||||
TickFrequency="5"
|
||||
IsSnapToTickEnabled="True" />
|
||||
</StackPanel>
|
||||
</ui:SettingsExpanderItem>
|
||||
</ui:FASettingsExpanderItem>
|
||||
|
||||
<!-- 评分阈值显示 -->
|
||||
<ui:SettingsExpanderItem>
|
||||
<!-- 鐠囧嫬鍨庨梼鍫濃偓鍏兼▔缁€?-->
|
||||
<ui:FASettingsExpanderItem>
|
||||
<TextBlock Classes="settings-item-description"
|
||||
Text="{Binding CurrentThresholdText}"
|
||||
TextWrapping="Wrap" />
|
||||
</ui:SettingsExpanderItem>
|
||||
</ui:SettingsExpander>
|
||||
</ui:FASettingsExpanderItem>
|
||||
</ui:FASettingsExpander>
|
||||
|
||||
<!-- 专注计时设置 -->
|
||||
<ui:SettingsExpander Classes="settings-expander-card"
|
||||
<!-- 娑撴挻鏁炵拋鈩冩鐠佸墽鐤?-->
|
||||
<ui:FASettingsExpander Classes="settings-expander-card"
|
||||
Header="{Binding FocusTimerHeader}"
|
||||
Description="{Binding FocusTimerDescription}"
|
||||
IsEnabled="{Binding StudyEnabled}">
|
||||
<ui:SettingsExpander.IconSource>
|
||||
<fi:SymbolIconSource Symbol="Timer" />
|
||||
</ui:SettingsExpander.IconSource>
|
||||
<ui:FASettingsExpander.IconSource>
|
||||
<ui:FAFontIconSource Glyph="󰙬" FontFamily="avares://fluenticons.resources.avalonia/Assets#Seagull Fluent Icons" />
|
||||
</ui:FASettingsExpander.IconSource>
|
||||
|
||||
<!-- 专注时长 -->
|
||||
<ui:SettingsExpanderItem>
|
||||
<!-- 娑撴挻鏁為弮鍫曟毐 -->
|
||||
<ui:FASettingsExpanderItem>
|
||||
<StackPanel Spacing="8">
|
||||
<Grid ColumnDefinitions="*,Auto" ColumnSpacing="16">
|
||||
<StackPanel Classes="settings-item">
|
||||
@@ -119,10 +119,10 @@
|
||||
TickFrequency="5"
|
||||
IsSnapToTickEnabled="True" />
|
||||
</StackPanel>
|
||||
</ui:SettingsExpanderItem>
|
||||
</ui:FASettingsExpanderItem>
|
||||
|
||||
<!-- 休息时长 -->
|
||||
<ui:SettingsExpanderItem>
|
||||
<!-- 娴兼垶浼呴弮鍫曟毐 -->
|
||||
<ui:FASettingsExpanderItem>
|
||||
<StackPanel Spacing="8">
|
||||
<Grid ColumnDefinitions="*,Auto" ColumnSpacing="16">
|
||||
<StackPanel Classes="settings-item">
|
||||
@@ -144,10 +144,10 @@
|
||||
TickFrequency="5"
|
||||
IsSnapToTickEnabled="True" />
|
||||
</StackPanel>
|
||||
</ui:SettingsExpanderItem>
|
||||
</ui:FASettingsExpanderItem>
|
||||
|
||||
<!-- 长休息时长 -->
|
||||
<ui:SettingsExpanderItem>
|
||||
<!-- 闂€澶哥搐閹垱妞傞梹?-->
|
||||
<ui:FASettingsExpanderItem>
|
||||
<StackPanel Spacing="8">
|
||||
<Grid ColumnDefinitions="*,Auto" ColumnSpacing="16">
|
||||
<StackPanel Classes="settings-item">
|
||||
@@ -169,10 +169,10 @@
|
||||
TickFrequency="5"
|
||||
IsSnapToTickEnabled="True" />
|
||||
</StackPanel>
|
||||
</ui:SettingsExpanderItem>
|
||||
</ui:FASettingsExpanderItem>
|
||||
|
||||
<!-- 长休息间隔 -->
|
||||
<ui:SettingsExpanderItem>
|
||||
<!-- 闂€澶哥搐閹垶妫块梾?-->
|
||||
<ui:FASettingsExpanderItem>
|
||||
<StackPanel Spacing="8">
|
||||
<Grid ColumnDefinitions="*,Auto" ColumnSpacing="16">
|
||||
<StackPanel Classes="settings-item">
|
||||
@@ -194,10 +194,10 @@
|
||||
TickFrequency="1"
|
||||
IsSnapToTickEnabled="True" />
|
||||
</StackPanel>
|
||||
</ui:SettingsExpanderItem>
|
||||
</ui:FASettingsExpanderItem>
|
||||
|
||||
<!-- 自动开始休息 -->
|
||||
<ui:SettingsExpanderItem>
|
||||
<!-- 閼奉亜濮╁鈧慨瀣╃搐閹?-->
|
||||
<ui:FASettingsExpanderItem>
|
||||
<Grid ColumnDefinitions="*,Auto" ColumnSpacing="16">
|
||||
<StackPanel Classes="settings-item">
|
||||
<TextBlock Classes="settings-item-label"
|
||||
@@ -208,10 +208,10 @@
|
||||
<ToggleSwitch Grid.Column="1"
|
||||
IsChecked="{Binding AutoStartBreak}" />
|
||||
</Grid>
|
||||
</ui:SettingsExpanderItem>
|
||||
</ui:FASettingsExpanderItem>
|
||||
|
||||
<!-- 自动开始专注 -->
|
||||
<ui:SettingsExpanderItem>
|
||||
<!-- 閼奉亜濮╁鈧慨瀣╃瑩濞?-->
|
||||
<ui:FASettingsExpanderItem>
|
||||
<Grid ColumnDefinitions="*,Auto" ColumnSpacing="16">
|
||||
<StackPanel Classes="settings-item">
|
||||
<TextBlock Classes="settings-item-label"
|
||||
@@ -222,20 +222,20 @@
|
||||
<ToggleSwitch Grid.Column="1"
|
||||
IsChecked="{Binding AutoStartFocus}" />
|
||||
</Grid>
|
||||
</ui:SettingsExpanderItem>
|
||||
</ui:SettingsExpander>
|
||||
</ui:FASettingsExpanderItem>
|
||||
</ui:FASettingsExpander>
|
||||
|
||||
<!-- 提醒设置 -->
|
||||
<ui:SettingsExpander Classes="settings-expander-card"
|
||||
<!-- 閹绘劙鍟嬬拋鍓х枂 -->
|
||||
<ui:FASettingsExpander Classes="settings-expander-card"
|
||||
Header="{Binding AlertHeader}"
|
||||
Description="{Binding AlertDescription}"
|
||||
IsEnabled="{Binding StudyEnabled}">
|
||||
<ui:SettingsExpander.IconSource>
|
||||
<fi:SymbolIconSource Symbol="Alert" />
|
||||
</ui:SettingsExpander.IconSource>
|
||||
<ui:FASettingsExpander.IconSource>
|
||||
<ui:FAFontIconSource Glyph="󰀐" FontFamily="avares://fluenticons.resources.avalonia/Assets#Seagull Fluent Icons" />
|
||||
</ui:FASettingsExpander.IconSource>
|
||||
|
||||
<!-- 噪音打断提醒 -->
|
||||
<ui:SettingsExpanderItem>
|
||||
<!-- 閸n亪鐓堕幍鎾存焽閹绘劙鍟?-->
|
||||
<ui:FASettingsExpanderItem>
|
||||
<Grid ColumnDefinitions="*,Auto" ColumnSpacing="16">
|
||||
<StackPanel Classes="settings-item">
|
||||
<TextBlock Classes="settings-item-label"
|
||||
@@ -246,10 +246,10 @@
|
||||
<ToggleSwitch Grid.Column="1"
|
||||
IsChecked="{Binding NoiseAlertEnabled}" />
|
||||
</Grid>
|
||||
</ui:SettingsExpanderItem>
|
||||
</ui:FASettingsExpanderItem>
|
||||
|
||||
<!-- 每分钟最大容忍打断次数 -->
|
||||
<ui:SettingsExpanderItem IsVisible="{Binding NoiseAlertEnabled}">
|
||||
<!-- 濮e繐鍨庨柦鐔告付婢堆冾啇韫囧秵澧﹂弬顓燁偧閺?-->
|
||||
<ui:FASettingsExpanderItem IsVisible="{Binding NoiseAlertEnabled}">
|
||||
<Grid ColumnDefinitions="*,Auto" ColumnSpacing="16">
|
||||
<StackPanel Classes="settings-item">
|
||||
<TextBlock Classes="settings-item-label"
|
||||
@@ -264,20 +264,20 @@
|
||||
Increment="1"
|
||||
Value="{Binding MaxInterruptsPerMinute}" />
|
||||
</Grid>
|
||||
</ui:SettingsExpanderItem>
|
||||
</ui:SettingsExpander>
|
||||
</ui:FASettingsExpanderItem>
|
||||
</ui:FASettingsExpander>
|
||||
|
||||
<!-- 显示设置 -->
|
||||
<ui:SettingsExpander Classes="settings-expander-card"
|
||||
<!-- 閺勫墽銇氱拋鍓х枂 -->
|
||||
<ui:FASettingsExpander Classes="settings-expander-card"
|
||||
Header="{Binding DisplayHeader}"
|
||||
Description="{Binding DisplayDescription}"
|
||||
IsEnabled="{Binding StudyEnabled}">
|
||||
<ui:SettingsExpander.IconSource>
|
||||
<fi:SymbolIconSource Symbol="Eye" />
|
||||
</ui:SettingsExpander.IconSource>
|
||||
<ui:FASettingsExpander.IconSource>
|
||||
<ui:FAFontIconSource Glyph="󰤈" FontFamily="avares://fluenticons.resources.avalonia/Assets#Seagull Fluent Icons" />
|
||||
</ui:FASettingsExpander.IconSource>
|
||||
|
||||
<!-- 显示实时分贝 -->
|
||||
<ui:SettingsExpanderItem>
|
||||
<!-- 閺勫墽銇氱€圭偞妞傞崚鍡氱 -->
|
||||
<ui:FASettingsExpanderItem>
|
||||
<Grid ColumnDefinitions="*,Auto" ColumnSpacing="16">
|
||||
<StackPanel Classes="settings-item">
|
||||
<TextBlock Classes="settings-item-label"
|
||||
@@ -288,10 +288,10 @@
|
||||
<ToggleSwitch Grid.Column="1"
|
||||
IsChecked="{Binding ShowRealtimeDb}" />
|
||||
</Grid>
|
||||
</ui:SettingsExpanderItem>
|
||||
</ui:FASettingsExpanderItem>
|
||||
|
||||
<!-- 基准显示分贝 -->
|
||||
<ui:SettingsExpanderItem>
|
||||
<!-- 閸╁搫鍣弰鍓с仛閸掑棜绀?-->
|
||||
<ui:FASettingsExpanderItem>
|
||||
<StackPanel Spacing="8">
|
||||
<Grid ColumnDefinitions="*,Auto" ColumnSpacing="16">
|
||||
<StackPanel Classes="settings-item">
|
||||
@@ -313,10 +313,10 @@
|
||||
TickFrequency="5"
|
||||
IsSnapToTickEnabled="True" />
|
||||
</StackPanel>
|
||||
</ui:SettingsExpanderItem>
|
||||
</ui:FASettingsExpanderItem>
|
||||
|
||||
<!-- 平均时间窗 -->
|
||||
<ui:SettingsExpanderItem>
|
||||
<!-- 楠炲啿娼庨弮鍫曟?缁?-->
|
||||
<ui:FASettingsExpanderItem>
|
||||
<StackPanel Spacing="8">
|
||||
<Grid ColumnDefinitions="*,Auto" ColumnSpacing="16">
|
||||
<StackPanel Classes="settings-item">
|
||||
@@ -338,8 +338,8 @@
|
||||
TickFrequency="1"
|
||||
IsSnapToTickEnabled="True" />
|
||||
</StackPanel>
|
||||
</ui:SettingsExpanderItem>
|
||||
</ui:SettingsExpander>
|
||||
</ui:FASettingsExpanderItem>
|
||||
</ui:FASettingsExpander>
|
||||
|
||||
<TextBlock Classes="settings-item-description"
|
||||
Margin="0,8,0,0"
|
||||
@@ -347,4 +347,4 @@
|
||||
TextWrapping="Wrap" />
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
</UserControl>
|
||||
</UserControl>
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:vm="using:LanMountainDesktop.ViewModels"
|
||||
xmlns:controls="using:LanMountainDesktop.Controls"
|
||||
xmlns:ui="using:FluentAvalonia.UI.Controls"
|
||||
xmlns:fi="using:FluentIcons.Avalonia.Fluent"
|
||||
xmlns:fi="using:FluentIcons.Avalonia"
|
||||
x:Class="LanMountainDesktop.Views.SettingsPages.UpdateSettingsPage"
|
||||
x:DataType="vm:UpdateSettingsPageViewModel">
|
||||
<UserControl.Styles>
|
||||
@@ -163,13 +163,13 @@
|
||||
Margin="0,0,0,18"
|
||||
Text="{Binding PreferencesDescription}" />
|
||||
|
||||
<ui:SettingsExpander Classes="settings-expander-card"
|
||||
<ui:FASettingsExpander Classes="settings-expander-card"
|
||||
Header="{Binding UpdateChannelLabel}"
|
||||
Description="{Binding SelectedUpdateChannelDescription}">
|
||||
<ui:SettingsExpander.IconSource>
|
||||
<fi:SymbolIconSource Symbol="BranchFork" />
|
||||
</ui:SettingsExpander.IconSource>
|
||||
<ui:SettingsExpander.Footer>
|
||||
<ui:FASettingsExpander.IconSource>
|
||||
<ui:FAFontIconSource Glyph="󰛈" FontFamily="avares://fluenticons.resources.avalonia/Assets#Seagull Fluent Icons" />
|
||||
</ui:FASettingsExpander.IconSource>
|
||||
<ui:FASettingsExpander.Footer>
|
||||
<ComboBox Width="220"
|
||||
ItemsSource="{Binding UpdateChannelOptions}"
|
||||
SelectedItem="{Binding SelectedUpdateChannelOption}">
|
||||
@@ -179,24 +179,24 @@
|
||||
</DataTemplate>
|
||||
</ComboBox.ItemTemplate>
|
||||
</ComboBox>
|
||||
</ui:SettingsExpander.Footer>
|
||||
<ui:SettingsExpanderItem Content="{Binding ForceCheckUpdateLabel}"
|
||||
</ui:FASettingsExpander.Footer>
|
||||
<ui:FASettingsExpanderItem Content="{Binding ForceCheckUpdateLabel}"
|
||||
Description="{Binding ForceCheckUpdateDescription}"
|
||||
IsClickEnabled="True"
|
||||
Command="{Binding ForceCheckUpdateCommand}">
|
||||
<ui:SettingsExpanderItem.IconSource>
|
||||
<fi:SymbolIconSource Symbol="ArrowSync" />
|
||||
</ui:SettingsExpanderItem.IconSource>
|
||||
</ui:SettingsExpanderItem>
|
||||
</ui:SettingsExpander>
|
||||
<ui:FASettingsExpanderItem.IconSource>
|
||||
<ui:FAFontIconSource Glyph="󰿔" FontFamily="avares://fluenticons.resources.avalonia/Assets#Seagull Fluent Icons" />
|
||||
</ui:FASettingsExpanderItem.IconSource>
|
||||
</ui:FASettingsExpanderItem>
|
||||
</ui:FASettingsExpander>
|
||||
|
||||
<ui:SettingsExpander Classes="settings-expander-card"
|
||||
<ui:FASettingsExpander Classes="settings-expander-card"
|
||||
Header="{Binding UpdateSourceLabel}"
|
||||
Description="{Binding SelectedUpdateSourceDescription}">
|
||||
<ui:SettingsExpander.IconSource>
|
||||
<fi:SymbolIconSource Symbol="GlobeArrowForward" />
|
||||
</ui:SettingsExpander.IconSource>
|
||||
<ui:SettingsExpander.Footer>
|
||||
<ui:FASettingsExpander.IconSource>
|
||||
<ui:FAFontIconSource Glyph="󱠬" FontFamily="avares://fluenticons.resources.avalonia/Assets#Seagull Fluent Icons" />
|
||||
</ui:FASettingsExpander.IconSource>
|
||||
<ui:FASettingsExpander.Footer>
|
||||
<ComboBox Width="220"
|
||||
ItemsSource="{Binding UpdateSourceOptions}"
|
||||
SelectedItem="{Binding SelectedUpdateSourceOption}">
|
||||
@@ -206,16 +206,16 @@
|
||||
</DataTemplate>
|
||||
</ComboBox.ItemTemplate>
|
||||
</ComboBox>
|
||||
</ui:SettingsExpander.Footer>
|
||||
</ui:SettingsExpander>
|
||||
</ui:FASettingsExpander.Footer>
|
||||
</ui:FASettingsExpander>
|
||||
|
||||
<ui:SettingsExpander Classes="settings-expander-card"
|
||||
<ui:FASettingsExpander Classes="settings-expander-card"
|
||||
Header="{Binding UpdateModeLabel}"
|
||||
Description="{Binding SelectedUpdateModeDescription}">
|
||||
<ui:SettingsExpander.IconSource>
|
||||
<fi:SymbolIconSource Symbol="Options" />
|
||||
</ui:SettingsExpander.IconSource>
|
||||
<ui:SettingsExpander.Footer>
|
||||
<ui:FASettingsExpander.IconSource>
|
||||
<ui:FAFontIconSource Glyph="󰛼" FontFamily="avares://fluenticons.resources.avalonia/Assets#Seagull Fluent Icons" />
|
||||
</ui:FASettingsExpander.IconSource>
|
||||
<ui:FASettingsExpander.Footer>
|
||||
<ComboBox Width="260"
|
||||
ItemsSource="{Binding UpdateModeOptions}"
|
||||
SelectedItem="{Binding SelectedUpdateModeOption}">
|
||||
@@ -225,23 +225,23 @@
|
||||
</DataTemplate>
|
||||
</ComboBox.ItemTemplate>
|
||||
</ComboBox>
|
||||
</ui:SettingsExpander.Footer>
|
||||
</ui:SettingsExpander>
|
||||
</ui:FASettingsExpander.Footer>
|
||||
</ui:FASettingsExpander>
|
||||
|
||||
<ui:SettingsExpander Classes="settings-expander-card"
|
||||
<ui:FASettingsExpander Classes="settings-expander-card"
|
||||
Header="{Binding DownloadThreadsLabel}"
|
||||
Description="{Binding DownloadThreadsDescription}">
|
||||
<ui:SettingsExpander.IconSource>
|
||||
<fi:SymbolIconSource Symbol="ArrowDownload" />
|
||||
</ui:SettingsExpander.IconSource>
|
||||
<ui:SettingsExpander.Footer>
|
||||
<ui:NumberBox Width="160"
|
||||
<ui:FASettingsExpander.IconSource>
|
||||
<ui:FAFontIconSource Glyph="󰛀" FontFamily="avares://fluenticons.resources.avalonia/Assets#Seagull Fluent Icons" />
|
||||
</ui:FASettingsExpander.IconSource>
|
||||
<ui:FASettingsExpander.Footer>
|
||||
<ui:FANumberBox Width="160"
|
||||
Minimum="1"
|
||||
Maximum="128"
|
||||
SpinButtonPlacementMode="Inline"
|
||||
Value="{Binding DownloadThreadsSliderValue}" />
|
||||
</ui:SettingsExpander.Footer>
|
||||
</ui:SettingsExpander>
|
||||
</ui:FASettingsExpander.Footer>
|
||||
</ui:FASettingsExpander>
|
||||
|
||||
|
||||
</StackPanel>
|
||||
|
||||
@@ -1,35 +1,36 @@
|
||||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:vm="using:LanMountainDesktop.ViewModels"
|
||||
xmlns:controls="using:LanMountainDesktop.Controls"
|
||||
xmlns:ui="using:FluentAvalonia.UI.Controls"
|
||||
xmlns:fi="using:FluentIcons.Avalonia.Fluent"
|
||||
xmlns:fi="using:FluentIcons.Avalonia"
|
||||
x:Class="LanMountainDesktop.Views.SettingsPages.WallpaperSettingsPage"
|
||||
x:DataType="vm:WallpaperSettingsPageViewModel">
|
||||
<ScrollViewer VerticalScrollBarVisibility="Auto">
|
||||
<StackPanel Classes="settings-page-container settings-page-animated">
|
||||
|
||||
<!-- 预览与颜色选择区域 -->
|
||||
<Grid ColumnDefinitions="*,*" ColumnSpacing="32" Margin="0,0,0,32">
|
||||
<!-- 左侧:模拟屏幕预览 (占一半宽度) -->
|
||||
<Border Grid.Column="0" VerticalAlignment="Top">
|
||||
<Grid ColumnDefinitions="*,*"
|
||||
ColumnSpacing="32"
|
||||
Margin="0,0,0,32">
|
||||
<Border Grid.Column="0"
|
||||
VerticalAlignment="Top">
|
||||
<Viewbox Stretch="Uniform">
|
||||
<Border Width="1600" Height="900"
|
||||
Background="#080808"
|
||||
BorderBrush="#1A1A1A"
|
||||
BorderThickness="24"
|
||||
<Border Width="1600"
|
||||
Height="900"
|
||||
Background="#080808"
|
||||
BorderBrush="#1A1A1A"
|
||||
BorderThickness="24"
|
||||
CornerRadius="48"
|
||||
BoxShadow="0 12 32 #50000000">
|
||||
<Panel Background="{DynamicResource AdaptiveSurfaceBaseBrush}" Margin="2">
|
||||
<!-- 图片预览 -->
|
||||
<Panel Background="{DynamicResource AdaptiveSurfaceBaseBrush}"
|
||||
Margin="2">
|
||||
<Border Background="#FFF6F7F9"
|
||||
IsVisible="{Binding IsImage}">
|
||||
<Border Background="{Binding PreviewBrush}" />
|
||||
</Border>
|
||||
<!-- 纯色预览 -->
|
||||
<Border Background="{Binding SelectedColor}"
|
||||
|
||||
<Border Background="{Binding SelectedColor}"
|
||||
IsVisible="{Binding IsSolidColor}" />
|
||||
<!-- 系统壁纸预览 -->
|
||||
|
||||
<Border Background="#FFF6F7F9"
|
||||
IsVisible="{Binding IsSystemWallpaper}">
|
||||
<Border Background="{Binding PreviewBrush}" />
|
||||
@@ -39,100 +40,139 @@
|
||||
</Viewbox>
|
||||
</Border>
|
||||
|
||||
<!-- 右侧:颜色选择网格 -->
|
||||
<StackPanel Grid.Column="1" VerticalAlignment="Center" Spacing="12" IsVisible="{Binding IsSolidColor}">
|
||||
<StackPanel Grid.Column="1"
|
||||
VerticalAlignment="Center"
|
||||
Spacing="12"
|
||||
IsVisible="{Binding IsSolidColor}">
|
||||
<TextBlock Text="{Binding WallpaperColorLabel}"
|
||||
FontSize="14"
|
||||
FontWeight="SemiBold"
|
||||
Opacity="0.8" />
|
||||
<UniformGrid Columns="4" Rows="3">
|
||||
<!-- 预设颜色 1-11 -->
|
||||
<Button Width="48" Height="48" Margin="4" Padding="0"
|
||||
<UniformGrid Columns="4"
|
||||
Rows="3">
|
||||
<Button Width="48"
|
||||
Height="48"
|
||||
Margin="4"
|
||||
Padding="0"
|
||||
Background="#D8A7B1"
|
||||
BorderThickness="0"
|
||||
CornerRadius="6"
|
||||
Command="{Binding SelectColorCommand}"
|
||||
CommandParameter="#D8A7B1"
|
||||
ToolTip.Tip="#D8A7B1" />
|
||||
<Button Width="48" Height="48" Margin="4" Padding="0"
|
||||
<Button Width="48"
|
||||
Height="48"
|
||||
Margin="4"
|
||||
Padding="0"
|
||||
Background="#B6C9BB"
|
||||
BorderThickness="0"
|
||||
CornerRadius="6"
|
||||
Command="{Binding SelectColorCommand}"
|
||||
CommandParameter="#B6C9BB"
|
||||
ToolTip.Tip="#B6C9BB" />
|
||||
<Button Width="48" Height="48" Margin="4" Padding="0"
|
||||
<Button Width="48"
|
||||
Height="48"
|
||||
Margin="4"
|
||||
Padding="0"
|
||||
Background="#A2B5BB"
|
||||
BorderThickness="0"
|
||||
CornerRadius="6"
|
||||
Command="{Binding SelectColorCommand}"
|
||||
CommandParameter="#A2B5BB"
|
||||
ToolTip.Tip="#A2B5BB" />
|
||||
<Button Width="48" Height="48" Margin="4" Padding="0"
|
||||
<Button Width="48"
|
||||
Height="48"
|
||||
Margin="4"
|
||||
Padding="0"
|
||||
Background="#E6E2D3"
|
||||
BorderThickness="0"
|
||||
CornerRadius="6"
|
||||
Command="{Binding SelectColorCommand}"
|
||||
CommandParameter="#E6E2D3"
|
||||
ToolTip.Tip="#E6E2D3" />
|
||||
<Button Width="48" Height="48" Margin="4" Padding="0"
|
||||
<Button Width="48"
|
||||
Height="48"
|
||||
Margin="4"
|
||||
Padding="0"
|
||||
Background="#B5A397"
|
||||
BorderThickness="0"
|
||||
CornerRadius="6"
|
||||
Command="{Binding SelectColorCommand}"
|
||||
CommandParameter="#B5A397"
|
||||
ToolTip.Tip="#B5A397" />
|
||||
<Button Width="48" Height="48" Margin="4" Padding="0"
|
||||
<Button Width="48"
|
||||
Height="48"
|
||||
Margin="4"
|
||||
Padding="0"
|
||||
Background="#C5C1C0"
|
||||
BorderThickness="0"
|
||||
CornerRadius="6"
|
||||
Command="{Binding SelectColorCommand}"
|
||||
CommandParameter="#C5C1C0"
|
||||
ToolTip.Tip="#C5C1C0" />
|
||||
<Button Width="48" Height="48" Margin="4" Padding="0"
|
||||
<Button Width="48"
|
||||
Height="48"
|
||||
Margin="4"
|
||||
Padding="0"
|
||||
Background="#D4BE8D"
|
||||
BorderThickness="0"
|
||||
CornerRadius="6"
|
||||
Command="{Binding SelectColorCommand}"
|
||||
CommandParameter="#D4BE8D"
|
||||
ToolTip.Tip="#D4BE8D" />
|
||||
<Button Width="48" Height="48" Margin="4" Padding="0"
|
||||
<Button Width="48"
|
||||
Height="48"
|
||||
Margin="4"
|
||||
Padding="0"
|
||||
Background="#C08261"
|
||||
BorderThickness="0"
|
||||
CornerRadius="6"
|
||||
Command="{Binding SelectColorCommand}"
|
||||
CommandParameter="#C08261"
|
||||
ToolTip.Tip="#C08261" />
|
||||
<Button Width="48" Height="48" Margin="4" Padding="0"
|
||||
<Button Width="48"
|
||||
Height="48"
|
||||
Margin="4"
|
||||
Padding="0"
|
||||
Background="#8E9775"
|
||||
BorderThickness="0"
|
||||
CornerRadius="6"
|
||||
Command="{Binding SelectColorCommand}"
|
||||
CommandParameter="#8E9775"
|
||||
ToolTip.Tip="#8E9775" />
|
||||
<Button Width="48" Height="48" Margin="4" Padding="0"
|
||||
<Button Width="48"
|
||||
Height="48"
|
||||
Margin="4"
|
||||
Padding="0"
|
||||
Background="#9FBAD3"
|
||||
BorderThickness="0"
|
||||
CornerRadius="6"
|
||||
Command="{Binding SelectColorCommand}"
|
||||
CommandParameter="#9FBAD3"
|
||||
ToolTip.Tip="#9FBAD3" />
|
||||
<Button Width="48" Height="48" Margin="4" Padding="0"
|
||||
<Button Width="48"
|
||||
Height="48"
|
||||
Margin="4"
|
||||
Padding="0"
|
||||
Background="#E5BAA2"
|
||||
BorderThickness="0"
|
||||
CornerRadius="6"
|
||||
Command="{Binding SelectColorCommand}"
|
||||
CommandParameter="#E5BAA2"
|
||||
ToolTip.Tip="#E5BAA2" />
|
||||
<!-- 第12个位置:自定义颜色选择器 -->
|
||||
<Button Width="48" Height="48" Margin="4" Padding="0"
|
||||
|
||||
<Button Width="48"
|
||||
Height="48"
|
||||
Margin="4"
|
||||
Padding="0"
|
||||
Background="{Binding CustomColorBrush}"
|
||||
BorderThickness="0"
|
||||
CornerRadius="6"
|
||||
ToolTip.Tip="自定义颜色">
|
||||
ToolTip.Tip="Custom color">
|
||||
<Button.Flyout>
|
||||
<Flyout Placement="BottomEdgeAlignedLeft">
|
||||
<StackPanel Width="260" Spacing="12">
|
||||
<StackPanel Width="260"
|
||||
Spacing="12">
|
||||
<ColorPicker Color="{Binding CustomColor}" />
|
||||
</StackPanel>
|
||||
</Flyout>
|
||||
@@ -141,8 +181,10 @@
|
||||
</UniformGrid>
|
||||
</StackPanel>
|
||||
|
||||
<!-- 右侧:系统壁纸状态 -->
|
||||
<StackPanel Grid.Column="1" VerticalAlignment="Center" Spacing="12" IsVisible="{Binding IsSystemWallpaper}">
|
||||
<StackPanel Grid.Column="1"
|
||||
VerticalAlignment="Center"
|
||||
Spacing="12"
|
||||
IsVisible="{Binding IsSystemWallpaper}">
|
||||
<TextBlock Text="{Binding SystemWallpaperLabel}"
|
||||
FontSize="14"
|
||||
FontWeight="SemiBold"
|
||||
@@ -155,19 +197,18 @@
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
|
||||
<Separator Classes="settings-separator" Margin="0,0,0,24" />
|
||||
<Separator Classes="settings-separator"
|
||||
Margin="0,0,0,24" />
|
||||
|
||||
<!-- 基本设置项 -->
|
||||
<controls:IconText Icon="Image"
|
||||
Text="{Binding WallpaperHeader}"
|
||||
Margin="0,0,0,8" />
|
||||
|
||||
<!-- 壁纸类型 -->
|
||||
<ui:SettingsExpander Header="{Binding WallpaperTypeLabel}">
|
||||
<ui:SettingsExpander.IconSource>
|
||||
<fi:SymbolIconSource Symbol="Layer" />
|
||||
</ui:SettingsExpander.IconSource>
|
||||
<ui:SettingsExpander.Footer>
|
||||
<ui:FASettingsExpander Header="{Binding WallpaperTypeLabel}">
|
||||
<ui:FASettingsExpander.IconSource>
|
||||
<ui:FAFontIconSource Glyph="󰙼" FontFamily="avares://fluenticons.resources.avalonia/Assets#Seagull Fluent Icons" />
|
||||
</ui:FASettingsExpander.IconSource>
|
||||
<ui:FASettingsExpander.Footer>
|
||||
<ComboBox Width="200"
|
||||
ItemsSource="{Binding WallpaperTypes}"
|
||||
SelectedItem="{Binding SelectedWallpaperType}">
|
||||
@@ -177,18 +218,18 @@
|
||||
</DataTemplate>
|
||||
</ComboBox.ItemTemplate>
|
||||
</ComboBox>
|
||||
</ui:SettingsExpander.Footer>
|
||||
</ui:SettingsExpander>
|
||||
</ui:FASettingsExpander.Footer>
|
||||
</ui:FASettingsExpander>
|
||||
|
||||
<!-- 图片文件选择 -->
|
||||
<ui:SettingsExpander Header="{Binding WallpaperPathLabel}"
|
||||
<ui:FASettingsExpander Header="{Binding WallpaperPathLabel}"
|
||||
IsVisible="{Binding IsImage}"
|
||||
Margin="0,4,0,0">
|
||||
<ui:SettingsExpander.IconSource>
|
||||
<fi:SymbolIconSource Symbol="FolderOpen" />
|
||||
</ui:SettingsExpander.IconSource>
|
||||
<ui:SettingsExpander.Footer>
|
||||
<StackPanel Orientation="Horizontal" Spacing="8">
|
||||
<ui:FASettingsExpander.IconSource>
|
||||
<ui:FAFontIconSource Glyph="󰖌" FontFamily="avares://fluenticons.resources.avalonia/Assets#Seagull Fluent Icons" />
|
||||
</ui:FASettingsExpander.IconSource>
|
||||
<ui:FASettingsExpander.Footer>
|
||||
<StackPanel Orientation="Horizontal"
|
||||
Spacing="8">
|
||||
<TextBox IsReadOnly="True"
|
||||
Width="300"
|
||||
Text="{Binding WallpaperPath}"
|
||||
@@ -198,18 +239,18 @@
|
||||
Content="{Binding ImportWallpaperButtonText}"
|
||||
VerticalAlignment="Center" />
|
||||
</StackPanel>
|
||||
</ui:SettingsExpander.Footer>
|
||||
</ui:SettingsExpander>
|
||||
</ui:FASettingsExpander.Footer>
|
||||
</ui:FASettingsExpander>
|
||||
|
||||
<!-- 系统壁纸刷新设置 -->
|
||||
<ui:SettingsExpander Header="{Binding RefreshIntervalLabel}"
|
||||
<ui:FASettingsExpander Header="{Binding RefreshIntervalLabel}"
|
||||
IsVisible="{Binding IsSystemWallpaper}"
|
||||
Margin="0,4,0,0">
|
||||
<ui:SettingsExpander.IconSource>
|
||||
<fi:SymbolIconSource Symbol="Clock" />
|
||||
</ui:SettingsExpander.IconSource>
|
||||
<ui:SettingsExpander.Footer>
|
||||
<StackPanel Orientation="Horizontal" Spacing="8">
|
||||
<ui:FASettingsExpander.IconSource>
|
||||
<ui:FAFontIconSource Glyph="󰅨" FontFamily="avares://fluenticons.resources.avalonia/Assets#Seagull Fluent Icons" />
|
||||
</ui:FASettingsExpander.IconSource>
|
||||
<ui:FASettingsExpander.Footer>
|
||||
<StackPanel Orientation="Horizontal"
|
||||
Spacing="8">
|
||||
<ComboBox Width="140"
|
||||
ItemsSource="{Binding RefreshIntervals}"
|
||||
SelectedItem="{Binding SelectedRefreshInterval}">
|
||||
@@ -224,21 +265,21 @@
|
||||
ToolTip.Tip="{Binding RefreshButtonTooltip}"
|
||||
VerticalAlignment="Center"
|
||||
Padding="12,8">
|
||||
<fi:SymbolIcon Symbol="ArrowSync" IconVariant="Regular" />
|
||||
<fi:SymbolIcon Symbol="ArrowSync"
|
||||
IconVariant="Regular" />
|
||||
</Button>
|
||||
</StackPanel>
|
||||
</ui:SettingsExpander.Footer>
|
||||
</ui:SettingsExpander>
|
||||
</ui:FASettingsExpander.Footer>
|
||||
</ui:FASettingsExpander>
|
||||
|
||||
<!-- 填充方式(图片和系统壁纸都显示) -->
|
||||
<ui:SettingsExpander Header="{Binding WallpaperPlacementLabel}"
|
||||
<ui:FASettingsExpander Header="{Binding WallpaperPlacementLabel}"
|
||||
Description="{Binding WallpaperPlacementDescription}"
|
||||
IsVisible="{Binding IsImageOrVideo}"
|
||||
IsVisible="{Binding IsImage}"
|
||||
Margin="0,4,0,0">
|
||||
<ui:SettingsExpander.IconSource>
|
||||
<fi:SymbolIconSource Symbol="Maximize" />
|
||||
</ui:SettingsExpander.IconSource>
|
||||
<ui:SettingsExpander.Footer>
|
||||
<ui:FASettingsExpander.IconSource>
|
||||
<ui:FAFontIconSource Glyph="󰆨" FontFamily="avares://fluenticons.resources.avalonia/Assets#Seagull Fluent Icons" />
|
||||
</ui:FASettingsExpander.IconSource>
|
||||
<ui:FASettingsExpander.Footer>
|
||||
<ComboBox Width="200"
|
||||
ItemsSource="{Binding WallpaperPlacements}"
|
||||
SelectedItem="{Binding SelectedWallpaperPlacement}">
|
||||
@@ -248,18 +289,17 @@
|
||||
</DataTemplate>
|
||||
</ComboBox.ItemTemplate>
|
||||
</ComboBox>
|
||||
</ui:SettingsExpander.Footer>
|
||||
</ui:SettingsExpander>
|
||||
</ui:FASettingsExpander.Footer>
|
||||
</ui:FASettingsExpander>
|
||||
|
||||
<!-- 系统壁纸填充方式 -->
|
||||
<ui:SettingsExpander Header="{Binding WallpaperPlacementLabel}"
|
||||
<ui:FASettingsExpander Header="{Binding WallpaperPlacementLabel}"
|
||||
Description="{Binding WallpaperPlacementDescription}"
|
||||
IsVisible="{Binding IsSystemWallpaper}"
|
||||
Margin="0,4,0,0">
|
||||
<ui:SettingsExpander.IconSource>
|
||||
<fi:SymbolIconSource Symbol="Maximize" />
|
||||
</ui:SettingsExpander.IconSource>
|
||||
<ui:SettingsExpander.Footer>
|
||||
<ui:FASettingsExpander.IconSource>
|
||||
<ui:FAFontIconSource Glyph="󰆨" FontFamily="avares://fluenticons.resources.avalonia/Assets#Seagull Fluent Icons" />
|
||||
</ui:FASettingsExpander.IconSource>
|
||||
<ui:FASettingsExpander.Footer>
|
||||
<ComboBox Width="200"
|
||||
ItemsSource="{Binding WallpaperPlacements}"
|
||||
SelectedItem="{Binding SelectedWallpaperPlacement}">
|
||||
@@ -269,9 +309,8 @@
|
||||
</DataTemplate>
|
||||
</ComboBox.ItemTemplate>
|
||||
</ComboBox>
|
||||
</ui:SettingsExpander.Footer>
|
||||
</ui:SettingsExpander>
|
||||
|
||||
</ui:FASettingsExpander.Footer>
|
||||
</ui:FASettingsExpander>
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
</UserControl>
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:vm="using:LanMountainDesktop.ViewModels"
|
||||
xmlns:models="using:LanMountainDesktop.Models"
|
||||
xmlns:controls="using:LanMountainDesktop.Controls"
|
||||
xmlns:ui="using:FluentAvalonia.UI.Controls"
|
||||
xmlns:fi="using:FluentIcons.Avalonia.Fluent"
|
||||
xmlns:fi="using:FluentIcons.Avalonia"
|
||||
x:Class="LanMountainDesktop.Views.SettingsPages.WeatherSettingsPage"
|
||||
x:DataType="vm:WeatherSettingsPageViewModel">
|
||||
<ScrollViewer VerticalScrollBarVisibility="Auto">
|
||||
@@ -47,7 +47,7 @@
|
||||
<Button Classes="settings-accent-button"
|
||||
Command="{Binding RefreshPreviewCommand}"
|
||||
Content="{Binding RefreshButtonText}" />
|
||||
<ui:ProgressRing IsIndeterminate="True"
|
||||
<ui:FAProgressRing IsIndeterminate="True"
|
||||
IsVisible="{Binding IsRefreshingPreview}"
|
||||
Width="28"
|
||||
Height="28"
|
||||
@@ -56,13 +56,13 @@
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
<ui:SettingsExpander Classes="settings-expander-card"
|
||||
<ui:FASettingsExpander Classes="settings-expander-card"
|
||||
Header="{Binding LocationSourceHeader}"
|
||||
Description="{Binding LocationSourceDescription}">
|
||||
<ui:SettingsExpander.IconSource>
|
||||
<fi:SymbolIconSource Symbol="WeatherMoon" />
|
||||
</ui:SettingsExpander.IconSource>
|
||||
<ui:SettingsExpander.Footer>
|
||||
<ui:FASettingsExpander.IconSource>
|
||||
<ui:FAFontIconSource Glyph="󰔄" FontFamily="avares://fluenticons.resources.avalonia/Assets#Seagull Fluent Icons" />
|
||||
</ui:FASettingsExpander.IconSource>
|
||||
<ui:FASettingsExpander.Footer>
|
||||
<ComboBox Width="220"
|
||||
ItemsSource="{Binding LocationModes}"
|
||||
SelectedItem="{Binding SelectedLocationMode}">
|
||||
@@ -72,33 +72,33 @@
|
||||
</DataTemplate>
|
||||
</ComboBox.ItemTemplate>
|
||||
</ComboBox>
|
||||
</ui:SettingsExpander.Footer>
|
||||
<ui:SettingsExpanderItem>
|
||||
</ui:FASettingsExpander.Footer>
|
||||
<ui:FASettingsExpanderItem>
|
||||
<TextBlock Classes="settings-item-description"
|
||||
Text="{Binding CurrentLocationSummary}"
|
||||
TextWrapping="Wrap" />
|
||||
</ui:SettingsExpanderItem>
|
||||
</ui:SettingsExpander>
|
||||
</ui:FASettingsExpanderItem>
|
||||
</ui:FASettingsExpander>
|
||||
|
||||
<ui:SettingsExpander Classes="settings-expander-card"
|
||||
<ui:FASettingsExpander Classes="settings-expander-card"
|
||||
Header="{Binding CitySearchHeader}"
|
||||
Description="{Binding CitySearchDescription}"
|
||||
IsVisible="{Binding IsCitySearchMode}">
|
||||
<ui:SettingsExpander.IconSource>
|
||||
<fi:SymbolIconSource Symbol="Search" />
|
||||
</ui:SettingsExpander.IconSource>
|
||||
<ui:SettingsExpander.Footer>
|
||||
<ui:FASettingsExpander.IconSource>
|
||||
<ui:FAFontIconSource Glyph="󰏴" FontFamily="avares://fluenticons.resources.avalonia/Assets#Seagull Fluent Icons" />
|
||||
</ui:FASettingsExpander.IconSource>
|
||||
<ui:FASettingsExpander.Footer>
|
||||
<Button Classes="settings-accent-button"
|
||||
Command="{Binding ApplyCitySelectionCommand}"
|
||||
Content="{Binding ApplyCityButtonText}" />
|
||||
</ui:SettingsExpander.Footer>
|
||||
<ui:SettingsExpanderItem>
|
||||
</ui:FASettingsExpander.Footer>
|
||||
<ui:FASettingsExpanderItem>
|
||||
<StackPanel Spacing="14">
|
||||
<Grid ColumnDefinitions="*,Auto"
|
||||
ColumnSpacing="12">
|
||||
<TextBox x:Name="SearchKeywordTextBox"
|
||||
Text="{Binding SearchKeyword}"
|
||||
Watermark="{Binding SearchPlaceholder}"
|
||||
PlaceholderText="{Binding SearchPlaceholder}"
|
||||
Focusable="True"
|
||||
IsTabStop="True" />
|
||||
<Button Grid.Column="1"
|
||||
@@ -106,7 +106,7 @@
|
||||
Content="{Binding SearchButtonText}" />
|
||||
</Grid>
|
||||
|
||||
<ui:ProgressRing IsIndeterminate="True"
|
||||
<ui:FAProgressRing IsIndeterminate="True"
|
||||
IsVisible="{Binding IsSearching}"
|
||||
Width="24"
|
||||
Height="24"
|
||||
@@ -123,9 +123,10 @@
|
||||
<DataTemplate x:DataType="models:WeatherLocation">
|
||||
<Grid ColumnDefinitions="Auto,*"
|
||||
ColumnSpacing="12">
|
||||
<fi:SymbolIcon Classes="icon-s"
|
||||
<ui:FAFontIcon Classes="icon-s"
|
||||
Margin="0,2,0,0"
|
||||
Symbol="City" />
|
||||
Glyph="󰊼"
|
||||
FontFamily="avares://fluenticons.resources.avalonia/Assets#Seagull Fluent Icons" />
|
||||
<StackPanel Grid.Column="1"
|
||||
Spacing="4">
|
||||
<TextBlock Classes="settings-item-label"
|
||||
@@ -140,22 +141,22 @@
|
||||
</ListBox.ItemTemplate>
|
||||
</ListBox>
|
||||
</StackPanel>
|
||||
</ui:SettingsExpanderItem>
|
||||
</ui:SettingsExpander>
|
||||
</ui:FASettingsExpanderItem>
|
||||
</ui:FASettingsExpander>
|
||||
|
||||
<ui:SettingsExpander Classes="settings-expander-card"
|
||||
<ui:FASettingsExpander Classes="settings-expander-card"
|
||||
Header="{Binding CoordinatesHeader}"
|
||||
Description="{Binding CoordinatesDescription}"
|
||||
IsVisible="{Binding IsCoordinatesMode}">
|
||||
<ui:SettingsExpander.IconSource>
|
||||
<fi:SymbolIconSource Symbol="Location" />
|
||||
</ui:SettingsExpander.IconSource>
|
||||
<ui:SettingsExpander.Footer>
|
||||
<ui:FASettingsExpander.IconSource>
|
||||
<ui:FAFontIconSource Glyph="󰊼" FontFamily="avares://fluenticons.resources.avalonia/Assets#Seagull Fluent Icons" />
|
||||
</ui:FASettingsExpander.IconSource>
|
||||
<ui:FASettingsExpander.Footer>
|
||||
<Button Classes="settings-accent-button"
|
||||
Command="{Binding ApplyCoordinatesCommand}"
|
||||
Content="{Binding ApplyCoordinatesButtonText}" />
|
||||
</ui:SettingsExpander.Footer>
|
||||
<ui:SettingsExpanderItem>
|
||||
</ui:FASettingsExpander.Footer>
|
||||
<ui:FASettingsExpanderItem>
|
||||
<Grid ColumnDefinitions="*,*"
|
||||
Classes="settings-inline-pair">
|
||||
<StackPanel Classes="settings-item">
|
||||
@@ -179,36 +180,36 @@
|
||||
Value="{Binding Longitude}" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</ui:SettingsExpanderItem>
|
||||
<ui:SettingsExpanderItem>
|
||||
</ui:FASettingsExpanderItem>
|
||||
<ui:FASettingsExpanderItem>
|
||||
<TextBox x:Name="LocationKeyTextBox"
|
||||
Text="{Binding LocationKey}"
|
||||
Watermark="{Binding LocationKeyPlaceholder}"
|
||||
PlaceholderText="{Binding LocationKeyPlaceholder}"
|
||||
Focusable="True"
|
||||
IsTabStop="True" />
|
||||
</ui:SettingsExpanderItem>
|
||||
<ui:SettingsExpanderItem>
|
||||
</ui:FASettingsExpanderItem>
|
||||
<ui:FASettingsExpanderItem>
|
||||
<TextBox x:Name="LocationNameTextBox"
|
||||
Text="{Binding LocationName}"
|
||||
Watermark="{Binding LocationNamePlaceholder}"
|
||||
PlaceholderText="{Binding LocationNamePlaceholder}"
|
||||
Focusable="True"
|
||||
IsTabStop="True" />
|
||||
</ui:SettingsExpanderItem>
|
||||
</ui:SettingsExpander>
|
||||
</ui:FASettingsExpanderItem>
|
||||
</ui:FASettingsExpander>
|
||||
|
||||
<ui:SettingsExpander Classes="settings-expander-card"
|
||||
<ui:FASettingsExpander Classes="settings-expander-card"
|
||||
Header="{Binding LocationServicesHeader}"
|
||||
Description="{Binding LocationServicesDescription}">
|
||||
<ui:SettingsExpander.IconSource>
|
||||
<fi:SymbolIconSource Symbol="Location" />
|
||||
</ui:SettingsExpander.IconSource>
|
||||
<ui:SettingsExpander.Footer>
|
||||
<ui:FASettingsExpander.IconSource>
|
||||
<ui:FAFontIconSource Glyph="󰊼" FontFamily="avares://fluenticons.resources.avalonia/Assets#Seagull Fluent Icons" />
|
||||
</ui:FASettingsExpander.IconSource>
|
||||
<ui:FASettingsExpander.Footer>
|
||||
<Button Classes="settings-accent-button"
|
||||
Command="{Binding UseCurrentLocationCommand}"
|
||||
Content="{Binding UseCurrentLocationButtonText}"
|
||||
IsVisible="{Binding IsLocationSupported}" />
|
||||
</ui:SettingsExpander.Footer>
|
||||
<ui:SettingsExpanderItem>
|
||||
</ui:FASettingsExpander.Footer>
|
||||
<ui:FASettingsExpanderItem>
|
||||
<Grid ColumnDefinitions="*,Auto"
|
||||
ColumnSpacing="16">
|
||||
<StackPanel Classes="settings-item">
|
||||
@@ -222,23 +223,23 @@
|
||||
IsChecked="{Binding AutoRefreshLocation}"
|
||||
IsEnabled="{Binding IsLocationSupported}" />
|
||||
</Grid>
|
||||
</ui:SettingsExpanderItem>
|
||||
<ui:SettingsExpanderItem IsVisible="{Binding IsRefreshingLocation}">
|
||||
<ui:ProgressRing IsIndeterminate="True"
|
||||
</ui:FASettingsExpanderItem>
|
||||
<ui:FASettingsExpanderItem IsVisible="{Binding IsRefreshingLocation}">
|
||||
<ui:FAProgressRing IsIndeterminate="True"
|
||||
IsVisible="{Binding IsRefreshingLocation}"
|
||||
Width="28"
|
||||
Height="28"
|
||||
HorizontalAlignment="Left" />
|
||||
</ui:SettingsExpanderItem>
|
||||
</ui:SettingsExpander>
|
||||
</ui:FASettingsExpanderItem>
|
||||
</ui:FASettingsExpander>
|
||||
|
||||
<ui:SettingsExpander Classes="settings-expander-card"
|
||||
<ui:FASettingsExpander Classes="settings-expander-card"
|
||||
Header="{Binding AlertFilterHeader}"
|
||||
Description="{Binding AlertFilterDescription}">
|
||||
<ui:SettingsExpander.IconSource>
|
||||
<fi:SymbolIconSource Symbol="Warning" />
|
||||
</ui:SettingsExpander.IconSource>
|
||||
<ui:SettingsExpander.Footer>
|
||||
<ui:FASettingsExpander.IconSource>
|
||||
<ui:FAFontIconSource Glyph="󰓨" FontFamily="avares://fluenticons.resources.avalonia/Assets#Seagull Fluent Icons" />
|
||||
</ui:FASettingsExpander.IconSource>
|
||||
<ui:FASettingsExpander.Footer>
|
||||
<TextBox x:Name="ExcludedAlertsTextBox"
|
||||
Width="360"
|
||||
MinHeight="120"
|
||||
@@ -247,24 +248,24 @@
|
||||
Text="{Binding ExcludedAlerts}"
|
||||
Focusable="True"
|
||||
IsTabStop="True" />
|
||||
</ui:SettingsExpander.Footer>
|
||||
</ui:SettingsExpander>
|
||||
</ui:FASettingsExpander.Footer>
|
||||
</ui:FASettingsExpander>
|
||||
|
||||
<ui:SettingsExpander Classes="settings-expander-card"
|
||||
<ui:FASettingsExpander Classes="settings-expander-card"
|
||||
Header="{Binding RequestHeader}"
|
||||
Description="{Binding RequestDescription}">
|
||||
<ui:SettingsExpander.IconSource>
|
||||
<fi:SymbolIconSource Symbol="ShieldDismiss" />
|
||||
</ui:SettingsExpander.IconSource>
|
||||
<ui:SettingsExpander.Footer>
|
||||
<ui:FASettingsExpander.IconSource>
|
||||
<ui:FAFontIconSource Glyph="󰯄" FontFamily="avares://fluenticons.resources.avalonia/Assets#Seagull Fluent Icons" />
|
||||
</ui:FASettingsExpander.IconSource>
|
||||
<ui:FASettingsExpander.Footer>
|
||||
<ToggleSwitch IsChecked="{Binding NoTlsRequests}" />
|
||||
</ui:SettingsExpander.Footer>
|
||||
<ui:SettingsExpanderItem>
|
||||
</ui:FASettingsExpander.Footer>
|
||||
<ui:FASettingsExpanderItem>
|
||||
<TextBlock Classes="settings-item-description"
|
||||
Text="{Binding NoTlsToggleText}"
|
||||
TextWrapping="Wrap" />
|
||||
</ui:SettingsExpanderItem>
|
||||
</ui:SettingsExpander>
|
||||
</ui:FASettingsExpanderItem>
|
||||
</ui:FASettingsExpander>
|
||||
|
||||
<TextBlock Classes="settings-item-description"
|
||||
Margin="0,8,0,0"
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:vm="using:LanMountainDesktop.ViewModels"
|
||||
xmlns:ui="using:FluentAvalonia.UI.Controls"
|
||||
xmlns:fi="using:FluentIcons.Avalonia.Fluent"
|
||||
xmlns:fi="using:FluentIcons.Avalonia"
|
||||
x:Class="LanMountainDesktop.Views.SettingsWindow"
|
||||
x:DataType="vm:SettingsWindowViewModel"
|
||||
Width="1120"
|
||||
@@ -11,7 +11,7 @@
|
||||
MinHeight="480"
|
||||
CanResize="True"
|
||||
WindowStartupLocation="Manual"
|
||||
SystemDecorations="BorderOnly"
|
||||
WindowDecorations="BorderOnly"
|
||||
FontFamily="{DynamicResource AppFontFamily}"
|
||||
Background="Transparent"
|
||||
Title="{Binding Title}">
|
||||
@@ -112,7 +112,7 @@
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
<ui:NavigationView x:Name="RootNavigationView"
|
||||
<ui:FANavigationView x:Name="RootNavigationView"
|
||||
Grid.Row="1"
|
||||
Margin="0,8,0,0"
|
||||
Background="Transparent"
|
||||
@@ -122,10 +122,10 @@
|
||||
IsPaneToggleButtonVisible="False"
|
||||
IsBackButtonVisible="False"
|
||||
SelectionChanged="OnNavigationSelectionChanged">
|
||||
<ui:NavigationView.Resources>
|
||||
<ui:FANavigationView.Resources>
|
||||
<SolidColorBrush x:Key="NavigationViewContentBackground" Color="Transparent" />
|
||||
<SolidColorBrush x:Key="NavigationViewContentGridBorderBrush" Color="Transparent" />
|
||||
</ui:NavigationView.Resources>
|
||||
</ui:FANavigationView.Resources>
|
||||
|
||||
<Grid x:Name="SettingsContentGrid"
|
||||
ColumnDefinitions="*,Auto"
|
||||
@@ -142,7 +142,7 @@
|
||||
Text="{Binding CurrentPageTitle}" />
|
||||
</Grid>
|
||||
|
||||
<ui:Frame x:Name="ContentFrame"
|
||||
<ui:FAFrame x:Name="ContentFrame"
|
||||
Grid.Row="1" />
|
||||
</Grid>
|
||||
|
||||
@@ -180,6 +180,6 @@
|
||||
</Grid>
|
||||
</Border>
|
||||
</Grid>
|
||||
</ui:NavigationView>
|
||||
</ui:FANavigationView>
|
||||
</Grid>
|
||||
</Window>
|
||||
|
||||
@@ -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 { })
|
||||
{
|
||||
@@ -205,27 +201,23 @@ public partial class SettingsWindow : Window, ISettingsPageHostContext
|
||||
{
|
||||
if (previousCategory is not null && previousCategory != page.Category)
|
||||
{
|
||||
RootNavigationView.MenuItems.Add(new NavigationViewItemSeparator());
|
||||
RootNavigationView.MenuItems.Add(new FANavigationViewItemSeparator());
|
||||
}
|
||||
|
||||
RootNavigationView.MenuItems.Add(new NavigationViewItem
|
||||
RootNavigationView.MenuItems.Add(new FANavigationViewItem
|
||||
{
|
||||
Content = page.Title,
|
||||
Tag = page.PageId,
|
||||
IconSource = new FluentIcons.Avalonia.Fluent.SymbolIconSource
|
||||
{
|
||||
Symbol = MapIcon(page.IconKey),
|
||||
IconVariant = FluentIcons.Common.IconVariant.Regular
|
||||
}
|
||||
IconSource = CreateSettingsIconSource(MapIcon(page.IconKey))
|
||||
});
|
||||
|
||||
previousCategory = page.Category;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnNavigationSelectionChanged(object? sender, NavigationViewSelectionChangedEventArgs e)
|
||||
private void OnNavigationSelectionChanged(object? sender, FANavigationViewSelectionChangedEventArgs e)
|
||||
{
|
||||
var selectedItem = e.SelectedItemContainer ?? e.SelectedItem as NavigationViewItem;
|
||||
var selectedItem = e.SelectedItemContainer ?? e.SelectedItem as FANavigationViewItem;
|
||||
NavigateTo(selectedItem?.Tag as string);
|
||||
}
|
||||
|
||||
@@ -301,7 +293,7 @@ public partial class SettingsWindow : Window, ISettingsPageHostContext
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var item in RootNavigationView.MenuItems.OfType<NavigationViewItem>())
|
||||
foreach (var item in RootNavigationView.MenuItems.OfType<FANavigationViewItem>())
|
||||
{
|
||||
if (string.Equals(item.Tag as string, pageId, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
@@ -374,17 +366,17 @@ public partial class SettingsWindow : Window, ISettingsPageHostContext
|
||||
|
||||
try
|
||||
{
|
||||
var dialog = new ContentDialog
|
||||
var dialog = new FAContentDialog
|
||||
{
|
||||
Title = ViewModel.RestartDialogTitle,
|
||||
Content = ViewModel.RestartMessage,
|
||||
PrimaryButtonText = ViewModel.RestartDialogPrimaryText,
|
||||
CloseButtonText = ViewModel.RestartDialogCloseText,
|
||||
DefaultButton = ContentDialogButton.Primary
|
||||
DefaultButton = FAContentDialogButton.Primary
|
||||
};
|
||||
|
||||
var result = await dialog.ShowAsync(this);
|
||||
if (result == ContentDialogResult.Primary)
|
||||
if (result == FAContentDialogResult.Primary)
|
||||
{
|
||||
_hostApplicationLifecycle.TryRestart(new HostApplicationLifecycleRequest(
|
||||
Source: "SettingsWindow",
|
||||
@@ -486,7 +478,7 @@ public partial class SettingsWindow : Window, ISettingsPageHostContext
|
||||
{
|
||||
_ = TryApplyResponsiveLayout();
|
||||
|
||||
// 小窗口时隐藏抽屉面板
|
||||
// Hide the drawer pane on narrow windows.
|
||||
}
|
||||
|
||||
private void OnClosed(object? sender, EventArgs e)
|
||||
@@ -537,9 +529,9 @@ public partial class SettingsWindow : Window, ISettingsPageHostContext
|
||||
{
|
||||
_ = sender;
|
||||
|
||||
if (e.Property == NavigationView.IsPaneOpenProperty ||
|
||||
e.Property == NavigationView.OpenPaneLengthProperty ||
|
||||
e.Property == NavigationView.PaneDisplayModeProperty)
|
||||
if (e.Property == FANavigationView.IsPaneOpenProperty ||
|
||||
e.Property == FANavigationView.OpenPaneLengthProperty ||
|
||||
e.Property == FANavigationView.PaneDisplayModeProperty)
|
||||
{
|
||||
UpdatePaneToggleIcon();
|
||||
RequestResponsiveLayoutRefresh();
|
||||
@@ -736,16 +728,41 @@ public partial class SettingsWindow : Window, ISettingsPageHostContext
|
||||
"GridDots" => Symbol.GridDots,
|
||||
"PuzzlePiece" => Symbol.PuzzlePiece,
|
||||
"ShoppingBag" => Symbol.ShoppingBag,
|
||||
"Shield" => Symbol.ShieldDismiss,
|
||||
"Shield" => Symbol.ShieldLock,
|
||||
"Info" => Symbol.Info,
|
||||
"ArrowSync" => Symbol.ArrowSync,
|
||||
"Hourglass" => Symbol.Hourglass,
|
||||
"Alert" => Symbol.Alert,
|
||||
"Bell" => Symbol.Alert,
|
||||
"Bell" => Symbol.AlertOn,
|
||||
"DeveloperBoard" => Symbol.DeveloperBoard,
|
||||
"FolderLink" => Symbol.FolderLink,
|
||||
"WindowConsole" => Symbol.WindowConsole,
|
||||
_ => Symbol.Settings
|
||||
};
|
||||
}
|
||||
|
||||
private static FAFontIconSource CreateSettingsIconSource(Symbol symbol)
|
||||
{
|
||||
var symbolIcon = new FluentIcons.Avalonia.SymbolIcon
|
||||
{
|
||||
Symbol = symbol,
|
||||
IconVariant = FluentIcons.Common.IconVariant.Regular
|
||||
};
|
||||
|
||||
// FluentAvalonia still expects IconSource here, so bridge the Avalonia 12 FluentIcons glyph/font into FAFontIconSource.
|
||||
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
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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">
|
||||
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
<Window xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
x:Class="LanMountainDesktop.Views.TransparentOverlayWindow"
|
||||
SystemDecorations="None"
|
||||
WindowDecorations="None"
|
||||
CanResize="False"
|
||||
ShowInTaskbar="False"
|
||||
ExtendClientAreaToDecorationsHint="True"
|
||||
ExtendClientAreaChromeHints="NoChrome"
|
||||
Background="Transparent"
|
||||
Title="LanMountainDesktop Fused Desktop">
|
||||
<!--
|
||||
|
||||
@@ -695,7 +695,7 @@ public sealed class PluginRuntimeService : IDisposable
|
||||
if (assemblyName.StartsWith("Avalonia", StringComparison.OrdinalIgnoreCase) ||
|
||||
string.Equals(assemblyName, "FluentAvaloniaUI", StringComparison.OrdinalIgnoreCase) ||
|
||||
string.Equals(assemblyName, "FluentIcons.Avalonia", StringComparison.OrdinalIgnoreCase) ||
|
||||
string.Equals(assemblyName, "FluentIcons.Avalonia.Fluent", StringComparison.OrdinalIgnoreCase) ||
|
||||
string.Equals(assemblyName, "Material.Avalonia", StringComparison.OrdinalIgnoreCase) ||
|
||||
string.Equals(assemblyName, "Material.Icons.Avalonia", StringComparison.OrdinalIgnoreCase) ||
|
||||
string.Equals(assemblyName, "MicroCom.Runtime", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
|
||||
@@ -96,9 +96,9 @@ dotnet new install LanMountainDesktop.PluginTemplate
|
||||
dotnet new lmd-plugin -n MyPlugin
|
||||
```
|
||||
|
||||
- **Plugin SDK**: `LanMountainDesktop.PluginSdk` (API 4.0.1)
|
||||
- **Plugin SDK**: `LanMountainDesktop.PluginSdk` (API 5.0.0)
|
||||
- **共享契约**: `LanMountainDesktop.Shared.Contracts`
|
||||
- **迁移指南**: [PLUGIN_SDK_V4_MIGRATION.md](docs/PLUGIN_SDK_V4_MIGRATION.md)
|
||||
- **迁移指南**: [PLUGIN_SDK_V5_MIGRATION.md](docs/PLUGIN_SDK_V5_MIGRATION.md)
|
||||
|
||||
## 项目结构
|
||||
|
||||
|
||||
29
TestFluentIcons/Program.cs
Normal file
29
TestFluentIcons/Program.cs
Normal file
@@ -0,0 +1,29 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using FluentAvalonia.UI.Controls;
|
||||
|
||||
class Test
|
||||
{
|
||||
static void Main()
|
||||
{
|
||||
var faSymbols = new System.Collections.Generic.HashSet<string>(Enum.GetNames(typeof(FASymbol)));
|
||||
|
||||
// 从错误信息中提取的图标名称
|
||||
var usedIcons = new[]
|
||||
{
|
||||
"Info", "Color", "Apps", "Code", "Home", "Settings",
|
||||
"WeatherMoon", "Search", "Location", "City", "Warning",
|
||||
"ShieldDismiss", "Shield", "Announcements", "Package",
|
||||
"StatusCircle", "Book", "BranchFork", "ArrowSync",
|
||||
"GlobeArrowForward", "Options", "Store", "Layer",
|
||||
"FolderOpen", "Clock", "Maximize"
|
||||
};
|
||||
|
||||
Console.WriteLine("Checking icon availability in FASymbol:");
|
||||
foreach (var icon in usedIcons.Distinct().OrderBy(i => i))
|
||||
{
|
||||
bool exists = faSymbols.Contains(icon);
|
||||
Console.WriteLine($" {icon}: {(exists ? "OK" : "MISSING")}");
|
||||
}
|
||||
}
|
||||
}
|
||||
15
TestFluentIcons/TestFluentIcons.csproj
Normal file
15
TestFluentIcons/TestFluentIcons.csproj
Normal file
@@ -0,0 +1,15 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="FluentAvaloniaUI" />
|
||||
<PackageReference Include="FluentIcons.Avalonia" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -63,11 +63,11 @@ MyAwesomePlugin/
|
||||
|
||||
### 插件 SDK 版本
|
||||
|
||||
当前 SDK 版本: **4.0.1**
|
||||
当前 SDK 版本: **5.0.0**
|
||||
|
||||
```xml
|
||||
<PackageReference Include="LanMountainDesktop.PluginSdk" Version="4.0.1" />
|
||||
<PackageReference Include="LanMountainDesktop.Shared.Contracts" Version="4.0.1" />
|
||||
<PackageReference Include="LanMountainDesktop.PluginSdk" Version="5.0.0" />
|
||||
<PackageReference Include="LanMountainDesktop.Shared.Contracts" Version="5.0.0" />
|
||||
```
|
||||
|
||||
### 插件清单 (plugin.json)
|
||||
@@ -175,9 +175,9 @@ public class Plugin : IPlugin
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="LanMountainDesktop.PluginSdk" Version="4.0.1" />
|
||||
<PackageReference Include="LanMountainDesktop.Shared.Contracts" Version="4.0.1" />
|
||||
<PackageReference Include="Avalonia" Version="11.3.12" />
|
||||
<PackageReference Include="LanMountainDesktop.PluginSdk" Version="5.0.0" />
|
||||
<PackageReference Include="LanMountainDesktop.Shared.Contracts" Version="5.0.0" />
|
||||
<PackageReference Include="Avalonia" Version="12.0.1" />
|
||||
</ItemGroup>
|
||||
|
||||
<!-- 复制 plugin.json 到输出目录 -->
|
||||
@@ -680,7 +680,7 @@ if (!url.StartsWith("https://", StringComparison.OrdinalIgnoreCase))
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [Plugin SDK v4 迁移指南](PLUGIN_SDK_V4_MIGRATION.md)
|
||||
- [Plugin SDK v5 迁移指南](PLUGIN_SDK_V5_MIGRATION.md)
|
||||
- [组件开发指南](COMPONENT_DEVELOPMENT.md)
|
||||
- [API 参考](API_REFERENCE.md)
|
||||
- [架构文档](ARCHITECTURE.md)
|
||||
|
||||
34
docs/PLUGIN_SDK_V5_MIGRATION.md
Normal file
34
docs/PLUGIN_SDK_V5_MIGRATION.md
Normal file
@@ -0,0 +1,34 @@
|
||||
# Plugin SDK v5 Migration Guide
|
||||
|
||||
Plugin SDK v5 is the Avalonia 12 compatibility baseline for LanMountainDesktop plugins.
|
||||
|
||||
## What Changed
|
||||
|
||||
- Rebuild plugins against `LanMountainDesktop.PluginSdk` `5.0.0`.
|
||||
- Set `plugin.json` `apiVersion` to `5.0.0`.
|
||||
- Target `net10.0` and use Avalonia `12.0.1` compatible UI dependencies.
|
||||
- Use `FluentAvaloniaUI` `3.0.0-preview1` and `FluentIcons.Avalonia` `2.1.325` when a plugin directly references those packages.
|
||||
|
||||
## Compatibility
|
||||
|
||||
SDK v5 is a binary breaking change because the SDK exposes Avalonia UI types such as `Control`, `UserControl`, and `SettingsPageBase`. Plugins built for SDK v4 must be rebuilt and republished for SDK v5.
|
||||
|
||||
The host does not provide an Avalonia 11 / Avalonia 12 dual UI stack. The public extension entry points remain the same: custom settings pages still derive from `SettingsPageBase`, and desktop components still provide Avalonia controls through the existing registration APIs.
|
||||
|
||||
## Minimal Package Update
|
||||
|
||||
```xml
|
||||
<ItemGroup>
|
||||
<PackageReference Include="LanMountainDesktop.PluginSdk" Version="5.0.0" />
|
||||
</ItemGroup>
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"apiVersion": "5.0.0"
|
||||
}
|
||||
```
|
||||
|
||||
## Validation
|
||||
|
||||
After updating package versions and rebuilding the plugin, verify that the generated `.laapp` contains the rebuilt assembly, `plugin.json`, and `.deps.json` next to the plugin entry assembly.
|
||||
@@ -39,7 +39,7 @@
|
||||
### 当前阶段
|
||||
|
||||
- 产品版本:`1.0.0`
|
||||
- Plugin SDK API 基线:`4.0.1`
|
||||
- Plugin SDK API 基线:`5.0.0`
|
||||
- 当前重点:持续完善宿主体验、设置页体验、组件能力与插件生态
|
||||
- 近期需求入口:以 `.trae/specs/` 中的 feature spec 为准
|
||||
|
||||
@@ -59,4 +59,4 @@
|
||||
|
||||
LanMountainDesktop is a cross-platform desktop enhancement product built with Avalonia UI and .NET 10. It targets students, office users, and customization-focused users who want a programmable desktop surface for information, tools, and plugin-driven extensions.
|
||||
|
||||
This repository is the source of truth for the desktop host, plugin runtime, Plugin SDK, shared contracts, and core appearance/settings infrastructure. The current product version is `1.0.0`, and the active Plugin SDK baseline in this repository is `4.0.1`.
|
||||
This repository is the source of truth for the desktop host, plugin runtime, Plugin SDK, shared contracts, and core appearance/settings infrastructure. The current product version is `1.0.0`, and the active Plugin SDK baseline in this repository is `5.0.0`.
|
||||
|
||||
@@ -40,7 +40,7 @@ cd MyFirstPlugin
|
||||
"description": "这是一个测试插件",
|
||||
"author": "你的名字",
|
||||
"version": "1.0.0",
|
||||
"apiVersion": "4.0.1",
|
||||
"apiVersion": "5.0.0",
|
||||
"entranceAssembly": "MyFirstPlugin.dll",
|
||||
"sharedContracts": []
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ MyPlugin/
|
||||
"description": "这是一个示例插件",
|
||||
"author": "作者名称",
|
||||
"version": "1.0.0",
|
||||
"apiVersion": "4.0.1",
|
||||
"apiVersion": "5.0.0",
|
||||
"entranceAssembly": "MyPlugin.dll",
|
||||
"sharedContracts": [],
|
||||
"website": "https://example.com",
|
||||
@@ -53,7 +53,7 @@ MyPlugin/
|
||||
| `description` | ✅ | 简短描述 | `显示实时天气信息` |
|
||||
| `author` | ✅ | 作者名称 | `张三` |
|
||||
| `version` | ✅ | 版本号(语义化版本) | `1.0.0` |
|
||||
| `apiVersion` | ✅ | SDK API 版本 | `4.0.1` |
|
||||
| `apiVersion` | ✅ | SDK API 版本 | `5.0.0` |
|
||||
| `entranceAssembly` | ✅ | 入口程序集文件名 | `MyPlugin.dll` |
|
||||
| `sharedContracts` | ✅ | 共享契约类型列表 | `[]` |
|
||||
| `website` | ❌ | 项目网站 | `https://github.com/...` |
|
||||
@@ -74,7 +74,7 @@ MyPlugin/
|
||||
|
||||
⚠️ **apiVersion 字段规则:**
|
||||
- 必须与引用的 SDK 版本兼容
|
||||
- 当前最新版本:`4.0.1`
|
||||
- 当前最新版本:`5.0.0`
|
||||
- 不兼容时宿主将拒绝加载插件
|
||||
|
||||
---
|
||||
@@ -96,7 +96,7 @@ MyPlugin/
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="LanMountainDesktop.PluginSdk" Version="4.0.1" />
|
||||
<PackageReference Include="LanMountainDesktop.PluginSdk" Version="5.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
@@ -122,7 +122,7 @@ MyPlugin/
|
||||
### SDK 引用
|
||||
|
||||
```xml
|
||||
<PackageReference Include="LanMountainDesktop.PluginSdk" Version="4.0.1" />
|
||||
<PackageReference Include="LanMountainDesktop.PluginSdk" Version="5.0.0" />
|
||||
```
|
||||
|
||||
⚠️ **版本必须匹配:**
|
||||
|
||||
@@ -213,7 +213,7 @@ public override void Initialize(HostBuilderContext context, IServiceCollection s
|
||||
- 关闭阑山桌面
|
||||
|
||||
**当前限制:**
|
||||
- SDK v4 暂无显式的卸载回调方法
|
||||
- SDK v5 暂无显式的卸载回调方法
|
||||
- 资源释放依赖 .NET 垃圾回收
|
||||
- 建议:
|
||||
- 使用 `IDisposable` 模式管理资源
|
||||
|
||||
@@ -33,7 +33,7 @@ MyPlugin.laapp
|
||||
"description": "插件描述",
|
||||
"author": "作者名",
|
||||
"version": "1.0.0",
|
||||
"apiVersion": "4.0.1",
|
||||
"apiVersion": "5.0.0",
|
||||
"entranceAssembly": "MyPlugin.dll",
|
||||
"sharedContracts": []
|
||||
}
|
||||
@@ -61,7 +61,7 @@ MyPlugin.laapp
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="LanMountainDesktop.PluginSdk" Version="4.0.1" />
|
||||
<PackageReference Include="LanMountainDesktop.PluginSdk" Version="5.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<!-- 确保资源文件复制到输出目录 -->
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
| 视觉规范 | `docs/VISUAL_SPEC.md` | 颜色、语义资源、玻璃层级 |
|
||||
| 圆角规范 | `docs/CORNER_RADIUS_SPEC.md` | 圆角层级与动态规则 |
|
||||
| 插件生态边界 | `docs/ECOSYSTEM_BOUNDARIES.md` | 仓库边界和 market 所属 |
|
||||
| SDK v4 迁移 | `docs/PLUGIN_SDK_V4_MIGRATION.md` | Plugin SDK breaking changes |
|
||||
| SDK v5 迁移 | `docs/PLUGIN_SDK_V5_MIGRATION.md` | Plugin SDK breaking changes |
|
||||
|
||||
## 已废弃来源
|
||||
|
||||
|
||||
11
test_fluenticons.cs
Normal file
11
test_fluenticons.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
using System;
|
||||
using FluentIcons.Avalonia;
|
||||
|
||||
class Test
|
||||
{
|
||||
static void Main()
|
||||
{
|
||||
// 尝试创建 SymbolIconSource
|
||||
var source = new SymbolIconSource();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user