diff --git a/Changelog.md b/Changelog.md index d39b145d..8b095c6b 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,5 +1,12 @@ # CHANGELOG - ## COMPASS v1.8.7 (27 May 2025) + ## COMPASS v1.8.8 (28 June 2025) + +### Fixes +- Fix crashes on commands in context menu when no items are selected. +- Fix potential crash when looking at the change logs in the settings +- Fix a crash when deleting a collection when a file is locked +- Fix an issue where the open collection was copied to the new data location after changing it +## COMPASS v1.8.7 (27 May 2025) ### Fixes diff --git a/Deployment/install.iss b/Deployment/install.iss index 66d1882a..90a2e90d 100644 --- a/Deployment/install.iss +++ b/Deployment/install.iss @@ -2,7 +2,7 @@ ; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES! #define MyAppName "COMPASS" -#define MyAppVersion "1.8.7" +#define MyAppVersion "1.8.8" #define MyAppPublisher "Paul De Smul" #define MyAppURL "https://www.compassapp.info" #define MyAppExeName "COMPASS.exe" diff --git a/src/COMPASS.csproj b/src/COMPASS.csproj index 14d18365..893df0a9 100644 --- a/src/COMPASS.csproj +++ b/src/COMPASS.csproj @@ -69,8 +69,8 @@ - - + + diff --git a/src/Models/CodexCollection.cs b/src/Models/CodexCollection.cs index c83e81c9..9d3c10da 100644 --- a/src/Models/CodexCollection.cs +++ b/src/Models/CodexCollection.cs @@ -254,7 +254,7 @@ public void Save() try { - Directory.CreateDirectory(UserFilesPath); + Directory.CreateDirectory(FullDataPath); } catch (Exception ex) { @@ -585,6 +585,8 @@ public void DeleteCodex(Codex toDelete) public void DeleteCodices(IList toDelete) { + if (!toDelete.Any()) return; + Notification deleteWarnNotification = Notification.AreYouSureNotification; deleteWarnNotification.Body = $"You are about to remove {toDelete.Count} item{(toDelete.Count > 1 ? @"s" : @"")}. " + $"This cannot be undone. " + @@ -604,7 +606,8 @@ public void DeleteCodices(IList toDelete) public void BanishCodices(IList toBanish) { - if (toBanish is null) return; + if (!toBanish.SafeAny()) return; + IEnumerable toBanishPaths = toBanish.Select(codex => codex.Sources.Path); IEnumerable toBanishURLs = toBanish.Select(codex => codex.Sources.SourceURL); IEnumerable toBanishStrings = toBanishPaths diff --git a/src/Models/CodexProperties/EnumerableProperty.cs b/src/Models/CodexProperties/EnumerableProperty.cs index 423224a2..c2ff0018 100644 --- a/src/Models/CodexProperties/EnumerableProperty.cs +++ b/src/Models/CodexProperties/EnumerableProperty.cs @@ -33,7 +33,7 @@ public override bool HasNewValue(IHasCodexMetadata toEvaluate, IHasCodexMetadata return true; } - return !newVal!.SequenceEqual(refVal); + return !newVal.SequenceEqual(refVal); } } } diff --git a/src/Properties/AssemblyInfo.cs b/src/Properties/AssemblyInfo.cs index d1d084b2..7d1b1b9d 100644 --- a/src/Properties/AssemblyInfo.cs +++ b/src/Properties/AssemblyInfo.cs @@ -40,7 +40,7 @@ // app, or any theme specific resource dictionaries) )] -[assembly: AssemblyVersion("1.8.7")] +[assembly: AssemblyVersion("1.8.8")] [assembly: System.Runtime.Versioning.SupportedOSPlatform("windows")] diff --git a/src/Services/CoverService.cs b/src/Services/CoverService.cs index 0dbc4ca2..510ee452 100644 --- a/src/Services/CoverService.cs +++ b/src/Services/CoverService.cs @@ -87,6 +87,8 @@ public static async Task GetCover(Codex codex, ChooseMetaDataViewModel? chooseMe public static async Task GetCover(List codices) { + if (!codices.Any()) return; + var progressVM = ProgressViewModel.GetInstance(); progressVM.ResetCounter(); progressVM.TotalAmount = codices.Count; diff --git a/src/Tools/ExtensionMethods.cs b/src/Tools/ExtensionMethods.cs index 47c81896..68c89770 100644 --- a/src/Tools/ExtensionMethods.cs +++ b/src/Tools/ExtensionMethods.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using System.Collections.ObjectModel; +using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.Linq; using System.Reflection; @@ -172,7 +173,7 @@ public static IEnumerable Flatten(this IEnumerable l, string method = " } } - public static bool SafeAny(this IEnumerable? l) => l is not null && l.Any(); + public static bool SafeAny([NotNullWhen(true)] this IEnumerable? l) => l is not null && l.Any(); #endregion } } diff --git a/src/Tools/Utils.cs b/src/Tools/Utils.cs index 467e3189..1fb42a43 100644 --- a/src/Tools/Utils.cs +++ b/src/Tools/Utils.cs @@ -1,6 +1,8 @@ using COMPASS.Models; +using System; using System.Collections.Generic; using System.Linq; +using System.Threading; namespace COMPASS.Tools { @@ -16,5 +18,28 @@ public static int GetAvailableID(IEnumerable collection) where T : IHasID } return tempID; } + + public static void Retry(int maxAttempts, Action action, int retryDelayMs = 1000, Action? onFailedAttempt = null) => + Retry(maxAttempts, action, retryDelayMs, onFailedAttempt); + public static void Retry(int maxAttempts, Action action, int retryDelayMs = 1000, Action? onFailedAttempt = null) where T : Exception + { + for (int i = 0; i < maxAttempts; i++) + { + try + { + action(); + return; + } + catch (T e) when (i < maxAttempts - 1) //failure in last attempt will not be caught by design + { + onFailedAttempt?.Invoke(e); + if (retryDelayMs > 0) + { + Thread.Sleep(retryDelayMs); + } + } + } + } + } } diff --git a/src/ViewModels/CodexViewModel.cs b/src/ViewModels/CodexViewModel.cs index cdcc6e3c..b16a18cd 100644 --- a/src/ViewModels/CodexViewModel.cs +++ b/src/ViewModels/CodexViewModel.cs @@ -108,7 +108,7 @@ public static bool CanOpenCodexOnline(Codex? toOpen) public RelayCommand OpenSelectedCodicesCommand => _openSelectedCodicesCommand ??= new(l => OpenSelectedCodices(l?.Cast().ToList())); public static bool OpenSelectedCodices(IList? toOpen) { - if (toOpen is null) return false; + if (!toOpen.SafeAny()) return false; if (toOpen.Count == 1) { @@ -152,7 +152,7 @@ public static void EditCodex(Codex? toEdit) public static void EditCodices(IList? toEdit) { List? toEditList = toEdit?.Cast().ToList(); - if (toEditList is null) return; + if (!toEditList.SafeAny()) return; if (toEditList.Count == 1) { @@ -186,7 +186,8 @@ public static void FavoriteCodex(Codex? toFavorite) private static void FavoriteCodices(IList? toFavorite) { List? toFavoriteList = toFavorite?.Cast().ToList(); - if (toFavoriteList is null) return; + if (!toFavoriteList.SafeAny()) return; + if (toFavoriteList.Count == 1) { FavoriteCodex(toFavoriteList.First()); @@ -247,6 +248,8 @@ public void MoveToCollection(object[]? par) /// public static void MoveToCollection(CodexCollection targetCollection, List toMoveList) { + if (!toMoveList.Any()) return; + //Check if target Collection is valid if (targetCollection.DirectoryName == MainViewModel.CollectionVM.CurrentCollection.DirectoryName) { @@ -324,6 +327,8 @@ public static void DeleteCodex(Codex? toDelete) public RelayCommand DeleteCodicesCommand => _deleteCodicesCommand ??= new(DeleteCodices); public static void DeleteCodices(IList? toDelete) { + if (toDelete == null || toDelete.Count == 0) return; + MainViewModel.CollectionVM.CurrentCollection.DeleteCodices(toDelete?.Cast().ToList() ?? new()); MainViewModel.CollectionVM.FilterVM.ReFilter(); } @@ -341,6 +346,8 @@ public static void DeleteCodices(IList? toDelete) public RelayCommand BanishCodicesCommand => _banishCodicesCommand ??= new(BanishCodices); public static void BanishCodices(IList? toBanish) { + if (toBanish == null || toBanish.Count == 0) return; + MainViewModel.CollectionVM.CurrentCollection.BanishCodices(toBanish?.Cast().ToList() ?? new()); DeleteCodices(toBanish); } @@ -362,6 +369,8 @@ public static async Task StartGetMetaDataProcess(Codex? codex) } public static async Task StartGetMetaDataProcess(IList codices) { + if (!codices.Any()) return; + var progressVM = ProgressViewModel.GetInstance(); progressVM.ResetCounter(); progressVM.Text = "Getting MetaData"; diff --git a/src/ViewModels/CollectionViewModel.cs b/src/ViewModels/CollectionViewModel.cs index 0594c591..33487f9e 100644 --- a/src/ViewModels/CollectionViewModel.cs +++ b/src/ViewModels/CollectionViewModel.cs @@ -379,9 +379,20 @@ public void DeleteCollection(CodexCollection toDelete) //if Dir name of toDelete is empty, it will delete the entire collections folder if (String.IsNullOrEmpty(toDelete.DirectoryName)) return; - if (Directory.Exists(toDelete.FullDataPath)) //does not exist if collection was never saved + + //possible that folder does not exist if collection was never saved + if (!Directory.Exists(toDelete.FullDataPath)) return; + + try + { + //sometimes delete fails because a file is locked, retry could help with that + Utils.Retry(3, () => Directory.Delete(toDelete.FullDataPath, true), + onFailedAttempt: (ex) => Logger.Warn($"Failed to delete collection {toDelete.DirectoryName}, retrying...", ex) + ); + } + catch (Exception ex) { - Directory.Delete(toDelete.FullDataPath, true); + Logger.Error($"Failed to delete collection {toDelete.DirectoryName}", ex); } } diff --git a/src/ViewModels/MainViewModel.cs b/src/ViewModels/MainViewModel.cs index 8596eb46..1bf07891 100644 --- a/src/ViewModels/MainViewModel.cs +++ b/src/ViewModels/MainViewModel.cs @@ -108,6 +108,8 @@ private void InitConnectionTimer() #region Properties + public static bool SaveOnClose { get; set; } = true; + private bool _isOnline; public bool IsOnline { diff --git a/src/ViewModels/SettingsViewModel.cs b/src/ViewModels/SettingsViewModel.cs index 3299d672..891b9de0 100644 --- a/src/ViewModels/SettingsViewModel.cs +++ b/src/ViewModels/SettingsViewModel.cs @@ -549,13 +549,19 @@ private async Task CopyToNewDataPath() /// public void ChangeToNewDataPath() { + //save stuff in old location MainViewModel.CollectionVM?.CurrentCollection.Save(); + PreferencesService.GetInstance().SavePreferences(); + //change location CompassDataPath = NewDataPath; Notification changeSuccessful = new("Data path changed succesfully", $"Data path was successfully changed to {CompassDataPath}. COMPASS will now restart."); App.Container.ResolveKeyed(NotificationDisplayType.Windowed).Show(changeSuccessful); + //Now that datapath has been changed, don't save on close because it would save to new location + MainViewModel.SaveOnClose = false; + //Restart COMPASS var currentExecutablePath = Environment.ProcessPath; var args = Environment.GetCommandLineArgs(); diff --git a/src/Windows/MainWindow.xaml.cs b/src/Windows/MainWindow.xaml.cs index 985cd47c..b853df3c 100644 --- a/src/Windows/MainWindow.xaml.cs +++ b/src/Windows/MainWindow.xaml.cs @@ -34,8 +34,11 @@ public MainWindow() private void Window_Closing(object sender, CancelEventArgs e) { ProgressViewModel.GetInstance().CancelBackgroundTask(); - MainViewModel.CollectionVM?.CurrentCollection.Save(); - PreferencesService.GetInstance().SavePreferences(); + if (MainViewModel.SaveOnClose) + { + MainViewModel.CollectionVM?.CurrentCollection.Save(); + PreferencesService.GetInstance().SavePreferences(); + } } #region Window management diff --git a/src/Windows/SettingsWindow.xaml.cs b/src/Windows/SettingsWindow.xaml.cs index 7e39acd3..a44ad1af 100644 --- a/src/Windows/SettingsWindow.xaml.cs +++ b/src/Windows/SettingsWindow.xaml.cs @@ -1,7 +1,9 @@ using COMPASS.Models; using COMPASS.Services; +using COMPASS.Tools; using COMPASS.ViewModels; using Microsoft.Web.WebView2.Core; +using System; using System.Diagnostics; using System.Windows; using System.Windows.Controls; @@ -47,19 +49,27 @@ private void Hyperlink_RequestNavigate(object sender, System.Windows.Navigation. public async void LoadChangeLog() { - string sHTML = "" + - "" + - "" + - "" + - "Changelog" + - "" + - "" + - "" + - "" + - ""; + try + { + string sHTML = "" + + "" + + "" + + "" + + "Changelog" + + "" + + "" + + "" + + "" + + ""; - await ChangelogWebView.EnsureCoreWebView2Async(await CoreWebView2Environment.CreateAsync(userDataFolder: VM.WebViewDataDir)); - ChangelogWebView.NavigateToString(sHTML); + var environment = await CoreWebView2Environment.CreateAsync(userDataFolder: VM.WebViewDataDir); + await ChangelogWebView.EnsureCoreWebView2Async(environment); + ChangelogWebView.NavigateToString(sHTML); + } + catch (Exception ex) + { + Logger.Error("failed to load changelog", ex); + } } private void SelectFolderForFolderTagPairButton_Click(object sender, RoutedEventArgs e) => NewFolderTagPairTextBox.Text = IOService.PickFolder(); diff --git a/versionInfo.xml b/versionInfo.xml index 68d0722d..f4d68cef 100644 --- a/versionInfo.xml +++ b/versionInfo.xml @@ -1,6 +1,6 @@ - 1.8.7 - https://github.com/DSPAUL/COMPASS/releases/download/v1.8.7/COMPASS_Setup_1.8.7.exe + 1.8.8 + https://github.com/DSPAUL/COMPASS/releases/download/v1.8.8/COMPASS_Setup_1.8.8.exe false