Exemple #1
0
    /// <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);
        }