Copy file to clipboard

This commit is contained in:
2023-07-06 22:38:14 +02:00
parent 5c716d5c28
commit ed5d5806ae
10 changed files with 117 additions and 30 deletions

View File

@@ -5,5 +5,6 @@ namespace FileTime.App.Core.Services;
public interface ISystemClipboardService public interface ISystemClipboardService
{ {
Task CopyToClipboardAsync(string text); Task CopyToClipboardAsync(string text);
Task<IEnumerable<FullName>> GetFiles(); Task<IEnumerable<FullName>> GetFilesAsync();
Task SetFilesAsync(IEnumerable<FullName> files);
} }

View File

@@ -0,0 +1,14 @@
namespace FileTime.App.Core.UserCommand;
public class CopyFilesToClipboardCommand : IIdentifiableUserCommand
{
public const string CommandName = "copy_to_clipboard";
public static readonly CopyFilesToClipboardCommand Instance = new();
private CopyFilesToClipboardCommand()
{
}
public string UserCommandID => CommandName;
}

View File

@@ -1,13 +0,0 @@
namespace FileTime.App.Core.UserCommand;
public sealed class CreateElement : IIdentifiableUserCommand
{
public const string CommandName = "create_element";
public static CreateElement Instance { get; } = new();
private CreateElement()
{
}
public string UserCommandID => CommandName;
}

View File

@@ -0,0 +1,13 @@
namespace FileTime.App.Core.UserCommand;
public sealed class CreateElementCommand : IIdentifiableUserCommand
{
public const string CommandName = "create_element";
public static CreateElementCommand Instance { get; } = new();
private CreateElementCommand()
{
}
public string UserCommandID => CommandName;
}

View File

