* Batch actions for visible books: 'remove from library' complete

* refactor entity properties into extension methods
* refactor shared simple message boxes => MessageBoxLib
This commit is contained in:
Robert McRackan 2022-05-12 09:53:21 -04:00
parent b784bd6b8d
commit 75c5f662dc
22 changed files with 272 additions and 231 deletions

View file

@ -26,8 +26,8 @@ namespace LibationWinForms.BookLiberation
//Set default values from library
AudioDecodable_TitleDiscovered(sender, libraryBook.Book.Title);
AudioDecodable_AuthorsDiscovered(sender, libraryBook.Book.AuthorNames);
AudioDecodable_NarratorsDiscovered(sender, libraryBook.Book.NarratorNames);
AudioDecodable_AuthorsDiscovered(sender, libraryBook.Book.AuthorNames());
AudioDecodable_NarratorsDiscovered(sender, libraryBook.Book.NarratorNames());
AudioDecodable_CoverImageDiscovered(sender,
PictureStorage.GetPicture(
new PictureDefinition(

View file

@ -240,8 +240,8 @@ namespace LibationWinForms.BookLiberation
details =
$@" Title: {libraryBook.Book.Title}
ID: {libraryBook.Book.AudibleProductId}
Author: {trunc(libraryBook.Book.AuthorNames)}
Narr: {trunc(libraryBook.Book.NarratorNames)}";
Author: {trunc(libraryBook.Book.AuthorNames())}
Narr: {trunc(libraryBook.Book.NarratorNames())}";
}
catch
{

View file

@ -128,7 +128,7 @@ namespace LibationWinForms.Dialogs
}
catch (Exception ex)
{
MessageBoxAlertAdmin.Show("Error attempting to save accounts", "Error saving accounts", ex);
MessageBoxLib.ShowAdminAlert("Error attempting to save accounts", "Error saving accounts", ex);
}
}

View file

@ -46,15 +46,16 @@ namespace LibationWinForms.Dialogs
var t = @$"
Title: {Book.Title}
Author(s): {Book.AuthorNames}
Narrator(s): {Book.NarratorNames}
Author(s): {Book.AuthorNames()}
Narrator(s): {Book.NarratorNames()}
Length: {(Book.LengthInMinutes == 0 ? "" : $"{Book.LengthInMinutes / 60} hr {Book.LengthInMinutes % 60} min")}
Category: {string.Join(" > ", Book.CategoriesNames)}
Category: {string.Join(" > ", Book.CategoriesNames())}
Purchase Date: {_libraryBook.DateAdded.ToString("d")}
".Trim();
if (!string.IsNullOrWhiteSpace(Book.SeriesNames))
t += $"\r\nSeries: {Book.SeriesNames}";
var seriesNames = Book.SeriesNames();
if (!string.IsNullOrWhiteSpace(seriesNames))
t += $"\r\nSeries: {seriesNames}";
var bookRating = Book.Rating?.ToStarString();
if (!string.IsNullOrWhiteSpace(bookRating))

View file

@ -46,7 +46,7 @@ namespace LibationWinForms.Dialogs
if (template is null)
{
MessageBoxAlertAdmin.Show($"Programming error. {nameof(EditTemplateDialog)} was not created correctly", "Edit template error", new NullReferenceException($"{nameof(template)} is null"));
MessageBoxLib.ShowAdminAlert($"Programming error. {nameof(EditTemplateDialog)} was not created correctly", "Edit template error", new NullReferenceException($"{nameof(template)} is null"));
return;
}

View file

@ -77,7 +77,7 @@ namespace LibationWinForms.Dialogs
}
catch (Exception ex)
{
MessageBoxAlertAdmin.Show(
MessageBoxLib.ShowAdminAlert(
"Error scanning library. You may still manually select books to remove from Libation's library.",
"Error scanning library",
ex);
@ -95,34 +95,22 @@ namespace LibationWinForms.Dialogs
if (selectedBooks.Count == 0)
return;
var titles = selectedBooks.Select(rge => "- " + rge.Title).ToList();
var titlesAgg = titles.Take(5).Aggregate((a, b) => $"{a}\r\n{b}");
if (titles.Count == 6)
titlesAgg += $"\r\n\r\nand 1 other";
else if (titles.Count > 6)
titlesAgg += $"\r\n\r\nand {titles.Count - 5} others";
var libraryBooks = selectedBooks.Select(rge => rge.LibraryBook).ToList();
var result = MessageBoxLib.ShowConfirmationDialog(
libraryBooks,
$"Are you sure you want to remove {0} from Libation's library?",
"Remove books from Libation?");
string thisThese = selectedBooks.Count > 1 ? "these" : "this";
string bookBooks = selectedBooks.Count > 1 ? "books" : "book";
if (result != DialogResult.Yes)
return;
var result = MessageBox.Show(
this,
$"Are you sure you want to remove {thisThese} {selectedBooks.Count} {bookBooks} from Libation's library?\r\n\r\n{titlesAgg}",
"Remove books from Libation?",
MessageBoxButtons.YesNo,
MessageBoxIcon.Question,
MessageBoxDefaultButton.Button1);
var idsToRemove = libraryBooks.Select(lb => lb.Book.AudibleProductId).ToList();
var removeLibraryBooks = await LibraryCommands.RemoveBooksAsync(idsToRemove);
if (result == DialogResult.Yes)
{
var idsToRemove = selectedBooks.Select(rge => rge.AudibleProductId).ToList();
var removeLibraryBooks = await LibraryCommands.RemoveBooksAsync(idsToRemove);
foreach (var rEntry in selectedBooks)
_removableGridEntries.Remove(rEntry);
foreach (var rEntry in selectedBooks)
_removableGridEntries.Remove(rEntry);
UpdateSelection();
}
UpdateSelection();
}
private void UpdateSelection()

View file

@ -181,7 +181,7 @@ namespace LibationWinForms.Dialogs
// only warn if changed during this time. don't want to warn every time user happens to change settings while level is verbose
if (logLevelOld != logLevelNew)
MessageBoxVerboseLoggingWarning.ShowIfTrue();
MessageBoxLib.VerboseLoggingWarning_ShowIfTrue();
}
config.AllowLibationFixup = allowLibationFixupCbox.Checked;

