batch book status updates
bug fixes, esp. threading
This commit is contained in:
parent
613c97524a
commit
14e14ba9bd
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net5.0</TargetFramework>
|
<TargetFramework>net5.0</TargetFramework>
|
||||||
<Version>6.0.5.1</Version>
|
<Version>6.0.6.1</Version>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@ -106,6 +106,11 @@ namespace DataLayer
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region LiberatedStatuses
|
#region LiberatedStatuses
|
||||||
|
/// <summary>
|
||||||
|
/// Occurs when <see cref="Tags"/>, <see cref="BookStatus"/>, or <see cref="PdfStatus"/> values change.
|
||||||
|
/// This signals the change of the in-memory value; it does not ensure that the new value has been persisted.
|
||||||
|
/// </summary>
|
||||||
|
public static event EventHandler<string> ItemChanged;
|
||||||
|
|
||||||
private LiberatedStatus _bookStatus;
|
private LiberatedStatus _bookStatus;
|
||||||
private LiberatedStatus? _pdfStatus;
|
private LiberatedStatus? _pdfStatus;
|
||||||
@ -132,13 +137,41 @@ namespace DataLayer
|
|||||||
ItemChanged?.Invoke(this, nameof(PdfStatus));
|
ItemChanged?.Invoke(this, nameof(PdfStatus));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region batch changes
|
||||||
|
public static event EventHandler<string> Batch_ItemChanged;
|
||||||
|
public void BatchMode_UpdateBookStatus(LiberatedStatus value)
|
||||||
|
{
|
||||||
|
if (_bookStatus != value)
|
||||||
|
{
|
||||||
|
_bookStatus = value;
|
||||||
|
batchFlag = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// don't overwrite current with null. Therefore input is "LiberatedStatus" not "LiberatedStatus?"
|
||||||
|
public void BatchMode_UpdatePdfStatus(LiberatedStatus value)
|
||||||
|
{
|
||||||
|
if (_pdfStatus != value)
|
||||||
|
{
|
||||||
|
_pdfStatus = value;
|
||||||
|
batchFlag = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool batchFlag = false;
|
||||||
|
|
||||||
|
public static void BatchMode_Finalize()
|
||||||
|
{
|
||||||
|
if (batchFlag)
|
||||||
|
Batch_ItemChanged?.Invoke(null, null);
|
||||||
|
|
||||||
|
batchFlag = false;
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
/// <summary>
|
|
||||||
/// Occurs when <see cref="Tags"/>, <see cref="BookStatus"/>, or <see cref="PdfStatus"/> values change.
|
|
||||||
/// This signals the change of the in-memory value; it does not ensure that the new value has been persisted.
|
|
||||||
/// </summary>
|
|
||||||
public static event EventHandler<string> ItemChanged;
|
|
||||||
public override string ToString() => $"{Book} {Rating} {Tags}";
|
public override string ToString() => $"{Book} {Rating} {Tags}";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -315,7 +315,7 @@ namespace LibationSearchEngine
|
|||||||
var docs = searcher.Search(query, 1);
|
var docs = searcher.Search(query, 1);
|
||||||
var scoreDoc = docs.ScoreDocs.SingleOrDefault();
|
var scoreDoc = docs.ScoreDocs.SingleOrDefault();
|
||||||
if (scoreDoc == null)
|
if (scoreDoc == null)
|
||||||
throw new Exception("document not found");
|
return;
|
||||||
var document = searcher.Doc(scoreDoc.Doc);
|
var document = searcher.Doc(scoreDoc.Doc);
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -34,6 +34,8 @@ namespace LibationWinForms
|
|||||||
this.FormClosing += (_, _) => this.SaveSizeAndLocation(Configuration.Instance);
|
this.FormClosing += (_, _) => this.SaveSizeAndLocation(Configuration.Instance);
|
||||||
LibraryCommands.LibrarySizeChanged += reloadGridAndUpdateBottomNumbers;
|
LibraryCommands.LibrarySizeChanged += reloadGridAndUpdateBottomNumbers;
|
||||||
LibraryCommands.BookUserDefinedItemCommitted += setBackupCounts;
|
LibraryCommands.BookUserDefinedItemCommitted += setBackupCounts;
|
||||||
|
// used by async migrations to update ui when complete
|
||||||
|
DataLayer.UserDefinedItem.Batch_ItemChanged += reloadGridAndUpdateBottomNumbers;
|
||||||
|
|
||||||
var format = System.Drawing.Imaging.ImageFormat.Jpeg;
|
var format = System.Drawing.Imaging.ImageFormat.Jpeg;
|
||||||
PictureStorage.SetDefaultImage(PictureSize._80x80, Properties.Resources.default_cover_80x80.ToBytes(format));
|
PictureStorage.SetDefaultImage(PictureSize._80x80, Properties.Resources.default_cover_80x80.ToBytes(format));
|
||||||
|
|||||||
@ -27,17 +27,16 @@ namespace LibationWinForms
|
|||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
public event EventHandler Committed;
|
||||||
|
|
||||||
private Book Book => LibraryBook.Book;
|
private Book Book => LibraryBook.Book;
|
||||||
private Image _cover;
|
private Image _cover;
|
||||||
private Action Refilter { get; }
|
|
||||||
|
|
||||||
public GridEntry(LibraryBook libraryBook, Action refilterOnChanged = null)
|
public GridEntry(LibraryBook libraryBook)
|
||||||
{
|
{
|
||||||
LibraryBook = libraryBook;
|
LibraryBook = libraryBook;
|
||||||
Refilter = refilterOnChanged;
|
|
||||||
_memberValues = CreateMemberValueDictionary();
|
_memberValues = CreateMemberValueDictionary();
|
||||||
|
|
||||||
|
|
||||||
//Get cover art. If it's default, subscribe to PictureCached
|
//Get cover art. If it's default, subscribe to PictureCached
|
||||||
{
|
{
|
||||||
(bool isDefault, byte[] picture) = FileManager.PictureStorage.GetPicture(new FileManager.PictureDefinition(Book.PictureId, FileManager.PictureSize._80x80));
|
(bool isDefault, byte[] picture) = FileManager.PictureStorage.GetPicture(new FileManager.PictureDefinition(Book.PictureId, FileManager.PictureSize._80x80));
|
||||||
@ -142,7 +141,7 @@ namespace LibationWinForms
|
|||||||
|
|
||||||
Book.UserDefinedItem.BookStatus = displayStatus;
|
Book.UserDefinedItem.BookStatus = displayStatus;
|
||||||
|
|
||||||
Refilter?.Invoke();
|
Committed?.Invoke(this, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|||||||
@ -3,9 +3,9 @@ using System.Linq;
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
using ApplicationServices;
|
using ApplicationServices;
|
||||||
using DataLayer;
|
|
||||||
using Dinah.Core;
|
using Dinah.Core;
|
||||||
using Dinah.Core.DataBinding;
|
using Dinah.Core.DataBinding;
|
||||||
|
using Dinah.Core.Threading;
|
||||||
using Dinah.Core.Windows.Forms;
|
using Dinah.Core.Windows.Forms;
|
||||||
using LibationWinForms.Dialogs;
|
using LibationWinForms.Dialogs;
|
||||||
|
|
||||||
@ -130,7 +130,12 @@ namespace LibationWinForms
|
|||||||
}
|
}
|
||||||
|
|
||||||
var orderedGridEntries = lib
|
var orderedGridEntries = lib
|
||||||
.Select(lb => new GridEntry(lb, Filter)).ToList()
|
.Select(lb =>
|
||||||
|
{
|
||||||
|
var entry = new GridEntry(lb);
|
||||||
|
entry.Committed += (_, __) => Filter();
|
||||||
|
return entry;
|
||||||
|
}).ToList()
|
||||||
// default load order
|
// default load order
|
||||||
.OrderByDescending(ge => (DateTime)ge.GetMemberValue(nameof(ge.PurchaseDate)))
|
.OrderByDescending(ge => (DateTime)ge.GetMemberValue(nameof(ge.PurchaseDate)))
|
||||||
//// more advanced example: sort by author, then series, then title
|
//// more advanced example: sort by author, then series, then title
|
||||||
@ -166,8 +171,11 @@ namespace LibationWinForms
|
|||||||
var bindingContext = BindingContext[_dataGridView.DataSource];
|
var bindingContext = BindingContext[_dataGridView.DataSource];
|
||||||
bindingContext.SuspendBinding();
|
bindingContext.SuspendBinding();
|
||||||
{
|
{
|
||||||
for (var r = _dataGridView.RowCount - 1; r >= 0; r--)
|
this.UIThreadSync(() =>
|
||||||
_dataGridView.Rows[r].Visible = productIds.Contains(getGridEntry(r).AudibleProductId);
|
{
|
||||||
|
for (var r = _dataGridView.RowCount - 1; r >= 0; r--)
|
||||||
|
_dataGridView.Rows[r].Visible = productIds.Contains(getGridEntry(r).AudibleProductId);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
//Causes repainting of the DataGridView
|
//Causes repainting of the DataGridView
|
||||||
|
|||||||
@ -259,22 +259,25 @@ namespace LibationWinForms
|
|||||||
|
|
||||||
// assign these strings and enums/ints unconditionally. EFCore will only update if changed
|
// assign these strings and enums/ints unconditionally. EFCore will only update if changed
|
||||||
if (fileType == FileType.PDF)
|
if (fileType == FileType.PDF)
|
||||||
book.UserDefinedItem.PdfStatus = LiberatedStatus.Liberated;
|
book.UserDefinedItem.BatchMode_UpdatePdfStatus(LiberatedStatus.Liberated);
|
||||||
|
|
||||||
if (fileType == FileType.Audio)
|
if (fileType == FileType.Audio)
|
||||||
{
|
{
|
||||||
var lhack = libhackFiles.FirstOrDefault(f => f.ContainsInsensitive(asin));
|
var lhack = libhackFiles.FirstOrDefault(f => f.ContainsInsensitive(asin));
|
||||||
if (lhack is null)
|
if (lhack is null)
|
||||||
book.UserDefinedItem.BookStatus = LiberatedStatus.Liberated;
|
book.UserDefinedItem.BatchMode_UpdateBookStatus(LiberatedStatus.Liberated);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
book.UserDefinedItem.BookStatus = LiberatedStatus.Error;
|
book.UserDefinedItem.BatchMode_UpdateBookStatus(LiberatedStatus.Error);
|
||||||
libhackFilesToDelete.Add(lhack);
|
libhackFilesToDelete.Add(lhack);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// in order: save to db, full reindex from db, refresh ui
|
||||||
context.SaveChanges();
|
context.SaveChanges();
|
||||||
|
ApplicationServices.SearchEngineCommands.FullReIndex();
|
||||||
|
UserDefinedItem.BatchMode_Finalize();
|
||||||
|
|
||||||
// only do this after save changes
|
// only do this after save changes
|
||||||
foreach (var libhackFile in libhackFilesToDelete)
|
foreach (var libhackFile in libhackFilesToDelete)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user