diff --git a/Files.Launcher/MessageHandlers/FileOperationsHandler.cs b/Files.Launcher/MessageHandlers/FileOperationsHandler.cs index 8e7ea35f0b46..7c06ddfa11dd 100644 --- a/Files.Launcher/MessageHandlers/FileOperationsHandler.cs +++ b/Files.Launcher/MessageHandlers/FileOperationsHandler.cs @@ -464,24 +464,36 @@ await Win32API.StartSTATask(() => case "UpdateLink": var linkSavePath = (string)message["filepath"]; var targetPath = (string)message["targetpath"]; - if (linkSavePath.EndsWith(".lnk")) + try { - var arguments = (string)message["arguments"]; - var workingDirectory = (string)message["workingdir"]; - var runAsAdmin = (bool)message["runasadmin"]; - using var newLink = new ShellLink(targetPath, arguments, workingDirectory); - newLink.RunAsAdministrator = runAsAdmin; - newLink.SaveAs(linkSavePath); // Overwrite if exists + bool success = false; + if (linkSavePath.EndsWith(".lnk")) + { + var arguments = (string)message["arguments"]; + var workingDirectory = (string)message["workingdir"]; + var runAsAdmin = (bool)message["runasadmin"]; + using var newLink = new ShellLink(targetPath, arguments, workingDirectory); + newLink.RunAsAdministrator = runAsAdmin; + newLink.SaveAs(linkSavePath); // Overwrite if exists + success = true; + } + else if (linkSavePath.EndsWith(".url")) + { + success = await Win32API.StartSTATask(() => + { + var ipf = new Url.IUniformResourceLocator(); + ipf.SetUrl(targetPath, Url.IURL_SETURL_FLAGS.IURL_SETURL_FL_GUESS_PROTOCOL); + (ipf as System.Runtime.InteropServices.ComTypes.IPersistFile).Save(linkSavePath, false); // Overwrite if exists + return true; + }); + } + await Win32API.SendMessageAsync(connection, new ValueSet() { { "Success", success } }, message.Get("RequestID", (string)null)); } - else if (linkSavePath.EndsWith(".url")) + catch (Exception ex) { - await Win32API.StartSTATask(() => - { - var ipf = new Url.IUniformResourceLocator(); - ipf.SetUrl(targetPath, Url.IURL_SETURL_FLAGS.IURL_SETURL_FL_GUESS_PROTOCOL); - (ipf as System.Runtime.InteropServices.ComTypes.IPersistFile).Save(linkSavePath, false); // Overwrite if exists - return true; - }); + // Could not create shortcut + Program.Logger.Warn(ex, ex.Message); + await Win32API.SendMessageAsync(connection, new ValueSet() { { "Success", false } }, message.Get("RequestID", (string)null)); } break; diff --git a/Files/BaseLayout.cs b/Files/BaseLayout.cs index affda3c12117..55cd08aba403 100644 --- a/Files/BaseLayout.cs +++ b/Files/BaseLayout.cs @@ -761,17 +761,12 @@ protected virtual void Page_CharacterReceived(CoreWindow sender, CharacterReceiv protected async void FileList_DragItemsStarting(object sender, DragItemsStartingEventArgs e) { List selectedStorageItems = new List(); + var result = (FilesystemResult)false; - foreach (var itemObj in e.Items) - { - var item = itemObj as ListedItem; - if (item == null || item is ShortcutItem) - { - // Can't drag shortcut items - continue; - } + e.Items.OfType().ForEach(item => SelectedItems.Add(item)); - SelectedItems.Add(item); + foreach (var item in e.Items.OfType()) + { if (item is FtpItem ftpItem) { if (item.PrimaryItemAttribute == StorageItemTypes.File) @@ -781,16 +776,32 @@ protected async void FileList_DragItemsStarting(object sender, DragItemsStarting } else if (item.PrimaryItemAttribute == StorageItemTypes.File) { - await ParentShellPageInstance.FilesystemViewModel.GetFileFromPathAsync(item.ItemPath) + result = await ParentShellPageInstance.FilesystemViewModel.GetFileFromPathAsync(item.ItemPath) .OnSuccess(t => selectedStorageItems.Add(t)); + if (!result) + { + break; + } } else if (item.PrimaryItemAttribute == StorageItemTypes.Folder) { - await ParentShellPageInstance.FilesystemViewModel.GetFolderFromPathAsync(item.ItemPath) + result = await ParentShellPageInstance.FilesystemViewModel.GetFolderFromPathAsync(item.ItemPath) .OnSuccess(t => selectedStorageItems.Add(t)); + if (!result) + { + break; + } } } + if (result.ErrorCode == FileSystemStatusCode.Unauthorized) + { + var itemList = e.Items.OfType().Select(x => StorageItemHelpers.FromPathAndType( + x.ItemPath, x.PrimaryItemAttribute == StorageItemTypes.File ? FilesystemItemType.File : FilesystemItemType.Directory)); + e.Data.Properties["FileDrop"] = itemList.ToList(); + return; + } + if (selectedStorageItems.Count == 1) { if (selectedStorageItems[0] is IStorageFile file) @@ -853,37 +864,26 @@ protected async void Item_DragOver(object sender, DragEventArgs e) }, TimeSpan.FromMilliseconds(1000), false); } - if (e.DataView.Contains(StandardDataFormats.StorageItems)) + if (Filesystem.FilesystemHelpers.HasDraggedStorageItems(e.DataView)) { - IReadOnlyList draggedItems; - try - { - draggedItems = await e.DataView.GetStorageItemsAsync(); - } - catch (Exception ex) when ((uint)ex.HResult == 0x80040064 || (uint)ex.HResult == 0x8004006A) - { - // Handled by FTP - draggedItems = new List(); - } - catch (Exception ex) - { - App.Logger.Warn(ex, ex.Message); - e.AcceptedOperation = DataPackageOperation.None; - deferral.Complete(); - return; - } - e.Handled = true; + + var (handledByFtp, draggedItems) = await Filesystem.FilesystemHelpers.GetDraggedStorageItems(e.DataView); + if (draggedItems.Any(draggedItem => draggedItem.Path == item.ItemPath)) { e.AcceptedOperation = DataPackageOperation.None; } - else if (!draggedItems.Any()) + else if (handledByFtp) { e.DragUIOverride.IsCaptionVisible = true; e.DragUIOverride.Caption = string.Format("CopyToFolderCaptionText".GetLocalized(), item.ItemName); e.AcceptedOperation = DataPackageOperation.Copy; } + else if (!draggedItems.Any()) + { + e.AcceptedOperation = DataPackageOperation.None; + } else { e.DragUIOverride.IsCaptionVisible = true; @@ -892,6 +892,11 @@ protected async void Item_DragOver(object sender, DragEventArgs e) e.DragUIOverride.Caption = $"{"OpenItemsWithCaptionText".GetLocalized()} {item.ItemName}"; e.AcceptedOperation = DataPackageOperation.Link; } // Items from the same drive as this folder are dragged into this folder, so we move the items instead of copy + else if (e.Modifiers.HasFlag(DragDropModifiers.Alt) || e.Modifiers.HasFlag(DragDropModifiers.Control | DragDropModifiers.Shift)) + { + e.DragUIOverride.Caption = string.Format("LinkToFolderCaptionText".GetLocalized(), item.ItemName); + e.AcceptedOperation = DataPackageOperation.Link; + } else if (e.Modifiers.HasFlag(DragDropModifiers.Control)) { e.DragUIOverride.Caption = string.Format("CopyToFolderCaptionText".GetLocalized(), item.ItemName); diff --git a/Files/Enums/FileOperationType.cs b/Files/Enums/FileOperationType.cs index 9e6ee6870399..e60ae852947e 100644 --- a/Files/Enums/FileOperationType.cs +++ b/Files/Enums/FileOperationType.cs @@ -46,6 +46,11 @@ public enum FileOperationType : byte /// /// A item has been deleted /// - Delete = 8 + Delete = 8, + + /// + /// A link to an item has been created + /// + CreateLink = 9, } } \ No newline at end of file diff --git a/Files/Filesystem/FilesystemOperations/FilesystemOperations.cs b/Files/Filesystem/FilesystemOperations/FilesystemOperations.cs index 44ea78c9ddc9..97fda4411ce6 100644 --- a/Files/Filesystem/FilesystemOperations/FilesystemOperations.cs +++ b/Files/Filesystem/FilesystemOperations/FilesystemOperations.cs @@ -84,12 +84,6 @@ public FilesystemOperations(IShellPage associatedInstance) break; } - case FilesystemItemType.Symlink: - { - Debugger.Break(); - throw new NotImplementedException(); - } - default: Debugger.Break(); break; @@ -1159,5 +1153,10 @@ public async Task DeleteItemsAsync(IEnumerable CreateShortcutItemsAsync(IEnumerable source, IEnumerable destination, IProgress progress, IProgress errorCode, CancellationToken token) + { + throw new NotImplementedException("Cannot create shortcuts in UWP."); + } } } \ No newline at end of file diff --git a/Files/Filesystem/FilesystemOperations/Helpers/FilesystemHelpers.cs b/Files/Filesystem/FilesystemOperations/Helpers/FilesystemHelpers.cs index 68b2eeb03dd5..1b4dba05bb09 100644 --- a/Files/Filesystem/FilesystemOperations/Helpers/FilesystemHelpers.cs +++ b/Files/Filesystem/FilesystemOperations/Helpers/FilesystemHelpers.cs @@ -10,6 +10,7 @@ using Files.ViewModels; using Files.ViewModels.Dialogs; using Microsoft.Toolkit.Uwp; +using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Diagnostics; @@ -423,10 +424,12 @@ public async Task PerformOperationTypeAsync(DataPackageOperation o { var items = await packageView.GetStorageItemsAsync(); NavigationHelpers.OpenItemsWithExecutable(associatedInstance, items.ToList(), destination); + return ReturnResult.Success; + } + else + { + return await CreateShortcutFromClipboard(packageView, destination, showDialog, registerHistory); } - - // TODO: Support link creation - return default; } else if (operation.HasFlag(DataPackageOperation.None)) { @@ -583,36 +586,29 @@ public async Task CopyItemAsync(IStorageItemWithPath source, strin public async Task CopyItemsFromClipboard(DataPackageView packageView, string destination, bool showDialog, bool registerHistory) { - if (packageView.Contains(StandardDataFormats.StorageItems)) + var (handledByFtp, source) = await GetDraggedStorageItems(packageView); + + if (handledByFtp) { - IReadOnlyList source; - try - { - source = await packageView.GetStorageItemsAsync(); - } - catch (Exception ex) when ((uint)ex.HResult == 0x80040064 || (uint)ex.HResult == 0x8004006A) - { - var connection = await ServiceConnection; - if (connection != null) - { - var (status, response) = await connection.SendMessageForResponseAsync(new ValueSet() { - { "Arguments", "FileOperation" }, - { "fileop", "DragDrop" }, - { "droppath", associatedInstance.FilesystemViewModel.WorkingDirectory } }); - return (status == AppServiceResponseStatus.Success && response.Get("Success", false)) ? ReturnResult.Success : ReturnResult.Failed; - } - return ReturnResult.Failed; - } - catch (Exception ex) + var connection = await ServiceConnection; + if (connection != null) { - App.Logger.Warn(ex, ex.Message); - return ReturnResult.UnknownException; + var (status, response) = await connection.SendMessageForResponseAsync(new ValueSet() { + { "Arguments", "FileOperation" }, + { "fileop", "DragDrop" }, + { "droppath", associatedInstance.FilesystemViewModel.WorkingDirectory } }); + return (status == AppServiceResponseStatus.Success && response.Get("Success", false)) ? ReturnResult.Success : ReturnResult.Failed; } + return ReturnResult.Failed; + } + + if (source.Any()) + { ReturnResult returnStatus = ReturnResult.InProgress; var destinations = new List(); List binItems = null; - foreach (IStorageItem item in source) + foreach (var item in source) { if (recycleBinHelpers.IsPathUnderRecycleBin(item.Path)) { @@ -815,32 +811,25 @@ public async Task MoveItemAsync(IStorageItemWithPath source, strin public async Task MoveItemsFromClipboard(DataPackageView packageView, string destination, bool showDialog, bool registerHistory) { - if (!packageView.Contains(StandardDataFormats.StorageItems)) + if (!HasDraggedStorageItems(packageView)) { // Happens if you copy some text and then you Ctrl+V in Files return ReturnResult.BadArgumentException; } - IReadOnlyList source; - try - { - source = await packageView.GetStorageItemsAsync(); - } - catch (Exception ex) when ((uint)ex.HResult == 0x80040064 || (uint)ex.HResult == 0x8004006A) + var (handledByFtp, source) = await GetDraggedStorageItems(packageView); + + if (handledByFtp) { // Not supported return ReturnResult.Failed; } - catch (Exception ex) - { - App.Logger.Warn(ex, ex.Message); - return ReturnResult.UnknownException; - } + ReturnResult returnStatus = ReturnResult.InProgress; var destinations = new List(); List binItems = null; - foreach (IStorageItem item in source) + foreach (var item in source) { if (recycleBinHelpers.IsPathUnderRecycleBin(item.Path)) { @@ -919,29 +908,57 @@ not when file name has changed */ #endregion Rename - public async Task RecycleItemsFromClipboard(DataPackageView packageView, string destination, bool showDialog, bool registerHistory) + public async Task CreateShortcutFromClipboard(DataPackageView packageView, string destination, bool showDialog, bool registerHistory) { - if (!packageView.Contains(StandardDataFormats.StorageItems)) + if (!HasDraggedStorageItems(packageView)) { // Happens if you copy some text and then you Ctrl+V in Files return ReturnResult.BadArgumentException; } - IReadOnlyList source; - try - { - source = await packageView.GetStorageItemsAsync(); - } - catch (Exception ex) when ((uint)ex.HResult == 0x80040064 || (uint)ex.HResult == 0x8004006A) + var (handledByFtp, source) = await GetDraggedStorageItems(packageView); + + if (handledByFtp) { // Not supported return ReturnResult.Failed; } - catch (Exception ex) + + var returnCode = FileSystemStatusCode.InProgress; + var errorCode = new Progress(); + errorCode.ProgressChanged += (s, e) => returnCode = e; + + source = source.Where(x => !string.IsNullOrEmpty(x.Path)); + var dest = source.Select(x => Path.Combine(destination, + string.Format("ShortcutCreateNewSuffix".GetLocalized(), x.Name) + ".lnk")); + + var history = await filesystemOperations.CreateShortcutItemsAsync(source, dest, null, errorCode, cancellationToken); + + if (registerHistory) + { + App.HistoryWrapper.AddHistory(history); + } + + await Task.Yield(); + return returnCode.ToStatus(); + } + + public async Task RecycleItemsFromClipboard(DataPackageView packageView, string destination, bool showDialog, bool registerHistory) + { + if (!HasDraggedStorageItems(packageView)) + { + // Happens if you copy some text and then you Ctrl+V in Files + return ReturnResult.BadArgumentException; + } + + var (handledByFtp, source) = await GetDraggedStorageItems(packageView); + + if (handledByFtp) { - App.Logger.Warn(ex, ex.Message); - return ReturnResult.UnknownException; + // Not supported + return ReturnResult.Failed; } + ReturnResult returnStatus = ReturnResult.InProgress; source = source.Where(x => !recycleBinHelpers.IsPathUnderRecycleBin(x.Path)).ToList(); // Can't recycle items already in recyclebin @@ -961,7 +978,7 @@ public async Task RecycleItemsFromClipboard(DataPackageView packag for (int i = 0; i < source.Count(); i++) { - var itemPathOrName = string.IsNullOrEmpty(source.ElementAt(i).Path) ? + var itemPathOrName = string.IsNullOrEmpty(source.ElementAt(i).Path) ? (string.IsNullOrEmpty(source.ElementAt(i).Item.Path) ? source.ElementAt(i).Item.Name : source.ElementAt(i).Item.Path) : source.ElementAt(i).Path; incomingItems.Add(new FilesystemItemsOperationItemModel(operationType, itemPathOrName, destination.ElementAt(i))); collisions.Add(incomingItems.ElementAt(i).SourcePath, FileNameConflictResolveOptionType.GenerateNewName); @@ -1028,104 +1045,39 @@ public async Task RecycleItemsFromClipboard(DataPackageView packag #region Public Helpers - public static async Task GetItemSize(IStorageItem item) + public static bool HasDraggedStorageItems(DataPackageView packageView) { - if (item == null) - { - return 0L; - } - - if (item.IsOfType(StorageItemTypes.Folder)) - { - return await CalculateFolderSizeAsync(item.Path); - } - else - { - return CalculateFileSize(item.Path); - } + return packageView.Contains(StandardDataFormats.StorageItems) || (packageView.Properties.TryGetValue("FileDrop", out var data)); } - public static async Task CalculateFolderSizeAsync(string path) + public static async Task<(bool handledByFtp, IEnumerable items)> GetDraggedStorageItems(DataPackageView packageView) { - if (string.IsNullOrEmpty(path)) - { - // In MTP devices calculating folder size would be too slow - // Also should use StorageFolder methods instead of FindFirstFileExFromApp - return 0; - } - - long size = 0; - FINDEX_INFO_LEVELS findInfoLevel = FINDEX_INFO_LEVELS.FindExInfoBasic; - int additionalFlags = FIND_FIRST_EX_LARGE_FETCH; - - IntPtr hFile = FindFirstFileExFromApp( - path + "\\*.*", - findInfoLevel, - out WIN32_FIND_DATA findData, - FINDEX_SEARCH_OPS.FindExSearchNameMatch, - IntPtr.Zero, - additionalFlags); - - int count = 0; - if (hFile.ToInt64() != -1) + var itemsList = new List(); + if (packageView.Contains(StandardDataFormats.StorageItems)) { - do + try { - if (((FileAttributes)findData.dwFileAttributes & FileAttributes.Directory) != FileAttributes.Directory) - { - size += findData.GetSize(); - ++count; - } - else if (((FileAttributes)findData.dwFileAttributes & FileAttributes.Directory) == FileAttributes.Directory) - { - if (findData.cFileName != "." && findData.cFileName != "..") - { - string itemPath = Path.Combine(path, findData.cFileName); - - size += await CalculateFolderSizeAsync(itemPath); - ++count; - } - } - } while (FindNextFile(hFile, out findData)); - FindClose(hFile); - return size; - } - else - { - return 0; - } - } - - public static long CalculateFileSize(string path) - { - if (string.IsNullOrEmpty(path)) - { - // In MTP devices calculating folder size would be too slow - // Also should use StorageFolder methods instead of FindFirstFileExFromApp - return 0; - } - - long size = 0; - FINDEX_INFO_LEVELS findInfoLevel = FINDEX_INFO_LEVELS.FindExInfoBasic; - int additionalFlags = FIND_FIRST_EX_LARGE_FETCH; - - IntPtr hFile = FindFirstFileExFromApp(path, findInfoLevel, out WIN32_FIND_DATA findData, FINDEX_SEARCH_OPS.FindExSearchNameMatch, IntPtr.Zero, - additionalFlags); - - if (hFile.ToInt64() != -1) - { - if (((FileAttributes)findData.dwFileAttributes & FileAttributes.Directory) != FileAttributes.Directory) + var source = await packageView.GetStorageItemsAsync(); + itemsList.AddRange(source.Select(x => x.FromStorageItem())); + } + catch (Exception ex) when ((uint)ex.HResult == 0x80040064 || (uint)ex.HResult == 0x8004006A) { - size += findData.GetSize(); + return (true, itemsList); + } + catch (Exception ex) + { + App.Logger.Warn(ex, ex.Message); + return (false, itemsList); } - FindClose(hFile); - Debug.WriteLine($"Individual file size for Progress UI will be reported as: {size} bytes"); - return size; } - else + if (packageView.Properties.TryGetValue("FileDrop", out var data)) { - return 0; + if (data is List source) + { + itemsList.AddRange(source); + } } + return (false, itemsList); } public static bool ContainsRestrictedCharacters(string input) @@ -1157,20 +1109,6 @@ public static bool ContainsRestrictedFileName(string input) return false; } - public async Task OpenShellCommandInExplorerAsync(string shellCommand, NamedPipeAsAppServiceConnection connection) - { - Debug.WriteLine("Launching shell command in FullTrustProcess"); - if (connection != null) - { - ValueSet value = new ValueSet() - { - { "ShellCommand", shellCommand }, - { "Arguments", "ShellCommand" } - }; - await connection.SendMessageAsync(value); - } - } - #endregion Public Helpers #region IDisposable diff --git a/Files/Filesystem/FilesystemOperations/Helpers/IFilesystemHelpers.cs b/Files/Filesystem/FilesystemOperations/Helpers/IFilesystemHelpers.cs index 258e652cadf9..8646ffc9cca2 100644 --- a/Files/Filesystem/FilesystemOperations/Helpers/IFilesystemHelpers.cs +++ b/Files/Filesystem/FilesystemOperations/Helpers/IFilesystemHelpers.cs @@ -144,6 +144,10 @@ public interface IFilesystemHelpers : IDisposable /// of performed operation Task CopyItemsFromClipboard(DataPackageView packageView, string destination, bool showDialog, bool registerHistory); + Task RecycleItemsFromClipboard(DataPackageView packageView, string destination, bool showDialog, bool registerHistory); + + Task CreateShortcutFromClipboard(DataPackageView packageView, string destination, bool showDialog, bool registerHistory); + #endregion Copy #region Move diff --git a/Files/Filesystem/FilesystemOperations/IFilesystemOperations.cs b/Files/Filesystem/FilesystemOperations/IFilesystemOperations.cs index c41a99c54bc9..1a8bd20be3de 100644 --- a/Files/Filesystem/FilesystemOperations/IFilesystemOperations.cs +++ b/Files/Filesystem/FilesystemOperations/IFilesystemOperations.cs @@ -32,6 +32,8 @@ public interface IFilesystemOperations : IDisposable /// Task<(IStorageHistory, IStorageItem)> CreateAsync(IStorageItemWithPath source, IProgress errorCode, CancellationToken cancellationToken); + Task CreateShortcutItemsAsync(IEnumerable source, IEnumerable destination, IProgress progress, IProgress errorCode, CancellationToken cancellationToken); + /// /// Copies to fullPath /// diff --git a/Files/Filesystem/FilesystemOperations/ShellFilesystemOperations.cs b/Files/Filesystem/FilesystemOperations/ShellFilesystemOperations.cs index f47d3553a677..f70e89ec5e73 100644 --- a/Files/Filesystem/FilesystemOperations/ShellFilesystemOperations.cs +++ b/Files/Filesystem/FilesystemOperations/ShellFilesystemOperations.cs @@ -157,6 +157,42 @@ public async Task CopyItemsAsync(IEnumerable CreateShortcutItemsAsync(IEnumerable source, IEnumerable destination, IProgress progress, IProgress errorCode, CancellationToken cancellationToken) + { + var createdSources = new List(); + var createdDestination = new List(); + + var connection = await AppServiceConnectionHelper.Instance; + if (connection != null) + { + var items = source.Zip(destination, (src, dest) => new { src, dest }).Where(x => !string.IsNullOrEmpty(x.src.Path) && !string.IsNullOrEmpty(x.dest)); + for (int i = 0; i < items.Count(); i++) + { + var value = new ValueSet() + { + { "Arguments", "FileOperation" }, + { "fileop", "CreateLink" }, + { "targetpath", items.ElementAt(i).src.Path }, + { "arguments", "" }, + { "workingdir", "" }, + { "runasadmin", false }, + { "filepath", items.ElementAt(i).dest } + }; + var (status, response) = await connection.SendMessageForResponseAsync(value); + var success = status == AppServiceResponseStatus.Success && response.Get("Success", false); + if (success) + { + createdSources.Add(items.ElementAt(i).src); + createdDestination.Add(StorageItemHelpers.FromPathAndType(items.ElementAt(i).dest, FilesystemItemType.File)); + } + progress?.Report(i / (float)source.Count() * 100.0f); + } + } + + errorCode?.Report(createdSources.Count() == source.Count() ? FileSystemStatusCode.Success : FileSystemStatusCode.Generic); + return new StorageHistory(FileOperationType.CreateLink, createdSources, createdDestination); + } + public async Task DeleteAsync(IStorageItem source, IProgress progress, IProgress errorCode, bool permanently, CancellationToken cancellationToken) { return await DeleteAsync(source.FromStorageItem(), @@ -194,7 +230,7 @@ public async Task DeleteItemsAsync(IEnumerable Path.Combine(Path.GetDirectoryName(x.Path), Path.GetFileName(x.Path).Replace("$R", "$I")))); + 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(); diff --git a/Files/Filesystem/StorageFileHelpers/IStorageItemWithPath.cs b/Files/Filesystem/StorageFileHelpers/IStorageItemWithPath.cs index 46e508639700..388e20e398e8 100644 --- a/Files/Filesystem/StorageFileHelpers/IStorageItemWithPath.cs +++ b/Files/Filesystem/StorageFileHelpers/IStorageItemWithPath.cs @@ -5,6 +5,7 @@ namespace Files.Filesystem public interface IStorageItemWithPath // TODO: Maybe use here : IStorageItem instead of declaring a variable, // and keep the Path property for it to override IStorageItem.Path ? { + public string Name { get; } public string Path { get; set; } public IStorageItem Item { get; set; } public FilesystemItemType ItemType { get; } diff --git a/Files/Filesystem/StorageFileHelpers/StorageFileExtensions.cs b/Files/Filesystem/StorageFileHelpers/StorageFileExtensions.cs index b975ecffc706..37aaa95b0cca 100644 --- a/Files/Filesystem/StorageFileHelpers/StorageFileExtensions.cs +++ b/Files/Filesystem/StorageFileHelpers/StorageFileExtensions.cs @@ -253,12 +253,12 @@ public static string GetPathWithoutEnvironmentVariable(string path) return Environment.ExpandEnvironmentVariables(path); } - public static bool AreItemsInSameDrive(this IEnumerable storageItems, string destinationPath) + public static bool AreItemsInSameDrive(this IEnumerable itemsPath, string destinationPath) { try { - return storageItems.Any(storageItem => - Path.GetPathRoot(storageItem.Path).Equals( + return itemsPath.Any(itemPath => + Path.GetPathRoot(itemPath).Equals( Path.GetPathRoot(destinationPath), StringComparison.OrdinalIgnoreCase)); } @@ -268,12 +268,22 @@ public static bool AreItemsInSameDrive(this IEnumerable storageIte } } - public static bool AreItemsAlreadyInFolder(this IEnumerable storageItems, string destinationPath) + public static bool AreItemsInSameDrive(this IEnumerable storageItems, string destinationPath) + { + return storageItems.Select(x => x.Path).AreItemsInSameDrive(destinationPath); + } + + public static bool AreItemsInSameDrive(this IEnumerable storageItems, string destinationPath) + { + return storageItems.Select(x => x.Path).AreItemsInSameDrive(destinationPath); + } + + public static bool AreItemsAlreadyInFolder(this IEnumerable itemsPath, string destinationPath) { try { - return storageItems.All(storageItem => - Path.GetDirectoryName(storageItem.Path).Equals( + return itemsPath.All(itemPath => + Path.GetDirectoryName(itemPath).Equals( destinationPath.TrimPath(), StringComparison.OrdinalIgnoreCase)); } catch @@ -281,5 +291,15 @@ public static bool AreItemsAlreadyInFolder(this IEnumerable storag return false; } } + + public static bool AreItemsAlreadyInFolder(this IEnumerable storageItems, string destinationPath) + { + return storageItems.Select(x => x.Path).AreItemsAlreadyInFolder(destinationPath); + } + + public static bool AreItemsAlreadyInFolder(this IEnumerable storageItems, string destinationPath) + { + return storageItems.Select(x => x.Path).AreItemsAlreadyInFolder(destinationPath); + } } } \ No newline at end of file diff --git a/Files/Filesystem/StorageFileHelpers/StorageFileWithPath.cs b/Files/Filesystem/StorageFileHelpers/StorageFileWithPath.cs index f5397dc1efb3..ece4699b50a7 100644 --- a/Files/Filesystem/StorageFileHelpers/StorageFileWithPath.cs +++ b/Files/Filesystem/StorageFileHelpers/StorageFileWithPath.cs @@ -17,6 +17,7 @@ public StorageFile File } public string Path { get; set; } + public string Name => Item?.Name ?? System.IO.Path.GetFileName(Path); public IStorageItem Item { get; set; } public FilesystemItemType ItemType => FilesystemItemType.File; diff --git a/Files/Filesystem/StorageFileHelpers/StorageFolderWithPath.cs b/Files/Filesystem/StorageFileHelpers/StorageFolderWithPath.cs index 63174d5fe842..fc1a893fdee7 100644 --- a/Files/Filesystem/StorageFileHelpers/StorageFolderWithPath.cs +++ b/Files/Filesystem/StorageFileHelpers/StorageFolderWithPath.cs @@ -17,6 +17,7 @@ public StorageFolder Folder } public string Path { get; set; } + public string Name => Item?.Name ?? System.IO.Path.GetFileName(Path); public IStorageItem Item { get; set; } public FilesystemItemType ItemType => FilesystemItemType.Directory; diff --git a/Files/Filesystem/StorageHistory/StorageHistoryOperations.cs b/Files/Filesystem/StorageHistory/StorageHistoryOperations.cs index 91b608f390c5..fea0da9a9cb3 100644 --- a/Files/Filesystem/StorageHistory/StorageHistoryOperations.cs +++ b/Files/Filesystem/StorageHistory/StorageHistoryOperations.cs @@ -63,6 +63,18 @@ public async Task Redo(IStorageHistory history) break; } + case FileOperationType.CreateLink: // CreateLink PASS + { + if (IsHistoryNull(history)) + { + break; + } + + await filesystemOperations.CreateShortcutItemsAsync(history.Source, history.Destination.Select(item => item.Path), null, errorCode, cancellationToken); + + break; + } + case FileOperationType.Rename: // Rename PASS { if (IsHistoryNull(history)) @@ -180,6 +192,18 @@ public async Task Undo(IStorageHistory history) return await filesystemHelpers.DeleteItemsAsync(history.Source, false, true, false); } + case FileOperationType.CreateLink: // CreateLink PASS + { + // Opposite: Delete created items + + if (IsHistoryNull(history.Destination)) + { + break; + } + + return await filesystemHelpers.DeleteItemsAsync(history.Destination, false, true, false); + } + case FileOperationType.Rename: // Rename PASS { // Opposite: Restore original item names diff --git a/Files/Helpers/ContextFlyoutItemHelper.cs b/Files/Helpers/ContextFlyoutItemHelper.cs index 6f9588fdebc6..d6dde9783811 100644 --- a/Files/Helpers/ContextFlyoutItemHelper.cs +++ b/Files/Helpers/ContextFlyoutItemHelper.cs @@ -608,9 +608,10 @@ public static List GetBaseItemMenuItems(BaseLayo Items = new List() { new() { - Text = "Placeholder....." + Text = "Placeholder" } }, + ShowInSearchPage = true, ShowItem = selectedItems.All(i => i.PrimaryItemAttribute == Windows.Storage.StorageItemTypes.File && !i.IsShortcutItem), }, new ContextMenuFlyoutItemViewModel() @@ -825,7 +826,7 @@ public static List GetBaseItemMenuItems(BaseLayo OverlayLayerGlyph = "\u0026", }, Command = commandsViewModel.ShareItemCommand, - ShowItem = DataTransferManager.IsSupported() && !selectedItems.Any(i => i.IsHiddenItem || i.IsShortcutItem || i.PrimaryItemAttribute == StorageItemTypes.Folder), + ShowItem = DataTransferManager.IsSupported() && !selectedItems.Any(i => i.IsHiddenItem || (i.IsShortcutItem && !i.IsLinkItem) || i.PrimaryItemAttribute == StorageItemTypes.Folder), }, new ContextMenuFlyoutItemViewModel() { diff --git a/Files/Helpers/ShellContextMenuHelper.cs b/Files/Helpers/ShellContextMenuHelper.cs index d5b51b6e5fde..f40f030009e7 100644 --- a/Files/Helpers/ShellContextMenuHelper.cs +++ b/Files/Helpers/ShellContextMenuHelper.cs @@ -136,23 +136,23 @@ public static void LoadMenuFlyoutItem(IList menu } } - static async void InvokeShellMenuItem(object tag) + async void InvokeShellMenuItem(object tag) { var connection = await AppServiceConnectionHelper.Instance; var (menuItem, menuHandle) = ParseContextMenuTag(tag); if (connection != null) { await connection.SendMessageAsync(new ValueSet() - { - { "Arguments", "ExecAndCloseContextMenu" }, - { "Handle", menuHandle }, - { "ItemID", menuItem.ID }, - { "CommandString", menuItem.CommandString } - }); + { + { "Arguments", "ExecAndCloseContextMenu" }, + { "Handle", menuHandle }, + { "ItemID", menuItem.ID }, + { "CommandString", menuItem.CommandString } + }); } } - static (Win32ContextMenuItem menuItem, string menuHandle) ParseContextMenuTag(object tag) + (Win32ContextMenuItem menuItem, string menuHandle) ParseContextMenuTag(object tag) { if (tag is ValueTuple tuple) { diff --git a/Files/Helpers/StorageItemHelpers.cs b/Files/Helpers/StorageItemHelpers.cs index 7f56a8f8e7b4..8605f8a38eac 100644 --- a/Files/Helpers/StorageItemHelpers.cs +++ b/Files/Helpers/StorageItemHelpers.cs @@ -2,7 +2,6 @@ using Files.Filesystem; using Files.Filesystem.StorageItems; using System; -using System.Diagnostics; using System.Threading.Tasks; using Windows.Storage; using Windows.Storage.FileProperties; @@ -27,19 +26,11 @@ public static async Task ToStorageItem(string path, IShellPage assoc if (path.ToLower().EndsWith(".lnk") || path.ToLower().EndsWith(".url")) { // TODO: In the future, when IStorageItemWithPath will inherit from IStorageItem, - // we could implement this code here for getting .lnk files - // for now, we can't - + // we could implement this code here for getting .lnk files + // for now, we can't return default; - - if (false) // Prevent unnecessary exceptions - { - Debugger.Break(); - throw new ArgumentException("Function ToStorageItem() does not support converting from .lnk and .url files"); - } } - - if (typeof(IStorageFile).IsAssignableFrom(typeof(TOut))) + else if (typeof(IStorageFile).IsAssignableFrom(typeof(TOut))) { await GetFile(); } diff --git a/Files/Interacts/BaseLayoutCommandImplementationModel.cs b/Files/Interacts/BaseLayoutCommandImplementationModel.cs index 370471b3794e..949ca8631508 100644 --- a/Files/Interacts/BaseLayoutCommandImplementationModel.cs +++ b/Files/Interacts/BaseLayoutCommandImplementationModel.cs @@ -529,35 +529,22 @@ public virtual async void DragOver(DragEventArgs e) } itemManipulationModel.ClearSelection(); - if (e.DataView.Contains(StandardDataFormats.StorageItems)) + + if (Filesystem.FilesystemHelpers.HasDraggedStorageItems(e.DataView)) { e.Handled = true; - IEnumerable draggedItems; - try - { - draggedItems = await e.DataView.GetStorageItemsAsync(); - } - catch (Exception ex) when ((uint)ex.HResult == 0x80040064 || (uint)ex.HResult == 0x8004006A) - { - // Handled by FTP - draggedItems = new List(); - } - catch (Exception ex) - { - App.Logger.Warn(ex, ex.Message); - e.AcceptedOperation = DataPackageOperation.None; - deferral.Complete(); - return; - } + + var (handledByFtp, draggedItems) = await Filesystem.FilesystemHelpers.GetDraggedStorageItems(e.DataView); var pwd = associatedInstance.FilesystemViewModel.WorkingDirectory.TrimPath(); var folderName = (Path.IsPathRooted(pwd) && Path.GetPathRoot(pwd) == pwd) ? Path.GetPathRoot(pwd) : Path.GetFileName(pwd); + // As long as one file doesn't already belong to this folder if (associatedInstance.InstanceViewModel.IsPageTypeSearchResults || (draggedItems.Any() && draggedItems.AreItemsAlreadyInFolder(associatedInstance.FilesystemViewModel.WorkingDirectory))) { e.AcceptedOperation = DataPackageOperation.None; } - else if (!draggedItems.Any()) + else if (handledByFtp) { if (pwd.StartsWith(App.AppSettings.RecycleBinPath)) { @@ -570,6 +557,10 @@ public virtual async void DragOver(DragEventArgs e) e.AcceptedOperation = DataPackageOperation.Copy; } } + else if (!draggedItems.Any()) + { + e.AcceptedOperation = DataPackageOperation.None; + } else { e.DragUIOverride.IsCaptionVisible = true; @@ -578,6 +569,11 @@ public virtual async void DragOver(DragEventArgs e) e.DragUIOverride.Caption = string.Format("MoveToFolderCaptionText".GetLocalized(), folderName); e.AcceptedOperation = DataPackageOperation.Move; } + else if (e.Modifiers.HasFlag(DragDropModifiers.Alt) || e.Modifiers.HasFlag(DragDropModifiers.Control | DragDropModifiers.Shift)) + { + e.DragUIOverride.Caption = string.Format("LinkToFolderCaptionText".GetLocalized(), folderName); + e.AcceptedOperation = DataPackageOperation.Link; + } else if (e.Modifiers.HasFlag(DragDropModifiers.Control)) { e.DragUIOverride.Caption = string.Format("CopyToFolderCaptionText".GetLocalized(), folderName); @@ -608,7 +604,7 @@ public virtual async void Drop(DragEventArgs e) { var deferral = e.GetDeferral(); - if (e.DataView.Contains(StandardDataFormats.StorageItems)) + if (Filesystem.FilesystemHelpers.HasDraggedStorageItems(e.DataView)) { await associatedInstance.FilesystemHelpers.PerformOperationTypeAsync(e.AcceptedOperation, e.DataView, associatedInstance.FilesystemViewModel.WorkingDirectory, false, true); e.Handled = true; @@ -627,9 +623,9 @@ public void SearchUnindexedItems(RoutedEventArgs e) associatedInstance.SubmitSearch(associatedInstance.InstanceViewModel.CurrentSearchQuery, true); } - public void CreateFolderWithSelection(RoutedEventArgs e) + public async void CreateFolderWithSelection(RoutedEventArgs e) { - UIFilesystemHelpers.CreateFolderWithSelectionAsync(associatedInstance); + await UIFilesystemHelpers.CreateFolderWithSelectionAsync(associatedInstance); } public async void DecompressArchive() diff --git a/Files/Strings/en-US/Resources.resw b/Files/Strings/en-US/Resources.resw index ca968050ebd1..ad5a5dcbc1bc 100644 --- a/Files/Strings/en-US/Resources.resw +++ b/Files/Strings/en-US/Resources.resw @@ -2794,4 +2794,7 @@ We use App Center to keep track of app usage, find bugs, and fix crashes. All in No items found - + + Create link in {0} + + \ No newline at end of file diff --git a/Files/UserControls/SidebarControl.xaml.cs b/Files/UserControls/SidebarControl.xaml.cs index 905200bc5d69..d2ed18d02810 100644 --- a/Files/UserControls/SidebarControl.xaml.cs +++ b/Files/UserControls/SidebarControl.xaml.cs @@ -455,28 +455,13 @@ private async void NavigationViewLocationItem_DragOver(object sender, DragEventA return; } - // If the dragged item is a folder or file from a file system - if (e.DataView.Contains(StandardDataFormats.StorageItems)) + var deferral = e.GetDeferral(); + + if (Filesystem.FilesystemHelpers.HasDraggedStorageItems(e.DataView)) { - var deferral = e.GetDeferral(); e.Handled = true; - IReadOnlyList storageItems; - try - { - storageItems = await e.DataView.GetStorageItemsAsync(); - } - catch (Exception ex) when ((uint)ex.HResult == 0x80040064 || (uint)ex.HResult == 0x8004006A) - { - // Handled by FTP - storageItems = new List(); - } - catch (Exception ex) - { - App.Logger.Warn(ex, ex.Message); - e.AcceptedOperation = DataPackageOperation.None; - deferral.Complete(); - return; - } + + var (handledByFtp, storageItems) = await Filesystem.FilesystemHelpers.GetDraggedStorageItems(e.DataView); if (string.IsNullOrEmpty(locationItem.Path) || (storageItems.Any() && storageItems.AreItemsAlreadyInFolder(locationItem.Path)) @@ -484,7 +469,7 @@ private async void NavigationViewLocationItem_DragOver(object sender, DragEventA { e.AcceptedOperation = DataPackageOperation.None; } - else if (!storageItems.Any()) + else if (handledByFtp) { if (locationItem.Path.StartsWith(App.AppSettings.RecycleBinPath)) { @@ -497,6 +482,10 @@ private async void NavigationViewLocationItem_DragOver(object sender, DragEventA e.AcceptedOperation = DataPackageOperation.Copy; } } + else if (!storageItems.Any()) + { + e.AcceptedOperation = DataPackageOperation.None; + } else { e.DragUIOverride.IsCaptionVisible = true; @@ -505,6 +494,11 @@ private async void NavigationViewLocationItem_DragOver(object sender, DragEventA e.DragUIOverride.Caption = string.Format("MoveToFolderCaptionText".GetLocalized(), locationItem.Text); e.AcceptedOperation = DataPackageOperation.Move; } + else if (e.Modifiers.HasFlag(DragDropModifiers.Alt) || e.Modifiers.HasFlag(DragDropModifiers.Control | DragDropModifiers.Shift)) + { + e.DragUIOverride.Caption = string.Format("LinkToFolderCaptionText".GetLocalized(), locationItem.Text); + e.AcceptedOperation = DataPackageOperation.Link; + } else if (e.Modifiers.HasFlag(DragDropModifiers.Control)) { e.DragUIOverride.Caption = string.Format("CopyToFolderCaptionText".GetLocalized(), locationItem.Text); @@ -526,15 +520,14 @@ private async void NavigationViewLocationItem_DragOver(object sender, DragEventA e.DragUIOverride.Caption = string.Format("CopyToFolderCaptionText".GetLocalized(), locationItem.Text); } } - - deferral.Complete(); } else if ((e.DataView.Properties["sourceLocationItem"] as Microsoft.UI.Xaml.Controls.NavigationViewItem)?.DataContext is LocationItem sourceLocationItem) { // else if the drag over event is called over a location item - NavigationViewLocationItem_DragOver_SetCaptions(locationItem, sourceLocationItem, e); } + + deferral.Complete(); } /// @@ -570,7 +563,7 @@ private void NavigationViewLocationItem_Drop(object sender, DragEventArgs e) } // If the dropped item is a folder or file from a file system - if (e.DataView.Contains(StandardDataFormats.StorageItems)) + if (Filesystem.FilesystemHelpers.HasDraggedStorageItems(e.DataView)) { VisualStateManager.GoToState(sender as Microsoft.UI.Xaml.Controls.NavigationViewItem, "Drop", false); @@ -595,46 +588,40 @@ private void NavigationViewLocationItem_Drop(object sender, DragEventArgs e) private async void NavigationViewDriveItem_DragOver(object sender, DragEventArgs e) { if (!((sender as Microsoft.UI.Xaml.Controls.NavigationViewItem).DataContext is DriveItem driveItem) || - !e.DataView.Contains(StandardDataFormats.StorageItems)) + !Filesystem.FilesystemHelpers.HasDraggedStorageItems(e.DataView)) { return; } var deferral = e.GetDeferral(); e.Handled = true; - IReadOnlyList storageItems; - try - { - storageItems = await e.DataView.GetStorageItemsAsync(); - } - catch (Exception ex) when ((uint)ex.HResult == 0x80040064 || (uint)ex.HResult == 0x8004006A) - { - // Handled by FTP - storageItems = new List(); - } - catch (Exception ex) - { - App.Logger.Warn(ex, ex.Message); - e.AcceptedOperation = DataPackageOperation.None; - deferral.Complete(); - return; - } + var (handledByFtp, storageItems) = await Filesystem.FilesystemHelpers.GetDraggedStorageItems(e.DataView); + if ("DriveCapacityUnknown".GetLocalized().Equals(driveItem.SpaceText, StringComparison.OrdinalIgnoreCase) || (storageItems.Any() && storageItems.AreItemsAlreadyInFolder(driveItem.Path))) { e.AcceptedOperation = DataPackageOperation.None; } - else if (!storageItems.Any()) + else if (handledByFtp) { e.DragUIOverride.IsCaptionVisible = true; e.DragUIOverride.Caption = string.Format("CopyToFolderCaptionText".GetLocalized(), driveItem.Text); e.AcceptedOperation = DataPackageOperation.Copy; } + else if (!storageItems.Any()) + { + e.AcceptedOperation = DataPackageOperation.None; + } else { e.DragUIOverride.IsCaptionVisible = true; - if (e.Modifiers.HasFlag(DragDropModifiers.Control)) + if (e.Modifiers.HasFlag(DragDropModifiers.Alt) || e.Modifiers.HasFlag(DragDropModifiers.Control | DragDropModifiers.Shift)) + { + e.DragUIOverride.Caption = string.Format("LinkToFolderCaptionText".GetLocalized(), driveItem.Text); + e.AcceptedOperation = DataPackageOperation.Link; + } + else if (e.Modifiers.HasFlag(DragDropModifiers.Control)) { e.DragUIOverride.Caption = string.Format("CopyToFolderCaptionText".GetLocalized(), driveItem.Text); e.AcceptedOperation = DataPackageOperation.Copy; diff --git a/Files/ViewModels/NavToolbarViewModel.cs b/Files/ViewModels/NavToolbarViewModel.cs index 5a2e40dd671c..8e146acdb02f 100644 --- a/Files/ViewModels/NavToolbarViewModel.cs +++ b/Files/ViewModels/NavToolbarViewModel.cs @@ -428,7 +428,7 @@ public async void PathBoxItem_DragOver(object sender, DragEventArgs e) } } - if (!e.DataView.Contains(StandardDataFormats.StorageItems)) + if (!Filesystem.FilesystemHelpers.HasDraggedStorageItems(e.DataView)) { e.AcceptedOperation = DataPackageOperation.None; return; @@ -442,20 +442,9 @@ public async void PathBoxItem_DragOver(object sender, DragEventArgs e) e.Handled = true; var deferral = e.GetDeferral(); - IReadOnlyList storageItems; - try + var (handledByFtp, storageItems) = await Filesystem.FilesystemHelpers.GetDraggedStorageItems(e.DataView); + if (handledByFtp) { - storageItems = await e.DataView.GetStorageItemsAsync(); - } - catch (Exception ex) when ((uint)ex.HResult == 0x80040064 || (uint)ex.HResult == 0x8004006A) - { - e.AcceptedOperation = DataPackageOperation.None; - deferral.Complete(); - return; - } - catch (Exception ex) - { - App.Logger.Warn(ex, ex.Message); e.AcceptedOperation = DataPackageOperation.None; deferral.Complete(); return; @@ -977,7 +966,7 @@ public List SelectedItems } public bool CanCopy => SelectedItems is not null && SelectedItems.Any(); - public bool CanShare => SelectedItems is not null && SelectedItems.Any() && DataTransferManager.IsSupported() && !SelectedItems.Any(x => x.IsShortcutItem || x.IsHiddenItem || x.PrimaryItemAttribute == StorageItemTypes.Folder); + public bool CanShare => SelectedItems is not null && SelectedItems.Any() && DataTransferManager.IsSupported() && !SelectedItems.Any(x => (x.IsShortcutItem && !x.IsLinkItem) || x.IsHiddenItem || x.PrimaryItemAttribute == StorageItemTypes.Folder); public bool CanRename => SelectedItems is not null && SelectedItems.Count == 1; public void Dispose() diff --git a/Files/ViewModels/Widgets/Bundles/BundleContainerViewModel.cs b/Files/ViewModels/Widgets/Bundles/BundleContainerViewModel.cs index ed4b3f24bec8..3172c3d0798e 100644 --- a/Files/ViewModels/Widgets/Bundles/BundleContainerViewModel.cs +++ b/Files/ViewModels/Widgets/Bundles/BundleContainerViewModel.cs @@ -286,7 +286,7 @@ private void RenameBundleConfirm(string bundleRenameText) private void DragOver(DragEventArgs e) { - if (e.DataView.Contains(StandardDataFormats.StorageItems) || e.DataView.Contains(StandardDataFormats.Text)) + if (Filesystem.FilesystemHelpers.HasDraggedStorageItems(e.DataView) || e.DataView.Contains(StandardDataFormats.Text)) { if (Contents.Count < Constants.Widgets.Bundles.MaxAmountOfItemsPerBundle) // Don't exceed the limit! { @@ -308,11 +308,11 @@ private async Task Drop(DragEventArgs e) { bool itemsAdded = false; - if (e.DataView.Contains(StandardDataFormats.StorageItems)) + if (Filesystem.FilesystemHelpers.HasDraggedStorageItems(e.DataView)) { - IReadOnlyList items = await e.DataView.GetStorageItemsAsync(); + var (_, items) = await Filesystem.FilesystemHelpers.GetDraggedStorageItems(e.DataView); - if (await AddItemsFromPath(items.ToDictionary((item) => item.Path, (item) => item.IsOfType(StorageItemTypes.Folder) ? FilesystemItemType.Directory : FilesystemItemType.File))) + if (await AddItemsFromPath(items.ToDictionary((item) => item.Path, (item) => item.ItemType))) { itemsAdded = true; } diff --git a/Files/Views/ColumnShellPage.xaml.cs b/Files/Views/ColumnShellPage.xaml.cs index 75782022a6cc..69775456e0b5 100644 --- a/Files/Views/ColumnShellPage.xaml.cs +++ b/Files/Views/ColumnShellPage.xaml.cs @@ -211,23 +211,6 @@ private void ColumnViewBase_ItemInvoked(object sender, EventArgs e) { } - private void CopyWorkingLocation() - { - try - { - if (this.SlimContentPage != null) - { - DataPackage data = new DataPackage(); - data.SetText(this.FilesystemViewModel.WorkingDirectory); - Clipboard.SetContent(data); - Clipboard.Flush(); - } - } - catch - { - } - } - private void FolderSettings_LayoutPreferencesUpdateRequired(object sender, LayoutPreferenceEventArgs e) { if (FilesystemViewModel != null) @@ -892,7 +875,7 @@ private void SetLoadingIndicatorForTabs(bool isLoading) public DataPackageOperation TabItemDragOver(object sender, DragEventArgs e) { - if (e.DataView.AvailableFormats.Contains(StandardDataFormats.StorageItems)) + if (Filesystem.FilesystemHelpers.HasDraggedStorageItems(e.DataView)) { if (!InstanceViewModel.IsPageTypeSearchResults) { @@ -904,7 +887,7 @@ public DataPackageOperation TabItemDragOver(object sender, DragEventArgs e) public async Task TabItemDrop(object sender, DragEventArgs e) { - if (e.DataView.AvailableFormats.Contains(StandardDataFormats.StorageItems)) + if (Filesystem.FilesystemHelpers.HasDraggedStorageItems(e.DataView)) { if (InstanceViewModel.IsPageTypeNotHome && !InstanceViewModel.IsPageTypeSearchResults) { diff --git a/Files/Views/ModernShellPage.xaml.cs b/Files/Views/ModernShellPage.xaml.cs index 487c6eeabca0..fe56087a534e 100644 --- a/Files/Views/ModernShellPage.xaml.cs +++ b/Files/Views/ModernShellPage.xaml.cs @@ -216,23 +216,6 @@ private void ModernShellPage_RefreshWidgetsRequested(object sender, EventArgs e) currentPage.RefreshWidgetList(); } - private void CopyLocation() - { - try - { - if (this.SlimContentPage != null && SlimContentPage.SelectedItems is not null && SlimContentPage.SelectedItems.Any()) - { - DataPackage data = new DataPackage(); - data.SetText(this.FilesystemViewModel.WorkingDirectory); - Clipboard.SetContent(data); - Clipboard.Flush(); - } - } - catch - { - } - } - private void FolderSettings_LayoutPreferencesUpdateRequired(object sender, LayoutPreferenceEventArgs e) { if (FilesystemViewModel != null) @@ -1042,7 +1025,7 @@ private void SetLoadingIndicatorForTabs(bool isLoading) public DataPackageOperation TabItemDragOver(object sender, DragEventArgs e) { - if (e.DataView.AvailableFormats.Contains(StandardDataFormats.StorageItems)) + if (Filesystem.FilesystemHelpers.HasDraggedStorageItems(e.DataView)) { if (!InstanceViewModel.IsPageTypeSearchResults) { @@ -1054,7 +1037,7 @@ public DataPackageOperation TabItemDragOver(object sender, DragEventArgs e) public async Task TabItemDrop(object sender, DragEventArgs e) { - if (e.DataView.AvailableFormats.Contains(StandardDataFormats.StorageItems)) + if (Filesystem.FilesystemHelpers.HasDraggedStorageItems(e.DataView)) { if (InstanceViewModel.IsPageTypeNotHome && !InstanceViewModel.IsPageTypeSearchResults) {