fix(Fixed some issues in the settings page.):

This commit is contained in:
real-zony 2024-07-02 18:27:52 +08:00
parent b57739f543
commit d5689164b5
7 changed files with 116 additions and 125 deletions

View File

@ -8,6 +8,10 @@
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">
@ -80,7 +84,7 @@
<!-- 歌词下载器配置 -->
<ui:SettingsExpander Header="歌词下载器设置" Description="配置每个单独的歌词下载器参数" IconSource="{StaticResource DownloadIcon}">
<ItemsRepeater ItemsSource="{Binding Plugin}">
<ItemsRepeater ItemsSource="{Binding LyricsProviders}">
<ItemsRepeater.ItemTemplate>
<DataTemplate>
<ui:SettingsExpander Margin="0,0,0,10">
@ -90,13 +94,13 @@
<ui:SettingsExpanderItem Content="下载器优先级">
<ui:SettingsExpanderItem.Footer>
<NumericUpDown Value="{Binding Priority}" Minimum="-1" Maximum="100" />
<NumericUpDown Value="{Binding Priority}" Minimum="-1" Maximum="100" Increment="1" />
</ui:SettingsExpanderItem.Footer>
</ui:SettingsExpanderItem>
<ui:SettingsExpanderItem Content="搜索深度">
<ui:SettingsExpanderItem.Footer>
<NumericUpDown Value="{Binding Depth}" Minimum="1" Maximum="100" />
<NumericUpDown Value="{Binding Depth}" Minimum="1" Maximum="100" Increment="1" />
</ui:SettingsExpanderItem.Footer>
</ui:SettingsExpanderItem>
</ui:SettingsExpander>
@ -118,13 +122,13 @@
<ui:SettingsExpanderItem.Footer>
<StackPanel Orientation="Horizontal" Spacing="10">
<TextBox Text="{Binding Tag.BlockWord.FilePath}" Width="200" />
<Button Content="浏览" Command="{Binding BrowseBlockWordFileCommand}" />
<Button Content="浏览" Command="{Binding BrowseBlockWordFileCommand}" CommandParameter="{Binding $parent[Window]}" />
</StackPanel>
</ui:SettingsExpanderItem.Footer>
</ui:SettingsExpanderItem>
<ui:SettingsExpander Header="标签扫描器" Description="配置标签扫描器">
<ItemsRepeater ItemsSource="{Binding Tag.Plugin}">
<ItemsRepeater ItemsSource="{Binding Tag.TagInfoProviders}">
<ItemsRepeater.ItemTemplate>
<DataTemplate>
<ui:SettingsExpander Margin="0,0,0,10">
@ -134,7 +138,7 @@
<ui:SettingsExpanderItem Content="优先级">
<ui:SettingsExpanderItem.Footer>
<NumericUpDown Value="{Binding Priority}" Minimum="-1" Maximum="100" />
<NumericUpDown Value="{Binding Priority}" Minimum="-1" Maximum="100" Increment="1" />
</ui:SettingsExpanderItem.Footer>
</ui:SettingsExpanderItem>

View File

@ -1,37 +1,26 @@
using System;
using ReactiveUI;
using ReactiveUI.Fody.Helpers;
using ZonyLrcTools.Common.Configuration;
namespace ZonyLrcTools.Desktop.ViewModels.Settings;
public class BlockWordViewModel : ViewModelBase
{
private readonly BlockWordOptions _options;
public BlockWordViewModel(BlockWordOptions options)
public BlockWordViewModel(GlobalOptions options)
{
_options = options;
IsEnable = options.Provider.Tag.BlockWord.IsEnable;
FilePath = options.Provider.Tag.BlockWord.FilePath;
this.WhenAnyValue(x => x.IsEnable, x => x.FilePath)
.Subscribe(_ =>
{
options.Provider.Tag.BlockWord.IsEnable = IsEnable;
options.Provider.Tag.BlockWord.FilePath = FilePath;
});
}
public bool IsEnable
{
get => _options.IsEnable;
set
{
if (_options.IsEnable != value)
{
_options.IsEnable = value;
}
}
}
[Reactive] public bool IsEnable { get; set; }
public string FilePath
{
get => _options.FilePath;
set
{
if (_options.FilePath != value)
{
_options.FilePath = value;
}
}
}
[Reactive] public string? FilePath { get; set; }
}

View File

