feat: Added a settings page.

This commit is contained in:
real-zony 2024-06-28 15:07:06 +08:00
parent 5ccd8a7c53
commit 4f15d06e63
14 changed files with 201 additions and 46 deletions

11
Directory.Build.props Normal file
View File

@ -0,0 +1,11 @@
<Project>
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<Version>5.0.0.0</Version>
<Authors>Zony(real-zony)</Authors>
<RepositoryUrl>https://github.com/real-zony/ZonyLrcToolsX</RepositoryUrl>
</PropertyGroup>
</Project>

View File

@ -3,10 +3,6 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
<AssemblyVersion>0.0.0.1</AssemblyVersion>
<FileVersion>0.0.0.1</FileVersion>
<PackageVersion>0.0.0.1</PackageVersion>
<Version>0.0.0.1</Version>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@ -4,7 +4,6 @@
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<Version>4.0.0.58</Version>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@ -14,7 +14,20 @@
<Application.Resources> <Application.Resources>
<ResourceDictionary> <ResourceDictionary>
<ic:SymbolIconSource x:Key="OpenIcon" Symbol="Open" />
<ic:SymbolIconSource x:Key="CodeIcon" Symbol="Code" />
<ic:SymbolIconSource x:Key="ChatHelpIcon" Symbol="ChatHelp" />
<ic:SymbolIconSource x:Key="SettingsIcon" Symbol="Settings" />
<ic:SymbolIconSource x:Key="DownloadIcon" Symbol="ArrowDownload" />
<ic:SymbolIconSource x:Key="TagIcon" Symbol="Tag" />
<FontFamily x:Key="GlobalFontFamily">Microsoft YaHei, Simsun, Arial</FontFamily> <FontFamily x:Key="GlobalFontFamily">Microsoft YaHei, Simsun, Arial</FontFamily>
<ControlTheme x:Key="FluentBodyStrongTextBlockStyle"
BasedOn="{StaticResource BodyStrongTextBlockStyle}" TargetType="TextBlock">
<Setter Property="LineHeight" Value="20" />
<Setter Property="ClipToBounds" Value="False" />
</ControlTheme>
</ResourceDictionary> </ResourceDictionary>
</Application.Resources> </Application.Resources>

View File

@ -4,26 +4,25 @@ using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Markup.Xaml; using Avalonia.Markup.Xaml;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using ZonyLrcTools.Common.Infrastructure.DependencyInject; using ZonyLrcTools.Common.Infrastructure.DependencyInject;
using ZonyLrcTools.Common.Infrastructure.Network;
using ZonyLrcTools.Desktop.ViewModels; using ZonyLrcTools.Desktop.ViewModels;
using ZonyLrcTools.Desktop.Views; using ZonyLrcTools.Desktop.Views;
namespace ZonyLrcTools.Desktop; namespace ZonyLrcTools.Desktop;
public partial class App : Application public class App : Application
{ {
public new static App Current => (App)Application.Current!; public new static App Current => (App)Application.Current!;
public IServiceProvider Services { get; } public IServiceProvider Services { get; } = ConfigureServices();
public App()
{
Services = ConfigureServices();
}
private static IServiceProvider ConfigureServices() private static IServiceProvider ConfigureServices()
{ {
var services = new ServiceCollection(); var services = new ServiceCollection();
services.BeginAutoDependencyInject<Program>();
services.BeginAutoDependencyInject<IWarpHttpClient>();
services.ConfigureConfiguration(); services.ConfigureConfiguration();
services.ConfigureToolService();
return services.BuildServiceProvider(); return services.BuildServiceProvider();
} }

View File

@ -0,0 +1,33 @@
using System.Diagnostics;
using System.Runtime.InteropServices;
namespace ZonyLrcTools.Desktop.Helpers;
public static class UrlHelper
{
public static void OpenLink(string url)
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
using var process = Process.Start(new ProcessStartInfo
{
FileName = "/bin/sh",
Arguments = $"-c \"xdg-open {url.Replace("\"", "\\\"")}\"",
RedirectStandardOutput = true,
UseShellExecute = false,
CreateNoWindow = true,
WindowStyle = ProcessWindowStyle.Hidden
});
}
else
{
using var process = Process.Start(new ProcessStartInfo
{
FileName = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? url : "open",
Arguments = RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? url : "",
CreateNoWindow = true,
UseShellExecute = RuntimeInformation.IsOSPlatform(OSPlatform.Windows)
});
}
}
}

