mirror of
https://github.com/rmcrackan/Libation.git
synced 2026-08-07 04:42:17 -04:00
Merge branch 'rmcrackan:master' into master
This commit is contained in:
22 files changed
+1260
-1167
No files matched your search
+970
-957
File diff suppressed because it is too large.
Load diff
@@ -35,6 +35,7 @@ namespace LibationWinForms.Dialogs
|
||||
this.showImportedStatsCb.Text = desc(nameof(config.ShowImportedStats));
|
||||
this.importEpisodesCb.Text = desc(nameof(config.ImportEpisodes));
|
||||
this.downloadEpisodesCb.Text = desc(nameof(config.DownloadEpisodes));
|
||||
this.autoDownloadEpisodesCb.Text = desc(nameof(config.AutoDownloadEpisodes));
|
||||
|
||||
this.booksLocationDescLbl.Text = desc(nameof(config.Books));
|
||||
this.inProgressDescLbl.Text = desc(nameof(config.InProgress));
|
||||
@@ -80,6 +81,7 @@ namespace LibationWinForms.Dialogs
|
||||
showImportedStatsCb.Checked = config.ShowImportedStats;
|
||||
importEpisodesCb.Checked = config.ImportEpisodes;
|
||||
downloadEpisodesCb.Checked = config.DownloadEpisodes;
|
||||
autoDownloadEpisodesCb.Checked = config.AutoDownloadEpisodes;
|
||||
|
||||
lameTargetRb_CheckedChanged(this, e);
|
||||
LameMatchSourceBRCbox_CheckedChanged(this, e);
|
||||
@@ -204,6 +206,7 @@ namespace LibationWinForms.Dialogs
|
||||
config.ShowImportedStats = showImportedStatsCb.Checked;
|
||||
config.ImportEpisodes = importEpisodesCb.Checked;
|
||||
config.DownloadEpisodes = downloadEpisodesCb.Checked;
|
||||
config.AutoDownloadEpisodes = autoDownloadEpisodesCb.Checked;
|
||||
|
||||
config.InProgress = inProgressSelectControl.SelectedDirectory;
|
||||
|
||||
|
||||
@@ -6,6 +6,8 @@ namespace LibationWinForms
|
||||
{
|
||||
public partial class Form1
|
||||
{
|
||||
private System.ComponentModel.BackgroundWorker updateCountsBw = new();
|
||||
|
||||
protected void Configure_BackupCounts()
|
||||
{
|
||||
// init formattable
|
||||
@@ -16,22 +18,23 @@ namespace LibationWinForms
|
||||
Load += setBackupCounts;
|
||||
LibraryCommands.LibrarySizeChanged += setBackupCounts;
|
||||
LibraryCommands.BookUserDefinedItemCommitted += setBackupCounts;
|
||||
}
|
||||
|
||||
private System.ComponentModel.BackgroundWorker updateCountsBw;
|
||||
updateCountsBw.DoWork += UpdateCountsBw_DoWork;
|
||||
updateCountsBw.RunWorkerCompleted += exportMenuEnable;
|
||||
updateCountsBw.RunWorkerCompleted += updateBottomBookNumbers;
|
||||
updateCountsBw.RunWorkerCompleted += update_BeginBookBackups_menuItem;
|
||||
updateCountsBw.RunWorkerCompleted += updateBottomPdfNumbers;
|
||||
updateCountsBw.RunWorkerCompleted += udpate_BeginPdfOnlyBackups_menuItem;
|
||||
}
|
||||
|
||||
private bool runBackupCountsAgain;
|
||||
|
||||
private void setBackupCounts(object _, object __)
|
||||
{
|
||||
runBackupCountsAgain = true;
|
||||
|
||||
if (updateCountsBw is not null)
|
||||
return;
|
||||
|
||||
updateCountsBw = new System.ComponentModel.BackgroundWorker();
|
||||
updateCountsBw.DoWork += UpdateCountsBw_DoWork;
|
||||
updateCountsBw.RunWorkerCompleted += UpdateCountsBw_RunWorkerCompleted;
|
||||
updateCountsBw.RunWorkerAsync();
|
||||
if (!updateCountsBw.IsBusy)
|
||||
updateCountsBw.RunWorkerAsync();
|
||||
}
|
||||
|
||||
private void UpdateCountsBw_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
|
||||
@@ -39,87 +42,78 @@ namespace LibationWinForms
|
||||
while (runBackupCountsAgain)
|
||||
{
|
||||
runBackupCountsAgain = false;
|
||||
|
||||
var libraryStats = LibraryCommands.GetCounts();
|
||||
e.Result = libraryStats;
|
||||
e.Result = LibraryCommands.GetCounts();
|
||||
}
|
||||
updateCountsBw = null;
|
||||
}
|
||||
|
||||
private void UpdateCountsBw_RunWorkerCompleted(object sender, System.ComponentModel.RunWorkerCompletedEventArgs e)
|
||||
private void exportMenuEnable(object _, System.ComponentModel.RunWorkerCompletedEventArgs e)
|
||||
{
|
||||
var libraryStats = e.Result as LibraryCommands.LibraryStats;
|
||||
|
||||
setBookBackupCounts(libraryStats);
|
||||
setPdfBackupCounts(libraryStats);
|
||||
exportLibraryToolStripMenuItem.Enabled = libraryStats.HasBookResults;
|
||||
}
|
||||
|
||||
// this cannot be cleanly be FormattableToolStripMenuItem because of the optional "Errors" text
|
||||
private const string backupsCountsLbl_Format = "BACKUPS: No progress: {0} In process: {1} Fully backed up: {2}";
|
||||
|
||||
private void setBookBackupCounts(LibraryCommands.LibraryStats libraryStats)
|
||||
private void updateBottomBookNumbers(object _, System.ComponentModel.RunWorkerCompletedEventArgs e)
|
||||
{
|
||||
var pending = libraryStats.booksNoProgress + libraryStats.booksDownloadedOnly;
|
||||
var hasResults = 0 < (libraryStats.booksFullyBackedUp + libraryStats.booksDownloadedOnly + libraryStats.booksNoProgress + libraryStats.booksError);
|
||||
var libraryStats = e.Result as LibraryCommands.LibraryStats;
|
||||
|
||||
// enable/disable export
|
||||
{
|
||||
exportLibraryToolStripMenuItem.Enabled = hasResults;
|
||||
}
|
||||
|
||||
// update bottom numbers
|
||||
{
|
||||
var formatString
|
||||
= !hasResults ? "No books. Begin by importing your library"
|
||||
: libraryStats.booksError > 0 ? backupsCountsLbl_Format + " Errors: {3}"
|
||||
: pending > 0 ? backupsCountsLbl_Format
|
||||
: $"All {"book".PluralizeWithCount(libraryStats.booksFullyBackedUp)} backed up";
|
||||
var statusStripText = string.Format(formatString,
|
||||
libraryStats.booksNoProgress,
|
||||
libraryStats.booksDownloadedOnly,
|
||||
libraryStats.booksFullyBackedUp,
|
||||
libraryStats.booksError);
|
||||
statusStrip1.UIThreadAsync(() => backupsCountsLbl.Text = statusStripText);
|
||||
}
|
||||
|
||||
// update 'begin book backups' menu item
|
||||
{
|
||||
var menuItemText
|
||||
= pending > 0
|
||||
? $"{pending} remaining"
|
||||
: "All books have been liberated";
|
||||
menuStrip1.UIThreadAsync(() =>
|
||||
{
|
||||
beginBookBackupsToolStripMenuItem.Format(menuItemText);
|
||||
beginBookBackupsToolStripMenuItem.Enabled = pending > 0;
|
||||
});
|
||||
}
|
||||
var formatString
|
||||
= !libraryStats.HasBookResults ? "No books. Begin by importing your library"
|
||||
: libraryStats.booksError > 0 ? backupsCountsLbl_Format + " Errors: {3}"
|
||||
: libraryStats.HasPendingBooks ? backupsCountsLbl_Format
|
||||
: $"All {"book".PluralizeWithCount(libraryStats.booksFullyBackedUp)} backed up";
|
||||
var statusStripText = string.Format(formatString,
|
||||
libraryStats.booksNoProgress,
|
||||
libraryStats.booksDownloadedOnly,
|
||||
libraryStats.booksFullyBackedUp,
|
||||
libraryStats.booksError);
|
||||
statusStrip1.UIThreadAsync(() => backupsCountsLbl.Text = statusStripText);
|
||||
}
|
||||
private void setPdfBackupCounts(LibraryCommands.LibraryStats libraryStats)
|
||||
{
|
||||
// update bottom numbers
|
||||
{
|
||||
var hasResults = 0 < (libraryStats.pdfsNotDownloaded + libraryStats.pdfsDownloaded);
|
||||
// don't need to assign the output of Format(). It just makes this logic cleaner
|
||||
var statusStripText
|
||||
= !hasResults ? ""
|
||||
: libraryStats.pdfsNotDownloaded > 0 ? pdfsCountsLbl.Format(libraryStats.pdfsNotDownloaded, libraryStats.pdfsDownloaded)
|
||||
: $"| All {libraryStats.pdfsDownloaded} PDFs downloaded";
|
||||
statusStrip1.UIThreadAsync(() => pdfsCountsLbl.Text = statusStripText);
|
||||
}
|
||||
|
||||
// update 'begin pdf only backups' menu item
|
||||
// update 'begin book backups' menu item
|
||||
private void update_BeginBookBackups_menuItem(object _, System.ComponentModel.RunWorkerCompletedEventArgs e)
|
||||
{
|
||||
var libraryStats = e.Result as LibraryCommands.LibraryStats;
|
||||
|
||||
var menuItemText
|
||||
= libraryStats.HasPendingBooks
|
||||
? $"{libraryStats.PendingBooks} remaining"
|
||||
: "All books have been liberated";
|
||||
menuStrip1.UIThreadAsync(() =>
|
||||
{
|
||||
var menuItemText
|
||||
= libraryStats.pdfsNotDownloaded > 0
|
||||
? $"{libraryStats.pdfsNotDownloaded} remaining"
|
||||
: "All PDFs have been downloaded";
|
||||
menuStrip1.UIThreadAsync(() =>
|
||||
{
|
||||
beginPdfBackupsToolStripMenuItem.Format(menuItemText);
|
||||
beginPdfBackupsToolStripMenuItem.Enabled = libraryStats.pdfsNotDownloaded > 0;
|
||||
});
|
||||
}
|
||||
beginBookBackupsToolStripMenuItem.Format(menuItemText);
|
||||
beginBookBackupsToolStripMenuItem.Enabled = libraryStats.HasPendingBooks;
|
||||
});
|
||||
}
|
||||
|
||||
private void updateBottomPdfNumbers(object _, System.ComponentModel.RunWorkerCompletedEventArgs e)
|
||||
{
|
||||
var libraryStats = e.Result as LibraryCommands.LibraryStats;
|
||||
|
||||
// don't need to assign the output of Format(). It just makes this logic cleaner
|
||||
var statusStripText
|
||||
= !libraryStats.HasPdfResults ? ""
|
||||
: libraryStats.pdfsNotDownloaded > 0 ? pdfsCountsLbl.Format(libraryStats.pdfsNotDownloaded, libraryStats.pdfsDownloaded)
|
||||
: $"| All {libraryStats.pdfsDownloaded} PDFs downloaded";
|
||||
statusStrip1.UIThreadAsync(() => pdfsCountsLbl.Text = statusStripText);
|
||||
}
|
||||
|
||||
// update 'begin pdf only backups' menu item
|
||||
private void udpate_BeginPdfOnlyBackups_menuItem(object _, System.ComponentModel.RunWorkerCompletedEventArgs e)
|
||||
{
|
||||
var libraryStats = e.Result as LibraryCommands.LibraryStats;
|
||||
|
||||
var menuItemText
|
||||
= libraryStats.pdfsNotDownloaded > 0
|
||||
? $"{libraryStats.pdfsNotDownloaded} remaining"
|
||||
: "All PDFs have been downloaded";
|
||||
menuStrip1.UIThreadAsync(() =>
|
||||
{
|
||||
beginPdfBackupsToolStripMenuItem.Format(menuItemText);
|
||||
beginPdfBackupsToolStripMenuItem.Enabled = libraryStats.pdfsNotDownloaded > 0;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,7 +10,7 @@ namespace LibationWinForms
|
||||
private void Configure_Liberate() { }
|
||||
|
||||
//GetLibrary_Flat_NoTracking() may take a long time on a hugh library. so run in new thread
|
||||
private async void beginBookBackupsToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
private async void beginBookBackupsToolStripMenuItem_Click(object _ = null, EventArgs __ = null)
|
||||
{
|
||||
SetQueueCollapseState(false);
|
||||
await Task.Run(() => processBookQueue1.AddDownloadDecrypt(ApplicationServices.DbContexts.GetLibrary_Flat_NoTracking()
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
using Dinah.Core.Drawing;
|
||||
using LibationFileManager;
|
||||
|
||||
namespace LibationWinForms
|
||||
{
|
||||
public partial class Form1
|
||||
{
|
||||
private void Configure_PictureStorage()
|
||||
{
|
||||
// init default/placeholder cover art
|
||||
var format = System.Drawing.Imaging.ImageFormat.Jpeg;
|
||||
PictureStorage.SetDefaultImage(PictureSize._80x80, Properties.Resources.default_cover_80x80.ToBytes(format));
|
||||
PictureStorage.SetDefaultImage(PictureSize._300x300, Properties.Resources.default_cover_300x300.ToBytes(format));
|
||||
PictureStorage.SetDefaultImage(PictureSize._500x500, Properties.Resources.default_cover_500x500.ToBytes(format));
|
||||
PictureStorage.SetDefaultImage(PictureSize.Native, Properties.Resources.default_cover_500x500.ToBytes(format));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -22,7 +22,7 @@ namespace LibationWinForms
|
||||
|
||||
LibraryCommands.BookUserDefinedItemCommitted += setLiberatedVisibleMenuItemAsync;
|
||||
}
|
||||
private async void setLiberatedVisibleMenuItemAsync(object _, EventArgs __)
|
||||
private async void setLiberatedVisibleMenuItemAsync(object _, object __)
|
||||
=> await Task.Run(setLiberatedVisibleMenuItem);
|
||||
void setLiberatedVisibleMenuItem()
|
||||
{
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using ApplicationServices;
|
||||
using Dinah.Core.Drawing;
|
||||
using LibationFileManager;
|
||||
|
||||
namespace LibationWinForms
|
||||
{
|
||||
public partial class Form1
|
||||
{
|
||||
private void Configure_NonUI()
|
||||
{
|
||||
// init default/placeholder cover art
|
||||
var format = System.Drawing.Imaging.ImageFormat.Jpeg;
|
||||
PictureStorage.SetDefaultImage(PictureSize._80x80, Properties.Resources.default_cover_80x80.ToBytes(format));
|
||||
PictureStorage.SetDefaultImage(PictureSize._300x300, Properties.Resources.default_cover_300x300.ToBytes(format));
|
||||
PictureStorage.SetDefaultImage(PictureSize._500x500, Properties.Resources.default_cover_500x500.ToBytes(format));
|
||||
PictureStorage.SetDefaultImage(PictureSize.Native, Properties.Resources.default_cover_500x500.ToBytes(format));
|
||||
|
||||
// wire-up event to automatically download after scan.
|
||||
// winforms only. this should NOT be allowed in cli
|
||||
updateCountsBw.RunWorkerCompleted += (object sender, System.ComponentModel.RunWorkerCompletedEventArgs e) =>
|
||||
{
|
||||
if (!Configuration.Instance.AutoDownloadEpisodes)
|
||||
return;
|
||||
|
||||
var libraryStats = e.Result as LibraryCommands.LibraryStats;
|
||||
|
||||
if ((libraryStats.booksNoProgress + libraryStats.pdfsNotDownloaded) > 0)
|
||||
beginBookBackupsToolStripMenuItem_Click();
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -38,7 +38,6 @@ namespace LibationWinForms
|
||||
// these should do nothing interesting yet (storing simple var, subscribe to events) and should never rely on each other for order.
|
||||
// otherwise, order could be an issue.
|
||||
// eg: if one of these init'd productsGrid, then another can't reliably subscribe to it
|
||||
Configure_PictureStorage();
|
||||
Configure_BackupCounts();
|
||||
Configure_ScanAuto();
|
||||
Configure_ScanNotification();
|
||||
@@ -50,6 +49,8 @@ namespace LibationWinForms
|
||||
Configure_Settings();
|
||||
Configure_ProcessQueue();
|
||||
Configure_Filter();
|
||||
// misc which belongs in winforms app but doesn't have a UI element
|
||||
Configure_NonUI();
|
||||
|
||||
// Configure_Grid(); // since it's just this, can keep here. If it needs more, then give grid it's own 'partial class Form1'
|
||||
{
|
||||
|
||||
@@ -25,6 +25,7 @@ namespace LibationWinForms.GridView
|
||||
#endregion
|
||||
|
||||
protected override Book Book => LibraryBook.Book;
|
||||
|
||||
#region Model properties exposed to the view
|
||||
|
||||
private DateTime lastStatusUpdate = default;
|
||||
@@ -75,6 +76,7 @@ namespace LibationWinForms.GridView
|
||||
if (AudibleProductId != libraryBook.Book.AudibleProductId)
|
||||
throw new Exception("Invalid grid entry update. IDs must match");
|
||||
|
||||
UserDefinedItem.ItemChanged -= UserDefinedItem_ItemChanged;
|
||||
setLibraryBook(libraryBook);
|
||||
|
||||
NotifyPropertyChanged();
|
||||
@@ -84,8 +86,6 @@ namespace LibationWinForms.GridView
|
||||
{
|
||||
LibraryBook = libraryBook;
|
||||
|
||||
UserDefinedItem.ItemChanged -= UserDefinedItem_ItemChanged;
|
||||
|
||||
// Immutable properties
|
||||
{
|
||||
Title = Book.Title;
|
||||
@@ -110,7 +110,7 @@ namespace LibationWinForms.GridView
|
||||
|
||||
/// <summary>
|
||||
/// This event handler receives notifications from the model that it has changed.
|
||||
/// Save to the database and notify the view that it's changed.
|
||||
/// Notify the view that it's changed.
|
||||
/// </summary>
|
||||
private void UserDefinedItem_ItemChanged(object sender, string itemName)
|
||||
{
|
||||
@@ -119,23 +119,23 @@ namespace LibationWinForms.GridView
|
||||
if (udi.Book.AudibleProductId != Book.AudibleProductId)
|
||||
return;
|
||||
|
||||
// UDI changed, possibly in a different context/view. Update this viewmodel. Call NotifyPropertyChanged to notify view.
|
||||
// - This method responds to tons of incidental changes. Do not persist to db from here. Committing to db must be a volitional action by the caller, not incidental. Otherwise batch changes would be impossible; we would only have slow one-offs
|
||||
// - Don't restrict notifying view to 'only if property changed'. This same book instance can get passed to a different view, then changed there. When the chain of events makes its way back here, the property is unchanged (because it's the same instance), but this view is out of sync. NotifyPropertyChanged will then update this view.
|
||||
switch (itemName)
|
||||
{
|
||||
case nameof(udi.Tags):
|
||||
Book.UserDefinedItem.Tags = udi.Tags;
|
||||
SearchEngineCommands.UpdateBookTags(Book);
|
||||
NotifyPropertyChanged(nameof(DisplayTags));
|
||||
break;
|
||||
case nameof(udi.BookStatus):
|
||||
Book.UserDefinedItem.BookStatus = udi.BookStatus;
|
||||
_bookStatus = udi.BookStatus;
|
||||
SearchEngineCommands.UpdateLiberatedStatus(Book);
|
||||
NotifyPropertyChanged(nameof(Liberate));
|
||||
break;
|
||||
case nameof(udi.PdfStatus):
|
||||
Book.UserDefinedItem.PdfStatus = udi.PdfStatus;
|
||||
_pdfStatus = udi.PdfStatus;
|
||||
SearchEngineCommands.UpdateLiberatedStatus(Book);
|
||||
NotifyPropertyChanged(nameof(Liberate));
|
||||
break;
|
||||
}
|
||||
@@ -143,23 +143,8 @@ namespace LibationWinForms.GridView
|
||||
|
||||
/// <summary>Save edits to the database</summary>
|
||||
public void Commit(string newTags, LiberatedStatus bookStatus, LiberatedStatus? pdfStatus)
|
||||
{
|
||||
// validate
|
||||
if (DisplayTags.EqualsInsensitive(newTags) &&
|
||||
Liberate.BookStatus == bookStatus &&
|
||||
Liberate.PdfStatus == pdfStatus)
|
||||
return;
|
||||
|
||||
// update cache
|
||||
_bookStatus = bookStatus;
|
||||
_pdfStatus = pdfStatus;
|
||||
|
||||
// set + save
|
||||
Book.UserDefinedItem.Tags = newTags;
|
||||
Book.UserDefinedItem.BookStatus = bookStatus;
|
||||
Book.UserDefinedItem.PdfStatus = pdfStatus;
|
||||
LibraryCommands.UpdateUserDefinedItem(Book);
|
||||
}
|
||||
// MVVM pass-through
|
||||
=> Book.UpdateBook(newTags, bookStatus: bookStatus, pdfStatus: pdfStatus);
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
@@ -1,8 +1,4 @@
|
||||
using DataLayer;
|
||||
using Dinah.Core;
|
||||
using FileLiberator;
|
||||
using LibationFileManager;
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Drawing;
|
||||
@@ -10,6 +6,11 @@ using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
using ApplicationServices;
|
||||
using DataLayer;
|
||||
using Dinah.Core;
|
||||
using FileLiberator;
|
||||
using LibationFileManager;
|
||||
|
||||
namespace LibationWinForms.ProcessQueue
|
||||
{
|
||||
@@ -349,8 +350,7 @@ $@" Title: {libraryBook.Book.Title}
|
||||
|
||||
if (dialogResult == SkipResult)
|
||||
{
|
||||
libraryBook.Book.UserDefinedItem.BookStatus = LiberatedStatus.Error;
|
||||
ApplicationServices.LibraryCommands.UpdateUserDefinedItem(libraryBook.Book);
|
||||
libraryBook.Book.UpdateBookStatus(LiberatedStatus.Error);
|
||||
|
||||
Logger.Info($"Error. Skip: [{libraryBook.Book.AudibleProductId}] {libraryBook.Book.Title}");
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
using ApplicationServices;
|
||||
|
||||
namespace LibationWinForms.ProcessQueue
|
||||
{
|
||||
@@ -156,10 +157,7 @@ namespace LibationWinForms.ProcessQueue
|
||||
else if (result == ProcessBookResult.FailedAbort)
|
||||
Queue.ClearQueue();
|
||||
else if (result == ProcessBookResult.FailedSkip)
|
||||
{
|
||||
nextBook.LibraryBook.Book.UserDefinedItem.BookStatus = DataLayer.LiberatedStatus.Error;
|
||||
ApplicationServices.LibraryCommands.UpdateUserDefinedItem(nextBook.LibraryBook.Book);
|
||||
}
|
||||
nextBook.LibraryBook.Book.UpdateBookStatus(DataLayer.LiberatedStatus.Error);
|
||||
}
|
||||
Queue_CompletedCountChanged(this, 0);
|
||||
counterTimer.Stop();
|
||||
|
||||
Reference in new issue
Block a user