Пример #1
0
        public async Task <IStorageHistory> MoveAsync(IStorageItemWithPath source,
                                                      string destination,
                                                      IProgress <float> progress,
                                                      IProgress <FilesystemErrorCode> errorCode,
                                                      CancellationToken cancellationToken)
        {
            if (source.Path == destination)
            {
                progress?.Report(100.0f);
                errorCode?.Report(FilesystemErrorCode.ERROR_SUCCESS);
                return(null);
            }

            IStorageHistory history = await CopyAsync(source, destination, progress, errorCode, cancellationToken);

            if (history == null)
            {
                // If copy was not performed we don't continue to delete to prevent data loss
                return(null);
            }

            if (string.IsNullOrWhiteSpace(source.Path))
            {
                // Can't move (only copy) files from MTP devices because:
                // StorageItems returned in DataPackageView are read-only
                // The item.Path property will be empty and there's no way of retrieving a new StorageItem with R/W access
                errorCode?.Report(FilesystemErrorCode.ERROR_SUCCESS | FilesystemErrorCode.ERROR_INPROGRESS);
            }

            await DeleteAsync(source, progress, errorCode, true, cancellationToken);

            progress?.Report(100.0f);

            return(new StorageHistory(FileOperationType.Move, history.Source, history.Destination));
        }
Пример #2
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))
            {
                try
                {
                    IStorageItem itemToRename = await source.ToStorageItem(associatedInstance);

                    await itemToRename.RenameAsync(newName, collision);

                    errorCode?.Report(FilesystemErrorCode.ERROR_SUCCESS);
                    return(new StorageHistory(FileOperationType.Rename, source, itemToRename.FromStorageItem()));
                }
                catch (Exception e)
                {
                    errorCode?.Report(FilesystemTasks.GetErrorCode(e));
                    return(null);
                }
            }

            return(null);
        }
Пример #3
0
        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(@"\\?\"))
            {
                // Fallback to builtin file operations
                return(await filesystemOperations.RestoreFromTrashAsync(source, destination, progress, errorCode, cancellationToken));
            }

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

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

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

            connection.RequestReceived += handler;

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

            var result = (FilesystemResult)(status == AppServiceResponseStatus.Success &&
                                            response.Get("Success", false));

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

            if (result)
            {
                progress?.Report(100.0f);
                var movedItems = JsonConvert.DeserializeObject <IEnumerable <string> >(response["MovedItems"] as string);
                errorCode?.Report(FileSystemStatusCode.Success);
                if (movedItems != null && movedItems.Count() == 1)
                {
                    // Recycle bin also stores a file starting with $I for each item
                    await DeleteAsync(StorageItemHelpers.FromPathAndType(
                                          Path.Combine(Path.GetDirectoryName(source.Path), Path.GetFileName(source.Path).Replace("$R", "$I")), source.ItemType),
                                      null, null, true, cancellationToken);

                    return(new StorageHistory(FileOperationType.Restore, source,
                                              StorageItemHelpers.FromPathAndType(movedItems.Single(), source.ItemType)));
                }
                return(null); // Cannot undo overwrite operation
            }
            else
            {
                // Retry failed operations
                return(await filesystemOperations.RestoreFromTrashAsync(source, destination, progress, errorCode, cancellationToken));
            }
        }
Пример #4
0
        public async Task <(IStorageHistory, IStorageItem)> CreateAsync(IStorageItemWithPath source, IProgress <FileSystemStatusCode> errorCode, CancellationToken cancellationToken)
        {
            IStorageItem item = null;

            try
            {
                switch (source.ItemType)
                {
                case FilesystemItemType.File:
                {
                    var newEntryInfo = await RegistryHelper.GetNewContextMenuEntryForType(Path.GetExtension(source.Path));

                    if (newEntryInfo == null)
                    {
                        StorageFolder folder = await associatedInstance.FilesystemViewModel.GetFolderFromPathAsync(Path.GetDirectoryName(source.Path));

                        item = await folder.CreateFileAsync(Path.GetFileName(source.Path));
                    }
                    else
                    {
                        item = (await newEntryInfo.Create(source.Path, associatedInstance)).Result;
                    }

                    break;
                }

                case FilesystemItemType.Directory:
                {
                    StorageFolder folder = await associatedInstance.FilesystemViewModel.GetFolderFromPathAsync(Path.GetDirectoryName(source.Path));

                    item = await folder.CreateFolderAsync(Path.GetFileName(source.Path));

                    break;
                }

                case FilesystemItemType.Symlink:
                {
                    Debugger.Break();
                    throw new NotImplementedException();
                }

                default:
                    Debugger.Break();
                    break;
                }

                errorCode?.Report(FileSystemStatusCode.Success);
                return(new StorageHistory(FileOperationType.CreateNew, source.CreateEnumerable(), null), item);
            }
            catch (Exception e)
            {
                errorCode?.Report(FilesystemTasks.GetErrorCode(e));
                return(null, null);
            }
        }