View File

@ -0,0 +1,35 @@
using System;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using ZonyLrcTools.Common.Infrastructure.DependencyInject;
using ZonyLrcTools.Common.Infrastructure.Logging;
namespace ZonyLrcTools.Desktop.Infrastructure.Logging;
public class SerilogWarpLogger(ILogger<SerilogWarpLogger> logger) : IWarpLogger, ITransientDependency
{
public Task DebugAsync(string message, Exception? exception = null)
{
logger.LogDebug(message, exception);
return Task.CompletedTask;
}
public Task InfoAsync(string message, Exception? exception = null)
{
logger.LogInformation(message, exception);
return Task.CompletedTask;
}
public Task WarnAsync(string message, Exception? exception = null)
{
logger.LogWarning(message, exception);
return Task.CompletedTask;
}
public Task ErrorAsync(string message, Exception? exception = null)
{
logger.LogError(message, exception);
return Task.CompletedTask;
}
}

View File

@ -5,20 +5,36 @@
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="ZonyLrcTools.Desktop.Pages.SettingsPage" x:Class="ZonyLrcTools.Desktop.Pages.SettingsPage"
xmlns:ui="using:FluentAvalonia.UI.Controls" xmlns:ui="using:FluentAvalonia.UI.Controls"
xmlns:viewModels="clr-namespace:ZonyLrcTools.Desktop.ViewModels"
xmlns:settings="clr-namespace:ZonyLrcTools.Desktop.ViewModels.Settings" xmlns:settings="clr-namespace:ZonyLrcTools.Desktop.ViewModels.Settings"
x:DataType="settings:LyricsSettingsViewModel"> x:DataType="settings:LyricsSettingsViewModel">
<ScrollViewer> <ScrollViewer>
<StackPanel Spacing="20"> <StackPanel Orientation="Vertical" Margin="24" Spacing="8">
<!-- Global Configuration --> <Grid ColumnDefinitions="Auto,*,Auto,Auto">
<ui:SettingsExpander Header="Global Lyrics Configuration" Description="Configure global settings for lyrics"> <Image Width="64" Height="64" HorizontalAlignment="Left"
<ui:SettingsExpanderItem Content="Merge Bilingual Lyrics"> Source="/Assets/logo.ico"
RenderOptions.BitmapInterpolationMode="HighQuality" />
<StackPanel Grid.Column="1"
Margin="12,0,0,0" VerticalAlignment="Center">
<TextBlock Theme="{StaticResource FluentSubtitleTextBlockStyle}" Text="ZonyLrcToolsX" />
<TextBlock Theme="{StaticResource FluentBodyTextBlockStyle}"
Foreground="{DynamicResource TextFillColorSecondaryBrush}"
Text="{Binding Version, StringFormat='Version {0}'}" />
</StackPanel>
</Grid>
<TextBlock Margin="0,20,0,0"
Theme="{StaticResource FluentBodyStrongTextBlockStyle}"
Text="软件设置" />
<!-- 全局设置 -->
<ui:SettingsExpander Header="全局设置" Description="配置软件的全局设置" IconSource="{StaticResource SettingsIcon}">
<ui:SettingsExpanderItem Content="是否合并歌词为一行">
<ui:SettingsExpanderItem.Footer> <ui:SettingsExpanderItem.Footer>
<ToggleSwitch IsChecked="{Binding Config.IsOneLine}" /> <ToggleSwitch IsChecked="{Binding Config.IsOneLine}" />
</ui:SettingsExpanderItem.Footer> </ui:SettingsExpanderItem.Footer>
</ui:SettingsExpanderItem> </ui:SettingsExpanderItem>
<ui:SettingsExpanderItem Content="Line Break Format"> <ui:SettingsExpanderItem Content="换行符">
<ui:SettingsExpanderItem.Footer> <ui:SettingsExpanderItem.Footer>
<ComboBox SelectedItem="{Binding Config.LineBreak}"> <ComboBox SelectedItem="{Binding Config.LineBreak}">
<ComboBoxItem Content="Windows" /> <ComboBoxItem Content="Windows" />
@ -28,19 +44,19 @@
</ui:SettingsExpanderItem.Footer> </ui:SettingsExpanderItem.Footer>
</ui:SettingsExpanderItem> </ui:SettingsExpanderItem>
<ui:SettingsExpanderItem Content="Enable Translation"> <ui:SettingsExpanderItem Content="启用翻译歌词">
<ui:SettingsExpanderItem.Footer> <ui:SettingsExpanderItem.Footer>
<ToggleSwitch IsChecked="{Binding Config.IsEnableTranslation}" /> <ToggleSwitch IsChecked="{Binding Config.IsEnableTranslation}" />
</ui:SettingsExpanderItem.Footer> </ui:SettingsExpanderItem.Footer>
</ui:SettingsExpanderItem> </ui:SettingsExpanderItem>
<ui:SettingsExpanderItem Content="Skip Existing Lyric Files"> <ui:SettingsExpanderItem Content="跳过已经存在的歌词文件(不覆盖)">
<ui:SettingsExpanderItem.Footer> <ui:SettingsExpanderItem.Footer>
<ToggleSwitch IsChecked="{Binding Config.IsSkipExistLyricFiles}" /> <ToggleSwitch IsChecked="{Binding Config.IsSkipExistLyricFiles}" />
</ui:SettingsExpanderItem.Footer> </ui:SettingsExpanderItem.Footer>
</ui:SettingsExpanderItem> </ui:SettingsExpanderItem>
<ui:SettingsExpanderItem Content="File Encoding"> <ui:SettingsExpanderItem Content="文件编码">
<ui:SettingsExpanderItem.Footer> <ui:SettingsExpanderItem.Footer>
<ComboBox SelectedItem="{Binding Config.FileEncoding}"> <ComboBox SelectedItem="{Binding Config.FileEncoding}">
<ComboBoxItem Content="UTF-8" /> <ComboBoxItem Content="UTF-8" />
@ -50,15 +66,15 @@
</ui:SettingsExpanderItem.Footer> </ui:SettingsExpanderItem.Footer>
</ui:SettingsExpanderItem> </ui:SettingsExpanderItem>
<ui:SettingsExpanderItem Content="Only Output Translation"> <ui:SettingsExpanderItem Content="只输出翻译歌词">
<ui:SettingsExpanderItem.Footer> <ui:SettingsExpanderItem.Footer>
<ToggleSwitch IsChecked="{Binding Config.IsOnlyOutputTranslation}" /> <ToggleSwitch IsChecked="{Binding Config.IsOnlyOutputTranslation}" />
</ui:SettingsExpanderItem.Footer> </ui:SettingsExpanderItem.Footer>
</ui:SettingsExpanderItem> </ui:SettingsExpanderItem>
</ui:SettingsExpander> </ui:SettingsExpander>
<!-- Plugin Configuration --> <!-- 歌词下载器配置 -->
<ui:SettingsExpander Header="Lyrics Provider Plugins" Description="Configure settings for lyrics provider plugins"> <ui:SettingsExpander Header="歌词下载器设置" Description="配置每个单独的歌词下载器参数" IconSource="{StaticResource DownloadIcon}">
<ItemsRepeater ItemsSource="{Binding Plugin}"> <ItemsRepeater ItemsSource="{Binding Plugin}">
<ItemsRepeater.ItemTemplate> <ItemsRepeater.ItemTemplate>
<DataTemplate> <DataTemplate>
@ -67,13 +83,13 @@
<TextBlock Text="{Binding Name}" /> <TextBlock Text="{Binding Name}" />
</ui:SettingsExpander.Header> </ui:SettingsExpander.Header>
<ui:SettingsExpanderItem Content="Priority"> <ui:SettingsExpanderItem Content="下载器优先级">
<ui:SettingsExpanderItem.Footer> <ui:SettingsExpanderItem.Footer>
<NumericUpDown Value="{Binding Priority}" Minimum="-1" Maximum="100" /> <NumericUpDown Value="{Binding Priority}" Minimum="-1" Maximum="100" />
</ui:SettingsExpanderItem.Footer> </ui:SettingsExpanderItem.Footer>
</ui:SettingsExpanderItem> </ui:SettingsExpanderItem>
<ui:SettingsExpanderItem Content="Search Depth"> <ui:SettingsExpanderItem Content="搜索深度">
<ui:SettingsExpanderItem.Footer> <ui:SettingsExpanderItem.Footer>
<NumericUpDown Value="{Binding Depth}" Minimum="1" Maximum="100" /> <NumericUpDown Value="{Binding Depth}" Minimum="1" Maximum="100" />
</ui:SettingsExpanderItem.Footer> </ui:SettingsExpanderItem.Footer>
@ -84,26 +100,25 @@
</ItemsRepeater> </ItemsRepeater>
</ui:SettingsExpander> </ui:SettingsExpander>
<!-- Tag Info Configuration --> <!-- 标签设置 -->
<ui:SettingsExpander Header="Tag Info Configuration" Description="Configure settings for tag information"> <ui:SettingsExpander Header="标签读取设置" Description="配置读取音乐文件标签时的一些参数" IconSource="{StaticResource TagIcon}">
<!-- Block Word Options --> <!-- Block Word Options -->
<ui:SettingsExpanderItem Content="Enable Block Word Feature"> <ui:SettingsExpanderItem Content="是否启用屏蔽字典">
<ui:SettingsExpanderItem.Footer> <ui:SettingsExpanderItem.Footer>
<ToggleSwitch IsChecked="{Binding Tag.BlockWord.IsEnable}" /> <ToggleSwitch IsChecked="{Binding Tag.BlockWord.IsEnable}" />
</ui:SettingsExpanderItem.Footer> </ui:SettingsExpanderItem.Footer>
</ui:SettingsExpanderItem> </ui:SettingsExpanderItem>
<ui:SettingsExpanderItem Content="Block Word Dictionary File Path"> <ui:SettingsExpanderItem Content="屏蔽字典的路径:">
<ui:SettingsExpanderItem.Footer> <ui:SettingsExpanderItem.Footer>
<StackPanel Orientation="Horizontal" Spacing="10"> <StackPanel Orientation="Horizontal" Spacing="10">
<TextBox Text="{Binding Tag.BlockWord.FilePath}" Width="200" /> <TextBox Text="{Binding Tag.BlockWord.FilePath}" Width="200" />
<Button Content="Browse" Command="{Binding BrowseBlockWordFileCommand}" /> <Button Content="浏览" Command="{Binding BrowseBlockWordFileCommand}" />
</StackPanel> </StackPanel>
</ui:SettingsExpanderItem.Footer> </ui:SettingsExpanderItem.Footer>
</ui:SettingsExpanderItem> </ui:SettingsExpanderItem>
<!-- Tag Info Providers --> <ui:SettingsExpander Header="标签扫描器" Description="配置标签扫描器">
<ui:SettingsExpander Header="Tag Info Providers" Description="Configure settings for tag info provider plugins">
<ItemsRepeater ItemsSource="{Binding Tag.Plugin}"> <ItemsRepeater ItemsSource="{Binding Tag.Plugin}">
<ItemsRepeater.ItemTemplate> <ItemsRepeater.ItemTemplate>
<DataTemplate> <DataTemplate>
@ -112,13 +127,13 @@
<TextBlock Text="{Binding Name}" /> <TextBlock Text="{Binding Name}" />
</ui:SettingsExpander.Header> </ui:SettingsExpander.Header>
<ui:SettingsExpanderItem Content="Priority"> <ui:SettingsExpanderItem Content="优先级">
<ui:SettingsExpanderItem.Footer> <ui:SettingsExpanderItem.Footer>
<NumericUpDown Value="{Binding Priority}" Minimum="-1" Maximum="100" /> <NumericUpDown Value="{Binding Priority}" Minimum="-1" Maximum="100" />
</ui:SettingsExpanderItem.Footer> </ui:SettingsExpanderItem.Footer>
</ui:SettingsExpanderItem> </ui:SettingsExpanderItem>
<ui:SettingsExpanderItem Content="Extensions"> <ui:SettingsExpanderItem Content="扩展配置">
<ui:SettingsExpanderItem.Footer> <ui:SettingsExpanderItem.Footer>
<ItemsRepeater ItemsSource="{Binding Extensions}"> <ItemsRepeater ItemsSource="{Binding Extensions}">
<ItemsRepeater.ItemTemplate> <ItemsRepeater.ItemTemplate>
@ -138,6 +153,30 @@
</ItemsRepeater> </ItemsRepeater>
</ui:SettingsExpander> </ui:SettingsExpander>
</ui:SettingsExpander> </ui:SettingsExpander>
<TextBlock Margin="0,20,0,0"
Theme="{StaticResource FluentBodyStrongTextBlockStyle}"
Text="关于" />
<ui:SettingsExpander Description="获得帮助与支持信息" Header="帮助与支持"
IconSource="{StaticResource ChatHelpIcon}">
<ui:SettingsExpanderItem>
<!-- QQ 群 -->
<StackPanel Orientation="Vertical" Spacing="10">
<TextBlock Text="QQ 群: 337656932" />
<ui:HyperlinkButton NavigateUri="https://docs.myzony.com/">
<StackPanel Orientation="Horizontal" Spacing="5">
<ui:SymbolIcon Symbol="Link" />
<TextBlock Text="使用文档" />
</StackPanel>
</ui:HyperlinkButton>
</StackPanel>
</ui:SettingsExpanderItem>
</ui:SettingsExpander>
<ui:SettingsExpander ActionIconSource="{StaticResource OpenIcon}" Click="OnGitHubClick"
Description="获取软件的源代码" Header="GitHub 仓库"
IconSource="{StaticResource CodeIcon}" IsClickEnabled="True" />
</StackPanel> </StackPanel>
</ScrollViewer> </ScrollViewer>
</UserControl> </UserControl>

