New feature #430 : bulk set pdf-downloaded status
This commit is contained in:
parent
c98664d584
commit
83fb2cd1d0
@ -13,221 +13,221 @@ using static DtoImporterService.PerfLogger;
|
|||||||
|
|
||||||
namespace ApplicationServices
|
namespace ApplicationServices
|
||||||
{
|
{
|
||||||
public static class LibraryCommands
|
public static class LibraryCommands
|
||||||
{
|
{
|
||||||
public static event EventHandler<int> ScanBegin;
|
public static event EventHandler<int> ScanBegin;
|
||||||
public static event EventHandler ScanEnd;
|
public static event EventHandler ScanEnd;
|
||||||
|
|
||||||
public static bool Scanning { get; private set; }
|
public static bool Scanning { get; private set; }
|
||||||
private static object _lock { get; } = new();
|
private static object _lock { get; } = new();
|
||||||
|
|
||||||
static LibraryCommands()
|
static LibraryCommands()
|
||||||
{
|
{
|
||||||
ScanBegin += (_, __) => Scanning = true;
|
ScanBegin += (_, __) => Scanning = true;
|
||||||
ScanEnd += (_, __) => Scanning = false;
|
ScanEnd += (_, __) => Scanning = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async Task<List<LibraryBook>> FindInactiveBooks(Func<Account, Task<ApiExtended>> apiExtendedfunc, IEnumerable<LibraryBook> existingLibrary, params Account[] accounts)
|
public static async Task<List<LibraryBook>> FindInactiveBooks(Func<Account, Task<ApiExtended>> apiExtendedfunc, IEnumerable<LibraryBook> existingLibrary, params Account[] accounts)
|
||||||
{
|
{
|
||||||
logRestart();
|
logRestart();
|
||||||
|
|
||||||
lock (_lock)
|
lock (_lock)
|
||||||
{
|
|
||||||
if (Scanning)
|
|
||||||
return new();
|
|
||||||
}
|
|
||||||
ScanBegin?.Invoke(null, accounts.Length);
|
|
||||||
|
|
||||||
//These are the minimum response groups required for the
|
|
||||||
//library scanner to pass all validation and filtering.
|
|
||||||
var libraryOptions = new LibraryOptions
|
|
||||||
{
|
{
|
||||||
ResponseGroups
|
if (Scanning)
|
||||||
= LibraryOptions.ResponseGroupOptions.ProductAttrs
|
return new();
|
||||||
| LibraryOptions.ResponseGroupOptions.ProductDesc
|
}
|
||||||
| LibraryOptions.ResponseGroupOptions.Relationships
|
ScanBegin?.Invoke(null, accounts.Length);
|
||||||
};
|
|
||||||
|
//These are the minimum response groups required for the
|
||||||
|
//library scanner to pass all validation and filtering.
|
||||||
|
var libraryOptions = new LibraryOptions
|
||||||
|
{
|
||||||
|
ResponseGroups
|
||||||
|
= LibraryOptions.ResponseGroupOptions.ProductAttrs
|
||||||
|
| LibraryOptions.ResponseGroupOptions.ProductDesc
|
||||||
|
| LibraryOptions.ResponseGroupOptions.Relationships
|
||||||
|
};
|
||||||
if (accounts is null || accounts.Length == 0)
|
if (accounts is null || accounts.Length == 0)
|
||||||
return new List<LibraryBook>();
|
return new List<LibraryBook>();
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
logTime($"pre {nameof(scanAccountsAsync)} all");
|
logTime($"pre {nameof(scanAccountsAsync)} all");
|
||||||
var libraryItems = await scanAccountsAsync(apiExtendedfunc, accounts, libraryOptions);
|
var libraryItems = await scanAccountsAsync(apiExtendedfunc, accounts, libraryOptions);
|
||||||
logTime($"post {nameof(scanAccountsAsync)} all");
|
logTime($"post {nameof(scanAccountsAsync)} all");
|
||||||
|
|
||||||
var totalCount = libraryItems.Count;
|
var totalCount = libraryItems.Count;
|
||||||
Log.Logger.Information($"GetAllLibraryItems: Total count {totalCount}");
|
Log.Logger.Information($"GetAllLibraryItems: Total count {totalCount}");
|
||||||
|
|
||||||
var missingBookList = existingLibrary.Where(b => !libraryItems.Any(i => i.DtoItem.Asin == b.Book.AudibleProductId)).ToList();
|
var missingBookList = existingLibrary.Where(b => !libraryItems.Any(i => i.DtoItem.Asin == b.Book.AudibleProductId)).ToList();
|
||||||
|
|
||||||
return missingBookList;
|
return missingBookList;
|
||||||
}
|
}
|
||||||
catch (AudibleApi.Authentication.LoginFailedException lfEx)
|
catch (AudibleApi.Authentication.LoginFailedException lfEx)
|
||||||
{
|
{
|
||||||
lfEx.SaveFiles(Configuration.Instance.LibationFiles);
|
lfEx.SaveFiles(Configuration.Instance.LibationFiles);
|
||||||
|
|
||||||
// nuget Serilog.Exceptions would automatically log custom properties
|
// nuget Serilog.Exceptions would automatically log custom properties
|
||||||
// However, it comes with a scary warning when used with EntityFrameworkCore which I'm not yet ready to implement:
|
// However, it comes with a scary warning when used with EntityFrameworkCore which I'm not yet ready to implement:
|
||||||
// https://github.com/RehanSaeed/Serilog.Exceptions
|
// https://github.com/RehanSaeed/Serilog.Exceptions
|
||||||
// work-around: use 3rd param. don't just put exception object in 3rd param -- info overload: stack trace, etc
|
// work-around: use 3rd param. don't just put exception object in 3rd param -- info overload: stack trace, etc
|
||||||
Log.Logger.Error(lfEx, "Error scanning library. Login failed. {@DebugInfo}", new
|
Log.Logger.Error(lfEx, "Error scanning library. Login failed. {@DebugInfo}", new
|
||||||
{
|
|
||||||
lfEx.RequestUrl,
|
|
||||||
ResponseStatusCodeNumber = (int)lfEx.ResponseStatusCode,
|
|
||||||
ResponseStatusCodeDesc = lfEx.ResponseStatusCode,
|
|
||||||
lfEx.ResponseInputFields,
|
|
||||||
lfEx.ResponseBodyFilePaths
|
|
||||||
});
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Log.Logger.Error(ex, "Error scanning library");
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
stop();
|
|
||||||
var putBreakPointHere = logOutput;
|
|
||||||
ScanEnd?.Invoke(null, null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#region FULL LIBRARY scan and import
|
|
||||||
public static async Task<(int totalCount, int newCount)> ImportAccountAsync(Func<Account, Task<ApiExtended>> apiExtendedfunc, params Account[] accounts)
|
|
||||||
{
|
|
||||||
logRestart();
|
|
||||||
|
|
||||||
if (accounts is null || accounts.Length == 0)
|
|
||||||
return (0, 0);
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
lock (_lock)
|
|
||||||
{
|
{
|
||||||
if (Scanning)
|
lfEx.RequestUrl,
|
||||||
return (0, 0);
|
ResponseStatusCodeNumber = (int)lfEx.ResponseStatusCode,
|
||||||
}
|
ResponseStatusCodeDesc = lfEx.ResponseStatusCode,
|
||||||
ScanBegin?.Invoke(null, accounts.Length);
|
lfEx.ResponseInputFields,
|
||||||
|
lfEx.ResponseBodyFilePaths
|
||||||
|
});
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Log.Logger.Error(ex, "Error scanning library");
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
stop();
|
||||||
|
var putBreakPointHere = logOutput;
|
||||||
|
ScanEnd?.Invoke(null, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
logTime($"pre {nameof(scanAccountsAsync)} all");
|
#region FULL LIBRARY scan and import
|
||||||
var libraryOptions = new LibraryOptions
|
public static async Task<(int totalCount, int newCount)> ImportAccountAsync(Func<Account, Task<ApiExtended>> apiExtendedfunc, params Account[] accounts)
|
||||||
{
|
{
|
||||||
ResponseGroups = LibraryOptions.ResponseGroupOptions.ALL_OPTIONS,
|
logRestart();
|
||||||
ImageSizes = LibraryOptions.ImageSizeOptions._500 | LibraryOptions.ImageSizeOptions._1215
|
|
||||||
};
|
if (accounts is null || accounts.Length == 0)
|
||||||
|
return (0, 0);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
lock (_lock)
|
||||||
|
{
|
||||||
|
if (Scanning)
|
||||||
|
return (0, 0);
|
||||||
|
}
|
||||||
|
ScanBegin?.Invoke(null, accounts.Length);
|
||||||
|
|
||||||
|
logTime($"pre {nameof(scanAccountsAsync)} all");
|
||||||
|
var libraryOptions = new LibraryOptions
|
||||||
|
{
|
||||||
|
ResponseGroups = LibraryOptions.ResponseGroupOptions.ALL_OPTIONS,
|
||||||
|
ImageSizes = LibraryOptions.ImageSizeOptions._500 | LibraryOptions.ImageSizeOptions._1215
|
||||||
|
};
|
||||||
var importItems = await scanAccountsAsync(apiExtendedfunc, accounts, libraryOptions);
|
var importItems = await scanAccountsAsync(apiExtendedfunc, accounts, libraryOptions);
|
||||||
logTime($"post {nameof(scanAccountsAsync)} all");
|
logTime($"post {nameof(scanAccountsAsync)} all");
|
||||||
|
|
||||||
var totalCount = importItems.Count;
|
var totalCount = importItems.Count;
|
||||||
Log.Logger.Information($"GetAllLibraryItems: Total count {totalCount}");
|
Log.Logger.Information($"GetAllLibraryItems: Total count {totalCount}");
|
||||||
|
|
||||||
if (totalCount == 0)
|
if (totalCount == 0)
|
||||||
return default;
|
return default;
|
||||||
|
|
||||||
|
|
||||||
Log.Logger.Information("Begin scan for orphaned episode parents");
|
Log.Logger.Information("Begin scan for orphaned episode parents");
|
||||||
var newParents = await findAndAddMissingParents(accounts);
|
var newParents = await findAndAddMissingParents(accounts);
|
||||||
Log.Logger.Information($"Orphan episode scan complete. New parents count {newParents}");
|
Log.Logger.Information($"Orphan episode scan complete. New parents count {newParents}");
|
||||||
|
|
||||||
if (newParents >= 0)
|
if (newParents >= 0)
|
||||||
{
|
{
|
||||||
//If any episodes are still orphaned, their series have been
|
//If any episodes are still orphaned, their series have been
|
||||||
//removed from the catalog and we'll never be able to find them.
|
//removed from the catalog and we'll never be able to find them.
|
||||||
|
|
||||||
//only do this if findAndAddMissingParents returned >= 0. If it
|
//only do this if findAndAddMissingParents returned >= 0. If it
|
||||||
//returned < 0, an error happened and there's still a chance that
|
//returned < 0, an error happened and there's still a chance that
|
||||||
//a future successful run will find missing parents.
|
//a future successful run will find missing parents.
|
||||||
removedOrphanedEpisodes();
|
removedOrphanedEpisodes();
|
||||||
}
|
}
|
||||||
|
|
||||||
Log.Logger.Information("Begin long-running import");
|
Log.Logger.Information("Begin long-running import");
|
||||||
logTime($"pre {nameof(importIntoDbAsync)}");
|
logTime($"pre {nameof(importIntoDbAsync)}");
|
||||||
var newCount = await importIntoDbAsync(importItems);
|
var newCount = await importIntoDbAsync(importItems);
|
||||||
logTime($"post {nameof(importIntoDbAsync)}");
|
logTime($"post {nameof(importIntoDbAsync)}");
|
||||||
Log.Logger.Information($"Import complete. New count {newCount}");
|
Log.Logger.Information($"Import complete. New count {newCount}");
|
||||||
|
|
||||||
return (totalCount, newCount);
|
return (totalCount, newCount);
|
||||||
}
|
}
|
||||||
catch (AudibleApi.Authentication.LoginFailedException lfEx)
|
catch (AudibleApi.Authentication.LoginFailedException lfEx)
|
||||||
{
|
{
|
||||||
lfEx.SaveFiles(Configuration.Instance.LibationFiles);
|
lfEx.SaveFiles(Configuration.Instance.LibationFiles);
|
||||||
|
|
||||||
// nuget Serilog.Exceptions would automatically log custom properties
|
// nuget Serilog.Exceptions would automatically log custom properties
|
||||||
// However, it comes with a scary warning when used with EntityFrameworkCore which I'm not yet ready to implement:
|
// However, it comes with a scary warning when used with EntityFrameworkCore which I'm not yet ready to implement:
|
||||||
// https://github.com/RehanSaeed/Serilog.Exceptions
|
// https://github.com/RehanSaeed/Serilog.Exceptions
|
||||||
// work-around: use 3rd param. don't just put exception object in 3rd param -- info overload: stack trace, etc
|
// work-around: use 3rd param. don't just put exception object in 3rd param -- info overload: stack trace, etc
|
||||||
Log.Logger.Error(lfEx, "Error importing library. Login failed. {@DebugInfo}", new
|
Log.Logger.Error(lfEx, "Error importing library. Login failed. {@DebugInfo}", new
|
||||||
{
|
{
|
||||||
lfEx.RequestUrl,
|
lfEx.RequestUrl,
|
||||||
ResponseStatusCodeNumber = (int)lfEx.ResponseStatusCode,
|
ResponseStatusCodeNumber = (int)lfEx.ResponseStatusCode,
|
||||||
ResponseStatusCodeDesc = lfEx.ResponseStatusCode,
|
ResponseStatusCodeDesc = lfEx.ResponseStatusCode,
|
||||||
lfEx.ResponseInputFields,
|
lfEx.ResponseInputFields,
|
||||||
lfEx.ResponseBodyFilePaths
|
lfEx.ResponseBodyFilePaths
|
||||||
});
|
});
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Log.Logger.Error(ex, "Error importing library");
|
Log.Logger.Error(ex, "Error importing library");
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
stop();
|
stop();
|
||||||
var putBreakPointHere = logOutput;
|
var putBreakPointHere = logOutput;
|
||||||
ScanEnd?.Invoke(null, null);
|
ScanEnd?.Invoke(null, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static async Task<List<ImportItem>> scanAccountsAsync(Func<Account, Task<ApiExtended>> apiExtendedfunc, Account[] accounts, LibraryOptions libraryOptions)
|
private static async Task<List<ImportItem>> scanAccountsAsync(Func<Account, Task<ApiExtended>> apiExtendedfunc, Account[] accounts, LibraryOptions libraryOptions)
|
||||||
{
|
{
|
||||||
var tasks = new List<Task<List<ImportItem>>>();
|
var tasks = new List<Task<List<ImportItem>>>();
|
||||||
foreach (var account in accounts)
|
foreach (var account in accounts)
|
||||||
{
|
{
|
||||||
// get APIs in serial b/c of logins. do NOT move inside of parallel (Task.WhenAll)
|
// get APIs in serial b/c of logins. do NOT move inside of parallel (Task.WhenAll)
|
||||||
var apiExtended = await apiExtendedfunc(account);
|
var apiExtended = await apiExtendedfunc(account);
|
||||||
|
|
||||||
// add scanAccountAsync as a TASK: do not await
|
// add scanAccountAsync as a TASK: do not await
|
||||||
tasks.Add(scanAccountAsync(apiExtended, account, libraryOptions));
|
tasks.Add(scanAccountAsync(apiExtended, account, libraryOptions));
|
||||||
}
|
}
|
||||||
|
|
||||||
// import library in parallel
|
// import library in parallel
|
||||||
var arrayOfLists = await Task.WhenAll(tasks);
|
var arrayOfLists = await Task.WhenAll(tasks);
|
||||||
var importItems = arrayOfLists.SelectMany(a => a).ToList();
|
var importItems = arrayOfLists.SelectMany(a => a).ToList();
|
||||||
return importItems;
|
return importItems;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static async Task<List<ImportItem>> scanAccountAsync(ApiExtended apiExtended, Account account, LibraryOptions libraryOptions)
|
private static async Task<List<ImportItem>> scanAccountAsync(ApiExtended apiExtended, Account account, LibraryOptions libraryOptions)
|
||||||
{
|
{
|
||||||
ArgumentValidator.EnsureNotNull(account, nameof(account));
|
ArgumentValidator.EnsureNotNull(account, nameof(account));
|
||||||
|
|
||||||
Log.Logger.Information("ImportLibraryAsync. {@DebugInfo}", new
|
Log.Logger.Information("ImportLibraryAsync. {@DebugInfo}", new
|
||||||
{
|
{
|
||||||
Account = account?.MaskedLogEntry ?? "[null]"
|
Account = account?.MaskedLogEntry ?? "[null]"
|
||||||
});
|
});
|
||||||
|
|
||||||
logTime($"pre scanAccountAsync {account.AccountName}");
|
logTime($"pre scanAccountAsync {account.AccountName}");
|
||||||
|
|
||||||
var dtoItems = await apiExtended.GetLibraryValidatedAsync(libraryOptions, Configuration.Instance.ImportEpisodes);
|
var dtoItems = await apiExtended.GetLibraryValidatedAsync(libraryOptions, Configuration.Instance.ImportEpisodes);
|
||||||
|
|
||||||
logTime($"post scanAccountAsync {account.AccountName} qty: {dtoItems.Count}");
|
logTime($"post scanAccountAsync {account.AccountName} qty: {dtoItems.Count}");
|
||||||
|
|
||||||
return dtoItems.Select(d => new ImportItem { DtoItem = d, AccountId = account.AccountId, LocaleName = account.Locale?.Name }).ToList();
|
return dtoItems.Select(d => new ImportItem { DtoItem = d, AccountId = account.AccountId, LocaleName = account.Locale?.Name }).ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static async Task<int> importIntoDbAsync(List<ImportItem> importItems)
|
private static async Task<int> importIntoDbAsync(List<ImportItem> importItems)
|
||||||
{
|
{
|
||||||
logTime("importIntoDbAsync -- pre db");
|
logTime("importIntoDbAsync -- pre db");
|
||||||
using var context = DbContexts.GetContext();
|
using var context = DbContexts.GetContext();
|
||||||
var libraryBookImporter = new LibraryBookImporter(context);
|
var libraryBookImporter = new LibraryBookImporter(context);
|
||||||
var newCount = await Task.Run(() => libraryBookImporter.Import(importItems));
|
var newCount = await Task.Run(() => libraryBookImporter.Import(importItems));
|
||||||
logTime("importIntoDbAsync -- post Import()");
|
logTime("importIntoDbAsync -- post Import()");
|
||||||
int qtyChanges = SaveContext(context);
|
int qtyChanges = SaveContext(context);
|
||||||
logTime("importIntoDbAsync -- post SaveChanges");
|
logTime("importIntoDbAsync -- post SaveChanges");
|
||||||
|
|
||||||
// this is any changes at all to the database, not just new books
|
// this is any changes at all to the database, not just new books
|
||||||
if (qtyChanges > 0)
|
if (qtyChanges > 0)
|
||||||
await Task.Run(() => finalizeLibrarySizeChange());
|
await Task.Run(() => finalizeLibrarySizeChange());
|
||||||
logTime("importIntoDbAsync -- post finalizeLibrarySizeChange");
|
logTime("importIntoDbAsync -- post finalizeLibrarySizeChange");
|
||||||
@ -235,112 +235,112 @@ namespace ApplicationServices
|
|||||||
return newCount;
|
return newCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void removedOrphanedEpisodes()
|
static void removedOrphanedEpisodes()
|
||||||
{
|
{
|
||||||
using var context = DbContexts.GetContext();
|
using var context = DbContexts.GetContext();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var orphanedEpisodes =
|
var orphanedEpisodes =
|
||||||
context
|
context
|
||||||
.GetLibrary_Flat_NoTracking(includeParents: true)
|
.GetLibrary_Flat_NoTracking(includeParents: true)
|
||||||
.FindOrphanedEpisodes();
|
.FindOrphanedEpisodes();
|
||||||
|
|
||||||
context.LibraryBooks.RemoveRange(orphanedEpisodes);
|
context.LibraryBooks.RemoveRange(orphanedEpisodes);
|
||||||
context.Books.RemoveRange(orphanedEpisodes.Select(lb => lb.Book));
|
context.Books.RemoveRange(orphanedEpisodes.Select(lb => lb.Book));
|
||||||
|
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Serilog.Log.Logger.Error(ex, "An error occurred while trying to remove orphaned episodes from the database");
|
Serilog.Log.Logger.Error(ex, "An error occurred while trying to remove orphaned episodes from the database");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static async Task<int> findAndAddMissingParents(Account[] accounts)
|
static async Task<int> findAndAddMissingParents(Account[] accounts)
|
||||||
{
|
{
|
||||||
using var context = DbContexts.GetContext();
|
using var context = DbContexts.GetContext();
|
||||||
|
|
||||||
var library = context.GetLibrary_Flat_NoTracking(includeParents: true);
|
var library = context.GetLibrary_Flat_NoTracking(includeParents: true);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var orphanedEpisodes = library.FindOrphanedEpisodes().ToList();
|
var orphanedEpisodes = library.FindOrphanedEpisodes().ToList();
|
||||||
|
|
||||||
if (!orphanedEpisodes.Any())
|
if (!orphanedEpisodes.Any())
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
var orphanedSeries =
|
var orphanedSeries =
|
||||||
orphanedEpisodes
|
orphanedEpisodes
|
||||||
.SelectMany(lb => lb.Book.SeriesLink)
|
.SelectMany(lb => lb.Book.SeriesLink)
|
||||||
.DistinctBy(s => s.Series.AudibleSeriesId)
|
.DistinctBy(s => s.Series.AudibleSeriesId)
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
// The Catalog endpoint does not require authentication.
|
// The Catalog endpoint does not require authentication.
|
||||||
var api = new ApiUnauthenticated(accounts[0].Locale);
|
var api = new ApiUnauthenticated(accounts[0].Locale);
|
||||||
|
|
||||||
var seriesParents = orphanedSeries.Select(o => o.Series.AudibleSeriesId).ToList();
|
var seriesParents = orphanedSeries.Select(o => o.Series.AudibleSeriesId).ToList();
|
||||||
var items = await api.GetCatalogProductsAsync(seriesParents, CatalogOptions.ResponseGroupOptions.ALL_OPTIONS);
|
var items = await api.GetCatalogProductsAsync(seriesParents, CatalogOptions.ResponseGroupOptions.ALL_OPTIONS);
|
||||||
|
|
||||||
List<ImportItem> newParentsImportItems = new();
|
List<ImportItem> newParentsImportItems = new();
|
||||||
foreach (var sp in orphanedSeries)
|
foreach (var sp in orphanedSeries)
|
||||||
{
|
{
|
||||||
var seriesItem = items.First(i => i.Asin == sp.Series.AudibleSeriesId);
|
var seriesItem = items.First(i => i.Asin == sp.Series.AudibleSeriesId);
|
||||||
|
|
||||||
if (seriesItem.Relationships is null)
|
if (seriesItem.Relationships is null)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
var episode = orphanedEpisodes.First(l => l.Book.AudibleProductId == sp.Book.AudibleProductId);
|
var episode = orphanedEpisodes.First(l => l.Book.AudibleProductId == sp.Book.AudibleProductId);
|
||||||
|
|
||||||
seriesItem.PurchaseDate = new DateTimeOffset(episode.DateAdded);
|
seriesItem.PurchaseDate = new DateTimeOffset(episode.DateAdded);
|
||||||
seriesItem.Series = new AudibleApi.Common.Series[]
|
seriesItem.Series = new AudibleApi.Common.Series[]
|
||||||
{
|
{
|
||||||
new AudibleApi.Common.Series{ Asin = seriesItem.Asin, Title = seriesItem.TitleWithSubtitle, Sequence = "-1"}
|
new AudibleApi.Common.Series{ Asin = seriesItem.Asin, Title = seriesItem.TitleWithSubtitle, Sequence = "-1"}
|
||||||
};
|
};
|
||||||
|
|
||||||
newParentsImportItems.Add(new ImportItem { DtoItem = seriesItem, AccountId = episode.Account, LocaleName = episode.Book.Locale });
|
newParentsImportItems.Add(new ImportItem { DtoItem = seriesItem, AccountId = episode.Account, LocaleName = episode.Book.Locale });
|
||||||
}
|
}
|
||||||
|
|
||||||
var newCount = new LibraryBookImporter(context)
|
var newCount = new LibraryBookImporter(context)
|
||||||
.Import(newParentsImportItems);
|
.Import(newParentsImportItems);
|
||||||
|
|
||||||
await context.SaveChangesAsync();
|
await context.SaveChangesAsync();
|
||||||
|
|
||||||
return newCount;
|
return newCount;
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Serilog.Log.Logger.Error(ex, "An error occurred while trying to scan for orphaned episode parents.");
|
Serilog.Log.Logger.Error(ex, "An error occurred while trying to scan for orphaned episode parents.");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int SaveContext(LibationContext context)
|
public static int SaveContext(LibationContext context)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
return context.SaveChanges();
|
return context.SaveChanges();
|
||||||
}
|
}
|
||||||
catch (Microsoft.EntityFrameworkCore.DbUpdateException ex)
|
catch (Microsoft.EntityFrameworkCore.DbUpdateException ex)
|
||||||
{
|
{
|
||||||
// DbUpdateException exceptions can wreck serilog. Condense it until we can find a better solution. I suspect the culprit is the "WithExceptionDetails" serilog extension
|
// DbUpdateException exceptions can wreck serilog. Condense it until we can find a better solution. I suspect the culprit is the "WithExceptionDetails" serilog extension
|
||||||
|
|
||||||
static string format(Exception ex) => $"\r\nMessage: {ex.Message}\r\nStack Trace:\r\n{ex.StackTrace}";
|
static string format(Exception ex) => $"\r\nMessage: {ex.Message}\r\nStack Trace:\r\n{ex.StackTrace}";
|
||||||
|
|
||||||
var msg = "Microsoft.EntityFrameworkCore.DbUpdateException";
|
var msg = "Microsoft.EntityFrameworkCore.DbUpdateException";
|
||||||
if (ex.InnerException is null)
|
if (ex.InnerException is null)
|
||||||
throw new Exception($"{msg}{format(ex)}");
|
throw new Exception($"{msg}{format(ex)}");
|
||||||
throw new Exception(
|
throw new Exception(
|
||||||
$"{msg}{format(ex)}",
|
$"{msg}{format(ex)}",
|
||||||
new Exception($"Inner Exception{format(ex.InnerException)}"));
|
new Exception($"Inner Exception{format(ex.InnerException)}"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region remove/restore books
|
#region remove/restore books
|
||||||
public static Task<int> RemoveBooksAsync(List<string> idsToRemove) => Task.Run(() => removeBooks(idsToRemove));
|
public static Task<int> RemoveBooksAsync(List<string> idsToRemove) => Task.Run(() => removeBooks(idsToRemove));
|
||||||
public static int RemoveBook(string idToRemove) => removeBooks(new() { idToRemove });
|
public static int RemoveBook(string idToRemove) => removeBooks(new() { idToRemove });
|
||||||
private static int removeBooks(List<string> idsToRemove)
|
private static int removeBooks(List<string> idsToRemove)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (idsToRemove is null || !idsToRemove.Any())
|
if (idsToRemove is null || !idsToRemove.Any())
|
||||||
return 0;
|
return 0;
|
||||||
@ -370,8 +370,8 @@ namespace ApplicationServices
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static int RestoreBooks(this List<LibraryBook> libraryBooks)
|
public static int RestoreBooks(this List<LibraryBook> libraryBooks)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (libraryBooks is null || !libraryBooks.Any())
|
if (libraryBooks is null || !libraryBooks.Any())
|
||||||
return 0;
|
return 0;
|
||||||
@ -402,59 +402,58 @@ namespace ApplicationServices
|
|||||||
// call this whenever books are added or removed from library
|
// call this whenever books are added or removed from library
|
||||||
private static void finalizeLibrarySizeChange() => LibrarySizeChanged?.Invoke(null, null);
|
private static void finalizeLibrarySizeChange() => LibrarySizeChanged?.Invoke(null, null);
|
||||||
|
|
||||||
/// <summary>Occurs when the size of the library changes. ie: books are added or removed</summary>
|
/// <summary>Occurs when the size of the library changes. ie: books are added or removed</summary>
|
||||||
public static event EventHandler LibrarySizeChanged;
|
public static event EventHandler LibrarySizeChanged;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Occurs when the size of the library does not change but book(s) details do. Especially when <see cref="UserDefinedItem.Tags"/>, <see cref="UserDefinedItem.BookStatus"/>, or <see cref="UserDefinedItem.PdfStatus"/> changed values are successfully persisted.
|
/// Occurs when the size of the library does not change but book(s) details do. Especially when <see cref="UserDefinedItem.Tags"/>, <see cref="UserDefinedItem.BookStatus"/>, or <see cref="UserDefinedItem.PdfStatus"/> changed values are successfully persisted.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static event EventHandler<IEnumerable<Book>> BookUserDefinedItemCommitted;
|
public static event EventHandler<IEnumerable<Book>> BookUserDefinedItemCommitted;
|
||||||
|
|
||||||
#region Update book details
|
#region Update book details
|
||||||
public static int UpdateUserDefinedItem(
|
public static int UpdateUserDefinedItem(
|
||||||
this Book book,
|
this Book book,
|
||||||
string tags = null,
|
string tags = null,
|
||||||
LiberatedStatus? bookStatus = null,
|
LiberatedStatus? bookStatus = null,
|
||||||
LiberatedStatus? pdfStatus = null)
|
LiberatedStatus? pdfStatus = null)
|
||||||
=> new[] { book }.UpdateUserDefinedItem(tags, bookStatus, pdfStatus);
|
=> new[] { book }.UpdateUserDefinedItem(tags, bookStatus, pdfStatus);
|
||||||
|
|
||||||
public static int UpdateUserDefinedItem(
|
public static int UpdateUserDefinedItem(
|
||||||
this IEnumerable<Book> books,
|
this IEnumerable<Book> books,
|
||||||
string tags = null,
|
string tags = null,
|
||||||
LiberatedStatus? bookStatus = null,
|
LiberatedStatus? bookStatus = null,
|
||||||
LiberatedStatus? pdfStatus = null)
|
LiberatedStatus? pdfStatus = null)
|
||||||
=> updateUserDefinedItem(
|
=> updateUserDefinedItem(
|
||||||
books,
|
books,
|
||||||
udi => {
|
udi => {
|
||||||
// blank tags are expected. null tags are not
|
// blank tags are expected. null tags are not
|
||||||
if (tags is not null && udi.Tags != tags)
|
if (tags is not null)
|
||||||
udi.Tags = tags;
|
udi.Tags = tags;
|
||||||
|
|
||||||
if (bookStatus is not null && udi.BookStatus != bookStatus.Value)
|
if (bookStatus.HasValue)
|
||||||
udi.BookStatus = bookStatus.Value;
|
udi.BookStatus = bookStatus.Value;
|
||||||
|
|
||||||
// even though PdfStatus is nullable, there's no case where we'd actually overwrite with null
|
// method handles null logic
|
||||||
if (pdfStatus is not null && udi.PdfStatus != pdfStatus.Value)
|
udi.SetPdfStatus(pdfStatus);
|
||||||
udi.PdfStatus = pdfStatus.Value;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
public static int UpdateBookStatus(this Book book, LiberatedStatus bookStatus)
|
public static int UpdateBookStatus(this Book book, LiberatedStatus bookStatus)
|
||||||
=> book.UpdateUserDefinedItem(udi => udi.BookStatus = bookStatus);
|
=> book.UpdateUserDefinedItem(udi => udi.BookStatus = bookStatus);
|
||||||
public static int UpdateBookStatus(this IEnumerable<Book> books, LiberatedStatus bookStatus)
|
public static int UpdateBookStatus(this IEnumerable<Book> books, LiberatedStatus bookStatus)
|
||||||
=> books.UpdateUserDefinedItem(udi => udi.BookStatus = bookStatus);
|
=> books.UpdateUserDefinedItem(udi => udi.BookStatus = bookStatus);
|
||||||
public static int UpdateBookStatus(this LibraryBook libraryBook, LiberatedStatus bookStatus)
|
public static int UpdateBookStatus(this LibraryBook libraryBook, LiberatedStatus bookStatus)
|
||||||
=> libraryBook.UpdateUserDefinedItem(udi => udi.BookStatus = bookStatus);
|
=> libraryBook.UpdateUserDefinedItem(udi => udi.BookStatus = bookStatus);
|
||||||
public static int UpdateBookStatus(this IEnumerable<LibraryBook> libraryBooks, LiberatedStatus bookStatus)
|
public static int UpdateBookStatus(this IEnumerable<LibraryBook> libraryBooks, LiberatedStatus bookStatus)
|
||||||
=> libraryBooks.UpdateUserDefinedItem(udi => udi.BookStatus = bookStatus);
|
=> libraryBooks.UpdateUserDefinedItem(udi => udi.BookStatus = bookStatus);
|
||||||
|
|
||||||
public static int UpdatePdfStatus(this Book book, LiberatedStatus pdfStatus)
|
public static int UpdatePdfStatus(this Book book, LiberatedStatus pdfStatus)
|
||||||
=> book.UpdateUserDefinedItem(udi => udi.PdfStatus = pdfStatus);
|
=> book.UpdateUserDefinedItem(udi => udi.SetPdfStatus(pdfStatus));
|
||||||
public static int UpdatePdfStatus(this IEnumerable<Book> books, LiberatedStatus pdfStatus)
|
public static int UpdatePdfStatus(this IEnumerable<Book> books, LiberatedStatus pdfStatus)
|
||||||
=> books.UpdateUserDefinedItem(udi => udi.PdfStatus = pdfStatus);
|
=> books.UpdateUserDefinedItem(udi => udi.SetPdfStatus(pdfStatus));
|
||||||
public static int UpdatePdfStatus(this LibraryBook libraryBook, LiberatedStatus pdfStatus)
|
public static int UpdatePdfStatus(this LibraryBook libraryBook, LiberatedStatus pdfStatus)
|
||||||
=> libraryBook.UpdateUserDefinedItem(udi => udi.PdfStatus = pdfStatus);
|
=> libraryBook.UpdateUserDefinedItem(udi => udi.SetPdfStatus(pdfStatus));
|
||||||
public static int UpdatePdfStatus(this IEnumerable<LibraryBook> libraryBooks, LiberatedStatus pdfStatus)
|
public static int UpdatePdfStatus(this IEnumerable<LibraryBook> libraryBooks, LiberatedStatus pdfStatus)
|
||||||
=> libraryBooks.UpdateUserDefinedItem(udi => udi.PdfStatus = pdfStatus);
|
=> libraryBooks.UpdateUserDefinedItem(udi => udi.SetPdfStatus(pdfStatus));
|
||||||
|
|
||||||
public static int UpdateTags(this Book book, string tags)
|
public static int UpdateTags(this Book book, string tags)
|
||||||
=> book.UpdateUserDefinedItem(udi => udi.Tags = tags);
|
=> book.UpdateUserDefinedItem(udi => udi.Tags = tags);
|
||||||
@ -466,9 +465,9 @@ namespace ApplicationServices
|
|||||||
=> libraryBooks.UpdateUserDefinedItem(udi => udi.Tags = tags);
|
=> libraryBooks.UpdateUserDefinedItem(udi => udi.Tags = tags);
|
||||||
|
|
||||||
public static int UpdateUserDefinedItem(this LibraryBook libraryBook, Action<UserDefinedItem> action)
|
public static int UpdateUserDefinedItem(this LibraryBook libraryBook, Action<UserDefinedItem> action)
|
||||||
=> libraryBook.Book.updateUserDefinedItem(action);
|
=> libraryBook.Book.updateUserDefinedItem(action);
|
||||||
public static int UpdateUserDefinedItem(this IEnumerable<LibraryBook> libraryBooks, Action<UserDefinedItem> action)
|
public static int UpdateUserDefinedItem(this IEnumerable<LibraryBook> libraryBooks, Action<UserDefinedItem> action)
|
||||||
=> libraryBooks.Select(lb => lb.Book).updateUserDefinedItem(action);
|
=> libraryBooks.Select(lb => lb.Book).updateUserDefinedItem(action);
|
||||||
|
|
||||||
public static int UpdateUserDefinedItem(this Book book, Action<UserDefinedItem> action) => book.updateUserDefinedItem(action);
|
public static int UpdateUserDefinedItem(this Book book, Action<UserDefinedItem> action) => book.updateUserDefinedItem(action);
|
||||||
public static int UpdateUserDefinedItem(this IEnumerable<Book> books, Action<UserDefinedItem> action) => books.updateUserDefinedItem(action);
|
public static int UpdateUserDefinedItem(this IEnumerable<Book> books, Action<UserDefinedItem> action) => books.updateUserDefinedItem(action);
|
||||||
@ -481,7 +480,7 @@ namespace ApplicationServices
|
|||||||
if (books is null || !books.Any())
|
if (books is null || !books.Any())
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
foreach (var book in books)
|
foreach (var book in books)
|
||||||
action?.Invoke(book.UserDefinedItem);
|
action?.Invoke(book.UserDefinedItem);
|
||||||
|
|
||||||
using var context = DbContexts.GetContext();
|
using var context = DbContexts.GetContext();
|
||||||
@ -506,49 +505,49 @@ namespace ApplicationServices
|
|||||||
|
|
||||||
// must be here instead of in db layer due to AaxcExists
|
// must be here instead of in db layer due to AaxcExists
|
||||||
public static LiberatedStatus Liberated_Status(Book book)
|
public static LiberatedStatus Liberated_Status(Book book)
|
||||||
=> book.Audio_Exists() ? book.UserDefinedItem.BookStatus
|
=> book.Audio_Exists() ? book.UserDefinedItem.BookStatus
|
||||||
: AudibleFileStorage.AaxcExists(book.AudibleProductId) ? LiberatedStatus.PartialDownload
|
: AudibleFileStorage.AaxcExists(book.AudibleProductId) ? LiberatedStatus.PartialDownload
|
||||||
: LiberatedStatus.NotLiberated;
|
: LiberatedStatus.NotLiberated;
|
||||||
|
|
||||||
// exists here for feature predictability. It makes sense for this to be where Liberated_Status is
|
// exists here for feature predictability. It makes sense for this to be where Liberated_Status is
|
||||||
public static LiberatedStatus? Pdf_Status(Book book) => book.UserDefinedItem.PdfStatus;
|
public static LiberatedStatus? Pdf_Status(Book book) => book.UserDefinedItem.PdfStatus;
|
||||||
|
|
||||||
// below are queries, not commands. maybe I should make a LibraryQueries. except there's already one of those...
|
// below are queries, not commands. maybe I should make a LibraryQueries. except there's already one of those...
|
||||||
|
|
||||||
public record LibraryStats(int booksFullyBackedUp, int booksDownloadedOnly, int booksNoProgress, int booksError, int pdfsDownloaded, int pdfsNotDownloaded)
|
public record LibraryStats(int booksFullyBackedUp, int booksDownloadedOnly, int booksNoProgress, int booksError, int pdfsDownloaded, int pdfsNotDownloaded)
|
||||||
{
|
{
|
||||||
public int PendingBooks => booksNoProgress + booksDownloadedOnly;
|
public int PendingBooks => booksNoProgress + booksDownloadedOnly;
|
||||||
public bool HasPendingBooks => PendingBooks > 0;
|
public bool HasPendingBooks => PendingBooks > 0;
|
||||||
|
|
||||||
public bool HasBookResults => 0 < (booksFullyBackedUp + booksDownloadedOnly + booksNoProgress + booksError);
|
public bool HasBookResults => 0 < (booksFullyBackedUp + booksDownloadedOnly + booksNoProgress + booksError);
|
||||||
public bool HasPdfResults => 0 < (pdfsNotDownloaded + pdfsDownloaded);
|
public bool HasPdfResults => 0 < (pdfsNotDownloaded + pdfsDownloaded);
|
||||||
}
|
}
|
||||||
public static LibraryStats GetCounts()
|
public static LibraryStats GetCounts()
|
||||||
{
|
{
|
||||||
var libraryBooks = DbContexts.GetLibrary_Flat_NoTracking();
|
var libraryBooks = DbContexts.GetLibrary_Flat_NoTracking();
|
||||||
|
|
||||||
var results = libraryBooks
|
var results = libraryBooks
|
||||||
.AsParallel()
|
.AsParallel()
|
||||||
.Select(lb => Liberated_Status(lb.Book))
|
.Select(lb => Liberated_Status(lb.Book))
|
||||||
.ToList();
|
.ToList();
|
||||||
var booksFullyBackedUp = results.Count(r => r == LiberatedStatus.Liberated);
|
var booksFullyBackedUp = results.Count(r => r == LiberatedStatus.Liberated);
|
||||||
var booksDownloadedOnly = results.Count(r => r == LiberatedStatus.PartialDownload);
|
var booksDownloadedOnly = results.Count(r => r == LiberatedStatus.PartialDownload);
|
||||||
var booksNoProgress = results.Count(r => r == LiberatedStatus.NotLiberated);
|
var booksNoProgress = results.Count(r => r == LiberatedStatus.NotLiberated);
|
||||||
var booksError = results.Count(r => r == LiberatedStatus.Error);
|
var booksError = results.Count(r => r == LiberatedStatus.Error);
|
||||||
|
|
||||||
Log.Logger.Information("Book counts. {@DebugInfo}", new { total = results.Count, booksFullyBackedUp, booksDownloadedOnly, booksNoProgress, booksError });
|
Log.Logger.Information("Book counts. {@DebugInfo}", new { total = results.Count, booksFullyBackedUp, booksDownloadedOnly, booksNoProgress, booksError });
|
||||||
|
|
||||||
var boolResults = libraryBooks
|
var boolResults = libraryBooks
|
||||||
.AsParallel()
|
.AsParallel()
|
||||||
.Where(lb => lb.Book.HasPdf())
|
.Where(lb => lb.Book.HasPdf())
|
||||||
.Select(lb => Pdf_Status(lb.Book))
|
.Select(lb => Pdf_Status(lb.Book))
|
||||||
.ToList();
|
.ToList();
|
||||||
var pdfsDownloaded = boolResults.Count(r => r == LiberatedStatus.Liberated);
|
var pdfsDownloaded = boolResults.Count(r => r == LiberatedStatus.Liberated);
|
||||||
var pdfsNotDownloaded = boolResults.Count(r => r == LiberatedStatus.NotLiberated);
|
var pdfsNotDownloaded = boolResults.Count(r => r == LiberatedStatus.NotLiberated);
|
||||||
|
|
||||||
Log.Logger.Information("PDF counts. {@DebugInfo}", new { total = boolResults.Count, pdfsDownloaded, pdfsNotDownloaded });
|
Log.Logger.Information("PDF counts. {@DebugInfo}", new { total = boolResults.Count, pdfsDownloaded, pdfsNotDownloaded });
|
||||||
|
|
||||||
return new(booksFullyBackedUp, booksDownloadedOnly, booksNoProgress, booksError, pdfsDownloaded, pdfsNotDownloaded);
|
return new(booksFullyBackedUp, booksDownloadedOnly, booksNoProgress, booksError, pdfsDownloaded, pdfsNotDownloaded);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -146,10 +146,19 @@ namespace DataLayer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
public void SetPdfStatus(LiberatedStatus? pdfStatus)
|
||||||
|
{
|
||||||
|
// don't change whether pdf is actually available. if null, leave as null. if not null, only assign non-null
|
||||||
|
|
||||||
|
// null => non-null : only when adding a supplement
|
||||||
|
|
||||||
|
if (pdfStatus.HasValue && PdfStatus.HasValue)
|
||||||
|
PdfStatus = pdfStatus;
|
||||||
|
}
|
||||||
public LiberatedStatus? PdfStatus
|
public LiberatedStatus? PdfStatus
|
||||||
{
|
{
|
||||||
get => _pdfStatus;
|
get => _pdfStatus;
|
||||||
set
|
internal set
|
||||||
{
|
{
|
||||||
if (_pdfStatus != value)
|
if (_pdfStatus != value)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -34,7 +34,13 @@ namespace LibationAvalonia.Dialogs
|
|||||||
new liberatedComboBoxItem { Status = LiberatedStatus.NotLiberated, Text = "Not Downloaded" },
|
new liberatedComboBoxItem { Status = LiberatedStatus.NotLiberated, Text = "Not Downloaded" },
|
||||||
};
|
};
|
||||||
|
|
||||||
public LiberatedStatusBatchManualDialog()
|
public LiberatedStatusBatchManualDialog(bool isPdf) : this()
|
||||||
|
{
|
||||||
|
if (isPdf)
|
||||||
|
this.Title = this.Title.Replace("book", "PDF");
|
||||||
|
}
|
||||||
|
|
||||||
|
public LiberatedStatusBatchManualDialog()
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
SelectedItem = BookStatuses[0] as liberatedComboBoxItem;
|
SelectedItem = BookStatuses[0] as liberatedComboBoxItem;
|
||||||
|
|||||||
@ -108,7 +108,7 @@ namespace LibationAvalonia.ViewModels
|
|||||||
this.RaisePropertyChanged(nameof(Liberate));
|
this.RaisePropertyChanged(nameof(Liberate));
|
||||||
break;
|
break;
|
||||||
case nameof(udi.PdfStatus):
|
case nameof(udi.PdfStatus):
|
||||||
Book.UserDefinedItem.PdfStatus = udi.PdfStatus;
|
Book.UserDefinedItem.SetPdfStatus(udi.PdfStatus);
|
||||||
_pdfStatus = udi.PdfStatus;
|
_pdfStatus = udi.PdfStatus;
|
||||||
this.RaisePropertyChanged(nameof(Liberate));
|
this.RaisePropertyChanged(nameof(Liberate));
|
||||||
break;
|
break;
|
||||||
|
|||||||
@ -62,7 +62,7 @@ namespace LibationAvalonia.Views
|
|||||||
visibleLibraryBooks.UpdateTags(dialog.NewTags);
|
visibleLibraryBooks.UpdateTags(dialog.NewTags);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async void setDownloadedManualToolStripMenuItem_Click(object sender, Avalonia.Interactivity.RoutedEventArgs args)
|
public async void setBookDownloadedManualToolStripMenuItem_Click(object sender, Avalonia.Interactivity.RoutedEventArgs args)
|
||||||
{
|
{
|
||||||
var dialog = new Dialogs.LiberatedStatusBatchManualDialog();
|
var dialog = new Dialogs.LiberatedStatusBatchManualDialog();
|
||||||
var result = await dialog.ShowDialog<DialogResult>(this);
|
var result = await dialog.ShowDialog<DialogResult>(this);
|
||||||
@ -75,7 +75,7 @@ namespace LibationAvalonia.Views
|
|||||||
this,
|
this,
|
||||||
visibleLibraryBooks,
|
visibleLibraryBooks,
|
||||||
// do not use `$` string interpolation. See impl.
|
// do not use `$` string interpolation. See impl.
|
||||||
"Are you sure you want to replace downloaded status in {0}?",
|
"Are you sure you want to replace book downloaded status in {0}?",
|
||||||
"Replace downloaded status?");
|
"Replace downloaded status?");
|
||||||
|
|
||||||
if (confirmationResult != DialogResult.Yes)
|
if (confirmationResult != DialogResult.Yes)
|
||||||
@ -84,7 +84,29 @@ namespace LibationAvalonia.Views
|
|||||||
visibleLibraryBooks.UpdateBookStatus(dialog.BookLiberatedStatus);
|
visibleLibraryBooks.UpdateBookStatus(dialog.BookLiberatedStatus);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async void setDownloadedAutoToolStripMenuItem_Click(object sender, Avalonia.Interactivity.RoutedEventArgs args)
|
public async void setPdfDownloadedManualToolStripMenuItem_Click(object sender, Avalonia.Interactivity.RoutedEventArgs args)
|
||||||
|
{
|
||||||
|
var dialog = new Dialogs.LiberatedStatusBatchManualDialog(isPdf: true);
|
||||||
|
var result = await dialog.ShowDialog<DialogResult>(this);
|
||||||
|
if (result != DialogResult.OK)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var visibleLibraryBooks = _viewModel.ProductsDisplay.GetVisibleBookEntries();
|
||||||
|
|
||||||
|
var confirmationResult = await MessageBox.ShowConfirmationDialog(
|
||||||
|
this,
|
||||||
|
visibleLibraryBooks,
|
||||||
|
// do not use `$` string interpolation. See impl.
|
||||||
|
"Are you sure you want to replace PDF downloaded status in {0}?",
|
||||||
|
"Replace downloaded status?");
|
||||||
|
|
||||||
|
if (confirmationResult != DialogResult.Yes)
|
||||||
|
return;
|
||||||
|
|
||||||
|
visibleLibraryBooks.UpdatePdfStatus(dialog.BookLiberatedStatus);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async void setDownloadedAutoToolStripMenuItem_Click(object sender, Avalonia.Interactivity.RoutedEventArgs args)
|
||||||
{
|
{
|
||||||
var dialog = new Dialogs.LiberatedStatusBatchAutoDialog();
|
var dialog = new Dialogs.LiberatedStatusBatchAutoDialog();
|
||||||
var result = await dialog.ShowDialog<DialogResult>(this);
|
var result = await dialog.ShowDialog<DialogResult>(this);
|
||||||
|
|||||||
@ -110,7 +110,8 @@
|
|||||||
</MenuItem.Styles>
|
</MenuItem.Styles>
|
||||||
<MenuItem Click="liberateVisible" Header="{Binding LiberateVisibleToolStripText_2}" IsEnabled="{Binding AnyVisibleNotLiberated}" />
|
<MenuItem Click="liberateVisible" Header="{Binding LiberateVisibleToolStripText_2}" IsEnabled="{Binding AnyVisibleNotLiberated}" />
|
||||||
<MenuItem Click="replaceTagsToolStripMenuItem_Click" Header="Replace _Tags..." />
|
<MenuItem Click="replaceTagsToolStripMenuItem_Click" Header="Replace _Tags..." />
|
||||||
<MenuItem Click="setDownloadedManualToolStripMenuItem_Click" Header="Set '_Downloaded' status manually..." />
|
<MenuItem Click="setBookDownloadedManualToolStripMenuItem_Click" Header="Set book '_Downloaded' status manually..." />
|
||||||
|
<MenuItem Click="setPdfDownloadedManualToolStripMenuItem_Click" Header="Set _PDF 'Downloaded' status manually..." />
|
||||||
<MenuItem Click="setDownloadedAutoToolStripMenuItem_Click" Header="Set '_Downloaded' status automatically..." />
|
<MenuItem Click="setDownloadedAutoToolStripMenuItem_Click" Header="Set '_Downloaded' status automatically..." />
|
||||||
<MenuItem Click="removeToolStripMenuItem_Click" Header="_Remove from library..." />
|
<MenuItem Click="removeToolStripMenuItem_Click" Header="_Remove from library..." />
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
|
|||||||
@ -1,10 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
using DataLayer;
|
using DataLayer;
|
||||||
using Dinah.Core;
|
|
||||||
using LibationFileManager;
|
|
||||||
|
|
||||||
namespace LibationWinForms.Dialogs
|
namespace LibationWinForms.Dialogs
|
||||||
{
|
{
|
||||||
@ -19,6 +15,12 @@ namespace LibationWinForms.Dialogs
|
|||||||
public override string ToString() => Text;
|
public override string ToString() => Text;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public LiberatedStatusBatchManualDialog(bool isPdf) : this()
|
||||||
|
{
|
||||||
|
if (isPdf)
|
||||||
|
this.Text = this.Text.Replace("book", "PDF");
|
||||||
|
}
|
||||||
|
|
||||||
public LiberatedStatusBatchManualDialog()
|
public LiberatedStatusBatchManualDialog()
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
|||||||
72
Source/LibationWinForms/Form1.Designer.cs
generated
72
Source/LibationWinForms/Form1.Designer.cs
generated
@ -57,7 +57,9 @@
|
|||||||
this.visibleBooksToolStripMenuItem = new LibationWinForms.FormattableToolStripMenuItem();
|
this.visibleBooksToolStripMenuItem = new LibationWinForms.FormattableToolStripMenuItem();
|
||||||
this.liberateVisibleToolStripMenuItem_VisibleBooksMenu = new LibationWinForms.FormattableToolStripMenuItem();
|
this.liberateVisibleToolStripMenuItem_VisibleBooksMenu = new LibationWinForms.FormattableToolStripMenuItem();
|
||||||
this.replaceTagsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
this.replaceTagsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||||
this.setDownloadedManualToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
this.setBookDownloadedManualToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||||
|
this.setPdfDownloadedManualToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||||
|
this.setDownloadedAutoToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||||
this.removeToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
this.removeToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||||
this.settingsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
this.settingsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||||
this.accountsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
this.accountsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||||
@ -77,7 +79,6 @@
|
|||||||
this.doneRemovingBtn = new System.Windows.Forms.Button();
|
this.doneRemovingBtn = new System.Windows.Forms.Button();
|
||||||
this.removeBooksBtn = new System.Windows.Forms.Button();
|
this.removeBooksBtn = new System.Windows.Forms.Button();
|
||||||
this.processBookQueue1 = new LibationWinForms.ProcessQueue.ProcessQueueControl();
|
this.processBookQueue1 = new LibationWinForms.ProcessQueue.ProcessQueueControl();
|
||||||
this.setDownloadedAutoToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
|
||||||
this.menuStrip1.SuspendLayout();
|
this.menuStrip1.SuspendLayout();
|
||||||
this.statusStrip1.SuspendLayout();
|
this.statusStrip1.SuspendLayout();
|
||||||
((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).BeginInit();
|
((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).BeginInit();
|
||||||
@ -101,7 +102,7 @@
|
|||||||
// filterBtn
|
// filterBtn
|
||||||
//
|
//
|
||||||
this.filterBtn.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
|
this.filterBtn.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
|
||||||
this.filterBtn.Location = new System.Drawing.Point(892, 3);
|
this.filterBtn.Location = new System.Drawing.Point(884, 3);
|
||||||
this.filterBtn.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
this.filterBtn.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||||
this.filterBtn.Name = "filterBtn";
|
this.filterBtn.Name = "filterBtn";
|
||||||
this.filterBtn.Size = new System.Drawing.Size(88, 27);
|
this.filterBtn.Size = new System.Drawing.Size(88, 27);
|
||||||
@ -118,7 +119,7 @@
|
|||||||
this.filterSearchTb.Location = new System.Drawing.Point(195, 5);
|
this.filterSearchTb.Location = new System.Drawing.Point(195, 5);
|
||||||
this.filterSearchTb.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
this.filterSearchTb.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||||
this.filterSearchTb.Name = "filterSearchTb";
|
this.filterSearchTb.Name = "filterSearchTb";
|
||||||
this.filterSearchTb.Size = new System.Drawing.Size(689, 25);
|
this.filterSearchTb.Size = new System.Drawing.Size(681, 25);
|
||||||
this.filterSearchTb.TabIndex = 1;
|
this.filterSearchTb.TabIndex = 1;
|
||||||
this.filterSearchTb.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.filterSearchTb_KeyPress);
|
this.filterSearchTb.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.filterSearchTb_KeyPress);
|
||||||
//
|
//
|
||||||
@ -136,7 +137,7 @@
|
|||||||
this.menuStrip1.Location = new System.Drawing.Point(0, 0);
|
this.menuStrip1.Location = new System.Drawing.Point(0, 0);
|
||||||
this.menuStrip1.Name = "menuStrip1";
|
this.menuStrip1.Name = "menuStrip1";
|
||||||
this.menuStrip1.Padding = new System.Windows.Forms.Padding(7, 2, 0, 2);
|
this.menuStrip1.Padding = new System.Windows.Forms.Padding(7, 2, 0, 2);
|
||||||
this.menuStrip1.Size = new System.Drawing.Size(1037, 24);
|
this.menuStrip1.Size = new System.Drawing.Size(1025, 24);
|
||||||
this.menuStrip1.TabIndex = 0;
|
this.menuStrip1.TabIndex = 0;
|
||||||
this.menuStrip1.Text = "menuStrip1";
|
this.menuStrip1.Text = "menuStrip1";
|
||||||
//
|
//
|
||||||
@ -316,7 +317,8 @@
|
|||||||
this.visibleBooksToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
this.visibleBooksToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||||
this.liberateVisibleToolStripMenuItem_VisibleBooksMenu,
|
this.liberateVisibleToolStripMenuItem_VisibleBooksMenu,
|
||||||
this.replaceTagsToolStripMenuItem,
|
this.replaceTagsToolStripMenuItem,
|
||||||
this.setDownloadedManualToolStripMenuItem,
|
this.setBookDownloadedManualToolStripMenuItem,
|
||||||
|
this.setPdfDownloadedManualToolStripMenuItem,
|
||||||
this.setDownloadedAutoToolStripMenuItem,
|
this.setDownloadedAutoToolStripMenuItem,
|
||||||
this.removeToolStripMenuItem});
|
this.removeToolStripMenuItem});
|
||||||
this.visibleBooksToolStripMenuItem.FormatText = "&Visible Books: {0}";
|
this.visibleBooksToolStripMenuItem.FormatText = "&Visible Books: {0}";
|
||||||
@ -328,28 +330,42 @@
|
|||||||
//
|
//
|
||||||
this.liberateVisibleToolStripMenuItem_VisibleBooksMenu.FormatText = "&Liberate: {0}";
|
this.liberateVisibleToolStripMenuItem_VisibleBooksMenu.FormatText = "&Liberate: {0}";
|
||||||
this.liberateVisibleToolStripMenuItem_VisibleBooksMenu.Name = "liberateVisibleToolStripMenuItem_VisibleBooksMenu";
|
this.liberateVisibleToolStripMenuItem_VisibleBooksMenu.Name = "liberateVisibleToolStripMenuItem_VisibleBooksMenu";
|
||||||
this.liberateVisibleToolStripMenuItem_VisibleBooksMenu.Size = new System.Drawing.Size(284, 22);
|
this.liberateVisibleToolStripMenuItem_VisibleBooksMenu.Size = new System.Drawing.Size(314, 22);
|
||||||
this.liberateVisibleToolStripMenuItem_VisibleBooksMenu.Text = "&Liberate: {0}";
|
this.liberateVisibleToolStripMenuItem_VisibleBooksMenu.Text = "&Liberate: {0}";
|
||||||
this.liberateVisibleToolStripMenuItem_VisibleBooksMenu.Click += new System.EventHandler(this.liberateVisible);
|
this.liberateVisibleToolStripMenuItem_VisibleBooksMenu.Click += new System.EventHandler(this.liberateVisible);
|
||||||
//
|
//
|
||||||
// replaceTagsToolStripMenuItem
|
// replaceTagsToolStripMenuItem
|
||||||
//
|
//
|
||||||
this.replaceTagsToolStripMenuItem.Name = "replaceTagsToolStripMenuItem";
|
this.replaceTagsToolStripMenuItem.Name = "replaceTagsToolStripMenuItem";
|
||||||
this.replaceTagsToolStripMenuItem.Size = new System.Drawing.Size(284, 22);
|
this.replaceTagsToolStripMenuItem.Size = new System.Drawing.Size(314, 22);
|
||||||
this.replaceTagsToolStripMenuItem.Text = "Replace &Tags...";
|
this.replaceTagsToolStripMenuItem.Text = "Replace &Tags...";
|
||||||
this.replaceTagsToolStripMenuItem.Click += new System.EventHandler(this.replaceTagsToolStripMenuItem_Click);
|
this.replaceTagsToolStripMenuItem.Click += new System.EventHandler(this.replaceTagsToolStripMenuItem_Click);
|
||||||
//
|
//
|
||||||
// setDownloadedManualToolStripMenuItem
|
// setBookDownloadedManualToolStripMenuItem
|
||||||
//
|
//
|
||||||
this.setDownloadedManualToolStripMenuItem.Name = "setDownloadedManualToolStripMenuItem";
|
this.setBookDownloadedManualToolStripMenuItem.Name = "setBookDownloadedManualToolStripMenuItem";
|
||||||
this.setDownloadedManualToolStripMenuItem.Size = new System.Drawing.Size(284, 22);
|
this.setBookDownloadedManualToolStripMenuItem.Size = new System.Drawing.Size(314, 22);
|
||||||
this.setDownloadedManualToolStripMenuItem.Text = "Set \'&Downloaded\' status manually...";
|
this.setBookDownloadedManualToolStripMenuItem.Text = "Set book \'&Downloaded\' status manually...";
|
||||||
this.setDownloadedManualToolStripMenuItem.Click += new System.EventHandler(this.setDownloadedManualToolStripMenuItem_Click);
|
this.setBookDownloadedManualToolStripMenuItem.Click += new System.EventHandler(this.setBookDownloadedManualToolStripMenuItem_Click);
|
||||||
|
//
|
||||||
|
// setPdfDownloadedManualToolStripMenuItem
|
||||||
|
//
|
||||||
|
this.setPdfDownloadedManualToolStripMenuItem.Name = "setPdfDownloadedManualToolStripMenuItem";
|
||||||
|
this.setPdfDownloadedManualToolStripMenuItem.Size = new System.Drawing.Size(314, 22);
|
||||||
|
this.setPdfDownloadedManualToolStripMenuItem.Text = "Set &PDF \'Downloaded\' status manually...";
|
||||||
|
this.setPdfDownloadedManualToolStripMenuItem.Click += new System.EventHandler(this.setPdfDownloadedManualToolStripMenuItem_Click);
|
||||||
|
//
|
||||||
|
// setDownloadedAutoToolStripMenuItem
|
||||||
|
//
|
||||||
|
this.setDownloadedAutoToolStripMenuItem.Name = "setDownloadedAutoToolStripMenuItem";
|
||||||
|
this.setDownloadedAutoToolStripMenuItem.Size = new System.Drawing.Size(314, 22);
|
||||||
|
this.setDownloadedAutoToolStripMenuItem.Text = "Set book \'Downloaded\' status &automatically...";
|
||||||
|
this.setDownloadedAutoToolStripMenuItem.Click += new System.EventHandler(this.setDownloadedAutoToolStripMenuItem_Click);
|
||||||
//
|
//
|
||||||
// removeToolStripMenuItem
|
// removeToolStripMenuItem
|
||||||
//
|
//
|
||||||
this.removeToolStripMenuItem.Name = "removeToolStripMenuItem";
|
this.removeToolStripMenuItem.Name = "removeToolStripMenuItem";
|
||||||
this.removeToolStripMenuItem.Size = new System.Drawing.Size(284, 22);
|
this.removeToolStripMenuItem.Size = new System.Drawing.Size(314, 22);
|
||||||
this.removeToolStripMenuItem.Text = "&Remove from library...";
|
this.removeToolStripMenuItem.Text = "&Remove from library...";
|
||||||
this.removeToolStripMenuItem.Click += new System.EventHandler(this.removeToolStripMenuItem_Click);
|
this.removeToolStripMenuItem.Click += new System.EventHandler(this.removeToolStripMenuItem_Click);
|
||||||
//
|
//
|
||||||
@ -402,7 +418,7 @@
|
|||||||
this.statusStrip1.Name = "statusStrip1";
|
this.statusStrip1.Name = "statusStrip1";
|
||||||
this.statusStrip1.Padding = new System.Windows.Forms.Padding(1, 0, 16, 0);
|
this.statusStrip1.Padding = new System.Windows.Forms.Padding(1, 0, 16, 0);
|
||||||
this.statusStrip1.ShowItemToolTips = true;
|
this.statusStrip1.ShowItemToolTips = true;
|
||||||
this.statusStrip1.Size = new System.Drawing.Size(1033, 22);
|
this.statusStrip1.Size = new System.Drawing.Size(1025, 22);
|
||||||
this.statusStrip1.TabIndex = 6;
|
this.statusStrip1.TabIndex = 6;
|
||||||
this.statusStrip1.Text = "statusStrip1";
|
this.statusStrip1.Text = "statusStrip1";
|
||||||
//
|
//
|
||||||
@ -416,7 +432,7 @@
|
|||||||
// springLbl
|
// springLbl
|
||||||
//
|
//
|
||||||
this.springLbl.Name = "springLbl";
|
this.springLbl.Name = "springLbl";
|
||||||
this.springLbl.Size = new System.Drawing.Size(519, 17);
|
this.springLbl.Size = new System.Drawing.Size(511, 17);
|
||||||
this.springLbl.Spring = true;
|
this.springLbl.Spring = true;
|
||||||
//
|
//
|
||||||
// backupsCountsLbl
|
// backupsCountsLbl
|
||||||
@ -460,7 +476,7 @@
|
|||||||
//
|
//
|
||||||
this.splitContainer1.Panel2.Controls.Add(this.processBookQueue1);
|
this.splitContainer1.Panel2.Controls.Add(this.processBookQueue1);
|
||||||
this.splitContainer1.Size = new System.Drawing.Size(1463, 640);
|
this.splitContainer1.Size = new System.Drawing.Size(1463, 640);
|
||||||
this.splitContainer1.SplitterDistance = 1033;
|
this.splitContainer1.SplitterDistance = 1025;
|
||||||
this.splitContainer1.SplitterWidth = 8;
|
this.splitContainer1.SplitterWidth = 8;
|
||||||
this.splitContainer1.TabIndex = 7;
|
this.splitContainer1.TabIndex = 7;
|
||||||
//
|
//
|
||||||
@ -479,19 +495,19 @@
|
|||||||
this.panel1.Location = new System.Drawing.Point(0, 24);
|
this.panel1.Location = new System.Drawing.Point(0, 24);
|
||||||
this.panel1.Margin = new System.Windows.Forms.Padding(0);
|
this.panel1.Margin = new System.Windows.Forms.Padding(0);
|
||||||
this.panel1.Name = "panel1";
|
this.panel1.Name = "panel1";
|
||||||
this.panel1.Size = new System.Drawing.Size(1033, 594);
|
this.panel1.Size = new System.Drawing.Size(1025, 594);
|
||||||
this.panel1.TabIndex = 7;
|
this.panel1.TabIndex = 7;
|
||||||
//
|
//
|
||||||
// productsDisplay
|
// productsDisplay
|
||||||
//
|
//
|
||||||
this.productsDisplay.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
|
this.productsDisplay.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
|
||||||
| System.Windows.Forms.AnchorStyles.Left)
|
| System.Windows.Forms.AnchorStyles.Left)
|
||||||
| System.Windows.Forms.AnchorStyles.Right)));
|
| System.Windows.Forms.AnchorStyles.Right)));
|
||||||
this.productsDisplay.AutoScroll = true;
|
this.productsDisplay.AutoScroll = true;
|
||||||
this.productsDisplay.Location = new System.Drawing.Point(15, 36);
|
this.productsDisplay.Location = new System.Drawing.Point(15, 36);
|
||||||
this.productsDisplay.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
this.productsDisplay.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||||
this.productsDisplay.Name = "productsDisplay";
|
this.productsDisplay.Name = "productsDisplay";
|
||||||
this.productsDisplay.Size = new System.Drawing.Size(1007, 555);
|
this.productsDisplay.Size = new System.Drawing.Size(999, 555);
|
||||||
this.productsDisplay.TabIndex = 9;
|
this.productsDisplay.TabIndex = 9;
|
||||||
this.productsDisplay.VisibleCountChanged += new System.EventHandler<int>(this.productsDisplay_VisibleCountChanged);
|
this.productsDisplay.VisibleCountChanged += new System.EventHandler<int>(this.productsDisplay_VisibleCountChanged);
|
||||||
this.productsDisplay.RemovableCountChanged += new System.EventHandler<int>(this.productsDisplay_RemovableCountChanged);
|
this.productsDisplay.RemovableCountChanged += new System.EventHandler<int>(this.productsDisplay_RemovableCountChanged);
|
||||||
@ -501,7 +517,7 @@
|
|||||||
// toggleQueueHideBtn
|
// toggleQueueHideBtn
|
||||||
//
|
//
|
||||||
this.toggleQueueHideBtn.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
|
this.toggleQueueHideBtn.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
|
||||||
this.toggleQueueHideBtn.Location = new System.Drawing.Point(985, 3);
|
this.toggleQueueHideBtn.Location = new System.Drawing.Point(977, 3);
|
||||||
this.toggleQueueHideBtn.Margin = new System.Windows.Forms.Padding(4, 3, 15, 3);
|
this.toggleQueueHideBtn.Margin = new System.Windows.Forms.Padding(4, 3, 15, 3);
|
||||||
this.toggleQueueHideBtn.Name = "toggleQueueHideBtn";
|
this.toggleQueueHideBtn.Name = "toggleQueueHideBtn";
|
||||||
this.toggleQueueHideBtn.Size = new System.Drawing.Size(33, 27);
|
this.toggleQueueHideBtn.Size = new System.Drawing.Size(33, 27);
|
||||||
@ -542,16 +558,9 @@
|
|||||||
this.processBookQueue1.Location = new System.Drawing.Point(0, 0);
|
this.processBookQueue1.Location = new System.Drawing.Point(0, 0);
|
||||||
this.processBookQueue1.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4);
|
this.processBookQueue1.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4);
|
||||||
this.processBookQueue1.Name = "processBookQueue1";
|
this.processBookQueue1.Name = "processBookQueue1";
|
||||||
this.processBookQueue1.Size = new System.Drawing.Size(422, 640);
|
this.processBookQueue1.Size = new System.Drawing.Size(430, 640);
|
||||||
this.processBookQueue1.TabIndex = 0;
|
this.processBookQueue1.TabIndex = 0;
|
||||||
//
|
//
|
||||||
// setDownloadedAutoToolStripMenuItem
|
|
||||||
//
|
|
||||||
this.setDownloadedAutoToolStripMenuItem.Name = "setDownloadedAutoToolStripMenuItem";
|
|
||||||
this.setDownloadedAutoToolStripMenuItem.Size = new System.Drawing.Size(284, 22);
|
|
||||||
this.setDownloadedAutoToolStripMenuItem.Text = "Set \'&Downloaded\' status automatically...";
|
|
||||||
this.setDownloadedAutoToolStripMenuItem.Click += new System.EventHandler(this.setDownloadedAutoToolStripMenuItem_Click);
|
|
||||||
//
|
|
||||||
// Form1
|
// Form1
|
||||||
//
|
//
|
||||||
this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F);
|
this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F);
|
||||||
@ -618,7 +627,7 @@
|
|||||||
private LibationWinForms.FormattableToolStripMenuItem visibleBooksToolStripMenuItem;
|
private LibationWinForms.FormattableToolStripMenuItem visibleBooksToolStripMenuItem;
|
||||||
private LibationWinForms.FormattableToolStripMenuItem liberateVisibleToolStripMenuItem_VisibleBooksMenu;
|
private LibationWinForms.FormattableToolStripMenuItem liberateVisibleToolStripMenuItem_VisibleBooksMenu;
|
||||||
private System.Windows.Forms.ToolStripMenuItem replaceTagsToolStripMenuItem;
|
private System.Windows.Forms.ToolStripMenuItem replaceTagsToolStripMenuItem;
|
||||||
private System.Windows.Forms.ToolStripMenuItem setDownloadedManualToolStripMenuItem;
|
private System.Windows.Forms.ToolStripMenuItem setBookDownloadedManualToolStripMenuItem;
|
||||||
private System.Windows.Forms.ToolStripMenuItem setDownloadedAutoToolStripMenuItem;
|
private System.Windows.Forms.ToolStripMenuItem setDownloadedAutoToolStripMenuItem;
|
||||||
private System.Windows.Forms.ToolStripMenuItem removeToolStripMenuItem;
|
private System.Windows.Forms.ToolStripMenuItem removeToolStripMenuItem;
|
||||||
private LibationWinForms.FormattableToolStripMenuItem liberateVisibleToolStripMenuItem_LiberateMenu;
|
private LibationWinForms.FormattableToolStripMenuItem liberateVisibleToolStripMenuItem_LiberateMenu;
|
||||||
@ -629,5 +638,6 @@
|
|||||||
private LibationWinForms.GridView.ProductsDisplay productsDisplay;
|
private LibationWinForms.GridView.ProductsDisplay productsDisplay;
|
||||||
private System.Windows.Forms.Button removeBooksBtn;
|
private System.Windows.Forms.Button removeBooksBtn;
|
||||||
private System.Windows.Forms.Button doneRemovingBtn;
|
private System.Windows.Forms.Button doneRemovingBtn;
|
||||||
|
private System.Windows.Forms.ToolStripMenuItem setPdfDownloadedManualToolStripMenuItem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -90,7 +90,7 @@ namespace LibationWinForms
|
|||||||
visibleLibraryBooks.UpdateTags(dialog.NewTags);
|
visibleLibraryBooks.UpdateTags(dialog.NewTags);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setDownloadedManualToolStripMenuItem_Click(object sender, EventArgs e)
|
private void setBookDownloadedManualToolStripMenuItem_Click(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
var dialog = new LiberatedStatusBatchManualDialog();
|
var dialog = new LiberatedStatusBatchManualDialog();
|
||||||
var result = dialog.ShowDialog();
|
var result = dialog.ShowDialog();
|
||||||
@ -102,7 +102,7 @@ namespace LibationWinForms
|
|||||||
var confirmationResult = MessageBoxLib.ShowConfirmationDialog(
|
var confirmationResult = MessageBoxLib.ShowConfirmationDialog(
|
||||||
visibleLibraryBooks,
|
visibleLibraryBooks,
|
||||||
// do not use `$` string interpolation. See impl.
|
// do not use `$` string interpolation. See impl.
|
||||||
"Are you sure you want to replace downloaded status in {0}?",
|
"Are you sure you want to replace book downloaded status in {0}?",
|
||||||
"Replace downloaded status?");
|
"Replace downloaded status?");
|
||||||
|
|
||||||
if (confirmationResult != DialogResult.Yes)
|
if (confirmationResult != DialogResult.Yes)
|
||||||
@ -111,6 +111,27 @@ namespace LibationWinForms
|
|||||||
visibleLibraryBooks.UpdateBookStatus(dialog.BookLiberatedStatus);
|
visibleLibraryBooks.UpdateBookStatus(dialog.BookLiberatedStatus);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void setPdfDownloadedManualToolStripMenuItem_Click(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
var dialog = new LiberatedStatusBatchManualDialog(isPdf: true);
|
||||||
|
var result = dialog.ShowDialog();
|
||||||
|
if (result != DialogResult.OK)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var visibleLibraryBooks = productsDisplay.GetVisible();
|
||||||
|
|
||||||
|
var confirmationResult = MessageBoxLib.ShowConfirmationDialog(
|
||||||
|
visibleLibraryBooks,
|
||||||
|
// do not use `$` string interpolation. See impl.
|
||||||
|
"Are you sure you want to replace PDF downloaded status in {0}?",
|
||||||
|
"Replace downloaded status?");
|
||||||
|
|
||||||
|
if (confirmationResult != DialogResult.Yes)
|
||||||
|
return;
|
||||||
|
|
||||||
|
visibleLibraryBooks.UpdatePdfStatus(dialog.BookLiberatedStatus);
|
||||||
|
}
|
||||||
|
|
||||||
private async void setDownloadedAutoToolStripMenuItem_Click(object sender, EventArgs e)
|
private async void setDownloadedAutoToolStripMenuItem_Click(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
var dialog = new LiberatedStatusBatchAutoDialog();
|
var dialog = new LiberatedStatusBatchAutoDialog();
|
||||||
|
|||||||
@ -122,7 +122,7 @@ namespace LibationWinForms.GridView
|
|||||||
NotifyPropertyChanged(nameof(Liberate));
|
NotifyPropertyChanged(nameof(Liberate));
|
||||||
break;
|
break;
|
||||||
case nameof(udi.PdfStatus):
|
case nameof(udi.PdfStatus):
|
||||||
Book.UserDefinedItem.PdfStatus = udi.PdfStatus;
|
Book.UserDefinedItem.SetPdfStatus(udi.PdfStatus);
|
||||||
_pdfStatus = udi.PdfStatus;
|
_pdfStatus = udi.PdfStatus;
|
||||||
NotifyPropertyChanged(nameof(Liberate));
|
NotifyPropertyChanged(nameof(Liberate));
|
||||||
break;
|
break;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user