Refactor command handlers and Startup

This commit is contained in:
2022-04-18 22:10:50 +02:00
parent 570f695e60
commit be6c3938ce
9 changed files with 207 additions and 127 deletions

View File

@@ -0,0 +1,10 @@
using FileTime.App.Core.Command;
namespace FileTime.App.Core.Services
{
public interface ICommandHandler
{
bool CanHandleCommand(Commands command);
Task HandleCommandAsync(Commands command);
}
}

View File

@@ -0,0 +1,23 @@
using FileTime.App.Core.Command;
namespace FileTime.App.Core.Services.CommandHandler
{
public abstract class CommandHanderBase : ICommandHandler
{
private readonly Dictionary<Commands, Func<Task>> _commandHandlers = new();
public bool CanHandleCommand(Commands command) => _commandHandlers.ContainsKey(command);
public async Task HandleCommandAsync(Commands command) => await _commandHandlers[command].Invoke();
protected void AddCommandHandler(Commands command, Func<Task> handler) => _commandHandlers.Add(command, handler);
protected void AddCommandHandlers(IEnumerable<(Commands command, Func<Task> handler)> commandHandlers)
{
foreach (var (command, handler) in commandHandlers)
{
AddCommandHandler(command, handler);
}
}
protected void RemoveCommandHandler(Commands command) => _commandHandlers.Remove(command);
}
}

View File

@@ -0,0 +1,71 @@
using System.Reactive.Linq;
using FileTime.App.Core.Command;
using FileTime.App.Core.Extensions;
using FileTime.App.Core.ViewModels;
using FileTime.Core.Models;
namespace FileTime.App.Core.Services.CommandHandler
{
public class NavigationCommandHandler : CommandHanderBase
{
private readonly IAppState _appState;
private ITabViewModel? _selectedTab;
private IContainer? _currentLocation;
private IItemViewModel? _currentSelectedItem;
private List<IItemViewModel> _currentItems = new();
public NavigationCommandHandler(IAppState appState)
{
_appState = appState;
_appState.SelectedTab.Subscribe(t => _selectedTab = t);
_appState.SelectedTab.Select(t => t == null ? Observable.Return<IContainer?>(null) : t.CurrentLocation).Switch().Subscribe(l => _currentLocation = l);
_appState.SelectedTab.Select(t => t == null ? Observable.Return<IItemViewModel?>(null) : t.CurrentSelectedItem).Switch().Subscribe(l => _currentSelectedItem = l);
_appState.SelectedTab.Select(t => t == null ? Observable.Return(Enumerable.Empty<IItemViewModel>()) : t.CurrentItems).Switch().Subscribe(i => _currentItems = i.ToList());
AddCommandHandlers(new (Commands, Func<Task>)[]
{
(Commands.GoUp, GoUp),
(Commands.MoveCursorDown, MoveCursorDown),
(Commands.MoveCursorUp, MoveCursorUp),
(Commands.Open, OpenContainer),
});
}
private Task OpenContainer()
{
if (_currentSelectedItem is not IContainerViewModel containerViewModel || containerViewModel.Container is null) return Task.CompletedTask;
_selectedTab?.Tab?.SetCurrentLocation(containerViewModel.Container);
return Task.CompletedTask;
}
private async Task GoUp()
{
if (_currentLocation?.Parent is not IAbsolutePath parentPath || await parentPath.ResolveAsyncSafe() is not IContainer newContainer) return;
_selectedTab?.Tab?.SetCurrentLocation(newContainer);
}
private Task MoveCursorDown()
{
SelectNewSelectedItem(i => i.SkipWhile(i => i != _currentSelectedItem).Skip(1).FirstOrDefault());
return Task.CompletedTask;
}
private Task MoveCursorUp()
{
SelectNewSelectedItem(i => i.TakeWhile(i => i != _currentSelectedItem).LastOrDefault());
return Task.CompletedTask;
}
private void SelectNewSelectedItem(Func<IEnumerable<IItemViewModel>, IItemViewModel?> getNewSelected)
{
if (_selectedTab is null || _currentLocation is null) return;
var newSelectedItem = getNewSelected(_currentItems);
if (newSelectedItem == null) return;
_selectedTab.Tab?.SetSelectedItem(newSelectedItem.ToAbsolutePath());
}
}
}

View File

