refactor: Removed avalonia code.

This commit is contained in:
real-zony 2024-11-29 22:54:38 +08:00
parent 9ab9cd50e2
commit 7732ab52d3
31 changed files with 0 additions and 1324 deletions

View File

@ -13,8 +13,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ZonyLrcTools.Tests", "tests
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ZonyLrcTools.Common", "src\ZonyLrcTools.Common\ZonyLrcTools.Common.csproj", "{9B42E4CA-61AA-4798-8D2B-2D8A7035EB67}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ZonyLrcTools.Common", "src\ZonyLrcTools.Common\ZonyLrcTools.Common.csproj", "{9B42E4CA-61AA-4798-8D2B-2D8A7035EB67}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ZonyLrcTools.Desktop", "src\ZonyLrcTools.Desktop\ZonyLrcTools.Desktop.csproj", "{DC92902B-4303-4E43-AFB3-3F93FD3986AD}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
@ -33,10 +31,6 @@ Global
{9B42E4CA-61AA-4798-8D2B-2D8A7035EB67}.Debug|Any CPU.Build.0 = Debug|Any CPU {9B42E4CA-61AA-4798-8D2B-2D8A7035EB67}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9B42E4CA-61AA-4798-8D2B-2D8A7035EB67}.Release|Any CPU.ActiveCfg = Release|Any CPU {9B42E4CA-61AA-4798-8D2B-2D8A7035EB67}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9B42E4CA-61AA-4798-8D2B-2D8A7035EB67}.Release|Any CPU.Build.0 = Release|Any CPU {9B42E4CA-61AA-4798-8D2B-2D8A7035EB67}.Release|Any CPU.Build.0 = Release|Any CPU
{DC92902B-4303-4E43-AFB3-3F93FD3986AD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DC92902B-4303-4E43-AFB3-3F93FD3986AD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DC92902B-4303-4E43-AFB3-3F93FD3986AD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DC92902B-4303-4E43-AFB3-3F93FD3986AD}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
@ -48,6 +42,5 @@ Global
{55D74323-ABFA-4A73-A3BF-F3E8D5DE6DE8} = {C29FB05C-54B1-4020-94D2-87E192EB2F98} {55D74323-ABFA-4A73-A3BF-F3E8D5DE6DE8} = {C29FB05C-54B1-4020-94D2-87E192EB2F98}
{FFBD3200-568F-455B-8390-5E76C51D522C} = {AF8ADB2F-E46C-4DEE-8316-652D9FE1A69B} {FFBD3200-568F-455B-8390-5E76C51D522C} = {AF8ADB2F-E46C-4DEE-8316-652D9FE1A69B}
{9B42E4CA-61AA-4798-8D2B-2D8A7035EB67} = {C29FB05C-54B1-4020-94D2-87E192EB2F98} {9B42E4CA-61AA-4798-8D2B-2D8A7035EB67} = {C29FB05C-54B1-4020-94D2-87E192EB2F98}
{DC92902B-4303-4E43-AFB3-3F93FD3986AD} = {C29FB05C-54B1-4020-94D2-87E192EB2F98}
EndGlobalSection EndGlobalSection
EndGlobal EndGlobal

View File

@ -1,35 +0,0 @@
<Application xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="ZonyLrcTools.Desktop.App"
xmlns:local="using:ZonyLrcTools.Desktop"
xmlns:styling="clr-namespace:FluentAvalonia.Styling;assembly=FluentAvalonia"
RequestedThemeVariant="Default"
xmlns:ic="using:FluentIcons.Avalonia.Fluent">
<!-- "Default" ThemeVariant follows system theme variant. "Dark" or "Light" are other available options. -->
<Application.DataTemplates>
<local:ViewLocator />
</Application.DataTemplates>
<Application.Resources>
<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>
</ResourceDictionary>
</Application.Resources>
<Application.Styles>
<FluentTheme />
<styling:FluentAvaloniaTheme />
<Style Selector="TextBlock">
<Setter Property="FontFamily" Value="{StaticResource GlobalFontFamily}" />
</Style>
<StyleInclude Source="/Controls/DownloadStatusControl.axaml" />
</Application.Styles>
</Application>

View File

