Added EditTemplateDialog and LibationFilesDialog

This commit is contained in:
Michael Bucari-Tovo 2022-07-20 13:35:30 -06:00
parent e7c5b1d8dc
commit 2cb2479d63
8 changed files with 764 additions and 129 deletions

View File

@ -20,15 +20,13 @@
<controls:WheelComboBox
HorizontalContentAlignment = "Stretch"
HorizontalAlignment = "Stretch"
VerticalAlignment="Stretch"
VerticalContentAlignment="Stretch"
MinHeight="{Binding #displayPathTbox.MinHeight}"
SelectedItem="{Binding $parent[1].SelectedDirectory, Mode=TwoWay}"
Items="{Binding $parent[1].KnownDirectories}">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock
FontSize="12"
Text="{Binding, Converter={StaticResource KnownDirectoryConverter}}" />
</DataTemplate>

View File

@ -0,0 +1,119 @@
<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="800" d:DesignHeight="450"
x:Class="LibationWinForms.AvaloniaUI.Views.Dialogs.EditTemplateDialog"
xmlns:dialogs="clr-namespace:LibationWinForms.AvaloniaUI.Views.Dialogs"
Icon="/AvaloniaUI/Assets/libation.ico"
Title="EditTemplateDialog">
<Window.Resources>
<dialogs:BracketEscapeConverter x:Key="BracketEscapeConverter" />
</Window.Resources>
<Grid RowDefinitions="Auto,*,Auto">
<Grid
Grid.Row="0"
RowDefinitions="Auto,Auto"
ColumnDefinitions="*,Auto" Margin="5">
<TextBlock
Grid.Column="0"
Grid.Row="0"
Text="{Binding Description}" />
<TextBox
Grid.Column="0"
Grid.Row="1"
Text="{Binding workingTemplateText, Mode=TwoWay}" />
<Button
Grid.Column="1"
Grid.Row="1"
Margin="10,0,0,0"
VerticalAlignment="Stretch"
Padding="20,3,20,3"
Content="Reset to Default"
Click="ResetButton_Click" />
</Grid>
<Grid Grid.Row="1" ColumnDefinitions="*,*">
<Border
Grid.Row="0"
Grid.Column="0"
Margin="5"
BorderThickness="1"
BorderBrush="{DynamicResource DataGridGridLinesBrush}">
<DataGrid
GridLinesVisibility="All"
AutoGenerateColumns="False"
Items="{Binding ListItems}" >
<DataGrid.Columns>
<DataGridTemplateColumn Width="Auto" Header="Tag">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextPresenter Height="18" Margin="10,0,10,0" VerticalAlignment="Center" Text="{Binding TagName, Converter={StaticResource BracketEscapeConverter}}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Width="*" Header="Description">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextPresenter Height="18" Margin="10,0,10,0" VerticalAlignment="Center" Text="{Binding Description}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
</Border>
<Grid
Grid.Row="1"
Grid.Column="1"
Margin="5"
RowDefinitions="Auto,*,80">
<TextBlock
Margin="5,5,5,10"
Text="Example:"/>
<Border
Grid.Row="1"
Margin="5"
BorderThickness="1"
BorderBrush="{DynamicResource DataGridGridLinesBrush}">
<WrapPanel
Grid.Row="1"
Name="wrapPanel"
Orientation="Horizontal" />
</Border>
<TextBlock
Grid.Row="2"
Margin="5"
Foreground="Firebrick"
Text="{Binding WarningText}" />
</Grid>
</Grid>
<Button
Grid.Row="2"
Margin="5"
Padding="30,5,30,5"
HorizontalAlignment="Right"
Content="Save"
Click="SaveButton_Click" />
</Grid>
</Window>

View File

