Fixed visible books count not updating
This commit is contained in:
parent
e9a331292a
commit
720fd64c97
@ -0,0 +1,53 @@
|
||||
<TemplatedControl 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:controls="clr-namespace:LibationWinForms.AvaloniaUI.Controls"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="LibationWinForms.AvaloniaUI.Controls.DirectorySelectControl">
|
||||
|
||||
<Design.DataContext>
|
||||
</Design.DataContext>
|
||||
|
||||
|
||||
<TemplatedControl.Styles>
|
||||
<Style Selector="controls|DirectorySelectControl Border">
|
||||
<Setter Property="BorderBrush" Value="DarkGray" />
|
||||
</Style>
|
||||
<Style Selector="controls|DirectorySelectControl">
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate>
|
||||
|
||||
|
||||
<StackPanel Orientation="Vertical">
|
||||
<StackPanel.Styles>
|
||||
<Style Selector="ItemsPresenter#PART_ItemsPresenter">
|
||||
<Setter Property="Height" Value="NaN"/>
|
||||
</Style>
|
||||
</StackPanel.Styles>
|
||||
<ComboBox
|
||||
HorizontalContentAlignment = "Stretch"
|
||||
HorizontalAlignment = "Stretch"
|
||||
VerticalAlignment="Stretch"
|
||||
VerticalContentAlignment="Stretch"
|
||||
SelectedItem="{Binding SelectedComboBoxItem, Mode=TwoWay}"
|
||||
Items="{Binding ComboBoxItems}">
|
||||
<ComboBox.ItemTemplate>
|
||||
<DataTemplate>
|
||||
|
||||
<TextBlock
|
||||
FontSize="12"
|
||||
Text="{Binding Description}" />
|
||||
|
||||
</DataTemplate>
|
||||
</ComboBox.ItemTemplate>
|
||||
</ComboBox>
|
||||
<TextBox Margin="0,10,0,10" Text="{Binding SelectedComboBoxItem.UiDisplayPath}" />
|
||||
</StackPanel>
|
||||
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
</Style>
|
||||
</TemplatedControl.Styles>
|
||||
|
||||
</TemplatedControl>
|
||||
@ -0,0 +1,146 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using Dinah.Core;
|
||||
using LibationFileManager;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using ReactiveUI;
|
||||
using Avalonia.Controls.Primitives;
|
||||
using System.Collections;
|
||||
using Avalonia.Data.Converters;
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using Avalonia.Data;
|
||||
|
||||
namespace LibationWinForms.AvaloniaUI.Controls
|
||||
{
|
||||
public class TextCaseConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
if (value is Configuration.KnownDirectories dir)
|
||||
{
|
||||
|
||||
}
|
||||
return new BindingNotification(new InvalidCastException(), BindingErrorType.Error);
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
public partial class DirectorySelectControl : TemplatedControl
|
||||
{
|
||||
private static readonly List<Configuration.KnownDirectories> defaultList = new List<Configuration.KnownDirectories>()
|
||||
{
|
||||
Configuration.KnownDirectories.WinTemp,
|
||||
Configuration.KnownDirectories.UserProfile,
|
||||
Configuration.KnownDirectories.AppDir,
|
||||
Configuration.KnownDirectories.MyDocs,
|
||||
Configuration.KnownDirectories.LibationFiles
|
||||
};
|
||||
public static readonly StyledProperty<Configuration.KnownDirectories?> SelectedirectoryProperty =
|
||||
AvaloniaProperty.Register<DirectorySelectControl, Configuration.KnownDirectories?>(nameof(Selectedirectory), defaultList[0]);
|
||||
|
||||
public static readonly StyledProperty<List<Configuration.KnownDirectories>> KnownDirectoriesProperty =
|
||||
AvaloniaProperty.Register<DirectorySelectControl, List<Configuration.KnownDirectories>>(nameof(KnownDirectories), defaultList);
|
||||
|
||||
public static readonly StyledProperty<string?> SubdirectoryProperty =
|
||||
AvaloniaProperty.Register<DirectorySelectControl, string?>(nameof(Subdirectory), "subdir");
|
||||
|
||||
DirectorySelectViewModel DirectorySelect { get; } = new();
|
||||
public DirectorySelectControl()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
DirectorySelect.Directories.Clear();
|
||||
|
||||
int insertIndex = 0;
|
||||
foreach (var kd in KnownDirectories.Distinct())
|
||||
DirectorySelect.Directories.Insert(insertIndex++, new(this, kd));
|
||||
|
||||
DataContext = DirectorySelect;
|
||||
base.OnInitialized();
|
||||
}
|
||||
|
||||
public List<Configuration.KnownDirectories> KnownDirectories
|
||||
{
|
||||
get { return GetValue(KnownDirectoriesProperty); }
|
||||
set
|
||||
{
|
||||
SetValue(KnownDirectoriesProperty, value);
|
||||
//SetDirectoryItems(KnownDirectories);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public Configuration.KnownDirectories? Selectedirectory
|
||||
{
|
||||
get { return GetValue(SelectedirectoryProperty); }
|
||||
set
|
||||
{
|
||||
SetValue(SelectedirectoryProperty, value);
|
||||
|
||||
if (value is null or Configuration.KnownDirectories.None)
|
||||
return;
|
||||
|
||||
// set default
|
||||
var item = DirectorySelect.Directories.SingleOrDefault(item => item.Value == value.Value);
|
||||
if (item is null)
|
||||
return;
|
||||
|
||||
DirectorySelect.SelectedDirectory = item;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public string? Subdirectory
|
||||
{
|
||||
get { return GetValue(SubdirectoryProperty); }
|
||||
set
|
||||
{
|
||||
SetValue(SubdirectoryProperty, value);
|
||||
}
|
||||
}
|
||||
|
||||
private void InitializeComponent()
|
||||
{
|
||||
AvaloniaXamlLoader.Load(this);
|
||||
}
|
||||
}
|
||||
|
||||
public class DirectorySelectViewModel : ViewModels.ViewModelBase
|
||||
{
|
||||
public class DirectoryComboBoxItem
|
||||
{
|
||||
private readonly DirectorySelectControl _parentControl;
|
||||
public string Description { get; }
|
||||
public Configuration.KnownDirectories Value { get; }
|
||||
|
||||
public string FullPath => AddSubDirectoryToPath(Configuration.GetKnownDirectoryPath(Value));
|
||||
|
||||
/// <summary>Displaying relative paths is confusing. UI should display absolute equivalent</summary>
|
||||
public string UiDisplayPath => Value == Configuration.KnownDirectories.AppDir ? AddSubDirectoryToPath(Configuration.AppDir_Absolute) : FullPath;
|
||||
|
||||
public DirectoryComboBoxItem(DirectorySelectControl parentControl, Configuration.KnownDirectories knownDirectory)
|
||||
{
|
||||
_parentControl = parentControl;
|
||||
Value = knownDirectory;
|
||||
Description = Value.GetDescription();
|
||||
}
|
||||
|
||||
internal string AddSubDirectoryToPath(string path) => string.IsNullOrWhiteSpace(_parentControl.Subdirectory) ? path : System.IO.Path.Combine(path, _parentControl.Subdirectory);
|
||||
|
||||
public override string ToString() => Description;
|
||||
}
|
||||
public ObservableCollection<DirectoryComboBoxItem> Directories { get; } = new(new());
|
||||
private DirectoryComboBoxItem _selectedDirectory;
|
||||
public DirectoryComboBoxItem SelectedDirectory { get => _selectedDirectory; set => this.RaiseAndSetIfChanged(ref _selectedDirectory, value); }
|
||||
}
|
||||
}
|
||||
@ -86,10 +86,8 @@ namespace LibationWinForms.AvaloniaUI.ViewModels
|
||||
GridEntries = new GridEntryCollection(CreateGridEntries(dbBooks));
|
||||
GridEntries.CollapseAll();
|
||||
|
||||
int bookEntryCount = GridEntries.BookEntries().Count();
|
||||
|
||||
InitialLoaded?.Invoke(this, EventArgs.Empty);
|
||||
VisibleCountChanged?.Invoke(this, bookEntryCount);
|
||||
VisibleCountChanged?.Invoke(this, GridEntries.BookEntries().Count());
|
||||
|
||||
RegisterCollectionChanged();
|
||||
}
|
||||
@ -112,7 +110,12 @@ namespace LibationWinForms.AvaloniaUI.ViewModels
|
||||
|
||||
var existingSeriesEntries = GridEntries.AllItems().SeriesEntries().ToList();
|
||||
|
||||
await Dispatcher.UIThread.InvokeAsync(() => GridEntries.ReplaceList(newEntries));
|
||||
await Dispatcher.UIThread.InvokeAsync(() =>
|
||||
{
|
||||
GridEntries.ReplaceList(newEntries);
|
||||
GridEntries.Filter = existingFilter;
|
||||
ReSort();
|
||||
});
|
||||
|
||||
//We're replacing the list, so preserve usere's existing collapse/expand
|
||||
//state. When resetting a list, default state is open.
|
||||
@ -122,11 +125,8 @@ namespace LibationWinForms.AvaloniaUI.ViewModels
|
||||
if (sEntry is SeriesEntry se && !series.Liberate.Expanded)
|
||||
await Dispatcher.UIThread.InvokeAsync(() => GridEntries.CollapseItem(se));
|
||||
}
|
||||
await Dispatcher.UIThread.InvokeAsync(() =>
|
||||
{
|
||||
GridEntries.Filter = existingFilter;
|
||||
ReSort();
|
||||
});
|
||||
|
||||
await Dispatcher.UIThread.InvokeAsync(() => VisibleCountChanged?.Invoke(this, GridEntries.BookEntries().Count()));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
@ -36,6 +36,7 @@
|
||||
Width="60"
|
||||
Height="30"
|
||||
Content="X"
|
||||
IsEnabled="{Binding !IsDefault}"
|
||||
Click="DeleteButton_Clicked" />
|
||||
|
||||
</DataTemplate>
|
||||
@ -50,6 +51,7 @@
|
||||
Width="60"
|
||||
Height="30"
|
||||
Content="Export"
|
||||
IsEnabled="{Binding !IsDefault}"
|
||||
ToolTip.Tip="Export account authorization to audible-cli"
|
||||
Click="ExportButton_Clicked" />
|
||||
|
||||
@ -71,13 +73,13 @@
|
||||
<DataTemplate>
|
||||
<ComboBox
|
||||
MinHeight="30"
|
||||
HorizontalAlignment="Center"
|
||||
HorizontalContentAlignment = "Stretch"
|
||||
HorizontalAlignment = "Stretch"
|
||||
SelectedItem="{Binding SelectedLocale, Mode=TwoWay}"
|
||||
Items="{Binding Locales}">
|
||||
|
||||
<ComboBox.ItemTemplate>
|
||||
<DataTemplate>
|
||||
|
||||
<TextBlock ZIndex="2"
|
||||
FontSize="12"
|
||||
Text="{Binding Name}" />
|
||||
@ -101,26 +103,12 @@
|
||||
Margin="10"
|
||||
ColumnDefinitions="*,Auto" >
|
||||
|
||||
<StackPanel
|
||||
Grid.Column="0"
|
||||
Orientation="Horizontal">
|
||||
|
||||
<Button
|
||||
Grid.Column="0"
|
||||
Height="30"
|
||||
Content="Add an Account"
|
||||
Name="AddAccountButton"
|
||||
Click="AddAccountButton_Clicked" />
|
||||
|
||||
<Button
|
||||
Grid.Column="0"
|
||||
Height="30"
|
||||
Margin="20,0,0,0"
|
||||
Content="Import from audible-cli"
|
||||
Click="ImportButton_Clicked" />
|
||||
|
||||
</StackPanel>
|
||||
|
||||
<Button
|
||||
Grid.Column="1"
|
||||
Height="30"
|
||||
|
||||
@ -1,34 +1,52 @@
|
||||
using AudibleUtilities;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using ReactiveUI;
|
||||
using AudibleApi;
|
||||
|
||||
namespace LibationWinForms.AvaloniaUI.Views.Dialogs
|
||||
{
|
||||
public partial class AccountsDialog : DialogWindow
|
||||
{
|
||||
public ObservableCollection<AccountDto> Accounts { get; } = new();
|
||||
public class AccountDto
|
||||
public class AccountDto : ViewModels.ViewModelBase
|
||||
{
|
||||
public IList<AudibleApi.Locale> Locales { get; init; }
|
||||
private string _accountId;
|
||||
private Locale _selectedLocale;
|
||||
public IReadOnlyList<Locale> Locales => AccountsDialog.Locales;
|
||||
public bool LibraryScan { get; set; } = true;
|
||||
public string AccountId { get; set; }
|
||||
public AudibleApi.Locale SelectedLocale { get; set; }
|
||||
public string AccountId
|
||||
{
|
||||
get => _accountId;
|
||||
set
|
||||
{
|
||||
this.RaiseAndSetIfChanged(ref _accountId, value);
|
||||
this.RaisePropertyChanged(nameof(IsDefault));
|
||||
}
|
||||
}
|
||||
public Locale SelectedLocale
|
||||
{
|
||||
get => _selectedLocale;
|
||||
set
|
||||
{
|
||||
this.RaiseAndSetIfChanged(ref _selectedLocale, value);
|
||||
this.RaisePropertyChanged(nameof(IsDefault));
|
||||
}
|
||||
}
|
||||
public string AccountName { get; set; }
|
||||
public bool IsDefault => AccountId is null && SelectedLocale is null && AccountName is null;
|
||||
public bool IsDefault => string.IsNullOrEmpty(AccountId) && SelectedLocale is null;
|
||||
}
|
||||
|
||||
private static string GetAudibleCliAppDataPath()
|
||||
=> Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Audible");
|
||||
|
||||
private List<AudibleApi.Locale> Locales => AudibleApi.Localization.Locales.OrderBy(l => l.Name).ToList();
|
||||
private static IReadOnlyList<Locale> Locales => Localization.Locales.OrderBy(l => l.Name).ToList();
|
||||
public AccountsDialog()
|
||||
{
|
||||
InitializeComponent();
|
||||
@ -41,26 +59,51 @@ namespace LibationWinForms.AvaloniaUI.Views.Dialogs
|
||||
if (!accounts.Any())
|
||||
return;
|
||||
|
||||
|
||||
ControlToFocusOnShow = this.FindControl<Button>(nameof(AddAccountButton));
|
||||
|
||||
DataContext = this;
|
||||
|
||||
foreach (var account in accounts)
|
||||
AddAccountToGrid(account);
|
||||
|
||||
var newBlank = new AccountDto();
|
||||
newBlank.PropertyChanged += AccountDto_PropertyChanged;
|
||||
Accounts.Insert(Accounts.Count, newBlank);
|
||||
}
|
||||
|
||||
private void AddAccountToGrid(Account account)
|
||||
{
|
||||
//ObservableCollection doesn't fire CollectionChanged on Add, so use Insert instead
|
||||
Accounts.Insert(Accounts.Count, new()
|
||||
AccountDto accountDto = new()
|
||||
{
|
||||
LibraryScan = account.LibraryScan,
|
||||
AccountId = account.AccountId,
|
||||
SelectedLocale = Locales.Single(l => l.Name == account.Locale.Name),
|
||||
AccountName = account.AccountName,
|
||||
Locales = Locales
|
||||
});
|
||||
};
|
||||
accountDto.PropertyChanged += AccountDto_PropertyChanged;
|
||||
|
||||
//ObservableCollection doesn't fire CollectionChanged on Add, so use Insert instead
|
||||
Accounts.Insert(Accounts.Count, accountDto);
|
||||
}
|
||||
|
||||
private void AccountDto_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
|
||||
{
|
||||
if (Accounts.Any(a => a.IsDefault))
|
||||
return;
|
||||
|
||||
var newBlank = new AccountDto();
|
||||
newBlank.PropertyChanged += AccountDto_PropertyChanged;
|
||||
Accounts.Insert(Accounts.Count, newBlank);
|
||||
}
|
||||
|
||||
public void DeleteButton_Clicked(object sender, Avalonia.Interactivity.RoutedEventArgs e)
|
||||
{
|
||||
if (e.Source is Button expBtn && expBtn.DataContext is AccountDto acc)
|
||||
{
|
||||
var index = Accounts.IndexOf(acc);
|
||||
if (index < 0) return;
|
||||
|
||||
acc.PropertyChanged -= AccountDto_PropertyChanged;
|
||||
Accounts.Remove(acc);
|
||||
}
|
||||
}
|
||||
|
||||
public async void ImportButton_Clicked(object sender, Avalonia.Interactivity.RoutedEventArgs e)
|
||||
@ -109,21 +152,6 @@ namespace LibationWinForms.AvaloniaUI.Views.Dialogs
|
||||
}
|
||||
}
|
||||
|
||||
public void AddAccountButton_Clicked(object sender, Avalonia.Interactivity.RoutedEventArgs e)
|
||||
{
|
||||
if (Accounts.Any(a => a.IsDefault))
|
||||
return;
|
||||
|
||||
//ObservableCollection doesn't fire CollectionChanged on Add, so use Insert instead
|
||||
Accounts.Insert(Accounts.Count, new() { Locales = Locales });
|
||||
}
|
||||
|
||||
public void DeleteButton_Clicked(object sender, Avalonia.Interactivity.RoutedEventArgs e)
|
||||
{
|
||||
if (e.Source is Button expBtn && expBtn.DataContext is AccountDto acc)
|
||||
Accounts.Remove(acc);
|
||||
}
|
||||
|
||||
public void ExportButton_Clicked(object sender, Avalonia.Interactivity.RoutedEventArgs e)
|
||||
{
|
||||
if (e.Source is Button expBtn && expBtn.DataContext is AccountDto acc)
|
||||
@ -177,7 +205,7 @@ namespace LibationWinForms.AvaloniaUI.Views.Dialogs
|
||||
var existing = existingAccounts[i];
|
||||
if (!Accounts.Any(dto =>
|
||||
dto.AccountId?.ToLower().Trim() == existing.AccountId.ToLower()
|
||||
&& dto.SelectedLocale.Name == existing.Locale?.Name))
|
||||
&& dto.SelectedLocale?.Name == existing.Locale?.Name))
|
||||
{
|
||||
accountsSettings.Delete(existing);
|
||||
}
|
||||
@ -186,11 +214,11 @@ namespace LibationWinForms.AvaloniaUI.Views.Dialogs
|
||||
// upsert each. validation occurs through Account and AccountsSettings
|
||||
foreach (var dto in Accounts)
|
||||
{
|
||||
var acct = accountsSettings.Upsert(dto.AccountId, dto.SelectedLocale.Name);
|
||||
var acct = accountsSettings.Upsert(dto.AccountId, dto.SelectedLocale?.Name);
|
||||
acct.LibraryScan = dto.LibraryScan;
|
||||
acct.AccountName
|
||||
= string.IsNullOrWhiteSpace(dto.AccountName)
|
||||
? $"{dto.AccountId} - {dto.SelectedLocale.Name}"
|
||||
? $"{dto.AccountId} - {dto.SelectedLocale?.Name}"
|
||||
: dto.AccountName.Trim();
|
||||
}
|
||||
}
|
||||
@ -210,7 +238,7 @@ namespace LibationWinForms.AvaloniaUI.Views.Dialogs
|
||||
return false;
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(dto.SelectedLocale.Name))
|
||||
if (string.IsNullOrWhiteSpace(dto.SelectedLocale?.Name))
|
||||
{
|
||||
await MessageBox.Show(this, "Please select a locale (i.e.: country or region) for all accounts.", "Blank region", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
return false;
|
||||
@ -225,7 +253,7 @@ namespace LibationWinForms.AvaloniaUI.Views.Dialogs
|
||||
// without transaction, accounts persister will write ANY EDIT immediately to file
|
||||
using var persister = AudibleApiStorage.GetAccountsSettingsPersister();
|
||||
|
||||
var account = persister.AccountsSettings.Accounts.FirstOrDefault(a => a.AccountId == acc.AccountId && a.Locale.Name == acc.SelectedLocale.Name);
|
||||
var account = persister.AccountsSettings.Accounts.FirstOrDefault(a => a.AccountId == acc.AccountId && a.Locale.Name == acc.SelectedLocale?.Name);
|
||||
|
||||
if (account is null)
|
||||
return;
|
||||
|
||||
@ -0,0 +1,406 @@
|
||||
<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"
|
||||
mc:Ignorable="d" d:DesignWidth="900" d:DesignHeight="600"
|
||||
x:Class="LibationWinForms.AvaloniaUI.Views.Dialogs.SettingsDialog"
|
||||
xmlns:controls="clr-namespace:LibationWinForms.AvaloniaUI.Controls"
|
||||
Title="Edit Settings"
|
||||
Icon="/AvaloniaUI/Assets/libation.ico">
|
||||
|
||||
<Grid RowDefinitions="*,Auto">
|
||||
|
||||
<Button
|
||||
Grid.Row="1"
|
||||
Margin="10"
|
||||
HorizontalAlignment="Right"
|
||||
Height="30"
|
||||
Padding="30,3,30,3"
|
||||
Content="Save"
|
||||
Click="SaveButton_Clicked" />
|
||||
|
||||
<TabControl Grid.Column="0">
|
||||
<TabControl.Styles>
|
||||
<Style Selector="ItemsPresenter#PART_ItemsPresenter">
|
||||
<Setter Property="Height" Value="33"/>
|
||||
</Style>
|
||||
<Style Selector="TextBlock">
|
||||
<Setter Property="FontSize" Value="12"/>
|
||||
</Style>
|
||||
</TabControl.Styles>
|
||||
|
||||
<TabItem>
|
||||
|
||||
<TabItem.Header>
|
||||
|
||||
<TextBlock
|
||||
FontSize="14"
|
||||
VerticalAlignment="Center"
|
||||
Text="Download/Decrypt"/>
|
||||
|
||||
</TabItem.Header>
|
||||
<Border
|
||||
Grid.Column="0"
|
||||
Grid.Row="0"
|
||||
BorderThickness="2"
|
||||
Background="WhiteSmoke"
|
||||
BorderBrush="{DynamicResource DataGridGridLinesBrush}">
|
||||
|
||||
<Grid RowDefinitions="Auto,Auto,*">
|
||||
<controls:GroupBox Grid.Row="0" BorderWidth="1" Label="{Binding DownloadDecryptSettings.BadBookGroupboxText}">
|
||||
|
||||
<Grid ColumnDefinitions="*,*" RowDefinitions="Auto,Auto">
|
||||
|
||||
<RadioButton
|
||||
Grid.Column="0"
|
||||
Grid.Row="0"
|
||||
Margin="0,5,0,5"
|
||||
IsChecked="{Binding DownloadDecryptSettings.BadBookAsk, Mode=TwoWay}">
|
||||
<TextBlock Text="{Binding DownloadDecryptSettings.BadBookAskText}" />
|
||||
</RadioButton>
|
||||
<RadioButton
|
||||
Grid.Column="1"
|
||||
Grid.Row="0"
|
||||
Margin="0,5,0,5"
|
||||
IsChecked="{Binding DownloadDecryptSettings.BadBookAbort, Mode=TwoWay}">
|
||||
<TextBlock Text="{Binding DownloadDecryptSettings.BadBookAbortText}" />
|
||||
</RadioButton>
|
||||
<RadioButton
|
||||
Grid.Column="0"
|
||||
Grid.Row="1"
|
||||
Margin="0,5,0,5"
|
||||
IsChecked="{Binding DownloadDecryptSettings.BadBookRetry, Mode=TwoWay}">
|
||||
<TextBlock Text="{Binding DownloadDecryptSettings.BadBookRetryText}" />
|
||||
</RadioButton>
|
||||
<RadioButton
|
||||
Grid.Column="1"
|
||||
Grid.Row="1"
|
||||
Margin="0,5,0,5"
|
||||
IsChecked="{Binding DownloadDecryptSettings.BadBookIgnore, Mode=TwoWay}">
|
||||
<TextBlock Text="{Binding DownloadDecryptSettings.BadBookIgnoreText}" />
|
||||
</RadioButton>
|
||||
|
||||
</Grid>
|
||||
</controls:GroupBox>
|
||||
|
||||
<controls:GroupBox Grid.Row="1" BorderWidth="1" Label="Custom File Naming">
|
||||
|
||||
<Grid RowDefinitions="Auto,Auto,Auto,Auto" ColumnDefinitions="*,Auto">
|
||||
|
||||
<TextBox
|
||||
Grid.Row="0"
|
||||
Grid.Column="0"
|
||||
Margin="0,10,10,10"
|
||||
FontSize="14"
|
||||
IsReadOnly="True"
|
||||
Text="{Binding DownloadDecryptSettings.FolderTemplate}" />
|
||||
|
||||
<Button
|
||||
Grid.Row="0"
|
||||
Grid.Column="1"
|
||||
Content="Edit"
|
||||
Height="30"
|
||||
Padding="30,3,30,3"
|
||||
Click="EditFolderTemplateButton_Click" />
|
||||
|
||||
<TextBox
|
||||
Grid.Row="1"
|
||||
Grid.Column="0"
|
||||
Margin="0,10,10,10"
|
||||
FontSize="14"
|
||||
IsReadOnly="True"
|
||||
Text="{Binding DownloadDecryptSettings.FileTemplate}" />
|
||||
|
||||
<Button
|
||||
Grid.Row="1"
|
||||
Grid.Column="1"
|
||||
Content="Edit"
|
||||
Height="30"
|
||||
Padding="30,3,30,3"
|
||||
Click="EditFileTemplateButton_Click" />
|
||||
|
||||
<TextBox
|
||||
Grid.Row="2"
|
||||
Grid.Column="0"
|
||||
Margin="0,10,10,10"
|
||||
FontSize="14"
|
||||
IsReadOnly="True"
|
||||
Text="{Binding DownloadDecryptSettings.ChapterFileTemplate}" />
|
||||
|
||||
<Button
|
||||
Grid.Row="2"
|
||||
Grid.Column="1"
|
||||
Content="Edit"
|
||||
Height="30"
|
||||
Padding="30,3,30,3"
|
||||
Click="EditChapterFileTemplateButton_Click" />
|
||||
|
||||
<Button
|
||||
Grid.Row="3"
|
||||
Grid.Column="0"
|
||||
Content="{Binding DownloadDecryptSettings.EditCharReplacementText}"
|
||||
Height="30"
|
||||
Padding="30,3,30,3"
|
||||
Click="EditChapterTitleTemplateButton_Click" />
|
||||
|
||||
</Grid>
|
||||
|
||||
</controls:GroupBox>
|
||||
|
||||
<controls:DirectorySelectControl
|
||||
Grid.Row="2"
|
||||
Subdirectory="{Binding DownloadDecryptSettings.EditCharReplacementText}"
|
||||
KnownDirectories="{Binding DownloadDecryptSettings.KnownDirectories}"
|
||||
Selectedirectory="{Binding DownloadDecryptSettings.SelectedDirectory, Mode=TwoWay}" />
|
||||
|
||||
</Grid>
|
||||
|
||||
</Border>
|
||||
|
||||
</TabItem>
|
||||
|
||||
<TabItem>
|
||||
|
||||
<TabItem.Header>
|
||||
|
||||
<TextBlock
|
||||
FontSize="14"
|
||||
VerticalAlignment="Center"
|
||||
Text="Audio File Settings"/>
|
||||
|
||||
</TabItem.Header>
|
||||
<Border
|
||||
Grid.Column="0"
|
||||
Grid.Row="0"
|
||||
BorderThickness="2"
|
||||
Background="WhiteSmoke"
|
||||
BorderBrush="{DynamicResource DataGridGridLinesBrush}">
|
||||
|
||||
<Grid
|
||||
RowDefinitions="*,Auto"
|
||||
ColumnDefinitions="*,*">
|
||||
|
||||
<StackPanel Margin="5"
|
||||
Grid.Row="0"
|
||||
Grid.Column="0">
|
||||
|
||||
<CheckBox IsChecked="{Binding AudioSettings.CreateCueSheet, Mode=TwoWay}">
|
||||
<TextBlock Text="{Binding AudioSettings.CreateCueSheetText}" />
|
||||
</CheckBox>
|
||||
<CheckBox IsChecked="{Binding AudioSettings.DownloadCoverArt, Mode=TwoWay}">
|
||||
<TextBlock Text="{Binding AudioSettings.DownloadCoverArtText}" />
|
||||
</CheckBox>
|
||||
<CheckBox IsChecked="{Binding AudioSettings.RetainAaxFile, Mode=TwoWay}">
|
||||
<TextBlock Text="{Binding AudioSettings.RetainAaxFileText}" />
|
||||
</CheckBox>
|
||||
<CheckBox IsChecked="{Binding AudioSettings.MergeOpeningAndEndCredits, Mode=TwoWay}">
|
||||
<TextBlock Text="{Binding AudioSettings.MergeOpeningEndCreditsText}" />
|
||||
</CheckBox>
|
||||
<CheckBox IsChecked="{Binding AudioSettings.AllowLibationFixup, Mode=TwoWay}">
|
||||
<TextBlock Text="{Binding AudioSettings.AllowLibationFixupText}" />
|
||||
</CheckBox>
|
||||
|
||||
<controls:GroupBox BorderWidth="1" Label="Audiobook Fix-ups" IsEnabled="{Binding AudioSettings.AllowLibationFixup}">
|
||||
<StackPanel Orientation="Vertical">
|
||||
<CheckBox IsChecked="{Binding AudioSettings.SplitFilesByChapter, Mode=TwoWay}">
|
||||
<TextBlock Text="{Binding AudioSettings.SplitFilesByChapterText}" />
|
||||
</CheckBox>
|
||||
|
||||
<CheckBox IsChecked="{Binding AudioSettings.StripAudibleBrandAudio, Mode=TwoWay}">
|
||||
<TextBlock Text="{Binding AudioSettings.StripAudibleBrandingText}" />
|
||||
</CheckBox>
|
||||
|
||||
<CheckBox IsChecked="{Binding AudioSettings.StripUnabridged, Mode=TwoWay}">
|
||||
<TextBlock Text="{Binding AudioSettings.StripUnabridgedText}" />
|
||||
</CheckBox>
|
||||
|
||||
<RadioButton Margin="0,5,0,5" IsChecked="{Binding !AudioSettings.DecryptToLossy, Mode=TwoWay}">
|
||||
<TextBlock Text="Download my books in the original audio format (Lossless)" />
|
||||
</RadioButton>
|
||||
|
||||
<RadioButton Margin="0,5,0,5" IsChecked="{Binding AudioSettings.DecryptToLossy, Mode=TwoWay}">
|
||||
<TextBlock Text="Download my books as .MP3 files (transcode if necessary)" />
|
||||
</RadioButton>
|
||||
|
||||
</StackPanel>
|
||||
|
||||
</controls:GroupBox>
|
||||
|
||||
</StackPanel>
|
||||
|
||||
|
||||
<StackPanel
|
||||
Grid.Row="0"
|
||||
Grid.Column="1">
|
||||
|
||||
<controls:GroupBox BorderWidth="1" Label="Mp3 Encoding Options">
|
||||
|
||||
<StackPanel Orientation="Vertical">
|
||||
<Grid Margin="5,5,5,0" ColumnDefinitions="Auto,*">
|
||||
|
||||
<controls:GroupBox BorderWidth="1" Grid.Column="0" Label="Target">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
|
||||
<RadioButton Margin="10" IsChecked="{Binding AudioSettings.LameTargetBitrate, Mode=TwoWay}">
|
||||
<TextBlock Text="Bitrate" />
|
||||
</RadioButton>
|
||||
|
||||
<RadioButton Margin="10" IsChecked="{Binding !AudioSettings.LameTargetBitrate, Mode=TwoWay}">
|
||||
<TextBlock Text="Quality" />
|
||||
</RadioButton>
|
||||
|
||||
</StackPanel>
|
||||
</controls:GroupBox>
|
||||
|
||||
<CheckBox HorizontalAlignment="Right" Grid.Column="1" IsChecked="{Binding AudioSettings.LameDownsampleMono, Mode=TwoWay}">
|
||||
<TextBlock Text="Downsample to mono?
(Recommended)" />
|
||||
</CheckBox>
|
||||
</Grid>
|
||||
<controls:GroupBox Margin="5,5,5,0" BorderWidth="1" Label="Bitrate" IsEnabled="{Binding AudioSettings.LameTargetBitrate}" >
|
||||
<StackPanel>
|
||||
<Grid ColumnDefinitions="*,25,Auto">
|
||||
<Slider
|
||||
Grid.Column="0"
|
||||
IsEnabled="{Binding !AudioSettings.LameMatchSource}"
|
||||
Value="{Binding AudioSettings.LameBitrate, Mode=TwoWay}"
|
||||
Minimum="16"
|
||||
Maximum="320"
|
||||
IsSnapToTickEnabled="True" TickFrequency="16"
|
||||
Ticks="16,32,48,64,80,96,112,128,144,160,176,192,208,224,240,256,272,288,304,320"
|
||||
TickPlacement="Outside">
|
||||
<Slider.Styles>
|
||||
<Style Selector="Slider /template/ Thumb">
|
||||
<Setter Property="ToolTip.Tip" Value="{Binding $parent[Slider].Value, Mode=OneWay, StringFormat='\{0:f0\} Kbps'}" />
|
||||
<Setter Property="ToolTip.Placement" Value="Top" />
|
||||
<Setter Property="ToolTip.VerticalOffset" Value="-10" />
|
||||
<Setter Property="ToolTip.HorizontalOffset" Value="-30" />
|
||||
</Style>
|
||||
</Slider.Styles>
|
||||
</Slider>
|
||||
<TextBlock Grid.Column="1" HorizontalAlignment="Right" Text="{Binding AudioSettings.LameBitrate}" />
|
||||
<TextBlock Grid.Column="2" Text=" Kbps" />
|
||||
</Grid>
|
||||
<Grid ColumnDefinitions="Auto,*">
|
||||
|
||||
<CheckBox Grid.Column="0" IsChecked="{Binding AudioSettings.LameConstantBitrate, Mode=TwoWay}">
|
||||
<TextBlock Text="Restrict Encoder to Constant Bitrate?" />
|
||||
</CheckBox>
|
||||
<CheckBox Grid.Column="1" IsChecked="{Binding AudioSettings.LameMatchSource, Mode=TwoWay}" HorizontalAlignment="Right">
|
||||
<TextBlock Text="Match Source Bitrate?" />
|
||||
</CheckBox>
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
</controls:GroupBox>
|
||||
|
||||
<controls:GroupBox Margin="5,5,5,0" BorderWidth="1" Label="Quality" IsEnabled="{Binding !AudioSettings.LameTargetBitrate}" >
|
||||
<Grid ColumnDefinitions="*,*,25" RowDefinitions="*,Auto">
|
||||
<Slider
|
||||
Grid.Column="0"
|
||||
Grid.ColumnSpan="2"
|
||||
Value="{Binding AudioSettings.LameVBRQuality, Mode=TwoWay}"
|
||||
Minimum="0"
|
||||
Maximum="9"
|
||||
IsSnapToTickEnabled="True" TickFrequency="1"
|
||||
Ticks="0,1,2,3,4,5,6,7,8,9"
|
||||
TickPlacement="Outside">
|
||||
<Slider.Styles>
|
||||
<Style Selector="Slider /template/ Thumb">
|
||||
<Setter Property="ToolTip.Tip" Value="{Binding $parent[Slider].Value, Mode=OneWay, StringFormat='V\{0:f0\}'}" />
|
||||
<Setter Property="ToolTip.Placement" Value="Top" />
|
||||
<Setter Property="ToolTip.VerticalOffset" Value="-10" />
|
||||
<Setter Property="ToolTip.HorizontalOffset" Value="-30" />
|
||||
</Style>
|
||||
</Slider.Styles>
|
||||
</Slider>
|
||||
<StackPanel Grid.Column="2" HorizontalAlignment="Right" Orientation="Horizontal">
|
||||
<TextBlock Text="V" />
|
||||
<TextBlock Text="{Binding AudioSettings.LameVBRQuality}" />
|
||||
</StackPanel>
|
||||
<TextBlock Margin="10,0,0,0" Grid.Column="0" Grid.Row="1" Text="Higher" />
|
||||
<TextBlock Margin="0,0,10,0" Grid.Column="1" Grid.Row="1" HorizontalAlignment="Right" Text="Lower" />
|
||||
|
||||
</Grid>
|
||||
</controls:GroupBox>
|
||||
|
||||
<TextBlock Margin="5,5,5,5" Text="Using L.A.M.E encoding engine" FontStyle="Italic" />
|
||||
|
||||
</StackPanel>
|
||||
</controls:GroupBox>
|
||||
|
||||
|
||||
</StackPanel>
|
||||
|
||||
<controls:GroupBox
|
||||
Grid.Row="1"
|
||||
Grid.ColumnSpan="2"
|
||||
Margin="5"
|
||||
BorderWidth="1" IsEnabled="{Binding AudioSettings.SplitFilesByChapter}"
|
||||
Label="{Binding AudioSettings.ChapterTitleTemplateText}">
|
||||
<Grid ColumnDefinitions="*,Auto">
|
||||
<TextBox
|
||||
Grid.Column="0"
|
||||
Margin="0,10,10,10"
|
||||
FontSize="14"
|
||||
IsReadOnly="True"
|
||||
Text="{Binding AudioSettings.ChapterTitleTemplate}" />
|
||||
|
||||
<Button
|
||||
Grid.Column="1"
|
||||
Content="Edit"
|
||||
Height="30"
|
||||
Padding="30,3,30,3"
|
||||
Click="EditChapterTitleTemplateButton_Click" />
|
||||
</Grid>
|
||||
</controls:GroupBox>
|
||||
</Grid>
|
||||
|
||||
</Border>
|
||||
|
||||
</TabItem>
|
||||
|
||||
<TabItem>
|
||||
|
||||
<TabItem.Header>
|
||||
|
||||
<TextBlock
|
||||
FontSize="14"
|
||||
VerticalAlignment="Center"
|
||||
Text="Important Settings"/>
|
||||
|
||||
</TabItem.Header>
|
||||
<Border
|
||||
Grid.Column="0"
|
||||
Grid.Row="0"
|
||||
BorderThickness="2"
|
||||
Background="WhiteSmoke"
|
||||
BorderBrush="{DynamicResource DataGridGridLinesBrush}">
|
||||
|
||||
</Border>
|
||||
|
||||
</TabItem>
|
||||
|
||||
<TabItem>
|
||||
|
||||
<TabItem.Header>
|
||||
|
||||
<TextBlock
|
||||
FontSize="14"
|
||||
VerticalAlignment="Center"
|
||||
Text="Import Library"/>
|
||||
|
||||
</TabItem.Header>
|
||||
<Border
|
||||
Grid.Column="0"
|
||||
Grid.Row="0"
|
||||
BorderThickness="2"
|
||||
Background="WhiteSmoke"
|
||||
BorderBrush="{DynamicResource DataGridGridLinesBrush}">
|
||||
|
||||
</Border>
|
||||
|
||||
</TabItem>
|
||||
|
||||
</TabControl>
|
||||
|
||||
</Grid>
|
||||
</Window>
|
||||
@ -0,0 +1,322 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using LibationFileManager;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using ReactiveUI;
|
||||
using Dinah.Core;
|
||||
|
||||
namespace LibationWinForms.AvaloniaUI.Views.Dialogs
|
||||
{
|
||||
public partial class SettingsDialog : DialogWindow
|
||||
{
|
||||
private SettingsPages settingsDisp;
|
||||
public SettingsDialog()
|
||||
{
|
||||
if (Design.IsDesignMode)
|
||||
AudibleUtilities.AudibleApiStorage.EnsureAccountsSettingsFileExists();
|
||||
InitializeComponent();
|
||||
|
||||
DataContext = settingsDisp = new(Configuration.Instance);
|
||||
}
|
||||
|
||||
private void InitializeComponent()
|
||||
{
|
||||
AvaloniaXamlLoader.Load(this);
|
||||
}
|
||||
protected override async Task SaveAndCloseAsync()
|
||||
{
|
||||
|
||||
|
||||
await base.SaveAndCloseAsync();
|
||||
}
|
||||
public async void SaveButton_Clicked(object sender, Avalonia.Interactivity.RoutedEventArgs e)
|
||||
=> await SaveAndCloseAsync();
|
||||
|
||||
|
||||
|
||||
public void EditFolderTemplateButton_Click(object sender, Avalonia.Interactivity.RoutedEventArgs e)
|
||||
{
|
||||
var newTemplate = editTemplate(Templates.ChapterTitle, settingsDisp.AudioSettings.ChapterTitleTemplate);
|
||||
if (newTemplate is not null)
|
||||
settingsDisp.AudioSettings.ChapterTitleTemplate = newTemplate;
|
||||
}
|
||||
|
||||
|
||||
public void EditFileTemplateButton_Click(object sender, Avalonia.Interactivity.RoutedEventArgs e)
|
||||
{
|
||||
var newTemplate = editTemplate(Templates.ChapterTitle, settingsDisp.AudioSettings.ChapterTitleTemplate);
|
||||
if (newTemplate is not null)
|
||||
settingsDisp.AudioSettings.ChapterTitleTemplate = newTemplate;
|
||||
}
|
||||
|
||||
|
||||
public void EditChapterFileTemplateButton_Click(object sender, Avalonia.Interactivity.RoutedEventArgs e)
|
||||
{
|
||||
var newTemplate = editTemplate(Templates.ChapterTitle, settingsDisp.AudioSettings.ChapterTitleTemplate);
|
||||
if (newTemplate is not null)
|
||||
settingsDisp.AudioSettings.ChapterTitleTemplate = newTemplate;
|
||||
}
|
||||
|
||||
|
||||
public void EditChapterTitleTemplateButton_Click(object sender, Avalonia.Interactivity.RoutedEventArgs e)
|
||||
{
|
||||
var newTemplate = editTemplate(Templates.ChapterTitle, settingsDisp.AudioSettings.ChapterTitleTemplate);
|
||||
if (newTemplate is not null)
|
||||
settingsDisp.AudioSettings.ChapterTitleTemplate = newTemplate;
|
||||
}
|
||||
|
||||
|
||||
private static string editTemplate(Templates template, string existingTemplate)
|
||||
{
|
||||
var form = new LibationWinForms.Dialogs.EditTemplateDialog(template, existingTemplate);
|
||||
if (form.ShowDialog() == System.Windows.Forms.DialogResult.OK)
|
||||
return form.TemplateText;
|
||||
else return null;
|
||||
}
|
||||
|
||||
}
|
||||
internal interface ISettingsTab
|
||||
{
|
||||
void LoadSettings(Configuration config);
|
||||
void SaveSettings(Configuration config);
|
||||
}
|
||||
|
||||
public class SettingsPages
|
||||
{
|
||||
public Configuration config { get; }
|
||||
public SettingsPages(Configuration config)
|
||||
{
|
||||
this.config = config;
|
||||
AudioSettings = new(config);
|
||||
DownloadDecryptSettings = new(config);
|
||||
}
|
||||
public AudioSettings AudioSettings { get;}
|
||||
public DownloadDecryptSettings DownloadDecryptSettings { get;}
|
||||
}
|
||||
|
||||
public class DownloadDecryptSettings : ViewModels.ViewModelBase, ISettingsTab
|
||||
{
|
||||
private static Func<string, string> desc { get; } = Configuration.GetDescription;
|
||||
|
||||
private bool _badBookAsk;
|
||||
private bool _badBookAbort;
|
||||
private bool _badBookRetry;
|
||||
private bool _badBookIgnore;
|
||||
|
||||
private string _folderTemplate;
|
||||
private string _fileTemplate;
|
||||
private string _chapterFileTemplate;
|
||||
|
||||
public DownloadDecryptSettings(Configuration config)
|
||||
{
|
||||
LoadSettings(config);
|
||||
}
|
||||
|
||||
public void LoadSettings(Configuration config)
|
||||
{
|
||||
BadBookAsk = config.BadBook is Configuration.BadBookAction.Ask;
|
||||
BadBookAbort = config.BadBook is Configuration.BadBookAction.Abort;
|
||||
BadBookRetry = config.BadBook is Configuration.BadBookAction.Retry;
|
||||
BadBookIgnore = config.BadBook is Configuration.BadBookAction.Ignore;
|
||||
FolderTemplate = config.FolderTemplate;
|
||||
FileTemplate = config.FileTemplate;
|
||||
ChapterFileTemplate = config.ChapterFileTemplate;
|
||||
}
|
||||
|
||||
public void SaveSettings(Configuration config)
|
||||
{
|
||||
config.BadBook
|
||||
= BadBookAbort ? Configuration.BadBookAction.Abort
|
||||
: BadBookRetry ? Configuration.BadBookAction.Retry
|
||||
: BadBookIgnore ? Configuration.BadBookAction.Ignore
|
||||
: Configuration.BadBookAction.Ask;
|
||||
|
||||
config.FolderTemplate = FolderTemplate;
|
||||
config.FileTemplate = FileTemplate;
|
||||
config.ChapterFileTemplate = ChapterFileTemplate;
|
||||
}
|
||||
|
||||
public string BadBookGroupboxText => desc(nameof(Configuration.BadBook));
|
||||
public string BadBookAskText { get; } = Configuration.BadBookAction.Ask.GetDescription();
|
||||
public string BadBookAbortText { get; } = Configuration.BadBookAction.Abort.GetDescription();
|
||||
public string BadBookRetryText { get; } = Configuration.BadBookAction.Retry.GetDescription();
|
||||
public string BadBookIgnoreText { get; } = Configuration.BadBookAction.Ignore.GetDescription();
|
||||
|
||||
public string FolderTemplateText => desc(nameof(Configuration.FolderTemplate));
|
||||
public string FileTemplateText => desc(nameof(Configuration.FileTemplate));
|
||||
public string ChapterFileTemplateText => desc(nameof(Configuration.ChapterFileTemplate));
|
||||
public string? EditCharReplacementText => desc(nameof(Configuration.ReplacementCharacters));
|
||||
|
||||
public string FolderTemplate { get => _folderTemplate; set { this.RaiseAndSetIfChanged(ref _folderTemplate, value); } }
|
||||
public string FileTemplate { get => _fileTemplate; set { this.RaiseAndSetIfChanged(ref _fileTemplate, value); } }
|
||||
public string ChapterFileTemplate { get => _chapterFileTemplate; set { this.RaiseAndSetIfChanged(ref _chapterFileTemplate, value); } }
|
||||
|
||||
|
||||
public bool BadBookAsk
|
||||
{
|
||||
get => _badBookAsk;
|
||||
set
|
||||
{
|
||||
this.RaiseAndSetIfChanged(ref _badBookAsk, value);
|
||||
if (value)
|
||||
{
|
||||
BadBookAbort = false;
|
||||
BadBookRetry = false;
|
||||
BadBookIgnore = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
public bool BadBookAbort
|
||||
{
|
||||
get => _badBookAbort;
|
||||
set
|
||||
{
|
||||
this.RaiseAndSetIfChanged(ref _badBookAbort, value);
|
||||
if (value)
|
||||
{
|
||||
BadBookAsk = false;
|
||||
BadBookRetry = false;
|
||||
BadBookIgnore = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
public bool BadBookRetry
|
||||
{
|
||||
get => _badBookRetry;
|
||||
set
|
||||
{
|
||||
this.RaiseAndSetIfChanged(ref _badBookRetry, value);
|
||||
if (value)
|
||||
{
|
||||
BadBookAsk = false;
|
||||
BadBookAbort = false;
|
||||
BadBookIgnore = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
public bool BadBookIgnore
|
||||
{
|
||||
get => _badBookIgnore;
|
||||
set
|
||||
{
|
||||
this.RaiseAndSetIfChanged(ref _badBookIgnore, value);
|
||||
if (value)
|
||||
{
|
||||
BadBookAsk = false;
|
||||
BadBookAbort = false;
|
||||
BadBookRetry = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class AudioSettings : ViewModels.ViewModelBase, ISettingsTab
|
||||
{
|
||||
|
||||
private bool _splitFilesByChapter;
|
||||
private bool _allowLibationFixup;
|
||||
private bool _lameTargetBitrate;
|
||||
private bool _lameMatchSource;
|
||||
private int _lameBitrate;
|
||||
private int _lameVBRQuality;
|
||||
private string _chapterTitleTemplate;
|
||||
private static Func<string, string> desc { get; } = Configuration.GetDescription;
|
||||
public AudioSettings(Configuration config)
|
||||
{
|
||||
LoadSettings(config);
|
||||
}
|
||||
public void LoadSettings(Configuration config)
|
||||
{
|
||||
CreateCueSheet = config.CreateCueSheet;
|
||||
AllowLibationFixup = config.AllowLibationFixup;
|
||||
DownloadCoverArt = config.DownloadCoverArt;
|
||||
RetainAaxFile = config.RetainAaxFile;
|
||||
SplitFilesByChapter = config.SplitFilesByChapter;
|
||||
MergeOpeningAndEndCredits = config.MergeOpeningAndEndCredits;
|
||||
StripAudibleBrandAudio = config.StripAudibleBrandAudio;
|
||||
StripUnabridged = config.StripUnabridged;
|
||||
ChapterTitleTemplate = config.ChapterTitleTemplate;
|
||||
DecryptToLossy = config.DecryptToLossy;
|
||||
LameTargetBitrate = config.LameTargetBitrate;
|
||||
LameDownsampleMono = config.LameDownsampleMono;
|
||||
LameConstantBitrate = config.LameConstantBitrate;
|
||||
LameMatchSource = config.LameMatchSourceBR;
|
||||
LameBitrate = config.LameBitrate;
|
||||
LameVBRQuality = config.LameVBRQuality;
|
||||
}
|
||||
|
||||
public void SaveSettings(Configuration config)
|
||||
{
|
||||
config.CreateCueSheet = CreateCueSheet;
|
||||
config.AllowLibationFixup = AllowLibationFixup;
|
||||
config.DownloadCoverArt = DownloadCoverArt;
|
||||
config.RetainAaxFile = RetainAaxFile;
|
||||
config.SplitFilesByChapter = SplitFilesByChapter;
|
||||
config.MergeOpeningAndEndCredits = MergeOpeningAndEndCredits;
|
||||
config.StripAudibleBrandAudio = StripAudibleBrandAudio;
|
||||
config.StripUnabridged = StripUnabridged;
|
||||
config.ChapterTitleTemplate = ChapterTitleTemplate;
|
||||
config.DecryptToLossy = DecryptToLossy;
|
||||
config.LameTargetBitrate = LameTargetBitrate;
|
||||
config.LameDownsampleMono = LameDownsampleMono;
|
||||
config.LameConstantBitrate = LameConstantBitrate;
|
||||
config.LameMatchSourceBR = LameMatchSource;
|
||||
config.LameBitrate = LameBitrate;
|
||||
config.LameVBRQuality = LameVBRQuality;
|
||||
}
|
||||
|
||||
public string CreateCueSheetText => desc(nameof(Configuration.CreateCueSheet));
|
||||
public string AllowLibationFixupText => desc(nameof(Configuration.AllowLibationFixup));
|
||||
public string DownloadCoverArtText => desc(nameof(Configuration.DownloadCoverArt));
|
||||
public string RetainAaxFileText => desc(nameof(Configuration.RetainAaxFile));
|
||||
public string SplitFilesByChapterText => desc(nameof(Configuration.SplitFilesByChapter));
|
||||
public string MergeOpeningEndCreditsText => desc(nameof(Configuration.MergeOpeningAndEndCredits));
|
||||
public string StripAudibleBrandingText => desc(nameof(Configuration.StripAudibleBrandAudio));
|
||||
public string StripUnabridgedText => desc(nameof(Configuration.StripUnabridged));
|
||||
public string ChapterTitleTemplateText => desc(nameof(Configuration.ChapterTitleTemplate));
|
||||
|
||||
public bool CreateCueSheet { get; set; }
|
||||
public bool DownloadCoverArt { get; set; }
|
||||
public bool RetainAaxFile { get; set; }
|
||||
public bool MergeOpeningAndEndCredits { get; set; }
|
||||
public bool StripAudibleBrandAudio { get; set; }
|
||||
public bool StripUnabridged { get; set; }
|
||||
public bool DecryptToLossy { get; set; }
|
||||
|
||||
public bool LameDownsampleMono { get; set; } = Design.IsDesignMode;
|
||||
public bool LameConstantBitrate { get; set; } = Design.IsDesignMode;
|
||||
|
||||
public bool SplitFilesByChapter { get => _splitFilesByChapter; set { this.RaiseAndSetIfChanged(ref _splitFilesByChapter, value); } }
|
||||
public bool LameTargetBitrate { get => _lameTargetBitrate; set { this.RaiseAndSetIfChanged(ref _lameTargetBitrate, value); } }
|
||||
public bool LameMatchSource { get => _lameMatchSource; set { this.RaiseAndSetIfChanged(ref _lameMatchSource, value); } }
|
||||
public int LameBitrate { get => _lameBitrate; set { this.RaiseAndSetIfChanged(ref _lameBitrate, value); } }
|
||||
public int LameVBRQuality { get => _lameVBRQuality; set { this.RaiseAndSetIfChanged(ref _lameVBRQuality, value); } }
|
||||
|
||||
|
||||
public string ChapterTitleTemplate { get => _chapterTitleTemplate; set { this.RaiseAndSetIfChanged(ref _chapterTitleTemplate, value); } }
|
||||
|
||||
|
||||
public bool AllowLibationFixup
|
||||
{
|
||||
get => _allowLibationFixup;
|
||||
set
|
||||
{
|
||||
this.RaiseAndSetIfChanged(ref _allowLibationFixup, value);
|
||||
if (!_allowLibationFixup)
|
||||
{
|
||||
SplitFilesByChapter = false;
|
||||
StripAudibleBrandAudio = false;
|
||||
StripUnabridged = false;
|
||||
DecryptToLossy = false;
|
||||
this.RaisePropertyChanged(nameof(SplitFilesByChapter));
|
||||
this.RaisePropertyChanged(nameof(StripAudibleBrandAudio));
|
||||
this.RaisePropertyChanged(nameof(StripUnabridged));
|
||||
this.RaisePropertyChanged(nameof(DecryptToLossy));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -67,7 +67,8 @@ namespace LibationWinForms.AvaloniaUI.Views
|
||||
|
||||
private async void MainWindow_Opened(object sender, EventArgs e)
|
||||
{
|
||||
|
||||
//var settings = new SettingsDialog();
|
||||
//settings.Show();
|
||||
}
|
||||
|
||||
public void ProductsDisplay_Initialized1(object sender, EventArgs e)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user