Example #1
0
        public virtual void ShareItem(RoutedEventArgs e)
        {
            DataTransferManager manager = DataTransferManager.GetForCurrentView();

            manager.DataRequested += new TypedEventHandler <DataTransferManager, DataRequestedEventArgs>(Manager_DataRequested);
            DataTransferManager.ShowShareUI(new ShareUIOptions
            {
                Theme = Enum.IsDefined(typeof(ShareUITheme), ThemeHelper.RootTheme.ToString()) ? (ShareUITheme)ThemeHelper.RootTheme : ShareUITheme.Default
            });

            async void Manager_DataRequested(DataTransferManager sender, DataRequestedEventArgs args)
            {
                DataRequestDeferral dataRequestDeferral = args.Request.GetDeferral();
                List <IStorageItem> items       = new List <IStorageItem>();
                DataRequest         dataRequest = args.Request;

                /*dataRequest.Data.Properties.Title = "Data Shared From Files";
                 * dataRequest.Data.Properties.Description = "The items you selected will be shared";*/

                foreach (ListedItem item in SlimContentPage.SelectedItems)
                {
                    if (item.IsShortcutItem)
                    {
                        if (item.IsLinkItem)
                        {
                            dataRequest.Data.Properties.Title       = string.Format("ShareDialogTitle".GetLocalized(), items.First().Name);
                            dataRequest.Data.Properties.Description = "ShareDialogSingleItemDescription".GetLocalized();
                            dataRequest.Data.SetWebLink(new Uri(((ShortcutItem)item).TargetPath));
                            dataRequestDeferral.Complete();
                            return;
                        }
                    }
                    else if (item.PrimaryItemAttribute == StorageItemTypes.Folder)
                    {
                        if (await StorageItemHelpers.ToStorageItem <StorageFolder>(item.ItemPath, associatedInstance) is StorageFolder folder)
                        {
                            items.Add(folder);
                        }
                    }
                    else
                    {
                        if (await StorageItemHelpers.ToStorageItem <StorageFile>(item.ItemPath, associatedInstance) is StorageFile file)
                        {
                            items.Add(file);
                        }
                    }
                }

                if (items.Count == 1)
                {
                    dataRequest.Data.Properties.Title       = string.Format("ShareDialogTitle".GetLocalized(), items.First().Name);
                    dataRequest.Data.Properties.Description = "ShareDialogSingleItemDescription".GetLocalized();
                }
                else if (items.Count == 0)
                {
                    dataRequest.FailWithDisplayText("ShareDialogFailMessage".GetLocalized());
                    dataRequestDeferral.Complete();
                    return;
                }
                else
                {
                    dataRequest.Data.Properties.Title = string.Format("ShareDialogTitleMultipleItems".GetLocalized(), items.Count,
                                                                      "ItemsCount.Text".GetLocalized());
                    dataRequest.Data.Properties.Description = "ShareDialogMultipleItemsDescription".GetLocalized();
                }

                dataRequest.Data.SetStorageItems(items);
                dataRequestDeferral.Complete();

                // TODO: Unhook the event somewhere
            }
        }
        public async Task <IStorageHistory> RenameAsync(IStorageItemWithPath source,
                                                        string newName,
                                                        NameCollisionOption collision,
                                                        IProgress <FileSystemStatusCode> errorCode,
                                                        CancellationToken cancellationToken)
        {
            if (Path.GetFileName(source.Path) == newName && collision == NameCollisionOption.FailIfExists)
            {
                errorCode?.Report(FileSystemStatusCode.AlreadyExists);
                return(null);
            }

            if (!string.IsNullOrWhiteSpace(newName) &&
                !FilesystemHelpers.ContainsRestrictedCharacters(newName) &&
                !FilesystemHelpers.ContainsRestrictedFileName(newName))
            {
                var renamed = await source.ToStorageItemResult(associatedInstance)
                              .OnSuccess(async(t) =>
                {
                    if (t.Name.Equals(newName, StringComparison.CurrentCultureIgnoreCase))
                    {
                        await t.RenameAsync(newName, NameCollisionOption.ReplaceExisting);
                    }
                    else
                    {
                        await t.RenameAsync(newName, collision);
                    }
                    return(t);
                });

                if (renamed)
                {
                    errorCode?.Report(FileSystemStatusCode.Success);
                    return(new StorageHistory(FileOperationType.Rename, source, renamed.Result.FromStorageItem()));
                }
                else if (renamed == FileSystemStatusCode.Unauthorized)
                {
                    // Try again with MoveFileFromApp
                    var destination = Path.Combine(Path.GetDirectoryName(source.Path), newName);
                    if (NativeFileOperationsHelper.MoveFileFromApp(source.Path, destination))
                    {
                        errorCode?.Report(FileSystemStatusCode.Success);
                        return(new StorageHistory(FileOperationType.Rename, source, StorageItemHelpers.FromPathAndType(destination, source.ItemType)));
                    }
                    else
                    {
                        Debug.WriteLine(System.Runtime.InteropServices.Marshal.GetLastWin32Error());
                    }
                }
                else if (renamed == FileSystemStatusCode.NotAFile || renamed == FileSystemStatusCode.NotAFolder)
                {
                    await DialogDisplayHelper.ShowDialogAsync("RenameError/NameInvalid/Title".GetLocalized(), "RenameError/NameInvalid/Text".GetLocalized());
                }
                else if (renamed == FileSystemStatusCode.NameTooLong)
                {
                    await DialogDisplayHelper.ShowDialogAsync("RenameError/TooLong/Title".GetLocalized(), "RenameError/TooLong/Text".GetLocalized());
                }
                else if (renamed == FileSystemStatusCode.InUse)
                {
                    // TODO: proper dialog, retry
                    await DialogDisplayHelper.ShowDialogAsync("FileInUseDeleteDialog/Title".GetLocalized(), "");
                }
                else if (renamed == FileSystemStatusCode.NotFound)
                {
                    await DialogDisplayHelper.ShowDialogAsync("RenameError/ItemDeleted/Title".GetLocalized(), "RenameError/ItemDeleted/Text".GetLocalized());
                }
                else if (renamed == FileSystemStatusCode.AlreadyExists)
                {
                    var ItemAlreadyExistsDialog = new ContentDialog()
                    {
                        Title               = "ItemAlreadyExistsDialogTitle".GetLocalized(),
                        Content             = "ItemAlreadyExistsDialogContent".GetLocalized(),
                        PrimaryButtonText   = "ItemAlreadyExistsDialogPrimaryButtonText".GetLocalized(),
                        SecondaryButtonText = "ItemAlreadyExistsDialogSecondaryButtonText".GetLocalized(),
                        CloseButtonText     = "ItemAlreadyExistsDialogCloseButtonText".GetLocalized()
                    };

                    if (Interacts.Interaction.IsAnyContentDialogOpen())
                    {
                        // Only a single ContentDialog can be open at any time.
                        return(null);
                    }
                    ContentDialogResult result = await ItemAlreadyExistsDialog.ShowAsync();

                    if (result == ContentDialogResult.Primary)
                    {
                        return(await RenameAsync(source, newName, NameCollisionOption.GenerateUniqueName, errorCode, cancellationToken));
                    }
                    else if (result == ContentDialogResult.Secondary)
                    {
                        return(await RenameAsync(source, newName, NameCollisionOption.ReplaceExisting, errorCode, cancellationToken));
                    }
                }
                errorCode?.Report(renamed);
            }

            return(null);
        }
        public async Task <IStorageHistory> RestoreFromTrashAsync(IStorageItemWithPath source,
                                                                  string destination,
                                                                  IProgress <float> progress,
                                                                  IProgress <FileSystemStatusCode> errorCode,
                                                                  CancellationToken cancellationToken)
        {
            FilesystemResult fsResult = FileSystemStatusCode.InProgress;

            errorCode?.Report(fsResult);

            if (source.ItemType == FilesystemItemType.Directory)
            {
                FilesystemResult <StorageFolder> sourceFolder = await associatedInstance.FilesystemViewModel.GetFolderFromPathAsync(source.Path);

                FilesystemResult <StorageFolder> destinationFolder = await associatedInstance.FilesystemViewModel.GetFolderFromPathAsync(Path.GetDirectoryName(destination));

                fsResult = sourceFolder.ErrorCode | destinationFolder.ErrorCode;
                errorCode?.Report(fsResult);

                if (fsResult)
                {
                    fsResult = await FilesystemTasks.Wrap(() =>
                    {
                        return(MoveDirectoryAsync(sourceFolder.Result,
                                                  destinationFolder.Result,
                                                  Path.GetFileName(destination),
                                                  CreationCollisionOption.FailIfExists,
                                                  true));
                    }); // TODO: we could use here FilesystemHelpers with registerHistory false?
                }
                errorCode?.Report(fsResult);
            }
            else
            {
                FilesystemResult <StorageFile> sourceFile = await associatedInstance.FilesystemViewModel.GetFileFromPathAsync(source.Path);

                FilesystemResult <StorageFolder> destinationFolder = await associatedInstance.FilesystemViewModel.GetFolderFromPathAsync(Path.GetDirectoryName(destination));

                fsResult = sourceFile.ErrorCode | destinationFolder.ErrorCode;
                errorCode?.Report(fsResult);

                if (fsResult)
                {
                    fsResult = await FilesystemTasks.Wrap(() =>
                    {
                        return(sourceFile.Result.MoveAsync(destinationFolder.Result,
                                                           Path.GetFileName(destination),
                                                           NameCollisionOption.GenerateUniqueName).AsTask());
                    });
                }
                else if (fsResult == FileSystemStatusCode.Unauthorized)
                {
                    // Try again with MoveFileFromApp
                    fsResult = (FilesystemResult)NativeFileOperationsHelper.MoveFileFromApp(source.Path, destination);
                }
                errorCode?.Report(fsResult);
            }

            if (fsResult)
            {
                // Recycle bin also stores a file starting with $I for each item
                string iFilePath = Path.Combine(Path.GetDirectoryName(source.Path), Path.GetFileName(source.Path).Replace("$R", "$I"));
                await associatedInstance.FilesystemViewModel.GetFileFromPathAsync(iFilePath)
                .OnSuccess(iFile => iFile.DeleteAsync().AsTask());
            }

            errorCode?.Report(fsResult);
            if (fsResult != FileSystemStatusCode.Success)
            {
                if (((FileSystemStatusCode)fsResult).HasFlag(FileSystemStatusCode.Unauthorized))
                {
                    await DialogDisplayHelper.ShowDialogAsync("AccessDeniedDeleteDialog/Title".GetLocalized(), "AccessDeniedDeleteDialog/Text".GetLocalized());
                }
                else if (((FileSystemStatusCode)fsResult).HasFlag(FileSystemStatusCode.Unauthorized))
                {
                    await DialogDisplayHelper.ShowDialogAsync("FileNotFoundDialog/Title".GetLocalized(), "FileNotFoundDialog/Text".GetLocalized());
                }
                else if (((FileSystemStatusCode)fsResult).HasFlag(FileSystemStatusCode.AlreadyExists))
                {
                    await DialogDisplayHelper.ShowDialogAsync("ItemAlreadyExistsDialogTitle".GetLocalized(), "ItemAlreadyExistsDialogContent".GetLocalized());
                }
            }

            return(new StorageHistory(FileOperationType.Restore, source, StorageItemHelpers.FromPathAndType(destination, source.ItemType)));
        }
