Clipboard
This commit is contained in:
@@ -0,0 +1,16 @@
|
||||
using FileTime.Core.Command;
|
||||
using FileTime.Core.Models;
|
||||
|
||||
namespace FileTime.App.Core.Services
|
||||
{
|
||||
public interface IClipboardService
|
||||
{
|
||||
Type? CommandType { get; }
|
||||
IReadOnlyList<IAbsolutePath> Content { get; }
|
||||
|
||||
void AddContent(IAbsolutePath absolutePath);
|
||||
void RemoveContent(IAbsolutePath absolutePath);
|
||||
void Clear();
|
||||
void SetCommand<T>() where T : ITransportationCommand;
|
||||
}
|
||||
}
|
||||
@@ -15,7 +15,7 @@ namespace FileTime.App.Core.ViewModels
|
||||
IObservable<IContainer?> CurrentLocation { get; }
|
||||
IObservable<IItemViewModel?> CurrentSelectedItem { get; }
|
||||
IObservable<IObservable<IChangeSet<IItemViewModel>>?> CurrentItems { get; }
|
||||
IObservable<IEnumerable<FullName>> MarkedItems { get; }
|
||||
IObservable<IChangeSet<IAbsolutePath>> MarkedItems { get; }
|
||||
IObservable<IObservable<IChangeSet<IItemViewModel>>?> SelectedsChildren { get; }
|
||||
IObservable<IObservable<IChangeSet<IItemViewModel>>?> ParentsChildren { get; }
|
||||
BindedCollection<IItemViewModel>? CurrentItemsCollection { get; }
|
||||
@@ -23,8 +23,8 @@ namespace FileTime.App.Core.ViewModels
|
||||
BindedCollection<IItemViewModel>? ParentsChildrenCollection { get; }
|
||||
IObservable<IReadOnlyCollection<IItemViewModel>?> CurrentItemsCollectionObservable { get; }
|
||||
void ClearMarkedItems();
|
||||
void RemoveMarkedItem(FullName item);
|
||||
void AddMarkedItem(FullName item);
|
||||
void ToggleMarkedItem(FullName item);
|
||||
void RemoveMarkedItem(IAbsolutePath item);
|
||||
void AddMarkedItem(IAbsolutePath item);
|
||||
void ToggleMarkedItem(IAbsolutePath item);
|
||||
}
|
||||
}
|
||||
@@ -18,6 +18,7 @@
|
||||
<ProjectReference Include="..\..\Core\FileTime.Core.Models\FileTime.Core.Models.csproj" />
|
||||
<ProjectReference Include="..\..\Tools\FileTime.Tools\FileTime.Tools.csproj" />
|
||||
<ProjectReference Include="..\FileTime.App.Core.Abstraction\FileTime.App.Core.Abstraction.csproj" />
|
||||
<ProjectReference Include="..\..\Core\FileTime.Core.Command\FileTime.Core.Command.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
51
src/AppCommon/FileTime.App.Core/Services/ClipboardService.cs
Normal file
51
src/AppCommon/FileTime.App.Core/Services/ClipboardService.cs
Normal file
@@ -0,0 +1,51 @@
|
||||
using FileTime.Core.Command;
|
||||
using FileTime.Core.Models;
|
||||
|
||||
namespace FileTime.App.Core.Services
|
||||
{
|
||||
public class ClipboardService : IClipboardService
|
||||
{
|
||||
private List<IAbsolutePath> _content;
|
||||
public IReadOnlyList<IAbsolutePath> Content { get; private set; }
|
||||
public Type? CommandType { get; private set; }
|
||||
|
||||
public ClipboardService()
|
||||
{
|
||||
_content = new List<IAbsolutePath>();
|
||||
Content = _content.AsReadOnly();
|
||||
}
|
||||
|
||||
public void AddContent(IAbsolutePath absolutePath)
|
||||
{
|
||||
foreach (var content in _content)
|
||||
{
|
||||
if (content.Equals(absolutePath)) return;
|
||||
}
|
||||
|
||||
_content.Add(absolutePath);
|
||||
}
|
||||
|
||||
public void RemoveContent(IAbsolutePath absolutePath)
|
||||
{
|
||||
for (var i = 0; i < _content.Count; i++)
|
||||
{
|
||||
if (_content[i].Equals(absolutePath))
|
||||
{
|
||||
_content.RemoveAt(i--);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
_content = new List<IAbsolutePath>();
|
||||
Content = _content.AsReadOnly();
|
||||
CommandType = null;
|
||||
}
|
||||
|
||||
public void SetCommand<T>() where T : ITransportationCommand
|
||||
{
|
||||
CommandType = typeof(T);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,16 +1,17 @@
|
||||
using System.Reactive.Linq;
|
||||
using DynamicData;
|
||||
using FileTime.App.Core.Command;
|
||||
using FileTime.App.Core.ViewModels;
|
||||
using FileTime.Core.Models;
|
||||
|
||||
namespace FileTime.App.Core.Services.CommandHandler
|
||||
{
|
||||
public abstract class CommandHanderBase : ICommandHandler
|
||||
public abstract class CommandHandlerBase : ICommandHandler
|
||||
{
|
||||
private readonly Dictionary<Commands, Func<Task>> _commandHandlers = new();
|
||||
private readonly IAppState? _appState;
|
||||
|
||||
protected CommandHanderBase(IAppState? appState = null)
|
||||
protected CommandHandlerBase(IAppState? appState = null)
|
||||
{
|
||||
_appState = appState;
|
||||
}
|
||||
@@ -40,9 +41,12 @@ namespace FileTime.App.Core.Services.CommandHandler
|
||||
protected IDisposable SaveCurrentItems(Action<IEnumerable<IItemViewModel>> handler)
|
||||
=> RunWithAppState(appState => appState.SelectedTab.Select(t => t?.CurrentItemsCollectionObservable ?? Observable.Return((IEnumerable<IItemViewModel>?)Enumerable.Empty<IItemViewModel>())).Switch().Subscribe(i => handler(i ?? Enumerable.Empty<IItemViewModel>())));
|
||||
|
||||
protected IDisposable SaveMarkedItems(Action<IChangeSet<IAbsolutePath>> handler)
|
||||
=> RunWithAppState(appstate => appstate.SelectedTab.Select(t => t == null ? Observable.Empty<IChangeSet<IAbsolutePath>>() : t.MarkedItems).Switch().Subscribe(handler));
|
||||
|
||||
private IDisposable RunWithAppState(Func<IAppState, IDisposable> act)
|
||||
{
|
||||
if (_appState == null) throw new NullReferenceException($"AppState is nit initialized in {nameof(CommandHanderBase)}.");
|
||||
if (_appState == null) throw new NullReferenceException($"AppState is nit initialized in {nameof(CommandHandlerBase)}.");
|
||||
|
||||
return act(_appState);
|
||||
}
|
||||
@@ -1,24 +1,44 @@
|
||||
using DynamicData;
|
||||
using FileTime.App.Core.Command;
|
||||
using FileTime.App.Core.Models;
|
||||
using FileTime.App.Core.ViewModels;
|
||||
using FileTime.Core.Command;
|
||||
using FileTime.Core.Command.Copy;
|
||||
using FileTime.Core.Models;
|
||||
|
||||
namespace FileTime.App.Core.Services.CommandHandler
|
||||
{
|
||||
public class ItemManipulationCommandHandler : CommandHanderBase
|
||||
public class ItemManipulationCommandHandler : CommandHandlerBase
|
||||
{
|
||||
private ITabViewModel? _selectedTab;
|
||||
private IItemViewModel? _currentSelectedItem;
|
||||
private readonly ICommandHandlerService _commandHandlerService;
|
||||
private readonly IClipboardService _clipboardService;
|
||||
private BindedCollection<IAbsolutePath>? _markedItems;
|
||||
|
||||
public ItemManipulationCommandHandler(IAppState appState, ICommandHandlerService commandHandlerService) : base(appState)
|
||||
public ItemManipulationCommandHandler(
|
||||
IAppState appState,
|
||||
ICommandHandlerService commandHandlerService,
|
||||
IClipboardService clipboardService) : base(appState)
|
||||
{
|
||||
_commandHandlerService = commandHandlerService;
|
||||
_clipboardService = clipboardService;
|
||||
|
||||
SaveSelectedTab(t => _selectedTab = t);
|
||||
SaveSelectedTab(t =>
|
||||
{
|
||||
_selectedTab = t;
|
||||
_markedItems?.Dispose();
|
||||
_markedItems = t == null ? null : new BindedCollection<IAbsolutePath>(t.MarkedItems);
|
||||
});
|
||||
SaveCurrentSelectedItem(i => _currentSelectedItem = i);
|
||||
|
||||
AddCommandHandlers(new (Commands, Func<Task>)[]
|
||||
{
|
||||
(Commands.Mark, MarkItem)
|
||||
(Commands.Copy, Copy),
|
||||
(Commands.Mark, MarkItem),
|
||||
(Commands.PasteMerge, PasteMerge),
|
||||
(Commands.PasteOverwrite, PasteOverwrite),
|
||||
(Commands.PasteSkip, PasteSkip),
|
||||
});
|
||||
}
|
||||
|
||||
@@ -26,8 +46,51 @@ namespace FileTime.App.Core.Services.CommandHandler
|
||||
{
|
||||
if (_selectedTab == null || _currentSelectedItem?.BaseItem?.FullName == null) return;
|
||||
|
||||
_selectedTab.ToggleMarkedItem(_currentSelectedItem.BaseItem.FullName);
|
||||
_selectedTab.ToggleMarkedItem(new AbsolutePath(_currentSelectedItem.BaseItem));
|
||||
await _commandHandlerService.HandleCommandAsync(Commands.MoveCursorDown);
|
||||
}
|
||||
|
||||
private Task Copy()
|
||||
{
|
||||
_clipboardService.Clear();
|
||||
_clipboardService.SetCommand<CopyCommand>();
|
||||
|
||||
if ((_markedItems?.Collection.Count ?? 0) > 0)
|
||||
{
|
||||
foreach (var item in _markedItems!.Collection)
|
||||
{
|
||||
_clipboardService.AddContent(item);
|
||||
}
|
||||
|
||||
_selectedTab?.ClearMarkedItems();
|
||||
}
|
||||
else if (_currentSelectedItem?.BaseItem != null)
|
||||
{
|
||||
_clipboardService.AddContent(new AbsolutePath(_currentSelectedItem.BaseItem));
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
private async Task PasteMerge()
|
||||
{
|
||||
await Paste(TransportMode.Merge);
|
||||
}
|
||||
|
||||
private async Task PasteOverwrite()
|
||||
{
|
||||
await Paste(TransportMode.Overwrite);
|
||||
}
|
||||
|
||||
private async Task PasteSkip()
|
||||
{
|
||||
await Paste(TransportMode.Skip);
|
||||
}
|
||||
|
||||
private Task Paste(TransportMode skip)
|
||||
{
|
||||
if (_clipboardService.CommandType is null) return Task.CompletedTask;
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,7 @@ using FileTime.Core.Models;
|
||||
|
||||
namespace FileTime.App.Core.Services.CommandHandler
|
||||
{
|
||||
public class NavigationCommandHandler : CommandHanderBase
|
||||
public class NavigationCommandHandler : CommandHandlerBase
|
||||
{
|
||||
private ITabViewModel? _selectedTab;
|
||||
private IContainer? _currentLocation;
|
||||
|
||||
@@ -15,6 +15,7 @@ namespace FileTime.App.Core
|
||||
.AddTransient<IElementViewModel, ElementViewModel>()
|
||||
.AddTransient<IItemNameConverterService, ItemNameConverterService>()
|
||||
.AddSingleton<ICommandHandlerService, CommandHandlerService>()
|
||||
.AddSingleton<IClipboardService, ClipboardService>()
|
||||
.AddCommandHandlers();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Reactive.Linq;
|
||||
using DynamicData;
|
||||
using FileTime.App.Core.Models;
|
||||
using FileTime.App.Core.Models.Enums;
|
||||
using FileTime.App.Core.Services;
|
||||
@@ -45,7 +46,7 @@ namespace FileTime.App.Core.ViewModels
|
||||
BaseItem = item;
|
||||
DisplayName = _appState.SearchText.Select(s => _itemNameConverterService.GetDisplayName(item.DisplayName, s));
|
||||
DisplayNameText = item.DisplayName;
|
||||
IsMarked = parentTab.MarkedItems.Select(m => m.Contains(item.FullName));
|
||||
IsMarked = parentTab.MarkedItems.ToCollection().Select(m => m.Any(i => i.Path.Path == item.FullName?.Path));
|
||||
IsSelected = parentTab.CurrentSelectedItem.Select(EqualsTo);
|
||||
IsAlternative = parentTab.CurrentItemsCollectionObservable.Select(c => c?.Index().FirstOrDefault(i => EqualsTo(i.Value)).Key % 2 == 0);
|
||||
ViewMode = Observable.CombineLatest(IsMarked, IsSelected, IsAlternative, GenerateViewMode);
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using System.Reactive.Linq;
|
||||
using System.Reactive.Subjects;
|
||||
using DynamicData;
|
||||
using FileTime.App.Core.Extensions;
|
||||
using FileTime.App.Core.Models;
|
||||
@@ -19,8 +18,7 @@ namespace FileTime.App.Core.ViewModels
|
||||
private readonly IItemNameConverterService _itemNameConverterService;
|
||||
private readonly IAppState _appState;
|
||||
private readonly IRxSchedulerService _rxSchedulerService;
|
||||
private readonly BehaviorSubject<IEnumerable<FullName>> _markedItems = new(Enumerable.Empty<FullName>());
|
||||
private readonly List<FullName> _currentMarkedItems = new();
|
||||
private readonly SourceList<IAbsolutePath> _markedItems = new();
|
||||
private readonly List<IDisposable> _disposables = new();
|
||||
private bool disposed;
|
||||
|
||||
@@ -32,7 +30,7 @@ namespace FileTime.App.Core.ViewModels
|
||||
public IObservable<IContainer?> CurrentLocation { get; private set; } = null!;
|
||||
public IObservable<IItemViewModel?> CurrentSelectedItem { get; private set; } = null!;
|
||||
public IObservable<IObservable<IChangeSet<IItemViewModel>>?> CurrentItems { get; private set; } = null!;
|
||||
public IObservable<IEnumerable<FullName>> MarkedItems { get; }
|
||||
public IObservable<IChangeSet<IAbsolutePath>> MarkedItems { get; }
|
||||
public IObservable<IObservable<IChangeSet<IItemViewModel>>?> SelectedsChildren { get; private set; } = null!;
|
||||
public IObservable<IObservable<IChangeSet<IItemViewModel>>?> ParentsChildren { get; private set; } = null!;
|
||||
|
||||
@@ -57,7 +55,7 @@ namespace FileTime.App.Core.ViewModels
|
||||
_itemNameConverterService = itemNameConverterService;
|
||||
_appState = appState;
|
||||
|
||||
MarkedItems = _markedItems.Select(e => e.ToList()).AsObservable();
|
||||
MarkedItems = _markedItems.Connect().StartWithEmpty();
|
||||
IsSelected = _appState.SelectedTab.Select(s => s == this);
|
||||
_rxSchedulerService = rxSchedulerService;
|
||||
}
|
||||
@@ -117,7 +115,7 @@ namespace FileTime.App.Core.ViewModels
|
||||
SelectedsChildrenCollection = children.MapNull(c => new BindedCollection<IItemViewModel>(c!));
|
||||
});
|
||||
|
||||
tab.CurrentLocation.Subscribe((_) => _markedItems.OnNext(Enumerable.Empty<FullName>()));
|
||||
tab.CurrentLocation.Subscribe((_) => _markedItems.Clear());
|
||||
|
||||
IObservable<IObservable<IChangeSet<IItemViewModel>>?> InitSelectedsChildren()
|
||||
{
|
||||
@@ -195,21 +193,18 @@ namespace FileTime.App.Core.ViewModels
|
||||
throw new ArgumentException($"{nameof(item)} is not {nameof(IContainer)} neither {nameof(IElement)}");
|
||||
}
|
||||
|
||||
public void AddMarkedItem(FullName item)
|
||||
public void AddMarkedItem(IAbsolutePath item) => _markedItems.Add(item);
|
||||
|
||||
public void RemoveMarkedItem(IAbsolutePath item)
|
||||
{
|
||||
_currentMarkedItems.Add(item);
|
||||
_markedItems.OnNext(_currentMarkedItems);
|
||||
var itemsToRemove = _markedItems.Items.Where(i => i.Path.Path == item.Path.Path).ToList();
|
||||
|
||||
_markedItems.RemoveMany(itemsToRemove);
|
||||
}
|
||||
|
||||
public void RemoveMarkedItem(FullName item)
|
||||
public void ToggleMarkedItem(IAbsolutePath item)
|
||||
{
|
||||
_currentMarkedItems.RemoveAll(i => i.Path == item.Path);
|
||||
_markedItems.OnNext(_currentMarkedItems);
|
||||
}
|
||||
|
||||
public void ToggleMarkedItem(FullName item)
|
||||
{
|
||||
if (_currentMarkedItems.Any(i => i.Path == item.Path))
|
||||
if (_markedItems.Items.Any(i => i.Path.Path == item.Path.Path))
|
||||
{
|
||||
RemoveMarkedItem(item);
|
||||
}
|
||||
@@ -221,8 +216,7 @@ namespace FileTime.App.Core.ViewModels
|
||||
|
||||
public void ClearMarkedItems()
|
||||
{
|
||||
_currentMarkedItems.Clear();
|
||||
_markedItems.OnNext(_currentMarkedItems);
|
||||
_markedItems.Clear();
|
||||
}
|
||||
|
||||
~TabViewModel() => Dispose(false);
|
||||
|
||||
Reference in New Issue
Block a user