Пример #5
0
        public async Task <IStorageHistory> RenameAsync(IStorageItemWithPath source, string newName, NameCollisionOption collision, IProgress <FileSystemStatusCode> errorCode, CancellationToken cancellationToken)
        {
            var connection = await AppServiceConnectionHelper.Instance;

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

            var renameResult = new ShellOperationResult();

            var(status, response) = await connection.SendMessageForResponseAsync(new ValueSet()
            {
                { "Arguments", "FileOperation" },
                { "fileop", "RenameItem" },
                { "operationID", Guid.NewGuid().ToString() },
                { "filepath", source.Path },
                { "newName", newName },
                { "overwrite", collision == NameCollisionOption.ReplaceExisting }
            });

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

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

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

            if (result)
            {
                errorCode?.Report(FileSystemStatusCode.Success);
                var renamedSources = renameResult.Items.Where(x => x.Succeeded && x.Destination != null && x.Source != x.Destination)
                                     .Where(x => new[] { source }.Select(s => s.Path).Contains(x.Source));
                if (renamedSources.Any())
                {
                    return(new StorageHistory(FileOperationType.Rename, source,
                                              StorageHelpers.FromPathAndType(renamedSources.Single().Destination, source.ItemType)));
                }
                return(null); // Cannot undo overwrite operation
            }
            else
            {
                // Retry failed operations
                return(await filesystemOperations.RenameAsync(source, newName, collision, errorCode, cancellationToken));
            }
        }
Пример #6
0
        public async Task <ReturnResult> CreateAsync(IStorageItemWithPath source, bool registerHistory)
        {
            FilesystemErrorCode            returnCode = FilesystemErrorCode.ERROR_INPROGRESS;
            Progress <FilesystemErrorCode> errorCode  = new Progress <FilesystemErrorCode>();

            errorCode.ProgressChanged += (s, e) => returnCode = e;

            IStorageHistory history = await filesystemOperations.CreateAsync(source, errorCode, cancellationToken);

            if (registerHistory && !string.IsNullOrWhiteSpace(source.Path))
            {
                App.HistoryWrapper.AddHistory(history);
            }

            return(returnCode.ToStatus());
        }
Пример #7
0
        public async Task <ReturnResult> RestoreFromTrashAsync(IStorageItemWithPath source, string destination, bool registerHistory)
        {
            var returnCode = FileSystemStatusCode.InProgress;
            var errorCode  = new Progress <FileSystemStatusCode>();

            errorCode.ProgressChanged += (s, e) => returnCode = e;

            IStorageHistory history = await filesystemOperations.RestoreFromTrashAsync(source, destination, null, errorCode, cancellationToken);

            if (registerHistory && !string.IsNullOrWhiteSpace(source.Path))
            {
                App.HistoryWrapper.AddHistory(history);
            }

            return(returnCode.ToStatus());
        }
Пример #8
0
        public async Task <(ReturnResult, IStorageItem)> CreateAsync(IStorageItemWithPath source, bool registerHistory)
        {
            var returnCode = FileSystemStatusCode.InProgress;
            var errorCode  = new Progress <FileSystemStatusCode>();

            errorCode.ProgressChanged += (s, e) => returnCode = e;

            var result = await filesystemOperations.CreateAsync(source, errorCode, cancellationToken);

            if (registerHistory && !string.IsNullOrWhiteSpace(source.Path))
            {
                App.HistoryWrapper.AddHistory(result.Item1);
            }

            return(returnCode.ToStatus(), result.Item2);
        }
Пример #9
0
 public static async Task <IStorageItem> ToStorageItem(this IStorageItemWithPath item, IShellPage associatedInstance = null)
 {
     if (item.Item != null)
     {
         return(item.Item);
     }
     if (!string.IsNullOrEmpty(item.Path))
     {
         return((item.ItemType == FilesystemItemType.File) ?
                (associatedInstance != null ?
                 (IStorageItem)(StorageFile)await associatedInstance.FilesystemViewModel.GetFileFromPathAsync(item.Path) :
                 (IStorageItem)(StorageFile)await FilesystemTasks.Wrap(() => StorageFileExtensions.DangerousGetFileFromPathAsync(item.Path))) :
                (associatedInstance != null ?
                 (IStorageItem)(StorageFolder)await associatedInstance.FilesystemViewModel.GetFolderFromPathAsync(item.Path) :
                 (IStorageItem)(StorageFolder)await FilesystemTasks.Wrap(() => StorageFileExtensions.DangerousGetFolderFromPathAsync(item.Path))));
     }
     return(null);
 }
Пример #10
0
        public async Task <IStorageHistory> RenameAsync(IStorageItemWithPath source, string newName, NameCollisionOption collision, IProgress <FileSystemStatusCode> errorCode, CancellationToken cancellationToken)
        {
            var connection = await AppServiceConnectionHelper.Instance;

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

            var(status, response) = await connection.SendMessageForResponseAsync(new ValueSet()
            {
                { "Arguments", "FileOperation" },
                { "fileop", "RenameItem" },
                { "operationID", Guid.NewGuid().ToString() },
                { "filepath", source.Path },
                { "newName", newName },
                { "overwrite", collision == NameCollisionOption.ReplaceExisting }
            });

            var result = (FilesystemResult)(status == AppServiceResponseStatus.Success &&
                                            response.Get("Success", false));

            if (result)
            {
                var renamedItems = JsonConvert.DeserializeObject <IEnumerable <string> >(response["RenamedItems"] as string);
                errorCode?.Report(FileSystemStatusCode.Success);
                if (collision != NameCollisionOption.ReplaceExisting && renamedItems != null && renamedItems.Count() == 1)
                {
                    return(new StorageHistory(FileOperationType.Rename, source,
                                              StorageItemHelpers.FromPathAndType(renamedItems.Single(), source.ItemType)));
                }
                return(null); // Cannot undo overwrite operation
            }
            else
            {
                // Retry failed operations
                return(await filesystemOperations.RenameAsync(source, newName, collision, errorCode, cancellationToken));
            }
        }