View file

@ -404,7 +404,7 @@ namespace LibationWinForms
}
catch (Exception ex)
{
MessageBoxAlertAdmin.Show(
MessageBoxLib.ShowAdminAlert(
"Error importing library. Please try again. If this still happens after 2 or 3 tries, stop and contact administrator",
"Error importing library",
ex);
@ -468,7 +468,7 @@ namespace LibationWinForms
}
catch (Exception ex)
{
MessageBoxAlertAdmin.Show("Error attempting to export your library.", "Error exporting", ex);
MessageBoxLib.ShowAdminAlert("Error attempting to export your library.", "Error exporting", ex);
}
}
#endregion
@ -562,10 +562,7 @@ namespace LibationWinForms
}
private async void liberateVisible(object sender, EventArgs e)
{
var visibleBooks = productsGrid.GetVisible();
await BookLiberation.ProcessorAutomationController.BackupAllBooksAsync(visibleBooks);
}
=> await BookLiberation.ProcessorAutomationController.BackupAllBooksAsync(productsGrid.GetVisible());
private void replaceTagsToolStripMenuItem_Click(object sender, EventArgs e)
{
@ -585,7 +582,17 @@ namespace LibationWinForms
private async void removeToolStripMenuItem_Click(object sender, EventArgs e)
{
var visibleIds = productsGrid.GetVisible().Select(lb => lb.Book.AudibleProductId).ToList();
var libraryBooks = productsGrid.GetVisible();
var result = MessageBoxLib.ShowConfirmationDialog(
libraryBooks,
$"Are you sure you want to remove {0} from Libation's library?",
"Remove books from Libation?");
if (result != DialogResult.Yes)
return;
var visibleIds = libraryBooks.Select(lb => lb.Book.AudibleProductId).ToList();
await LibraryCommands.RemoveBooksAsync(visibleIds);
}
#endregion

View file

@ -1,27 +0,0 @@
using System;
using LibationWinForms.Dialogs;
namespace LibationWinForms
{
public static class MessageBoxAlertAdmin
{
/// <summary>
/// Logs error. Displays a message box dialog with specified text and caption.
/// </summary>
/// <param name="text">The text to display in the message box.</param>
/// <param name="caption">The text to display in the title bar of the message box.</param>
/// <param name="exception">Exception to log</param>
/// <returns>One of the System.Windows.Forms.DialogResult values.</returns>
public static System.Windows.Forms.DialogResult Show(string text, string caption, Exception exception)
{
try
{
Serilog.Log.Logger.Error(exception, "Alert admin error: {@DebugText}", new { text, caption });
}
catch { }
using var form = new MessageBoxAlertAdminDialog(text, caption, exception);
return form.ShowDialog();
}
}
}

View file

@ -0,0 +1,72 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using DataLayer;
using Dinah.Core.Logging;
using LibationWinForms.Dialogs;
using Serilog;
namespace LibationWinForms
{
public static class MessageBoxLib
{
/// <summary>
/// Logs error. Displays a message box dialog with specified text and caption.
/// </summary>
/// <param name="text">The text to display in the message box.</param>
/// <param name="caption">The text to display in the title bar of the message box.</param>
/// <param name="exception">Exception to log</param>
/// <returns>One of the System.Windows.Forms.DialogResult values.</returns>
public static DialogResult ShowAdminAlert(string text, string caption, Exception exception)
{
try
{
Serilog.Log.Logger.Error(exception, "Alert admin error: {@DebugText}", new { text, caption });
}
catch { }
using var form = new MessageBoxAlertAdminDialog(text, caption, exception);
return form.ShowDialog();
}
public static void VerboseLoggingWarning_ShowIfTrue()
{
// when turning on debug (and especially Verbose) to share logs, some privacy settings may not be obscured
if (Log.Logger.IsVerboseEnabled())
MessageBox.Show(@"
Warning: verbose logging is enabled.
This should be used for debugging only. It creates many
more logs and debug files, neither of which are as
strictly anonymous.
When you are finished debugging, it's highly recommended
to set your debug MinimumLevel to Information and restart
Libation.
".Trim(), "Verbose logging enabled", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
public static DialogResult ShowConfirmationDialog(IEnumerable<LibraryBook> libraryBooks, string format, string title)
{
if (libraryBooks is null || !libraryBooks.Any())
return DialogResult.Cancel;
var count = libraryBooks.Count();
string thisThese = count > 1 ? "these" : "this";
string bookBooks = count > 1 ? "books" : "book";
string titlesAgg = libraryBooks.AggregateTitles();
var message
= string.Format(format, $"{thisThese} {count} {bookBooks}")
+ $"\r\n\r\n{titlesAgg}";
return MessageBox.Show(
message,
title,
MessageBoxButtons.YesNo,
MessageBoxIcon.Question,
MessageBoxDefaultButton.Button1);
}
}
}

View file

@ -1,28 +0,0 @@
using System;
using System.Linq;
using Dinah.Core.Logging;
using Serilog;
using System.Windows.Forms;
namespace LibationWinForms
{
public static class MessageBoxVerboseLoggingWarning
{
public static void ShowIfTrue()
{
// when turning on debug (and especially Verbose) to share logs, some privacy settings may not be obscured
if (Log.Logger.IsVerboseEnabled())
MessageBox.Show(@"
Warning: verbose logging is enabled.
This should be used for debugging only. It creates many
more logs and debug files, neither of which are as
strictly anonymous.
When you are finished debugging, it's highly recommended
to set your debug MinimumLevel to Information and restart
Libation.
".Trim(), "Verbose logging enabled", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
}
}

View file

@ -49,7 +49,7 @@ namespace LibationWinForms
// migrations which require Forms or are long-running
RunWindowsOnlyMigrations(config);
MessageBoxVerboseLoggingWarning.ShowIfTrue();
MessageBoxLib.VerboseLoggingWarning_ShowIfTrue();
#if !DEBUG
checkForUpdate();
@ -63,7 +63,7 @@ namespace LibationWinForms
var body = "An unrecoverable error occurred. Since this error happened before logging could be initialized, this error can not be written to the log file.";
try
{
MessageBoxAlertAdmin.Show(body, title, ex);
MessageBoxLib.ShowAdminAlert(body, title, ex);
}
catch
{
@ -178,7 +178,7 @@ namespace LibationWinForms
}
catch (Exception ex)
{
MessageBoxAlertAdmin.Show("Error checking for update", "Error checking for update", ex);
MessageBoxLib.ShowAdminAlert("Error checking for update", "Error checking for update", ex);
return;
}
@ -203,7 +203,7 @@ namespace LibationWinForms
}
catch (Exception ex)
{
MessageBoxAlertAdmin.Show("Error downloading update", "Error downloading update", ex);
MessageBoxLib.ShowAdminAlert("Error downloading update", "Error downloading update", ex);
}
}
}

View file

@ -128,14 +128,14 @@ namespace LibationWinForms
// Immutable properties
{
Title = Book.Title;
Series = Book.SeriesNames;
Series = Book.SeriesNames();
Length = Book.LengthInMinutes == 0 ? "" : $"{Book.LengthInMinutes / 60} hr {Book.LengthInMinutes % 60} min";
MyRating = Book.UserDefinedItem.Rating?.ToStarString()?.DefaultIfNullOrWhiteSpace("");
PurchaseDate = libraryBook.DateAdded.ToString("d");
ProductRating = Book.Rating?.ToStarString()?.DefaultIfNullOrWhiteSpace("");
Authors = Book.AuthorNames;
Narrators = Book.NarratorNames;
Category = string.Join(" > ", Book.CategoriesNames);
Authors = Book.AuthorNames();
Narrators = Book.NarratorNames();
Category = string.Join(" > ", Book.CategoriesNames());
Misc = GetMiscDisplay(libraryBook);
LongDescription = GetDescriptionDisplay(Book);
Description = TrimTextToWord(LongDescription, 62);
@ -232,12 +232,12 @@ namespace LibationWinForms
/// </summary>
private Dictionary<string, Func<object>> CreateMemberValueDictionary() => new()
{
{ nameof(Title), () => Book.TitleSortable },
{ nameof(Series), () => Book.SeriesSortable },
{ nameof(Title), () => Book.TitleSortable() },
{ nameof(Series), () => Book.SeriesSortable() },
{ nameof(Length), () => Book.LengthInMinutes },
{ nameof(MyRating), () => Book.UserDefinedItem.Rating.FirstScore },
{ nameof(MyRating), () => Book.UserDefinedItem.Rating.FirstScore() },
{ nameof(PurchaseDate), () => LibraryBook.DateAdded },
{ nameof(ProductRating), () => Book.Rating.FirstScore },
{ nameof(ProductRating), () => Book.Rating.FirstScore() },
{ nameof(Authors), () => Authors },
{ nameof(Narrators), () => Narrators },
{ nameof(Description), () => Description },
@ -292,7 +292,7 @@ namespace LibationWinForms
details.Add($"Account: {locale} - {acct}");
if (libraryBook.Book.HasPdf)
if (libraryBook.Book.HasPdf())
details.Add("Has PDF");
if (libraryBook.Book.IsAbridged)
details.Add("Abridged");

View file

@ -5,6 +5,7 @@ using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
using ApplicationServices;
using DataLayer;
using Dinah.Core;
using Dinah.Core.DataBinding;
using Dinah.Core.Threading;
@ -128,7 +129,7 @@ namespace LibationWinForms
var libraryBook = liveGridEntry.LibraryBook;
// liberated: open explorer to file
if (libraryBook.Book.Audio_Exists)
if (libraryBook.Book.Audio_Exists())
{
var filePath = AudibleFileStorage.Audio.GetPath(libraryBook.Book.AudibleProductId);
if (!Go.To.File(filePath))