| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497 | 
							- using ImageMagick;
 
- using PicView.Avalonia.ImageHandling;
 
- using PicView.Avalonia.Input;
 
- using PicView.Avalonia.UI;
 
- using PicView.Avalonia.ViewModels;
 
- using PicView.Core.ArchiveHandling;
 
- using PicView.Core.DebugTools;
 
- using PicView.Core.FileHandling;
 
- using PicView.Core.FileHistory;
 
- using PicView.Core.Gallery;
 
- using PicView.Core.Http;
 
- using PicView.Core.ImageDecoding;
 
- using PicView.Core.Localization;
 
- using PicView.Core.Navigation;
 
- namespace PicView.Avalonia.Navigation;
 
- public static class ImageLoader
 
- {
 
-     #region Load Pic From String
 
-     /// <summary>
 
-     ///     Loads a picture from a given string source, which can be a file path, directory path, or URL.
 
-     /// </summary>
 
-     public static async Task LoadPicFromStringAsync(string source, MainViewModel vm, ImageIterator imageIterator)
 
-     {
 
-         if (string.IsNullOrWhiteSpace(source) || vm is null)
 
-         {
 
-             return;
 
-         }
 
-         MenuManager.CloseMenus(vm);
 
-         vm.IsLoading = true;
 
-         TitleManager.SetLoadingTitle(vm);
 
-         // Starting in new task makes it more responsive and works better
 
-         await Task.Run(async () =>
 
-         {
 
-             var check = ErrorHelper.CheckIfLoadableString(source);
 
-             if (check == null)
 
-             {
 
-                 await ErrorHandling.ReloadAsync(vm).ConfigureAwait(false);
 
-                 vm.IsLoading = false;
 
-                 ArchiveExtraction.Cleanup();
 
-                 return;
 
-             }
 
-             switch (check.Value.Type)
 
-             {
 
-                 case ErrorHelper.LoadAbleFileType.File:
 
-                     vm.CurrentView = vm.ImageViewer;
 
-                     await LoadPicFromFile(check.Value.Data, vm, imageIterator).ConfigureAwait(false);
 
-                     vm.IsLoading = false;
 
-                     ArchiveExtraction.Cleanup();
 
-                     return;
 
-                 case ErrorHelper.LoadAbleFileType.Directory:
 
-                     vm.CurrentView = vm.ImageViewer;
 
-                     await LoadPicFromDirectoryAsync(check.Value.Data, vm).ConfigureAwait(false);
 
-                     vm.IsLoading = false;
 
-                     ArchiveExtraction.Cleanup();
 
-                     return;
 
-                 case ErrorHelper.LoadAbleFileType.Web:
 
-                     vm.CurrentView = vm.ImageViewer;
 
-                     await LoadPicFromUrlAsync(check.Value.Data, vm, imageIterator).ConfigureAwait(false);
 
-                     vm.IsLoading = false;
 
-                     ArchiveExtraction.Cleanup();
 
-                     return;
 
-                 case ErrorHelper.LoadAbleFileType.Base64:
 
-                     vm.CurrentView = vm.ImageViewer;
 
-                     await LoadPicFromBase64Async(check.Value.Data, vm, imageIterator).ConfigureAwait(false);
 
-                     vm.IsLoading = false;
 
-                     ArchiveExtraction.Cleanup();
 
-                     return;
 
-                 case ErrorHelper.LoadAbleFileType.Zip:
 
-                     vm.CurrentView = vm.ImageViewer;
 
-                     await LoadPicFromArchiveAsync(check.Value.Data, vm, imageIterator).ConfigureAwait(false);
 
-                     vm.IsLoading = false;
 
-                     return;
 
-                 default:
 
-                     await ErrorHandling.ReloadAsync(vm).ConfigureAwait(false);
 
-                     vm.IsLoading = false;
 
-                     ArchiveExtraction.Cleanup();
 
-                     return;
 
-             }
 
-         });
 
-     }
 
-     #endregion
 
-     #region Load Pic From File
 
-     /// <summary>
 
-     /// Loads an image from a specified file and manages navigation within the directory or recreates the iterator.
 
-     /// </summary>
 
-     /// <param name="fileName">The full path of the file to load.</param>
 
-     /// <param name="vm">The main view model instance associated with the application context.</param>
 
-     /// <param name="imageIterator">An iterator for navigating through images in the directory.</param>
 
-     /// <param name="fileInfo">Optional file information, defaults to a new <c>FileInfo</c> instance for the given file name if not provided.</param>
 
-     public static async Task LoadPicFromFile(string fileName, MainViewModel vm, ImageIterator imageIterator,
 
-         FileInfo? fileInfo = null)
 
-     {
 
-         fileInfo ??= new FileInfo(fileName);
 
-         if (!fileInfo.Exists)
 
-         {
 
-             return;
 
-         }
 
-         await CancelAsync().ConfigureAwait(false);
 
-         if (imageIterator is not null)
 
-         {
 
-             // If image is in same directory as is being browsed, navigate to it. Otherwise, load without iterator.
 
-             if (fileInfo.DirectoryName == imageIterator.InitialFileInfo.DirectoryName)
 
-             {
 
-                 var index = imageIterator.ImagePaths.IndexOf(fileInfo.FullName);
 
-                 if (index != -1)
 
-                 {
 
-                     await imageIterator.IterateToIndex(index, _cancellationTokenSource).ConfigureAwait(false);
 
-                     await NavigationManager.CheckIfTiffAndUpdate(vm, fileInfo, index);
 
-                     if (Settings.Gallery.IsBottomGalleryShown && NavigationManager.GetCount > 0)
 
-                     {
 
-                         vm.GalleryMode = GalleryMode.ClosedToBottom;
 
-                     }
 
-                 }
 
-                 else
 
-                 {
 
-                     await LoadWithoutIterator();
 
-                 }
 
-             }
 
-             else
 
-             {
 
-                 await LoadWithoutIterator();
 
-             }
 
-         }
 
-         else
 
-         {
 
-             await LoadWithoutIterator();
 
-         }
 
-         return;
 
-         async Task LoadWithoutIterator()
 
-         {
 
-             if (Settings.UIProperties.IsTaskbarProgressEnabled)
 
-             {
 
-                 vm.PlatformService.StopTaskbarProgress();
 
-             }
 
-             await NavigationManager.LoadWithoutImageIterator(fileInfo, vm).ConfigureAwait(false);
 
-         }
 
-     }
 
-     #endregion
 
-     #region Load Pic From Directory
 
-     /// <summary>
 
-     /// Loads a picture from a directory.
 
-     /// </summary>
 
-     /// <param name="file">The path to the directory containing the picture.</param>
 
-     /// <param name="vm">The main view model instance.</param>
 
-     /// <param name="fileInfo">Optional: FileInfo object for the directory.</param>
 
-     public static async Task LoadPicFromDirectoryAsync(string file, MainViewModel vm, FileInfo? fileInfo = null)
 
-     {
 
-         vm.IsLoading = true;
 
-         TitleManager.SetLoadingTitle(vm);
 
-         if (_cancellationTokenSource is not null)
 
-         {
 
-             await _cancellationTokenSource.CancelAsync().ConfigureAwait(false);
 
-         }
 
-         _cancellationTokenSource = new CancellationTokenSource();
 
-         if (Settings.UIProperties.IsTaskbarProgressEnabled)
 
-         {
 
-             vm.PlatformService.StopTaskbarProgress();
 
-         }
 
-         fileInfo ??= new FileInfo(file);
 
-         var newFileList = await Task.Run(() =>
 
-         {
 
-             var fileList = vm.PlatformService.GetFiles(fileInfo);
 
-             if (fileList.Count > 0)
 
-             {
 
-                 return fileList;
 
-             }
 
-             // Attempt to reload with subdirectories and reset the setting
 
-             if (Settings.Sorting.IncludeSubDirectories)
 
-             {
 
-                 return null;
 
-             }
 
-             Settings.Sorting.IncludeSubDirectories = true;
 
-             fileList = vm.PlatformService.GetFiles(fileInfo);
 
-             if (fileList.Count <= 0)
 
-             {
 
-                 return null;
 
-             }
 
-             Settings.Sorting.IncludeSubDirectories = false;
 
-             return fileList;
 
-         }).ConfigureAwait(false);
 
-         if (newFileList is null)
 
-         {
 
-             await ErrorHandling.ReloadAsync(vm).ConfigureAwait(false);
 
-             return;
 
-         }
 
-         var firstFileInfo = new FileInfo(newFileList[0]);
 
-         await NavigationManager.LoadWithoutImageIterator(firstFileInfo, vm, newFileList);
 
-     }
 
-     #endregion
 
-     #region Load Pic From Archive
 
-     /// <summary>
 
-     ///     Asynchronously loads pictures from the specified archive file.
 
-     /// </summary>
 
-     /// <param name="path">The path to the archive file containing the picture(s) to load.</param>
 
-     /// <param name="vm">The main view model instance used to manage UI state and operations.</param>
 
-     /// <param name="imageIterator">The image iterator to use for navigation.</param>
 
-     public static async Task LoadPicFromArchiveAsync(string path, MainViewModel vm, ImageIterator imageIterator)
 
-     {
 
-         if (_cancellationTokenSource is not null)
 
-         {
 
-             await _cancellationTokenSource.CancelAsync().ConfigureAwait(false);
 
-         }
 
-         vm.IsLoading = true;
 
-         TitleManager.SetLoadingTitle(vm);
 
-         string? prevArchiveLocation = null;
 
-         var previousArchiveExist = !string.IsNullOrEmpty(ArchiveExtraction.TempZipDirectory);
 
-         if (previousArchiveExist)
 
-         {
 
-             prevArchiveLocation = ArchiveExtraction.TempZipDirectory;
 
-         }
 
-         var extraction = await ArchiveExtraction
 
-             .ExtractArchiveAsync(path, vm.PlatformService.ExtractWithLocalSoftwareAsync).ConfigureAwait(false);
 
-         if (!extraction)
 
-         {
 
-             await ErrorHandling.ReloadAsync(vm);
 
-             Clean();
 
-             return;
 
-         }
 
-         if (Directory.Exists(ArchiveExtraction.TempZipDirectory))
 
-         {
 
-             var dirInfo = new DirectoryInfo(ArchiveExtraction.TempZipDirectory);
 
-             if (dirInfo.EnumerateDirectories().Any())
 
-             {
 
-                 var firstDir = dirInfo.EnumerateDirectories().First();
 
-                 var firstFile = firstDir.EnumerateFiles().First();
 
-                 await LoadPicFromFile(firstFile.FullName, vm, imageIterator, firstFile).ConfigureAwait(false);
 
-             }
 
-             else
 
-             {
 
-                 await LoadPicFromDirectoryAsync(ArchiveExtraction.TempZipDirectory, vm).ConfigureAwait(false);
 
-             }
 
-             FileHistoryManager.Add(path);
 
-             MainKeyboardShortcuts.ClearKeyDownModifiers(); // Fix possible modifier key state issue
 
-             if (previousArchiveExist)
 
-             {
 
-                 try
 
-                 {
 
-                     Directory.Delete(prevArchiveLocation, true);
 
-                 }
 
-                 catch (Exception e)
 
-                 {
 
-                     DebugHelper.LogDebug(nameof(ImageLoader), nameof(LoadPicFromArchiveAsync), e);
 
-                 }
 
-             }
 
-         }
 
-         else
 
-         {
 
-             await imageIterator.DisposeAsync();
 
-             await ErrorHandling.ReloadAsync(vm);
 
-             Clean();
 
-         }
 
-         
 
-         return;
 
-         void Clean()
 
-         {
 
-             TempFileHelper.DeleteTempFiles();
 
-             ArchiveExtraction.Cleanup();
 
-         }
 
-     }
 
-     #endregion
 
-     #region Load Pic From URL
 
-     /// <summary>
 
-     ///     Loads a picture from a given URL.
 
-     /// </summary>
 
-     /// <param name="url">The URL of the picture to load.</param>
 
-     /// <param name="vm">The main view model instance.</param>
 
-     /// <param name="imageIterator">The image iterator to use for navigation.</param>
 
-     public static async Task LoadPicFromUrlAsync(string url, MainViewModel vm, ImageIterator imageIterator)
 
-     {
 
-         var tasks = new List<Task>();
 
-         if (_cancellationTokenSource is not null)
 
-         {
 
-             tasks.Add(_cancellationTokenSource.CancelAsync());
 
-         }
 
-         string destination;
 
-         try
 
-         {
 
-             vm.PlatformService.StopTaskbarProgress();
 
-             var httpDownload = HttpManager.GetDownloadClient(url);
 
-             using var client = httpDownload.Client;
 
-             var fileName = Path.GetFileName(url);
 
-             client.ProgressChanged += (totalFileSize, totalBytesDownloaded, progressPercentage) =>
 
-             {
 
-                 if (totalFileSize is null || totalBytesDownloaded is null || progressPercentage is null)
 
-                 {
 
-                     return;
 
-                 }
 
-                 var displayProgress = HttpManager.GetProgressDisplay(totalFileSize, totalBytesDownloaded,
 
-                     progressPercentage);
 
-                 var title = $"{fileName} {TranslationManager.Translation.Downloading} {displayProgress}";
 
-                 vm.PicViewer.Title = title;
 
-                 vm.PicViewer.TitleTooltip = title;
 
-                 vm.PicViewer.WindowTitle = title;
 
-                 if (Settings.UIProperties.IsTaskbarProgressEnabled)
 
-                 {
 
-                     vm.PlatformService.SetTaskbarProgress((ulong)totalBytesDownloaded, (ulong)totalFileSize);
 
-                 }
 
-             };
 
-             tasks.Add(client.StartDownloadAsync());
 
-             if (imageIterator is not null)
 
-             {
 
-                 tasks.Add(imageIterator.DisposeAsync().AsTask());
 
-             }
 
-             await Task.WhenAll(tasks).ConfigureAwait(false);
 
-             destination = httpDownload.DownloadPath;
 
-         }
 
-         catch (Exception e)
 
-         {
 
-             DebugHelper.LogDebug(nameof(ImageLoader), nameof(LoadPicFromUrlAsync), e);
 
-             await ErrorHandling.ReloadAsync(vm);
 
-             await TooltipHelper.ShowTooltipMessageAsync(e.Message, true);
 
-             return;
 
-         }
 
-         var fileInfo = new FileInfo(destination);
 
-         if (!fileInfo.Exists)
 
-         {
 
-             await ErrorHandling.ReloadAsync(vm);
 
-             return;
 
-         }
 
-         var imageModel = await GetImageModel.GetImageModelAsync(fileInfo).ConfigureAwait(false);
 
-         await UpdateImage.SetSingleImageAsync(imageModel.Image, imageModel.ImageType, url, vm);
 
-         vm.IsLoading = false;
 
-         vm.PicViewer.FileInfo = fileInfo;
 
-         vm.PicViewer.ExifOrientation = imageModel.EXIFOrientation;
 
-         FileHistoryManager.Add(url);
 
-         await NavigationManager.DisposeImageIteratorAsync();
 
-         TempFileHelper.TempFilePath = destination;
 
-     }
 
-     #endregion
 
-     #region Load Pic From Base64
 
-     /// <summary>
 
-     ///     Loads a picture from a Base64-encoded string.
 
-     /// </summary>
 
-     /// <param name="base64">The Base64-encoded string representing the picture.</param>
 
-     /// <param name="vm">The main view model instance.</param>
 
-     /// <param name="imageIterator">The image iterator to use for navigation.</param>
 
-     public static async Task LoadPicFromBase64Async(string base64, MainViewModel vm, ImageIterator imageIterator)
 
-     {
 
-         TitleManager.SetLoadingTitle(vm);
 
-         vm.IsLoading = true;
 
-         vm.PicViewer.ImageSource = null;
 
-         vm.PicViewer.FileInfo = null;
 
-         if (_cancellationTokenSource is not null)
 
-         {
 
-             await _cancellationTokenSource.CancelAsync().ConfigureAwait(false);
 
-         }
 
-         await NavigationManager.DisposeImageIteratorAsync().ConfigureAwait(false);
 
-         await Task.Run(async () =>
 
-         {
 
-             try
 
-             {
 
-                 var magickImage = ImageDecoder.Base64ToMagickImage(base64);
 
-                 magickImage.Format = MagickFormat.Png;
 
-                 var bitmap = magickImage.ToWriteableBitmap();
 
-                 var imageModel = new ImageModel
 
-                 {
 
-                     Image = bitmap,
 
-                     PixelWidth = bitmap?.PixelSize.Width ?? 0,
 
-                     PixelHeight = bitmap?.PixelSize.Height ?? 0,
 
-                     ImageType = ImageType.Bitmap
 
-                 };
 
-                 await UpdateImage.SetSingleImageAsync(imageModel.Image, imageModel.ImageType,
 
-                     TranslationManager.Translation.Base64Image, vm);
 
-             }
 
-             catch (Exception e)
 
-             {
 
-                 DebugHelper.LogDebug(nameof(ImageLoader), nameof(LoadPicFromBase64Async), e);
 
-                 await imageIterator.DisposeAsync();
 
-                 await ErrorHandling.ReloadAsync(vm);
 
-             }
 
-         });
 
-         vm.IsLoading = false;
 
-     }
 
-     #endregion
 
-     #region Cancellation
 
-     private static CancellationTokenSource? _cancellationTokenSource;
 
-     public static void Cancel()
 
-     {
 
-         if (_cancellationTokenSource is not null)
 
-         {
 
-             _cancellationTokenSource.Cancel();
 
-             _cancellationTokenSource.Dispose();
 
-             _cancellationTokenSource = null;
 
-         }
 
-         _cancellationTokenSource = new CancellationTokenSource();
 
-     }
 
-     public static async Task CancelAsync()
 
-     {
 
-         if (_cancellationTokenSource is not null)
 
-         {
 
-             await _cancellationTokenSource.CancelAsync().ConfigureAwait(false);
 
-             _cancellationTokenSource.Dispose();
 
-             _cancellationTokenSource = null;
 
-         }
 
-         _cancellationTokenSource = new CancellationTokenSource();
 
-     }
 
-     #endregion
 
-     #region Image Iterator Loading
 
-     /// <inheritdoc cref="ImageIterator.NextIteration(NavigateTo, CancellationTokenSource)" />
 
-     public static async Task LastIterationAsync(ImageIterator imageIterator) =>
 
-         await imageIterator
 
-             .NextIteration(NavigateTo.Last, _cancellationTokenSource)
 
-             .ConfigureAwait(false);
 
-     /// <inheritdoc cref="ImageIterator.NextIteration(NavigateTo, CancellationTokenSource)" />
 
-     public static async Task FirstIterationAsync(ImageIterator imageIterator) =>
 
-         await imageIterator
 
-             .NextIteration(NavigateTo.First, _cancellationTokenSource)
 
-             .ConfigureAwait(false);
 
-     /// <summary>
 
-     ///     Checks if the previous iteration has been canceled and starts the iteration at the given index
 
-     /// </summary>
 
-     /// <param name="index">The index to iterate to.</param>
 
-     /// <param name="imageIterator">The ImageIterator instance.</param>
 
-     public static async Task CheckCancellationAndStartIterateToIndex(int index, ImageIterator imageIterator)
 
-     {
 
-         if (_cancellationTokenSource is not null)
 
-         {
 
-             await _cancellationTokenSource.CancelAsync().ConfigureAwait(false);
 
-         }
 
-         // Need to start in a new task. This makes it more responsive, since it can get laggy when loading large images
 
-         await Task.Run(async () =>
 
-         {
 
-             _cancellationTokenSource = new CancellationTokenSource();
 
-             await imageIterator.NextIteration(index, _cancellationTokenSource).ConfigureAwait(false);
 
-         }).ConfigureAwait(false);
 
-     }
 
-     #endregion
 
- }
 
 
  |