Пример #11
0
        public async Task <IStorageHistory> RestoreFromTrashAsync(IStorageItemWithPath source,
                                                                  string destination,
                                                                  IProgress <float> progress,
                                                                  IProgress <FileSystemStatusCode> errorCode,
                                                                  CancellationToken cancellationToken)
        {
            FilesystemResult fsResult = FileSystemStatusCode.InProgress;

            errorCode?.Report(fsResult);

            fsResult = (FilesystemResult)await Task.Run(() => NativeFileOperationsHelper.MoveFileFromApp(source.Path, destination));

            if (!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(() => 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(() => sourceFile.Result.MoveAsync(destinationFolder.Result, Path.GetFileName(destination), NameCollisionOption.GenerateUniqueName).AsTask());
                    }
                    errorCode?.Report(fsResult);
                }
                if (fsResult == FileSystemStatusCode.Unauthorized || fsResult == FileSystemStatusCode.ReadOnly)
                {
                    fsResult = await PerformAdminOperation(new ValueSet()
                    {
                        { "Arguments", "FileOperation" },
                        { "fileop", "MoveItem" },
                        { "filepath", source.Path },
                        { "destpath", destination },
                        { "overwrite", false }
                    });
                }
            }

            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)));
        }
Пример #12
0
        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
                    {
                        var fsResult = await PerformAdminOperation(new ValueSet()
                        {
                            { "Arguments", "FileOperation" },
                            { "fileop", "RenameItem" },
                            { "filepath", source.Path },
                            { "newName", newName },
                            { "overwrite", collision == NameCollisionOption.ReplaceExisting }
                        });

                        if (fsResult)
                        {
                            errorCode?.Report(FileSystemStatusCode.Success);
                            return(new StorageHistory(FileOperationType.Rename, source, StorageItemHelpers.FromPathAndType(destination, source.ItemType)));
                        }
                    }
                }
                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 (UIHelpers.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);
        }
Пример #13
0
        public async Task <ReturnResult> DeleteItemAsync(IStorageItemWithPath source, bool showDialog, bool permanently, bool registerHistory)
        {
            PostedStatusBanner banner;
            bool deleteFromRecycleBin = await recycleBinHelpers.IsRecycleBinItem(source.Path);

            if (deleteFromRecycleBin)
            {
                permanently = true;
            }

            if (permanently)
            {
                banner = associatedInstance.BottomStatusStripControl.OngoingTasksControl.PostBanner(string.Empty,
                                                                                                    associatedInstance.FilesystemViewModel.WorkingDirectory,
                                                                                                    0,
                                                                                                    ReturnResult.InProgress,
                                                                                                    FileOperationType.Delete);
            }
            else
            {
                banner = associatedInstance.BottomStatusStripControl.OngoingTasksControl.PostBanner(string.Empty,
                                                                                                    associatedInstance.FilesystemViewModel.WorkingDirectory,
                                                                                                    0,
                                                                                                    ReturnResult.InProgress,
                                                                                                    FileOperationType.Recycle);
            }

            ReturnResult returnStatus = ReturnResult.InProgress;

            banner.ErrorCode.ProgressChanged += (s, e) => returnStatus = e.ToStatus();

            if (App.AppSettings.ShowConfirmDeleteDialog && showDialog) // Check if the setting to show a confirmation dialog is on
            {
                ConfirmDeleteDialog dialog = new ConfirmDeleteDialog(
                    deleteFromRecycleBin,
                    permanently,
                    associatedInstance.ContentPage.SelectedItemsPropertiesViewModel);

                await dialog.ShowAsync();

                if (dialog.Result != DialogResult.Delete) // Delete selected item if the result is Yes
                {
                    return(ReturnResult.Cancelled);       // Return if the result isn't delete
                }

                permanently = dialog.PermanentlyDelete;
            }

            Stopwatch sw = new Stopwatch();

            sw.Start();

            IStorageHistory history = await filesystemOperations.DeleteAsync(source, banner.Progress, banner.ErrorCode, permanently, cancellationToken);

            if (!permanently && registerHistory)
            {
                App.HistoryWrapper.AddHistory(history);
            }

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

            PostBannerHelpers.PostBanner_Delete(returnStatus, permanently ? FileOperationType.Delete : FileOperationType.Recycle, sw, associatedInstance);

            return(returnStatus);
        }
