public override void Dispose() { // Cancel refreshing thumbnails ExplorerDialogViewModel.CancelRefreshingThumbnails = true; // Dispose base class base.Dispose(); // Dispose the stream ArchiveFileStream?.Dispose(); // Dispose every directory ClearAndDisposeItems(); // Dispose the generator ArchiveFileGenerator?.Dispose(); RL.Logger?.LogInformationSource($"The archive {DisplayName} has been disposed"); }
/// <summary> /// Disposes the archive and its folders and files /// </summary> public override void Dispose() { // Cancel refreshing thumbnails ExplorerDialogViewModel.CancelInitializeFiles = true; // Dispose base class base.Dispose(); // Dispose the stream ArchiveFileStream.Dispose(); // Dispose every directory ClearAndDisposeItems(); // Dispose the generator ArchiveFileGenerator?.Dispose(); // Dispose the cache ThumbnailCache.Dispose(); Logger.Info("The archive {0} has been disposed", DisplayName); }
/// <summary> /// Saves any pending changes to the archive and reloads it /// </summary> /// <returns>The task</returns> public async Task SaveAsync() { Logger.Info("The archive {0} is being repacked", DisplayName); // Run as a load operation using (await Archive.LoadOperation.RunAsync()) { // Lock the access to the archive using (await Archive.ArchiveLock.LockAsync()) { // Find the selected item path string?selectedDirAddr = ExplorerDialogViewModel.SelectedDir == null ? null : ExplorerDialogViewModel.GetDirectoryAddress(ExplorerDialogViewModel.SelectedDir); // Run as a task await Task.Run(async() => { // Stop file initialization if (ExplorerDialogViewModel.IsInitializingFiles) { ExplorerDialogViewModel.CancelInitializeFiles = true; } Archive.SetDisplayStatus(String.Format(Resources.Archive_RepackingStatus, DisplayName)); try { // Get a temporary file path to write to using TempFile tempOutputFile = new(false); // Create the file and get the stream using (ArchiveFileStream outputStream = new(File.Create(tempOutputFile.TempPath), tempOutputFile.TempPath.Name, true)) { // Write to the stream Manager.WriteArchive( generator: ArchiveFileGenerator, archive: ArchiveData ?? throw new Exception("Archive data has not been loaded"), outputFileStream: outputStream, files: this.GetAllChildren <ArchiveDirectoryViewModel>(true). SelectMany(x => x.Files). Select(x => x.FileData). ToArray()); } // Dispose the archive file stream ArchiveFileStream.Dispose(); ArchiveData = null; // If the operation succeeded, replace the archive file with the temporary output Services.File.MoveFile(tempOutputFile.TempPath, FilePath, true); // Re-open the file stream OpenFile(); } catch (Exception ex) { Logger.Error(ex, "Repacking archive {0}", DisplayName); await Services.MessageUI.DisplayExceptionMessageAsync(ex, Resources.Archive_RepackError); // Re-open the file stream if closed if (ArchiveFileStream.SafeFileHandle?.IsClosed != false) { OpenFile(); } } }); // Reload the archive LoadArchive(); // Load the previously selected directory if it still exists if (selectedDirAddr != null) { ExplorerDialogViewModel.LoadDirectory(selectedDirAddr); } Archive.SetDisplayStatus(String.Empty); } } }
/// <summary> /// Updates the archive with the pending imports /// </summary> /// <param name="modifiedImportData">The import data for the files which have been modified</param> /// <returns>A value indicating if the updating succeeded</returns> public async Task <bool> UpdateArchiveAsync(IEnumerable <ArchiveImportData> modifiedImportData) { RL.Logger?.LogInformationSource($"The archive {DisplayName} is being updated"); // Stop refreshing thumbnails if (ExplorerDialogViewModel.IsRefreshingThumbnails) { ExplorerDialogViewModel.CancelRefreshingThumbnails = true; } Archive.SetDisplayStatus(String.Format(Resources.Archive_RepackingStatus, DisplayName)); // Find the selected item ID var selected = SelectedItem.FullID; // Flag for if the update succeeded var succeeded = false; try { // Get a temporary file path to write to using var tempOutputFile = new TempFile(false); // Create the file and get the stream using (var outputStream = File.Create(tempOutputFile.TempPath)) { // Get the modified files var modified = modifiedImportData.ToArray(); // Get the non-modified files var origFiles = this. // Get all directories GetAllChildren <ArchiveDirectoryViewModel>(true). // Get the files SelectMany(x => x.Files). // Get the file data Select(x => x.FileData). // Make sure the file isn't one of the modified ones Where(x => modified.All(y => y.FileEntryData != x.FileEntryData)). // Get the import data Select(x => (IArchiveImportData) new ArchiveImportData(x.FileEntryData, file => x.GetEncodedFileBytes(ArchiveFileStream, ArchiveFileGenerator))); // Update the archive Manager.UpdateArchive(ArchiveData, outputStream, modified.Concat(origFiles)); } // Dispose the archive file stream ArchiveFileStream.Dispose(); ArchiveData = null; ArchiveFileStream = null; // If the operation succeeded, replace the archive file with the temporary output RCPServices.File.MoveFile(tempOutputFile.TempPath, FilePath, true); // Re-open the file stream ArchiveFileStream = new FileStream(FilePath, FileMode.Open, FileAccess.ReadWrite, FileShare.Read); succeeded = true; } catch (Exception ex) { ex.HandleError("Repacking archive", DisplayName); await WPF.Services.MessageUI.DisplayExceptionMessageAsync(ex, Resources.Archive_RepackError); // Re-open the file stream if closed if (ArchiveFileStream == null) { ArchiveFileStream = new FileStream(FilePath, FileMode.Open, FileAccess.ReadWrite, FileShare.Read); } } // Reload the archive LoadArchive(); // Get the previously selected item var previouslySelectedItem = this.GetAllChildren <ArchiveDirectoryViewModel>(true).FindItem(x => x.FullID.SequenceEqual(selected)); // Expand the parent items var parent = previouslySelectedItem; while (parent != null) { parent.IsExpanded = true; parent = parent.Parent; } // If the item is selected, simply reload the thumbnails, but without awaiting it if (previouslySelectedItem.IsSelected) { // Run async without awaiting _ = ExplorerDialogViewModel.ChangeLoadedDirAsync(null, previouslySelectedItem); } // Otherwise select the item and let the thumbnails get automatically reloaded else { previouslySelectedItem.IsSelected = true; } Archive.SetDisplayStatus(String.Empty); return(succeeded); }