Merge pull request #296 from Mbucari/master
Error handling inside all click handlers
This commit is contained in:
commit
10bdddb262
@ -88,5 +88,13 @@ namespace DataLayer
|
|||||||
s.Series.AudibleSeriesId == parent.Book.AudibleProductId
|
s.Series.AudibleSeriesId == parent.Book.AudibleProductId
|
||||||
) == true
|
) == true
|
||||||
).ToList();
|
).ToList();
|
||||||
|
|
||||||
|
public static IEnumerable<LibraryBook> UnLiberated(this IEnumerable<LibraryBook> bookList)
|
||||||
|
=> bookList
|
||||||
|
.Where(
|
||||||
|
lb =>
|
||||||
|
lb.Book.UserDefinedItem.BookStatus is LiberatedStatus.NotLiberated or LiberatedStatus.PartialDownload
|
||||||
|
|| lb.Book.UserDefinedItem.PdfStatus is LiberatedStatus.NotLiberated or LiberatedStatus.PartialDownload
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -165,7 +165,7 @@ namespace FileLiberator
|
|||||||
LameConfig = GetLameOptions(config)
|
LameConfig = GetLameOptions(config)
|
||||||
};
|
};
|
||||||
|
|
||||||
var chapters = getChapters(contentLic.ContentMetadata.ChapterInfo.Chapters).OrderBy(c => c.StartOffsetMs).ToList();
|
var chapters = flattenChapters(contentLic.ContentMetadata.ChapterInfo.Chapters).OrderBy(c => c.StartOffsetMs).ToList();
|
||||||
|
|
||||||
if (config.AllowLibationFixup || outputFormat == OutputFormat.Mp3)
|
if (config.AllowLibationFixup || outputFormat == OutputFormat.Mp3)
|
||||||
{
|
{
|
||||||
@ -192,7 +192,7 @@ namespace FileLiberator
|
|||||||
return dlOptions;
|
return dlOptions;
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<AudibleApi.Common.Chapter> getChapters(IEnumerable<AudibleApi.Common.Chapter> chapters)
|
public static List<AudibleApi.Common.Chapter> flattenChapters(IEnumerable<AudibleApi.Common.Chapter> chapters, string titleConcat = ": ")
|
||||||
{
|
{
|
||||||
List<AudibleApi.Common.Chapter> chaps = new();
|
List<AudibleApi.Common.Chapter> chaps = new();
|
||||||
|
|
||||||
@ -200,20 +200,14 @@ namespace FileLiberator
|
|||||||
{
|
{
|
||||||
if (c.Chapters is not null)
|
if (c.Chapters is not null)
|
||||||
{
|
{
|
||||||
var firstSub = new AudibleApi.Common.Chapter
|
c.Chapters[0].StartOffsetMs = c.StartOffsetMs;
|
||||||
{
|
c.Chapters[0].StartOffsetSec = c.StartOffsetSec;
|
||||||
Title = $"{c.Title}: {c.Chapters[0].Title}",
|
c.Chapters[0].LengthMs += c.LengthMs;
|
||||||
StartOffsetMs = c.StartOffsetMs,
|
|
||||||
StartOffsetSec = c.StartOffsetSec,
|
|
||||||
LengthMs = c.LengthMs + c.Chapters[0].LengthMs
|
|
||||||
};
|
|
||||||
|
|
||||||
chaps.Add(firstSub);
|
var children = flattenChapters(c.Chapters);
|
||||||
|
|
||||||
var children = getChapters(c.Chapters[1..]);
|
|
||||||
|
|
||||||
foreach (var child in children)
|
foreach (var child in children)
|
||||||
child.Title = string.IsNullOrEmpty(c.Title) ? child.Title : $"{c.Title}: {child.Title}";
|
child.Title = $"{c.Title}{titleConcat}{child.Title}";
|
||||||
|
|
||||||
chaps.AddRange(children);
|
chaps.AddRange(children);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,7 +7,7 @@ using System.Linq;
|
|||||||
|
|
||||||
namespace FileManager
|
namespace FileManager
|
||||||
{
|
{
|
||||||
public class Replacement
|
public class Replacement : ICloneable
|
||||||
{
|
{
|
||||||
public const int FIXED_COUNT = 6;
|
public const int FIXED_COUNT = 6;
|
||||||
|
|
||||||
@ -30,6 +30,8 @@ namespace FileManager
|
|||||||
Mandatory = mandatory;
|
Mandatory = mandatory;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public object Clone() => new Replacement(CharacterToReplace, ReplacementString, Description, Mandatory);
|
||||||
|
|
||||||
public void Update(char charToReplace, string replacementString, string description)
|
public void Update(char charToReplace, string replacementString, string description)
|
||||||
{
|
{
|
||||||
ReplacementString = replacementString;
|
ReplacementString = replacementString;
|
||||||
@ -53,6 +55,7 @@ namespace FileManager
|
|||||||
public static Replacement OpenAngleBracket(string replacement) => new('<', replacement, "Open Angle Bracket");
|
public static Replacement OpenAngleBracket(string replacement) => new('<', replacement, "Open Angle Bracket");
|
||||||
public static Replacement CloseAngleBracket(string replacement) => new('>', replacement, "Close Angle Bracket");
|
public static Replacement CloseAngleBracket(string replacement) => new('>', replacement, "Close Angle Bracket");
|
||||||
public static Replacement Pipe(string replacement) => new('|', replacement, "Vertical Line");
|
public static Replacement Pipe(string replacement) => new('|', replacement, "Vertical Line");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[JsonConverter(typeof(ReplacementCharactersConverter))]
|
[JsonConverter(typeof(ReplacementCharactersConverter))]
|
||||||
|
|||||||
@ -29,14 +29,14 @@
|
|||||||
private void InitializeComponent()
|
private void InitializeComponent()
|
||||||
{
|
{
|
||||||
this.dataGridView1 = new System.Windows.Forms.DataGridView();
|
this.dataGridView1 = new System.Windows.Forms.DataGridView();
|
||||||
|
this.charToReplaceCol = new System.Windows.Forms.DataGridViewTextBoxColumn();
|
||||||
|
this.replacementStringCol = new System.Windows.Forms.DataGridViewTextBoxColumn();
|
||||||
|
this.descriptionCol = new System.Windows.Forms.DataGridViewTextBoxColumn();
|
||||||
this.defaultsBtn = new System.Windows.Forms.Button();
|
this.defaultsBtn = new System.Windows.Forms.Button();
|
||||||
this.loFiDefaultsBtn = new System.Windows.Forms.Button();
|
this.loFiDefaultsBtn = new System.Windows.Forms.Button();
|
||||||
this.saveBtn = new System.Windows.Forms.Button();
|
this.saveBtn = new System.Windows.Forms.Button();
|
||||||
this.cancelBtn = new System.Windows.Forms.Button();
|
this.cancelBtn = new System.Windows.Forms.Button();
|
||||||
this.minDefaultBtn = new System.Windows.Forms.Button();
|
this.minDefaultBtn = new System.Windows.Forms.Button();
|
||||||
this.charToReplaceCol = new System.Windows.Forms.DataGridViewTextBoxColumn();
|
|
||||||
this.replacementStringCol = new System.Windows.Forms.DataGridViewTextBoxColumn();
|
|
||||||
this.descriptionCol = new System.Windows.Forms.DataGridViewTextBoxColumn();
|
|
||||||
((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).BeginInit();
|
((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).BeginInit();
|
||||||
this.SuspendLayout();
|
this.SuspendLayout();
|
||||||
//
|
//
|
||||||
@ -54,6 +54,7 @@
|
|||||||
this.descriptionCol});
|
this.descriptionCol});
|
||||||
this.dataGridView1.Location = new System.Drawing.Point(12, 12);
|
this.dataGridView1.Location = new System.Drawing.Point(12, 12);
|
||||||
this.dataGridView1.Name = "dataGridView1";
|
this.dataGridView1.Name = "dataGridView1";
|
||||||
|
this.dataGridView1.RowHeadersWidthSizeMode = System.Windows.Forms.DataGridViewRowHeadersWidthSizeMode.DisableResizing;
|
||||||
this.dataGridView1.RowTemplate.Height = 25;
|
this.dataGridView1.RowTemplate.Height = 25;
|
||||||
this.dataGridView1.Size = new System.Drawing.Size(498, 393);
|
this.dataGridView1.Size = new System.Drawing.Size(498, 393);
|
||||||
this.dataGridView1.TabIndex = 0;
|
this.dataGridView1.TabIndex = 0;
|
||||||
@ -61,6 +62,31 @@
|
|||||||
this.dataGridView1.UserDeletingRow += new System.Windows.Forms.DataGridViewRowCancelEventHandler(this.dataGridView1_UserDeletingRow);
|
this.dataGridView1.UserDeletingRow += new System.Windows.Forms.DataGridViewRowCancelEventHandler(this.dataGridView1_UserDeletingRow);
|
||||||
this.dataGridView1.Resize += new System.EventHandler(this.dataGridView1_Resize);
|
this.dataGridView1.Resize += new System.EventHandler(this.dataGridView1_Resize);
|
||||||
//
|
//
|
||||||
|
// charToReplaceCol
|
||||||
|
//
|
||||||
|
this.charToReplaceCol.HeaderText = "Char to Replace";
|
||||||
|
this.charToReplaceCol.MinimumWidth = 70;
|
||||||
|
this.charToReplaceCol.Name = "charToReplaceCol";
|
||||||
|
this.charToReplaceCol.Resizable = System.Windows.Forms.DataGridViewTriState.False;
|
||||||
|
this.charToReplaceCol.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable;
|
||||||
|
this.charToReplaceCol.Width = 70;
|
||||||
|
//
|
||||||
|
// replacementStringCol
|
||||||
|
//
|
||||||
|
this.replacementStringCol.HeaderText = "Replacement Text";
|
||||||
|
this.replacementStringCol.MinimumWidth = 85;
|
||||||
|
this.replacementStringCol.Name = "replacementStringCol";
|
||||||
|
this.replacementStringCol.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable;
|
||||||
|
this.replacementStringCol.Width = 85;
|
||||||
|
//
|
||||||
|
// descriptionCol
|
||||||
|
//
|
||||||
|
this.descriptionCol.HeaderText = "Description";
|
||||||
|
this.descriptionCol.MinimumWidth = 100;
|
||||||
|
this.descriptionCol.Name = "descriptionCol";
|
||||||
|
this.descriptionCol.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable;
|
||||||
|
this.descriptionCol.Width = 200;
|
||||||
|
//
|
||||||
// defaultsBtn
|
// defaultsBtn
|
||||||
//
|
//
|
||||||
this.defaultsBtn.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
|
this.defaultsBtn.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
|
||||||
@ -116,28 +142,6 @@
|
|||||||
this.minDefaultBtn.UseVisualStyleBackColor = true;
|
this.minDefaultBtn.UseVisualStyleBackColor = true;
|
||||||
this.minDefaultBtn.Click += new System.EventHandler(this.minDefaultBtn_Click);
|
this.minDefaultBtn.Click += new System.EventHandler(this.minDefaultBtn_Click);
|
||||||
//
|
//
|
||||||
// charToReplaceCol
|
|
||||||
//
|
|
||||||
this.charToReplaceCol.HeaderText = "Char to Replace";
|
|
||||||
this.charToReplaceCol.MinimumWidth = 70;
|
|
||||||
this.charToReplaceCol.Name = "charToReplaceCol";
|
|
||||||
this.charToReplaceCol.Resizable = System.Windows.Forms.DataGridViewTriState.False;
|
|
||||||
this.charToReplaceCol.Width = 70;
|
|
||||||
//
|
|
||||||
// replacementStringCol
|
|
||||||
//
|
|
||||||
this.replacementStringCol.HeaderText = "Replacement Text";
|
|
||||||
this.replacementStringCol.MinimumWidth = 85;
|
|
||||||
this.replacementStringCol.Name = "replacementStringCol";
|
|
||||||
this.replacementStringCol.Width = 85;
|
|
||||||
//
|
|
||||||
// descriptionCol
|
|
||||||
//
|
|
||||||
this.descriptionCol.HeaderText = "Description";
|
|
||||||
this.descriptionCol.MinimumWidth = 100;
|
|
||||||
this.descriptionCol.Name = "descriptionCol";
|
|
||||||
this.descriptionCol.Width = 200;
|
|
||||||
//
|
|
||||||
// EditReplacementChars
|
// EditReplacementChars
|
||||||
//
|
//
|
||||||
this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F);
|
this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F);
|
||||||
|
|||||||
@ -29,8 +29,8 @@ namespace LibationWinForms.Dialogs
|
|||||||
{
|
{
|
||||||
var r = replacements[i];
|
var r = replacements[i];
|
||||||
|
|
||||||
int row = dataGridView1.Rows.Add(r.CharacterToReplace, r.ReplacementString, r.Description);
|
int row = dataGridView1.Rows.Add(r.CharacterToReplace.ToString(), r.ReplacementString, r.Description);
|
||||||
dataGridView1.Rows[row].Tag = r;
|
dataGridView1.Rows[row].Tag = r.Clone();
|
||||||
|
|
||||||
|
|
||||||
if (r.Mandatory)
|
if (r.Mandatory)
|
||||||
@ -90,7 +90,7 @@ namespace LibationWinForms.Dialogs
|
|||||||
{
|
{
|
||||||
dataGridView1.Rows[e.RowIndex].ErrorText = $"Only 1 {charToReplaceCol.HeaderText} per entry";
|
dataGridView1.Rows[e.RowIndex].ErrorText = $"Only 1 {charToReplaceCol.HeaderText} per entry";
|
||||||
}
|
}
|
||||||
else if (e.RowIndex >= Replacement.FIXED_COUNT &&
|
else if (dataGridView1.Rows[e.RowIndex].Tag is Replacement repl && !repl.Mandatory &&
|
||||||
dataGridView1.Rows
|
dataGridView1.Rows
|
||||||
.Cast<DataGridViewRow>()
|
.Cast<DataGridViewRow>()
|
||||||
.Where(r => r.Index != e.RowIndex)
|
.Where(r => r.Index != e.RowIndex)
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
using System;
|
using DataLayer;
|
||||||
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
@ -10,11 +11,24 @@ namespace LibationWinForms
|
|||||||
private void Configure_Liberate() { }
|
private void Configure_Liberate() { }
|
||||||
|
|
||||||
//GetLibrary_Flat_NoTracking() may take a long time on a hugh library. so run in new thread
|
//GetLibrary_Flat_NoTracking() may take a long time on a hugh library. so run in new thread
|
||||||
private async void beginBookBackupsToolStripMenuItem_Click(object _ = null, EventArgs __ = null)
|
private void beginBookBackupsToolStripMenuItem_Click(object _ = null, EventArgs __ = null)
|
||||||
{
|
{
|
||||||
SetQueueCollapseState(false);
|
try
|
||||||
await Task.Run(() => processBookQueue1.AddDownloadDecrypt(ApplicationServices.DbContexts.GetLibrary_Flat_NoTracking()
|
{
|
||||||
.Where(lb => lb.Book.UserDefinedItem.PdfStatus is DataLayer.LiberatedStatus.NotLiberated || lb.Book.UserDefinedItem.BookStatus is DataLayer.LiberatedStatus.NotLiberated)));
|
SetQueueCollapseState(false);
|
||||||
|
|
||||||
|
Serilog.Log.Logger.Information("Begin backing up all library books");
|
||||||
|
|
||||||
|
processBookQueue1.AddDownloadDecrypt(
|
||||||
|
ApplicationServices.DbContexts
|
||||||
|
.GetLibrary_Flat_NoTracking()
|
||||||
|
.UnLiberated()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Serilog.Log.Logger.Error(ex, "An error occurred while backing up all library books");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void beginPdfBackupsToolStripMenuItem_Click(object sender, EventArgs e)
|
private async void beginPdfBackupsToolStripMenuItem_Click(object sender, EventArgs e)
|
||||||
|
|||||||
@ -22,27 +22,36 @@ namespace LibationWinForms
|
|||||||
this.Width = width;
|
this.Width = width;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ProductsDisplay_LiberateClicked(object sender, LibraryBook e)
|
private void ProductsDisplay_LiberateClicked(object sender, LibraryBook libraryBook)
|
||||||
{
|
{
|
||||||
if (e.Book.UserDefinedItem.BookStatus != LiberatedStatus.Liberated)
|
try
|
||||||
{
|
{
|
||||||
SetQueueCollapseState(false);
|
if (libraryBook.Book.UserDefinedItem.BookStatus is LiberatedStatus.NotLiberated or LiberatedStatus.PartialDownload)
|
||||||
processBookQueue1.AddDownloadDecrypt(e);
|
|
||||||
}
|
|
||||||
else if (e.Book.UserDefinedItem.PdfStatus is not null and LiberatedStatus.NotLiberated)
|
|
||||||
{
|
|
||||||
SetQueueCollapseState(false);
|
|
||||||
processBookQueue1.AddDownloadPdf(e);
|
|
||||||
}
|
|
||||||
else if (e.Book.Audio_Exists())
|
|
||||||
{
|
|
||||||
// liberated: open explorer to file
|
|
||||||
var filePath = AudibleFileStorage.Audio.GetPath(e.Book.AudibleProductId);
|
|
||||||
if (!Go.To.File(filePath?.ShortPathName))
|
|
||||||
{
|
{
|
||||||
var suffix = string.IsNullOrWhiteSpace(filePath) ? "" : $":\r\n{filePath}";
|
Serilog.Log.Logger.Information("Begin single book backup of {libraryBook}", libraryBook);
|
||||||
MessageBox.Show($"File not found" + suffix);
|
SetQueueCollapseState(false);
|
||||||
|
processBookQueue1.AddDownloadDecrypt(libraryBook);
|
||||||
}
|
}
|
||||||
|
else if (libraryBook.Book.UserDefinedItem.PdfStatus is LiberatedStatus.NotLiberated)
|
||||||
|
{
|
||||||
|
Serilog.Log.Logger.Information("Begin single pdf backup of {libraryBook}", libraryBook);
|
||||||
|
SetQueueCollapseState(false);
|
||||||
|
processBookQueue1.AddDownloadPdf(libraryBook);
|
||||||
|
}
|
||||||
|
else if (libraryBook.Book.Audio_Exists())
|
||||||
|
{
|
||||||
|
// liberated: open explorer to file
|
||||||
|
var filePath = AudibleFileStorage.Audio.GetPath(libraryBook.Book.AudibleProductId);
|
||||||
|
if (!Go.To.File(filePath?.ShortPathName))
|
||||||
|
{
|
||||||
|
var suffix = string.IsNullOrWhiteSpace(filePath) ? "" : $":\r\n{filePath}";
|
||||||
|
MessageBox.Show($"File not found" + suffix);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Serilog.Log.Logger.Error(ex, "An error occurred while handling the stop light button click for {libraryBook}", libraryBook);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -3,6 +3,7 @@ using System.Linq;
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
using ApplicationServices;
|
using ApplicationServices;
|
||||||
|
using DataLayer;
|
||||||
using Dinah.Core.Threading;
|
using Dinah.Core.Threading;
|
||||||
using LibationWinForms.Dialogs;
|
using LibationWinForms.Dialogs;
|
||||||
|
|
||||||
@ -48,10 +49,24 @@ namespace LibationWinForms
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void liberateVisible(object sender, EventArgs e)
|
private void liberateVisible(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
SetQueueCollapseState(false);
|
try
|
||||||
await Task.Run(() => processBookQueue1.AddDownloadDecrypt(productsDisplay.GetVisible()));
|
{
|
||||||
|
SetQueueCollapseState(false);
|
||||||
|
|
||||||
|
Serilog.Log.Logger.Information("Begin backing up visible library books");
|
||||||
|
|
||||||
|
processBookQueue1.AddDownloadDecrypt(
|
||||||
|
productsDisplay
|
||||||
|
.GetVisible()
|
||||||
|
.UnLiberated()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Serilog.Log.Logger.Error(ex, "An error occurred while backing up visible library books");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void replaceTagsToolStripMenuItem_Click(object sender, EventArgs e)
|
private void replaceTagsToolStripMenuItem_Click(object sender, EventArgs e)
|
||||||
|
|||||||
@ -50,45 +50,52 @@ namespace LibationWinForms.GridView
|
|||||||
#region Button controls
|
#region Button controls
|
||||||
private void DataGridView_CellContentClick(object sender, DataGridViewCellEventArgs e)
|
private void DataGridView_CellContentClick(object sender, DataGridViewCellEventArgs e)
|
||||||
{
|
{
|
||||||
// handle grid button click: https://stackoverflow.com/a/13687844
|
try
|
||||||
if (e.RowIndex < 0)
|
{
|
||||||
return;
|
// handle grid button click: https://stackoverflow.com/a/13687844
|
||||||
|
if (e.RowIndex < 0)
|
||||||
|
return;
|
||||||
|
|
||||||
var entry = getGridEntry(e.RowIndex);
|
var entry = getGridEntry(e.RowIndex);
|
||||||
if (entry is LibraryBookEntry lbEntry)
|
if (entry is LibraryBookEntry lbEntry)
|
||||||
{
|
|
||||||
if (e.ColumnIndex == liberateGVColumn.Index)
|
|
||||||
LiberateClicked?.Invoke(lbEntry);
|
|
||||||
else if (e.ColumnIndex == tagAndDetailsGVColumn.Index)
|
|
||||||
DetailsClicked?.Invoke(lbEntry);
|
|
||||||
else if (e.ColumnIndex == descriptionGVColumn.Index)
|
|
||||||
DescriptionClicked?.Invoke(lbEntry, gridEntryDataGridView.GetCellDisplayRectangle(e.ColumnIndex, e.RowIndex, false));
|
|
||||||
else if (e.ColumnIndex == coverGVColumn.Index)
|
|
||||||
CoverClicked?.Invoke(lbEntry);
|
|
||||||
}
|
|
||||||
else if (entry is SeriesEntry sEntry)
|
|
||||||
{
|
|
||||||
if (e.ColumnIndex == liberateGVColumn.Index)
|
|
||||||
{
|
{
|
||||||
if (sEntry.Liberate.Expanded)
|
if (e.ColumnIndex == liberateGVColumn.Index)
|
||||||
bindingList.CollapseItem(sEntry);
|
LiberateClicked?.Invoke(lbEntry);
|
||||||
else
|
else if (e.ColumnIndex == tagAndDetailsGVColumn.Index)
|
||||||
bindingList.ExpandItem(sEntry);
|
DetailsClicked?.Invoke(lbEntry);
|
||||||
|
else if (e.ColumnIndex == descriptionGVColumn.Index)
|
||||||
sEntry.NotifyPropertyChanged(nameof(sEntry.Liberate));
|
DescriptionClicked?.Invoke(lbEntry, gridEntryDataGridView.GetCellDisplayRectangle(e.ColumnIndex, e.RowIndex, false));
|
||||||
|
else if (e.ColumnIndex == coverGVColumn.Index)
|
||||||
VisibleCountChanged?.Invoke(this, bindingList.BookEntries().Count());
|
CoverClicked?.Invoke(lbEntry);
|
||||||
}
|
}
|
||||||
else if (e.ColumnIndex == descriptionGVColumn.Index)
|
else if (entry is SeriesEntry sEntry)
|
||||||
DescriptionClicked?.Invoke(sEntry, gridEntryDataGridView.GetCellDisplayRectangle(e.ColumnIndex, e.RowIndex, false));
|
{
|
||||||
else if (e.ColumnIndex == coverGVColumn.Index)
|
if (e.ColumnIndex == liberateGVColumn.Index)
|
||||||
CoverClicked?.Invoke(sEntry);
|
{
|
||||||
}
|
if (sEntry.Liberate.Expanded)
|
||||||
|
bindingList.CollapseItem(sEntry);
|
||||||
|
else
|
||||||
|
bindingList.ExpandItem(sEntry);
|
||||||
|
|
||||||
if (e.ColumnIndex == removeGVColumn.Index)
|
sEntry.NotifyPropertyChanged(nameof(sEntry.Liberate));
|
||||||
|
|
||||||
|
VisibleCountChanged?.Invoke(this, bindingList.BookEntries().Count());
|
||||||
|
}
|
||||||
|
else if (e.ColumnIndex == descriptionGVColumn.Index)
|
||||||
|
DescriptionClicked?.Invoke(sEntry, gridEntryDataGridView.GetCellDisplayRectangle(e.ColumnIndex, e.RowIndex, false));
|
||||||
|
else if (e.ColumnIndex == coverGVColumn.Index)
|
||||||
|
CoverClicked?.Invoke(sEntry);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (e.ColumnIndex == removeGVColumn.Index)
|
||||||
|
{
|
||||||
|
gridEntryDataGridView.CommitEdit(DataGridViewDataErrorContexts.Commit);
|
||||||
|
RemovableCountChanged?.Invoke(this, EventArgs.Empty);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch(Exception ex)
|
||||||
{
|
{
|
||||||
gridEntryDataGridView.CommitEdit(DataGridViewDataErrorContexts.Commit);
|
Serilog.Log.Logger.Error(ex, $"An error was encountered while processing a user click in the {nameof(ProductsGrid)}");
|
||||||
RemovableCountChanged?.Invoke(this, EventArgs.Empty);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
202
Source/_Tests/FileLiberator.Tests/DownloadDecryptBookTests.cs
Normal file
202
Source/_Tests/FileLiberator.Tests/DownloadDecryptBookTests.cs
Normal file
@ -0,0 +1,202 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using AudibleApi.Common;
|
||||||
|
using Dinah.Core;
|
||||||
|
using FileManager;
|
||||||
|
using FluentAssertions;
|
||||||
|
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||||
|
|
||||||
|
|
||||||
|
namespace FileLiberator.Tests
|
||||||
|
{
|
||||||
|
[TestClass]
|
||||||
|
public class DownloadDecryptBookTests
|
||||||
|
{
|
||||||
|
[TestMethod]
|
||||||
|
public void HierarchicalChapters_Flatten()
|
||||||
|
{
|
||||||
|
var expected = new Chapter[]
|
||||||
|
{
|
||||||
|
new()
|
||||||
|
{
|
||||||
|
Title = "Book 1: Part 1: Chapter 1",
|
||||||
|
StartOffsetMs = 0,
|
||||||
|
StartOffsetSec = 0,
|
||||||
|
LengthMs = 100000,
|
||||||
|
},
|
||||||
|
new()
|
||||||
|
{
|
||||||
|
Title = "Book 1: Part 1: Chapter 2",
|
||||||
|
StartOffsetMs = 100000,
|
||||||
|
StartOffsetSec = 100,
|
||||||
|
LengthMs = 100000,
|
||||||
|
},
|
||||||
|
new()
|
||||||
|
{
|
||||||
|
Title = "Book 1: Part 2: Chapter 3",
|
||||||
|
StartOffsetMs = 200000,
|
||||||
|
StartOffsetSec = 200,
|
||||||
|
LengthMs = 100000,
|
||||||
|
},
|
||||||
|
new()
|
||||||
|
{
|
||||||
|
Title = "Book 1: Part 2: Chapter 4",
|
||||||
|
StartOffsetMs = 300000,
|
||||||
|
StartOffsetSec = 300,
|
||||||
|
LengthMs = 100000,
|
||||||
|
},
|
||||||
|
new()
|
||||||
|
{
|
||||||
|
Title = "Book 2: Part 3: Chapter 5",
|
||||||
|
StartOffsetMs = 400000,
|
||||||
|
StartOffsetSec = 400,
|
||||||
|
LengthMs = 100000,
|
||||||
|
},
|
||||||
|
new()
|
||||||
|
{
|
||||||
|
Title = "Book 2: Part 3: Chapter 6",
|
||||||
|
StartOffsetMs = 500000,
|
||||||
|
StartOffsetSec = 500,
|
||||||
|
LengthMs = 100000,
|
||||||
|
},
|
||||||
|
new()
|
||||||
|
{
|
||||||
|
Title = "Book 2: Part 4: Chapter 7",
|
||||||
|
StartOffsetMs = 600000,
|
||||||
|
StartOffsetSec = 600,
|
||||||
|
LengthMs = 100000,
|
||||||
|
},
|
||||||
|
new()
|
||||||
|
{
|
||||||
|
Title = "Book 2: Part 4: Chapter 8",
|
||||||
|
StartOffsetMs = 700000,
|
||||||
|
StartOffsetSec = 700,
|
||||||
|
LengthMs = 100000,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var hierarchicalChapters = new Chapter[]
|
||||||
|
{
|
||||||
|
new()
|
||||||
|
{
|
||||||
|
Title = "Book 1",
|
||||||
|
StartOffsetMs = 0,
|
||||||
|
StartOffsetSec = 0,
|
||||||
|
LengthMs = 2000,
|
||||||
|
Chapters = new Chapter[]
|
||||||
|
{
|
||||||
|
new()
|
||||||
|
{ Title = "Part 1",
|
||||||
|
StartOffsetMs = 2000,
|
||||||
|
StartOffsetSec = 2,
|
||||||
|
LengthMs = 2000,
|
||||||
|
Chapters = new Chapter[]
|
||||||
|
{
|
||||||
|
new()
|
||||||
|
{ Title = "Chapter 1",
|
||||||
|
StartOffsetMs = 4000,
|
||||||
|
StartOffsetSec = 4,
|
||||||
|
LengthMs = 96000,
|
||||||
|
},
|
||||||
|
new()
|
||||||
|
{ Title = "Chapter 2",
|
||||||
|
StartOffsetMs = 100000,
|
||||||
|
StartOffsetSec = 100,
|
||||||
|
LengthMs = 100000,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
new()
|
||||||
|
{ Title = "Part 2",
|
||||||
|
StartOffsetMs = 200000,
|
||||||
|
StartOffsetSec = 200,
|
||||||
|
LengthMs = 2000,
|
||||||
|
Chapters = new Chapter[]
|
||||||
|
{
|
||||||
|
new()
|
||||||
|
{ Title = "Chapter 3",
|
||||||
|
StartOffsetMs = 202000,
|
||||||
|
StartOffsetSec = 202,
|
||||||
|
LengthMs = 98000,
|
||||||
|
},
|
||||||
|
new()
|
||||||
|
{ Title = "Chapter 4",
|
||||||
|
StartOffsetMs = 300000,
|
||||||
|
StartOffsetSec = 300,
|
||||||
|
LengthMs = 100000,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
new()
|
||||||
|
{
|
||||||
|
Title = "Book 2",
|
||||||
|
StartOffsetMs = 400000,
|
||||||
|
StartOffsetSec = 400,
|
||||||
|
LengthMs = 2000,
|
||||||
|
Chapters = new Chapter[]
|
||||||
|
{
|
||||||
|
new()
|
||||||
|
{ Title = "Part 3",
|
||||||
|
StartOffsetMs = 402000,
|
||||||
|
StartOffsetSec = 402,
|
||||||
|
LengthMs = 2000,
|
||||||
|
Chapters = new Chapter[]
|
||||||
|
{
|
||||||
|
new()
|
||||||
|
{ Title = "Chapter 5",
|
||||||
|
StartOffsetMs = 404000,
|
||||||
|
StartOffsetSec = 404,
|
||||||
|
LengthMs = 96000,
|
||||||
|
},
|
||||||
|
new()
|
||||||
|
{ Title = "Chapter 6",
|
||||||
|
StartOffsetMs = 500000,
|
||||||
|
StartOffsetSec = 500,
|
||||||
|
LengthMs = 100000,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
new()
|
||||||
|
{ Title = "Part 4",
|
||||||
|
StartOffsetMs = 600000,
|
||||||
|
StartOffsetSec = 600,
|
||||||
|
LengthMs = 2000,
|
||||||
|
Chapters = new Chapter[]
|
||||||
|
{
|
||||||
|
new()
|
||||||
|
{ Title = "Chapter 7",
|
||||||
|
StartOffsetMs = 602000,
|
||||||
|
StartOffsetSec = 602,
|
||||||
|
LengthMs = 98000,
|
||||||
|
},
|
||||||
|
new()
|
||||||
|
{ Title = "Chapter 8",
|
||||||
|
StartOffsetMs = 700000,
|
||||||
|
StartOffsetSec = 700,
|
||||||
|
LengthMs = 100000,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var flatChapters = DownloadDecryptBook.flattenChapters(hierarchicalChapters);
|
||||||
|
|
||||||
|
flatChapters.Count.Should().Be(expected.Length);
|
||||||
|
|
||||||
|
for (int i = 0; i < flatChapters.Count; i++)
|
||||||
|
{
|
||||||
|
flatChapters[i].Title.Should().Be(expected[i].Title);
|
||||||
|
flatChapters[i].StartOffsetMs.Should().Be(expected[i].StartOffsetMs);
|
||||||
|
flatChapters[i].StartOffsetSec.Should().Be(expected[i].StartOffsetSec);
|
||||||
|
flatChapters[i].LengthMs.Should().Be(expected[i].LengthMs);
|
||||||
|
flatChapters[i].Chapters.Should().BeNull();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user