Пример #14
0
        public async Task <IStorageHistory> MoveAsync(IStorageItemWithPath source,
                                                      string destination,
                                                      NameCollisionOption collision,
                                                      IProgress <float> progress,
                                                      IProgress <FileSystemStatusCode> errorCode,
                                                      CancellationToken cancellationToken)
        {
            if (source.Path == destination)
            {
                progress?.Report(100.0f);
                errorCode?.Report(FileSystemStatusCode.Success);
                return(null);
            }

            if (string.IsNullOrWhiteSpace(source.Path))
            {
                // Can't move (only copy) files from MTP devices because:
                // StorageItems returned in DataPackageView are read-only
                // The item.Path property will be empty and there's no way of retrieving a new StorageItem with R/W access
                return(await CopyAsync(source, destination, collision, progress, errorCode, cancellationToken));
            }

            if (associatedInstance.FilesystemViewModel.WorkingDirectory.StartsWith(App.AppSettings.RecycleBinPath))
            {
                errorCode?.Report(FileSystemStatusCode.Unauthorized);
                progress?.Report(100.0f);

                // Do not paste files and folders inside the recycle bin
                await DialogDisplayHelper.ShowDialogAsync(
                    "ErrorDialogThisActionCannotBeDone".GetLocalized(),
                    "ErrorDialogUnsupportedOperation".GetLocalized());

                return(null);
            }

            IStorageItem movedItem = null;

            //long itemSize = await FilesystemHelpers.GetItemSize(await source.ToStorageItem(associatedInstance));

            if (source.ItemType == FilesystemItemType.Directory)
            {
                if (!string.IsNullOrWhiteSpace(source.Path) &&
                    Path.GetDirectoryName(destination).IsSubPathOf(source.Path)) // We check if user tried to move anything above the source.ItemPath
                {
                    var           destinationName = destination.Split(Path.DirectorySeparatorChar, StringSplitOptions.RemoveEmptyEntries).Last();
                    var           sourceName      = source.Path.Split(Path.DirectorySeparatorChar, StringSplitOptions.RemoveEmptyEntries).Last();
                    ContentDialog dialog          = new ContentDialog()
                    {
                        Title   = "ErrorDialogThisActionCannotBeDone".GetLocalized(),
                        Content = "ErrorDialogTheDestinationFolder".GetLocalized() + " (" + destinationName + ") " + "ErrorDialogIsASubfolder".GetLocalized() + " (" + sourceName + ")",
                        //PrimaryButtonText = "ErrorDialogSkip".GetLocalized(),
                        CloseButtonText = "ErrorDialogCancel".GetLocalized()
                    };

                    ContentDialogResult result = await dialog.ShowAsync();

                    if (result == ContentDialogResult.Primary)
                    {
                        progress?.Report(100.0f);
                        errorCode?.Report(FileSystemStatusCode.InProgress | FileSystemStatusCode.Success);
                    }
                    else
                    {
                        progress?.Report(100.0f);
                        errorCode?.Report(FileSystemStatusCode.InProgress | FileSystemStatusCode.Generic);
                    }
                    return(null);
                }
                else
                {
                    var fsResult = (FilesystemResult)await Task.Run(() => NativeFileOperationsHelper.MoveFileFromApp(source.Path, destination));

                    if (!fsResult)
                    {
                        Debug.WriteLine(System.Runtime.InteropServices.Marshal.GetLastWin32Error());

                        var fsSourceFolder = await source.ToStorageItemResult(associatedInstance);

                        var fsDestinationFolder = await associatedInstance.FilesystemViewModel.GetFolderFromPathAsync(Path.GetDirectoryName(destination));

                        fsResult = fsSourceFolder.ErrorCode | fsDestinationFolder.ErrorCode;

                        if (fsResult)
                        {
                            var fsResultMove = await FilesystemTasks.Wrap(() => MoveDirectoryAsync((StorageFolder)fsSourceFolder, (StorageFolder)fsDestinationFolder, fsSourceFolder.Result.Name, collision.Convert(), true));

                            if (fsResultMove == FileSystemStatusCode.AlreadyExists)
                            {
                                progress?.Report(100.0f);
                                errorCode?.Report(FileSystemStatusCode.AlreadyExists);
                                return(null);
                            }

                            if (fsResultMove)
                            {
                                if (FolderHelpers.CheckFolderForHiddenAttribute(source.Path))
                                {
                                    // The source folder was hidden, apply hidden attribute to destination
                                    NativeFileOperationsHelper.SetFileAttribute(fsResultMove.Result.Path, FileAttributes.Hidden);
                                }
                                movedItem = (StorageFolder)fsResultMove;
                            }
                            fsResult = fsResultMove;
                        }
                        if (fsResult == FileSystemStatusCode.Unauthorized || fsResult == FileSystemStatusCode.ReadOnly)
                        {
                            fsResult = await PerformAdminOperation(new ValueSet()
                            {
                                { "Arguments", "FileOperation" },
                                { "fileop", "MoveItem" },
                                { "filepath", source.Path },
                                { "destpath", destination },
                                { "overwrite", collision == NameCollisionOption.ReplaceExisting }
                            });
                        }
                    }
                    errorCode?.Report(fsResult.ErrorCode);
                }
            }
            else if (source.ItemType == FilesystemItemType.File)
            {
                var fsResult = (FilesystemResult)await Task.Run(() => NativeFileOperationsHelper.MoveFileFromApp(source.Path, destination));

                if (!fsResult)
                {
                    Debug.WriteLine(System.Runtime.InteropServices.Marshal.GetLastWin32Error());

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

                    var sourceResult = await source.ToStorageItemResult(associatedInstance);

                    fsResult = sourceResult.ErrorCode | destinationResult.ErrorCode;

                    if (fsResult)
                    {
                        var file         = (StorageFile)sourceResult;
                        var fsResultMove = await FilesystemTasks.Wrap(() => file.MoveAsync(destinationResult.Result, Path.GetFileName(file.Name), collision).AsTask());

                        if (fsResultMove == FileSystemStatusCode.AlreadyExists)
                        {
                            progress?.Report(100.0f);
                            errorCode?.Report(FileSystemStatusCode.AlreadyExists);
                            return(null);
                        }

                        if (fsResultMove)
                        {
                            movedItem = file;
                        }
                        fsResult = fsResultMove;
                    }
                    if (fsResult == FileSystemStatusCode.Unauthorized || fsResult == FileSystemStatusCode.ReadOnly)
                    {
                        fsResult = await PerformAdminOperation(new ValueSet()
                        {
                            { "Arguments", "FileOperation" },
                            { "fileop", "MoveItem" },
                            { "filepath", source.Path },
                            { "destpath", destination },
                            { "overwrite", collision == NameCollisionOption.ReplaceExisting }
                        });
                    }
                }
                errorCode?.Report(fsResult.ErrorCode);
            }

            if (Path.GetDirectoryName(destination) == associatedInstance.FilesystemViewModel.WorkingDirectory)
            {
                await Windows.ApplicationModel.Core.CoreApplication.MainView.DispatcherQueue.EnqueueAsync(async() =>
                {
                    await Task.Delay(50); // Small delay for the item to appear in the file list
                    List <ListedItem> movedListedItems = associatedInstance.FilesystemViewModel.FilesAndFolders
                                                         .Where(listedItem => destination.Contains(listedItem.ItemPath)).ToList();

                    if (movedListedItems.Count > 0)
                    {
                        itemManipulationModel.AddSelectedItems(movedListedItems);
                        itemManipulationModel.FocusSelectedItems();
                    }
                }, Windows.System.DispatcherQueuePriority.Low);
            }

            progress?.Report(100.0f);

            if (collision == NameCollisionOption.ReplaceExisting)
            {
                return(null); // Cannot undo overwrite operation
            }

            var pathWithType = movedItem.FromStorageItem(destination, source.ItemType);

            return(new StorageHistory(FileOperationType.Move, source, pathWithType));
        }
