mirror of
https://github.com/wwiinnddyy/LanMountainDesktop.git
synced 2026-08-21 04:31:20 +08:00
settings_re4
This commit is contained in:
@@ -0,0 +1,80 @@
|
||||
<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"
|
||||
x:Class="LanMountainDesktop.Views.SettingsPages.AboutSettingsPage"
|
||||
x:DataType="vm:AboutSettingsPageViewModel">
|
||||
<ScrollViewer VerticalScrollBarVisibility="Auto">
|
||||
<StackPanel Classes="settings-page-container">
|
||||
<TextBlock Classes="settings-section-title"
|
||||
Text="{Binding PageTitle}" />
|
||||
<TextBlock Classes="settings-section-description"
|
||||
Text="{Binding PageDescription}" />
|
||||
|
||||
<controls:SettingsSectionCard IconKey="Info"
|
||||
Title="{Binding AppInfoHeader}">
|
||||
<controls:SettingsSectionCard.CardContent>
|
||||
<StackPanel Spacing="14">
|
||||
<StackPanel Classes="settings-item">
|
||||
<TextBlock Classes="settings-item-label"
|
||||
Text="{Binding VersionLabel}" />
|
||||
<TextBlock Opacity="0.82"
|
||||
Text="{Binding VersionText}" />
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Classes="settings-item">
|
||||
<TextBlock Classes="settings-item-label"
|
||||
Text="{Binding RenderBackendLabel}" />
|
||||
<TextBlock Opacity="0.82"
|
||||
Text="{Binding RenderBackendText}" />
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</controls:SettingsSectionCard.CardContent>
|
||||
</controls:SettingsSectionCard>
|
||||
|
||||
<ui:SettingsExpander Classes="settings-expander-card"
|
||||
Header="{Binding UpdateHeader}"
|
||||
IsExpanded="True">
|
||||
<StackPanel Spacing="12">
|
||||
<controls:SettingsOptionCard IconKey="ArrowSync"
|
||||
Title="{Binding AutoCheckUpdatesLabel}">
|
||||
<controls:SettingsOptionCard.ActionContent>
|
||||
<ToggleSwitch IsChecked="{Binding AutoCheckUpdates}" />
|
||||
</controls:SettingsOptionCard.ActionContent>
|
||||
</controls:SettingsOptionCard>
|
||||
|
||||
<controls:SettingsOptionCard IconKey="ArrowSync"
|
||||
Title="{Binding IncludePrereleaseUpdatesLabel}">
|
||||
<controls:SettingsOptionCard.ActionContent>
|
||||
<ToggleSwitch IsChecked="{Binding IncludePrereleaseUpdates}" />
|
||||
</controls:SettingsOptionCard.ActionContent>
|
||||
</controls:SettingsOptionCard>
|
||||
|
||||
<controls:SettingsOptionCard IconKey="ArrowSync"
|
||||
Title="{Binding UpdateChannelLabel}">
|
||||
<controls:SettingsOptionCard.DetailsContent>
|
||||
<ComboBox ItemsSource="{Binding UpdateChannels}"
|
||||
SelectedItem="{Binding SelectedUpdateChannel}">
|
||||
<ComboBox.ItemTemplate>
|
||||
<DataTemplate x:DataType="vm:SelectionOption">
|
||||
<TextBlock Text="{Binding Label}" />
|
||||
</DataTemplate>
|
||||
</ComboBox.ItemTemplate>
|
||||
</ComboBox>
|
||||
</controls:SettingsOptionCard.DetailsContent>
|
||||
</controls:SettingsOptionCard>
|
||||
|
||||
<StackPanel Orientation="Horizontal"
|
||||
Spacing="12">
|
||||
<Button Command="{Binding CheckForUpdatesCommand}"
|
||||
Content="{Binding CheckForUpdatesButtonText}" />
|
||||
<TextBlock VerticalAlignment="Center"
|
||||
Opacity="0.76"
|
||||
Text="{Binding UpdateStatus}" />
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</ui:SettingsExpander>
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,30 @@
|
||||
using LanMountainDesktop.PluginSdk;
|
||||
using LanMountainDesktop.Services.Settings;
|
||||
using LanMountainDesktop.ViewModels;
|
||||
|
||||
namespace LanMountainDesktop.Views.SettingsPages;
|
||||
|
||||
[SettingsPageInfo(
|
||||
"about",
|
||||
"About",
|
||||
SettingsPageCategory.About,
|
||||
IconKey = "Info",
|
||||
SortOrder = 40,
|
||||
TitleLocalizationKey = "settings.about.title",
|
||||
DescriptionLocalizationKey = "settings.about.description")]
|
||||
public partial class AboutSettingsPage : SettingsPageBase
|
||||
{
|
||||
public AboutSettingsPage()
|
||||
: this(new AboutSettingsPageViewModel(HostSettingsFacadeProvider.GetOrCreate()))
|
||||
{
|
||||
}
|
||||
|
||||
public AboutSettingsPage(AboutSettingsPageViewModel viewModel)
|
||||
{
|
||||
ViewModel = viewModel;
|
||||
DataContext = ViewModel;
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
public AboutSettingsPageViewModel ViewModel { get; }
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
<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"
|
||||
x:Class="LanMountainDesktop.Views.SettingsPages.AppearanceSettingsPage"
|
||||
x:DataType="vm:AppearanceSettingsPageViewModel">
|
||||
<ScrollViewer VerticalScrollBarVisibility="Auto">
|
||||
<StackPanel Classes="settings-page-container">
|
||||
<TextBlock Classes="settings-section-title"
|
||||
Text="{Binding PageTitle}" />
|
||||
<TextBlock Classes="settings-section-description"
|
||||
Text="{Binding PageDescription}" />
|
||||
|
||||
<controls:SettingsOptionCard IconKey="DesignIdeas"
|
||||
Title="{Binding NightModeLabel}">
|
||||
<controls:SettingsOptionCard.ActionContent>
|
||||
<ToggleSwitch IsChecked="{Binding IsNightMode}" />
|
||||
</controls:SettingsOptionCard.ActionContent>
|
||||
</controls:SettingsOptionCard>
|
||||
|
||||
<controls:SettingsOptionCard IconKey="DesignIdeas"
|
||||
Title="{Binding UseSystemChromeLabel}">
|
||||
<controls:SettingsOptionCard.ActionContent>
|
||||
<ToggleSwitch IsChecked="{Binding UseSystemChrome}" />
|
||||
</controls:SettingsOptionCard.ActionContent>
|
||||
</controls:SettingsOptionCard>
|
||||
|
||||
<controls:SettingsOptionCard IconKey="DesignIdeas"
|
||||
Title="{Binding ThemeColorLabel}">
|
||||
<controls:SettingsOptionCard.DetailsContent>
|
||||
<TextBox Watermark="#AABBCC"
|
||||
Text="{Binding ThemeColor}" />
|
||||
</controls:SettingsOptionCard.DetailsContent>
|
||||
</controls:SettingsOptionCard>
|
||||
|
||||
<controls:SettingsSectionCard IconKey="DesignIdeas"
|
||||
Title="{Binding WallpaperHeader}">
|
||||
<controls:SettingsSectionCard.CardContent>
|
||||
<StackPanel Spacing="14">
|
||||
<StackPanel Classes="settings-item">
|
||||
<TextBlock Classes="settings-item-label"
|
||||
Text="{Binding WallpaperPathLabel}" />
|
||||
<TextBox IsReadOnly="True"
|
||||
Text="{Binding WallpaperPath}" />
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Classes="settings-item">
|
||||
<TextBlock Classes="settings-item-label"
|
||||
Text="{Binding WallpaperPlacementLabel}" />
|
||||
<ComboBox ItemsSource="{Binding WallpaperPlacements}"
|
||||
SelectedItem="{Binding SelectedWallpaperPlacement}">
|
||||
<ComboBox.ItemTemplate>
|
||||
<DataTemplate x:DataType="vm:SelectionOption">
|
||||
<TextBlock Text="{Binding Label}" />
|
||||
</DataTemplate>
|
||||
</ComboBox.ItemTemplate>
|
||||
</ComboBox>
|
||||
</StackPanel>
|
||||
|
||||
<Button HorizontalAlignment="Left"
|
||||
Click="OnBrowseWallpaperClick"
|
||||
Content="{Binding ImportWallpaperButtonText}" />
|
||||
</StackPanel>
|
||||
</controls:SettingsSectionCard.CardContent>
|
||||
</controls:SettingsSectionCard>
|
||||
|
||||
<controls:SettingsSectionCard IconKey="DesignIdeas"
|
||||
Title="{Binding ClockHeader}"
|
||||
Description="{Binding ClockDescription}">
|
||||
<controls:SettingsSectionCard.CardContent>
|
||||
<StackPanel Spacing="14">
|
||||
<controls:SettingsOptionCard IconKey="DesignIdeas"
|
||||
Title="{Binding ClockHeader}">
|
||||
<controls:SettingsOptionCard.ActionContent>
|
||||
<ToggleSwitch IsChecked="{Binding ShowClock}" />
|
||||
</controls:SettingsOptionCard.ActionContent>
|
||||
</controls:SettingsOptionCard>
|
||||
|
||||
<controls:SettingsOptionCard IconKey="DesignIdeas"
|
||||
Title="{Binding ClockFormatLabel}">
|
||||
<controls:SettingsOptionCard.DetailsContent>
|
||||
<ComboBox ItemsSource="{Binding ClockFormats}"
|
||||
SelectedItem="{Binding SelectedClockFormat}">
|
||||
<ComboBox.ItemTemplate>
|
||||
<DataTemplate x:DataType="vm:SelectionOption">
|
||||
<TextBlock Text="{Binding Label}" />
|
||||
</DataTemplate>
|
||||
</ComboBox.ItemTemplate>
|
||||
</ComboBox>
|
||||
</controls:SettingsOptionCard.DetailsContent>
|
||||
</controls:SettingsOptionCard>
|
||||
</StackPanel>
|
||||
</controls:SettingsSectionCard.CardContent>
|
||||
</controls:SettingsSectionCard>
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,54 @@
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Platform.Storage;
|
||||
using LanMountainDesktop.PluginSdk;
|
||||
using LanMountainDesktop.Services.Settings;
|
||||
using LanMountainDesktop.ViewModels;
|
||||
using System.Linq;
|
||||
|
||||
namespace LanMountainDesktop.Views.SettingsPages;
|
||||
|
||||
[SettingsPageInfo(
|
||||
"appearance",
|
||||
"Appearance",
|
||||
SettingsPageCategory.Appearance,
|
||||
IconKey = "DesignIdeas",
|
||||
SortOrder = 10,
|
||||
TitleLocalizationKey = "settings.appearance.title",
|
||||
DescriptionLocalizationKey = "settings.appearance.description")]
|
||||
public partial class AppearanceSettingsPage : SettingsPageBase
|
||||
{
|
||||
public AppearanceSettingsPage()
|
||||
: this(new AppearanceSettingsPageViewModel(HostSettingsFacadeProvider.GetOrCreate()))
|
||||
{
|
||||
}
|
||||
|
||||
public AppearanceSettingsPage(AppearanceSettingsPageViewModel viewModel)
|
||||
{
|
||||
ViewModel = viewModel;
|
||||
DataContext = ViewModel;
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
public AppearanceSettingsPageViewModel ViewModel { get; }
|
||||
|
||||
private async void OnBrowseWallpaperClick(object? sender, Avalonia.Interactivity.RoutedEventArgs e)
|
||||
{
|
||||
if (TopLevel.GetTopLevel(this)?.StorageProvider is not { } storageProvider)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var files = await storageProvider.OpenFilePickerAsync(new FilePickerOpenOptions
|
||||
{
|
||||
Title = ViewModel.FilePickerTitle,
|
||||
AllowMultiple = false
|
||||
});
|
||||
|
||||
var file = files.FirstOrDefault();
|
||||
var localPath = file?.TryGetLocalPath();
|
||||
if (!string.IsNullOrWhiteSpace(localPath))
|
||||
{
|
||||
await ViewModel.ImportWallpaperAsync(localPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
<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"
|
||||
x:Class="LanMountainDesktop.Views.SettingsPages.ComponentsSettingsPage"
|
||||
x:DataType="vm:ComponentsSettingsPageViewModel">
|
||||
<ScrollViewer VerticalScrollBarVisibility="Auto">
|
||||
<StackPanel Classes="settings-page-container">
|
||||
<TextBlock Classes="settings-section-title"
|
||||
Text="{Binding PageTitle}" />
|
||||
<TextBlock Classes="settings-section-description"
|
||||
Text="{Binding PageDescription}" />
|
||||
|
||||
<ui:SettingsExpander Classes="settings-expander-card"
|
||||
Header="{Binding GridHeader}"
|
||||
IsExpanded="True">
|
||||
<StackPanel Spacing="14">
|
||||
<StackPanel Classes="settings-item">
|
||||
<TextBlock Classes="settings-item-label"
|
||||
Text="{Binding ShortSideCellsLabel}" />
|
||||
<NumericUpDown Minimum="6"
|
||||
Maximum="96"
|
||||
Value="{Binding ShortSideCells}" />
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Classes="settings-item">
|
||||
<TextBlock Classes="settings-item-label"
|
||||
Text="{Binding EdgeInsetPercentLabel}" />
|
||||
<NumericUpDown Minimum="0"
|
||||
Maximum="30"
|
||||
Value="{Binding EdgeInsetPercent}" />
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Classes="settings-item">
|
||||
<TextBlock Classes="settings-item-label"
|
||||
Text="{Binding SpacingPresetLabel}" />
|
||||
<ComboBox ItemsSource="{Binding SpacingPresets}"
|
||||
SelectedItem="{Binding SelectedSpacingPreset}">
|
||||
<ComboBox.ItemTemplate>
|
||||
<DataTemplate x:DataType="vm:SelectionOption">
|
||||
<TextBlock Text="{Binding Label}" />
|
||||
</DataTemplate>
|
||||
</ComboBox.ItemTemplate>
|
||||
</ComboBox>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</ui:SettingsExpander>
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,30 @@
|
||||
using LanMountainDesktop.PluginSdk;
|
||||
using LanMountainDesktop.Services.Settings;
|
||||
using LanMountainDesktop.ViewModels;
|
||||
|
||||
namespace LanMountainDesktop.Views.SettingsPages;
|
||||
|
||||
[SettingsPageInfo(
|
||||
"components",
|
||||
"Components",
|
||||
SettingsPageCategory.Components,
|
||||
IconKey = "GridDots",
|
||||
SortOrder = 20,
|
||||
TitleLocalizationKey = "settings.components.title",
|
||||
DescriptionLocalizationKey = "settings.components.description")]
|
||||
public partial class ComponentsSettingsPage : SettingsPageBase
|
||||
{
|
||||
public ComponentsSettingsPage()
|
||||
: this(new ComponentsSettingsPageViewModel(HostSettingsFacadeProvider.GetOrCreate()))
|
||||
{
|
||||
}
|
||||
|
||||
public ComponentsSettingsPage(ComponentsSettingsPageViewModel viewModel)
|
||||
{
|
||||
ViewModel = viewModel;
|
||||
DataContext = ViewModel;
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
public ComponentsSettingsPageViewModel ViewModel { get; }
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
<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"
|
||||
x:Class="LanMountainDesktop.Views.SettingsPages.GeneralSettingsPage"
|
||||
x:DataType="vm:GeneralSettingsPageViewModel">
|
||||
<ScrollViewer VerticalScrollBarVisibility="Auto">
|
||||
<StackPanel Classes="settings-page-container">
|
||||
<TextBlock Classes="settings-section-title"
|
||||
Text="{Binding PageTitle}" />
|
||||
<TextBlock Classes="settings-section-description"
|
||||
Text="{Binding PageDescription}" />
|
||||
|
||||
<controls:SettingsOptionCard IconKey="Settings"
|
||||
Title="{Binding LanguageHeader}">
|
||||
<controls:SettingsOptionCard.DetailsContent>
|
||||
<ComboBox MinWidth="240"
|
||||
ItemsSource="{Binding Languages}"
|
||||
SelectedItem="{Binding SelectedLanguage}">
|
||||
<ComboBox.ItemTemplate>
|
||||
<DataTemplate x:DataType="vm:SelectionOption">
|
||||
<TextBlock Text="{Binding Label}" />
|
||||
</DataTemplate>
|
||||
</ComboBox.ItemTemplate>
|
||||
</ComboBox>
|
||||
</controls:SettingsOptionCard.DetailsContent>
|
||||
</controls:SettingsOptionCard>
|
||||
|
||||
<controls:SettingsOptionCard IconKey="Settings"
|
||||
Title="{Binding TimeZoneHeader}"
|
||||
Description="{Binding TimeZoneDescription}">
|
||||
<controls:SettingsOptionCard.DetailsContent>
|
||||
<ComboBox MinWidth="280"
|
||||
ItemsSource="{Binding TimeZones}"
|
||||
SelectedItem="{Binding SelectedTimeZone}">
|
||||
<ComboBox.ItemTemplate>
|
||||
<DataTemplate x:DataType="vm:TimeZoneOption">
|
||||
<TextBlock Text="{Binding Label}" />
|
||||
</DataTemplate>
|
||||
</ComboBox.ItemTemplate>
|
||||
</ComboBox>
|
||||
</controls:SettingsOptionCard.DetailsContent>
|
||||
</controls:SettingsOptionCard>
|
||||
|
||||
<controls:SettingsSectionCard IconKey="Info"
|
||||
Title="{Binding PreviewHeader}">
|
||||
<controls:SettingsSectionCard.CardContent>
|
||||
<Grid ColumnDefinitions="Auto,*"
|
||||
ColumnSpacing="16"
|
||||
RowDefinitions="Auto,Auto"
|
||||
RowSpacing="12">
|
||||
<TextBlock FontWeight="SemiBold"
|
||||
Text="{Binding PreviewTimeLabel}" />
|
||||
<TextBlock Grid.Column="1"
|
||||
Opacity="0.82"
|
||||
Text="{Binding PreviewTimeText}" />
|
||||
<TextBlock Grid.Row="1"
|
||||
FontWeight="SemiBold"
|
||||
Text="{Binding PreviewDateLabel}" />
|
||||
<TextBlock Grid.Row="1"
|
||||
Grid.Column="1"
|
||||
Opacity="0.82"
|
||||
Text="{Binding PreviewDateText}" />
|
||||
</Grid>
|
||||
</controls:SettingsSectionCard.CardContent>
|
||||
</controls:SettingsSectionCard>
|
||||
|
||||
<ui:SettingsExpander Classes="settings-expander-card"
|
||||
Header="{Binding RuntimeHeader}"
|
||||
Description="{Binding RuntimeDescription}"
|
||||
IsExpanded="True">
|
||||
<ui:SettingsExpander.Footer>
|
||||
<ComboBox MinWidth="240"
|
||||
ItemsSource="{Binding RenderModes}"
|
||||
SelectedItem="{Binding SelectedRenderMode}">
|
||||
<ComboBox.ItemTemplate>
|
||||
<DataTemplate x:DataType="vm:SelectionOption">
|
||||
<TextBlock Text="{Binding Label}" />
|
||||
</DataTemplate>
|
||||
</ComboBox.ItemTemplate>
|
||||
</ComboBox>
|
||||
</ui:SettingsExpander.Footer>
|
||||
</ui:SettingsExpander>
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,36 @@
|
||||
using LanMountainDesktop.PluginSdk;
|
||||
using LanMountainDesktop.Services.Settings;
|
||||
using LanMountainDesktop.ViewModels;
|
||||
|
||||
namespace LanMountainDesktop.Views.SettingsPages;
|
||||
|
||||
[SettingsPageInfo(
|
||||
"general",
|
||||
"General",
|
||||
SettingsPageCategory.General,
|
||||
IconKey = "Settings",
|
||||
SortOrder = 0,
|
||||
TitleLocalizationKey = "settings.general.title",
|
||||
DescriptionLocalizationKey = "settings.general.description")]
|
||||
public partial class GeneralSettingsPage : SettingsPageBase
|
||||
{
|
||||
public GeneralSettingsPage()
|
||||
: this(new GeneralSettingsPageViewModel(HostSettingsFacadeProvider.GetOrCreate()))
|
||||
{
|
||||
}
|
||||
|
||||
public GeneralSettingsPage(GeneralSettingsPageViewModel viewModel)
|
||||
{
|
||||
ViewModel = viewModel;
|
||||
ViewModel.RestartRequested += OnRestartRequested;
|
||||
DataContext = ViewModel;
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
public GeneralSettingsPageViewModel ViewModel { get; }
|
||||
|
||||
private void OnRestartRequested()
|
||||
{
|
||||
RequestRestart(ViewModel.RenderModeRestartMessage);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:vm="using:LanMountainDesktop.ViewModels"
|
||||
x:Class="LanMountainDesktop.Views.SettingsPages.GeneratedPluginSettingsPage"
|
||||
x:DataType="vm:PluginGeneratedSettingsPageViewModel">
|
||||
<ScrollViewer VerticalScrollBarVisibility="Auto">
|
||||
<StackPanel Classes="settings-page-container">
|
||||
<TextBlock Classes="settings-section-title"
|
||||
Text="{Binding Title}" />
|
||||
<TextBlock x:Name="DescriptionTextBlock"
|
||||
Classes="settings-section-description"
|
||||
Text="{Binding Description}" />
|
||||
|
||||
<StackPanel x:Name="DynamicOptionsHost"
|
||||
Spacing="0" />
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,226 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Avalonia.Controls;
|
||||
using LanMountainDesktop.Controls;
|
||||
using LanMountainDesktop.PluginSdk;
|
||||
using LanMountainDesktop.Services.Settings;
|
||||
using LanMountainDesktop.ViewModels;
|
||||
|
||||
namespace LanMountainDesktop.Views.SettingsPages;
|
||||
|
||||
public partial class GeneratedPluginSettingsPage : SettingsPageBase
|
||||
{
|
||||
public GeneratedPluginSettingsPage()
|
||||
: this(
|
||||
new PluginGeneratedSettingsPageViewModel(
|
||||
HostSettingsFacadeProvider.GetOrCreate().Settings,
|
||||
string.Empty,
|
||||
new PluginSettingsSectionRegistration("_preview", "preview", []),
|
||||
new PluginLocalizer(AppContext.BaseDirectory, "en-US")))
|
||||
{
|
||||
}
|
||||
|
||||
public GeneratedPluginSettingsPage(PluginGeneratedSettingsPageViewModel viewModel)
|
||||
{
|
||||
ViewModel = viewModel;
|
||||
DataContext = ViewModel;
|
||||
InitializeComponent();
|
||||
|
||||
if (DescriptionTextBlock is not null)
|
||||
{
|
||||
DescriptionTextBlock.IsVisible = !string.IsNullOrWhiteSpace(ViewModel.Description);
|
||||
}
|
||||
|
||||
BuildDynamicOptions();
|
||||
}
|
||||
|
||||
public PluginGeneratedSettingsPageViewModel ViewModel { get; }
|
||||
private void BuildDynamicOptions()
|
||||
{
|
||||
if (DynamicOptionsHost is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
DynamicOptionsHost.Children.Clear();
|
||||
foreach (var option in ViewModel.Section.Options)
|
||||
{
|
||||
DynamicOptionsHost.Children.Add(CreateOptionControl(option));
|
||||
}
|
||||
}
|
||||
|
||||
private Control CreateOptionControl(SettingsOptionDefinition option)
|
||||
{
|
||||
var title = ViewModel.Localizer.GetString(option.TitleLocalizationKey, option.TitleLocalizationKey);
|
||||
var description = string.IsNullOrWhiteSpace(option.DescriptionLocalizationKey)
|
||||
? null
|
||||
: ViewModel.Localizer.GetString(option.DescriptionLocalizationKey, option.DescriptionLocalizationKey);
|
||||
var card = new SettingsOptionCard
|
||||
{
|
||||
IconKey = "Settings",
|
||||
Title = title,
|
||||
Description = description
|
||||
};
|
||||
|
||||
switch (option.OptionType)
|
||||
{
|
||||
case SettingsOptionType.Toggle:
|
||||
card.ActionContent = CreateToggle(option);
|
||||
break;
|
||||
case SettingsOptionType.Number:
|
||||
card.DetailsContent = CreateNumber(option);
|
||||
break;
|
||||
case SettingsOptionType.Select:
|
||||
card.DetailsContent = CreateSelect(option);
|
||||
break;
|
||||
case SettingsOptionType.Path:
|
||||
card.DetailsContent = CreateText(option, "Path");
|
||||
break;
|
||||
case SettingsOptionType.List:
|
||||
card.DetailsContent = CreateText(option, "Comma-separated values");
|
||||
break;
|
||||
default:
|
||||
card.DetailsContent = CreateText(option, null);
|
||||
break;
|
||||
}
|
||||
|
||||
return card;
|
||||
}
|
||||
|
||||
private Control CreateToggle(SettingsOptionDefinition option)
|
||||
{
|
||||
var toggleSwitch = new ToggleSwitch
|
||||
{
|
||||
IsChecked = ViewModel.SettingsService.GetValue<bool?>(
|
||||
SettingsScope.Plugin,
|
||||
option.Key,
|
||||
ViewModel.PluginId,
|
||||
sectionId: ViewModel.Section.Id) ?? (option.DefaultValue as bool? ?? false)
|
||||
};
|
||||
|
||||
toggleSwitch.IsCheckedChanged += (_, _) =>
|
||||
{
|
||||
ViewModel.SettingsService.SetValue(
|
||||
SettingsScope.Plugin,
|
||||
option.Key,
|
||||
toggleSwitch.IsChecked == true,
|
||||
ViewModel.PluginId,
|
||||
sectionId: ViewModel.Section.Id,
|
||||
changedKeys: [option.Key]);
|
||||
};
|
||||
|
||||
return toggleSwitch;
|
||||
}
|
||||
|
||||
private Control CreateNumber(SettingsOptionDefinition option)
|
||||
{
|
||||
var currentValue = ViewModel.SettingsService.GetValue<double?>(
|
||||
SettingsScope.Plugin,
|
||||
option.Key,
|
||||
ViewModel.PluginId,
|
||||
sectionId: ViewModel.Section.Id);
|
||||
|
||||
var numeric = new NumericUpDown
|
||||
{
|
||||
Minimum = (decimal)(option.Minimum ?? 0d),
|
||||
Maximum = (decimal)(option.Maximum ?? 9999d),
|
||||
Value = (decimal)(currentValue ?? Convert.ToDouble(option.DefaultValue ?? 0d))
|
||||
};
|
||||
|
||||
numeric.ValueChanged += (_, _) =>
|
||||
{
|
||||
ViewModel.SettingsService.SetValue(
|
||||
SettingsScope.Plugin,
|
||||
option.Key,
|
||||
(double)(numeric.Value ?? 0m),
|
||||
ViewModel.PluginId,
|
||||
sectionId: ViewModel.Section.Id,
|
||||
changedKeys: [option.Key]);
|
||||
};
|
||||
|
||||
return numeric;
|
||||
}
|
||||
|
||||
private Control CreateSelect(SettingsOptionDefinition option)
|
||||
{
|
||||
var choices = option.Choices
|
||||
.Select(choice => new SelectionOption(
|
||||
choice.Value,
|
||||
ViewModel.Localizer.GetString(choice.TitleLocalizationKey, choice.TitleLocalizationKey)))
|
||||
.ToArray();
|
||||
|
||||
var comboBox = new ComboBox
|
||||
{
|
||||
ItemsSource = choices
|
||||
};
|
||||
|
||||
var currentValue = ViewModel.SettingsService.GetValue<string>(
|
||||
SettingsScope.Plugin,
|
||||
option.Key,
|
||||
ViewModel.PluginId,
|
||||
sectionId: ViewModel.Section.Id);
|
||||
comboBox.SelectedItem = choices.FirstOrDefault(choice =>
|
||||
string.Equals(choice.Value, currentValue ?? option.DefaultValue?.ToString(), StringComparison.OrdinalIgnoreCase));
|
||||
|
||||
comboBox.SelectionChanged += (_, _) =>
|
||||
{
|
||||
if (comboBox.SelectedItem is not SelectionOption selected)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ViewModel.SettingsService.SetValue(
|
||||
SettingsScope.Plugin,
|
||||
option.Key,
|
||||
selected.Value,
|
||||
ViewModel.PluginId,
|
||||
sectionId: ViewModel.Section.Id,
|
||||
changedKeys: [option.Key]);
|
||||
};
|
||||
|
||||
return comboBox;
|
||||
}
|
||||
|
||||
private Control CreateText(SettingsOptionDefinition option, string? watermark)
|
||||
{
|
||||
var currentValue = option.OptionType == SettingsOptionType.List
|
||||
? string.Join(
|
||||
", ",
|
||||
ViewModel.SettingsService.GetValue<IReadOnlyList<string>>(
|
||||
SettingsScope.Plugin,
|
||||
option.Key,
|
||||
ViewModel.PluginId,
|
||||
sectionId: ViewModel.Section.Id) ?? (option.DefaultValue as IReadOnlyList<string> ?? []))
|
||||
: ViewModel.SettingsService.GetValue<string>(
|
||||
SettingsScope.Plugin,
|
||||
option.Key,
|
||||
ViewModel.PluginId,
|
||||
sectionId: ViewModel.Section.Id) ?? option.DefaultValue?.ToString() ?? string.Empty;
|
||||
|
||||
var textBox = new TextBox
|
||||
{
|
||||
Watermark = watermark,
|
||||
Text = currentValue
|
||||
};
|
||||
|
||||
textBox.LostFocus += (_, _) =>
|
||||
{
|
||||
object value = option.OptionType == SettingsOptionType.List
|
||||
? textBox.Text?
|
||||
.Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries)
|
||||
.ToArray() ?? []
|
||||
: textBox.Text ?? string.Empty;
|
||||
|
||||
ViewModel.SettingsService.SetValue(
|
||||
SettingsScope.Plugin,
|
||||
option.Key,
|
||||
value,
|
||||
ViewModel.PluginId,
|
||||
sectionId: ViewModel.Section.Id,
|
||||
changedKeys: [option.Key]);
|
||||
};
|
||||
|
||||
return textBox;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:vm="using:LanMountainDesktop.ViewModels"
|
||||
x:Class="LanMountainDesktop.Views.SettingsPages.PluginsSettingsPage"
|
||||
x:Name="Root"
|
||||
x:DataType="vm:PluginsSettingsPageViewModel">
|
||||
<ScrollViewer VerticalScrollBarVisibility="Auto">
|
||||
<StackPanel Classes="settings-page-container">
|
||||
<TextBlock Classes="settings-section-title"
|
||||
Text="{Binding PageTitle}" />
|
||||
<TextBlock Classes="settings-section-description"
|
||||
Text="{Binding PageDescription}" />
|
||||
|
||||
<StackPanel Orientation="Horizontal"
|
||||
Spacing="12"
|
||||
Margin="0,0,0,18">
|
||||
<Button Command="{Binding RefreshCommand}"
|
||||
Content="{Binding RefreshButtonText}" />
|
||||
<TextBlock VerticalAlignment="Center"
|
||||
Opacity="0.76"
|
||||
Text="{Binding StatusMessage}" />
|
||||
</StackPanel>
|
||||
|
||||
<TextBlock Classes="settings-subsection-title"
|
||||
Text="{Binding InstalledHeader}" />
|
||||
|
||||
<ItemsControl ItemsSource="{Binding InstalledPlugins}">
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate x:DataType="vm:InstalledPluginItemViewModel">
|
||||
<Border Classes="settings-list-item">
|
||||
<Grid Classes="settings-list-actions"
|
||||
ColumnDefinitions="*,Auto,Auto">
|
||||
<StackPanel>
|
||||
<TextBlock FontWeight="SemiBold"
|
||||
Text="{Binding Name}" />
|
||||
<TextBlock Opacity="0.76"
|
||||
FontSize="12"
|
||||
Text="{Binding Description}" />
|
||||
<TextBlock Opacity="0.58"
|
||||
FontSize="11"
|
||||
Text="{Binding Version}" />
|
||||
</StackPanel>
|
||||
<ToggleSwitch Grid.Column="1"
|
||||
IsChecked="{Binding IsEnabled}"
|
||||
Command="{Binding #Root.DataContext.TogglePluginCommand}"
|
||||
CommandParameter="{Binding}" />
|
||||
<Button Grid.Column="2"
|
||||
Command="{Binding #Root.DataContext.DeletePluginCommand}"
|
||||
CommandParameter="{Binding}"
|
||||
Content="{Binding #Root.DataContext.DeleteButtonText}" />
|
||||
</Grid>
|
||||
</Border>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
|
||||
<TextBlock Classes="settings-subsection-title"
|
||||
Text="{Binding MarketplaceHeader}" />
|
||||
|
||||
<ItemsControl ItemsSource="{Binding MarketPlugins}">
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate x:DataType="vm:PluginMarketItemViewModel">
|
||||
<Border Classes="settings-list-item">
|
||||
<Grid Classes="settings-list-actions"
|
||||
ColumnDefinitions="*,Auto">
|
||||
<StackPanel>
|
||||
<TextBlock FontWeight="SemiBold"
|
||||
Text="{Binding Name}" />
|
||||
<TextBlock Opacity="0.76"
|
||||
FontSize="12"
|
||||
Text="{Binding Description}" />
|
||||
<TextBlock Opacity="0.58"
|
||||
FontSize="11"
|
||||
Text="{Binding Version}" />
|
||||
</StackPanel>
|
||||
<Button Grid.Column="1"
|
||||
Command="{Binding #Root.DataContext.InstallPluginCommand}"
|
||||
CommandParameter="{Binding}"
|
||||
Content="{Binding #Root.DataContext.InstallButtonText}" />
|
||||
</Grid>
|
||||
</Border>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,41 @@
|
||||
using LanMountainDesktop.PluginSdk;
|
||||
using LanMountainDesktop.Services.Settings;
|
||||
using LanMountainDesktop.ViewModels;
|
||||
|
||||
namespace LanMountainDesktop.Views.SettingsPages;
|
||||
|
||||
[SettingsPageInfo(
|
||||
"plugins",
|
||||
"Plugins",
|
||||
SettingsPageCategory.Plugins,
|
||||
IconKey = "PuzzlePiece",
|
||||
SortOrder = 30,
|
||||
TitleLocalizationKey = "settings.plugins.title",
|
||||
DescriptionLocalizationKey = "settings.plugins.description")]
|
||||
public partial class PluginsSettingsPage : SettingsPageBase
|
||||
{
|
||||
public PluginsSettingsPage()
|
||||
: this(new PluginsSettingsPageViewModel(HostSettingsFacadeProvider.GetOrCreate()))
|
||||
{
|
||||
}
|
||||
|
||||
public PluginsSettingsPage(PluginsSettingsPageViewModel viewModel)
|
||||
{
|
||||
ViewModel = viewModel;
|
||||
ViewModel.RestartRequested += OnRestartRequested;
|
||||
DataContext = ViewModel;
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
public PluginsSettingsPageViewModel ViewModel { get; }
|
||||
|
||||
public override async void OnNavigatedTo(object? parameter)
|
||||
{
|
||||
await ViewModel.InitializeAsync();
|
||||
}
|
||||
|
||||
private void OnRestartRequested()
|
||||
{
|
||||
RequestRestart(ViewModel.RestartRequiredMessage);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user