View File

@ -1,8 +1,9 @@
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Interactivity;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using ZonyLrcTools.Common.Configuration; using ZonyLrcTools.Common.Configuration;
using ZonyLrcTools.Desktop.ViewModels; using ZonyLrcTools.Desktop.Helpers;
using ZonyLrcTools.Desktop.ViewModels.Settings; using ZonyLrcTools.Desktop.ViewModels.Settings;
namespace ZonyLrcTools.Desktop.Pages; namespace ZonyLrcTools.Desktop.Pages;
@ -14,4 +15,6 @@ public partial class SettingsPage : UserControl
InitializeComponent(); InitializeComponent();
DataContext = new LyricsSettingsViewModel(App.Current.Services.GetRequiredService<IOptions<GlobalOptions>>().Value); DataContext = new LyricsSettingsViewModel(App.Current.Services.GetRequiredService<IOptions<GlobalOptions>>().Value);
} }
private void OnGitHubClick(object? sender, RoutedEventArgs? eventArgs) => UrlHelper.OpenLink("https://github.com/real-zony/ZonyLrcToolsX");
} }

View File

@ -1,11 +1,12 @@
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using ReactiveUI; using ReactiveUI;
using ZonyLrcTools.Common;
namespace ZonyLrcTools.Desktop.ViewModels; namespace ZonyLrcTools.Desktop.ViewModels;
public class HomeViewModel : ViewModelBase public class HomeViewModel : ViewModelBase
{ {
public ObservableCollection<SongInfo> Songs { get; } = []; public ObservableCollection<SongInfoViewModel> Songs { get; } = [];
private double _downloadProgress; private double _downloadProgress;
@ -16,10 +17,20 @@ public class HomeViewModel : ViewModelBase
} }
} }
public class SongInfo public class SongInfoViewModel(MusicInfo info)
{ {
public string SongName { get; set; } private MusicInfo Info { get; } = info;
public string ArtistName { get; set; }
public string FilePath { get; set; } public string SongName => Info.Name;
public string DownloadStatus { get; set; } public string ArtistName => Info.Artist;
public string FilePath => Info.FilePath;
public DownloadStatus DownloadStatus { get; set; } = DownloadStatus.NotStarted;
}
public enum DownloadStatus
{
NotStarted = 1,
Completed,
Failed
} }