@ -0,0 +1,249 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Data;
using Avalonia.Data.Converters;
using Avalonia.Markup.Xaml;
using Avalonia.Media;
using Avalonia.Media.TextFormatting;
using Dinah.Core;
using LibationFileManager;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using ReactiveUI;
namespace LibationWinForms.AvaloniaUI.Views.Dialogs
{
class BracketEscapeConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is string str && str[0] != '<' && str[^1] != '>')
return $"<{str}>";
return new BindingNotification(new InvalidCastException(), BindingErrorType.Error);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is string str && str[0] == '<' && str[^1] == '>')
return str[1..^2];
return new BindingNotification(new InvalidCastException(), BindingErrorType.Error);
}
}
public partial class EditTemplateDialog : DialogWindow
{
// final value. post-validity check
public string TemplateText { get; private set; }
private EditTemplateViewModel _viewModel;
public EditTemplateDialog()
{
InitializeComponent();
#if DEBUG
this.AttachDevTools();
#endif
_viewModel = new(Configuration.Instance, this.Find<WrapPanel>(nameof(wrapPanel)));
}
public EditTemplateDialog(Templates template, string inputTemplateText) : this()
{
_viewModel.template = ArgumentValidator.EnsureNotNull(template, nameof(template));
Title = $"Edit {_viewModel.template.Name}";
_viewModel.Description = _viewModel.template.Description;
_viewModel.resetTextBox(inputTemplateText);
_viewModel.ListItems = _viewModel.template.GetTemplateTags();
DataContext = _viewModel;
}
private void InitializeComponent()
{
AvaloniaXamlLoader.Load(this);
}
protected override async Task SaveAndCloseAsync()
{
if (!await _viewModel.Validate())
return;
TemplateText = _viewModel.workingTemplateText;
await base.SaveAndCloseAsync();
}
public async void SaveButton_Click(object sender, Avalonia.Interactivity.RoutedEventArgs e)
=> await SaveAndCloseAsync();
public void ResetButton_Click(object sender, Avalonia.Interactivity.RoutedEventArgs e)
=> _viewModel.resetTextBox(_viewModel.template.DefaultTemplate);
private class EditTemplateViewModel : ViewModels.ViewModelBase
{
WrapPanel WrapPanel;
public Configuration config { get; }
public EditTemplateViewModel(Configuration configuration, WrapPanel panel)
{
config = configuration;
WrapPanel = panel;
}
// hold the work-in-progress value. not guaranteed to be valid
private string _workingTemplateText;
public string workingTemplateText
{
get => _workingTemplateText;
set
{
_workingTemplateText = template.Sanitize(value);
templateTb_TextChanged();
}
}
private string _warningText;
public string WarningText
{
get => _warningText;
set
{
this.RaiseAndSetIfChanged(ref _warningText, value);
}
}
public Templates template { get; set; }
public string Description { get; set; }
public IEnumerable<TemplateTags> ListItems { get; set; }
public void resetTextBox(string value) => workingTemplateText = value;
public async Task<bool> Validate()
{
if (template.IsValid(workingTemplateText))
return true;
var errors = template
.GetErrors(workingTemplateText)
.Select(err => $"- {err}")
.Aggregate((a, b) => $"{a}\r\n{b}");
await MessageBox.Show($"This template text is not valid. Errors:\r\n{errors}", "Invalid", MessageBoxButtons.OK, MessageBoxIcon.Error);
return false;
}
private void templateTb_TextChanged()
{
var isChapterTitle = template == Templates.ChapterTitle;
var isFolder = template == Templates.Folder;
var libraryBookDto = new LibraryBookDto
{
Account = "my account",
AudibleProductId = "123456789",
Title = "A Study in Scarlet: A Sherlock Holmes Novel",
Locale = "us",
Authors = new List<string> { "Arthur Conan Doyle", "Stephen Fry - introductions" },
Narrators = new List<string> { "Stephen Fry" },
SeriesName = "Sherlock Holmes",
SeriesNumber = "1"
};
var chapterName = "A Flight for Life";
var chapterNumber = 4;
var chaptersTotal = 10;
var partFileProperties = new AaxDecrypter.MultiConvertFileProperties()
{
OutputFileName = "",
PartsPosition = chapterNumber,
PartsTotal = chaptersTotal,
Title = chapterName
};
var books = config.Books;
var folder = Templates.Folder.GetPortionFilename(
libraryBookDto,
isFolder ? workingTemplateText : config.FolderTemplate);
var file
= template == Templates.ChapterFile
? Templates.ChapterFile.GetPortionFilename(
libraryBookDto,
workingTemplateText,
partFileProperties,
"")
: Templates.File.GetPortionFilename(
libraryBookDto,
isFolder ? config.FileTemplate : workingTemplateText);
var ext = config.DecryptToLossy ? "mp3" : "m4b";
var chapterTitle = Templates.ChapterTitle.GetPortionTitle(libraryBookDto, workingTemplateText, partFileProperties);
const char ZERO_WIDTH_SPACE = '\u200B';
var sing = $"{Path.DirectorySeparatorChar}";
// result: can wrap long paths. eg:
// |-- LINE WRAP BOUNDARIES --|
// \books\author with a very <= normal line break on space between words
// long name\narrator narrator
// \title <= line break on the zero-with space we added before slashes
string slashWrap(string val) => val.Replace(sing, $"{ZERO_WIDTH_SPACE}{sing}");
WarningText
= !template.HasWarnings(workingTemplateText)
? ""
: "Warning:\r\n" +
template
.GetWarnings(workingTemplateText)
.Select(err => $"- {err}")
.Aggregate((a, b) => $"{a}\r\n{b}");
var list = new List<TextCharacters>();
var bold = new Typeface(Typeface.Default.FontFamily, FontStyle.Normal, FontWeight.Bold);
var normal = new Typeface(Typeface.Default.FontFamily, FontStyle.Normal, FontWeight.Normal);
var stringList = new List<(string, FontWeight)>();
if (isChapterTitle)
{
stringList.Add((chapterTitle, FontWeight.Bold));
}
else
{
stringList.Add((slashWrap(books), FontWeight.Normal));
stringList.Add((sing, FontWeight.Normal));
stringList.Add((slashWrap(folder), isFolder ? FontWeight.Bold : FontWeight.Normal));
stringList.Add((sing, FontWeight.Normal));
stringList.Add((file, !isFolder ? FontWeight.Bold : FontWeight.Normal));
stringList.Add(($".{ext}", FontWeight.Normal));
}
WrapPanel.Children.Clear();
//Avalonia doesn't yet support anything like rich text, so add a new textblock for every word/style
foreach (var item in stringList)
{
var wordsSplit = item.Item1.Split(' ');
for(int i = 0; i < wordsSplit.Length; i++)
{
var tb = new TextBlock();
tb.VerticalAlignment = Avalonia.Layout.VerticalAlignment.Bottom;
tb.Text = wordsSplit[i] + (i == wordsSplit.Length - 1 ? "" : " ");
tb.FontWeight = item.Item2;
WrapPanel.Children.Add(tb);
}
}
}
}
}
}