Example #4
0
        public async void DecompressArchive()
        {
            StorageFile archive = await StorageItemHelpers.ToStorageItem <StorageFile>(associatedInstance.SlimContentPage.SelectedItem.ItemPath);

            if (archive != null)
            {
                DecompressArchiveDialog          decompressArchiveDialog    = new DecompressArchiveDialog();
                DecompressArchiveDialogViewModel decompressArchiveViewModel = new DecompressArchiveDialogViewModel(archive);
                decompressArchiveDialog.ViewModel = decompressArchiveViewModel;

                ContentDialogResult option = await decompressArchiveDialog.ShowAsync();

                if (option == ContentDialogResult.Primary)
                {
                    // Check if archive still exists
                    if (!StorageItemHelpers.Exists(archive.Path))
                    {
                        return;
                    }

                    CancellationTokenSource extractCancellation = new CancellationTokenSource();
                    PostedStatusBanner      banner = App.StatusCenterViewModel.PostOperationBanner(
                        string.Empty,
                        "ExtractingArchiveText".GetLocalized(),
                        0,
                        ReturnResult.InProgress,
                        FileOperationType.Extract,
                        extractCancellation);

                    StorageFolder destinationFolder     = decompressArchiveViewModel.DestinationFolder;
                    string        destinationFolderPath = decompressArchiveViewModel.DestinationFolderPath;

                    if (destinationFolder == null)
                    {
                        StorageFolder parentFolder = await StorageItemHelpers.ToStorageItem <StorageFolder>(Path.GetDirectoryName(archive.Path));

                        destinationFolder = await parentFolder.CreateFolderAsync(Path.GetFileName(destinationFolderPath), CreationCollisionOption.GenerateUniqueName);
                    }

                    Stopwatch sw = new Stopwatch();
                    sw.Start();

                    await ZipHelpers.ExtractArchive(archive, destinationFolder, banner.Progress, extractCancellation.Token);

                    sw.Stop();
                    banner.Remove();

                    if (sw.Elapsed.TotalSeconds >= 6)
                    {
                        App.StatusCenterViewModel.PostBanner(
                            "ExtractingCompleteText".GetLocalized(),
                            "ArchiveExtractionCompletedSuccessfullyText".GetLocalized(),
                            0,
                            ReturnResult.Success,
                            FileOperationType.Extract);
                    }

                    if (decompressArchiveViewModel.OpenDestinationFolderOnCompletion)
                    {
                        await NavigationHelpers.OpenPath(destinationFolderPath, associatedInstance, FilesystemItemType.Directory);
                    }
                }
            }
        }
        public async Task <IStorageHistory> DeleteAsync(IStorageItemWithPath source,
                                                        IProgress <float> progress,
                                                        IProgress <FileSystemStatusCode> errorCode,
                                                        bool permanently,
                                                        CancellationToken cancellationToken)
        {
            bool deleteFromRecycleBin = recycleBinHelpers.IsPathUnderRecycleBin(source.Path);

            FilesystemResult fsResult = FileSystemStatusCode.InProgress;

            errorCode?.Report(fsResult);
            progress?.Report(0.0f);

            if (source.ItemType == FilesystemItemType.File)
            {
                fsResult = await associatedInstance.FilesystemViewModel.GetFileFromPathAsync(source.Path)
                           .OnSuccess((t) => t.DeleteAsync(permanently ? StorageDeleteOption.PermanentDelete : StorageDeleteOption.Default).AsTask());
            }
            else if (source.ItemType == FilesystemItemType.Directory)
            {
                fsResult = await associatedInstance.FilesystemViewModel.GetFolderFromPathAsync(source.Path)
                           .OnSuccess((t) => t.DeleteAsync(permanently ? StorageDeleteOption.PermanentDelete : StorageDeleteOption.Default).AsTask());
            }

            errorCode?.Report(fsResult);

            if (fsResult == FileSystemStatusCode.Unauthorized)
            {
                // Try again with fulltrust process
                if (associatedInstance.FilesystemViewModel.Connection != null)
                {
                    AppServiceResponse response = await associatedInstance.FilesystemViewModel.Connection.SendMessageAsync(new ValueSet()
                    {
                        { "Arguments", "FileOperation" },
                        { "fileop", "DeleteItem" },
                        { "filepath", source.Path },
                        { "permanently", permanently }
                    });

                    fsResult = (FilesystemResult)(response.Status == AppServiceResponseStatus.Success &&
                                                  response.Message.Get("Success", false));
                }
            }
            else if (fsResult == FileSystemStatusCode.InUse)
            {
                // TODO: retry or show dialog
                await DialogDisplayHelper.ShowDialogAsync("FileInUseDeleteDialog/Title".GetLocalized(), "FileInUseDeleteDialog/Text".GetLocalized());
            }

            if (deleteFromRecycleBin)
            {
                // Recycle bin also stores a file starting with $I for each item
                string iFilePath = Path.Combine(Path.GetDirectoryName(source.Path), Path.GetFileName(source.Path).Replace("$R", "$I"));
                await associatedInstance.FilesystemViewModel.GetFileFromPathAsync(iFilePath)
                .OnSuccess(t => t.DeleteAsync(StorageDeleteOption.PermanentDelete).AsTask());
            }
            errorCode?.Report(fsResult);
            progress?.Report(100.0f);

            if (fsResult)
            {
                await associatedInstance.FilesystemViewModel.RemoveFileOrFolderAsync(source.Path);

                if (!permanently)
                {
                    // Enumerate Recycle Bin
                    List <ShellFileItem> items = await recycleBinHelpers.EnumerateRecycleBin();

                    List <ShellFileItem> nameMatchItems = new List <ShellFileItem>();

                    // Get name matching files
                    if (items != null)
                    {
                        if (Path.GetExtension(source.Path) == ".lnk" || Path.GetExtension(source.Path) == ".url") // We need to check if it is a shortcut file
                        {
                            nameMatchItems = items.Where((item) => item.FilePath == Path.Combine(Path.GetDirectoryName(source.Path), Path.GetFileNameWithoutExtension(source.Path))).ToList();
                        }
                        else
                        {
                            nameMatchItems = items.Where((item) => item.FilePath == source.Path).ToList();
                        }
                    }

                    // Get newest file
                    ShellFileItem item = nameMatchItems.Where((item) => item.RecycleDate != null).OrderBy((item) => item.RecycleDate).FirstOrDefault();

                    return(new StorageHistory(FileOperationType.Recycle, source, StorageItemHelpers.FromPathAndType(item?.RecyclePath, source.ItemType)));
                }

                return(new StorageHistory(FileOperationType.Delete, source, null));
            }
            else
            {
                // Stop at first error
                return(null);
            }
        }
        private async Task <string> GetHashForFileAsync(ListedItem fileItem, string nameOfAlg, CancellationToken token, IProgress <float> progress, IShellPage associatedInstance)
        {
            HashAlgorithmProvider algorithmProvider = HashAlgorithmProvider.OpenAlgorithm(nameOfAlg);
            BaseStorageFile       file = await StorageItemHelpers.ToStorageItem <BaseStorageFile>((fileItem as ShortcutItem)?.TargetPath ?? fileItem.ItemPath, associatedInstance);

            if (file == null)
            {
                return("");
            }

            Stream stream = await FilesystemTasks.Wrap(() => file.OpenStreamForReadAsync());

            if (stream == null)
            {
                return("");
            }

            uint capacity;
            var  inputStream         = stream.AsInputStream();
            bool isProgressSupported = false;

            try
            {
                var cap = (long)(0.5 * stream.Length) / 100;
                if (cap >= uint.MaxValue)
                {
                    capacity = uint.MaxValue;
                }
                else
                {
                    capacity = Convert.ToUInt32(cap);
                }
                isProgressSupported = true;
            }
            catch (NotSupportedException)
            {
                capacity = 64 * 1024;
            }

            Windows.Storage.Streams.Buffer buffer = new Windows.Storage.Streams.Buffer(capacity);
            var hash = algorithmProvider.CreateHash();

            while (!token.IsCancellationRequested)
            {
                await inputStream.ReadAsync(buffer, capacity, InputStreamOptions.None);

                if (buffer.Length > 0)
                {
                    hash.Append(buffer);
                }
                else
                {
                    break;
                }
                if (stream.Length > 0)
                {
                    progress?.Report(isProgressSupported ? (float)stream.Position / stream.Length * 100.0f : 20);
                }
            }
            inputStream.Dispose();
            stream.Dispose();
            if (token.IsCancellationRequested)
            {
                return("");
            }
            return(CryptographicBuffer.EncodeToHexString(hash.GetValueAndReset()).ToLower());
        }
