diff --git a/AppScaffolding/LibationScaffolding.cs b/AppScaffolding/LibationScaffolding.cs index 3089b6f5..7aff95fc 100644 --- a/AppScaffolding/LibationScaffolding.cs +++ b/AppScaffolding/LibationScaffolding.cs @@ -104,7 +104,7 @@ namespace AppScaffolding private static void ensureSerilogConfig(Configuration config) { - if (config.GetObject("Serilog") != null) + if (config.GetObject("Serilog") is not null) return; var serilogObj = new JObject diff --git a/AudibleUtilities/Account.cs b/AudibleUtilities/Account.cs index 25727724..ddf2a0fb 100644 --- a/AudibleUtilities/Account.cs +++ b/AudibleUtilities/Account.cs @@ -73,10 +73,10 @@ namespace AudibleUtilities if (_identity is null && value is null) return; - if (_identity != null) + if (_identity is not null) _identity.Updated -= update; - if (value != null) + if (value is not null) value.Updated += update; _identity = value; diff --git a/AudibleUtilities/AccountsSettings.cs b/AudibleUtilities/AccountsSettings.cs index 83a07b6f..dd3d439e 100644 --- a/AudibleUtilities/AccountsSettings.cs +++ b/AudibleUtilities/AccountsSettings.cs @@ -66,7 +66,7 @@ namespace AudibleUtilities { var acct = GetAccount(accountId, locale); - if (acct != null) + if (acct is not null) return acct; var l = Localization.Get(locale); diff --git a/AudibleUtilities/ApiExtended.cs b/AudibleUtilities/ApiExtended.cs index 821e2751..512949ef 100644 --- a/AudibleUtilities/ApiExtended.cs +++ b/AudibleUtilities/ApiExtended.cs @@ -148,7 +148,7 @@ namespace AudibleUtilities foreach (var v in validators) { var exceptions = v.Validate(items); - if (exceptions != null && exceptions.Any()) + if (exceptions is not null && exceptions.Any()) throw new AggregateException(exceptions); } diff --git a/DataLayer/EfClasses/Book.cs b/DataLayer/EfClasses/Book.cs index 1c1d1c3e..4aee9b8c 100644 --- a/DataLayer/EfClasses/Book.cs +++ b/DataLayer/EfClasses/Book.cs @@ -43,12 +43,12 @@ namespace DataLayer internal int CategoryId { get; private set; } public Category Category { get; private set; } public string[] CategoriesNames - => Category == null ? new string[0] - : Category.ParentCategory == null ? new[] { Category.Name } + => Category is null ? new string[0] + : Category.ParentCategory is null ? new[] { Category.Name } : new[] { Category.ParentCategory.Name, Category.Name }; public string[] CategoriesIds - => Category == null ? null - : Category.ParentCategory == null ? new[] { Category.AudibleCategoryId } + => Category is null ? null + : Category.ParentCategory is null ? new[] { Category.AudibleCategoryId } : new[] { Category.ParentCategory.AudibleCategoryId, Category.AudibleCategoryId }; // is owned, not optional 1:1 @@ -216,7 +216,7 @@ namespace DataLayer getEntry(context).Collection(s => s.SeriesLink).Load(); var singleSeriesBook = _seriesLink.SingleOrDefault(sb => sb.Series == series); - if (singleSeriesBook == null) + if (singleSeriesBook is null) _seriesLink.Add(new SeriesBook(series, this, order)); else singleSeriesBook.UpdateOrder(order); diff --git a/DataLayer/EfClasses/Category.cs b/DataLayer/EfClasses/Category.cs index 64af14db..2060b72e 100644 --- a/DataLayer/EfClasses/Category.cs +++ b/DataLayer/EfClasses/Category.cs @@ -44,7 +44,7 @@ namespace DataLayer public void UpdateParentCategory(Category parentCategory) { // don't overwrite with null but not an error - if (parentCategory != null) + if (parentCategory is not null) ParentCategory = parentCategory; } diff --git a/DataLayer/EfClasses/UserDefinedItem.cs b/DataLayer/EfClasses/UserDefinedItem.cs index f1e77eee..f5da2cf8 100644 --- a/DataLayer/EfClasses/UserDefinedItem.cs +++ b/DataLayer/EfClasses/UserDefinedItem.cs @@ -162,38 +162,6 @@ namespace DataLayer } #endregion - #region batch changes - public static event EventHandler 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 - public override string ToString() => $"{Book} {Rating} {Tags}"; } } diff --git a/DataLayer/TagPersistenceInterceptor.cs b/DataLayer/TagPersistenceInterceptor.cs index c08d0c23..8be15d7f 100644 --- a/DataLayer/TagPersistenceInterceptor.cs +++ b/DataLayer/TagPersistenceInterceptor.cs @@ -19,7 +19,7 @@ namespace DataLayer .Entries() .Where(e => e.State.In(EntityState.Modified, EntityState.Added)) .Select(e => e.Entity as UserDefinedItem) - .Where(udi => udi != null) + .Where(udi => udi is not null) // do NOT filter out entires with blank tags. blank is the valid way to show the absence of tags .Select(t => (t.Book.AudibleProductId, t.Tags)) .ToList(); diff --git a/DtoImporterService/BookImporter.cs b/DtoImporterService/BookImporter.cs index 5e8d468e..cbb56d3b 100644 --- a/DtoImporterService/BookImporter.cs +++ b/DtoImporterService/BookImporter.cs @@ -172,7 +172,7 @@ namespace DtoImporterService // update series even for existing books. these are occasionally updated // these will upsert over library-scraped series, but will not leave orphans - if (item.Series != null) + if (item.Series is not null) { foreach (var seriesEntry in item.Series) { diff --git a/DtoImporterService/ImporterBase.cs b/DtoImporterService/ImporterBase.cs index 76f1132e..278659c7 100644 --- a/DtoImporterService/ImporterBase.cs +++ b/DtoImporterService/ImporterBase.cs @@ -25,7 +25,7 @@ namespace DtoImporterService try { var exceptions = Validate(param); - if (exceptions != null && exceptions.Any()) + if (exceptions is not null && exceptions.Any()) throw new AggregateException($"Importer validation failed", exceptions); } catch (Exception ex) diff --git a/LibationFileManager/AudibleFileStorage.cs b/LibationFileManager/AudibleFileStorage.cs index 1341256e..26d3c304 100644 --- a/LibationFileManager/AudibleFileStorage.cs +++ b/LibationFileManager/AudibleFileStorage.cs @@ -78,7 +78,7 @@ namespace LibationFileManager .FirstOrDefault(s => regex.IsMatch(s)); } - public bool Exists(string productId) => GetFilePath(productId) != null; + public bool Exists(string productId) => GetFilePath(productId) is not null; } public class AudioFileStorage : AudibleFileStorage diff --git a/LibationFileManager/FilePathCache.cs b/LibationFileManager/FilePathCache.cs index 4359ef88..802864b8 100644 --- a/LibationFileManager/FilePathCache.cs +++ b/LibationFileManager/FilePathCache.cs @@ -42,7 +42,7 @@ namespace LibationFileManager } } - public static bool Exists(string id, FileType type) => GetFirstPath(id, type) != null; + public static bool Exists(string id, FileType type) => GetFirstPath(id, type) is not null; public static List<(FileType fileType, string path)> GetFiles(string id) => getEntries(entry => entry.Id == id) diff --git a/LibationFileManager/PictureStorage.cs b/LibationFileManager/PictureStorage.cs index 70cb9d59..868e4e33 100644 --- a/LibationFileManager/PictureStorage.cs +++ b/LibationFileManager/PictureStorage.cs @@ -70,7 +70,7 @@ namespace LibationFileManager { lock (cacheLocker) { - if (!cache.ContainsKey(def) || cache[def] == null) + if (!cache.ContainsKey(def) || cache[def] is null) { var path = getPath(def); var bytes diff --git a/LibationSearchEngine/LuceneExtensions.cs b/LibationSearchEngine/LuceneExtensions.cs index 020427d3..0a0c2071 100644 --- a/LibationSearchEngine/LuceneExtensions.cs +++ b/LibationSearchEngine/LuceneExtensions.cs @@ -16,7 +16,7 @@ namespace LibationSearchEngine internal static void AddAnalyzed(this Document document, string name, string value) { - if (value != null) + if (value is not null) document.Add(new Field(name.ToLowerInvariant(), value, Field.Store.YES, Field.Index.ANALYZED)); } diff --git a/LibationSearchEngine/SearchEngine.cs b/LibationSearchEngine/SearchEngine.cs index aead2f18..ac365a35 100644 --- a/LibationSearchEngine/SearchEngine.cs +++ b/LibationSearchEngine/SearchEngine.cs @@ -70,11 +70,11 @@ namespace LibationSearchEngine .Select(s => s.Series.AudibleSeriesId)), ["SeriesId"] = lb => string.Join(", ", lb.Book.SeriesLink.Select(s => s.Series.AudibleSeriesId)), - [nameof(Book.CategoriesNames)] = lb => lb.Book.CategoriesIds == null ? null : string.Join(", ", lb.Book.CategoriesIds), - [nameof(Book.Category)] = lb => lb.Book.CategoriesIds == null ? null : string.Join(", ", lb.Book.CategoriesIds), - ["Categories"] = lb => lb.Book.CategoriesIds == null ? null : string.Join(", ", lb.Book.CategoriesIds), - ["CategoriesId"] = lb => lb.Book.CategoriesIds == null ? null : string.Join(", ", lb.Book.CategoriesIds), - ["CategoryId"] = lb => lb.Book.CategoriesIds == null ? null : string.Join(", ", lb.Book.CategoriesIds), + [nameof(Book.CategoriesNames)] = lb => lb.Book.CategoriesIds is null ? null : string.Join(", ", lb.Book.CategoriesIds), + [nameof(Book.Category)] = lb => lb.Book.CategoriesIds is null ? null : string.Join(", ", lb.Book.CategoriesIds), + ["Categories"] = lb => lb.Book.CategoriesIds is null ? null : string.Join(", ", lb.Book.CategoriesIds), + ["CategoriesId"] = lb => lb.Book.CategoriesIds is null ? null : string.Join(", ", lb.Book.CategoriesIds), + ["CategoryId"] = lb => lb.Book.CategoriesIds is null ? null : string.Join(", ", lb.Book.CategoriesIds), [TAGS.FirstCharToUpper()] = lb => lb.Book.UserDefinedItem.Tags, @@ -314,7 +314,7 @@ namespace LibationSearchEngine var query = new TermQuery(productTerm); var docs = searcher.Search(query, 1); var scoreDoc = docs.ScoreDocs.SingleOrDefault(); - if (scoreDoc == null) + if (scoreDoc is null) return; var document = searcher.Doc(scoreDoc.Doc); diff --git a/LibationWinForms/Dialogs/IndexLibraryDialog.cs b/LibationWinForms/Dialogs/IndexLibraryDialog.cs index f674161d..ca30ecd8 100644 --- a/LibationWinForms/Dialogs/IndexLibraryDialog.cs +++ b/LibationWinForms/Dialogs/IndexLibraryDialog.cs @@ -22,7 +22,7 @@ namespace LibationWinForms.Dialogs private async void IndexLibraryDialog_Shown(object sender, EventArgs e) { - if (_accounts != null && _accounts.Length > 0) + if (_accounts is not null && _accounts.Length > 0) { this.label1.Text = (_accounts.Length == 1) diff --git a/LibationWinForms/Dialogs/RemoveBooksDialog.cs b/LibationWinForms/Dialogs/RemoveBooksDialog.cs index e3739c4f..f8c7edd0 100644 --- a/LibationWinForms/Dialogs/RemoveBooksDialog.cs +++ b/LibationWinForms/Dialogs/RemoveBooksDialog.cs @@ -58,7 +58,7 @@ namespace LibationWinForms.Dialogs private async void RemoveBooksDialog_Shown(object sender, EventArgs e) { - if (_accounts == null || _accounts.Length == 0) + if (_accounts is null || _accounts.Length == 0) return; try { diff --git a/LibationWinForms/Form1.cs b/LibationWinForms/Form1.cs index 8306ded9..a507d081 100644 --- a/LibationWinForms/Form1.cs +++ b/LibationWinForms/Form1.cs @@ -34,8 +34,6 @@ namespace LibationWinForms this.FormClosing += (_, _) => this.SaveSizeAndLocation(Configuration.Instance); LibraryCommands.LibrarySizeChanged += reloadGridAndUpdateBottomNumbers; LibraryCommands.BookUserDefinedItemCommitted += setBackupCounts; - // used by async migrations to update ui when complete - DataLayer.UserDefinedItem.Batch_ItemChanged += reloadGridAndUpdateBottomNumbers; var format = System.Drawing.Imaging.ImageFormat.Jpeg; PictureStorage.SetDefaultImage(PictureSize._80x80, Properties.Resources.default_cover_80x80.ToBytes(format)); @@ -71,22 +69,22 @@ namespace LibationWinForms } #region reload grid - private ProductsGrid currProductsGrid; + private ProductsGrid productsGrid; private void setGrid() { SuspendLayout(); { - if (currProductsGrid != null) + if (productsGrid != null) { - gridPanel.Controls.Remove(currProductsGrid); - currProductsGrid.VisibleCountChanged -= setVisibleCount; - currProductsGrid.Dispose(); + gridPanel.Controls.Remove(productsGrid); + productsGrid.VisibleCountChanged -= setVisibleCount; + productsGrid.Dispose(); } - currProductsGrid = new ProductsGrid { Dock = DockStyle.Fill }; - currProductsGrid.VisibleCountChanged += setVisibleCount; - gridPanel.UIThreadSync(() => gridPanel.Controls.Add(currProductsGrid)); - currProductsGrid.Display(); + productsGrid = new ProductsGrid { Dock = DockStyle.Fill }; + productsGrid.VisibleCountChanged += setVisibleCount; + gridPanel.UIThreadSync(() => gridPanel.Controls.Add(productsGrid)); + productsGrid.Display(); } ResumeLayout(); } @@ -214,12 +212,12 @@ namespace LibationWinForms } private void doFilter() { - if (isProcessingGridSelect || currProductsGrid == null) + if (isProcessingGridSelect || productsGrid is null) return; try { - currProductsGrid.Filter(filterSearchTb.Text); + productsGrid.Filter(filterSearchTb.Text); lastGoodFilter = filterSearchTb.Text; } catch (Exception ex) diff --git a/LibationWinForms/Program.cs b/LibationWinForms/Program.cs index 9b4af346..30343ac0 100644 --- a/LibationWinForms/Program.cs +++ b/LibationWinForms/Program.cs @@ -158,135 +158,11 @@ namespace LibationWinForms /// migrations which require Forms or are long-running private static void RunWindowsOnlyMigrations(Configuration config) { - // only supported in winforms. don't move to app scaffolding - migrate_to_v5_0_0(config); - - // long running. won't get a chance to finish in cli. don't move to app scaffolding - migrate_to_v5_5_0(config); + // examples: + // - only supported in winforms. don't move to app scaffolding + // - long running. won't get a chance to finish in cli. don't move to app scaffolding } - #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 (!File.Exists(AudibleApiStorage.AccountsSettingsFile)) - return; - - var accountsPersister = AudibleApiStorage.GetAccountsSettingsPersister(); - - var accounts = accountsPersister?.AccountsSettings?.Accounts; - if (accounts is null) - return; - - foreach (var account in accounts) - { - var identity = account?.IdentityTokens; - - if (identity is null) - continue; - - if (!string.IsNullOrWhiteSpace(identity.DeviceType) && - !string.IsNullOrWhiteSpace(identity.DeviceSerialNumber) && - !string.IsNullOrWhiteSpace(identity.AmazonAccountId)) - continue; - - var authorize = new Authorize(identity.Locale); - - try - { - authorize.DeregisterAsync(identity.ExistingAccessToken, identity.Cookies.ToKeyValuePair()).GetAwaiter().GetResult(); - identity.Invalidate(); - - // re-registers device - ApiExtended.CreateAsync(account, new Login.WinformLoginChoiceEager(account)).GetAwaiter().GetResult(); - } - catch - { - // Don't care if it fails - } - } - } - #endregion - - #region migrate to v5.5.0. FilePaths.json => db. long running. fire and forget - private static void migrate_to_v5_5_0(Configuration config) - => new System.Threading.Thread(() => migrate_to_v5_5_0_thread(config)) { IsBackground = true }.Start(); - private static void migrate_to_v5_5_0_thread(Configuration config) - { - try - { - var filePaths = Path.Combine(config.LibationFiles, "FilePaths.json"); - if (!File.Exists(filePaths)) - return; - - var fileLocations = Path.Combine(config.LibationFiles, "FileLocations.json"); - if (!File.Exists(fileLocations)) - File.Copy(filePaths, fileLocations); - - // files to be deleted at the end - var libhackFilesToDelete = new List(); - // .libhack files => errors - var libhackFiles = Directory.EnumerateDirectories(config.Books, "*.libhack", SearchOption.AllDirectories); - - using var context = ApplicationServices.DbContexts.GetContext(); - - var jArr = JArray.Parse(File.ReadAllText(filePaths)); - - foreach (var jToken in jArr) - { - var asinToken = jToken["Id"]; - var fileTypeToken = jToken["FileType"]; - var pathToken = jToken["Path"]; - if (asinToken is null || fileTypeToken is null || pathToken is null || - asinToken.Type != JTokenType.String || fileTypeToken.Type != JTokenType.Integer || pathToken.Type != JTokenType.String) - continue; - - var asin = asinToken.Value(); - var fileType = (FileType)fileTypeToken.Value(); - var path = pathToken.Value(); - - if (fileType == FileType.Unknown || fileType == FileType.AAXC) - continue; - - var book = context.Books.FirstOrDefault(b => b.AudibleProductId == asin); - if (book is null) - continue; - - // assign these strings and enums/ints unconditionally. EFCore will only update if changed - if (fileType == FileType.PDF) - book.UserDefinedItem.BatchMode_UpdatePdfStatus(LiberatedStatus.Liberated); - - if (fileType == FileType.Audio) - { - var lhack = libhackFiles.FirstOrDefault(f => f.ContainsInsensitive(asin)); - if (lhack is null) - book.UserDefinedItem.BatchMode_UpdateBookStatus(LiberatedStatus.Liberated); - else - { - book.UserDefinedItem.BatchMode_UpdateBookStatus(LiberatedStatus.Error); - libhackFilesToDelete.Add(lhack); - } - } - } - - // in order: save to db, full reindex from db, refresh ui - var changed = context.SaveChanges(); - if (changed > 0) - ApplicationServices.SearchEngineCommands.FullReIndex(); - UserDefinedItem.BatchMode_Finalize(); - - // only do this after save changes - foreach (var libhackFile in libhackFilesToDelete) - File.Delete(libhackFile); - - File.Delete(filePaths); - } - catch (Exception ex) - { - Log.Logger.Error(ex, "Error attempting to insert FilePaths into db"); - } - } - #endregion - private static void checkForUpdate() { string zipUrl; diff --git a/LibationWinForms/SyncBindingSource.cs b/LibationWinForms/SyncBindingSource.cs index 67091443..49c65eb3 100644 --- a/LibationWinForms/SyncBindingSource.cs +++ b/LibationWinForms/SyncBindingSource.cs @@ -19,7 +19,7 @@ namespace LibationWinForms protected override void OnListChanged(ListChangedEventArgs e) { - if (syncContext != null) + if (syncContext is not null) syncContext.Send(_ => base.OnListChanged(e), null); else base.OnListChanged(e); diff --git a/LibationWinForms/grid/ProductsGrid.cs b/LibationWinForms/grid/ProductsGrid.cs index ba02d430..ba83ca2d 100644 --- a/LibationWinForms/grid/ProductsGrid.cs +++ b/LibationWinForms/grid/ProductsGrid.cs @@ -110,7 +110,7 @@ namespace LibationWinForms private SortableBindingList bindingList; /// Insert ad hoc library books to top of grid - public void AddToTop(DataLayer.LibraryBook libraryBook) => bindingList.Insert(0, libraryBookToGridEntry(libraryBook)); + public void AddToTop(DataLayer.LibraryBook libraryBook) => bindingList.Insert(0, toGridEntry(libraryBook)); #region UI display functions @@ -135,7 +135,7 @@ namespace LibationWinForms } var orderedGridEntries = lib - .Select(lb => libraryBookToGridEntry(lb)) + .Select(lb => toGridEntry(lb)) // default load order .OrderByDescending(ge => (DateTime)ge.GetMemberValue(nameof(ge.PurchaseDate))) //// more advanced example: sort by author, then series, then title @@ -152,7 +152,7 @@ namespace LibationWinForms Filter(); } - private GridEntry libraryBookToGridEntry(DataLayer.LibraryBook libraryBook) + private GridEntry toGridEntry(DataLayer.LibraryBook libraryBook) { var entry = new GridEntry(libraryBook); entry.Committed += Filter;