feat.开发者调试工具

This commit is contained in:
lincube
2026-04-13 08:02:47 +08:00
parent 99a82d64e3
commit 76d13ac024
22 changed files with 616 additions and 30 deletions

View File

@@ -36,7 +36,8 @@
<StackPanel Classes="about-page-container">
<Border x:Name="AboutHeroCard"
Classes="about-hero-card"
Height="240">
Height="240"
PointerPressed="OnAboutHeroCardPointerPressed">
<Image Source="/Assets/about_banner.png"
Stretch="Uniform"
HorizontalAlignment="Center"

View File

@@ -1,7 +1,13 @@
using System;
using System.Diagnostics;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Input;
using Avalonia.Interactivity;
using FluentAvalonia.UI.Controls;
using LanMountainDesktop.Models;
using LanMountainDesktop.PluginSdk;
using LanMountainDesktop.Services;
using LanMountainDesktop.Services.Settings;
using LanMountainDesktop.ViewModels;
@@ -19,6 +25,10 @@ namespace LanMountainDesktop.Views.SettingsPages;
public partial class AboutSettingsPage : SettingsPageBase
{
private const double HeroAspectRatio = 9d / 16d;
private const int DevModeActivationClicks = 5;
private int _heroCardClickCount;
private DateTime _lastHeroCardClickTime = DateTime.MinValue;
public AboutSettingsPage()
: this(new AboutSettingsPageViewModel(HostSettingsFacadeProvider.GetOrCreate()))
@@ -60,4 +70,94 @@ public partial class AboutSettingsPage : SettingsPageBase
AboutHeroCard.Height = targetHeight;
}
private void OnAboutHeroCardPointerPressed(object? sender, PointerPressedEventArgs e)
{
var now = DateTime.UtcNow;
var elapsed = now - _lastHeroCardClickTime;
if (elapsed.TotalSeconds > 3)
{
_heroCardClickCount = 1;
}
else
{
_heroCardClickCount++;
}
_lastHeroCardClickTime = now;
var settingsFacade = HostSettingsFacadeProvider.GetOrCreate();
var snapshot = settingsFacade.Settings.LoadSnapshot<AppSettingsSnapshot>(SettingsScope.App);
if (snapshot.IsDevModeEnabled)
{
if (_heroCardClickCount >= 3)
{
_heroCardClickCount = 0;
_ = ShowMessageAsync("开发者模式", "开发者模式已启用,无需重复操作。");
}
return;
}
var remaining = DevModeActivationClicks - _heroCardClickCount;
if (remaining <= 0)
{
_heroCardClickCount = 0;
PromptEnableDevMode(settingsFacade);
}
else if (remaining <= 2)
{
Debug.WriteLine($"[AboutSettingsPage] 再点击 {remaining} 次即可启用开发者模式。");
}
}
private async void PromptEnableDevMode(ISettingsFacadeService settingsFacade)
{
var dialog = new ContentDialog
{
Title = "启用开发者模式",
Content = "开发者模式提供了插件调试、热重载等高级功能,仅供开发和调试用途。\n\n" +
"请注意:开发者不对以非开发用途使用此功能造成的任何后果负责,也不接受以非开发用途使用时产生的 Bug 反馈。\n\n" +
"确定要启用开发者模式吗?",
PrimaryButtonText = "启用",
CloseButtonText = "取消",
DefaultButton = ContentDialogButton.Close
};
var result = await dialog.ShowAsync();
if (result != ContentDialogResult.Primary)
{
return;
}
var snapshot = settingsFacade.Settings.LoadSnapshot<AppSettingsSnapshot>(SettingsScope.App);
snapshot.IsDevModeEnabled = true;
settingsFacade.Settings.SaveSnapshot(
SettingsScope.App,
snapshot,
changedKeys: [nameof(AppSettingsSnapshot.IsDevModeEnabled)]);
AppLogger.Info("DevMode", "Developer mode enabled via About page activation.");
_ = ShowMessageAsync("开发者模式", "已启用开发者模式。重新打开设置窗口即可看到开发者选项。");
if (HostContext is not null)
{
HostContext.RequestRestart("开发者模式已更改");
}
}
private static async Task ShowMessageAsync(string title, string message)
{
var dialog = new ContentDialog
{
Title = title,
Content = message,
CloseButtonText = "确定"
};
await dialog.ShowAsync();
}
}