@ -10,26 +10,25 @@ namespace ZonyLrcTools.Desktop.ViewModels.Settings;
public class GlobalConfigurationViewModel : ViewModelBase
{
private readonly GlobalLyricsConfigOptions _config;
public GlobalConfigurationViewModel(GlobalLyricsConfigOptions config)
public GlobalConfigurationViewModel(GlobalOptions config)
{
_config = config;
InitializeLineBreakComboBoxItem();
var globalConfig = config.Provider.Lyric.Config;
IsOneLine = _config.IsOneLine;
IsEnableTranslation = _config.IsEnableTranslation;
IsSkipExistLyricFiles = _config.IsSkipExistLyricFiles;
IsOnlyOutputTranslation = _config.IsOnlyOutputTranslation;
InitializeLineBreakComboBoxItem(globalConfig);
IsOneLine = globalConfig.IsOneLine;
IsEnableTranslation = globalConfig.IsEnableTranslation;
IsSkipExistLyricFiles = globalConfig.IsSkipExistLyricFiles;
IsOnlyOutputTranslation = globalConfig.IsOnlyOutputTranslation;
this.WhenAnyValue(x => x.IsOneLine)
.Subscribe(x => _config.IsOneLine = x);
.Subscribe(x => globalConfig.IsOneLine = x);
this.WhenAnyValue(x => x.IsEnableTranslation)
.Subscribe(x => _config.IsEnableTranslation = x);
.Subscribe(x => globalConfig.IsEnableTranslation = x);
this.WhenAnyValue(x => x.IsSkipExistLyricFiles)
.Subscribe(x => _config.IsSkipExistLyricFiles = x);
.Subscribe(x => globalConfig.IsSkipExistLyricFiles = x);
this.WhenAnyValue(x => x.IsOnlyOutputTranslation)
.Subscribe(x => _config.IsOnlyOutputTranslation = x);
.Subscribe(x => globalConfig.IsOnlyOutputTranslation = x);
}
[Reactive] public bool IsOneLine { get; set; }
@ -38,11 +37,9 @@ public class GlobalConfigurationViewModel : ViewModelBase
[Reactive] public bool IsSkipExistLyricFiles { get; set; }
[Reactive] public string FileEncoding { get; set; }
[Reactive] public bool IsOnlyOutputTranslation { get; set; }
private void InitializeLineBreakComboBoxItem()
private void InitializeLineBreakComboBoxItem(GlobalLyricsConfigOptions config)
{
LineBreakOptions =
[
@ -50,20 +47,20 @@ public class GlobalConfigurationViewModel : ViewModelBase
new TextComboboxItem { Name = "Unix", Value = "\n" },
new TextComboboxItem { Name = "Mac", Value = "\r" }
];
SelectedLineBreak = LineBreakOptions.FirstOrDefault(x => x.Value == _config.LineBreak)
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)
SelectedFileEncoding = FileEncodingOptions.FirstOrDefault(x => x.Value == config.FileEncoding)
?? FileEncodingOptions.First();
this.WhenAnyValue(x => x.SelectedLineBreak)
.Subscribe(x => _config.LineBreak = x.Value);
.Subscribe(x => config.LineBreak = x.Value);
this.WhenAnyValue(x => x.SelectedFileEncoding)
.Subscribe(x => _config.FileEncoding = x.Value);
.Subscribe(x => config.FileEncoding = x.Value);
}
public List<TextComboboxItem> LineBreakOptions { get; private set; }

View File

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

View File

@ -1,6 +1,9 @@
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;
@ -8,31 +11,46 @@ namespace ZonyLrcTools.Desktop.ViewModels.Settings;
public class SettingsViewModel : ViewModelBase
{
private readonly GlobalOptions _globalOptions;
public SettingsViewModel(GlobalOptions globalOptions)
{
_globalOptions = globalOptions;
Config = new GlobalConfigurationViewModel(globalOptions.Provider.Lyric.Config);
Plugin = new ObservableCollection<LyricsProviderViewModel>(globalOptions.Provider.Lyric.Plugin.Select(p => new LyricsProviderViewModel(p)));
Tag = new TagInfoViewModel(globalOptions.Provider.Tag);
BrowseBlockWordFileCommand = ReactiveCommand.Create(BrowseBlockWordFile);
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<Unit, Unit> BrowseBlockWordFileCommand { get; }
public ReactiveCommand<Window, Unit> BrowseBlockWordFileCommand { get; }
public GlobalConfigurationViewModel Config { get; }
public ObservableCollection<LyricsProviderViewModel> Plugin { get; }
public ObservableCollection<LyricsProviderViewModel> LyricsProviders { get; }
private void BrowseBlockWordFile()
private async Task BrowseBlockWordFile(Window parentWindow)
{
// Implement file browsing logic here
// Update Tag.BlockWord.FilePath with the selected file path
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 +1,22 @@
using System.Collections.Generic;
using System.Collections.ObjectModel;
using ReactiveUI.Fody.Helpers;
using ZonyLrcTools.Common.Configuration;
namespace ZonyLrcTools.Desktop.ViewModels.Settings;
public class TagInfoProviderViewModel : ViewModelBase
{
private readonly TagInfoProviderOptions _options;
public TagInfoProviderViewModel(TagInfoProviderOptions options)
{
_options = options;
Name = options.Name;
Priority = options.Priority;
Extensions = new ObservableCollection<KeyValuePair<string, string>>(options.Extensions ?? new Dictionary<string, string>());
}
public string Name
{
get => _options.Name;
set
{
if (_options.Name != value)
{
_options.Name = value;
}
}
}
public string? Name { get; set; }
public int Priority
{
get => _options.Priority;
set
{
if (_options.Priority != value)
{
_options.Priority = value;
}
}
}
[Reactive] public int Priority { get; set; }
public ObservableCollection<KeyValuePair<string, string>> Extensions { get; }
}

View File

@ -6,16 +6,16 @@ namespace ZonyLrcTools.Desktop.ViewModels.Settings;
public class TagInfoViewModel : ViewModelBase
{
private readonly TagInfoOptions _options;
private readonly GlobalOptions _options;
public TagInfoViewModel(TagInfoOptions options)
public TagInfoViewModel(GlobalOptions options)
{
_options = options;
BlockWord = new BlockWordViewModel(options.BlockWord);
Plugin = new ObservableCollection<TagInfoProviderViewModel>(
options.Plugin.Select(p => new TagInfoProviderViewModel(p)));
BlockWord = new BlockWordViewModel(options);
TagInfoProviders = new ObservableCollection<TagInfoProviderViewModel>(options.Provider.Tag.Plugin.Select(p => new TagInfoProviderViewModel(p)));
}
public BlockWordViewModel BlockWord { get; }
public ObservableCollection<TagInfoProviderViewModel> Plugin { get; }
public ObservableCollection<TagInfoProviderViewModel> TagInfoProviders { get; }
}