From ced0c88a10e20eda1fdbac0deb6b18b033ab88bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81d=C3=A1m=20Kov=C3=A1cs?= Date: Thu, 19 May 2022 22:46:25 +0200 Subject: [PATCH] InputHandler, CreateContainer user command --- .../UserCommand/CreateContainer.cs | 13 ++++ .../FileTime.App.Core.csproj | 1 + ...emManipulationUserCommandHandlerService.cs | 21 ++++- ...faultIdentifiableCommandHandlerRegister.cs | 1 + .../FileTime.Core.Abstraction.csproj | 4 + .../Interactions/IInputElement.cs | 7 ++ .../Interactions/IInputInterface.cs | 6 ++ .../Interactions/IOptionElement.cs | 7 ++ .../Interactions/IOptionsInputElement.cs | 7 ++ .../Interactions/InputElementBase.cs | 13 ++++ .../Interactions/InputType.cs | 8 ++ .../Interactions/OptionElement.cs | 17 ++++ .../Interactions/OptionsInputElement.cs | 23 ++++++ .../Interactions/PasswordInputElement.cs | 17 ++++ .../Interactions/TextInputElement.cs | 14 ++++ .../Configuration/MainConfiguration.cs | 4 +- .../Services/IDialogService.cs | 10 +++ .../Services/IKeyboardConfigurationService.cs | 6 +- .../ViewModels/ReadInputsViewModel.cs | 28 +++++++ .../Avalonia/FileTime.GuiApp.App/Startup.cs | 5 +- .../Models/InputElementWrapper.cs | 19 ----- .../Services/DefaultModeKeyInputHandler.cs | 6 +- .../FileTime.GuiApp/Services/DialogService.cs | 59 ++++++++++++++ .../Services/KeyboardConfigurationService.cs | 20 ++--- .../RapidTravelModeKeyInputHandler.cs | 2 +- .../ViewModels/MainWindowViewModel.cs | 1 + .../FileTime.GuiApp/Views/MainWindow.axaml | 77 ++++++++++++++++++- .../FileTime.GuiApp/Views/MainWindow.axaml.cs | 14 ++-- 28 files changed, 358 insertions(+), 52 deletions(-) create mode 100644 src/AppCommon/FileTime.App.Core.Abstraction/UserCommand/CreateContainer.cs create mode 100644 src/Core/FileTime.Core.Abstraction/Interactions/IInputElement.cs create mode 100644 src/Core/FileTime.Core.Abstraction/Interactions/IInputInterface.cs create mode 100644 src/Core/FileTime.Core.Abstraction/Interactions/IOptionElement.cs create mode 100644 src/Core/FileTime.Core.Abstraction/Interactions/IOptionsInputElement.cs create mode 100644 src/Core/FileTime.Core.Abstraction/Interactions/InputElementBase.cs create mode 100644 src/Core/FileTime.Core.Abstraction/Interactions/InputType.cs create mode 100644 src/Core/FileTime.Core.Abstraction/Interactions/OptionElement.cs create mode 100644 src/Core/FileTime.Core.Abstraction/Interactions/OptionsInputElement.cs create mode 100644 src/Core/FileTime.Core.Abstraction/Interactions/PasswordInputElement.cs create mode 100644 src/Core/FileTime.Core.Abstraction/Interactions/TextInputElement.cs create mode 100644 src/GuiApp/Avalonia/FileTime.GuiApp.Abstractions/Services/IDialogService.cs create mode 100644 src/GuiApp/Avalonia/FileTime.GuiApp.Abstractions/ViewModels/ReadInputsViewModel.cs delete mode 100644 src/GuiApp/Avalonia/FileTime.GuiApp/Models/InputElementWrapper.cs create mode 100644 src/GuiApp/Avalonia/FileTime.GuiApp/Services/DialogService.cs diff --git a/src/AppCommon/FileTime.App.Core.Abstraction/UserCommand/CreateContainer.cs b/src/AppCommon/FileTime.App.Core.Abstraction/UserCommand/CreateContainer.cs new file mode 100644 index 0000000..2cf4b49 --- /dev/null +++ b/src/AppCommon/FileTime.App.Core.Abstraction/UserCommand/CreateContainer.cs @@ -0,0 +1,13 @@ +namespace FileTime.App.Core.UserCommand; + +public class CreateContainer : IIdentifiableUserCommand +{ + public const string CommandName = "create_container"; + public static CreateContainer Instance { get; } = new CreateContainer(); + + private CreateContainer() + { + } + + public string UserCommandID => CommandName; +} \ No newline at end of file diff --git a/src/AppCommon/FileTime.App.Core/FileTime.App.Core.csproj b/src/AppCommon/FileTime.App.Core/FileTime.App.Core.csproj index 90a0c45..8271a5d 100644 --- a/src/AppCommon/FileTime.App.Core/FileTime.App.Core.csproj +++ b/src/AppCommon/FileTime.App.Core/FileTime.App.Core.csproj @@ -11,6 +11,7 @@ + diff --git a/src/AppCommon/FileTime.App.Core/Services/UserCommandHandler/ItemManipulationUserCommandHandlerService.cs b/src/AppCommon/FileTime.App.Core/Services/UserCommandHandler/ItemManipulationUserCommandHandlerService.cs index 7a8e6c2..a16ed1d 100644 --- a/src/AppCommon/FileTime.App.Core/Services/UserCommandHandler/ItemManipulationUserCommandHandlerService.cs +++ b/src/AppCommon/FileTime.App.Core/Services/UserCommandHandler/ItemManipulationUserCommandHandlerService.cs @@ -4,7 +4,9 @@ using FileTime.App.Core.Models.Enums; using FileTime.App.Core.UserCommand; using FileTime.App.Core.ViewModels; using FileTime.Core.Command; +using FileTime.Core.Interactions; using FileTime.Core.Models; +using Microsoft.Extensions.Logging; using CopyCommand = FileTime.Core.Command.Copy.CopyCommand; namespace FileTime.App.Core.Services.UserCommandHandler; @@ -15,15 +17,21 @@ public class ItemManipulationUserCommandHandlerService : UserCommandHandlerServi private IItemViewModel? _currentSelectedItem; private readonly IUserCommandHandlerService _userCommandHandlerService; private readonly IClipboardService _clipboardService; + private readonly IInputInterface _inputInterface; + private readonly ILogger _logger; private readonly BindedCollection? _markedItems; public ItemManipulationUserCommandHandlerService( IAppState appState, IUserCommandHandlerService userCommandHandlerService, - IClipboardService clipboardService) : base(appState) + IClipboardService clipboardService, + IInputInterface inputInterface, + ILogger logger) : base(appState) { _userCommandHandlerService = userCommandHandlerService; _clipboardService = clipboardService; + _inputInterface = inputInterface; + _logger = logger; SaveSelectedTab(t => _selectedTab = t); SaveCurrentSelectedItem(i => _currentSelectedItem = i); @@ -35,6 +43,7 @@ public class ItemManipulationUserCommandHandlerService : UserCommandHandlerServi new TypeUserCommandHandler(Copy), new TypeUserCommandHandler(MarkItem), new TypeUserCommandHandler(Paste), + new TypeUserCommandHandler(CreateContainer), }); } @@ -99,4 +108,14 @@ public class ItemManipulationUserCommandHandlerService : UserCommandHandlerServi if (_clipboardService.CommandType is null) return Task.CompletedTask; return Task.CompletedTask; } + + private async Task CreateContainer() + { + var containerNameInput = new TextInputElement("Container name"); + + await _inputInterface.ReadInputs(new List() { containerNameInput }); + + //TODO: message on empty result + var newContainerName = containerNameInput.Value; + } } \ No newline at end of file diff --git a/src/AppCommon/FileTime.App.Core/StartupServices/DefaultIdentifiableCommandHandlerRegister.cs b/src/AppCommon/FileTime.App.Core/StartupServices/DefaultIdentifiableCommandHandlerRegister.cs index 297c556..13e9960 100644 --- a/src/AppCommon/FileTime.App.Core/StartupServices/DefaultIdentifiableCommandHandlerRegister.cs +++ b/src/AppCommon/FileTime.App.Core/StartupServices/DefaultIdentifiableCommandHandlerRegister.cs @@ -13,6 +13,7 @@ public class DefaultIdentifiableCommandHandlerRegister : IStartupHandler AddUserCommand(CloseTabCommand.Instance); AddUserCommand(CopyCommand.Instance); + AddUserCommand(CreateContainer.Instance); AddUserCommand(EnterRapidTravelCommand.Instance); AddUserCommand(ExitRapidTravelCommand.Instance); AddUserCommand(GoUpCommand.Instance); diff --git a/src/Core/FileTime.Core.Abstraction/FileTime.Core.Abstraction.csproj b/src/Core/FileTime.Core.Abstraction/FileTime.Core.Abstraction.csproj index 34b269c..c59001f 100644 --- a/src/Core/FileTime.Core.Abstraction/FileTime.Core.Abstraction.csproj +++ b/src/Core/FileTime.Core.Abstraction/FileTime.Core.Abstraction.csproj @@ -13,6 +13,10 @@ + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + diff --git a/src/Core/FileTime.Core.Abstraction/Interactions/IInputElement.cs b/src/Core/FileTime.Core.Abstraction/Interactions/IInputElement.cs new file mode 100644 index 0000000..fe418bc --- /dev/null +++ b/src/Core/FileTime.Core.Abstraction/Interactions/IInputElement.cs @@ -0,0 +1,7 @@ +namespace FileTime.Core.Interactions; + +public interface IInputElement +{ + InputType Type { get; } + string Label { get; } +} \ No newline at end of file diff --git a/src/Core/FileTime.Core.Abstraction/Interactions/IInputInterface.cs b/src/Core/FileTime.Core.Abstraction/Interactions/IInputInterface.cs new file mode 100644 index 0000000..06efc14 --- /dev/null +++ b/src/Core/FileTime.Core.Abstraction/Interactions/IInputInterface.cs @@ -0,0 +1,6 @@ +namespace FileTime.Core.Interactions; + +public interface IInputInterface +{ + Task ReadInputs(IEnumerable fields); +} \ No newline at end of file diff --git a/src/Core/FileTime.Core.Abstraction/Interactions/IOptionElement.cs b/src/Core/FileTime.Core.Abstraction/Interactions/IOptionElement.cs new file mode 100644 index 0000000..e2bc897 --- /dev/null +++ b/src/Core/FileTime.Core.Abstraction/Interactions/IOptionElement.cs @@ -0,0 +1,7 @@ +namespace FileTime.Core.Interactions; + +public interface IOptionElement +{ + string Text { get; } + object? Value { get; } +} \ No newline at end of file diff --git a/src/Core/FileTime.Core.Abstraction/Interactions/IOptionsInputElement.cs b/src/Core/FileTime.Core.Abstraction/Interactions/IOptionsInputElement.cs new file mode 100644 index 0000000..8764de7 --- /dev/null +++ b/src/Core/FileTime.Core.Abstraction/Interactions/IOptionsInputElement.cs @@ -0,0 +1,7 @@ +namespace FileTime.Core.Interactions; + +public interface IOptionsInputElement : IInputElement +{ + object Value { get; set; } + IEnumerable Options { get; } +} \ No newline at end of file diff --git a/src/Core/FileTime.Core.Abstraction/Interactions/InputElementBase.cs b/src/Core/FileTime.Core.Abstraction/Interactions/InputElementBase.cs new file mode 100644 index 0000000..48dadd5 --- /dev/null +++ b/src/Core/FileTime.Core.Abstraction/Interactions/InputElementBase.cs @@ -0,0 +1,13 @@ +namespace FileTime.Core.Interactions; + +public abstract class InputElementBase : IInputElement +{ + public InputType Type { get; } + public string Label { get; } + + protected InputElementBase(string label, InputType type) + { + Label = label; + Type = type; + } +} \ No newline at end of file diff --git a/src/Core/FileTime.Core.Abstraction/Interactions/InputType.cs b/src/Core/FileTime.Core.Abstraction/Interactions/InputType.cs new file mode 100644 index 0000000..0e9f496 --- /dev/null +++ b/src/Core/FileTime.Core.Abstraction/Interactions/InputType.cs @@ -0,0 +1,8 @@ +namespace FileTime.Core.Interactions; + +public enum InputType +{ + Options, + Password, + Text, +} \ No newline at end of file diff --git a/src/Core/FileTime.Core.Abstraction/Interactions/OptionElement.cs b/src/Core/FileTime.Core.Abstraction/Interactions/OptionElement.cs new file mode 100644 index 0000000..8fa1eac --- /dev/null +++ b/src/Core/FileTime.Core.Abstraction/Interactions/OptionElement.cs @@ -0,0 +1,17 @@ +namespace FileTime.Core.Interactions; + +public class OptionElement : IOptionElement +{ + public string Text { get; } + public T Value { get; } + + object IOptionElement.Value => Value; + + public OptionElement(string text, T value) + { + ArgumentNullException.ThrowIfNull(value); + + Text = text; + Value = value; + } +} \ No newline at end of file diff --git a/src/Core/FileTime.Core.Abstraction/Interactions/OptionsInputElement.cs b/src/Core/FileTime.Core.Abstraction/Interactions/OptionsInputElement.cs new file mode 100644 index 0000000..6d17e48 --- /dev/null +++ b/src/Core/FileTime.Core.Abstraction/Interactions/OptionsInputElement.cs @@ -0,0 +1,23 @@ +using System.ComponentModel; +using PropertyChanged.SourceGenerator; + +namespace FileTime.Core.Interactions; + +public partial class OptionsInputElement : InputElementBase, IOptionsInputElement, INotifyPropertyChanged +{ + public IEnumerable> Options { get; } + + [Notify] private T? _value; + + IEnumerable IOptionsInputElement.Options => Options; + object? IOptionsInputElement.Value + { + get => Value; + set => Value = (T?)value; + } + + public OptionsInputElement(string label, IEnumerable> options) : base(label, InputType.Options) + { + Options = options; + } +} \ No newline at end of file diff --git a/src/Core/FileTime.Core.Abstraction/Interactions/PasswordInputElement.cs b/src/Core/FileTime.Core.Abstraction/Interactions/PasswordInputElement.cs new file mode 100644 index 0000000..2ae7ed6 --- /dev/null +++ b/src/Core/FileTime.Core.Abstraction/Interactions/PasswordInputElement.cs @@ -0,0 +1,17 @@ +using System.ComponentModel; +using PropertyChanged.SourceGenerator; + +namespace FileTime.Core.Interactions; + +public partial class PasswordInputElement : InputElementBase, INotifyPropertyChanged +{ + public char PasswordChar { get; } + + [Notify] private string? _value; + + public PasswordInputElement(string label, string? value = null, char passwordChar = '*') : base(label, InputType.Password) + { + PasswordChar = passwordChar; + _value = value; + } +} \ No newline at end of file diff --git a/src/Core/FileTime.Core.Abstraction/Interactions/TextInputElement.cs b/src/Core/FileTime.Core.Abstraction/Interactions/TextInputElement.cs new file mode 100644 index 0000000..3e1db72 --- /dev/null +++ b/src/Core/FileTime.Core.Abstraction/Interactions/TextInputElement.cs @@ -0,0 +1,14 @@ +using System.ComponentModel; +using PropertyChanged.SourceGenerator; + +namespace FileTime.Core.Interactions; + +public partial class TextInputElement : InputElementBase, INotifyPropertyChanged +{ + [Notify] private string? _value; + + public TextInputElement(string label, string? value = null) : base(label, InputType.Text) + { + _value = value; + } +} \ No newline at end of file diff --git a/src/GuiApp/Avalonia/FileTime.GuiApp.Abstractions/Configuration/MainConfiguration.cs b/src/GuiApp/Avalonia/FileTime.GuiApp.Abstractions/Configuration/MainConfiguration.cs index 25f16de..7e31bc0 100644 --- a/src/GuiApp/Avalonia/FileTime.GuiApp.Abstractions/Configuration/MainConfiguration.cs +++ b/src/GuiApp/Avalonia/FileTime.GuiApp.Abstractions/Configuration/MainConfiguration.cs @@ -47,8 +47,8 @@ public static class MainConfiguration new CommandBindingConfiguration(CopyCommand.CommandName, new[] { Key.Y, Key.Y }), //new CommandBindingConfiguration(ConfigCommand.CopyHash, new[] { Key.C, Key.H }), //new CommandBindingConfiguration(ConfigCommand.CopyPath, new[] { Key.C, Key.P }), - //new CommandBindingConfiguration(ConfigCommand.CreateContainer, Key.F7), - //new CommandBindingConfiguration(ConfigCommand.CreateContainer, new[] { Key.C, Key.C }), + new CommandBindingConfiguration(CreateContainer.CommandName, Key.F7), + new CommandBindingConfiguration(CreateContainer.CommandName, new[] { Key.C, Key.C }), //new CommandBindingConfiguration(ConfigCommand.CreateElement, new[] { Key.C, Key.E }), //new CommandBindingConfiguration(ConfigCommand.Cut, new[] { Key.D, Key.D }), //new CommandBindingConfiguration(ConfigCommand.Edit, new KeyConfig(Key.F4)), diff --git a/src/GuiApp/Avalonia/FileTime.GuiApp.Abstractions/Services/IDialogService.cs b/src/GuiApp/Avalonia/FileTime.GuiApp.Abstractions/Services/IDialogService.cs new file mode 100644 index 0000000..f79f07e --- /dev/null +++ b/src/GuiApp/Avalonia/FileTime.GuiApp.Abstractions/Services/IDialogService.cs @@ -0,0 +1,10 @@ +using FileTime.Core.Interactions; +using FileTime.GuiApp.ViewModels; + +namespace FileTime.GuiApp.Services; + +public interface IDialogService : IInputInterface +{ + IObservable ReadInput { get; } + void ReadInputs(IEnumerable inputs, Action inputHandler, Action? cancelHandler = null); +} \ No newline at end of file diff --git a/src/GuiApp/Avalonia/FileTime.GuiApp.Abstractions/Services/IKeyboardConfigurationService.cs b/src/GuiApp/Avalonia/FileTime.GuiApp.Abstractions/Services/IKeyboardConfigurationService.cs index 24cf0b1..224a9ac 100644 --- a/src/GuiApp/Avalonia/FileTime.GuiApp.Abstractions/Services/IKeyboardConfigurationService.cs +++ b/src/GuiApp/Avalonia/FileTime.GuiApp.Abstractions/Services/IKeyboardConfigurationService.cs @@ -4,7 +4,7 @@ namespace FileTime.GuiApp.Services; public interface IKeyboardConfigurationService { - IReadOnlyDictionary CommandBindings { get; } - IReadOnlyDictionary UniversalCommandBindings { get; } - IReadOnlyDictionary AllShortcut { get; } + IReadOnlyList CommandBindings { get; } + IReadOnlyList UniversalCommandBindings { get; } + IReadOnlyList AllShortcut { get; } } \ No newline at end of file diff --git a/src/GuiApp/Avalonia/FileTime.GuiApp.Abstractions/ViewModels/ReadInputsViewModel.cs b/src/GuiApp/Avalonia/FileTime.GuiApp.Abstractions/ViewModels/ReadInputsViewModel.cs new file mode 100644 index 0000000..5fb4d2e --- /dev/null +++ b/src/GuiApp/Avalonia/FileTime.GuiApp.Abstractions/ViewModels/ReadInputsViewModel.cs @@ -0,0 +1,28 @@ +using FileTime.App.Core.ViewModels; +using FileTime.Core.Interactions; +using MvvmGen; + +namespace FileTime.GuiApp.ViewModels; + +[ViewModel] +[Inject(typeof(Action), "_cancel")] +[Inject(typeof(Action), "_process")] +public partial class ReadInputsViewModel : IModalViewModelBase +{ + public string Name => "ReadInputs"; + public List Inputs { get; set; } + public Action SuccessHandler { get; set; } + public Action? CancelHandler { get; set; } + + [Command] + public void Process() + { + _process.Invoke(this); + } + + [Command] + public void Cancel() + { + _cancel.Invoke(this); + } +} \ No newline at end of file diff --git a/src/GuiApp/Avalonia/FileTime.GuiApp.App/Startup.cs b/src/GuiApp/Avalonia/FileTime.GuiApp.App/Startup.cs index d2804ce..120298a 100644 --- a/src/GuiApp/Avalonia/FileTime.GuiApp.App/Startup.cs +++ b/src/GuiApp/Avalonia/FileTime.GuiApp.App/Startup.cs @@ -2,6 +2,7 @@ using System; using System.IO; using FileTime.App.Core.Services; using FileTime.App.Core.ViewModels; +using FileTime.Core.Interactions; using FileTime.GuiApp.Configuration; using FileTime.GuiApp.IconProviders; using FileTime.GuiApp.Logging; @@ -35,7 +36,9 @@ public static class Startup .AddSingleton() .AddSingleton() .AddSingleton() - .AddSingleton(); + .AddSingleton() + .AddSingleton() + .AddSingleton(s => s.GetRequiredService()); } internal static IServiceCollection RegisterLogging(this IServiceCollection serviceCollection) diff --git a/src/GuiApp/Avalonia/FileTime.GuiApp/Models/InputElementWrapper.cs b/src/GuiApp/Avalonia/FileTime.GuiApp/Models/InputElementWrapper.cs deleted file mode 100644 index e346d7e..0000000 --- a/src/GuiApp/Avalonia/FileTime.GuiApp/Models/InputElementWrapper.cs +++ /dev/null @@ -1,19 +0,0 @@ -namespace FileTime.GuiApp.Models; - -public class InputElementWrapper -{ - /*public InputElement InputElement { get; } - - public string Value { get; set; } - - public object? Option { get; set; } - - public char? PasswordChar { get; set; } - - public InputElementWrapper(InputElement inputElement, string? defaultValue = null) - { - InputElement = inputElement; - Value = defaultValue ?? ""; - PasswordChar = inputElement.InputType == InputType.Password ? '*' : null; - }*/ -} \ No newline at end of file diff --git a/src/GuiApp/Avalonia/FileTime.GuiApp/Services/DefaultModeKeyInputHandler.cs b/src/GuiApp/Avalonia/FileTime.GuiApp/Services/DefaultModeKeyInputHandler.cs index 28bd785..0f6b015 100644 --- a/src/GuiApp/Avalonia/FileTime.GuiApp/Services/DefaultModeKeyInputHandler.cs +++ b/src/GuiApp/Avalonia/FileTime.GuiApp/Services/DefaultModeKeyInputHandler.cs @@ -54,8 +54,8 @@ public class DefaultModeKeyInputHandler : IDefaultModeKeyInputHandler var keyWithModifiers = new KeyConfig(key, shift: specialKeysStatus.IsShiftPressed, alt: specialKeysStatus.IsAltPressed, ctrl: specialKeysStatus.IsCtrlPressed); _appState.PreviousKeys.Add(keyWithModifiers); - var selectedCommandBinding = _keyboardConfigurationService.UniversalCommandBindings.Values.FirstOrDefault(c => c.Keys.AreKeysEqual(_appState.PreviousKeys)); - selectedCommandBinding ??= _keyboardConfigurationService.CommandBindings.Values.FirstOrDefault(c => c.Keys.AreKeysEqual(_appState.PreviousKeys)); + var selectedCommandBinding = _keyboardConfigurationService.UniversalCommandBindings.FirstOrDefault(c => c.Keys.AreKeysEqual(_appState.PreviousKeys)); + selectedCommandBinding ??= _keyboardConfigurationService.CommandBindings.FirstOrDefault(c => c.Keys.AreKeysEqual(_appState.PreviousKeys)); if (key == Key.Escape) { @@ -125,7 +125,7 @@ public class DefaultModeKeyInputHandler : IDefaultModeKeyInputHandler else { setHandled(true); - var possibleCommands = _keyboardConfigurationService.AllShortcut.Values.Where(c => c.Keys[0].AreEquals(keyWithModifiers)).ToList(); + var possibleCommands = _keyboardConfigurationService.AllShortcut.Where(c => c.Keys[0].AreEquals(keyWithModifiers)).ToList(); if (possibleCommands.Count == 0) { diff --git a/src/GuiApp/Avalonia/FileTime.GuiApp/Services/DialogService.cs b/src/GuiApp/Avalonia/FileTime.GuiApp/Services/DialogService.cs new file mode 100644 index 0000000..34e6163 --- /dev/null +++ b/src/GuiApp/Avalonia/FileTime.GuiApp/Services/DialogService.cs @@ -0,0 +1,59 @@ +using System.Reactive.Linq; +using DynamicData; +using FileTime.App.Core.Services; +using FileTime.Core.Interactions; +using FileTime.GuiApp.ViewModels; + +namespace FileTime.GuiApp.Services; + +public class DialogService : IDialogService +{ + private readonly IModalService _modalService; + + public IObservable ReadInput { get; } + + public DialogService(IModalService modalService) + { + _modalService = modalService; + ReadInput = modalService + .OpenModals + .ToCollection() + .Select(modals => + (ReadInputsViewModel?)modals.FirstOrDefault(m => m is ReadInputsViewModel) + ) + .Publish(null) + .RefCount(); + } + + public void ReadInputs(IEnumerable inputs, Action inputHandler, Action? cancelHandler = null) + { + var modalViewModel = new ReadInputsViewModel(HandleReadInputsSuccess, HandleReadInputsCancel) + { + Inputs = inputs.ToList(), + SuccessHandler = inputHandler, + CancelHandler = cancelHandler + }; + + _modalService.OpenModal(modalViewModel); + } + + private void HandleReadInputsSuccess(ReadInputsViewModel readInputsViewModel) + { + _modalService.CloseModal(readInputsViewModel); + readInputsViewModel.SuccessHandler.Invoke(); + } + + private void HandleReadInputsCancel(ReadInputsViewModel readInputsViewModel) + { + _modalService.CloseModal(readInputsViewModel); + readInputsViewModel.CancelHandler?.Invoke(); + } + + public Task ReadInputs(IEnumerable fields) + { + var taskCompletionSource = new TaskCompletionSource(); + ReadInputs(fields, () => taskCompletionSource.SetResult(true), () => taskCompletionSource.SetResult(false)); + + return taskCompletionSource.Task; + } +} \ No newline at end of file diff --git a/src/GuiApp/Avalonia/FileTime.GuiApp/Services/KeyboardConfigurationService.cs b/src/GuiApp/Avalonia/FileTime.GuiApp/Services/KeyboardConfigurationService.cs index 328a5dc..aa1b744 100644 --- a/src/GuiApp/Avalonia/FileTime.GuiApp/Services/KeyboardConfigurationService.cs +++ b/src/GuiApp/Avalonia/FileTime.GuiApp/Services/KeyboardConfigurationService.cs @@ -6,14 +6,12 @@ namespace FileTime.GuiApp.Services; public class KeyboardConfigurationService : IKeyboardConfigurationService { - public IReadOnlyDictionary CommandBindings { get; } - public IReadOnlyDictionary UniversalCommandBindings { get; } - public IReadOnlyDictionary AllShortcut { get; } + public IReadOnlyList CommandBindings { get; } + public IReadOnlyList UniversalCommandBindings { get; } + public IReadOnlyList AllShortcut { get; } public KeyboardConfigurationService(IOptions keyBindingConfiguration) { - var commandBindings = new Dictionary(); - var universalCommandBindings = new Dictionary(); IEnumerable keyBindings = keyBindingConfiguration.Value.KeyBindings; if (keyBindingConfiguration.Value.UseDefaultBindings) @@ -21,6 +19,8 @@ public class KeyboardConfigurationService : IKeyboardConfigurationService keyBindings = keyBindings.Concat(keyBindingConfiguration.Value.DefaultKeyBindings); } + var commandBindings = new List(); + var universalCommandBindings = new List(); foreach (var keyBinding in keyBindings) { if (string.IsNullOrWhiteSpace(keyBinding.Command)) @@ -34,17 +34,17 @@ public class KeyboardConfigurationService : IKeyboardConfigurationService if (IsUniversal(keyBinding)) { - universalCommandBindings.Add(keyBinding.Command, keyBinding); + universalCommandBindings.Add(keyBinding); } else { - commandBindings.Add(keyBinding.Command, keyBinding); + commandBindings.Add(keyBinding); } } - CommandBindings = new ReadOnlyDictionary(commandBindings); - UniversalCommandBindings = new ReadOnlyDictionary(universalCommandBindings); - AllShortcut = new ReadOnlyDictionary(new Dictionary(CommandBindings.Concat(UniversalCommandBindings))); + CommandBindings = commandBindings.AsReadOnly(); + UniversalCommandBindings = universalCommandBindings.AsReadOnly(); + AllShortcut = new List(UniversalCommandBindings.Concat(CommandBindings)).AsReadOnly(); } private static bool IsUniversal(CommandBindingConfiguration keyMapping) diff --git a/src/GuiApp/Avalonia/FileTime.GuiApp/Services/RapidTravelModeKeyInputHandler.cs b/src/GuiApp/Avalonia/FileTime.GuiApp/Services/RapidTravelModeKeyInputHandler.cs index b20aa7a..e1d0f10 100644 --- a/src/GuiApp/Avalonia/FileTime.GuiApp/Services/RapidTravelModeKeyInputHandler.cs +++ b/src/GuiApp/Avalonia/FileTime.GuiApp/Services/RapidTravelModeKeyInputHandler.cs @@ -80,7 +80,7 @@ public class RapidTravelModeKeyInputHandler : IRapidTravelModeKeyInputHandler else { var currentKeyAsList = new List() {new KeyConfig(key)}; - var selectedCommandBinding = _keyboardConfigurationService.UniversalCommandBindings.Values.FirstOrDefault(c => c.Keys.AreKeysEqual(currentKeyAsList)); + var selectedCommandBinding = _keyboardConfigurationService.UniversalCommandBindings.FirstOrDefault(c => c.Keys.AreKeysEqual(currentKeyAsList)); if (selectedCommandBinding != null) { setHandled(true); diff --git a/src/GuiApp/Avalonia/FileTime.GuiApp/ViewModels/MainWindowViewModel.cs b/src/GuiApp/Avalonia/FileTime.GuiApp/ViewModels/MainWindowViewModel.cs index 659770d..4023450 100644 --- a/src/GuiApp/Avalonia/FileTime.GuiApp/ViewModels/MainWindowViewModel.cs +++ b/src/GuiApp/Avalonia/FileTime.GuiApp/ViewModels/MainWindowViewModel.cs @@ -21,6 +21,7 @@ namespace FileTime.GuiApp.ViewModels; [Inject(typeof(IUserCommandHandlerService), PropertyAccessModifier = AccessModifier.Public)] [Inject(typeof(LifecycleService), PropertyName = "_lifecycleService")] [Inject(typeof(IItemPreviewService), PropertyAccessModifier = AccessModifier.Public)] +[Inject(typeof(IDialogService), PropertyAccessModifier = AccessModifier.Public)] public partial class MainWindowViewModel : IMainWindowViewModelBase { public bool Loading => false; diff --git a/src/GuiApp/Avalonia/FileTime.GuiApp/Views/MainWindow.axaml b/src/GuiApp/Avalonia/FileTime.GuiApp/Views/MainWindow.axaml index 8dde8b5..32873dd 100644 --- a/src/GuiApp/Avalonia/FileTime.GuiApp/Views/MainWindow.axaml +++ b/src/GuiApp/Avalonia/FileTime.GuiApp/Views/MainWindow.axaml @@ -9,6 +9,7 @@ xmlns:vm="using:FileTime.GuiApp.ViewModels" xmlns:config="using:FileTime.GuiApp.Configuration" xmlns:appCoreModels="using:FileTime.App.Core.Models" + xmlns:interactions="using:FileTime.Core.Interactions" Title="FileTime" d:DesignHeight="450" d:DesignWidth="800" @@ -416,9 +417,12 @@ - - - + + + - + + + + + + + + + + + + + + + + + + + + +