View File

@@ -0,0 +1,89 @@
<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"
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"
IsClosable="False"
Severity="Warning"
Title="开发者模式"
Message="开发者模式仅供开发和调试用途。开发者不对以非开发用途使用此功能造成的任何后果负责。"
Margin="0,0,0,16" />
<ui:SettingsExpander Header="启用开发者模式"
Description="启用后可使用插件调试、开发者插件路径等高级功能">
<ui:SettingsExpander.IconSource>
<fi:SymbolIconSource Symbol="DeveloperBoard" />
</ui:SettingsExpander.IconSource>
<ui:SettingsExpander.Footer>
<ToggleSwitch IsChecked="{Binding IsDevModeEnabled}" />
</ui:SettingsExpander.Footer>
</ui:SettingsExpander>
<Separator Classes="settings-separator" />
<ui:SettingsExpander Header="开发者插件路径"
Description="指定开发中的插件目录路径,无需打包即可直接加载。多个路径用分号分隔。">
<ui:SettingsExpander.IconSource>
<fi:SymbolIconSource Symbol="FolderLink" />
</ui:SettingsExpander.IconSource>
<ui:SettingsExpanderItem>
<TextBox Text="{Binding DevPluginPath}"
Watermark="C:\path\to\plugin\bin\Debug\net10.0"
Width="360"
MinWidth="200" />
</ui:SettingsExpanderItem>
</ui:SettingsExpander>
<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" />
<Border Background="{DynamicResource ControlFillColorDefaultBrush}"
CornerRadius="8"
Padding="12,8">
<TextBlock FontFamily="Cascadia Code, Consolas, monospace"
FontSize="12"
Text="--dev-plugin &lt;path&gt; 或 -dp &lt;path&gt;"
TextWrapping="Wrap" />
</Border>
<TextBlock Text="环境变量:" FontWeight="SemiBold" Margin="0,8,0,0" />
<Border Background="{DynamicResource ControlFillColorDefaultBrush}"
CornerRadius="8"
Padding="12,8">
<TextBlock FontFamily="Cascadia Code, Consolas, monospace"
FontSize="12"
Text="LMD_DEV_PLUGIN=&lt;path&gt;"
TextWrapping="Wrap" />
</Border>
<TextBlock Text="其他参数:" 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 启用开发者模式" />
<TextBlock FontFamily="Cascadia Code, Consolas, monospace"
FontSize="12"
Text="--hot-reload / -hr 启用热重载(预留)" />
</StackPanel>
</Border>
</StackPanel>
</ui:SettingsExpanderItem>
</ui:SettingsExpander>
</StackPanel>
</ScrollViewer>
</UserControl>

View File

@@ -0,0 +1,30 @@
using LanMountainDesktop.PluginSdk;
using LanMountainDesktop.Services.Settings;
using LanMountainDesktop.ViewModels;
namespace LanMountainDesktop.Views.SettingsPages;
[SettingsPageInfo(
"dev",
"开发者",
SettingsPageCategory.Dev,
IconKey = "DeveloperBoard",
SortOrder = 0,
TitleLocalizationKey = "settings.dev.title",
DescriptionLocalizationKey = "settings.dev.description")]
public partial class DevSettingsPage : SettingsPageBase
{
public DevSettingsPage()
: this(new DevSettingsPageViewModel(HostSettingsFacadeProvider.GetOrCreate()))
{
}
public DevSettingsPage(DevSettingsPageViewModel viewModel)
{
ViewModel = viewModel;
DataContext = ViewModel;
InitializeComponent();
}
public DevSettingsPageViewModel ViewModel { get; }
}