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))); }
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()); }
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)); } }
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); }