Пример #15
0
 public FtpStorageFolder(IStorageItemWithPath item)
 {
     Name    = System.IO.Path.GetFileName(item.Path);
     Path    = item.Path;
     FtpPath = FtpHelpers.GetFtpPath(item.Path);
 }
Пример #16
0
 public async Task <ReturnResult> RestoreItemFromTrashAsync(IStorageItemWithPath source, string destination, bool registerHistory)
 {
     return(await RestoreItemsFromTrashAsync(source.CreateEnumerable(), destination.CreateEnumerable(), registerHistory));
 }
Пример #17
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);
        }
Пример #18
0
        public static async Task <FilesystemResult <IStorageItem> > ToStorageItemResult(this IStorageItemWithPath item, IShellPage associatedInstance = null)
        {
            var returnedItem = new FilesystemResult <IStorageItem>(null, FileSystemStatusCode.Generic);

            if (!string.IsNullOrEmpty(item.Path))
            {
                returnedItem = (item.ItemType == FilesystemItemType.File) ?
                               ToType <IStorageItem, StorageFile>(associatedInstance != null ?
                                                                  await associatedInstance.FilesystemViewModel.GetFileFromPathAsync(item.Path) :
                                                                  await FilesystemTasks.Wrap(() => StorageFileExtensions.DangerousGetFileFromPathAsync(item.Path))) :
                               ToType <IStorageItem, StorageFolder>(associatedInstance != null ?
                                                                    await associatedInstance.FilesystemViewModel.GetFolderFromPathAsync(item.Path) :
                                                                    await FilesystemTasks.Wrap(() => StorageFileExtensions.DangerousGetFolderFromPathAsync(item.Path)));
            }
            if (returnedItem.Result == null && item.Item != null)
            {
                returnedItem = new FilesystemResult <IStorageItem>(item.Item, FileSystemStatusCode.Success);
            }
            return(returnedItem);
        }
Пример #19
0
 public static async Task <IStorageItem> ToStorageItem(this IStorageItemWithPath item, IShellPage associatedInstance = null)
 {
     return((await item.ToStorageItemResult(associatedInstance)).Result);
 }
Пример #20
0
 public async Task <IStorageHistory> CopyAsync(IStorageItemWithPath source, string destination, NameCollisionOption collision, IProgress <float> progress, IProgress <FileSystemStatusCode> errorCode, CancellationToken cancellationToken)
 {
     return(await CopyItemsAsync(source.CreateEnumerable(), destination.CreateEnumerable(), collision.ConvertBack().CreateEnumerable(), progress, errorCode, cancellationToken));
 }
Пример #21
0
 public async Task <(IStorageHistory, IStorageItem)> CreateAsync(IStorageItemWithPath source, IProgress <FileSystemStatusCode> errorCode, CancellationToken cancellationToken)
 {
     return(await filesystemOperations.CreateAsync(source, errorCode, cancellationToken));
 }
