internal async Task PasteFilesAsync()

in sources/Google.Solutions.Mvvm/Controls/FileBrowser.cs [674:785]


        internal async Task PasteFilesAsync(IDataObject dataObject)
        {
            Precondition.ExpectNotNull(this.fileSystem, nameof(this.fileSystem));
            Precondition.ExpectNotNull(this.navigationState, nameof(this.navigationState));

            Debug.Assert(this.currentDirectoryContents != null);
            Debug.Assert(this.currentDirectoryContents!.Count == this.fileList.Items.Count);

            var filesToCopy = GetPastableFiles(dataObject, true);
            if (!filesToCopy.Any())
            {
                return;
            }

            //
            // Show a progress dialog to track overall progress.
            //
            using (var progressDialog = this.ProgressDialog.StartCopyOperation(
                this,
                (ulong)filesToCopy.Count(),
                (ulong)filesToCopy.Sum(f => f.Length)))
            {
                var copyProgress = new Progress<int>(
                    delta => progressDialog.OnBytesCompleted((ulong)delta));

                foreach (var file in filesToCopy)
                {
                    if (progressDialog.CancellationToken.IsCancellationRequested)
                    {
                        break;
                    }

                    try
                    {
                        //
                        // Perform the file copy in the background.
                        //
                        // NB. If the underlying file system session is closed, 
                        //     we expect I/O operations to be cancelled.
                        //
                        await Task
                            .Run(async () =>
                                {
                                    using (var sourceStream = file.OpenRead())
                                    using (var targetStream = await this.fileSystem!
                                        .OpenFileAsync(
                                            this.navigationState!.Directory,
                                            file.Name,
                                            FileMode.Create,
                                            FileAccess.Write)
                                        .ConfigureAwait(false))
                                    {
                                        await sourceStream
                                            .CopyToAsync(
                                                targetStream,
                                                copyProgress,
                                                this.StreamCopyBufferSize,
                                                progressDialog.CancellationToken)
                                            .ConfigureAwait(false);
                                    }
                                })
                            .ConfigureAwait(true);
                    }
                    catch (Exception e) when (e.IsCancellation())
                    {
                        //
                        // Ignore, and don't touch the UI because
                        // it might no longer be in a good state.
                        //
                        return;
                    }
                    catch (Exception e)
                    {
                        //
                        // Update dialog to avoid a situation where the
                        // dialog still indicates that the copy is progressing
                        // while we're showing an error dialog at the same time.
                        //
                        progressDialog.IsBlockedByError = true;

                        var parameters = new TaskDialogParameters(
                            "Copy files",
                            $"Unable to copy {file.Name}",
                            e.Unwrap().Message)
                        {
                            Icon = TaskDialogIcon.Error
                        };

                        parameters.Buttons.Add(new TaskDialogCommandLinkButton(
                            "Skip this file",
                            DialogResult.Ignore));
                        parameters.Buttons.Add(TaskDialogStandardButton.Cancel);

                        if (this.TaskDialog.ShowDialog(this, parameters) 
                            == DialogResult.Cancel)
                        {
                            return;
                        }
                    }
                    finally
                    {
                        progressDialog.IsBlockedByError = false;
                        progressDialog.OnItemCompleted();
                    }
                }
            }

            //
            // Refresh as there might be some new files now.
            //
            await RefreshAsync().ConfigureAwait(true);
        }