View File

@ -20,6 +20,8 @@ public class LyricsSettingsViewModel : ViewModelBase
BrowseBlockWordFileCommand = ReactiveCommand.Create(BrowseBlockWordFile); BrowseBlockWordFileCommand = ReactiveCommand.Create(BrowseBlockWordFile);
} }
public static string Version => typeof(Program).Assembly.GetName().Version!.ToString();
public TagInfoViewModel Tag { get; } public TagInfoViewModel Tag { get; }
public ReactiveCommand<Unit, Unit> BrowseBlockWordFileCommand { get; } public ReactiveCommand<Unit, Unit> BrowseBlockWordFileCommand { get; }

View File

@ -1,9 +1,14 @@
using System.Linq;
using Avalonia; using Avalonia;
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Interactivity; using Avalonia.Interactivity;
using Avalonia.Platform.Storage; using Avalonia.Platform.Storage;
using DynamicData;
using FluentAvalonia.UI.Controls; using FluentAvalonia.UI.Controls;
using Microsoft.Extensions.DependencyInjection;
using ZonyLrcTools.Common;
using ZonyLrcTools.Desktop.Pages; using ZonyLrcTools.Desktop.Pages;
using ZonyLrcTools.Desktop.ViewModels;
namespace ZonyLrcTools.Desktop.Views; namespace ZonyLrcTools.Desktop.Views;
@ -41,14 +46,20 @@ public partial class MainView : UserControl
private async void OnOpenFolderButtonClick(object? sender, RoutedEventArgs e) private async void OnOpenFolderButtonClick(object? sender, RoutedEventArgs e)
{ {
var storage = _window?.StorageProvider; var storage = _window?.StorageProvider;
if (storage?.CanOpen == true) var musicInfoLoader = App.Current.Services.GetRequiredService<IMusicInfoLoader>();
if (storage?.CanOpen == true && DataContext is HomeViewModel vm)
{ {
var options = new FolderPickerOpenOptions var options = new FolderPickerOpenOptions
{ {
SuggestedStartLocation = await storage.TryGetWellKnownFolderAsync(WellKnownFolder.Music) SuggestedStartLocation = await storage.TryGetWellKnownFolderAsync(WellKnownFolder.Music)
}; };
var folders = await storage.OpenFolderPickerAsync(options); var folders = await storage.OpenFolderPickerAsync(options);
var folderPath = folders[0].Path; var folderPath = folders[0].Path.LocalPath;
var musicInfos = await musicInfoLoader.LoadAsync(folderPath);
vm.Songs.Clear();
vm.Songs.AddRange(musicInfos.Select(x => new SongInfoViewModel(x!)));
} }
} }

View File

@ -1,4 +1,5 @@
using Avalonia.Controls; using Avalonia.Controls;
using ZonyLrcTools.Desktop.ViewModels;
namespace ZonyLrcTools.Desktop.Views; namespace ZonyLrcTools.Desktop.Views;
@ -6,6 +7,7 @@ public partial class MainWindow : Window
{ {
public MainWindow() public MainWindow()
{ {
DataContext = new HomeViewModel();
InitializeComponent(); InitializeComponent();
} }
} }

View File

@ -22,6 +22,7 @@
<PackageReference Include="Avalonia.ReactiveUI"/> <PackageReference Include="Avalonia.ReactiveUI"/>
<PackageReference Include="FluentAvaloniaUI" /> <PackageReference Include="FluentAvaloniaUI" />
<PackageReference Include="FluentIcons.Avalonia.Fluent" /> <PackageReference Include="FluentIcons.Avalonia.Fluent" />
<PackageReference Include="Microsoft.Extensions.Hosting"/>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>