783 lines
27 KiB
C#
783 lines
27 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Diagnostics;
|
|
using System.Linq;
|
|
using System.Threading.Tasks;
|
|
using Avalonia.Threading;
|
|
using FileTime.App.Core.Clipboard;
|
|
using FileTime.App.Core.Command;
|
|
using FileTime.Avalonia.Application;
|
|
using FileTime.Avalonia.IconProviders;
|
|
using FileTime.Avalonia.Misc;
|
|
using FileTime.Avalonia.ViewModels;
|
|
using FileTime.Core.Command;
|
|
using FileTime.Core.Components;
|
|
using FileTime.Core.Interactions;
|
|
using FileTime.Core.Models;
|
|
using FileTime.Core.Providers;
|
|
using FileTime.Core.Timeline;
|
|
using FileTime.Providers.Local;
|
|
|
|
namespace FileTime.Avalonia.Services
|
|
{
|
|
public class CommandHandlerService
|
|
{
|
|
private bool _addCommandToNextBatch;
|
|
|
|
private readonly AppState _appState;
|
|
private readonly LocalContentProvider _localContentProvider;
|
|
private readonly ItemNameConverterService _itemNameConverterService;
|
|
private readonly DialogService _dialogService;
|
|
private readonly IClipboard _clipboard;
|
|
private readonly TimeRunner _timeRunner;
|
|
private readonly IIconProvider _iconProvider;
|
|
private readonly IEnumerable<IContentProvider> _contentProviders;
|
|
private readonly Dictionary<Commands, Func<Task>> _commandHandlers;
|
|
|
|
public CommandHandlerService(
|
|
AppState appState,
|
|
LocalContentProvider localContentProvider,
|
|
ItemNameConverterService itemNameConverterService,
|
|
DialogService dialogService,
|
|
IClipboard clipboard,
|
|
TimeRunner timeRunner,
|
|
IIconProvider iconProvider,
|
|
IEnumerable<IContentProvider> contentProviders)
|
|
{
|
|
_appState = appState;
|
|
_localContentProvider = localContentProvider;
|
|
_itemNameConverterService = itemNameConverterService;
|
|
_dialogService = dialogService;
|
|
_clipboard = clipboard;
|
|
_timeRunner = timeRunner;
|
|
_iconProvider = iconProvider;
|
|
_contentProviders = contentProviders;
|
|
|
|
_commandHandlers = new Dictionary<Commands, Func<Task>>
|
|
{
|
|
{Commands.AutoRefresh, ToggleAutoRefresh},
|
|
{Commands.ChangeTimelineMode, ChangeTimelineMode},
|
|
{Commands.CloseTab, CloseTab},
|
|
{Commands.Copy, Copy},
|
|
{Commands.CopyPath, CopyPath},
|
|
{Commands.CreateContainer, CreateContainer},
|
|
{Commands.CreateElement, CreateElement},
|
|
{Commands.Cut, Cut},
|
|
{Commands.EnterRapidTravel, EnterRapidTravelMode},
|
|
{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.PreviousTimelineBlock, SelectPreviousTimelineBlock},
|
|
{Commands.PreviousTimelineCommand, SelectPreviousTimelineCommand},
|
|
{Commands.Refresh, RefreshCurrentLocation},
|
|
{Commands.Rename, Rename},
|
|
{Commands.RunCommand, RunCommandInContainer},
|
|
{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},
|
|
};
|
|
}
|
|
|
|
public async Task HandleCommandAsync(Commands command) =>
|
|
await _commandHandlers[command].Invoke();
|
|
|
|
private async Task OpenContainer()
|
|
{
|
|
_appState.RapidTravelText = "";
|
|
await _appState.SelectedTab.Open();
|
|
}
|
|
|
|
public async Task OpenContainer(IContainer container)
|
|
{
|
|
_appState.RapidTravelText = "";
|
|
await _appState.SelectedTab.OpenContainer(container);
|
|
}
|
|
|
|
private async Task OpenOrRun()
|
|
{
|
|
if (_appState.SelectedTab.SelectedItem is ContainerViewModel)
|
|
{
|
|
await OpenContainer();
|
|
}
|
|
else if (_appState.SelectedTab.SelectedItem is ElementViewModel elementViewModel && elementViewModel.Element is LocalFile localFile)
|
|
{
|
|
Process.Start(new ProcessStartInfo(localFile.File.FullName) { UseShellExecute = true });
|
|
|
|
if (_appState.ViewMode == ViewMode.RapidTravel)
|
|
{
|
|
await _appState.ExitRapidTravelMode();
|
|
}
|
|
}
|
|
}
|
|
|
|
private async Task GoUp()
|
|
{
|
|
await _appState.SelectedTab.GoUp();
|
|
}
|
|
|
|
private async Task MoveCursorUp()
|
|
{
|
|
await _appState.SelectedTab.MoveCursorUp();
|
|
}
|
|
|
|
private async Task MoveCursorDown()
|
|
{
|
|
await _appState.SelectedTab.MoveCursorDown();
|
|
}
|
|
|
|
private async Task MoveCursorUpPage()
|
|
{
|
|
await _appState.SelectedTab.MoveCursorUpPage();
|
|
}
|
|
|
|
private async Task MoveCursorDownPage()
|
|
{
|
|
await _appState.SelectedTab.MoveCursorDownPage();
|
|
}
|
|
|
|
private async Task MoveToFirst()
|
|
{
|
|
await _appState.SelectedTab.MoveCursorToFirst();
|
|
}
|
|
|
|
private async Task MoveToLast()
|
|
{
|
|
await _appState.SelectedTab.MoveCursorToLast();
|
|
}
|
|
|
|
private async Task GotToProvider()
|
|
{
|
|
await _appState.SelectedTab.GotToProvider();
|
|
}
|
|
|
|
private async Task GotToRoot()
|
|
{
|
|
await _appState.SelectedTab.GotToRoot();
|
|
}
|
|
|
|
private async Task GotToHome()
|
|
{
|
|
await _appState.SelectedTab.GotToHome();
|
|
}
|
|
|
|
private Task EnterRapidTravelMode()
|
|
{
|
|
_appState.ViewMode = ViewMode.RapidTravel;
|
|
|
|
_appState.PreviousKeys.Clear();
|
|
_appState.PossibleCommands = new();
|
|
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
private async Task SwitchToTab(int number)
|
|
{
|
|
var tabContainer = _appState.Tabs.FirstOrDefault(t => t.TabNumber == number);
|
|
|
|
if (number == -1)
|
|
{
|
|
var greatestNumber = _appState.Tabs.Max(t => t.TabNumber);
|
|
tabContainer = _appState.Tabs.FirstOrDefault(t => t.TabNumber == greatestNumber);
|
|
}
|
|
else if (tabContainer == null)
|
|
{
|
|
var newContainer = await _appState.SelectedTab.CurrentLocation.Container.Clone();
|
|
|
|
var newTab = new Tab();
|
|
await newTab.Init(newContainer);
|
|
|
|
tabContainer = new TabContainer(newTab, _localContentProvider, _itemNameConverterService);
|
|
await tabContainer.Init(number);
|
|
|
|
var i = 0;
|
|
for (i = 0; i < _appState.Tabs.Count; i++)
|
|
{
|
|
if (_appState.Tabs[i].TabNumber > number) break;
|
|
}
|
|
_appState.Tabs.Insert(i, tabContainer);
|
|
}
|
|
|
|
if (_appState.ViewMode == ViewMode.RapidTravel)
|
|
{
|
|
await _appState.ExitRapidTravelMode();
|
|
}
|
|
|
|
_appState.SelectedTab = tabContainer;
|
|
}
|
|
|
|
private async Task CloseTab()
|
|
{
|
|
var tabs = _appState.Tabs;
|
|
if (tabs.Count > 1)
|
|
{
|
|
var currentTab = tabs.FirstOrDefault(t => t == _appState.SelectedTab);
|
|
|
|
if (currentTab != null)
|
|
{
|
|
tabs.Remove(currentTab);
|
|
var tabNumber = tabs[0].TabNumber;
|
|
for (var i = 0; i < tabs.Count; i++)
|
|
{
|
|
tabNumber = tabs[i].TabNumber;
|
|
if (tabs[i].TabNumber > currentTab.TabNumber) break;
|
|
}
|
|
await SwitchToTab(tabNumber);
|
|
}
|
|
}
|
|
}
|
|
|
|
private Task CreateContainer()
|
|
{
|
|
var handler = async (List<InputElementWrapper> inputs) =>
|
|
{
|
|
var container = _appState.SelectedTab.CurrentLocation.Container;
|
|
var createContainerCommand = new CreateContainerCommand(new AbsolutePath(container), inputs[0].Value);
|
|
await AddCommand(createContainerCommand);
|
|
};
|
|
|
|
_dialogService.ReadInputs(new List<InputElement>() { new InputElement("Container name", InputType.Text) }, handler);
|
|
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
private Task CreateElement()
|
|
{
|
|
var handler = async (List<InputElementWrapper> inputs) =>
|
|
{
|
|
var container = _appState.SelectedTab.CurrentLocation.Container;
|
|
var createElementCommand = new CreateElementCommand(new AbsolutePath(container), inputs[0].Value);
|
|
await AddCommand(createElementCommand);
|
|
};
|
|
|
|
_dialogService.ReadInputs(new List<InputElement>() { new InputElement("Element name", InputType.Text) }, handler);
|
|
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
private async Task MarkCurrentItem()
|
|
{
|
|
await _appState.SelectedTab.MarkCurrentItem();
|
|
}
|
|
|
|
private async Task Copy()
|
|
{
|
|
_clipboard.Clear();
|
|
_clipboard.SetCommand<CopyCommand>();
|
|
|
|
var currentSelectedItems = await _appState.SelectedTab.TabState.GetCurrentMarkedItems();
|
|
if (currentSelectedItems.Count > 0)
|
|
{
|
|
foreach (var selectedItem in currentSelectedItems)
|
|
{
|
|
_clipboard.AddContent(selectedItem);
|
|
}
|
|
await _appState.SelectedTab.TabState.ClearCurrentMarkedItems();
|
|
}
|
|
else
|
|
{
|
|
var currentSelectedItem = _appState.SelectedTab.SelectedItem?.Item;
|
|
if (currentSelectedItem != null)
|
|
{
|
|
_clipboard.AddContent(new AbsolutePath(currentSelectedItem));
|
|
}
|
|
}
|
|
}
|
|
|
|
private Task Cut()
|
|
{
|
|
_clipboard.Clear();
|
|
_clipboard.SetCommand<MoveCommand>();
|
|
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
private async Task SoftDelete() => await Delete(false);
|
|
|
|
private async Task HardDelete() => await Delete(true);
|
|
|
|
public async Task Delete(bool hardDelete = false)
|
|
{
|
|
IList<AbsolutePath>? itemsToDelete = null;
|
|
var askForDelete = false;
|
|
var questionText = "";
|
|
var shouldDelete = false;
|
|
var shouldClearMarkedItems = false;
|
|
|
|
var currentSelectedItems = await _appState.SelectedTab.TabState.GetCurrentMarkedItems();
|
|
var currentSelectedItem = _appState.SelectedTab.SelectedItem?.Item;
|
|
if (currentSelectedItems.Count > 0)
|
|
{
|
|
itemsToDelete = new List<AbsolutePath>(currentSelectedItems);
|
|
shouldClearMarkedItems = true;
|
|
|
|
//FIXME: check 'is Container'
|
|
if (currentSelectedItems.Count == 1)
|
|
{
|
|
if ((await currentSelectedItems[0].Resolve()) is IContainer container
|
|
&& (await container.GetItems())?.Count > 0)
|
|
{
|
|
askForDelete = true;
|
|
questionText = $"The container '{container.Name}' is not empty. Proceed with delete?";
|
|
}
|
|
else
|
|
{
|
|
shouldDelete = true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
askForDelete = true;
|
|
questionText = $"Are you sure you want to delete {itemsToDelete.Count} item?";
|
|
}
|
|
}
|
|
else if (currentSelectedItem != null)
|
|
{
|
|
itemsToDelete = new List<AbsolutePath>()
|
|
{
|
|
new AbsolutePath(currentSelectedItem)
|
|
};
|
|
|
|
if (currentSelectedItem is IContainer container && (await container.GetItems())?.Count > 0)
|
|
{
|
|
askForDelete = true;
|
|
questionText = $"The container '{container.Name}' is not empty. Proceed with delete?";
|
|
}
|
|
else
|
|
{
|
|
shouldDelete = true;
|
|
}
|
|
}
|
|
|
|
if (itemsToDelete?.Count > 0)
|
|
{
|
|
if (askForDelete)
|
|
{
|
|
_dialogService.ShowMessageBox(questionText, HandleDelete);
|
|
}
|
|
else if (shouldDelete)
|
|
{
|
|
await HandleDelete();
|
|
}
|
|
}
|
|
|
|
async Task HandleDelete()
|
|
{
|
|
var deleteCommand = new DeleteCommand
|
|
{
|
|
HardDelete = hardDelete
|
|
};
|
|
|
|
foreach (var itemToDelete in itemsToDelete!)
|
|
{
|
|
deleteCommand.ItemsToDelete.Add(itemToDelete);
|
|
}
|
|
|
|
await AddCommand(deleteCommand);
|
|
_clipboard.Clear();
|
|
if (shouldClearMarkedItems)
|
|
{
|
|
await _appState.SelectedTab.TabState.ClearCurrentMarkedItems();
|
|
}
|
|
}
|
|
}
|
|
|
|
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 async Task Paste(TransportMode transportMode)
|
|
{
|
|
if (_clipboard.CommandType != null)
|
|
{
|
|
var command = (ITransportationCommand)Activator.CreateInstance(_clipboard.CommandType!)!;
|
|
command.TransportMode = transportMode;
|
|
|
|
command.Sources.Clear();
|
|
|
|
foreach (var item in _clipboard.Content)
|
|
{
|
|
command.Sources.Add(item);
|
|
}
|
|
|
|
var currentLocation = _appState.SelectedTab.CurrentLocation.Container;
|
|
command.Target = currentLocation is VirtualContainer virtualContainer
|
|
? virtualContainer.BaseContainer
|
|
: currentLocation;
|
|
|
|
await AddCommand(command);
|
|
|
|
_clipboard.Clear();
|
|
}
|
|
}
|
|
|
|
private Task Rename()
|
|
{
|
|
var selectedItem = _appState.SelectedTab.SelectedItem?.Item;
|
|
if (selectedItem != null)
|
|
{
|
|
var handler = async (List<InputElementWrapper> inputs) =>
|
|
{
|
|
var renameCommand = new RenameCommand(new AbsolutePath(selectedItem), inputs[0].Value);
|
|
await AddCommand(renameCommand);
|
|
};
|
|
|
|
_dialogService.ReadInputs(new List<InputElement>() { new InputElement("New name", InputType.Text, selectedItem.Name) }, handler);
|
|
}
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
private async Task RefreshCurrentLocation()
|
|
{
|
|
await _appState.SelectedTab.CurrentLocation.Container.RefreshAsync();
|
|
await _appState.SelectedTab.UpdateCurrentSelectedItem();
|
|
}
|
|
|
|
private Task PauseTimeline()
|
|
{
|
|
_timeRunner.EnableRunning = false;
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
private async Task ContinueTimeline()
|
|
{
|
|
_timeRunner.EnableRunning = true;
|
|
await _timeRunner.TryStartCommandRunner();
|
|
}
|
|
|
|
private async Task RefreshTimeline()
|
|
{
|
|
await _timeRunner.Refresh();
|
|
}
|
|
|
|
private Task ChangeTimelineMode()
|
|
{
|
|
_addCommandToNextBatch = !_addCommandToNextBatch;
|
|
_dialogService.ShowToastMessage("Timeline mode: " + (_addCommandToNextBatch ? "Continuous" : "Parallel"));
|
|
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
private Task GoToContainer()
|
|
{
|
|
var handler = async (List<InputElementWrapper> inputs) =>
|
|
{
|
|
var path = inputs[0].Value;
|
|
foreach (var contentProvider in _contentProviders)
|
|
{
|
|
if (contentProvider.CanHandlePath(path))
|
|
{
|
|
var possibleContainer = await contentProvider.GetByPath(path);
|
|
if (possibleContainer is IContainer container)
|
|
{
|
|
await _appState.SelectedTab.OpenContainer(container);
|
|
}
|
|
//TODO: multiple possible content provider handler
|
|
return;
|
|
}
|
|
}
|
|
};
|
|
|
|
_dialogService.ReadInputs(new List<InputElement>() { new InputElement("Path", InputType.Text) }, handler);
|
|
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
private Task ToggleAdvancedIcons()
|
|
{
|
|
_iconProvider.EnableAdvancedIcons = !_iconProvider.EnableAdvancedIcons;
|
|
_dialogService.ShowToastMessage("Advanced icons are: " + (_iconProvider.EnableAdvancedIcons ? "ON" : "OFF"));
|
|
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
private Task ToggleHidden()
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
private Task OpenInDefaultFileExplorer()
|
|
{
|
|
if (_appState.SelectedTab.CurrentLocation.Container is LocalFolder localFolder)
|
|
{
|
|
var path = localFolder.Directory.FullName;
|
|
if (path != null)
|
|
{
|
|
Process.Start("explorer.exe", "\"" + path + "\"");
|
|
}
|
|
}
|
|
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
private async Task CopyPath()
|
|
{
|
|
string? textToCopy = null;
|
|
if (_appState.SelectedTab.CurrentLocation.Container is LocalFolder localFolder)
|
|
{
|
|
textToCopy = localFolder.Directory.FullName;
|
|
}
|
|
if (_appState.SelectedTab.CurrentLocation.Container is LocalFile localFile)
|
|
{
|
|
textToCopy = localFile.File.FullName;
|
|
}
|
|
else if (_appState.SelectedTab.CurrentLocation.Container.FullName is string fullName)
|
|
{
|
|
textToCopy = fullName;
|
|
}
|
|
|
|
if (textToCopy != null && global::Avalonia.Application.Current?.Clipboard is not null)
|
|
{
|
|
await global::Avalonia.Application.Current.Clipboard.SetTextAsync(textToCopy);
|
|
}
|
|
}
|
|
|
|
private Task ShowAllShortcut()
|
|
{
|
|
_appState.IsAllShortcutVisible = true;
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
private Task RunCommandInContainer()
|
|
{
|
|
var handler = (List<InputElementWrapper> inputs) =>
|
|
{
|
|
var input = inputs[0].Value;
|
|
string? path = null;
|
|
string? arguments = null;
|
|
|
|
if (input.StartsWith("\""))
|
|
{
|
|
var pathEnd = input.IndexOf('\"', 1);
|
|
|
|
path = input.Substring(1, pathEnd);
|
|
arguments = input.Substring(pathEnd + 1).Trim();
|
|
}
|
|
else
|
|
{
|
|
var inputParts = input.Split(' ');
|
|
path = inputParts[0];
|
|
arguments = inputParts.Length > 1 ? string.Join(' ', inputParts[1..]).Trim() : null;
|
|
}
|
|
|
|
if (!string.IsNullOrWhiteSpace(path))
|
|
{
|
|
using var process = new Process();
|
|
process.StartInfo.FileName = path;
|
|
|
|
if (!string.IsNullOrWhiteSpace(arguments))
|
|
{
|
|
process.StartInfo.Arguments = arguments;
|
|
}
|
|
if (_appState.SelectedTab.CurrentLocation.Container is LocalFolder localFolder)
|
|
{
|
|
process.StartInfo.WorkingDirectory = localFolder.Directory.FullName;
|
|
}
|
|
process.Start();
|
|
}
|
|
|
|
return Task.CompletedTask;
|
|
};
|
|
|
|
_dialogService.ReadInputs(new List<InputElement>() { new InputElement("Command", InputType.Text) }, handler);
|
|
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
private Task SelectPreviousTimelineBlock()
|
|
{
|
|
var currentSelected = GetSelectedTimelineCommandOrSelectFirst();
|
|
if (currentSelected == null) return Task.CompletedTask;
|
|
|
|
ParallelCommandsViewModel? newBlockVM = null;
|
|
ParallelCommandsViewModel? previousBlockVM = null;
|
|
|
|
foreach (var timelineBlock in _appState.TimelineCommands)
|
|
{
|
|
|
|
foreach (var command in timelineBlock.ParallelCommands)
|
|
{
|
|
if (command.IsSelected)
|
|
{
|
|
newBlockVM = previousBlockVM;
|
|
break;
|
|
}
|
|
}
|
|
|
|
previousBlockVM = timelineBlock;
|
|
}
|
|
|
|
if (newBlockVM == null) return Task.CompletedTask;
|
|
|
|
foreach (var val in _appState.TimelineCommands.Select(t => t.ParallelCommands.Select((c, i) => (ParalellCommandVM: t, CommandVM: c, Index: i))).SelectMany(t => t))
|
|
{
|
|
val.CommandVM.IsSelected = val.ParalellCommandVM == newBlockVM && val.Index == 0;
|
|
}
|
|
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
private Task SelectNextTimelineCommand()
|
|
{
|
|
var currentSelected = GetSelectedTimelineCommandOrSelectFirst();
|
|
if (currentSelected == null) return Task.CompletedTask;
|
|
|
|
ParallelCommandViewModel? lastCommand = null;
|
|
var any = false;
|
|
foreach (var command in _appState.TimelineCommands.SelectMany(t => t.ParallelCommands))
|
|
{
|
|
var isSelected = lastCommand == currentSelected;
|
|
command.IsSelected = isSelected;
|
|
any = any || isSelected;
|
|
lastCommand = command;
|
|
}
|
|
if (!any && lastCommand != null) lastCommand.IsSelected = true;
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
private Task SelectPreviousTimelineCommand()
|
|
{
|
|
var currentSelected = GetSelectedTimelineCommandOrSelectFirst();
|
|
if (currentSelected == null) return Task.CompletedTask;
|
|
|
|
ParallelCommandViewModel? lastCommand = null;
|
|
foreach (var command in _appState.TimelineCommands.SelectMany(t => t.ParallelCommands))
|
|
{
|
|
if (lastCommand != null)
|
|
{
|
|
lastCommand.IsSelected = command == currentSelected;
|
|
}
|
|
lastCommand = command;
|
|
}
|
|
if (lastCommand != null) lastCommand.IsSelected = false;
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
private Task SelectNextTimelineBlock()
|
|
{
|
|
var currentSelected = GetSelectedTimelineCommandOrSelectFirst();
|
|
if (currentSelected == null) return Task.CompletedTask;
|
|
|
|
ParallelCommandsViewModel? newBlockVM = null;
|
|
var select = false;
|
|
foreach (var timelineBlock in _appState.TimelineCommands)
|
|
{
|
|
if (select)
|
|
{
|
|
newBlockVM = timelineBlock;
|
|
break;
|
|
}
|
|
foreach (var command in timelineBlock.ParallelCommands)
|
|
{
|
|
if (command.IsSelected)
|
|
{
|
|
select = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (newBlockVM == null) return Task.CompletedTask;
|
|
|
|
foreach (var val in _appState.TimelineCommands.Select(t => t.ParallelCommands.Select((c, i) => (ParalellCommandVM: t, CommandVM: c, Index: i))).SelectMany(t => t))
|
|
{
|
|
val.CommandVM.IsSelected = val.ParalellCommandVM == newBlockVM && val.Index == 0;
|
|
}
|
|
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
private ParallelCommandViewModel? GetSelectedTimelineCommandOrSelectFirst()
|
|
{
|
|
var currentSelected = _appState.TimelineCommands.SelectMany(t => t.ParallelCommands).FirstOrDefault(c => c.IsSelected);
|
|
if (currentSelected != null) return currentSelected;
|
|
|
|
var firstCommand = _appState.TimelineCommands.SelectMany(t => t.ParallelCommands).FirstOrDefault();
|
|
if (firstCommand != null)
|
|
{
|
|
firstCommand.IsSelected = true;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
private async Task AddCommand(ICommand command)
|
|
{
|
|
if (_addCommandToNextBatch)
|
|
{
|
|
await _timeRunner.AddCommand(command, toNewBatch: true);
|
|
}
|
|
else
|
|
{
|
|
ParallelCommandsViewModel? batchToAdd = null;
|
|
foreach (var val in _appState.TimelineCommands.Select(t => t.ParallelCommands.Select(c => (ParalellCommandVM: t, CommandVM: c))).SelectMany(t => t))
|
|
{
|
|
if (val.CommandVM.IsSelected)
|
|
{
|
|
batchToAdd = val.ParalellCommandVM;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (batchToAdd != null)
|
|
{
|
|
await _timeRunner.AddCommand(command, batchToAdd.Id);
|
|
}
|
|
else
|
|
{
|
|
await _timeRunner.AddCommand(command);
|
|
}
|
|
}
|
|
}
|
|
|
|
private Task ToggleAutoRefresh()
|
|
{
|
|
var tab = _appState.SelectedTab.TabState.Tab;
|
|
tab.AutoRefresh = !tab.AutoRefresh;
|
|
|
|
_dialogService.ShowToastMessage("Auto refresh is: " + (tab.AutoRefresh ? "ON" : "OFF"));
|
|
|
|
return Task.CompletedTask;
|
|
}
|
|
}
|
|
} |