using FileTime.App.Core.Extensions; using FileTime.App.Core.Models.Enums; using FileTime.App.Core.UserCommand; using FileTime.App.Core.ViewModels; using FileTime.Core.Models; using FileTime.Core.Services; using FileTime.Core.Timeline; using FileTime.Providers.Local; using Microsoft.Extensions.DependencyInjection; namespace FileTime.App.Core.Services.UserCommandHandler; public class NavigationUserCommandHandlerService : UserCommandHandlerServiceBase { private readonly IAppState _appState; private readonly IServiceProvider _serviceProvider; private readonly ILocalContentProvider _localContentProvider; private readonly IUserCommandHandlerService _userCommandHandlerService; private readonly ITimelessContentProvider _timelessContentProvider; private ITabViewModel? _selectedTab; private IContainer? _currentLocation; private IItemViewModel? _currentSelectedItem; private IEnumerable _currentItems = Enumerable.Empty(); private ViewMode _viewMode; public NavigationUserCommandHandlerService( IAppState appState, IServiceProvider serviceProvider, ILocalContentProvider localContentProvider, IUserCommandHandlerService userCommandHandlerService, ITimelessContentProvider timelessContentProvider) : base(appState) { _appState = appState; _serviceProvider = serviceProvider; _localContentProvider = localContentProvider; _userCommandHandlerService = userCommandHandlerService; _timelessContentProvider = timelessContentProvider; SaveSelectedTab(t => _selectedTab = t); SaveCurrentSelectedItem(i => _currentSelectedItem = i); SaveCurrentLocation(l => _currentLocation = l); SaveCurrentItems(i => _currentItems = i); appState.ViewMode.Subscribe(v => _viewMode = v); AddCommandHandlers(new IUserCommandHandler[] { new TypeUserCommandHandler(CloseTab), new TypeUserCommandHandler(EnterRapidTravel), new TypeUserCommandHandler(ExitRapidTravel), new TypeUserCommandHandler(GoUp), new TypeUserCommandHandler(MoveCursorDown), new TypeUserCommandHandler(MoveCursorUp), new TypeUserCommandHandler(OpenContainer), new TypeUserCommandHandler(OpenSelected), new TypeUserCommandHandler(SwitchToTab), }); } private async Task OpenContainer(OpenContainerCommand command) { var resolvedPath = await command.Path.ResolveAsync(); if (resolvedPath is not IContainer resolvedContainer) return; _selectedTab?.Tab?.SetCurrentLocation(resolvedContainer); } private Task OpenSelected() { 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 AbsolutePath parentPath || await parentPath.ResolveAsyncSafe() is not IContainer newContainer) return; _selectedTab?.Tab?.SetCurrentLocation(newContainer); } private Task MoveCursorDown() { SelectNewSelectedItem(i => i.SkipWhile(i => !i.EqualsTo(_currentSelectedItem)).Skip(1).FirstOrDefault()); return Task.CompletedTask; } private Task MoveCursorUp() { SelectNewSelectedItem(i => i.TakeWhile(i => !i.EqualsTo(_currentSelectedItem)).LastOrDefault()); return Task.CompletedTask; } private void SelectNewSelectedItem(Func, IItemViewModel?> getNewSelected) { if (_selectedTab is null || _currentLocation is null) return; var newSelectedItem = getNewSelected(_currentItems); if (newSelectedItem == null) return; _selectedTab.Tab?.SetSelectedItem(newSelectedItem.ToAbsolutePath(_timelessContentProvider)); } private Task EnterRapidTravel() { _appState.SwitchViewMode(ViewMode.RapidTravel); return Task.CompletedTask; } private Task ExitRapidTravel() { _appState.SwitchViewMode(ViewMode.Default); return Task.CompletedTask; } private Task SwitchToTab(SwitchToTabCommand command) { var number = command.TabNumber; var tabViewModel = _appState.Tabs.FirstOrDefault(t => t.TabNumber == number); if (number == -1) { var greatestNumber = _appState.Tabs.Max(t => t.TabNumber); tabViewModel = _appState.Tabs.FirstOrDefault(t => t.TabNumber == greatestNumber); } else if (tabViewModel == null) { var tab = _serviceProvider.GetInitableResolver(_currentLocation ?? _localContentProvider) .GetRequiredService(); var newTabViewModel = _serviceProvider.GetInitableResolver(tab, number).GetRequiredService(); _appState.AddTab(newTabViewModel); tabViewModel = newTabViewModel; } if (_viewMode == ViewMode.RapidTravel) { _userCommandHandlerService.HandleCommandAsync(ExitRapidTravelCommand.Instance); } _appState.SetSelectedTab(tabViewModel!); return Task.CompletedTask; } private Task CloseTab() { if (_appState.Tabs.Count < 2 || _selectedTab == null) return Task.CompletedTask; var tabToRemove = _selectedTab; _appState.RemoveTab(tabToRemove!); try { tabToRemove.Dispose(); } catch { } return Task.CompletedTask; } }