View File

@ -0,0 +1,29 @@
<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="800" d:DesignHeight="165"
MinHeight="165" MaxHeight="165"
MinWidth="800" MaxWidth="800"
x:Class="LibationWinForms.AvaloniaUI.Views.Dialogs.LibationFilesDialog"
xmlns:controls="clr-namespace:LibationWinForms.AvaloniaUI.Controls"
Title="Book Details"
Icon="/AvaloniaUI/Assets/libation.ico">
<Grid
RowDefinitions="Auto,Auto">
<controls:DirectoryOrCustomSelectControl
Grid.Row="0"
Margin="5"
Directory="{Binding Directory, Mode=TwoWay}"
KnownDirectories="{Binding KnownDirectories}" />
<Button
Grid.Row="1"
HorizontalAlignment="Right"
Margin="5"
Padding="30,3,30,3"
Content="Save" />
</Grid>
</Window>

View File

@ -0,0 +1,50 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
using LibationFileManager;
using LibationWinForms.AvaloniaUI.Controls;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace LibationWinForms.AvaloniaUI.Views.Dialogs
{
public partial class LibationFilesDialog : DialogWindow
{
private class DirSelectOptions
{
public List<Configuration.KnownDirectories> KnownDirectories { get; } = new()
{
Configuration.KnownDirectories.UserProfile,
Configuration.KnownDirectories.AppDir,
Configuration.KnownDirectories.MyDocs
};
public string Directory { get; set; } = Configuration.Instance.LibationFiles;
}
private DirSelectOptions dirSelectOptions;
public string SelectedDirectory => dirSelectOptions.Directory;
public LibationFilesDialog()
{
InitializeComponent();
DataContext = dirSelectOptions = new();
}
protected override async Task SaveAndCloseAsync()
{
var libationDir = dirSelectOptions.Directory;
if (!System.IO.Directory.Exists(libationDir))
{
await MessageBox.Show("Not saving change to Libation Files location. This folder does not exist:\r\n" + libationDir, "Folder does not exist", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
await base.SaveAndCloseAsync();
}
private void InitializeComponent()
{
AvaloniaXamlLoader.Load(this);
}
}
}

View File

@ -2,7 +2,8 @@
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="620"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="600"
MinWidth="800" MinHeight="600"
x:Class="LibationWinForms.AvaloniaUI.Views.Dialogs.SettingsDialog"
xmlns:controls="clr-namespace:LibationWinForms.AvaloniaUI.Controls"
Title="Edit Settings"
@ -35,7 +36,7 @@
</TabControl.Styles>
<TabItem Margin="0" Name="tabItem1">
<TabItem>
<TabItem.Header>
@ -45,11 +46,13 @@
Text="Important Settings"/>
</TabItem.Header>
<Border
Grid.Column="0"
Grid.Row="0"
BorderThickness="2"
BorderBrush="{DynamicResource DataGridGridLinesBrush}">
<Grid RowDefinitions="Auto,Auto,*">
<controls:GroupBox
@ -68,7 +71,6 @@
Directory="{Binding ImportantSettings.BooksDirectory, Mode=TwoWay}"
KnownDirectories="{Binding ImportantSettings.KnownDirectories}" />
<CheckBox IsChecked="{Binding ImportantSettings.SavePodcastsToParentFolder, Mode=TwoWay}">
<TextBlock Text="{Binding ImportantSettings.SavePodcastsToParentFolderText}" />
</CheckBox>
@ -81,7 +83,10 @@
Grid.Row="1" Margin="5"
Orientation="Horizontal">
<TextBlock Margin="0,0,10,0" VerticalAlignment="Center" Text="Logging level" />
<TextBlock
Margin="0,0,10,0"
VerticalAlignment="Center"
Text="Logging level" />
<controls:WheelComboBox
Width="150"
@ -108,9 +113,7 @@
</CheckBox>
</Grid>
</Border>
</TabItem>
@ -124,6 +127,7 @@
Text="Import Library"/>
</TabItem.Header>
<Border
Grid.Column="0"
Grid.Row="0"
@ -131,25 +135,57 @@
BorderBrush="{DynamicResource DataGridGridLinesBrush}">
<StackPanel Margin="5">
<CheckBox Margin="0,0,0,10" IsChecked="{Binding ImportSettings.AutoScan, Mode=TwoWay}">
<TextBlock TextWrapping="Wrap" Text="{Binding ImportSettings.AutoScanText}" />
<CheckBox
Margin="0,0,0,10"
IsChecked="{Binding ImportSettings.AutoScan, Mode=TwoWay}">
<TextBlock
TextWrapping="Wrap"
Text="{Binding ImportSettings.AutoScanText}" />
</CheckBox>
<CheckBox Margin="0,0,0,10" IsChecked="{Binding ImportSettings.ShowImportedStats, Mode=TwoWay}">
<TextBlock TextWrapping="Wrap" Text="{Binding ImportSettings.ShowImportedStatsText}" />
<CheckBox
Margin="0,0,0,10"
IsChecked="{Binding ImportSettings.ShowImportedStats, Mode=TwoWay}">
<TextBlock
TextWrapping="Wrap"
Text="{Binding ImportSettings.ShowImportedStatsText}" />
</CheckBox>
<CheckBox Margin="0,0,0,10" IsChecked="{Binding ImportSettings.ImportEpisodes, Mode=TwoWay}">
<TextBlock TextWrapping="Wrap" Text="{Binding ImportSettings.ImportEpisodesText}" />
<CheckBox
Margin="0,0,0,10"
IsChecked="{Binding ImportSettings.ImportEpisodes, Mode=TwoWay}">
<TextBlock
TextWrapping="Wrap"
Text="{Binding ImportSettings.ImportEpisodesText}" />
</CheckBox>
<CheckBox Margin="0,0,0,10" IsChecked="{Binding ImportSettings.DownloadEpisodes, Mode=TwoWay}">
<TextBlock TextWrapping="Wrap" Text="{Binding ImportSettings.DownloadEpisodesText}" />
<CheckBox
Margin="0,0,0,10"
IsChecked="{Binding ImportSettings.DownloadEpisodes, Mode=TwoWay}">
<TextBlock
TextWrapping="Wrap"
Text="{Binding ImportSettings.DownloadEpisodesText}" />
</CheckBox>
<CheckBox Margin="0,0,0,10" IsChecked="{Binding ImportSettings.AutoDownloadEpisodes, Mode=TwoWay}">
<TextBlock TextWrapping="Wrap" Text="{Binding ImportSettings.AutoDownloadEpisodesText}" />
<CheckBox
Margin="0,0,0,10"
IsChecked="{Binding ImportSettings.AutoDownloadEpisodes, Mode=TwoWay}">
<TextBlock
TextWrapping="Wrap"
Text="{Binding ImportSettings.AutoDownloadEpisodesText}" />
</CheckBox>
</StackPanel>
</Border>
</TabItem>
<TabItem>
@ -162,6 +198,7 @@
Text="Download/Decrypt"/>
</TabItem.Header>
<Border
Grid.Column="0"
Grid.Row="0"
@ -175,37 +212,57 @@
BorderWidth="1"
Label="{Binding DownloadDecryptSettings.BadBookGroupboxText}">
<Grid ColumnDefinitions="*,*" RowDefinitions="Auto,Auto">
<Grid
ColumnDefinitions="*,*"
RowDefinitions="Auto,Auto">
<RadioButton
Grid.Column="0"
Grid.Row="0"
Margin="0,5,0,5"
IsChecked="{Binding DownloadDecryptSettings.BadBookAsk, Mode=TwoWay}">
<TextBlock TextWrapping="Wrap" Text="{Binding DownloadDecryptSettings.BadBookAskText}" />
<TextBlock
TextWrapping="Wrap"
Text="{Binding DownloadDecryptSettings.BadBookAskText}" />
</RadioButton>
<RadioButton
Grid.Column="1"
Grid.Row="0"
Margin="0,5,0,5"
IsChecked="{Binding DownloadDecryptSettings.BadBookAbort, Mode=TwoWay}">
<TextBlock TextWrapping="Wrap" Text="{Binding DownloadDecryptSettings.BadBookAbortText}" />
<TextBlock
TextWrapping="Wrap"
Text="{Binding DownloadDecryptSettings.BadBookAbortText}" />
</RadioButton>
<RadioButton
Grid.Column="0"
Grid.Row="1"
Margin="0,5,0,5"
IsChecked="{Binding DownloadDecryptSettings.BadBookRetry, Mode=TwoWay}">
<TextBlock TextWrapping="Wrap" Text="{Binding DownloadDecryptSettings.BadBookRetryText}" />
<TextBlock
TextWrapping="Wrap"
Text="{Binding DownloadDecryptSettings.BadBookRetryText}" />
</RadioButton>
<RadioButton
Grid.Column="1"
Grid.Row="1"
Margin="0,5,0,5"
IsChecked="{Binding DownloadDecryptSettings.BadBookIgnore, Mode=TwoWay}">
<TextBlock TextWrapping="Wrap" Text="{Binding DownloadDecryptSettings.BadBookIgnoreText}" />
</RadioButton>
<TextBlock
TextWrapping="Wrap"
Text="{Binding DownloadDecryptSettings.BadBookIgnoreText}" />
</RadioButton>
</Grid>
</controls:GroupBox>
@ -215,7 +272,9 @@
BorderWidth="1"
Label="Custom File Naming">
<Grid RowDefinitions="Auto,Auto,Auto,Auto" ColumnDefinitions="*,Auto">
<Grid
RowDefinitions="Auto,Auto,Auto,Auto"
ColumnDefinitions="*,Auto">
<TextBox
Grid.Row="0"
@ -274,13 +333,15 @@
Click="EditCharReplacementButton_Click" />
</Grid>
</controls:GroupBox>
<StackPanel
Grid.Row="2"
Margin="5" >
<TextBlock Margin="0,0,0,10" Text="{Binding DownloadDecryptSettings.InProgressDescriptionText}" />
<TextBlock
Margin="0,0,0,10"
Text="{Binding DownloadDecryptSettings.InProgressDescriptionText}" />
<controls:DirectorySelectControl
SubDirectory="Libation\DecryptInProgress"
@ -289,9 +350,7 @@
</StackPanel>
</Grid>
</Border>
</TabItem>
<TabItem>
@ -304,6 +363,7 @@
Text="Audio File Settings"/>
</TabItem.Header>
<Border
Grid.Column="0"
Grid.Row="0"
@ -314,85 +374,176 @@
RowDefinitions="*,Auto"
ColumnDefinitions="*,*">
<StackPanel Margin="5"
<StackPanel
Margin="5"
Grid.Row="0"
Grid.Column="0">
<CheckBox Margin="0,0,0,5" IsChecked="{Binding AudioSettings.CreateCueSheet, Mode=TwoWay}">
<TextBlock TextWrapping="Wrap" Text="{Binding AudioSettings.CreateCueSheetText}" />
</CheckBox>
<CheckBox Margin="0,0,0,5" IsChecked="{Binding AudioSettings.DownloadCoverArt, Mode=TwoWay}">
<TextBlock TextWrapping="Wrap" Text="{Binding AudioSettings.DownloadCoverArtText}" />
</CheckBox>
<CheckBox Margin="0,0,0,5" IsChecked="{Binding AudioSettings.RetainAaxFile, Mode=TwoWay}">
<TextBlock TextWrapping="Wrap" Text="{Binding AudioSettings.RetainAaxFileText}" />
</CheckBox>
<CheckBox Margin="0,0,0,5" IsChecked="{Binding AudioSettings.MergeOpeningAndEndCredits, Mode=TwoWay}">
<TextBlock TextWrapping="Wrap" Text="{Binding AudioSettings.MergeOpeningEndCreditsText}" />
</CheckBox>
<CheckBox Margin="0,0,0,5" IsChecked="{Binding AudioSettings.AllowLibationFixup, Mode=TwoWay}">
<TextBlock TextWrapping="Wrap" Text="{Binding AudioSettings.AllowLibationFixupText}" />
<CheckBox
Margin="0,0,0,5"
IsChecked="{Binding AudioSettings.CreateCueSheet, Mode=TwoWay}">
<TextBlock
TextWrapping="Wrap"
Text="{Binding AudioSettings.CreateCueSheetText}" />
</CheckBox>
<controls:GroupBox BorderWidth="1" Label="Audiobook Fix-ups" IsEnabled="{Binding AudioSettings.AllowLibationFixup}">
<CheckBox
Margin="0,0,0,5"
IsChecked="{Binding AudioSettings.DownloadCoverArt, Mode=TwoWay}">
<TextBlock
TextWrapping="Wrap"
Text="{Binding AudioSettings.DownloadCoverArtText}" />
</CheckBox>
<CheckBox
Margin="0,0,0,5"
IsChecked="{Binding AudioSettings.RetainAaxFile, Mode=TwoWay}">
<TextBlock
TextWrapping="Wrap"
Text="{Binding AudioSettings.RetainAaxFileText}" />
</CheckBox>
<CheckBox
Margin="0,0,0,5"
IsChecked="{Binding AudioSettings.MergeOpeningAndEndCredits, Mode=TwoWay}">
<TextBlock
TextWrapping="Wrap"
Text="{Binding AudioSettings.MergeOpeningEndCreditsText}" />
</CheckBox>
<CheckBox
Margin="0,0,0,5"
IsChecked="{Binding AudioSettings.AllowLibationFixup, Mode=TwoWay}">
<TextBlock
TextWrapping="Wrap"
Text="{Binding AudioSettings.AllowLibationFixupText}" />
</CheckBox>
<controls:GroupBox
BorderWidth="1"
Label="Audiobook Fix-ups"
IsEnabled="{Binding AudioSettings.AllowLibationFixup}">
<StackPanel Orientation="Vertical">
<CheckBox Margin="0,0,0,5" IsChecked="{Binding AudioSettings.SplitFilesByChapter, Mode=TwoWay}">
<TextBlock TextWrapping="Wrap" Text="{Binding AudioSettings.SplitFilesByChapterText}" />
<CheckBox
Margin="0,0,0,5"
IsChecked="{Binding AudioSettings.SplitFilesByChapter, Mode=TwoWay}">
<TextBlock
TextWrapping="Wrap"
Text="{Binding AudioSettings.SplitFilesByChapterText}" />
</CheckBox>
<CheckBox Margin="0,0,0,5" IsChecked="{Binding AudioSettings.StripAudibleBrandAudio, Mode=TwoWay}">
<TextBlock TextWrapping="Wrap" Text="{Binding AudioSettings.StripAudibleBrandingText}" />
<CheckBox
Margin="0,0,0,5"
IsChecked="{Binding AudioSettings.StripAudibleBrandAudio, Mode=TwoWay}">
<TextBlock
TextWrapping="Wrap"
Text="{Binding AudioSettings.StripAudibleBrandingText}" />
</CheckBox>
<CheckBox Margin="0,0,0,5" IsChecked="{Binding AudioSettings.StripUnabridged, Mode=TwoWay}">
<TextBlock TextWrapping="Wrap" Text="{Binding AudioSettings.StripUnabridgedText}" />
<CheckBox
Margin="0,0,0,5"
IsChecked="{Binding AudioSettings.StripUnabridged, Mode=TwoWay}">
<TextBlock
TextWrapping="Wrap"
Text="{Binding AudioSettings.StripUnabridgedText}" />
</CheckBox>
<RadioButton Margin="0,5,0,5" IsChecked="{Binding !AudioSettings.DecryptToLossy, Mode=TwoWay}">
<TextBlock TextWrapping="Wrap" Text="Download my books in the original audio format (Lossless)" />
<RadioButton
Margin="0,5,0,5"
IsChecked="{Binding !AudioSettings.DecryptToLossy, Mode=TwoWay}">
<TextBlock
TextWrapping="Wrap"
Text="Download my books in the original audio format (Lossless)" />
</RadioButton>
<RadioButton Margin="0,5,0,5" IsChecked="{Binding AudioSettings.DecryptToLossy, Mode=TwoWay}">
<TextBlock TextWrapping="Wrap" Text="Download my books as .MP3 files (transcode if necessary)" />
</RadioButton>
<RadioButton
Margin="0,5,0,5"
IsChecked="{Binding AudioSettings.DecryptToLossy, Mode=TwoWay}">
<TextBlock
TextWrapping="Wrap"
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">
<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">
<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"
Content="Bitrate"
IsChecked="{Binding AudioSettings.LameTargetBitrate, Mode=TwoWay}"/>
<RadioButton Margin="10" IsChecked="{Binding !AudioSettings.LameTargetBitrate, Mode=TwoWay}">
<TextBlock Text="Quality" />
</RadioButton>
<RadioButton
Margin="10"
Content="Quality"
IsChecked="{Binding !AudioSettings.LameTargetBitrate, Mode=TwoWay}"/>
</StackPanel>
</controls:GroupBox>
<CheckBox HorizontalAlignment="Right" Grid.Column="1" IsChecked="{Binding AudioSettings.LameDownsampleMono, Mode=TwoWay}">
<TextBlock TextWrapping="Wrap" Text="Downsample to mono? (Recommended)" />
<CheckBox
HorizontalAlignment="Right"
Grid.Column="1"
IsChecked="{Binding AudioSettings.LameDownsampleMono, Mode=TwoWay}">
<TextBlock
TextWrapping="Wrap"
Text="Downsample to mono? (Recommended)" />
</CheckBox>
</Grid>
<controls:GroupBox Margin="5,5,5,0" BorderWidth="1" Label="Bitrate" IsEnabled="{Binding AudioSettings.LameTargetBitrate}" >
<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}"
@ -402,6 +553,7 @@
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'}" />
@ -411,23 +563,54 @@
</Style>
</Slider.Styles>
</Slider>
<TextBlock Grid.Column="1" HorizontalAlignment="Right" Text="{Binding AudioSettings.LameBitrate}" />
<TextBlock Grid.Column="2" Text=" Kbps" />
<TextBlock
Grid.Column="1"
HorizontalAlignment="Right"
Text="{Binding AudioSettings.LameBitrate}" />
<TextBlock
Grid.Column="2"
Text=" Kbps" />
</Grid>
<Grid ColumnDefinitions="*,*">
<CheckBox Grid.Column="0" IsChecked="{Binding AudioSettings.LameConstantBitrate, Mode=TwoWay}">
<TextBlock TextWrapping="Wrap" Text="Restrict Encoder to Constant Bitrate?" />
<CheckBox
Grid.Column="0"
IsChecked="{Binding AudioSettings.LameConstantBitrate, Mode=TwoWay}">
<TextBlock
TextWrapping="Wrap"
Text="Restrict Encoder to Constant Bitrate?" />
</CheckBox>
<CheckBox Grid.Column="1" IsChecked="{Binding AudioSettings.LameMatchSource, Mode=TwoWay}" HorizontalAlignment="Right">
<TextBlock TextWrapping="Wrap" Text="Match Source Bitrate?" />
<CheckBox
Grid.Column="1"
HorizontalAlignment="Right"
IsChecked="{Binding AudioSettings.LameMatchSource, Mode=TwoWay}">
<TextBlock
TextWrapping="Wrap"
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">
<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"
@ -446,22 +629,40 @@
</Style>
</Slider.Styles>
</Slider>
<StackPanel Grid.Column="2" HorizontalAlignment="Right" Orientation="Horizontal">
<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" />
<TextBlock
Grid.Column="0"
Grid.Row="1"
Margin="10,0,0,0"
Text="Higher" />
<TextBlock
Grid.Column="1"
Grid.Row="1"
Margin="0,0,10,0"
HorizontalAlignment="Right"
Text="Lower" />
</Grid>
</controls:GroupBox>
<TextBlock Margin="5,5,5,5" Text="Using L.A.M.E encoding engine" FontStyle="Italic" />
<TextBlock
Margin="5,5,5,5"
Text="Using L.A.M.E encoding engine"
FontStyle="Italic" />
</StackPanel>
</controls:GroupBox>
</StackPanel>
<controls:GroupBox
@ -470,7 +671,9 @@
Margin="5"
BorderWidth="1" IsEnabled="{Binding AudioSettings.SplitFilesByChapter}"
Label="{Binding AudioSettings.ChapterTitleTemplateText}">
<Grid ColumnDefinitions="*,Auto">
<TextBox
Grid.Column="0"
Margin="0,10,10,10"
@ -487,12 +690,8 @@
</Grid>
</controls:GroupBox>
</Grid>
</Border>
</TabItem>
</TabControl>
</Grid>
</Window>

View File

@ -24,14 +24,6 @@ namespace LibationWinForms.AvaloniaUI.Views.Dialogs
InitializeComponent();
DataContext = settingsDisp = new(config);
tabItem1 = this.Find<TabItem>("tabItem1");
tabItem1.GotFocus += TabItem1_GotFocus;
}
private void TabItem1_GotFocus(object sender, Avalonia.Input.GotFocusEventArgs e)
{
}
private void InitializeComponent()
@ -47,69 +39,67 @@ namespace LibationWinForms.AvaloniaUI.Views.Dialogs
public async void SaveButton_Clicked(object sender, Avalonia.Interactivity.RoutedEventArgs e)
=> await SaveAndCloseAsync();
public void OpenLogFolderButton_Click(object sender, Avalonia.Interactivity.RoutedEventArgs e)
{
Go.To.Folder(((LongPath)Configuration.Instance.LibationFiles).ShortPathName);
}
public void EditFolderTemplateButton_Click(object sender, Avalonia.Interactivity.RoutedEventArgs e)
public async void EditFolderTemplateButton_Click(object sender, Avalonia.Interactivity.RoutedEventArgs e)
{
var newTemplate = editTemplate(Templates.ChapterTitle, settingsDisp.DownloadDecryptSettings.FolderTemplate);
var newTemplate = await editTemplate(Templates.Folder, settingsDisp.DownloadDecryptSettings.FolderTemplate);
if (newTemplate is not null)
settingsDisp.DownloadDecryptSettings.FolderTemplate = newTemplate;
}
public void EditFileTemplateButton_Click(object sender, Avalonia.Interactivity.RoutedEventArgs e)
public async void EditFileTemplateButton_Click(object sender, Avalonia.Interactivity.RoutedEventArgs e)
{
var newTemplate = editTemplate(Templates.ChapterTitle, settingsDisp.DownloadDecryptSettings.FileTemplate);
var newTemplate = await editTemplate(Templates.File, settingsDisp.DownloadDecryptSettings.FileTemplate);
if (newTemplate is not null)
settingsDisp.DownloadDecryptSettings.FileTemplate = newTemplate;
}
public void EditChapterFileTemplateButton_Click(object sender, Avalonia.Interactivity.RoutedEventArgs e)
public async void EditChapterFileTemplateButton_Click(object sender, Avalonia.Interactivity.RoutedEventArgs e)
{
var newTemplate = editTemplate(Templates.ChapterTitle, settingsDisp.DownloadDecryptSettings.ChapterFileTemplate);
var newTemplate = await editTemplate(Templates.ChapterFile, settingsDisp.DownloadDecryptSettings.ChapterFileTemplate);
if (newTemplate is not null)
settingsDisp.DownloadDecryptSettings.ChapterFileTemplate = newTemplate;
}
public void EditCharReplacementButton_Click(object sender, Avalonia.Interactivity.RoutedEventArgs e)
public async void EditCharReplacementButton_Click(object sender, Avalonia.Interactivity.RoutedEventArgs e)
{
var form = new LibationWinForms.Dialogs.EditReplacementChars(config);
form.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
form.ShowDialog();
}
public void EditChapterTitleTemplateButton_Click(object sender, Avalonia.Interactivity.RoutedEventArgs e)
public async void EditChapterTitleTemplateButton_Click(object sender, Avalonia.Interactivity.RoutedEventArgs e)
{
var newTemplate = editTemplate(Templates.ChapterTitle, settingsDisp.AudioSettings.ChapterTitleTemplate);
var newTemplate = await editTemplate(Templates.ChapterTitle, settingsDisp.AudioSettings.ChapterTitleTemplate);
if (newTemplate is not null)
settingsDisp.AudioSettings.ChapterTitleTemplate = newTemplate;
}
private static string editTemplate(Templates template, string existingTemplate)
private async Task<string> editTemplate(Templates template, string existingTemplate)
{
var form = new LibationWinForms.Dialogs.EditTemplateDialog(template, existingTemplate);
if (form.ShowDialog() == System.Windows.Forms.DialogResult.OK)
var form = new EditTemplateDialog(template, existingTemplate);
if (await form.ShowDialog<DialogResult>(this) == DialogResult.OK)
return form.TemplateText;
else return null;
}
}
internal interface ISettingsTab
internal interface ISettingsDisplay
{
void LoadSettings(Configuration config);
void SaveSettings(Configuration config);
}
public class SettingsPages : ISettingsTab
public class SettingsPages : ISettingsDisplay
{
public SettingsPages(Configuration config)
{
@ -138,7 +128,7 @@ namespace LibationWinForms.AvaloniaUI.Views.Dialogs
}
}
public class ImportantSettings : ISettingsTab
public class ImportantSettings : ISettingsDisplay
{
private static Func<string, string> desc { get; } = Configuration.GetDescription;
@ -183,7 +173,7 @@ namespace LibationWinForms.AvaloniaUI.Views.Dialogs
}
public class ImportSettings : ISettingsTab
public class ImportSettings : ISettingsDisplay
{
private static Func<string, string> desc { get; } = Configuration.GetDescription;
@ -223,7 +213,7 @@ namespace LibationWinForms.AvaloniaUI.Views.Dialogs
public bool AutoDownloadEpisodes { get; set; }
}
public class DownloadDecryptSettings : ViewModels.ViewModelBase, ISettingsTab
public class DownloadDecryptSettings : ViewModels.ViewModelBase, ISettingsDisplay
{
private static Func<string, string> desc { get; } = Configuration.GetDescription;
@ -346,7 +336,7 @@ namespace LibationWinForms.AvaloniaUI.Views.Dialogs
}
}
public class AudioSettings : ViewModels.ViewModelBase, ISettingsTab
public class AudioSettings : ViewModels.ViewModelBase, ISettingsDisplay
{
private bool _splitFilesByChapter;

View File

@ -67,7 +67,8 @@ namespace LibationWinForms.AvaloniaUI.Views
private async void MainWindow_Opened(object sender, EventArgs e)
{
var dialog = new EditTemplateDialog(Templates.ChapterFile, "<title>");
await dialog.ShowDialog(this);
}
public void ProductsDisplay_Initialized1(object sender, EventArgs e)