@ -1,67 +0,0 @@
using System;
using System.IO;
using Avalonia;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Markup.Xaml;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using YamlDotNet.Core;
using YamlDotNet.Serialization;
using YamlDotNet.Serialization.NamingConventions;
using ZonyLrcTools.Common.Configuration;
using ZonyLrcTools.Common.Infrastructure.DependencyInject;
using ZonyLrcTools.Common.Infrastructure.Network;
using ZonyLrcTools.Desktop.ViewModels;
using ZonyLrcTools.Desktop.Views;
namespace ZonyLrcTools.Desktop;
public class App : Application
{
public new static App Current => (App)Application.Current!;
public IServiceProvider Services { get; } = ConfigureServices();
public IOptions<GlobalOptions> GlobalOptions => Services.GetRequiredService<IOptions<GlobalOptions>>();
private Lazy<ISerializer> _yamlSerializer = new(() => new SerializerBuilder()
.WithNamingConvention(CamelCaseNamingConvention.Instance)
.WithDefaultScalarStyle(ScalarStyle.DoubleQuoted)
.Build());
private static IServiceProvider ConfigureServices()
{
var services = new ServiceCollection();
services.BeginAutoDependencyInject<Program>();
services.BeginAutoDependencyInject<IWarpHttpClient>();
services.ConfigureConfiguration();
services.ConfigureToolService();
return services.BuildServiceProvider();
}
public override void Initialize()
{
AvaloniaXamlLoader.Load(this);
}
public override void OnFrameworkInitializationCompleted()
{
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
{
desktop.MainWindow = new MainWindow
{
DataContext = new HomeViewModel(),
};
}
base.OnFrameworkInitializationCompleted();
}
public void UpdateConfiguration()
{
var configPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "config.yaml");
var yamlString = _yamlSerializer.Value.Serialize(GlobalOptions.Value);
File.WriteAllText(configPath, yamlString);
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 172 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 142 KiB

View File

@ -1,92 +0,0 @@
<Styles xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="using:ZonyLrcTools.Desktop.Controls"
xmlns:fluent="using:FluentIcons.Avalonia.Fluent">
<Design.PreviewWith>
<controls:DownloadStatusControl Status="Completed" />
</Design.PreviewWith>
<Style Selector="controls|DownloadStatusControl">
<!-- Set Defaults -->
<Setter Property="Template">
<ControlTemplate>
<StackPanel Orientation="Horizontal" Spacing="5">
<Border Name="IconContainer" Width="20" Height="20">
<fluent:SymbolIcon Name="StatusIcon" Symbol="{TemplateBinding Symbol}" />
</Border>
<TextBlock Text="{TemplateBinding Text}" VerticalAlignment="Center" />
</StackPanel>
</ControlTemplate>
</Setter>
</Style>
<Style Selector="controls|DownloadStatusControl[Status=NotStarted]">
<Setter Property="Symbol" Value="QuestionCircle" />
<Setter Property="Text" Value="未下载" />
</Style>
<Style Selector="controls|DownloadStatusControl[Status=Completed]">
<Setter Property="Symbol" Value="CheckmarkCircle" />
<Setter Property="Text" Value="已完成" />
</Style>
<Style Selector="controls|DownloadStatusControl[Status=Failed]">
<Setter Property="Symbol" Value="DismissCircle" />
<Setter Property="Text" Value="失败" />
</Style>
<Style Selector="controls|DownloadStatusControl[Status=Completed] /template/ Border#IconContainer">
<Style.Animations>
<Animation Duration="0:0:0.5">
<KeyFrame Cue="0%">
<Setter Property="RotateTransform.Angle" Value="0"/>
<Setter Property="ScaleTransform.ScaleX" Value="1"/>
<Setter Property="ScaleTransform.ScaleY" Value="1"/>
</KeyFrame>
<KeyFrame Cue="50%">
<Setter Property="RotateTransform.Angle" Value="180"/>
<Setter Property="ScaleTransform.ScaleX" Value="1.2"/>
<Setter Property="ScaleTransform.ScaleY" Value="1.2"/>
</KeyFrame>
<KeyFrame Cue="100%">
<Setter Property="RotateTransform.Angle" Value="360"/>
<Setter Property="ScaleTransform.ScaleX" Value="1"/>
<Setter Property="ScaleTransform.ScaleY" Value="1"/>
</KeyFrame>
</Animation>
</Style.Animations>
</Style>
<Style Selector="controls|DownloadStatusControl[Status=Failed] /template/ Border#IconContainer">
<Style.Animations>
<Animation Duration="0:0:0.5" IterationCount="3">
<KeyFrame Cue="0%">
<Setter Property="TranslateTransform.X" Value="0"/>
</KeyFrame>
<KeyFrame Cue="25%">
<Setter Property="TranslateTransform.X" Value="-2"/>
</KeyFrame>
<KeyFrame Cue="50%">
<Setter Property="TranslateTransform.X" Value="0"/>
</KeyFrame>
<KeyFrame Cue="75%">
<Setter Property="TranslateTransform.X" Value="2"/>
</KeyFrame>
<KeyFrame Cue="100%">
<Setter Property="TranslateTransform.X" Value="0"/>
</KeyFrame>
</Animation>
</Style.Animations>
</Style>
<Style Selector="controls|DownloadStatusControl /template/ Border#IconContainer">
<Setter Property="RenderTransform">
<TransformGroup>
<RotateTransform/>
<ScaleTransform/>
<TranslateTransform/>
</TransformGroup>
</Setter>
</Style>
</Styles>

View File

@ -1,36 +0,0 @@
using Avalonia;
using Avalonia.Controls.Primitives;
using FluentIcons.Common;
using ZonyLrcTools.Desktop.ViewModels;
namespace ZonyLrcTools.Desktop.Controls;
public class DownloadStatusControl : TemplatedControl
{
public static readonly StyledProperty<DownloadStatus> StatusProperty =
AvaloniaProperty.Register<DownloadStatusControl, DownloadStatus>(nameof(Status));
public static readonly StyledProperty<Symbol> SymbolProperty =
AvaloniaProperty.Register<DownloadStatusControl, Symbol>(nameof(Symbol));
public static readonly StyledProperty<string> TextProperty =
AvaloniaProperty.Register<DownloadStatusControl, string>(nameof(Text));
public DownloadStatus Status
{
get => GetValue(StatusProperty);
set => SetValue(StatusProperty, value);
}
public Symbol Symbol
{
get => GetValue(SymbolProperty);
set => SetValue(SymbolProperty, value);
}
public string Text
{
get => GetValue(TextProperty);
set => SetValue(TextProperty, value);
}
}

View File

@ -1,3 +0,0 @@
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
<ReactiveUI />
</Weavers>

View File

@ -1,33 +0,0 @@
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

@ -1,35 +0,0 @@
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

@ -1,50 +0,0 @@
<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"
xmlns:viewModels="clr-namespace:ZonyLrcTools.Desktop.ViewModels"
xmlns:controls="clr-namespace:ZonyLrcTools.Desktop.Controls"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="ZonyLrcTools.Desktop.Pages.HomePage"
x:DataType="viewModels:HomeViewModel">
<DockPanel>
<StackPanel DockPanel.Dock="Bottom" Margin="10">
<TextBlock Text="下载进度:" Margin="0,0,0,5" />
<ProgressBar Value="{Binding DownloadProgress}" Maximum="{Binding MaxProgress}" Height="20" />
</StackPanel>
<DataGrid AutoGenerateColumns="False"
IsReadOnly="True"
GridLinesVisibility="All"
BorderThickness="1"
BorderBrush="Gray"
ItemsSource="{Binding Songs}">
<DataGrid.Columns>
<DataGridTextColumn Header="歌曲名称" Binding="{Binding SongName}" Width="*" />
<DataGridTextColumn Header="歌手名称" Binding="{Binding ArtistName}" Width="*" />
<DataGridTextColumn Header="文件路径" Binding="{Binding FilePath}" Width="2*" />
<DataGridTemplateColumn Header="下载状态" Width="1*">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<controls:DownloadStatusControl Status="{Binding DownloadStatus}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
<DataGrid.Styles>
<Style Selector="DataGridColumnHeader">
<Setter Property="Background" Value="{DynamicResource ControlFillColorDefault}" />
<Setter Property="Foreground" Value="{DynamicResource TextFillColorPrimary}" />
<Setter Property="FontWeight" Value="SemiBold" />
<Setter Property="Padding" Value="12,8,12,8" />
<Setter Property="VerticalContentAlignment" Value="Center" />
</Style>
<Style Selector="DataGridCell">
<Setter Property="Padding" Value="12,8" />
</Style>
</DataGrid.Styles>
</DataGrid>
</DockPanel>
</UserControl>

View File

@ -1,24 +0,0 @@
using Avalonia;
using Avalonia.Controls;
using ZonyLrcTools.Desktop.ViewModels;
namespace ZonyLrcTools.Desktop.Pages;
public partial class HomePage : UserControl
{
public HomePage()
{
InitializeComponent();
}
protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
{
base.OnAttachedToVisualTree(e);
if (DataContext is HomeViewModel vm)
{
vm.MaxProgress = 100;
vm.DownloadProgress = 0;
}
}
}

View File

@ -1,190 +0,0 @@
<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"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="ZonyLrcTools.Desktop.Pages.SettingsPage"
xmlns:ui="using:FluentAvalonia.UI.Controls"
xmlns:settings="clr-namespace:ZonyLrcTools.Desktop.ViewModels.Settings"
x:DataType="settings:SettingsViewModel">
<UserControl.Resources>
<settings:NullToDefaultValueConverter x:Key="NullToDefaultValueConverter" />
</UserControl.Resources>
<ScrollViewer>
<StackPanel Orientation="Vertical" Margin="24" Spacing="8">
<Grid ColumnDefinitions="Auto,*,Auto,Auto">
<Image Width="64" Height="64" HorizontalAlignment="Left"
Source="/Assets/logo.ico"
RenderOptions.BitmapInterpolationMode="HighQuality" />
<StackPanel Grid.Column="1"
Margin="12,0,0,0" VerticalAlignment="Center">
<TextBlock Text="ZonyLrcToolsX" />
<TextBlock Foreground="{DynamicResource TextFillColorSecondaryBrush}"
Text="{Binding Version, StringFormat='Version {0}'}" />
</StackPanel>
</Grid>
<TextBlock Margin="0,20,0,0"
Text="软件设置" />
<!-- 全局设置 -->
<ui:SettingsExpander Header="全局设置" Description="配置软件的全局设置" IconSource="{StaticResource SettingsIcon}">
<ui:SettingsExpanderItem Content="是否合并歌词为一行">
<ui:SettingsExpanderItem.Footer>
<ToggleSwitch IsChecked="{Binding Config.IsOneLine}" />
</ui:SettingsExpanderItem.Footer>
</ui:SettingsExpanderItem>
<ui:SettingsExpanderItem Content="换行符">
<ui:SettingsExpanderItem.Footer>
<ComboBox ItemsSource="{Binding Config.LineBreakOptions}"
SelectedItem="{Binding Config.SelectedLineBreak}">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</ui:SettingsExpanderItem.Footer>
</ui:SettingsExpanderItem>
<ui:SettingsExpanderItem Content="启用翻译歌词">
<ui:SettingsExpanderItem.Footer>
<ToggleSwitch IsChecked="{Binding Config.IsEnableTranslation}" />
</ui:SettingsExpanderItem.Footer>
</ui:SettingsExpanderItem>
<ui:SettingsExpanderItem Content="跳过已经存在的歌词文件(不覆盖)">
<ui:SettingsExpanderItem.Footer>
<ToggleSwitch IsChecked="{Binding Config.IsSkipExistLyricFiles}" />
</ui:SettingsExpanderItem.Footer>
</ui:SettingsExpanderItem>
<ui:SettingsExpanderItem Content="文件编码">
<ui:SettingsExpanderItem.Footer>
<ComboBox ItemsSource="{Binding Config.FileEncodingOptions}"
SelectedItem="{Binding Config.SelectedFileEncoding}">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</ui:SettingsExpanderItem.Footer>
</ui:SettingsExpanderItem>
<ui:SettingsExpanderItem Content="只输出翻译歌词">
<ui:SettingsExpanderItem.Footer>
<ToggleSwitch IsChecked="{Binding Config.IsOnlyOutputTranslation}" />
</ui:SettingsExpanderItem.Footer>
</ui:SettingsExpanderItem>
</ui:SettingsExpander>
<!-- 歌词下载器配置 -->
<ui:SettingsExpander Header="歌词下载器设置" Description="配置每个单独的歌词下载器参数" IconSource="{StaticResource DownloadIcon}">
<ItemsRepeater ItemsSource="{Binding LyricsProviders}">
<ItemsRepeater.ItemTemplate>
<DataTemplate>
<ui:SettingsExpander Margin="0,0,0,10">
<ui:SettingsExpander.Header>
<TextBlock Text="{Binding Name}" />
</ui:SettingsExpander.Header>
<ui:SettingsExpanderItem Content="下载器优先级">
<ui:SettingsExpanderItem.Footer>
<NumericUpDown Value="{Binding Priority, Converter={StaticResource NullToDefaultValueConverter}}" Minimum="-1" Maximum="100" Increment="1" />
</ui:SettingsExpanderItem.Footer>
</ui:SettingsExpanderItem>
<ui:SettingsExpanderItem Content="搜索深度">
<ui:SettingsExpanderItem.Footer>
<NumericUpDown Value="{Binding Depth, Converter={StaticResource NullToDefaultValueConverter}}" Minimum="1" Maximum="100" Increment="1" />
</ui:SettingsExpanderItem.Footer>
</ui:SettingsExpanderItem>
</ui:SettingsExpander>
</DataTemplate>
</ItemsRepeater.ItemTemplate>
</ItemsRepeater>
</ui:SettingsExpander>
<!-- 标签设置 -->
<ui:SettingsExpander Header="标签读取设置" Description="配置读取音乐文件标签时的一些参数" IconSource="{StaticResource TagIcon}">
<!-- Block Word Options -->
<ui:SettingsExpanderItem Content="是否启用屏蔽字典">
<ui:SettingsExpanderItem.Footer>
<ToggleSwitch IsChecked="{Binding Tag.BlockWord.IsEnable}" />
</ui:SettingsExpanderItem.Footer>
</ui:SettingsExpanderItem>
<ui:SettingsExpanderItem Content="屏蔽字典的路径:">
<ui:SettingsExpanderItem.Footer>
<StackPanel Orientation="Horizontal" Spacing="10">
<TextBox Text="{Binding Tag.BlockWord.FilePath}" Width="200" />
<Button Content="浏览" Command="{Binding BrowseBlockWordFileCommand}" CommandParameter="{Binding $parent[Window]}" />
</StackPanel>
</ui:SettingsExpanderItem.Footer>
</ui:SettingsExpanderItem>
<ui:SettingsExpander Header="标签扫描器" Description="配置标签扫描器">
<ItemsRepeater ItemsSource="{Binding Tag.TagInfoProviders}">
<ItemsRepeater.ItemTemplate>
<DataTemplate>
<ui:SettingsExpander Margin="0,0,0,10">
<ui:SettingsExpander.Header>
<TextBlock Text="{Binding Name}" />
</ui:SettingsExpander.Header>
<ui:SettingsExpanderItem Content="优先级">
<ui:SettingsExpanderItem.Footer>
<NumericUpDown Value="{Binding Priority , Converter={StaticResource NullToDefaultValueConverter}}" Minimum="-1" Maximum="100" Increment="1" />
</ui:SettingsExpanderItem.Footer>
</ui:SettingsExpanderItem>
<ui:SettingsExpanderItem Content="扩展配置">
<ui:SettingsExpanderItem.Footer>
<ItemsRepeater ItemsSource="{Binding Extensions}">
<ItemsRepeater.ItemTemplate>
<DataTemplate>
<Grid ColumnDefinitions="Auto,*" Margin="0,5">
<TextBlock Grid.Column="0" Text="{Binding Key}" Margin="0,0,10,0" />
<TextBox Grid.Column="1" Text="{Binding Value}" />
</Grid>
</DataTemplate>
</ItemsRepeater.ItemTemplate>
</ItemsRepeater>
</ui:SettingsExpanderItem.Footer>
</ui:SettingsExpanderItem>
</ui:SettingsExpander>
</DataTemplate>
</ItemsRepeater.ItemTemplate>
</ItemsRepeater>
</ui:SettingsExpander>
</ui:SettingsExpander>
<TextBlock Margin="0,20,0,0"
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>
</ScrollViewer>
</UserControl>

View File

@ -1,20 +0,0 @@
using Avalonia.Controls;
using Avalonia.Interactivity;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using ZonyLrcTools.Common.Configuration;
using ZonyLrcTools.Desktop.Helpers;
using ZonyLrcTools.Desktop.ViewModels.Settings;
namespace ZonyLrcTools.Desktop.Pages;
public partial class SettingsPage : UserControl
{
public SettingsPage()
{
InitializeComponent();
DataContext = new SettingsViewModel(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,27 +0,0 @@
using Avalonia;
using Avalonia.ReactiveUI;
using System;
using System.Text;
namespace ZonyLrcTools.Desktop;
class Program
{
// Initialization code. Don't use any Avalonia, third-party APIs or any
// SynchronizationContext-reliant code before AppMain is called: things aren't initialized
// yet and stuff might break.
[STAThread]
public static void Main(string[] args)
{
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
BuildAvaloniaApp().StartWithClassicDesktopLifetime(args);
}
// Avalonia configuration, don't remove; also used by visual designer.
public static AppBuilder BuildAvaloniaApp()
=> AppBuilder.Configure<App>()
.UsePlatformDetect()
.WithInterFont()
.LogToTrace()
.UseReactiveUI();
}

View File

@ -1,27 +0,0 @@
using System;
using Avalonia.Controls;
using Avalonia.Controls.Templates;
using ZonyLrcTools.Desktop.ViewModels;
namespace ZonyLrcTools.Desktop;
public class ViewLocator : IDataTemplate
{
public Control Build(object data)
{
var name = data.GetType().FullName!.Replace("ViewModel", "View");
var type = Type.GetType(name);
if (type != null)
{
return (Control)Activator.CreateInstance(type)!;
}
return new TextBlock { Text = "Not Found: " + name };
}
public bool Match(object data)
{
return data is ViewModelBase;
}
}

View File

@ -1,77 +0,0 @@
using System;
using System.Collections.ObjectModel;
using ReactiveUI;
using ZonyLrcTools.Common;
namespace ZonyLrcTools.Desktop.ViewModels;
public class HomeViewModel : ViewModelBase
{
private ObservableCollection<SongInfoViewModel> _songs = new();
public ObservableCollection<SongInfoViewModel> Songs
{
get => _songs;
set => this.RaiseAndSetIfChanged(ref _songs, value);
}
private int _downloadProgress;
public int DownloadProgress
{
get => _downloadProgress;
set => this.RaiseAndSetIfChanged(ref _downloadProgress, value);
}
private int _maxProgress;
public int MaxProgress
{
get => _maxProgress;
set => this.RaiseAndSetIfChanged(ref _maxProgress, value);
}
}
public class SongInfoViewModel : ReactiveObject
{
public SongInfoViewModel(MusicInfo info)
{
_info = info;
DownloadStatus = DownloadStatus.NotStarted;
this.WhenAnyValue(x => x.Info)
.Subscribe(_ =>
{
this.RaisePropertyChanged(nameof(SongName));
this.RaisePropertyChanged(nameof(ArtistName));
this.RaisePropertyChanged(nameof(FilePath));
});
}
private MusicInfo _info;
public MusicInfo Info
{
get => _info;
set => this.RaiseAndSetIfChanged(ref _info, value);
}
public string SongName => Info.Name;
public string ArtistName => Info.Artist;
public string FilePath => Info.FilePath;
private DownloadStatus _downloadStatus;
public DownloadStatus DownloadStatus
{
get => _downloadStatus;
set => this.RaiseAndSetIfChanged(ref _downloadStatus, value);
}
}
public enum DownloadStatus
{
NotStarted = 1,
Completed,
Failed
}

View File

@ -1,20 +0,0 @@
using ReactiveUI.Fody.Helpers;
using ZonyLrcTools.Common.Configuration;
namespace ZonyLrcTools.Desktop.ViewModels.Settings;
public class BlockWordViewModel : ViewModelBase
{
public BlockWordViewModel(GlobalOptions options)
{
IsEnable = options.Provider.Tag.BlockWord.IsEnable;
FilePath = options.Provider.Tag.BlockWord.FilePath;
SubscribeToProperty(this, x => x.IsEnable, x => options.Provider.Tag.BlockWord.IsEnable = x);
SubscribeToProperty(this, x => x.FilePath, x => options.Provider.Tag.BlockWord.FilePath = x!);
}
[Reactive] public bool IsEnable { get; set; }
[Reactive] public string? FilePath { get; set; }
}

View File

@ -1,75 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ReactiveUI;
using ReactiveUI.Fody.Helpers;
using ZonyLrcTools.Common.Configuration;
namespace ZonyLrcTools.Desktop.ViewModels.Settings;
public class GlobalConfigurationViewModel : ViewModelBase
{
public GlobalConfigurationViewModel(GlobalOptions config)
{
var globalConfig = config.Provider.Lyric.Config;
InitializeLineBreakComboBoxItem(globalConfig);
IsOneLine = globalConfig.IsOneLine;
IsEnableTranslation = globalConfig.IsEnableTranslation;
IsSkipExistLyricFiles = globalConfig.IsSkipExistLyricFiles;
IsOnlyOutputTranslation = globalConfig.IsOnlyOutputTranslation;
SubscribeToProperty(this, x => x.IsOneLine, x => globalConfig.IsOneLine = x);
SubscribeToProperty(this, x => x.IsEnableTranslation, x => globalConfig.IsEnableTranslation = x);
SubscribeToProperty(this, x => x.IsSkipExistLyricFiles, x => globalConfig.IsSkipExistLyricFiles = x);
SubscribeToProperty(this, x => x.IsOnlyOutputTranslation, x => globalConfig.IsOnlyOutputTranslation = x);
}
[Reactive] public bool IsOneLine { get; set; }
[Reactive] public bool IsEnableTranslation { get; set; }
[Reactive] public bool IsSkipExistLyricFiles { get; set; }
[Reactive] public bool IsOnlyOutputTranslation { get; set; }
private void InitializeLineBreakComboBoxItem(GlobalLyricsConfigOptions config)
{
LineBreakOptions =
[
new TextComboboxItem { Name = "Windows", Value = "\r\n" },
new TextComboboxItem { Name = "Unix", Value = "\n" },
new TextComboboxItem { Name = "Mac", Value = "\r" }
];
SelectedLineBreak = LineBreakOptions.FirstOrDefault(x => x.Value == config.LineBreak)
?? LineBreakOptions.First();
FileEncodingOptions = Encoding.GetEncodings()
.Select(x => new TextComboboxItem { Name = x.DisplayName, Value = x.Name })
.ToList();
FileEncodingOptions.Insert(0, new TextComboboxItem { Name = "UTF-8-BOM", Value = "utf-8-bom" });
SelectedFileEncoding = FileEncodingOptions.FirstOrDefault(x => x.Value == config.FileEncoding)
?? FileEncodingOptions.First();
this.WhenAnyValue(x => x.SelectedLineBreak)
.Subscribe(x => config.LineBreak = x.Value);
this.WhenAnyValue(x => x.SelectedFileEncoding)
.Subscribe(x => config.FileEncoding = x.Value);
}
public List<TextComboboxItem> LineBreakOptions { get; private set; }
[Reactive] public TextComboboxItem SelectedLineBreak { get; set; }
public List<TextComboboxItem> FileEncodingOptions { get; private set; }
[Reactive] public TextComboboxItem SelectedFileEncoding { get; set; }
public class TextComboboxItem
{
public string Name { get; set; } = default!;
public string Value { get; set; } = default!;
}
}

View File

@ -1,49 +0,0 @@
using System;
using System.Globalization;
using Avalonia.Data;
using Avalonia.Data.Converters;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using ReactiveUI.Fody.Helpers;
using ZonyLrcTools.Common.Configuration;
namespace ZonyLrcTools.Desktop.ViewModels.Settings;
public class LyricsProviderViewModel : ViewModelBase
{
public LyricsProviderViewModel(LyricsProviderOptions options)
{
var globalOptions = App.Current.Services.GetRequiredService<IOptions<GlobalOptions>>().Value;
Name = options.Name;
Priority = options.Priority;
Depth = options.Depth;
SubscribeToProperty(this, x => x.Priority, x => globalOptions.Provider.Lyric.GetLyricProviderOption(Name).Priority = x);
SubscribeToProperty(this, x => x.Depth, x => globalOptions.Provider.Lyric.GetLyricProviderOption(Name).Depth = x);
}
public string Name { get; set; }
[Reactive] public int Priority { get; set; }
[Reactive] public int Depth { get; set; }
}
internal class NullToDefaultValueConverter : IValueConverter
{
public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
{
return value != null ? System.Convert.ToDecimal(value) : 0;
}
public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
{
if (value is decimal dValue)
{
return System.Convert.ToInt32(dValue);
}
return BindingOperations.DoNothing;
}
}

View File

@ -1,56 +0,0 @@
using System.Collections.ObjectModel;
using System.Linq;
using System.Reactive;
using System.Threading.Tasks;
using Avalonia.Controls;
using Avalonia.Platform.Storage;
using ReactiveUI;
using ZonyLrcTools.Common.Configuration;
namespace ZonyLrcTools.Desktop.ViewModels.Settings;
public class SettingsViewModel : ViewModelBase
{
public SettingsViewModel(GlobalOptions globalOptions)
{
Config = new GlobalConfigurationViewModel(globalOptions);
LyricsProviders = new ObservableCollection<LyricsProviderViewModel>(globalOptions.Provider.Lyric.Plugin.Select(p => new LyricsProviderViewModel(p)));
Tag = new TagInfoViewModel(globalOptions);
BrowseBlockWordFileCommand = ReactiveCommand.CreateFromTask<Window>(BrowseBlockWordFile);
}
public static string Version => typeof(Program).Assembly.GetName().Version!.ToString();
public TagInfoViewModel Tag { get; }
public ReactiveCommand<Window, Unit> BrowseBlockWordFileCommand { get; }
public GlobalConfigurationViewModel Config { get; }
public ObservableCollection<LyricsProviderViewModel> LyricsProviders { get; }
private async Task BrowseBlockWordFile(Window parentWindow)
{
var storage = parentWindow.StorageProvider;
if (storage.CanOpen)
{
var options = new FilePickerOpenOptions
{
AllowMultiple = false,
FileTypeFilter = new[]
{
new FilePickerFileType("JSON")
{
Patterns = new[] { "*.json" }
}
}
};
var files = await storage.OpenFilePickerAsync(options);
if (files.Count > 0)
{
Tag.BlockWord.FilePath = files[0].Path.LocalPath;
}
}
}
}

View File

@ -1,42 +0,0 @@
using System.Collections.ObjectModel;
using System.Linq;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using ReactiveUI.Fody.Helpers;
using ZonyLrcTools.Common.Configuration;
namespace ZonyLrcTools.Desktop.ViewModels.Settings;
public class TagInfoProviderViewModel : ViewModelBase
{
public TagInfoProviderViewModel(TagInfoProviderOptions options)
{
var globalOptions = App.Current.Services.GetRequiredService<IOptions<GlobalOptions>>().Value;
Name = options.Name;
Priority = options.Priority;
Extensions = options.Extensions == null ? [] : new ObservableCollection<ObservableKeyValuePair>(options.Extensions.Select(x => new ObservableKeyValuePair(x.Key, x.Value)));
SubscribeToProperty(this, x => x.Priority, x => globalOptions.Provider.Tag.GetTagProviderOption(Name).Priority = x);
SubscribeToProperty(this, x => x.Extensions, x => globalOptions.Provider.Tag.GetTagProviderOption(Name).Extensions = x.ToDictionary(pair => pair.Key, pair => pair.Value));
}
public string? Name { get; set; }
[Reactive] public int Priority { get; set; }
[Reactive] public ObservableCollection<ObservableKeyValuePair> Extensions { get; set; }
}
public class ObservableKeyValuePair : ViewModelBase
{
[Reactive] public string Key { get; set; }
[Reactive] public string Value { get; set; }
public ObservableKeyValuePair(string key, string value)
{
Key = key;
Value = value;
}
}

View File

@ -1,18 +0,0 @@
using System.Collections.ObjectModel;
using System.Linq;
using ZonyLrcTools.Common.Configuration;
namespace ZonyLrcTools.Desktop.ViewModels.Settings;
public class TagInfoViewModel : ViewModelBase
{
public TagInfoViewModel(GlobalOptions options)
{
BlockWord = new BlockWordViewModel(options);
TagInfoProviders = new ObservableCollection<TagInfoProviderViewModel>(options.Provider.Tag.Plugin.Select(p => new TagInfoProviderViewModel(p)));
}
public BlockWordViewModel BlockWord { get; }
public ObservableCollection<TagInfoProviderViewModel> TagInfoProviders { get; }
}

View File

@ -1,18 +0,0 @@
using System;
using System.Linq.Expressions;
using ReactiveUI;
namespace ZonyLrcTools.Desktop.ViewModels;
public abstract class ViewModelBase : ReactiveObject
{
protected void SubscribeToProperty<TSender, TRet>(TSender sender, Expression<Func<TSender, TRet>> property, Action<TRet> updateGlobalConfigAction)
{
sender.WhenAnyValue(property)
.Subscribe(x =>
{
updateGlobalConfigAction(x);
App.Current.UpdateConfiguration();
});
}
}

View File

@ -1,74 +0,0 @@
<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:ui="using:FluentAvalonia.UI.Controls"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:fluent="clr-namespace:FluentIcons.Avalonia.Fluent;assembly=FluentIcons.Avalonia.Fluent"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="ZonyLrcTools.Desktop.Views.MainView">
<Grid RowDefinitions="Auto,*">
<Grid Name="TitleBarHost"
Background="Transparent"
ColumnDefinitions="Auto,Auto,*,Auto,0">
<Grid.Styles>
<Style Selector="Button.AppBarButton">
<Setter Property="Padding" Value="8" />
<Setter Property="BorderThickness" Value="0" />
<Setter Property="Theme" Value="{StaticResource TransparentButton}" />
</Style>
</Grid.Styles>
<Image Width="20" Height="20" Margin="14"
Source="/Assets/logo.ico" IsHitTestVisible="False"
IsVisible="{Binding !#FrameView.CanGoBack}"
RenderOptions.BitmapInterpolationMode="HighQuality" />
<Button Grid.Column="0" Margin="6"
Classes="AppBarButton" Command="{Binding #FrameView.GoBack}"
IsEnabled="{Binding #FrameView.CanGoBack}"
IsVisible="{Binding #FrameView.CanGoBack}">
<Button.Content>
<fluent:SymbolIcon Symbol="ArrowLeft" />
</Button.Content>
<ToolTip.Tip>Back</ToolTip.Tip>
</Button>
<TextBlock Grid.Column="1"
VerticalAlignment="Center"
FontSize="12"
Text="ZonyLrcToolsX" IsHitTestVisible="False" />
<StackPanel Grid.Column="3"
Orientation="Horizontal" Margin="6" Spacing="6">
<Button Name="OpenFolderButton" Classes="AppBarButton">
<Button.Content>
<fluent:SymbolIcon Symbol="FolderAdd" />
</Button.Content>
<ToolTip.Tip>扫描文件夹</ToolTip.Tip>
</Button>
<Button Name="DownloadButton" Classes="AppBarButton">
<Button.Content>
<fluent:SymbolIcon Symbol="ArrowDownload" />
</Button.Content>
<ToolTip.Tip>下载歌词</ToolTip.Tip>
</Button>
<Button Name="SettingsButton" Classes="AppBarButton">
<Button.Content>
<fluent:SymbolIcon Symbol="Settings" />
</Button.Content>
<ToolTip.Tip>软件设置</ToolTip.Tip>
</Button>
</StackPanel>
</Grid>
<Border Grid.Row="1" Grid.ColumnSpan="3"
Background="{DynamicResource LayerFillColorDefaultBrush}"
BorderBrush="{DynamicResource CardStrokeColorDefaultBrush}"
BorderThickness="0,1,0,0"
CornerRadius="8 8 0 0">
<ui:Frame Name="FrameView" />
</Border>
</Grid>
</UserControl>

View File

@ -1,102 +0,0 @@
using System.Linq;
using System.Threading.Tasks;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Interactivity;
using Avalonia.Platform.Storage;
using DynamicData;
using FluentAvalonia.UI.Controls;
using Microsoft.Extensions.DependencyInjection;
using ZonyLrcTools.Common;
using ZonyLrcTools.Common.Lyrics;
using ZonyLrcTools.Desktop.Pages;
using ZonyLrcTools.Desktop.ViewModels;
namespace ZonyLrcTools.Desktop.Views;
public partial class MainView : UserControl
{
private Window? _window;
private Frame? _frameView;
private Button? _settingsButton;
private Button? _openFolderButton;
private Button? _downloadButton;
public MainView()
{
InitializeComponent();
}
protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
{
base.OnAttachedToVisualTree(e);
_window = e.Root as Window;
_frameView = this.FindControl<Frame>("FrameView");
_frameView?.Navigate(typeof(HomePage));
_settingsButton = this.FindControl<Button>("SettingsButton");
if (_settingsButton != null) _settingsButton.Click += OnSettingsButtonClick;
_openFolderButton = this.FindControl<Button>("OpenFolderButton");
if (_openFolderButton != null) _openFolderButton.Click += OnOpenFolderButtonClick;
_downloadButton = this.FindControl<Button>("DownloadButton");
if (_downloadButton != null) _downloadButton.Click += OnDownloadButtonClick;
}
private async void OnDownloadButtonClick(object? sender, RoutedEventArgs e)
{
var downloader = App.Current.Services.GetRequiredService<ILyricsDownloader>();
if (DataContext is HomeViewModel vm)
{
var needDownloadMusicInfos = vm.Songs
.Where(x => x.DownloadStatus == DownloadStatus.NotStarted)
.Select(x => x.Info)
.ToList();
vm.DownloadProgress = 0;
vm.MaxProgress = needDownloadMusicInfos.Count;
await downloader.DownloadAsync(needDownloadMusicInfos, callback: info =>
{
var song = vm.Songs.FirstOrDefault(x => x.Info == info);
if (song != null)
{
song.DownloadStatus = DownloadStatus.Completed;
}
vm.DownloadProgress++;
return Task.CompletedTask;
});
}
}
private async void OnOpenFolderButtonClick(object? sender, RoutedEventArgs e)
{
var storage = _window?.StorageProvider;
var musicInfoLoader = App.Current.Services.GetRequiredService<IMusicInfoLoader>();
if (storage?.CanOpen == true && DataContext is HomeViewModel vm)
{
var options = new FolderPickerOpenOptions
{
SuggestedStartLocation = await storage.TryGetWellKnownFolderAsync(WellKnownFolder.Music)
};
var folders = await storage.OpenFolderPickerAsync(options);
if (folders.Count == 0) return;
var folderPath = folders[0].Path.LocalPath;
var musicInfos = await musicInfoLoader.LoadAsync(folderPath);
vm.Songs.Clear();
vm.Songs.AddRange(musicInfos.Select(x => new SongInfoViewModel(x!)));
}
}
private void OnSettingsButtonClick(object? sender, RoutedEventArgs e)
{
if (_frameView?.CurrentSourcePageType != typeof(SettingsPage))
_frameView?.Navigate(typeof(SettingsPage));
}
}

View File

@ -1,16 +0,0 @@
<Window 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"
xmlns:views="clr-namespace:ZonyLrcTools.Desktop.Views"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="ZonyLrcTools.Desktop.Views.MainWindow"
Background="{DynamicResource AcrylicBackgroundFillColorDefaultBrush}"
Icon="/Assets/avalonia-logo.ico"
Title="ZonyLrcTools.Desktop">
<Panel>
<views:MainView />
</Panel>
</Window>

View File

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

View File

@ -1,39 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<BuiltInComInteropSupport>true</BuiltInComInteropSupport>
<ApplicationManifest>app.manifest</ApplicationManifest>
<AvaloniaUseCompiledBindingsByDefault>true</AvaloniaUseCompiledBindingsByDefault>
</PropertyGroup>
<ItemGroup>
<AvaloniaResource Include="Assets\**"/>
</ItemGroup>
<ItemGroup>
<PackageReference Include="Avalonia"/>
<PackageReference Include="Avalonia.Desktop"/>
<PackageReference Include="Avalonia.Themes.Fluent"/>
<PackageReference Include="Avalonia.Fonts.Inter"/>
<!--Condition below is needed to remove Avalonia.Diagnostics package from build output in Release configuration.-->
<PackageReference Condition="'$(Configuration)' == 'Debug'" Include="Avalonia.Diagnostics"/>
<PackageReference Include="Avalonia.ReactiveUI"/>
<PackageReference Include="FluentAvaloniaUI" />
<PackageReference Include="FluentIcons.Avalonia.Fluent" />
<PackageReference Include="Microsoft.Extensions.Hosting"/>
<PackageReference Include="ReactiveUI.Fody" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\ZonyLrcTools.Common\ZonyLrcTools.Common.csproj" />
</ItemGroup>
<ItemGroup>
<None Remove="config.yaml"/>
<Content Include="config.yaml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
</Project>

View File

@ -1,18 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
<!-- This manifest is used on Windows only.
Don't remove it as it might cause problems with window transparency and embeded controls.
For more details visit https://learn.microsoft.com/en-us/windows/win32/sbscs/application-manifests -->
<assemblyIdentity version="1.0.0.0" name="ZonyLrcTools.Desktop.Desktop"/>
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<!-- A list of the Windows versions that this application has been tested on
and is designed to work with. Uncomment the appropriate elements
and Windows will automatically select the most compatible environment. -->
<!-- Windows 10 -->
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
</application>
</compatibility>
</assembly>

View File

@ -1,61 +0,0 @@
# 允许扫描的歌曲文件后缀名。
supportFileExtensions:
- '*.mp3'
- '*.flac'
- '*.wav'
- '*.m4a'
- '*.ogg'
- '*.opus'
# 网络代理服务设置,仅支持 HTTP 代理。
networkOptions:
isEnable: false # 是否启用代理。
ip: 127.0.0.1 # 代理服务 IP 地址。
port: 4780 # 代理服务端口号。
updateUrl: https://api.myzony.com/lrc-tools/update # 更新检查地址。
# 下载器的相关参数配置。
provider:
# 标签扫描器的相关参数配置。
tag:
# 支持的标签扫描器。
plugin:
- name: Taglib # 基于 Taglib 库的标签扫描器。
priority: 1 # 优先级,升序排列。
- name: FileName # 基于文件名的标签扫描器。
priority: 2
# 基于文件名扫描器的扩展参数。
extensions:
# 正则表达式,用于匹配文件名中的作者信息和歌曲信息,可根据
# 自己的需求进行调整。
regularExpressions: "(?'artist'.+)\\s-\\s(?'name'.+)"
# 歌曲标签屏蔽字典替换功能。
blockWord:
isEnable: false # 是否启用屏蔽字典。
filePath: 'BlockWords.json' # 屏蔽字典的路径。
# 歌词下载器的相关参数配置。
lyric:
# 支持的歌词下载器。
plugin:
- name: NetEase # 基于网易云音乐的歌词下载器。
priority: 1 # 优先级,升序排列,改为 -1 时禁用。
depth: 10 # 搜索深度,值越大搜索结果越多,但搜索时间越长。
additional:
isEnableRomanOutput: false # 是否启用罗马音输出,本参数仅当对应歌曲有罗马音歌词时有效。
- name: QQ # 基于 QQ 音乐的歌词下载器。
priority: 2
# depth: 10 # 暂时不支持。
- name: KuGou # 基于酷狗音乐的歌词下载器。
priority: 3
depth: 10
- name: KuWo # 基于酷我音乐的歌词下载器。
priority: 4
depth: 10
# 歌词下载的一些共有配置参数。
config:
isOneLine: true # 双语歌词是否合并为一行展示。
lineBreak: "\n" # 换行符的类型,记得使用双引号指定。
isEnableTranslation: true # 是否启用翻译歌词。
isOnlyOutputTranslation: false # 是否只输出翻译歌词。
isSkipExistLyricFiles: false # 如果歌词文件已经存在,是否跳过这些文件。
fileEncoding: 'utf-8' # 歌词文件的编码格式。