Пример #22
0
        public async Task <ReturnResult> DeleteItemAsync(IStorageItemWithPath source, bool showDialog, bool permanently, bool registerHistory)
        {
            try
            {
                PostedStatusBanner banner;
                bool deleteFromRecycleBin = recycleBinHelpers.IsPathUnderRecycleBin(source.Path);

                if (deleteFromRecycleBin)
                {
                    permanently = true;
                }

                if (permanently)
                {
                    banner = associatedInstance.StatusCenterActions.PostBanner(string.Empty,
                                                                               associatedInstance.FilesystemViewModel.WorkingDirectory,
                                                                               0,
                                                                               ReturnResult.InProgress,
                                                                               FileOperationType.Delete);
                }
                else
                {
                    banner = associatedInstance.StatusCenterActions.PostBanner(string.Empty,
                                                                               associatedInstance.FilesystemViewModel.WorkingDirectory,
                                                                               0,
                                                                               ReturnResult.InProgress,
                                                                               FileOperationType.Recycle);
                }

                var returnStatus = ReturnResult.InProgress;

                banner.ErrorCode.ProgressChanged += (s, e) => returnStatus = e.ToStatus();

                if (App.AppSettings.ShowConfirmDeleteDialog && showDialog) // Check if the setting to show a confirmation dialog is on
                {
                    List <FilesystemItemsOperationItemModel> incomingItems = new List <FilesystemItemsOperationItemModel>
                    {
                        new FilesystemItemsOperationItemModel(FilesystemOperationType.Delete, source.Path ?? source.Item.Path, null)
                    };

                    FilesystemOperationDialog dialog = FilesystemOperationDialogViewModel.GetDialog(new FilesystemItemsOperationDataModel(
                                                                                                        FilesystemOperationType.Delete,
                                                                                                        false,
                                                                                                        !deleteFromRecycleBin ? permanently : deleteFromRecycleBin,
                                                                                                        !deleteFromRecycleBin,
                                                                                                        incomingItems,
                                                                                                        new List <FilesystemItemsOperationItemModel>()));

                    ContentDialogResult result = await dialog.ShowAsync();

                    if (result != ContentDialogResult.Primary)
                    {
                        banner.Remove();
                        return(ReturnResult.Cancelled); // Return if the result isn't delete
                    }

                    // Delete selected item if the result is Yes
                    permanently = dialog.ViewModel.PermanentlyDelete;
                }

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

                IStorageHistory history = await filesystemOperations.DeleteAsync(source, banner.Progress, banner.ErrorCode, permanently, cancellationToken);

                ((IProgress <float>)banner.Progress).Report(100.0f);

                if (!permanently && registerHistory)
                {
                    App.HistoryWrapper.AddHistory(history);
                }

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

                PostBannerHelpers.PostBanner_Delete(returnStatus, permanently ? FileOperationType.Delete : FileOperationType.Recycle, sw, associatedInstance);
                return(returnStatus);
            }
            catch (System.Exception ex)
            {
                NLog.LogManager.GetCurrentClassLogger().Warn($"Delete item operation failed:\n{ex}");
                return(ReturnResult.Failed);
            }
        }
Пример #23
0
 public FtpStorageFile(IStorageItemWithPath item)
 {
     Path    = item.Path;
     Name    = IO.Path.GetFileName(item.Path);
     FtpPath = FtpHelpers.GetFtpPath(item.Path);
 }
Пример #24
0
 public async Task <IStorageHistory> DeleteAsync(IStorageItemWithPath source, IProgress <float> progress, IProgress <FileSystemStatusCode> errorCode, bool permanently, CancellationToken cancellationToken)
 {
     return(await DeleteItemsAsync(source.CreateEnumerable(), progress, errorCode, permanently, cancellationToken));
 }