@@ -18,6 +18,7 @@ using FileTime.Core.Timeline;
using InitableService; using InitableService;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using CreateElementCommand = FileTime.App.Core.UserCommand.CreateElementCommand;
namespace FileTime.App.Core.Services.UserCommandHandler; namespace FileTime.App.Core.Services.UserCommandHandler;
@@ -70,11 +71,30 @@ public class ItemManipulationUserCommandHandlerService : UserCommandHandlerServi
new TypeUserCommandHandler<MarkCommand>(MarkItemAsync), new TypeUserCommandHandler<MarkCommand>(MarkItemAsync),
new TypeUserCommandHandler<PasteCommand>(PasteAsync), new TypeUserCommandHandler<PasteCommand>(PasteAsync),
new TypeUserCommandHandler<CreateContainer>(CreateContainerAsync), new TypeUserCommandHandler<CreateContainer>(CreateContainerAsync),
new TypeUserCommandHandler<CreateElement>(CreateElementAsync), new TypeUserCommandHandler<CreateElementCommand>(CreateElementAsync),
new TypeUserCommandHandler<PasteFilesFromClipboardCommand>(PasteFilesFromClipboardAsync), new TypeUserCommandHandler<PasteFilesFromClipboardCommand>(PasteFilesFromClipboardAsync),
new TypeUserCommandHandler<CopyFilesToClipboardCommand>(CopyFilesToClipboardAsync),
}); });
} }
private async Task CopyFilesToClipboardAsync()
{
var list = new List<FullName>();
if ((_markedItems?.Collection?.Count ?? 0) > 0)
{
list.AddRange(_markedItems!.Collection!);
}
else if(_currentSelectedItem?.BaseItem?.FullName is { } selectedItemName)
{
list.Add(selectedItemName);
}
if (list.Count > 0)
{
await _systemClipboardService.SetFilesAsync(list);
}
}
private async Task PasteFilesFromClipboardAsync(PasteFilesFromClipboardCommand command) => private async Task PasteFilesFromClipboardAsync(PasteFilesFromClipboardCommand command) =>
await (command.PasteMode switch await (command.PasteMode switch
{ {
@@ -88,7 +108,7 @@ public class ItemManipulationUserCommandHandlerService : UserCommandHandlerServi
{ {
if (_currentLocation?.FullName is not { }) return; if (_currentLocation?.FullName is not { }) return;
var files = (await _systemClipboardService.GetFiles()).ToList(); var files = (await _systemClipboardService.GetFilesAsync()).ToList();
var copyCommandFactory = _serviceProvider.GetRequiredService<FileTime.Core.Command.Copy.CopyCommandFactory>(); var copyCommandFactory = _serviceProvider.GetRequiredService<FileTime.Core.Command.Copy.CopyCommandFactory>();
var copyCommand = copyCommandFactory.GenerateCommand(files, mode, _currentLocation.FullName); var copyCommand = copyCommandFactory.GenerateCommand(files, mode, _currentLocation.FullName);
@@ -187,7 +207,7 @@ public class ItemManipulationUserCommandHandlerService : UserCommandHandlerServi
var command = _serviceProvider var command = _serviceProvider
.GetInitableResolver(_currentLocation.FullName, newContainerName) .GetInitableResolver(_currentLocation.FullName, newContainerName)
.GetRequiredService<CreateElementCommand>(); .GetRequiredService<FileTime.Core.Command.CreateElement.CreateElementCommand>();
await AddCommandAsync(command); await AddCommandAsync(command);
} }

View File

@@ -14,9 +14,10 @@ public class DefaultIdentifiableCommandHandlerRegister : IStartupHandler
AddUserCommand(CloseTabCommand.Instance); AddUserCommand(CloseTabCommand.Instance);
AddUserCommand(CopyCommand.Instance); AddUserCommand(CopyCommand.Instance);
AddUserCommand(CopyBase64Command.Instance); AddUserCommand(CopyBase64Command.Instance);
AddUserCommand(CopyFilesToClipboardCommand.Instance);
AddUserCommand(CopyNativePathCommand.Instance); AddUserCommand(CopyNativePathCommand.Instance);
AddUserCommand(CreateContainer.Instance); AddUserCommand(CreateContainer.Instance);
AddUserCommand(CreateElement.Instance); AddUserCommand(CreateElementCommand.Instance);
AddUserCommand(DeleteCommand.HardDelete); AddUserCommand(DeleteCommand.HardDelete);
AddUserCommand(DeleteCommand.SoftDelete); AddUserCommand(DeleteCommand.SoftDelete);
AddUserCommand(EnterRapidTravelCommand.Instance); AddUserCommand(EnterRapidTravelCommand.Instance);

View File

@@ -16,4 +16,5 @@ public interface ITimelessContentProvider
Task<IItem?> GetItemByNativePathAsync(NativePath nativePath, PointInTime? pointInTime = null); Task<IItem?> GetItemByNativePathAsync(NativePath nativePath, PointInTime? pointInTime = null);
FullName? GetFullNameByNativePath(NativePath nativePath); FullName? GetFullNameByNativePath(NativePath nativePath);
NativePath? GetNativePathByFullName(FullName fullName);
} }

View File

@@ -56,4 +56,16 @@ public class TimelessContentProvider : ITimelessContentProvider
return null; return null;
} }
public NativePath? GetNativePathByFullName(FullName fullName)
{
foreach (var contentProvider in _contentProviderRegistry.ContentProviders)
{
if(!contentProvider.CanHandlePath(fullName)) continue;
return contentProvider.GetNativePath(fullName);
}
return null;
}
} }

View File

@@ -50,9 +50,10 @@ public static class MainConfiguration
new(CopyCommand.CommandName, new[] {Key.Y, Key.Y}), new(CopyCommand.CommandName, new[] {Key.Y, Key.Y}),
//new CommandBindingConfiguration(ConfigCommand.CopyHash, new[] { Key.C, Key.H }), //new CommandBindingConfiguration(ConfigCommand.CopyHash, new[] { Key.C, Key.H }),
new(CopyNativePathCommand.CommandName, new[] {Key.C, Key.P}), new(CopyNativePathCommand.CommandName, new[] {Key.C, Key.P}),
new(CopyFilesToClipboardCommand.CommandName, new[] {Key.Y, Key.C}),
new(CreateContainer.CommandName, Key.F7), new(CreateContainer.CommandName, Key.F7),
new(CreateContainer.CommandName, new[] {Key.C, Key.C}), new(CreateContainer.CommandName, new[] {Key.C, Key.C}),
new(CreateElement.CommandName, new[] {Key.C, Key.E}), new(CreateElementCommand.CommandName, new[] {Key.C, Key.E}),
//new CommandBindingConfiguration(ConfigCommand.Cut, new[] { Key.D, Key.D }), //new CommandBindingConfiguration(ConfigCommand.Cut, new[] { Key.D, Key.D }),
//new CommandBindingConfiguration(ConfigCommand.Edit, new KeyConfig(Key.F4)), //new CommandBindingConfiguration(ConfigCommand.Edit, new KeyConfig(Key.F4)),
new(EnterRapidTravelCommand.CommandName, new KeyConfig(Key.OemComma, shift: true)), new(EnterRapidTravelCommand.CommandName, new KeyConfig(Key.OemComma, shift: true)),

