Skip to content

Fix copy/paste for shortcuts #6109

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

Merged
merged 3 commits into from
Sep 12, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 8 additions & 20 deletions Files/DataModels/FilesystemItemsOperationDataModel.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using Files.Enums;
using Files.Helpers;
using Files.ViewModels.Dialogs;
using Microsoft.Toolkit.Uwp;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
Expand Down Expand Up @@ -58,51 +59,38 @@ public FilesystemItemsOperationDataModel(FilesystemOperationType operationType,
this.ConflictingItems = conflictingItems;
}

public async Task<List<FilesystemOperationItemViewModel>> ToItems(Action updatePrimaryButtonEnabled, Action optionGenerateNewName, Action optionReplaceExisting, Action optionSkip)
public List<FilesystemOperationItemViewModel> ToItems(Action updatePrimaryButtonEnabled, Action optionGenerateNewName, Action optionReplaceExisting, Action optionSkip)
{
ConcurrentBag<(int Index, FilesystemOperationItemViewModel Model)> items = new ConcurrentBag<(int Index, FilesystemOperationItemViewModel Model)>();

List<FilesystemOperationItemViewModel> items = new List<FilesystemOperationItemViewModel>();
List<FilesystemItemsOperationItemModel> nonConflictingItems = IncomingItems.Except(ConflictingItems).ToList();

// Add conflicting items first
await Task.WhenAll(ConflictingItems.Select(async (item, index) =>
{
var iconData = await FileThumbnailHelper.LoadIconFromPathAsync(item.SourcePath, 64u, Windows.Storage.FileProperties.ThumbnailMode.ListView);

items.Add((index, new FilesystemOperationItemViewModel(updatePrimaryButtonEnabled, optionGenerateNewName, optionReplaceExisting, optionSkip)
items.AddRange(ConflictingItems.Select((item, index) =>
new FilesystemOperationItemViewModel(updatePrimaryButtonEnabled, optionGenerateNewName, optionReplaceExisting, optionSkip)
{
IsConflict = true,
ItemIcon = iconData != null ? await iconData.ToBitmapAsync() : null,
SourcePath = item.SourcePath,
DestinationPath = item.DestinationPath,
DisplayFileName = item.DisplayFileName,
ConflictResolveOption = FileNameConflictResolveOptionType.GenerateNewName,
ItemOperation = item.OperationType,
ActionTaken = false
}));
}));

var baseIndex = ConflictingItems.Count;

// Then add non-conflicting items
await Task.WhenAll(nonConflictingItems.Select(async (item, index) =>
{
var iconData = await FileThumbnailHelper.LoadIconFromPathAsync(item.SourcePath, 64u, Windows.Storage.FileProperties.ThumbnailMode.ListView);

items.Add((baseIndex + index, new FilesystemOperationItemViewModel(updatePrimaryButtonEnabled, optionGenerateNewName, optionReplaceExisting, optionSkip)
items.AddRange(nonConflictingItems.Select((item, index) =>
new FilesystemOperationItemViewModel(updatePrimaryButtonEnabled, optionGenerateNewName, optionReplaceExisting, optionSkip)
{
IsConflict = false,
ItemIcon = iconData != null ? await iconData.ToBitmapAsync() : null,
SourcePath = item.SourcePath,
DestinationPath = item.DestinationPath,
DisplayFileName = item.DisplayFileName,
ConflictResolveOption = FileNameConflictResolveOptionType.NotAConflict,
ItemOperation = item.OperationType,
ActionTaken = true
}));
}));

return items.OrderBy(i => i.Index).Select(i => i.Model).ToList();
return items;
}

private string GetOperationIconGlyph(FilesystemOperationType operationType)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ public async Task<ReturnResult> DeleteItemsAsync(IEnumerable<IStorageItemWithPat
}
}

FilesystemOperationDialog dialog = await FilesystemOperationDialogViewModel.GetDialog(new FilesystemItemsOperationDataModel(
FilesystemOperationDialog dialog = FilesystemOperationDialogViewModel.GetDialog(new FilesystemItemsOperationDataModel(
FilesystemOperationType.Delete,
false,
canBeSentToBin ? permanently : true,
Expand Down Expand Up @@ -313,7 +313,7 @@ public async Task<ReturnResult> DeleteItemAsync(IStorageItemWithPath source, boo
incomingItems.Add(new FilesystemItemsOperationItemModel(FilesystemOperationType.Delete, srcPath, null));
}

FilesystemOperationDialog dialog = await FilesystemOperationDialogViewModel.GetDialog(new FilesystemItemsOperationDataModel(
FilesystemOperationDialog dialog = FilesystemOperationDialogViewModel.GetDialog(new FilesystemItemsOperationDataModel(
FilesystemOperationType.Delete,
false,
canBeSentToBin ? permanently : true,
Expand Down Expand Up @@ -1005,7 +1005,7 @@ public async Task<ReturnResult> RecycleItemsFromClipboard(DataPackageView packag

if (mustResolveConflicts || forceDialog)
{
FilesystemOperationDialog dialog = await FilesystemOperationDialogViewModel.GetDialog(new FilesystemItemsOperationDataModel(
FilesystemOperationDialog dialog = FilesystemOperationDialogViewModel.GetDialog(new FilesystemItemsOperationDataModel(
operationType,
mustResolveConflicts,
false,
Expand Down
75 changes: 33 additions & 42 deletions Files/Helpers/UIFilesystemHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,11 @@ public static async void CutItem(IShellPage associatedInstance)
{
await Task.WhenAll(associatedInstance.SlimContentPage.SelectedItems.ToList().Select(async listedItem =>
{
// FTP don't support cut, fallback to copy
if (listedItem is not FtpItem)
// FTP don't support cut, fallback to copy
if (listedItem is not FtpItem)
{
// Dim opacities accordingly
listedItem.Opacity = Constants.UI.DimItemOpacity;
// Dim opacities accordingly
listedItem.Opacity = Constants.UI.DimItemOpacity;
}

if (listedItem is FtpItem ftpItem)
Expand Down Expand Up @@ -80,31 +80,24 @@ await Task.WhenAll(associatedInstance.SlimContentPage.SelectedItems.ToList().Sel
}
catch
{
return;
}

if (result.ErrorCode == FileSystemStatusCode.NotFound)
{
associatedInstance.SlimContentPage.ItemManipulationModel.RefreshItemsOpacity();
return;
}
else if (result.ErrorCode == FileSystemStatusCode.Unauthorized)
{
// Try again with fulltrust process
var connection = await AppServiceConnectionHelper.Instance;
if (connection != null)
if (result.ErrorCode == FileSystemStatusCode.Unauthorized)
{
string filePaths = string.Join('|', associatedInstance.SlimContentPage.SelectedItems.Select(x => x.ItemPath));
AppServiceResponseStatus status = await connection.SendMessageAsync(new ValueSet()
{
{ "Arguments", "FileOperation" },
{ "fileop", "Clipboard" },
{ "filepath", filePaths },
{ "operation", (int)DataPackageOperation.Move }
});
if (status == AppServiceResponseStatus.Success)
// Try again with fulltrust process
var connection = await AppServiceConnectionHelper.Instance;
if (connection != null)
{
return;
string filePaths = string.Join('|', associatedInstance.SlimContentPage.SelectedItems.Select(x => x.ItemPath));
AppServiceResponseStatus status = await connection.SendMessageAsync(new ValueSet()
{
{ "Arguments", "FileOperation" },
{ "fileop", "Clipboard" },
{ "filepath", filePaths },
{ "operation", (int)DataPackageOperation.Move }
});
if (status == AppServiceResponseStatus.Success)
{
return;
}
}
}
associatedInstance.SlimContentPage.ItemManipulationModel.RefreshItemsOpacity();
Expand Down Expand Up @@ -188,23 +181,21 @@ await Task.WhenAll(associatedInstance.SlimContentPage.SelectedItems.ToList().Sel
}
catch
{
return;
}

if (result.ErrorCode == FileSystemStatusCode.Unauthorized)
{
// Try again with fulltrust process
var connection = await AppServiceConnectionHelper.Instance;
if (connection != null)
if (result.ErrorCode == FileSystemStatusCode.Unauthorized)
{
string filePaths = string.Join('|', associatedInstance.SlimContentPage.SelectedItems.Select(x => x.ItemPath));
await connection.SendMessageAsync(new ValueSet()
// Try again with fulltrust process
var connection = await AppServiceConnectionHelper.Instance;
if (connection != null)
{
{ "Arguments", "FileOperation" },
{ "fileop", "Clipboard" },
{ "filepath", filePaths },
{ "operation", (int)DataPackageOperation.Copy }
});
string filePaths = string.Join('|', associatedInstance.SlimContentPage.SelectedItems.Select(x => x.ItemPath));
await connection.SendMessageAsync(new ValueSet()
{
{ "Arguments", "FileOperation" },
{ "fileop", "Clipboard" },
{ "filepath", filePaths },
{ "operation", (int)DataPackageOperation.Copy }
});
}
}
return;
}
Expand Down
6 changes: 3 additions & 3 deletions Files/Interacts/BaseLayoutCommandImplementationModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -199,9 +199,9 @@ await FilesystemHelpers.RestoreFromTrashAsync(StorageItemHelpers.FromPathAndType

public virtual async void DeleteItem(RoutedEventArgs e)
{
var items = await Task.WhenAll(SlimContentPage.SelectedItems.Select((item) => Task.Run(() => StorageItemHelpers.FromPathAndType(
item.ItemPath,
item.PrimaryItemAttribute == StorageItemTypes.File ? FilesystemItemType.File : FilesystemItemType.Directory))));
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);
}

Expand Down
18 changes: 6 additions & 12 deletions Files/UserControls/Widgets/FolderWidget.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -140,23 +140,18 @@ public void Dispose()

private async Task GetItemsAddedIcon()
{
try
foreach (var item in ItemsAdded.ToList()) // ToList() is necessary
{
foreach (var item in ItemsAdded.ToList()) // ToList() is necessary
{
item.SelectCommand = LibraryCardClicked;
item.AutomationProperties = item.Text;
await this.LoadLibraryIcon(item);
}
}
catch
{
// Collection modified
item.SelectCommand = LibraryCardClicked;
item.AutomationProperties = item.Text;
await this.LoadLibraryIcon(item);
}
}

private async void FolderWidget_Loaded(object sender, RoutedEventArgs e)
{
Loaded -= FolderWidget_Loaded;

ItemsAdded.BeginBulkOperation();
ItemsAdded.Add(new LibraryCardItem
{
Expand Down Expand Up @@ -192,7 +187,6 @@ private async void FolderWidget_Loaded(object sender, RoutedEventArgs e)
await GetItemsAddedIcon();

ItemsAdded.EndBulkOperation();
Loaded -= FolderWidget_Loaded;
}

private void FolderWidget_Unloaded(object sender, RoutedEventArgs e)
Expand Down
27 changes: 24 additions & 3 deletions Files/ViewModels/Dialogs/FilesystemOperationDialogViewModel.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
using Files.DataModels;
using Files.Dialogs;
using Files.Enums;
using Files.Helpers;
using Microsoft.Toolkit.Mvvm.ComponentModel;
using Microsoft.Toolkit.Mvvm.Input;
using Microsoft.Toolkit.Uwp;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
Expand Down Expand Up @@ -191,7 +193,7 @@ public List<IFilesystemOperationItemModel> GetResult()
return Items.Cast<IFilesystemOperationItemModel>().ToList();
}

public static async Task<FilesystemOperationDialog> GetDialog(FilesystemItemsOperationDataModel itemsData)
public static FilesystemOperationDialog GetDialog(FilesystemItemsOperationDataModel itemsData)
{
string titleText = null;
string subtitleText = null;
Expand Down Expand Up @@ -280,12 +282,31 @@ public static async Task<FilesystemOperationDialog> GetDialog(FilesystemItemsOpe
PermanentlyDeleteEnabled = itemsData.PermanentlyDeleteEnabled,
MustResolveConflicts = itemsData.MustResolveConflicts
};
viewModel.Items = new ObservableCollection<FilesystemOperationItemViewModel>(await itemsData.ToItems(
viewModel.Items = new ObservableCollection<FilesystemOperationItemViewModel>(itemsData.ToItems(
viewModel.UpdatePrimaryButtonEnabled, viewModel.OptionGenerateNewName, viewModel.OptionReplaceExisting, viewModel.OptionSkip));

_ = LoadItemsIcon(viewModel.Items);
FilesystemOperationDialog dialog = new FilesystemOperationDialog(viewModel);

return dialog;
}

private static async Task LoadItemsIcon(IEnumerable<FilesystemOperationItemViewModel> items)
{
await Task.Run(() => Task.WhenAll(items.ToList().Select(async (item) =>
{
try
{
var iconData = await FileThumbnailHelper.LoadIconFromPathAsync(item.SourcePath, 64u, Windows.Storage.FileProperties.ThumbnailMode.ListView);
if (iconData != null)
{
await Windows.ApplicationModel.Core.CoreApplication.MainView.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Low, async () =>
{
item.ItemIcon = await iconData.ToBitmapAsync();
});
}
}
catch { }
})));
}
}
}
12 changes: 6 additions & 6 deletions Files/Views/ColumnShellPage.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -616,9 +616,9 @@ private async void KeyboardAccelerator_Invoked(KeyboardAccelerator sender, Keybo
case (false, true, false, true, VirtualKey.Delete): // shift + delete, PermanentDelete
if (ContentPage.IsItemSelected && !NavToolbarViewModel.IsEditModeEnabled && !InstanceViewModel.IsPageTypeSearchResults)
{
var items = await Task.WhenAll(ContentPage.SelectedItems.Select((item) => Task.Run(() => StorageItemHelpers.FromPathAndType(
item.ItemPath,
item.PrimaryItemAttribute == StorageItemTypes.File ? FilesystemItemType.File : FilesystemItemType.Directory))));
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, true, true);
}

Expand Down Expand Up @@ -660,9 +660,9 @@ private async void KeyboardAccelerator_Invoked(KeyboardAccelerator sender, Keybo
case (false, false, false, true, VirtualKey.Delete): // delete, delete item
if (ContentPage.IsItemSelected && !ContentPage.IsRenamingItem && !InstanceViewModel.IsPageTypeSearchResults)
{
var items = await Task.WhenAll(ContentPage.SelectedItems.Select((item) => Task.Run(() => StorageItemHelpers.FromPathAndType(
item.ItemPath,
item.PrimaryItemAttribute == StorageItemTypes.File ? FilesystemItemType.File : FilesystemItemType.Directory))));
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);
}

Expand Down
Loading