Browse Source

Duplication navigation fix and preloading refactor, xml doc

Ruben 9 months ago
parent
commit
88c10ed2c4

+ 7 - 2
src/PicView.Avalonia/Navigation/ImageIterator.cs

@@ -320,7 +320,7 @@ public sealed class ImageIterator : IDisposable
 
     public async Task Preload()
     {
-        await PreLoader.PreLoadAsync(CurrentIndex, ImagePaths.Count, IsReversed, ImagePaths).ConfigureAwait(false);
+        await PreLoader.PreLoadAsync(CurrentIndex, IsReversed, ImagePaths).ConfigureAwait(false);
     }
 
     public async Task AddAsync(int index, ImageModel imageModel)
@@ -370,6 +370,11 @@ public sealed class ImageIterator : IDisposable
         PreLoader.Remove(CurrentIndex, ImagePaths);
     }
 
+    public void RefreshAllFileInfo()
+    {
+        PreLoader.RefreshAllFileInfo(ImagePaths);
+    }
+
     #endregion
 
     #region Navigation
@@ -556,7 +561,7 @@ public sealed class ImageIterator : IDisposable
                         });
                     }
 
-                    await PreLoader.PreLoadAsync(CurrentIndex, ImagePaths.Count, IsReversed, ImagePaths)
+                    await PreLoader.PreLoadAsync(CurrentIndex, IsReversed, ImagePaths)
                         .ConfigureAwait(false);
                 }
 

+ 17 - 0
src/PicView.Avalonia/Navigation/NavigationHelper.cs

@@ -12,6 +12,7 @@ using PicView.Avalonia.ViewModels;
 using PicView.Avalonia.WindowBehavior;
 using PicView.Core.ArchiveHandling;
 using PicView.Core.Config;
+using PicView.Core.FileHandling;
 using PicView.Core.Gallery;
 using PicView.Core.ImageDecoding;
 using PicView.Core.Localization;
@@ -230,6 +231,22 @@ public static class NavigationHelper
         }
     }
 
+    public static async Task DuplicateAndNavigate(MainViewModel vm)
+    {
+        if (!CanNavigate(vm))
+        {
+            return;
+        }
+        var oldPath = vm.FileInfo.FullName;
+        var newPath = await Task.FromResult(FileHelper.DuplicateAndReturnFileName(oldPath)).ConfigureAwait(false);
+        if (File.Exists(newPath))
+        {
+            // Refresh preloader to not load cached image at same index
+            vm.ImageIterator.RefreshAllFileInfo();
+            await LoadPicFromFile(newPath, vm);
+        }
+    }
+
     #endregion
 
     #region Load pictures from string, file or url

+ 66 - 4
src/PicView.Avalonia/Preloading/Preloader.cs

@@ -7,6 +7,9 @@ using static System.GC;
 
 namespace PicView.Avalonia.Preloading;
 