Пример #25
0
        public async Task <IStorageHistory> CopyAsync(IStorageItemWithPath source,
                                                      string destination,
                                                      IProgress <float> progress,
                                                      IProgress <FilesystemErrorCode> errorCode,
                                                      CancellationToken cancellationToken)
        {
            if (associatedInstance.FilesystemViewModel.WorkingDirectory.StartsWith(App.AppSettings.RecycleBinPath))
            {
                errorCode?.Report(FilesystemErrorCode.ERROR_UNAUTHORIZED);
                progress?.Report(100.0f);

                // Do not paste files and folders inside the recycle bin
                await DialogDisplayHelper.ShowDialogAsync(
                    "ErrorDialogThisActionCannotBeDone".GetLocalized(),
                    "ErrorDialogUnsupportedOperation".GetLocalized());

                return(null);
            }

            IStorageItem copiedItem = null;

            //long itemSize = await FilesystemHelpers.GetItemSize(await source.ToStorageItem(associatedInstance));

            if (source.ItemType == FilesystemItemType.Directory)
            {
                if (!string.IsNullOrWhiteSpace(source.Path) &&
                    Path.GetDirectoryName(destination).IsSubPathOf(source.Path)) // We check if user tried to copy anything above the source.ItemPath
                {
                    var           destinationName = destination.Split(Path.DirectorySeparatorChar, StringSplitOptions.RemoveEmptyEntries).Last();
                    var           sourceName      = source.Path.Split(Path.DirectorySeparatorChar, StringSplitOptions.RemoveEmptyEntries).Last();
                    ContentDialog dialog          = new ContentDialog()
                    {
                        Title   = "ErrorDialogThisActionCannotBeDone".GetLocalized(),
                        Content = "ErrorDialogTheDestinationFolder".GetLocalized() + " (" + destinationName + ") " + "ErrorDialogIsASubfolder".GetLocalized() + " (" + sourceName + ")",
                        //PrimaryButtonText = "ErrorDialogSkip".GetLocalized(),
                        CloseButtonText = "ErrorDialogCancel".GetLocalized()
                    };

                    ContentDialogResult result = await dialog.ShowAsync();

                    if (result == ContentDialogResult.Primary)
                    {
                        progress?.Report(100.0f);
                        errorCode?.Report(FilesystemErrorCode.ERROR_INPROGRESS | FilesystemErrorCode.ERROR_SUCCESS);
                    }
                    else
                    {
                        progress?.Report(100.0f);
                        errorCode?.Report(FilesystemErrorCode.ERROR_INPROGRESS | FilesystemErrorCode.ERROR_GENERIC);
                    }
                    return(null);
                }
                else
                {
                    var fsSourceFolder = await source.ToStorageItemResult(associatedInstance);

                    var fsDestinationFolder = await associatedInstance.FilesystemViewModel.GetFolderFromPathAsync(Path.GetDirectoryName(destination));

                    var fsResult = (FilesystemResult)(fsSourceFolder.ErrorCode | fsDestinationFolder.ErrorCode);

                    if (fsResult)
                    {
                        var fsCopyResult = await FilesystemTasks.Wrap(() => CloneDirectoryAsync((StorageFolder)fsSourceFolder, (StorageFolder)fsDestinationFolder, fsSourceFolder.Result.Name, CreationCollisionOption.FailIfExists));

                        if (fsCopyResult == 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)
                            {
                                fsCopyResult = await FilesystemTasks.Wrap(() => CloneDirectoryAsync((StorageFolder)fsSourceFolder, (StorageFolder)fsDestinationFolder, fsSourceFolder.Result.Name, CreationCollisionOption.GenerateUniqueName));
                            }
                            else if (result == ContentDialogResult.Secondary)
                            {
                                fsCopyResult = await FilesystemTasks.Wrap(() => CloneDirectoryAsync((StorageFolder)fsSourceFolder, (StorageFolder)fsDestinationFolder, fsSourceFolder.Result.Name, CreationCollisionOption.ReplaceExisting));

                                return(null); // Cannot undo overwrite operation
                            }
                            else
                            {
                                return(null);
                            }
                        }
                        if (fsCopyResult)
                        {
                            if (associatedInstance.FilesystemViewModel.CheckFolderForHiddenAttribute(source.Path))
                            {
                                // The source folder was hidden, apply hidden attribute to destination
                                NativeFileOperationsHelper.SetFileAttribute(fsCopyResult.Result.Path, FileAttributes.Hidden);
                            }
                            copiedItem = (StorageFolder)fsCopyResult;
                        }
                        fsResult = fsCopyResult;
                    }
                    errorCode?.Report(fsResult.ErrorCode);
                    if (!fsResult)
                    {
                        return(null);
                    }
                }
            }
            else if (source.ItemType == FilesystemItemType.File)
            {
                FilesystemResult <StorageFolder> destinationResult = await associatedInstance.FilesystemViewModel.GetFolderFromPathAsync(Path.GetDirectoryName(destination));

                var sourceResult = await source.ToStorageItemResult(associatedInstance);

                var fsResult = (FilesystemResult)(sourceResult.ErrorCode | destinationResult.ErrorCode);

                if (fsResult)
                {
                    var file         = (StorageFile)sourceResult;
                    var fsResultCopy = await FilesystemTasks.Wrap(() => file.CopyAsync(destinationResult.Result, Path.GetFileName(file.Name), NameCollisionOption.FailIfExists).AsTask());

                    if (fsResultCopy == 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)
                        {
                            fsResultCopy = await FilesystemTasks.Wrap(() => file.CopyAsync(destinationResult.Result, Path.GetFileName(file.Name), NameCollisionOption.GenerateUniqueName).AsTask());
                        }
                        else if (result == ContentDialogResult.Secondary)
                        {
                            fsResultCopy = await FilesystemTasks.Wrap(() => file.CopyAsync(destinationResult.Result, Path.GetFileName(file.Name), NameCollisionOption.ReplaceExisting).AsTask());

                            return(null); // Cannot undo overwrite operation
                        }
                        else
                        {
                            return(null);
                        }
                    }
                    if (fsResultCopy)
                    {
                        copiedItem = fsResultCopy.Result;
                    }
                    fsResult = fsResultCopy;
                }
                if (fsResult == FilesystemErrorCode.ERROR_UNAUTHORIZED || fsResult == FilesystemErrorCode.ERROR_GENERIC)
                {
                    // Try again with CopyFileFromApp
                    if (NativeFileOperationsHelper.CopyFileFromApp(source.Path, destination, true))
                    {
                        fsResult = (FilesystemResult)true;
                    }
                    else
                    {
                        Debug.WriteLine(System.Runtime.InteropServices.Marshal.GetLastWin32Error());
                    }
                }
                errorCode?.Report(fsResult.ErrorCode);
                if (!fsResult)
                {
                    return(null);
                }
            }

            if (Path.GetDirectoryName(destination) == associatedInstance.FilesystemViewModel.WorkingDirectory)
            {
                if (copiedItem != null)
                {
                    List <ListedItem> copiedListedItems = associatedInstance.FilesystemViewModel.FilesAndFolders
                                                          .Where(listedItem => copiedItem.Path.Contains(listedItem.ItemPath)).ToList();

                    if (copiedListedItems.Count > 0)
                    {
                        associatedInstance.ContentPage.AddSelectedItemsOnUi(copiedListedItems);
                        associatedInstance.ContentPage.FocusSelectedItems();
                    }
                }
            }

            progress?.Report(100.0f);

            var pathWithType = copiedItem.FromStorageItem(destination, source.ItemType);

            return(new StorageHistory(FileOperationType.Copy, source, pathWithType));
        }