@@ -1,129 +1,79 @@
using System.Reactive.Linq;
using FileTime.App.Core.Command;
using FileTime.App.Core.Extensions;
using FileTime.App.Core.ViewModels;
using FileTime.Core.Models;
namespace FileTime.App.Core.Services
{
public class CommandHandlerService : ICommandHandlerService
{
private readonly Dictionary<Commands, Func<Task>> _commandHandlers;
private readonly IAppState _appState;
private ITabViewModel? _selectedTab;
private IContainer? _currentLocation;
private IItemViewModel? _currentSelectedItem;
private List<IItemViewModel> _currentItems = new();
private readonly IEnumerable<ICommandHandler> _commandHandlers;
public CommandHandlerService(IAppState appState)
public CommandHandlerService(IEnumerable<ICommandHandler> commandHandlers)
{
_appState = appState;
_commandHandlers = commandHandlers;
_appState.SelectedTab.Subscribe(t => _selectedTab = t);
_appState.SelectedTab.Select(t => t == null ? Observable.Return<IContainer?>(null) : t.CurrentLocation).Switch().Subscribe(l => _currentLocation = l);
_appState.SelectedTab.Select(t => t == null ? Observable.Return<IItemViewModel?>(null) : t.CurrentSelectedItem).Switch().Subscribe(l => _currentSelectedItem = l);
_appState.SelectedTab.Select(t => t == null ? Observable.Return(Enumerable.Empty<IItemViewModel>()) : t.CurrentItems).Switch().Subscribe(i => _currentItems = i.ToList());
//(Commands.AutoRefresh, ToggleAutoRefresh),
//(Commands.ChangeTimelineMode, ChangeTimelineMode),
//(Commands.CloseTab, CloseTab),
//(Commands.Compress, Compress),
//(Commands.Copy, Copy),
//(Commands.CopyHash, CopyHash),
//(Commands.CopyPath, CopyPath),
//(Commands.CreateContainer, CreateContainer),
//(Commands.CreateElement, CreateElement),
//(Commands.Cut, Cut),
//(Commands.Edit, Edit),
//(Commands.EnterRapidTravel, EnterRapidTravelMode),
//(Commands.FindByName, FindByName),
//(Commands.FindByNameRegex, FindByNameRegex),
//(Commands.GoToHome, GotToHome),
//(Commands.GoToPath, GoToContainer),
//(Commands.GoToProvider, GotToProvider),
//(Commands.GoToRoot, GotToRoot),
//(Commands.HardDelete, HardDelete),
//(Commands.Mark, MarkCurrentItem),
//(Commands.MoveCursorDownPage, MoveCursorDownPage),
//(Commands.MoveCursorUpPage, MoveCursorUpPage),
//(Commands.MoveToFirst, MoveToFirst),
//(Commands.MoveToLast, MoveToLast),
//(Commands.NextTimelineBlock, SelectNextTimelineBlock),
//(Commands.NextTimelineCommand, SelectNextTimelineCommand),
//(Commands.OpenInFileBrowser, OpenInDefaultFileExplorer),
//(Commands.OpenOrRun, OpenOrRun),
//(Commands.PasteMerge, PasteMerge),
//(Commands.PasteOverwrite, PasteOverwrite),
//(Commands.PasteSkip, PasteSkip),
//(Commands.PinFavorite, PinFavorite),
//(Commands.PreviousTimelineBlock, SelectPreviousTimelineBlock),
//(Commands.PreviousTimelineCommand, SelectPreviousTimelineCommand),
//(Commands.Refresh, RefreshCurrentLocation),
//(Commands.Rename, Rename),
//(Commands.RunCommand, RunCommandInContainer),
//(Commands.ScanContainerSize, ScanContainerSize),
//(Commands.ShowAllShotcut, ShowAllShortcut),
//(Commands.SoftDelete, SoftDelete),
//(Commands.SwitchToLastTab, async() => await SwitchToTab(-1)),
//(Commands.SwitchToTab1, async() => await SwitchToTab(1)),
//(Commands.SwitchToTab2, async() => await SwitchToTab(2)),
//(Commands.SwitchToTab3, async() => await SwitchToTab(3)),
//(Commands.SwitchToTab4, async() => await SwitchToTab(4)),
//(Commands.SwitchToTab5, async() => await SwitchToTab(5)),
//(Commands.SwitchToTab6, async() => await SwitchToTab(6)),
//(Commands.SwitchToTab7, async() => await SwitchToTab(7)),
//(Commands.SwitchToTab8, async() => await SwitchToTab(8)),
//(Commands.TimelinePause, PauseTimeline),
//(Commands.TimelineRefresh, RefreshTimeline),
//(Commands.TimelineStart, ContinueTimeline),
//(Commands.ToggleAdvancedIcons, ToggleAdvancedIcons),
//(Commands.ToggleHidden, ToggleHidden),
}
_commandHandlers = new Dictionary<Commands, Func<Task>>
public async Task HandleCommandAsync(Commands command)
{
//{Commands.AutoRefresh, ToggleAutoRefresh},
//{Commands.ChangeTimelineMode, ChangeTimelineMode},
//{Commands.CloseTab, CloseTab},
//{Commands.Compress, Compress},
//{Commands.Copy, Copy},
//{Commands.CopyHash, CopyHash},
//{Commands.CopyPath, CopyPath},
//{Commands.CreateContainer, CreateContainer},
//{Commands.CreateElement, CreateElement},
//{Commands.Cut, Cut},
//{Commands.Edit, Edit},
//{Commands.EnterRapidTravel, EnterRapidTravelMode},
//{Commands.FindByName, FindByName},
//{Commands.FindByNameRegex, FindByNameRegex},
//{Commands.GoToHome, GotToHome},
//{Commands.GoToPath, GoToContainer},
//{Commands.GoToProvider, GotToProvider},
//{Commands.GoToRoot, GotToRoot},
{Commands.GoUp, GoUp},
//{Commands.HardDelete, HardDelete},
//{Commands.Mark, MarkCurrentItem},
{Commands.MoveCursorDown, MoveCursorDown},
//{Commands.MoveCursorDownPage, MoveCursorDownPage},
{Commands.MoveCursorUp, MoveCursorUp},
//{Commands.MoveCursorUpPage, MoveCursorUpPage},
//{Commands.MoveToFirst, MoveToFirst},
//{Commands.MoveToLast, MoveToLast},
//{Commands.NextTimelineBlock, SelectNextTimelineBlock},
//{Commands.NextTimelineCommand, SelectNextTimelineCommand},
{Commands.Open, OpenContainer},
//{Commands.OpenInFileBrowser, OpenInDefaultFileExplorer},
//{Commands.OpenOrRun, OpenOrRun},
//{Commands.PasteMerge, PasteMerge},
//{Commands.PasteOverwrite, PasteOverwrite},
//{Commands.PasteSkip, PasteSkip},
//{Commands.PinFavorite, PinFavorite},
//{Commands.PreviousTimelineBlock, SelectPreviousTimelineBlock},
//{Commands.PreviousTimelineCommand, SelectPreviousTimelineCommand},
//{Commands.Refresh, RefreshCurrentLocation},
//{Commands.Rename, Rename},
//{Commands.RunCommand, RunCommandInContainer},
//{Commands.ScanContainerSize, ScanContainerSize},
//{Commands.ShowAllShotcut, ShowAllShortcut},
//{Commands.SoftDelete, SoftDelete},
//{Commands.SwitchToLastTab, async() => await SwitchToTab(-1)},
//{Commands.SwitchToTab1, async() => await SwitchToTab(1)},
//{Commands.SwitchToTab2, async() => await SwitchToTab(2)},
//{Commands.SwitchToTab3, async() => await SwitchToTab(3)},
//{Commands.SwitchToTab4, async() => await SwitchToTab(4)},
//{Commands.SwitchToTab5, async() => await SwitchToTab(5)},
//{Commands.SwitchToTab6, async() => await SwitchToTab(6)},
//{Commands.SwitchToTab7, async() => await SwitchToTab(7)},
//{Commands.SwitchToTab8, async() => await SwitchToTab(8)},
//{Commands.TimelinePause, PauseTimeline},
//{Commands.TimelineRefresh, RefreshTimeline},
//{Commands.TimelineStart, ContinueTimeline},
//{Commands.ToggleAdvancedIcons, ToggleAdvancedIcons},
//{Commands.ToggleHidden, ToggleHidden},
};
}
var handler = _commandHandlers.FirstOrDefault(h => h.CanHandleCommand(command));
public async Task HandleCommandAsync(Commands command) =>
await _commandHandlers[command].Invoke();
private Task OpenContainer()
if (handler != null)
{
if (_currentSelectedItem is not IContainerViewModel containerViewModel || containerViewModel.Container is null) return Task.CompletedTask;
_selectedTab?.Tab?.SetCurrentLocation(containerViewModel.Container);
return Task.CompletedTask;
}
private async Task GoUp()
{
if (_currentLocation?.Parent is not IAbsolutePath parentPath || await parentPath.ResolveAsyncSafe() is not IContainer newContainer) return;
_selectedTab?.Tab?.SetCurrentLocation(newContainer);
}
private Task MoveCursorDown()
{
SelectNewSelectedItem(i => i.SkipWhile(i => i != _currentSelectedItem).Skip(1).FirstOrDefault());
return Task.CompletedTask;
}
private Task MoveCursorUp()
{
SelectNewSelectedItem(i => i.TakeWhile(i => i != _currentSelectedItem).LastOrDefault());
return Task.CompletedTask;
}
private void SelectNewSelectedItem(Func<IEnumerable<IItemViewModel>, IItemViewModel?> getNewSelected)
{
if (_selectedTab is null || _currentLocation is null) return;
var newSelectedItem = getNewSelected(_currentItems);
if (newSelectedItem == null) return;
_selectedTab.Tab?.SetSelectedItem(newSelectedItem.ToAbsolutePath());
await handler.HandleCommandAsync(command);
}
}
}
}