+/// <summary>
+/// The PreLoader class is responsible for preloading images asynchronously and caching them.
+/// </summary>
 public sealed class PreLoader : IAsyncDisposable
 {
     
@@ -19,9 +22,23 @@ public sealed class PreLoader : IAsyncDisposable
     private readonly PreLoaderConfig _config = new();
 
     private readonly ConcurrentDictionary<int, PreLoadValue> _preLoadList = new();
+    /// <summary>
+    /// Indicates whether the preloader is currently running.
+    /// </summary>
     public static bool IsRunning { get; private set; }
+
+    /// <summary>
+    /// Gets the maximum count of preloaded images.
+    /// </summary>
     public static int MaxCount => PreLoaderConfig.MaxCount;
 
+    /// <summary>
+    /// Adds an image to the preload list asynchronously.
+    /// </summary>
+    /// <param name="index">The index of the image in the list.</param>
+    /// <param name="list">The list of image paths.</param>
+    /// <param name="imageModel">Optional image model to be added.</param>
+    /// <returns>True if the image was added successfully; otherwise, false.</returns>
     public async Task<bool> AddAsync(int index, List<string> list, ImageModel? imageModel = null)
     {
         if (list == null)
@@ -98,6 +115,12 @@ public sealed class PreLoader : IAsyncDisposable
         return false;
     }
 
+    /// <summary>
+    /// Refreshes the file information for a specific image in the preload list asynchronously.
+    /// </summary>
+    /// <param name="index">The index of the image in the list.</param>
+    /// <param name="list">The list of image paths.</param>
+    /// <returns>True if the image was refreshed successfully; otherwise, false.</returns>
     public async Task<bool> RefreshFileInfo(int index, List<string> list)
     {
         if (list == null)
@@ -131,6 +154,11 @@ public sealed class PreLoader : IAsyncDisposable
         return removed;
     }
 
+    
+    /// <summary>
+    /// Refreshes the file information for all images in the preload list.
+    /// </summary>
+    /// <param name="list">The list of image paths.</param>
     public void RefreshAllFileInfo(List<string> list)
     {
         try
@@ -158,7 +186,7 @@ public sealed class PreLoader : IAsyncDisposable
     }
 
     /// <summary>
-    /// Removes all keys from the cache.
+    /// Clears all preloaded images from the cache.
     /// </summary>
     public void Clear()
     {
@@ -173,6 +201,12 @@ public sealed class PreLoader : IAsyncDisposable
         _preLoadList.Clear();
     }
 
+    /// <summary>
+    /// Gets the preloaded value for a specific key.
+    /// </summary>
+    /// <param name="key">The key of the preloaded value.</param>
+    /// <param name="list">The list of image paths.</param>
+    /// <returns>The preloaded value if it exists; otherwise, null.</returns>
     public PreLoadValue? Get(int key, List<string> list)
     {
         if (list == null)
@@ -194,6 +228,13 @@ public sealed class PreLoader : IAsyncDisposable
         return !Contains(key, list) ? null : _preLoadList[key];
     }
 
+
+    /// <summary>
+    /// Gets the preloaded value for a specific key asynchronously.
+    /// </summary>
+    /// <param name="key">The key of the preloaded value.</param>
+    /// <param name="list">The list of image paths.</param>
+    /// <returns>The preloaded value if it exists; otherwise, null.</returns>
     public async Task<PreLoadValue?> GetAsync(int key, List<string> list)
     {
         if (list == null)
@@ -221,6 +262,12 @@ public sealed class PreLoader : IAsyncDisposable
         return Get(key, list);
     }
 
+    /// <summary>
+    /// Checks if a specific key exists in the preload list.
+    /// </summary>
+    /// <param name="key">The key to check.</param>
+    /// <param name="list">The list of image paths.</param>
+    /// <returns>True if the key exists; otherwise, false.</returns>
     public bool Contains(int key, List<string> list)
     {
         if (list == null)
@@ -242,6 +289,13 @@ public sealed class PreLoader : IAsyncDisposable
         return _preLoadList.ContainsKey(key);
     }
 
+    
+    /// <summary>
+    /// Removes a specific key from the preload list.
+    /// </summary>
+    /// <param name="key">The key to remove.</param>
+    /// <param name="list">The list of image paths.</param>
+    /// <returns>True if the key was removed; otherwise, false.</returns>
     public bool Remove(int key, List<string> list)
     {
         if (list == null)
@@ -297,14 +351,20 @@ public sealed class PreLoader : IAsyncDisposable
         }
     }
 
-    public async Task PreLoadAsync(int currentIndex, int count, bool reverse, List<string> list)
+    /// <summary>
+    /// Preloads images asynchronously.
+    /// </summary>
+    /// <param name="currentIndex">The current index of the image.</param>
+    /// <param name="reverse">Indicates whether to preload in reverse order.</param>
+    /// <param name="list">The list of image paths.</param>
+    public async Task PreLoadAsync(int currentIndex, bool reverse, List<string> list)
     {
         using var cts = new CancellationTokenSource();
         cts.CancelAfter(TimeSpan.FromMinutes(5));
 
         try
         {
-            await PreLoadInternalAsync(currentIndex, count, reverse, list, cts.Token);
+            await PreLoadInternalAsync(currentIndex, reverse, list, cts.Token);
         }
         catch (OperationCanceledException)
         {
@@ -318,7 +378,7 @@ public sealed class PreLoader : IAsyncDisposable
         }
     }
 
-    private async Task PreLoadInternalAsync(int currentIndex, int count, bool reverse, List<string> list, CancellationToken token)
+    private async Task PreLoadInternalAsync(int currentIndex, bool reverse, List<string> list, CancellationToken token)
     {
         if (list == null)
         {
@@ -334,6 +394,8 @@ public sealed class PreLoader : IAsyncDisposable
         }
 
         IsRunning = true;
+        
+        var count = list.Count;
 
         int nextStartingIndex, prevStartingIndex;
         if (reverse)

+ 1 - 10
src/PicView.Avalonia/UI/FunctionsHelper.cs

@@ -668,16 +668,7 @@ public static class FunctionsHelper
 
     public static async Task DuplicateFile()
     {
-        if (!NavigationHelper.CanNavigate(Vm))
-        {
-            return;
-        }
-        var oldPath = Vm.FileInfo.FullName;
-        var newPath = FileHelper.DuplicateAndReturnFileName(oldPath);
-        if (File.Exists(newPath))
-        {
-            await NavigationHelper.LoadPicFromFile(newPath, Vm);
-        }
+        await NavigationHelper.DuplicateAndNavigate(Vm).ConfigureAwait(false);
     }
 
     public static async Task CutFile()