View File

@@ -1,5 +1,5 @@
using System.Net; using System.Net;
using System.Text.Encodings.Web; using Avalonia.Input;
using Avalonia.Platform.Storage; using Avalonia.Platform.Storage;
using FileTime.App.Core.Services; using FileTime.App.Core.Services;
using FileTime.Core.Models; using FileTime.Core.Models;
@@ -10,14 +10,12 @@ namespace FileTime.GuiApp.Services;
public class SystemClipboardService : ISystemClipboardService public class SystemClipboardService : ISystemClipboardService
{ {
private const string ClipboardContentFiles = "Files"; private const string ClipboardContentFiles = "Files";
private readonly ITimelessContentProvider _timelessContentProvider; private readonly ITimelessContentProvider _timelessContentProvider;
public IUiAccessor UiAccessor { get; internal set; } public IUiAccessor UiAccessor { get; internal set; } = null!;
public SystemClipboardService(ITimelessContentProvider timelessContentProvider) public SystemClipboardService(ITimelessContentProvider timelessContentProvider)
{ => _timelessContentProvider = timelessContentProvider;
_timelessContentProvider = timelessContentProvider;
}
public async Task CopyToClipboardAsync(string text) public async Task CopyToClipboardAsync(string text)
{ {
@@ -31,7 +29,7 @@ public class SystemClipboardService : ISystemClipboardService
await clipboard.SetTextAsync(text); await clipboard.SetTextAsync(text);
} }
public async Task<IEnumerable<FullName>> GetFiles() public async Task<IEnumerable<FullName>> GetFilesAsync()
{ {
var clipboard = UiAccessor.GetTopLevel()?.Clipboard; var clipboard = UiAccessor.GetTopLevel()?.Clipboard;
@@ -48,11 +46,50 @@ public class SystemClipboardService : ISystemClipboardService
if (obj is IEnumerable<IStorageItem> storageItems) if (obj is IEnumerable<IStorageItem> storageItems)
{ {
return storageItems return storageItems
.Select(i => _timelessContentProvider.GetFullNameByNativePath(new NativePath(WebUtility.UrlDecode(i.Path.AbsolutePath)))) .Select(i => _timelessContentProvider.GetFullNameByNativePath(new NativePath(WebUtility.UrlDecode(i.Path.AbsolutePath))))
.Where(i => i != null) .Where(i => i != null)
.OfType<FullName>(); .OfType<FullName>();
} }
return Enumerable.Empty<FullName>(); return Enumerable.Empty<FullName>();
} }
public async Task SetFilesAsync(IEnumerable<FullName> files)
{
var clipboard = UiAccessor.GetTopLevel()?.Clipboard;
if (clipboard is null)
{
return;
}
var topLevel = UiAccessor.GetTopLevel();
if (topLevel is null)
{
//TODO:
return;
}
var fileNativePaths = files
.Select(i => _timelessContentProvider.GetNativePathByFullName(i))
.Where(i => i != null)
.OfType<NativePath>();
var targetFiles = new List<IStorageFile>();
foreach (var fileNativePath in fileNativePaths)
{
var file = await UiAccessor.InvokeOnUIThread(async () => await topLevel.StorageProvider.TryGetFileFromPathAsync(fileNativePath.Path));
//TODO: Handle null
if (file != null)
{
targetFiles.Add(file);
}
}
DataObject dataObject = new();
dataObject.Set(ClipboardContentFiles, targetFiles);
await clipboard.SetDataObjectAsync(dataObject);
}
} }