mirror of
https://github.com/wwiinnddyy/LanMountainDesktop.git
synced 2026-06-22 00:54:26 +08:00
settings_re9
This commit is contained in:
@@ -0,0 +1,142 @@
|
||||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:vm="using:LanMountainDesktop.ViewModels"
|
||||
xmlns:mdxaml="https://github.com/whistyun/Markdown.Avalonia"
|
||||
xmlns:helpers="using:LanMountainDesktop.Helpers"
|
||||
xmlns:fi="using:FluentIcons.Avalonia.Fluent"
|
||||
x:Class="LanMountainDesktop.Views.SettingsPages.PluginMarketDetailDrawer"
|
||||
x:DataType="vm:PluginMarketDetailViewModel">
|
||||
<ScrollViewer VerticalScrollBarVisibility="Auto">
|
||||
<StackPanel Classes="settings-page-container"
|
||||
Margin="0,0,0,8">
|
||||
<Border Classes="settings-section-card">
|
||||
<Grid ColumnDefinitions="Auto,*,Auto"
|
||||
ColumnSpacing="14">
|
||||
<Border Classes="settings-section-card-icon-host"
|
||||
Width="64"
|
||||
Height="64"
|
||||
Padding="0"
|
||||
VerticalAlignment="Center">
|
||||
<Grid>
|
||||
<Image IsVisible="{Binding Item.HasIcon}"
|
||||
Source="{Binding Item.IconBitmap}"
|
||||
Stretch="UniformToFill" />
|
||||
<TextBlock IsVisible="{Binding !Item.HasIcon}"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
FontSize="20"
|
||||
FontWeight="SemiBold"
|
||||
Text="{Binding Item.IconFallbackText}" />
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
<StackPanel Grid.Column="1"
|
||||
Spacing="4"
|
||||
VerticalAlignment="Center">
|
||||
<TextBlock Classes="settings-card-header"
|
||||
Margin="0"
|
||||
Text="{Binding Item.Name}" />
|
||||
<TextBlock Classes="settings-item-description"
|
||||
Text="{Binding Item.DeveloperInfo}" />
|
||||
</StackPanel>
|
||||
|
||||
<Button Grid.Column="2"
|
||||
Classes="plugin-market-icon-button"
|
||||
VerticalAlignment="Center"
|
||||
Command="{Binding PerformPrimaryActionCommand}"
|
||||
IsEnabled="{Binding Item.IsActionEnabled}"
|
||||
ToolTip.Tip="{Binding Item.ActionTooltip}">
|
||||
<fi:SymbolIcon Symbol="{Binding Item.ActionSymbol}" />
|
||||
</Button>
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
<Border Classes="settings-section-card">
|
||||
<StackPanel Spacing="12">
|
||||
<Grid ColumnDefinitions="Auto,*"
|
||||
ColumnSpacing="12">
|
||||
<TextBlock Classes="settings-item-label"
|
||||
Text="{Binding VersionLabel}" />
|
||||
<TextBlock Grid.Column="1"
|
||||
Classes="settings-item-description"
|
||||
Text="{Binding Item.Version}" />
|
||||
</Grid>
|
||||
<Grid ColumnDefinitions="Auto,*"
|
||||
ColumnSpacing="12">
|
||||
<TextBlock Classes="settings-item-label"
|
||||
Text="{Binding PublisherLabel}" />
|
||||
<TextBlock Grid.Column="1"
|
||||
Classes="settings-item-description"
|
||||
Text="{Binding Item.DeveloperInfo}" />
|
||||
</Grid>
|
||||
<Grid ColumnDefinitions="Auto,*"
|
||||
ColumnSpacing="12">
|
||||
<TextBlock Classes="settings-item-label"
|
||||
Text="{Binding MinHostVersionLabel}" />
|
||||
<TextBlock Grid.Column="1"
|
||||
Classes="settings-item-description"
|
||||
Text="{Binding Item.MinHostVersion}" />
|
||||
</Grid>
|
||||
<Grid ColumnDefinitions="Auto,*"
|
||||
ColumnSpacing="12">
|
||||
<TextBlock Classes="settings-item-label"
|
||||
Text="{Binding ApiVersionLabel}" />
|
||||
<TextBlock Grid.Column="1"
|
||||
Classes="settings-item-description"
|
||||
Text="{Binding Item.ApiVersion}" />
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
||||
<Border Classes="settings-section-card">
|
||||
<StackPanel Spacing="12">
|
||||
<TextBlock Classes="settings-card-header"
|
||||
Margin="0"
|
||||
Text="{Binding ReadmeHeader}" />
|
||||
|
||||
<TextBlock Classes="settings-item-description"
|
||||
IsVisible="{Binding IsReadmeLoading}"
|
||||
Text="{Binding ReadmeLoadingText}" />
|
||||
<TextBlock Classes="settings-item-description"
|
||||
IsVisible="{Binding HasReadmeError}"
|
||||
Text="{Binding ReadmeError}"
|
||||
TextWrapping="Wrap" />
|
||||
<mdxaml:MarkdownScrollViewer IsVisible="{Binding HasReadmeContent}"
|
||||
Markdown="{Binding ReadmeMarkdown}"
|
||||
Engine="{x:Static helpers:PluginMarketMarkdownHelper.Engine}" />
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
||||
<Border Classes="settings-section-card">
|
||||
<StackPanel Spacing="12">
|
||||
<TextBlock Classes="settings-card-header"
|
||||
Margin="0"
|
||||
Text="{Binding DependenciesHeader}" />
|
||||
|
||||
<TextBlock Classes="settings-item-description"
|
||||
IsVisible="{Binding !HasDependencies}"
|
||||
Text="{Binding EmptyDependenciesText}"
|
||||
TextWrapping="Wrap" />
|
||||
|
||||
<ItemsControl IsVisible="{Binding HasDependencies}"
|
||||
ItemsSource="{Binding Dependencies}">
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<Border Classes="settings-list-item">
|
||||
<StackPanel Spacing="4">
|
||||
<TextBlock Classes="settings-item-label"
|
||||
Text="{Binding Id}" />
|
||||
<TextBlock Classes="settings-item-description"
|
||||
Text="{Binding AssemblyName}" />
|
||||
<TextBlock Classes="settings-item-description"
|
||||
Text="{Binding Version, StringFormat=v{0}}" />
|
||||
</StackPanel>
|
||||
</Border>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,18 @@
|
||||
using Avalonia.Controls;
|
||||
using LanMountainDesktop.ViewModels;
|
||||
|
||||
namespace LanMountainDesktop.Views.SettingsPages;
|
||||
|
||||
public partial class PluginMarketDetailDrawer : UserControl
|
||||
{
|
||||
public PluginMarketDetailDrawer()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
public PluginMarketDetailDrawer(PluginMarketDetailViewModel viewModel)
|
||||
{
|
||||
DataContext = viewModel;
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
<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.PluginMarketSettingsPage"
|
||||
x:Name="Root"
|
||||
x:DataType="vm:PluginMarketSettingsPageViewModel">
|
||||
<ScrollViewer VerticalScrollBarVisibility="Auto">
|
||||
<StackPanel Classes="settings-page-container">
|
||||
<ui:SettingsExpander Header="{Binding RefreshButtonText}"
|
||||
Description="{Binding StatusMessage}">
|
||||
<ui:SettingsExpander.IconSource>
|
||||
<fi:SymbolIconSource Symbol="ShoppingBag" />
|
||||
</ui:SettingsExpander.IconSource>
|
||||
<ui:SettingsExpander.Footer>
|
||||
<Grid ColumnDefinitions="*,Auto"
|
||||
ColumnSpacing="12">
|
||||
<TextBox Text="{Binding SearchText}"
|
||||
Watermark="{Binding SearchPlaceholder}" />
|
||||
<Button Grid.Column="1"
|
||||
Command="{Binding RefreshCommand}"
|
||||
Content="{Binding RefreshButtonText}" />
|
||||
</Grid>
|
||||
</ui:SettingsExpander.Footer>
|
||||
</ui:SettingsExpander>
|
||||
|
||||
<TextBlock Classes="settings-item-description"
|
||||
IsVisible="{Binding ShowEmptyState}"
|
||||
Margin="0,4,0,14"
|
||||
Text="{Binding EmptyStateText}"
|
||||
TextWrapping="Wrap" />
|
||||
|
||||
<ListBox ItemsSource="{Binding FilteredPlugins}"
|
||||
BorderThickness="0"
|
||||
Padding="0"
|
||||
Background="Transparent">
|
||||
<ListBox.Styles>
|
||||
<Style Selector="ListBoxItem">
|
||||
<Setter Property="Padding" Value="0" />
|
||||
<Setter Property="Margin" Value="0,0,0,10" />
|
||||
<Setter Property="Background" Value="Transparent" />
|
||||
<Setter Property="BorderThickness" Value="0" />
|
||||
</Style>
|
||||
</ListBox.Styles>
|
||||
<ListBox.ItemTemplate>
|
||||
<DataTemplate x:DataType="vm:PluginMarketItemViewModel">
|
||||
<Border Classes="settings-list-item">
|
||||
<Grid ColumnDefinitions="Auto,*,Auto"
|
||||
ColumnSpacing="14">
|
||||
<Border Classes="settings-section-card-icon-host"
|
||||
Width="52"
|
||||
Height="52"
|
||||
Padding="0"
|
||||
VerticalAlignment="Center">
|
||||
<Grid>
|
||||
<Image IsVisible="{Binding HasIcon}"
|
||||
Source="{Binding IconBitmap}"
|
||||
Stretch="UniformToFill" />
|
||||
<TextBlock IsVisible="{Binding !HasIcon}"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
FontSize="18"
|
||||
FontWeight="SemiBold"
|
||||
Text="{Binding IconFallbackText}" />
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
<Button Grid.Column="1"
|
||||
Classes="plugin-market-row-button"
|
||||
Command="{Binding #Root.DataContext.OpenDetailsCommand}"
|
||||
CommandParameter="{Binding}">
|
||||
<StackPanel Spacing="4"
|
||||
HorizontalAlignment="Stretch">
|
||||
<TextBlock Classes="settings-item-label"
|
||||
Text="{Binding Name}" />
|
||||
<TextBlock Classes="settings-item-description"
|
||||
Text="{Binding DeveloperInfo}" />
|
||||
</StackPanel>
|
||||
</Button>
|
||||
|
||||
<Button Grid.Column="2"
|
||||
Classes="plugin-market-icon-button"
|
||||
VerticalAlignment="Center"
|
||||
Command="{Binding #Root.DataContext.ExecutePrimaryActionCommand}"
|
||||
CommandParameter="{Binding}"
|
||||
IsEnabled="{Binding IsActionEnabled}"
|
||||
ToolTip.Tip="{Binding ActionTooltip}">
|
||||
<fi:SymbolIcon Symbol="{Binding ActionSymbol}" />
|
||||
</Button>
|
||||
</Grid>
|
||||
</Border>
|
||||
</DataTemplate>
|
||||
</ListBox.ItemTemplate>
|
||||
</ListBox>
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,63 @@
|
||||
using LanMountainDesktop.PluginSdk;
|
||||
using LanMountainDesktop.Services;
|
||||
using LanMountainDesktop.Services.PluginMarket;
|
||||
using LanMountainDesktop.Services.Settings;
|
||||
using LanMountainDesktop.ViewModels;
|
||||
|
||||
namespace LanMountainDesktop.Views.SettingsPages;
|
||||
|
||||
[SettingsPageInfo(
|
||||
"plugin-market",
|
||||
"Plugin Market",
|
||||
SettingsPageCategory.PluginMarket,
|
||||
IconKey = "ShoppingBag",
|
||||
SortOrder = 35,
|
||||
TitleLocalizationKey = "settings.plugin_market.title",
|
||||
DescriptionLocalizationKey = "settings.plugin_market.subtitle")]
|
||||
public partial class PluginMarketSettingsPage : SettingsPageBase
|
||||
{
|
||||
public PluginMarketSettingsPage()
|
||||
: this(CreateDefaultViewModel())
|
||||
{
|
||||
}
|
||||
|
||||
public PluginMarketSettingsPage(PluginMarketSettingsPageViewModel viewModel)
|
||||
{
|
||||
ViewModel = viewModel;
|
||||
ViewModel.RestartRequested += OnRestartRequested;
|
||||
ViewModel.DetailsRequested += OnDetailsRequested;
|
||||
DataContext = ViewModel;
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
public PluginMarketSettingsPageViewModel ViewModel { get; }
|
||||
|
||||
public override async void OnNavigatedTo(object? parameter)
|
||||
{
|
||||
await ViewModel.InitializeAsync();
|
||||
}
|
||||
|
||||
private static PluginMarketSettingsPageViewModel CreateDefaultViewModel()
|
||||
{
|
||||
var settingsFacade = HostSettingsFacadeProvider.GetOrCreate();
|
||||
var localizationService = new LocalizationService();
|
||||
return new PluginMarketSettingsPageViewModel(
|
||||
settingsFacade,
|
||||
localizationService,
|
||||
new AirAppMarketIconService(),
|
||||
new AirAppMarketReadmeService());
|
||||
}
|
||||
|
||||
private void OnRestartRequested(string? reason)
|
||||
{
|
||||
RequestRestart(reason ?? ViewModel.RestartRequiredMessage);
|
||||
}
|
||||
|
||||
private async void OnDetailsRequested(PluginMarketItemViewModel item)
|
||||
{
|
||||
var detailViewModel = ViewModel.CreateDetailViewModel(item);
|
||||
var drawer = new PluginMarketDetailDrawer(detailViewModel);
|
||||
OpenDrawer(drawer, detailViewModel.DrawerTitle);
|
||||
await detailViewModel.InitializeAsync();
|
||||
}
|
||||
}
|
||||
@@ -9,8 +9,6 @@
|
||||
x:DataType="vm:PluginsSettingsPageViewModel">
|
||||
<ScrollViewer VerticalScrollBarVisibility="Auto">
|
||||
<StackPanel Classes="settings-page-container">
|
||||
|
||||
<!-- 刷新按钮和状态 -->
|
||||
<ui:SettingsExpander Header="{Binding RefreshButtonText}"
|
||||
Description="{Binding StatusMessage}">
|
||||
<ui:SettingsExpander.IconSource>
|
||||
@@ -24,7 +22,6 @@
|
||||
|
||||
<Separator Classes="settings-separator" />
|
||||
|
||||
<!-- 已安装插件分组 -->
|
||||
<controls:IconText Icon="PuzzleCube"
|
||||
Text="{Binding InstalledHeader}"
|
||||
Margin="0,0,0,4" />
|
||||
@@ -56,37 +53,6 @@
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
|
||||
<Separator Classes="settings-separator" />
|
||||
|
||||
<!-- 市场插件分组 -->
|
||||
<controls:IconText Icon="ShoppingBag"
|
||||
Text="{Binding MarketplaceHeader}"
|
||||
Margin="0,0,0,4" />
|
||||
|
||||
<ItemsControl ItemsSource="{Binding MarketPlugins}">
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate x:DataType="vm:PluginMarketItemViewModel">
|
||||
<ui:SettingsExpander>
|
||||
<ui:SettingsExpander.IconSource>
|
||||
<fi:SymbolIconSource Symbol="ShoppingBag" />
|
||||
</ui:SettingsExpander.IconSource>
|
||||
<ui:SettingsExpander.Header>
|
||||
<StackPanel>
|
||||
<TextBlock FontWeight="SemiBold" Text="{Binding Name}" />
|
||||
<TextBlock Opacity="0.76" FontSize="12" Text="{Binding Description}" />
|
||||
</StackPanel>
|
||||
</ui:SettingsExpander.Header>
|
||||
<ui:SettingsExpander.Footer>
|
||||
<Button Command="{Binding #Root.DataContext.InstallPluginCommand}"
|
||||
CommandParameter="{Binding}"
|
||||
Content="{Binding #Root.DataContext.InstallButtonText}" />
|
||||
</ui:SettingsExpander.Footer>
|
||||
</ui:SettingsExpander>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
</UserControl>
|
||||
|
||||
@@ -638,6 +638,7 @@ public partial class SettingsWindow : Window, ISettingsPageHostContext
|
||||
"Apps" => Symbol.Apps,
|
||||
"GridDots" => Symbol.GridDots,
|
||||
"PuzzlePiece" => Symbol.PuzzlePiece,
|
||||
"ShoppingBag" => Symbol.ShoppingBag,
|
||||
"Info" => Symbol.Info,
|
||||
"ArrowSync" => Symbol.ArrowSync,
|
||||
_ => Symbol.Settings
|
||||
|
||||
Reference in New Issue
Block a user