View File

@@ -0,0 +1,27 @@
using FileTime.App.Core.Services;
using FileTime.App.Core.Services.CommandHandler;
using FileTime.App.Core.ViewModels;
using Microsoft.Extensions.DependencyInjection;
namespace FileTime.App.Core
{
public static class Startup
{
public static IServiceCollection AddCoreAppServices(this IServiceCollection serviceCollection)
{
return serviceCollection
.AddTransient<ITabViewModel, TabViewModel>()
.AddTransient<IContainerViewModel, ContainerViewModel>()
.AddTransient<IElementViewModel, ElementViewModel>()
.AddTransient<IItemNameConverterService, ItemNameConverterService>()
.AddSingleton<ICommandHandlerService, CommandHandlerService>()
.AddCommandHandlers();
}
private static IServiceCollection AddCommandHandlers(this IServiceCollection serviceCollection)
{
return serviceCollection
.AddSingleton<ICommandHandler, NavigationCommandHandler>();
}
}
}

View File

@@ -1,3 +1,5 @@
using FileTime.App.Core;
using FileTime.Core.Services;
using FileTime.Providers.Local;
using Microsoft.Extensions.DependencyInjection;
@@ -10,6 +12,8 @@ namespace FileTime.App.DependencyInjection
serviceCollection ??= new ServiceCollection();
return serviceCollection
.AddTransient<ITab, Tab>()
.AddCoreAppServices()
.AddLocalServices();
}
}

