Copy file to clipboard
This commit is contained in:
@@ -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);
|
||||||
}
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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;
|
|
||||||
}
|
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -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)),
|
||||||
|
|||||||
@@ -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;
|
||||||
@@ -12,12 +12,10 @@ 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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user