Example #7
0
        public virtual async void DeleteItem(RoutedEventArgs e)
        {
            var items = await Task.Run(() => SlimContentPage.SelectedItems.ToList().Select((item) => StorageItemHelpers.FromPathAndType(
                                                                                               item.ItemPath,
                                                                                               item.PrimaryItemAttribute == StorageItemTypes.File ? FilesystemItemType.File : FilesystemItemType.Directory)));

            await FilesystemHelpers.DeleteItemsAsync(items, true, false, true);
        }
        public async Task <IStorageHistory> CopyItemsAsync(IEnumerable <IStorageItemWithPath> source, IEnumerable <string> destination, IEnumerable <FileNameConflictResolveOptionType> collisions, IProgress <float> progress, IProgress <FileSystemStatusCode> errorCode, CancellationToken cancellationToken)
        {
            var connection = await AppServiceConnectionHelper.Instance;

            if (connection == null || source.Any(x => string.IsNullOrWhiteSpace(x.Path) || x.Path.StartsWith(@"\\?\")) || destination.Any(x => string.IsNullOrWhiteSpace(x) || x.StartsWith(@"\\?\") || FtpHelpers.IsFtpPath(x)))
            {
                // Fallback to builtin file operations
                return(await filesystemOperations.CopyItemsAsync(source, destination, collisions, progress, errorCode, cancellationToken));
            }

            source      = source.Where((src, index) => collisions.ElementAt(index) != FileNameConflictResolveOptionType.Skip).ToList();
            destination = destination.Where((src, index) => collisions.ElementAt(index) != FileNameConflictResolveOptionType.Skip).ToList();
            collisions  = collisions.Where(c => c != FileNameConflictResolveOptionType.Skip).ToList();

            var operationID = Guid.NewGuid().ToString();

            using var r = cancellationToken.Register(CancelOperation, operationID, false);

            EventHandler <Dictionary <string, object> > handler = (s, e) => OnProgressUpdated(s, e, operationID, progress);

            connection.RequestReceived += handler;

            var sourceReplace      = source.Where((src, index) => collisions.ElementAt(index) == FileNameConflictResolveOptionType.ReplaceExisting);
            var destinationReplace = destination.Where((src, index) => collisions.ElementAt(index) == FileNameConflictResolveOptionType.ReplaceExisting);
            var sourceRename       = source.Where((src, index) => collisions.ElementAt(index) != FileNameConflictResolveOptionType.ReplaceExisting);
            var destinationRename  = destination.Where((src, index) => collisions.ElementAt(index) != FileNameConflictResolveOptionType.ReplaceExisting);

            var result     = (FilesystemResult)true;
            var copyResult = new ShellOperationResult();

            if (sourceRename.Any())
            {
                var(status, response) = await connection.SendMessageForResponseAsync(new ValueSet()
                {
                    { "Arguments", "FileOperation" },
                    { "fileop", "CopyItem" },
                    { "operationID", operationID },
                    { "filepath", string.Join('|', sourceRename.Select(s => s.Path)) },
                    { "destpath", string.Join('|', destinationRename) },
                    { "overwrite", false },
                    { "HWND", NativeWinApiHelper.CoreWindowHandle.ToInt64() }
                });

                result &= (FilesystemResult)(status == AppServiceResponseStatus.Success &&
                                             response.Get("Success", false));
                var shellOpResult = JsonConvert.DeserializeObject <ShellOperationResult>(response.Get("Result", ""));
                copyResult.Items.AddRange(shellOpResult?.Items ?? Enumerable.Empty <ShellOperationItemResult>());
            }
            if (sourceReplace.Any())
            {
                var(status, response) = await connection.SendMessageForResponseAsync(new ValueSet()
                {
                    { "Arguments", "FileOperation" },
                    { "fileop", "CopyItem" },
                    { "operationID", operationID },
                    { "filepath", string.Join('|', sourceReplace.Select(s => s.Path)) },
                    { "destpath", string.Join('|', destinationReplace) },
                    { "overwrite", true },
                    { "HWND", NativeWinApiHelper.CoreWindowHandle.ToInt64() }
                });

                result &= (FilesystemResult)(status == AppServiceResponseStatus.Success &&
                                             response.Get("Success", false));
                var shellOpResult = JsonConvert.DeserializeObject <ShellOperationResult>(response.Get("Result", ""));
                copyResult.Items.AddRange(shellOpResult?.Items ?? Enumerable.Empty <ShellOperationItemResult>());
            }

            if (connection != null)
            {
                connection.RequestReceived -= handler;
            }

            result &= (FilesystemResult)copyResult.Items.All(x => x.Succeeded);

            if (result)
            {
                progress?.Report(100.0f);
                errorCode?.Report(FileSystemStatusCode.Success);
                var copiedSources = copyResult.Items.Where(x => sourceRename.Select(s => s.Path).Contains(x.Source)).Where(x => x.Succeeded && x.Destination != null && x.Source != x.Destination);
                if (copiedSources.Any())
                {
                    return(new StorageHistory(FileOperationType.Copy, copiedSources.Select(x => sourceRename.Single(s => s.Path == x.Source)),
                                              copiedSources.Select(item => StorageItemHelpers.FromPathAndType(item.Destination, sourceRename.Single(s => s.Path == item.Source).ItemType))));
                }
                return(null); // Cannot undo overwrite operation
            }
            else
            {
                // Retry failed operations
                var failedSources = copyResult.Items.Where(x => source.Select(s => s.Path).Contains(x.Source)).Where(x => !x.Succeeded);
                var copyZip       = source.Zip(destination, (src, dest) => new { src, dest }).Zip(collisions, (z1, coll) => new { z1.src, z1.dest, coll });
                return(await filesystemOperations.CopyItemsAsync(
                           failedSources.Select(x => copyZip.Single(s => s.src.Path == x.Source).src),
                           failedSources.Select(x => copyZip.Single(s => s.src.Path == x.Source).dest),
                           failedSources.Select(x => copyZip.Single(s => s.src.Path == x.Source).coll), progress, errorCode, cancellationToken));
            }
        }
        public async Task <IStorageHistory> RestoreFromTrashAsync(IStorageItemWithPath source, string destination, IProgress <float> progress, IProgress <FileSystemStatusCode> errorCode, CancellationToken cancellationToken)
        {
            var connection = await AppServiceConnectionHelper.Instance;

            if (connection == null || string.IsNullOrWhiteSpace(source.Path) || source.Path.StartsWith(@"\\?\") || string.IsNullOrWhiteSpace(destination) || destination.StartsWith(@"\\?\") || FtpHelpers.IsFtpPath(destination))
            {
                // Fallback to builtin file operations
                return(await filesystemOperations.RestoreFromTrashAsync(source, destination, progress, errorCode, cancellationToken));
            }

            var operationID = Guid.NewGuid().ToString();

            using var r = cancellationToken.Register(CancelOperation, operationID, false);

            EventHandler <Dictionary <string, object> > handler = (s, e) => OnProgressUpdated(s, e, operationID, progress);

            connection.RequestReceived += handler;

            var moveResult = new ShellOperationResult();

            var(status, response) = await connection.SendMessageForResponseAsync(new ValueSet()
            {
                { "Arguments", "FileOperation" },
                { "fileop", "MoveItem" },
                { "operationID", operationID },
                { "filepath", source.Path },
                { "destpath", destination },
                { "overwrite", false },
                { "HWND", NativeWinApiHelper.CoreWindowHandle.ToInt64() }
            });

            var result = (FilesystemResult)(status == AppServiceResponseStatus.Success &&
                                            response.Get("Success", false));
            var shellOpResult = JsonConvert.DeserializeObject <ShellOperationResult>(response.Get("Result", ""));

            moveResult.Items.AddRange(shellOpResult?.Items ?? Enumerable.Empty <ShellOperationItemResult>());

            if (connection != null)
            {
                connection.RequestReceived -= handler;
            }

            result &= (FilesystemResult)moveResult.Items.All(x => x.Succeeded);

            if (result)
            {
                progress?.Report(100.0f);
                errorCode?.Report(FileSystemStatusCode.Success);
                var movedSources = moveResult.Items.Where(x => new[] { source }.Select(s => s.Path).Contains(x.Source)).Where(x => x.Succeeded && x.Destination != null && x.Source != x.Destination);
                if (movedSources.Any())
                {
                    // Recycle bin also stores a file starting with $I for each item
                    await DeleteItemsAsync(movedSources.Select(src => StorageItemHelpers.FromPathAndType(
                                                                   Path.Combine(Path.GetDirectoryName(src.Source), Path.GetFileName(src.Source).Replace("$R", "$I")),
                                                                   new[] { source }.Single(s => s.Path == src.Source).ItemType)), null, null, true, cancellationToken);

                    return(new StorageHistory(FileOperationType.Restore, source,
                                              StorageItemHelpers.FromPathAndType(movedSources.Single().Destination, source.ItemType)));
                }
                return(null); // Cannot undo overwrite operation
            }
            else
            {
                // Retry failed operations
                return(await filesystemOperations.RestoreFromTrashAsync(source, destination, progress, errorCode, cancellationToken));
            }
        }
 public async Task <IStorageHistory> RenameAsync(IStorageItem source, string newName, NameCollisionOption collision, IProgress <FileSystemStatusCode> errorCode, CancellationToken cancellationToken)
 {
     return(await RenameAsync(StorageItemHelpers.FromStorageItem(source), newName, collision, errorCode, cancellationToken));
 }
        public async Task <IStorageHistory> DeleteItemsAsync(IEnumerable <IStorageItemWithPath> source, IProgress <float> progress, IProgress <FileSystemStatusCode> errorCode, bool permanently, CancellationToken cancellationToken)
        {
            var connection = await AppServiceConnectionHelper.Instance;

            if (connection == null || source.Any(x => string.IsNullOrWhiteSpace(x.Path) || x.Path.StartsWith(@"\\?\") || FtpHelpers.IsFtpPath(x.Path)))
            {
                // Fallback to builtin file operations
                return(await filesystemOperations.DeleteItemsAsync(source, progress, errorCode, permanently, cancellationToken));
            }

            source = source.DistinctBy(x => x.Path); // #5771
            var deleleFilePaths = source.Select(s => s.Path);

            var deleteFromRecycleBin = source.Any() ? recycleBinHelpers.IsPathUnderRecycleBin(source.ElementAt(0).Path) : false;

            permanently |= deleteFromRecycleBin;

            if (deleteFromRecycleBin)
            {
                // Recycle bin also stores a file starting with $I for each item
                deleleFilePaths = deleleFilePaths.Concat(source.Select(x => Path.Combine(Path.GetDirectoryName(x.Path), Path.GetFileName(x.Path).Replace("$R", "$I")))).Distinct();
            }

            var operationID = Guid.NewGuid().ToString();

            using var r = cancellationToken.Register(CancelOperation, operationID, false);

            EventHandler <Dictionary <string, object> > handler = (s, e) => OnProgressUpdated(s, e, operationID, progress);

            connection.RequestReceived += handler;

            var deleteResult = new ShellOperationResult();

            var(status, response) = await connection.SendMessageForResponseAsync(new ValueSet()
            {
                { "Arguments", "FileOperation" },
                { "fileop", "DeleteItem" },
                { "operationID", operationID },
                { "filepath", string.Join('|', deleleFilePaths) },
                { "permanently", permanently },
                { "HWND", NativeWinApiHelper.CoreWindowHandle.ToInt64() }
            });

            var result = (FilesystemResult)(status == AppServiceResponseStatus.Success &&
                                            response.Get("Success", false));
            var shellOpResult = JsonConvert.DeserializeObject <ShellOperationResult>(response.Get("Result", ""));

            deleteResult.Items.AddRange(shellOpResult?.Items ?? Enumerable.Empty <ShellOperationItemResult>());

            if (connection != null)
            {
                connection.RequestReceived -= handler;
            }

            result &= (FilesystemResult)deleteResult.Items.All(x => x.Succeeded);

            if (result)
            {
                progress?.Report(100.0f);
                errorCode?.Report(FileSystemStatusCode.Success);
                foreach (var item in deleteResult.Items)
                {
                    await associatedInstance.FilesystemViewModel.RemoveFileOrFolderAsync(item.Source);
                }
                var recycledSources = deleteResult.Items.Where(x => source.Select(s => s.Path).Contains(x.Source)).Where(x => x.Succeeded && x.Destination != null && x.Source != x.Destination);
                if (recycledSources.Any())
                {
                    return(new StorageHistory(FileOperationType.Recycle, recycledSources.Select(x => source.Single(s => s.Path == x.Source)),
                                              recycledSources.Select(item => StorageItemHelpers.FromPathAndType(item.Destination, source.Single(s => s.Path == item.Source).ItemType))));
                }
                return(new StorageHistory(FileOperationType.Delete, source, null));
            }
            else
            {
                // Retry failed operations
                var failedSources = deleteResult.Items.Where(x => source.Select(s => s.Path).Contains(x.Source))
                                    .Where(x => !x.Succeeded && x.HRresult != HRESULT.COPYENGINE_E_USER_CANCELLED && x.HRresult != HRESULT.COPYENGINE_E_RECYCLE_BIN_NOT_FOUND);
                return(await filesystemOperations.DeleteItemsAsync(
                           failedSources.Select(x => source.Single(s => s.Path == x.Source)), progress, errorCode, permanently, cancellationToken));
            }
        }
Example #12
0
        public async Task <IStorageHistory> RenameAsync(IStorageItemWithPath source,
                                                        string newName,
                                                        NameCollisionOption collision,
                                                        IProgress <FilesystemErrorCode> errorCode,
                                                        CancellationToken cancellationToken)
        {
            if (Path.GetFileName(source.Path) == newName && collision == NameCollisionOption.FailIfExists)
            {
                errorCode?.Report(FilesystemErrorCode.ERROR_ALREADYEXIST);
                return(null);
            }

            if (!string.IsNullOrWhiteSpace(newName) &&
                !FilesystemHelpers.ContainsRestrictedCharacters(newName) &&
                !FilesystemHelpers.ContainsRestrictedFileName(newName))
            {
                var renamed = await source.ToStorageItemResult(associatedInstance)
                              .OnSuccess(async(t) =>
                {
                    await t.RenameAsync(newName, collision);
                    return(t);
                });

                if (renamed)
                {
                    errorCode?.Report(FilesystemErrorCode.ERROR_SUCCESS);
                    return(new StorageHistory(FileOperationType.Rename, source, renamed.Result.FromStorageItem()));
                }
                else if (renamed == FilesystemErrorCode.ERROR_UNAUTHORIZED)
                {
                    // Try again with MoveFileFromApp
                    var destination = Path.Combine(Path.GetDirectoryName(source.Path), newName);
                    if (NativeFileOperationsHelper.MoveFileFromApp(source.Path, destination))
                    {
                        errorCode?.Report(FilesystemErrorCode.ERROR_SUCCESS);
                        return(new StorageHistory(FileOperationType.Rename, source, StorageItemHelpers.FromPathAndType(destination, source.ItemType)));
                    }
                    else
                    {
                        Debug.WriteLine(System.Runtime.InteropServices.Marshal.GetLastWin32Error());
                    }
                }
                else if (renamed == FilesystemErrorCode.ERROR_NOTAFILE || renamed == FilesystemErrorCode.ERROR_NOTAFOLDER)
                {
                    await DialogDisplayHelper.ShowDialogAsync("RenameError/NameInvalid/Title".GetLocalized(), "RenameError/NameInvalid/Text".GetLocalized());
                }
                else if (renamed == FilesystemErrorCode.ERROR_NAMETOOLONG)
                {
                    await DialogDisplayHelper.ShowDialogAsync("RenameError/TooLong/Title".GetLocalized(), "RenameError/TooLong/Text".GetLocalized());
                }
                else if (renamed == FilesystemErrorCode.ERROR_INUSE)
                {
                    // TODO: proper dialog, retry
                    await DialogDisplayHelper.ShowDialogAsync("FileInUseDeleteDialog/Title".GetLocalized(), "");
                }
                else if (renamed == FilesystemErrorCode.ERROR_NOTFOUND)
                {
                    await DialogDisplayHelper.ShowDialogAsync("RenameError/ItemDeleted/Title".GetLocalized(), "RenameError/ItemDeleted/Text".GetLocalized());
                }
                else if (renamed == FilesystemErrorCode.ERROR_ALREADYEXIST)
                {
                    var ItemAlreadyExistsDialog = new ContentDialog()
                    {
                        Title               = "ItemAlreadyExistsDialogTitle".GetLocalized(),
                        Content             = "ItemAlreadyExistsDialogContent".GetLocalized(),
                        PrimaryButtonText   = "ItemAlreadyExistsDialogPrimaryButtonText".GetLocalized(),
                        SecondaryButtonText = "ItemAlreadyExistsDialogSecondaryButtonText".GetLocalized(),
                        CloseButtonText     = "ItemAlreadyExistsDialogCloseButtonText".GetLocalized()
                    };

                    ContentDialogResult result = await ItemAlreadyExistsDialog.ShowAsync();

                    if (result == ContentDialogResult.Primary)
                    {
                        return(await RenameAsync(source, newName, NameCollisionOption.GenerateUniqueName, errorCode, cancellationToken));
                    }
                    else if (result == ContentDialogResult.Secondary)
                    {
                        return(await RenameAsync(source, newName, NameCollisionOption.ReplaceExisting, errorCode, cancellationToken));
                    }
                }
                errorCode?.Report(renamed);
            }

            return(null);
        }