View File

@@ -10,6 +10,7 @@
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Providers\FileTime.Providers.Local\FileTime.Providers.Local.csproj" />
<ProjectReference Include="..\FileTime.App.Core\FileTime.App.Core.csproj" />
</ItemGroup>
</Project>

View File

@@ -17,6 +17,7 @@ namespace FileTime.GuiApp
.RegisterDefaultServices()
.AddConfiguration()
.RegisterLogging()
.RegisterServices()
.AddViewModels()
.BuildServiceProvider()
.InitSerilog();

View File

@@ -1,9 +1,7 @@
using System;
using System.IO;
using FileTime.App.Core;
using FileTime.App.Core.Services;
using FileTime.App.Core.ViewModels;
using FileTime.Core.Services;
using FileTime.GuiApp.Configuration;
using FileTime.GuiApp.Logging;
using FileTime.GuiApp.Services;
@@ -23,17 +21,12 @@ namespace FileTime.GuiApp
.AddSingleton<MainWindowViewModel>()
.AddSingleton<GuiAppState>()
.AddSingleton<IAppState, GuiAppState>(s => s.GetRequiredService<GuiAppState>())
.AddSingleton<IGuiAppState, GuiAppState>(s => s.GetRequiredService<GuiAppState>())
.AddSingleton<DefaultModeKeyInputHandler>()
.AddSingleton<RapidTravelModeKeyInputHandler>()
.AddSingleton<IGuiAppState, GuiAppState>(s => s.GetRequiredService<GuiAppState>());
}
internal static IServiceCollection RegisterServices(this IServiceCollection serviceCollection)
{
return serviceCollection
.AddSingleton<IRxSchedulerService, AvaloniaRxSchedulerService>()
//TODO: move??
.AddTransient<ITab, Tab>()
.AddTransient<ITabViewModel, TabViewModel>()
.AddTransient<IContainerViewModel, ContainerViewModel>()
.AddTransient<IElementViewModel, ElementViewModel>()
.AddTransient<IItemNameConverterService, ItemNameConverterService>()
.AddSingleton<ICommandHandlerService, CommandHandlerService>()
.AddSingleton<IKeyInputHandlerService, KeyInputHandlerService>()
.AddSingleton<IDefaultModeKeyInputHandler, DefaultModeKeyInputHandler>()
.AddSingleton<IKeyboardConfigurationService, KeyboardConfigurationService>()