diff --git a/LibationLauncher/LibationLauncher.csproj b/LibationLauncher/LibationLauncher.csproj
index 5af2cd25..33159e83 100644
--- a/LibationLauncher/LibationLauncher.csproj
+++ b/LibationLauncher/LibationLauncher.csproj
@@ -13,7 +13,11 @@
win-x64
- 5.4.9.79
+ 5.4.9.120
+
+
+
+ TRACE;DEBUG
diff --git a/LibationLauncher/Program.cs b/LibationLauncher/Program.cs
index 2fa3c87a..ab4c6e1c 100644
--- a/LibationLauncher/Program.cs
+++ b/LibationLauncher/Program.cs
@@ -59,7 +59,10 @@ namespace LibationLauncher
ensureSerilogConfig(config);
configureLogging(config);
logStartupState(config);
+
+#if !DEBUG
checkForUpdate(config);
+#endif
Application.Run(new Form1());
}
@@ -145,7 +148,7 @@ namespace LibationLauncher
CancelInstallation();
}
- #region migrate to v5.0.0 re-register device if device info not in settings
+#region migrate to v5.0.0 re-register device if device info not in settings
private static void migrate_to_v5_0_0(Configuration config)
{
if (!config.Exists(nameof(config.AllowLibationFixup)))
@@ -187,9 +190,9 @@ namespace LibationLauncher
}
}
}
- #endregion
+#endregion
- #region migrate to v5.2.0
+#region migrate to v5.2.0
// get rid of meta-directories, combine DownloadsInProgressEnum and DecryptInProgressEnum => InProgress
private static void migrate_to_v5_2_0__pre_config()
{
@@ -231,9 +234,9 @@ namespace LibationLauncher
if (!config.Exists(nameof(config.DecryptToLossy)))
config.DecryptToLossy = false;
}
- #endregion
+#endregion
- #region migrate to v5.4.1 see comment
+#region migrate to v5.4.1 see comment
// this 'migration' is a bit different. it intentionally runs each time Libation is started. its job will be fulfilled when I eventually
// implement the portion which removes FilePaths.json, at which time this method will be a proper migration
//
@@ -297,7 +300,7 @@ namespace LibationLauncher
debugStopwatch.Stop();
var debugTotal = debugStopwatch.Elapsed;
}
- #endregion
+#endregion
private static void ensureSerilogConfig(Configuration config)
{
@@ -418,6 +421,7 @@ namespace LibationLauncher
if (latest is null)
return;
+
var latestVersionString = latest.TagName.Trim('v');
if (!Version.TryParse(latestVersionString, out var latestRelease))
return;
diff --git a/LibationWinForms/Dialogs/RemoveBooksDialog.cs b/LibationWinForms/Dialogs/RemoveBooksDialog.cs
index 7bfafb8c..04e7af16 100644
--- a/LibationWinForms/Dialogs/RemoveBooksDialog.cs
+++ b/LibationWinForms/Dialogs/RemoveBooksDialog.cs
@@ -39,8 +39,8 @@ namespace LibationWinForms.Dialogs
dataGridView1.BindingContextChanged += (s, e) => UpdateSelection();
var orderedGridEntries = _libraryBooks
- .Select(lb => new RemovableGridEntry(new GridEntry(lb)))
- .OrderByDescending(ge => ge.GridEntry.PurchaseDate)
+ .Select(lb => new RemovableGridEntry(lb))
+ .OrderByDescending(ge => ge.PurchaseDate)
.ToList();
_removableGridEntries = orderedGridEntries.ToSortableBindingList();
@@ -65,7 +65,7 @@ namespace LibationWinForms.Dialogs
{
var rmovedBooks = await LibraryCommands.FindInactiveBooks((account) => new WinformResponder(account), _libraryBooks, _accounts);
- var removable = _removableGridEntries.Where(rge => rmovedBooks.Count(rb => rb.Book.AudibleProductId == rge.GridEntry.AudibleProductId) == 1);
+ var removable = _removableGridEntries.Where(rge => rmovedBooks.Count(rb => rb.Book.AudibleProductId == rge.AudibleProductId) == 1);
if (removable.Count() == 0)
return;
@@ -110,7 +110,7 @@ namespace LibationWinForms.Dialogs
var libBooks = context.GetLibrary_Flat_NoTracking();
- var removeLibraryBooks = libBooks.Where(lb => selected.Count(rge => rge.GridEntry.AudibleProductId == lb.Book.AudibleProductId) == 1).ToArray();
+ var removeLibraryBooks = libBooks.Where(lb => selected.Count(rge => rge.AudibleProductId == lb.Book.AudibleProductId) == 1).ToArray();
context.Library.RemoveRange(removeLibraryBooks);
context.SaveChanges();
BooksRemoved = true;
@@ -141,11 +141,8 @@ namespace LibationWinForms.Dialogs
}
- internal class RemovableGridEntry : INotifyPropertyChanged
+ internal class RemovableGridEntry : GridEntry
{
- public event PropertyChangedEventHandler PropertyChanged;
- public GridEntry GridEntry { get; }
-
public bool Remove
{
get
@@ -160,51 +157,12 @@ namespace LibationWinForms.Dialogs
NotifyPropertyChanged();
}
}
- }
- public Image Cover
- {
- get
- {
- return _cover;
- }
- set
- {
- _cover = value;
- NotifyPropertyChanged();
- }
- }
- public string Title => GridEntry.Title;
- public string Authors => GridEntry.Authors;
- public string Misc => GridEntry.Misc;
- public string DatePurchased => GridEntry.PurchaseDate;
+ }
private bool _remove = false;
- private Image _cover;
- public RemovableGridEntry(GridEntry gridEntry)
+ public RemovableGridEntry(LibraryBook libraryBook) :base(libraryBook)
{
- GridEntry = gridEntry;
-
- var picDef = new FileManager.PictureDefinition(GridEntry.LibraryBook.Book.PictureId, FileManager.PictureSize._80x80);
- (bool isDefault, byte[] picture) = FileManager.PictureStorage.GetPicture(picDef);
-
- if (isDefault)
- FileManager.PictureStorage.PictureCached += PictureStorage_PictureCached;
-
- _cover = ImageReader.ToImage(picture);
}
-
- private void PictureStorage_PictureCached(object sender, string pictureId)
- {
- if (pictureId == GridEntry.LibraryBook.Book.PictureId)
- {
- Cover = WindowsDesktopUtilities.WinAudibleImageServer.GetImage(pictureId, FileManager.PictureSize._80x80);
- FileManager.PictureStorage.PictureCached -= PictureStorage_PictureCached;
- }
- }
-
- private void NotifyPropertyChanged([CallerMemberName] string propertyName = "") =>
- PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
-
}
}
diff --git a/LibationWinForms/EditTagsDataGridViewImageButtonColumn.cs b/LibationWinForms/EditTagsDataGridViewImageButtonColumn.cs
index fdee638f..58f39545 100644
--- a/LibationWinForms/EditTagsDataGridViewImageButtonColumn.cs
+++ b/LibationWinForms/EditTagsDataGridViewImageButtonColumn.cs
@@ -12,15 +12,23 @@ namespace LibationWinForms
internal class EditTagsDataGridViewImageButtonCell : DataGridViewImageButtonCell
{
private static readonly Bitmap ButtonImage = Properties.Resources.edit_tags_25x25;
+ private static readonly Color HiddenForeColor = Color.LightGray;
+
protected override void Paint(Graphics graphics, Rectangle clipBounds, Rectangle cellBounds, int rowIndex, DataGridViewElementStates elementState, object value, object formattedValue, string errorText, DataGridViewCellStyle cellStyle, DataGridViewAdvancedBorderStyle advancedBorderStyle, DataGridViewPaintParts paintParts)
{
- if (((string)value).Length == 0)
+ var valueString = (string)value;
+
+ DataGridView.Rows[RowIndex].DefaultCellStyle.ForeColor = valueString?.Contains("hidden") == true ? HiddenForeColor : DataGridView.DefaultCellStyle.ForeColor;
+
+ if (valueString.Length == 0)
{
base.Paint(graphics, clipBounds, cellBounds, rowIndex, elementState, null, null, null, cellStyle, advancedBorderStyle, paintParts);
DrawImage(graphics, ButtonImage, cellBounds);
}
else
+ {
base.Paint(graphics, clipBounds, cellBounds, rowIndex, elementState, value, formattedValue, errorText, cellStyle, advancedBorderStyle, paintParts);
+ }
}
}
}
diff --git a/LibationWinForms/Form1.cs b/LibationWinForms/Form1.cs
index 4221082c..56d44638 100644
--- a/LibationWinForms/Form1.cs
+++ b/LibationWinForms/Form1.cs
@@ -48,13 +48,6 @@ namespace LibationWinForms
this.Load += (_, __) => RestoreSizeAndLocation();
this.Load += (_, __) => RefreshImportMenu();
- // start background service
- this.Load += (_, __) => startBackgroundImageDownloader();
- }
-
- private static void startBackgroundImageDownloader()
- {
- // load default/missing cover images. this will also initiate the background image downloader
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));
diff --git a/LibationWinForms/GridEntry.cs b/LibationWinForms/GridEntry.cs
index d20c6553..f9de6708 100644
--- a/LibationWinForms/GridEntry.cs
+++ b/LibationWinForms/GridEntry.cs
@@ -5,9 +5,11 @@ using System.ComponentModel;
using System.Drawing;
using System.Linq;
using System.Runtime.CompilerServices;
+using System.Threading;
using ApplicationServices;
using DataLayer;
using Dinah.Core.Drawing;
+using Dinah.Core.Windows.Forms;
namespace LibationWinForms
{
@@ -32,6 +34,7 @@ namespace LibationWinForms
public event PropertyChangedEventHandler PropertyChanged;
private Book Book => LibraryBook.Book;
+ private SynchronizationContext SyncContext { get; } = SynchronizationContext.Current;
private Image _cover;
public GridEntry(LibraryBook libraryBook)
@@ -72,16 +75,23 @@ namespace LibationWinForms
{
if (pictureId == Book.PictureId)
{
+ //GridEntry SHOULD be UI-ignorant, but PropertyChanged
Cover = WindowsDesktopUtilities.WinAudibleImageServer.GetImage(pictureId, FileManager.PictureSize._80x80);
FileManager.PictureStorage.PictureCached -= PictureStorage_PictureCached;
}
}
- private void NotifyPropertyChanged([CallerMemberName] string propertyName = "") =>
- PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
+ protected void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
+ => SyncContext.Post(
+ args => OnPropertyChangedAsync(args as AsyncCompletedEventArgs),
+ new AsyncCompletedEventArgs(null, false, new PropertyChangedEventArgs(propertyName))
+ );
- #region Data Source properties
- public Image Cover
+ private void OnPropertyChangedAsync(AsyncCompletedEventArgs e) =>
+ PropertyChanged?.Invoke(this, e.UserState as PropertyChangedEventArgs);
+
+ #region Data Source properties
+ public Image Cover
{
get
{
diff --git a/LibationWinForms/ProductsGrid.cs b/LibationWinForms/ProductsGrid.cs
index f06b8c1a..3f02b2e6 100644
--- a/LibationWinForms/ProductsGrid.cs
+++ b/LibationWinForms/ProductsGrid.cs
@@ -1,5 +1,4 @@
using System;
-using System.Drawing;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
@@ -38,7 +37,6 @@ namespace LibationWinForms
// sorting breaks filters. must reapply filters after sorting
_dataGridView.Sorted += (_, __) => Filter();
- _dataGridView.CellFormatting += HiddenFormatting;
_dataGridView.CellContentClick += DataGridView_CellContentClick;
EnableDoubleBuffering();
@@ -133,7 +131,7 @@ namespace LibationWinForms
var orderedGridEntries = lib
.Select(lb => new GridEntry(lb)).ToList()
// default load order
- .OrderByDescending(ge => ge.PurchaseDate)
+ .OrderByDescending(ge => (DateTime)ge.GetMemberValue(nameof(ge.PurchaseDate)))
//// more advanced example: sort by author, then series, then title
//.OrderBy(ge => ge.Authors)
// .ThenBy(ge => ge.Series)
@@ -155,10 +153,10 @@ namespace LibationWinForms
public void RefreshRow(string productId)
{
- var rowId = getRowIndex((ge) => ge.AudibleProductId == productId);
+ var rowIndex = getRowIndex((ge) => ge.AudibleProductId == productId);
// update cells incl Liberate button text
- _dataGridView.InvalidateRow(rowId);
+ _dataGridView.InvalidateRow(rowIndex);
// needed in case filtering by -IsLiberated and it gets changed to Liberated. want to immediately show the change
Filter();
@@ -166,28 +164,9 @@ namespace LibationWinForms
BackupCountsChanged?.Invoke(this, EventArgs.Empty);
}
- #region format text cells. ie: not buttons
-
- private void HiddenFormatting(object sender, DataGridViewCellFormattingEventArgs e)
- {
- var dgv = (DataGridView)sender;
- // no action needed for buttons
- if (e.RowIndex < 0 || dgv.Columns[e.ColumnIndex] is DataGridViewButtonColumn)
- return;
-
- var isHidden = getGridEntry(e.RowIndex).TagsEnumerated.Contains("hidden");
-
- getCell(e).Style
- = isHidden
- ? new DataGridViewCellStyle { ForeColor = Color.LightGray }
- : dgv.DefaultCellStyle;
- }
-
#endregion
- #endregion
-
- #region filter
+ #region Filter
string _filterSearchString;
private void Filter() => Filter(_filterSearchString);
@@ -220,7 +199,6 @@ namespace LibationWinForms
private int getRowIndex(Func func) => _dataGridView.GetRowIdOfBoundItem(func);
private GridEntry getGridEntry(int rowIndex) => _dataGridView.GetBoundItem(rowIndex);
- private DataGridViewCell getCell(DataGridViewCellFormattingEventArgs e) => _dataGridView.Rows[e.RowIndex].Cells[e.ColumnIndex];
#endregion
}