Пример #26
0
 public void Modify(FileOperationType operationType, IStorageItemWithPath source, IStorageItemWithPath destination)
 {
     OperationType = operationType;
     Source        = source.CreateEnumerable();
     Destination   = destination.CreateEnumerable();
 }
Пример #27
0
        public async Task <IStorageHistory> DeleteAsync(IStorageItemWithPath source,
                                                        IProgress <float> progress,
                                                        IProgress <FilesystemErrorCode> errorCode,
                                                        bool permanently,
                                                        CancellationToken cancellationToken)
        {
            bool deleteFromRecycleBin = recycleBinHelpers.IsPathUnderRecycleBin(source.Path);

            FilesystemResult fsResult = FilesystemErrorCode.ERROR_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 == FilesystemErrorCode.ERROR_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 == FilesystemErrorCode.ERROR_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);
            }
        }
Пример #28
0
        public async Task <ReturnResult> DeleteItemAsync(IStorageItemWithPath source, bool showDialog, bool permanently, bool registerHistory)
        {
            PostedStatusBanner banner;
            bool deleteFromRecycleBin = recycleBinHelpers.IsPathUnderRecycleBin(source.Path);

            if (deleteFromRecycleBin)
            {
                permanently = true;
            }

            if (permanently)
            {
                banner = associatedInstance.StatusCenterActions.PostBanner(string.Empty,
                                                                           associatedInstance.FilesystemViewModel.WorkingDirectory,
                                                                           0,
                                                                           ReturnResult.InProgress,
                                                                           FileOperationType.Delete);
            }
            else
            {
                banner = associatedInstance.StatusCenterActions.PostBanner(string.Empty,
                                                                           associatedInstance.FilesystemViewModel.WorkingDirectory,
                                                                           0,
                                                                           ReturnResult.InProgress,
                                                                           FileOperationType.Recycle);
            }

            var returnStatus = ReturnResult.InProgress;

            banner.ErrorCode.ProgressChanged += (s, e) => returnStatus = e.ToStatus();

            if (App.AppSettings.ShowConfirmDeleteDialog && showDialog) // Check if the setting to show a confirmation dialog is on
            {
                ConfirmDeleteDialog dialog = new ConfirmDeleteDialog(
                    deleteFromRecycleBin,
                    permanently,
                    associatedInstance.SlimContentPage.SelectedItems.Count);

                if (UIHelpers.IsAnyContentDialogOpen())
                {
                    // Can show only one dialog at a time
                    banner.Remove();
                    return(ReturnResult.Cancelled);
                }
                await dialog.ShowAsync();

                if (dialog.Result != DialogResult.Delete) // Delete selected item if the result is Yes
                {
                    banner.Remove();
                    return(ReturnResult.Cancelled); // Return if the result isn't delete
                }

                permanently = dialog.PermanentlyDelete;
            }

            var sw = new Stopwatch();

            sw.Start();

            IStorageHistory history = await filesystemOperations.DeleteAsync(source, banner.Progress, banner.ErrorCode, permanently, cancellationToken);

            ((IProgress <float>)banner.Progress).Report(100.0f);

            if (!permanently && registerHistory)
            {
                App.HistoryWrapper.AddHistory(history);
            }

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

            PostBannerHelpers.PostBanner_Delete(returnStatus, permanently ? FileOperationType.Delete : FileOperationType.Recycle, sw, associatedInstance);

            return(returnStatus);
        }
Пример #29
0
        public async Task <IStorageHistory> RestoreFromTrashAsync(IStorageItemWithPath source,
                                                                  string destination,
                                                                  IProgress <float> progress,
                                                                  IProgress <FilesystemErrorCode> errorCode,
                                                                  CancellationToken cancellationToken)
        {
            FilesystemResult fsResult = FilesystemErrorCode.ERROR_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));
                    }).OnSuccess(t => sourceFolder.Result.DeleteAsync(StorageDeleteOption.PermanentDelete).AsTask()); // 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 == FilesystemErrorCode.ERROR_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 != FilesystemErrorCode.ERROR_SUCCESS)
            {
                if (((FilesystemErrorCode)fsResult).HasFlag(FilesystemErrorCode.ERROR_UNAUTHORIZED))
                {
                    await DialogDisplayHelper.ShowDialogAsync("AccessDeniedDeleteDialog/Title".GetLocalized(), "AccessDeniedDeleteDialog/Text".GetLocalized());
                }
                else if (((FilesystemErrorCode)fsResult).HasFlag(FilesystemErrorCode.ERROR_UNAUTHORIZED))
                {
                    await DialogDisplayHelper.ShowDialogAsync("FileNotFoundDialog/Title".GetLocalized(), "FileNotFoundDialog/Text".GetLocalized());
                }
                else if (((FilesystemErrorCode)fsResult).HasFlag(FilesystemErrorCode.ERROR_ALREADYEXIST))
                {
                    await DialogDisplayHelper.ShowDialogAsync("ItemAlreadyExistsDialogTitle".GetLocalized(), "ItemAlreadyExistsDialogContent".GetLocalized());
                }
            }

            return(new StorageHistory(FileOperationType.Restore, source, StorageItemHelpers.FromPathAndType(destination, source.ItemType)));
        }
Пример #30
0
 public async Task <ReturnResult> DeleteItemAsync(IStorageItemWithPath source, bool showDialog, bool permanently, bool registerHistory)
 {
     return(await DeleteItemsAsync(source.CreateEnumerable(), showDialog, permanently, registerHistory));
 }