Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ability to drag & drop shortcuts and hidden files (only inside Files) #5810

Merged
merged 13 commits into from
Aug 22, 2021
Merged
42 changes: 27 additions & 15 deletions Files.Launcher/MessageHandlers/FileOperationsHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
67 changes: 36 additions & 31 deletions Files/BaseLayout.cs
Original file line number Diff line number Diff line change
Expand Up @@ -761,17 +761,12 @@ protected virtual void Page_CharacterReceived(CoreWindow sender, CharacterReceiv
protected async void FileList_DragItemsStarting(object sender, DragItemsStartingEventArgs e)
{
List<IStorageItem> selectedStorageItems = new List<IStorageItem>();
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<ListedItem>().ForEach(item => SelectedItems.Add(item));

SelectedItems.Add(item);
foreach (var item in e.Items.OfType<ListedItem>())
{
if (item is FtpItem ftpItem)
{
if (item.PrimaryItemAttribute == StorageItemTypes.File)
Expand All @@ -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<ListedItem>().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)
Expand Down Expand Up @@ -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<IStorageItem> 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<IStorageItem>();
}
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;
Expand All @@ -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);
Expand Down
7 changes: 6 additions & 1 deletion Files/Enums/FileOperationType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,11 @@ public enum FileOperationType : byte
/// <summary>
/// A item has been deleted
/// </summary>
Delete = 8
Delete = 8,

/// <summary>
/// A link to an item has been created
/// </summary>
CreateLink = 9,
}
}
11 changes: 5 additions & 6 deletions Files/Filesystem/FilesystemOperations/FilesystemOperations.cs
Original file line number Diff line number Diff line change
Expand Up @@ -84,12 +84,6 @@ public FilesystemOperations(IShellPage associatedInstance)
break;
}

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

default:
Debugger.Break();
break;
Expand Down Expand Up @@ -1159,5 +1153,10 @@ public async Task<IStorageHistory> DeleteItemsAsync(IEnumerable<IStorageItemWith
}
return null;
}

public Task<IStorageHistory> CreateShortcutItemsAsync(IEnumerable<IStorageItemWithPath> source, IEnumerable<string> destination, IProgress<float> progress, IProgress<FileSystemStatusCode> errorCode, CancellationToken token)
{
throw new NotImplementedException("Cannot create shortcuts in UWP.");
}
}
}
Loading