InputHandler, CreateContainer user command
This commit is contained in:
@@ -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;
|
||||||
|
}
|
||||||
@@ -11,6 +11,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="6.0.0" />
|
||||||
<PackageReference Include="morelinq" Version="3.3.2" />
|
<PackageReference Include="morelinq" Version="3.3.2" />
|
||||||
<PackageReference Include="MvvmGen" Version="1.1.5" />
|
<PackageReference Include="MvvmGen" Version="1.1.5" />
|
||||||
<PackageReference Include="System.Interactive.Async" Version="6.0.1" />
|
<PackageReference Include="System.Interactive.Async" Version="6.0.1" />
|
||||||
|
|||||||
@@ -4,7 +4,9 @@ using FileTime.App.Core.Models.Enums;
|
|||||||
using FileTime.App.Core.UserCommand;
|
using FileTime.App.Core.UserCommand;
|
||||||
using FileTime.App.Core.ViewModels;
|
using FileTime.App.Core.ViewModels;
|
||||||
using FileTime.Core.Command;
|
using FileTime.Core.Command;
|
||||||
|
using FileTime.Core.Interactions;
|
||||||
using FileTime.Core.Models;
|
using FileTime.Core.Models;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
using CopyCommand = FileTime.Core.Command.Copy.CopyCommand;
|
using CopyCommand = FileTime.Core.Command.Copy.CopyCommand;
|
||||||
|
|
||||||
namespace FileTime.App.Core.Services.UserCommandHandler;
|
namespace FileTime.App.Core.Services.UserCommandHandler;
|
||||||
@@ -15,15 +17,21 @@ public class ItemManipulationUserCommandHandlerService : UserCommandHandlerServi
|
|||||||
private IItemViewModel? _currentSelectedItem;
|
private IItemViewModel? _currentSelectedItem;
|
||||||
private readonly IUserCommandHandlerService _userCommandHandlerService;
|
private readonly IUserCommandHandlerService _userCommandHandlerService;
|
||||||
private readonly IClipboardService _clipboardService;
|
private readonly IClipboardService _clipboardService;
|
||||||
|
private readonly IInputInterface _inputInterface;
|
||||||
|
private readonly ILogger<ItemManipulationUserCommandHandlerService> _logger;
|
||||||
private readonly BindedCollection<IAbsolutePath>? _markedItems;
|
private readonly BindedCollection<IAbsolutePath>? _markedItems;
|
||||||
|
|
||||||
public ItemManipulationUserCommandHandlerService(
|
public ItemManipulationUserCommandHandlerService(
|
||||||
IAppState appState,
|
IAppState appState,
|
||||||
IUserCommandHandlerService userCommandHandlerService,
|
IUserCommandHandlerService userCommandHandlerService,
|
||||||
IClipboardService clipboardService) : base(appState)
|
IClipboardService clipboardService,
|
||||||
|
IInputInterface inputInterface,
|
||||||
|
ILogger<ItemManipulationUserCommandHandlerService> logger) : base(appState)
|
||||||
{
|
{
|
||||||
_userCommandHandlerService = userCommandHandlerService;
|
_userCommandHandlerService = userCommandHandlerService;
|
||||||
_clipboardService = clipboardService;
|
_clipboardService = clipboardService;
|
||||||
|
_inputInterface = inputInterface;
|
||||||
|
_logger = logger;
|
||||||
|
|
||||||
SaveSelectedTab(t => _selectedTab = t);
|
SaveSelectedTab(t => _selectedTab = t);
|
||||||
SaveCurrentSelectedItem(i => _currentSelectedItem = i);
|
SaveCurrentSelectedItem(i => _currentSelectedItem = i);
|
||||||
@@ -35,6 +43,7 @@ public class ItemManipulationUserCommandHandlerService : UserCommandHandlerServi
|
|||||||
new TypeUserCommandHandler<CopyCommand>(Copy),
|
new TypeUserCommandHandler<CopyCommand>(Copy),
|
||||||
new TypeUserCommandHandler<MarkCommand>(MarkItem),
|
new TypeUserCommandHandler<MarkCommand>(MarkItem),
|
||||||
new TypeUserCommandHandler<PasteCommand>(Paste),
|
new TypeUserCommandHandler<PasteCommand>(Paste),
|
||||||
|
new TypeUserCommandHandler<CreateContainer>(CreateContainer),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -99,4 +108,14 @@ public class ItemManipulationUserCommandHandlerService : UserCommandHandlerServi
|
|||||||
if (_clipboardService.CommandType is null) return Task.CompletedTask;
|
if (_clipboardService.CommandType is null) return Task.CompletedTask;
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task CreateContainer()
|
||||||
|
{
|
||||||
|
var containerNameInput = new TextInputElement("Container name");
|
||||||
|
|
||||||
|
await _inputInterface.ReadInputs(new List<IInputElement>() { containerNameInput });
|
||||||
|
|
||||||
|
//TODO: message on empty result
|
||||||
|
var newContainerName = containerNameInput.Value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -13,6 +13,7 @@ public class DefaultIdentifiableCommandHandlerRegister : IStartupHandler
|
|||||||
|
|
||||||
AddUserCommand(CloseTabCommand.Instance);
|
AddUserCommand(CloseTabCommand.Instance);
|
||||||
AddUserCommand(CopyCommand.Instance);
|
AddUserCommand(CopyCommand.Instance);
|
||||||
|
AddUserCommand(CreateContainer.Instance);
|
||||||
AddUserCommand(EnterRapidTravelCommand.Instance);
|
AddUserCommand(EnterRapidTravelCommand.Instance);
|
||||||
AddUserCommand(ExitRapidTravelCommand.Instance);
|
AddUserCommand(ExitRapidTravelCommand.Instance);
|
||||||
AddUserCommand(GoUpCommand.Instance);
|
AddUserCommand(GoUpCommand.Instance);
|
||||||
|
|||||||
@@ -13,6 +13,10 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="DynamicData" Version="7.7.14" />
|
<PackageReference Include="DynamicData" Version="7.7.14" />
|
||||||
|
<PackageReference Include="PropertyChanged.SourceGenerator" Version="1.0.3">
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
|
</PackageReference>
|
||||||
<PackageReference Include="System.Reactive" Version="5.0.0" />
|
<PackageReference Include="System.Reactive" Version="5.0.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
namespace FileTime.Core.Interactions;
|
||||||
|
|
||||||
|
public interface IInputElement
|
||||||
|
{
|
||||||
|
InputType Type { get; }
|
||||||
|
string Label { get; }
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
namespace FileTime.Core.Interactions;
|
||||||
|
|
||||||
|
public interface IInputInterface
|
||||||
|
{
|
||||||
|
Task<bool> ReadInputs(IEnumerable<IInputElement> fields);
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
namespace FileTime.Core.Interactions;
|
||||||
|
|
||||||
|
public interface IOptionElement
|
||||||
|
{
|
||||||
|
string Text { get; }
|
||||||
|
object? Value { get; }
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
namespace FileTime.Core.Interactions;
|
||||||
|
|
||||||
|
public interface IOptionsInputElement : IInputElement
|
||||||
|
{
|
||||||
|
object Value { get; set; }
|
||||||
|
IEnumerable<IOptionElement> Options { get; }
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
namespace FileTime.Core.Interactions;
|
||||||
|
|
||||||
|
public enum InputType
|
||||||
|
{
|
||||||
|
Options,
|
||||||
|
Password,
|
||||||
|
Text,
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
namespace FileTime.Core.Interactions;
|
||||||
|
|
||||||
|
public class OptionElement<T> : 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
using System.ComponentModel;
|
||||||
|
using PropertyChanged.SourceGenerator;
|
||||||
|
|
||||||
|
namespace FileTime.Core.Interactions;
|
||||||
|
|
||||||
|
public partial class OptionsInputElement<T> : InputElementBase, IOptionsInputElement, INotifyPropertyChanged
|
||||||
|
{
|
||||||
|
public IEnumerable<OptionElement<T>> Options { get; }
|
||||||
|
|
||||||
|
[Notify] private T? _value;
|
||||||
|
|
||||||
|
IEnumerable<IOptionElement> IOptionsInputElement.Options => Options;
|
||||||
|
object? IOptionsInputElement.Value
|
||||||
|
{
|
||||||
|
get => Value;
|
||||||
|
set => Value = (T?)value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public OptionsInputElement(string label, IEnumerable<OptionElement<T>> options) : base(label, InputType.Options)
|
||||||
|
{
|
||||||
|
Options = options;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -47,8 +47,8 @@ public static class MainConfiguration
|
|||||||
new CommandBindingConfiguration(CopyCommand.CommandName, new[] { Key.Y, Key.Y }),
|
new CommandBindingConfiguration(CopyCommand.CommandName, new[] { Key.Y, Key.Y }),
|
||||||
//new CommandBindingConfiguration(ConfigCommand.CopyHash, new[] { Key.C, Key.H }),
|
//new CommandBindingConfiguration(ConfigCommand.CopyHash, new[] { Key.C, Key.H }),
|
||||||
//new CommandBindingConfiguration(ConfigCommand.CopyPath, new[] { Key.C, Key.P }),
|
//new CommandBindingConfiguration(ConfigCommand.CopyPath, new[] { Key.C, Key.P }),
|
||||||
//new CommandBindingConfiguration(ConfigCommand.CreateContainer, Key.F7),
|
new CommandBindingConfiguration(CreateContainer.CommandName, Key.F7),
|
||||||
//new CommandBindingConfiguration(ConfigCommand.CreateContainer, new[] { Key.C, Key.C }),
|
new CommandBindingConfiguration(CreateContainer.CommandName, new[] { Key.C, Key.C }),
|
||||||
//new CommandBindingConfiguration(ConfigCommand.CreateElement, new[] { Key.C, Key.E }),
|
//new CommandBindingConfiguration(ConfigCommand.CreateElement, new[] { Key.C, Key.E }),
|
||||||
//new CommandBindingConfiguration(ConfigCommand.Cut, new[] { Key.D, Key.D }),
|
//new CommandBindingConfiguration(ConfigCommand.Cut, new[] { Key.D, Key.D }),
|
||||||
//new CommandBindingConfiguration(ConfigCommand.Edit, new KeyConfig(Key.F4)),
|
//new CommandBindingConfiguration(ConfigCommand.Edit, new KeyConfig(Key.F4)),
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
using FileTime.Core.Interactions;
|
||||||
|
using FileTime.GuiApp.ViewModels;
|
||||||
|
|
||||||
|
namespace FileTime.GuiApp.Services;
|
||||||
|
|
||||||
|
public interface IDialogService : IInputInterface
|
||||||
|
{
|
||||||
|
IObservable<ReadInputsViewModel?> ReadInput { get; }
|
||||||
|
void ReadInputs(IEnumerable<IInputElement> inputs, Action inputHandler, Action? cancelHandler = null);
|
||||||
|
}
|
||||||
@@ -4,7 +4,7 @@ namespace FileTime.GuiApp.Services;
|
|||||||
|
|
||||||
public interface IKeyboardConfigurationService
|
public interface IKeyboardConfigurationService
|
||||||
{
|
{
|
||||||
IReadOnlyDictionary<string, CommandBindingConfiguration> CommandBindings { get; }
|
IReadOnlyList<CommandBindingConfiguration> CommandBindings { get; }
|
||||||
IReadOnlyDictionary<string, CommandBindingConfiguration> UniversalCommandBindings { get; }
|
IReadOnlyList<CommandBindingConfiguration> UniversalCommandBindings { get; }
|
||||||
IReadOnlyDictionary<string, CommandBindingConfiguration> AllShortcut { get; }
|
IReadOnlyList<CommandBindingConfiguration> AllShortcut { get; }
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
using FileTime.App.Core.ViewModels;
|
||||||
|
using FileTime.Core.Interactions;
|
||||||
|
using MvvmGen;
|
||||||
|
|
||||||
|
namespace FileTime.GuiApp.ViewModels;
|
||||||
|
|
||||||
|
[ViewModel]
|
||||||
|
[Inject(typeof(Action<ReadInputsViewModel>), "_cancel")]
|
||||||
|
[Inject(typeof(Action<ReadInputsViewModel>), "_process")]
|
||||||
|
public partial class ReadInputsViewModel : IModalViewModelBase
|
||||||
|
{
|
||||||
|
public string Name => "ReadInputs";
|
||||||
|
public List<IInputElement> 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,6 +2,7 @@ using System;
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
using FileTime.App.Core.Services;
|
using FileTime.App.Core.Services;
|
||||||
using FileTime.App.Core.ViewModels;
|
using FileTime.App.Core.ViewModels;
|
||||||
|
using FileTime.Core.Interactions;
|
||||||
using FileTime.GuiApp.Configuration;
|
using FileTime.GuiApp.Configuration;
|
||||||
using FileTime.GuiApp.IconProviders;
|
using FileTime.GuiApp.IconProviders;
|
||||||
using FileTime.GuiApp.Logging;
|
using FileTime.GuiApp.Logging;
|
||||||
@@ -35,7 +36,9 @@ public static class Startup
|
|||||||
.AddSingleton<IStartupHandler, RootDriveInfoService>()
|
.AddSingleton<IStartupHandler, RootDriveInfoService>()
|
||||||
.AddSingleton<LifecycleService>()
|
.AddSingleton<LifecycleService>()
|
||||||
.AddSingleton<IIconProvider, MaterialIconProvider>()
|
.AddSingleton<IIconProvider, MaterialIconProvider>()
|
||||||
.AddSingleton<IModalService, ModalService>();
|
.AddSingleton<IModalService, ModalService>()
|
||||||
|
.AddSingleton<IDialogService, DialogService>()
|
||||||
|
.AddSingleton<IInputInterface>(s => s.GetRequiredService<IDialogService>());
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static IServiceCollection RegisterLogging(this IServiceCollection serviceCollection)
|
internal static IServiceCollection RegisterLogging(this IServiceCollection serviceCollection)
|
||||||
|
|||||||
@@ -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;
|
|
||||||
}*/
|
|
||||||
}
|
|
||||||
@@ -54,8 +54,8 @@ public class DefaultModeKeyInputHandler : IDefaultModeKeyInputHandler
|
|||||||
var keyWithModifiers = new KeyConfig(key, shift: specialKeysStatus.IsShiftPressed, alt: specialKeysStatus.IsAltPressed, ctrl: specialKeysStatus.IsCtrlPressed);
|
var keyWithModifiers = new KeyConfig(key, shift: specialKeysStatus.IsShiftPressed, alt: specialKeysStatus.IsAltPressed, ctrl: specialKeysStatus.IsCtrlPressed);
|
||||||
_appState.PreviousKeys.Add(keyWithModifiers);
|
_appState.PreviousKeys.Add(keyWithModifiers);
|
||||||
|
|
||||||
var selectedCommandBinding = _keyboardConfigurationService.UniversalCommandBindings.Values.FirstOrDefault(c => c.Keys.AreKeysEqual(_appState.PreviousKeys));
|
var selectedCommandBinding = _keyboardConfigurationService.UniversalCommandBindings.FirstOrDefault(c => c.Keys.AreKeysEqual(_appState.PreviousKeys));
|
||||||
selectedCommandBinding ??= _keyboardConfigurationService.CommandBindings.Values.FirstOrDefault(c => c.Keys.AreKeysEqual(_appState.PreviousKeys));
|
selectedCommandBinding ??= _keyboardConfigurationService.CommandBindings.FirstOrDefault(c => c.Keys.AreKeysEqual(_appState.PreviousKeys));
|
||||||
|
|
||||||
if (key == Key.Escape)
|
if (key == Key.Escape)
|
||||||
{
|
{
|
||||||
@@ -125,7 +125,7 @@ public class DefaultModeKeyInputHandler : IDefaultModeKeyInputHandler
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
setHandled(true);
|
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)
|
if (possibleCommands.Count == 0)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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<ReadInputsViewModel?> 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<IInputElement> 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<bool> ReadInputs(IEnumerable<IInputElement> fields)
|
||||||
|
{
|
||||||
|
var taskCompletionSource = new TaskCompletionSource<bool>();
|
||||||
|
ReadInputs(fields, () => taskCompletionSource.SetResult(true), () => taskCompletionSource.SetResult(false));
|
||||||
|
|
||||||
|
return taskCompletionSource.Task;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,14 +6,12 @@ namespace FileTime.GuiApp.Services;
|
|||||||
|
|
||||||
public class KeyboardConfigurationService : IKeyboardConfigurationService
|
public class KeyboardConfigurationService : IKeyboardConfigurationService
|
||||||
{
|
{
|
||||||
public IReadOnlyDictionary<string, CommandBindingConfiguration> CommandBindings { get; }
|
public IReadOnlyList<CommandBindingConfiguration> CommandBindings { get; }
|
||||||
public IReadOnlyDictionary<string, CommandBindingConfiguration> UniversalCommandBindings { get; }
|
public IReadOnlyList<CommandBindingConfiguration> UniversalCommandBindings { get; }
|
||||||
public IReadOnlyDictionary<string, CommandBindingConfiguration> AllShortcut { get; }
|
public IReadOnlyList<CommandBindingConfiguration> AllShortcut { get; }
|
||||||
|
|
||||||
public KeyboardConfigurationService(IOptions<KeyBindingConfiguration> keyBindingConfiguration)
|
public KeyboardConfigurationService(IOptions<KeyBindingConfiguration> keyBindingConfiguration)
|
||||||
{
|
{
|
||||||
var commandBindings = new Dictionary<string, CommandBindingConfiguration>();
|
|
||||||
var universalCommandBindings = new Dictionary<string, CommandBindingConfiguration>();
|
|
||||||
IEnumerable<CommandBindingConfiguration> keyBindings = keyBindingConfiguration.Value.KeyBindings;
|
IEnumerable<CommandBindingConfiguration> keyBindings = keyBindingConfiguration.Value.KeyBindings;
|
||||||
|
|
||||||
if (keyBindingConfiguration.Value.UseDefaultBindings)
|
if (keyBindingConfiguration.Value.UseDefaultBindings)
|
||||||
@@ -21,6 +19,8 @@ public class KeyboardConfigurationService : IKeyboardConfigurationService
|
|||||||
keyBindings = keyBindings.Concat(keyBindingConfiguration.Value.DefaultKeyBindings);
|
keyBindings = keyBindings.Concat(keyBindingConfiguration.Value.DefaultKeyBindings);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var commandBindings = new List<CommandBindingConfiguration>();
|
||||||
|
var universalCommandBindings = new List<CommandBindingConfiguration>();
|
||||||
foreach (var keyBinding in keyBindings)
|
foreach (var keyBinding in keyBindings)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(keyBinding.Command))
|
if (string.IsNullOrWhiteSpace(keyBinding.Command))
|
||||||
@@ -34,17 +34,17 @@ public class KeyboardConfigurationService : IKeyboardConfigurationService
|
|||||||
|
|
||||||
if (IsUniversal(keyBinding))
|
if (IsUniversal(keyBinding))
|
||||||
{
|
{
|
||||||
universalCommandBindings.Add(keyBinding.Command, keyBinding);
|
universalCommandBindings.Add(keyBinding);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
commandBindings.Add(keyBinding.Command, keyBinding);
|
commandBindings.Add(keyBinding);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CommandBindings = new ReadOnlyDictionary<string, CommandBindingConfiguration>(commandBindings);
|
CommandBindings = commandBindings.AsReadOnly();
|
||||||
UniversalCommandBindings = new ReadOnlyDictionary<string, CommandBindingConfiguration>(universalCommandBindings);
|
UniversalCommandBindings = universalCommandBindings.AsReadOnly();
|
||||||
AllShortcut = new ReadOnlyDictionary<string, CommandBindingConfiguration>(new Dictionary<string, CommandBindingConfiguration>(CommandBindings.Concat(UniversalCommandBindings)));
|
AllShortcut = new List<CommandBindingConfiguration>(UniversalCommandBindings.Concat(CommandBindings)).AsReadOnly();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool IsUniversal(CommandBindingConfiguration keyMapping)
|
private static bool IsUniversal(CommandBindingConfiguration keyMapping)
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ public class RapidTravelModeKeyInputHandler : IRapidTravelModeKeyInputHandler
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
var currentKeyAsList = new List<KeyConfig>() {new KeyConfig(key)};
|
var currentKeyAsList = new List<KeyConfig>() {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)
|
if (selectedCommandBinding != null)
|
||||||
{
|
{
|
||||||
setHandled(true);
|
setHandled(true);
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ namespace FileTime.GuiApp.ViewModels;
|
|||||||
[Inject(typeof(IUserCommandHandlerService), PropertyAccessModifier = AccessModifier.Public)]
|
[Inject(typeof(IUserCommandHandlerService), PropertyAccessModifier = AccessModifier.Public)]
|
||||||
[Inject(typeof(LifecycleService), PropertyName = "_lifecycleService")]
|
[Inject(typeof(LifecycleService), PropertyName = "_lifecycleService")]
|
||||||
[Inject(typeof(IItemPreviewService), PropertyAccessModifier = AccessModifier.Public)]
|
[Inject(typeof(IItemPreviewService), PropertyAccessModifier = AccessModifier.Public)]
|
||||||
|
[Inject(typeof(IDialogService), PropertyAccessModifier = AccessModifier.Public)]
|
||||||
public partial class MainWindowViewModel : IMainWindowViewModelBase
|
public partial class MainWindowViewModel : IMainWindowViewModelBase
|
||||||
{
|
{
|
||||||
public bool Loading => false;
|
public bool Loading => false;
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
xmlns:vm="using:FileTime.GuiApp.ViewModels"
|
xmlns:vm="using:FileTime.GuiApp.ViewModels"
|
||||||
xmlns:config="using:FileTime.GuiApp.Configuration"
|
xmlns:config="using:FileTime.GuiApp.Configuration"
|
||||||
xmlns:appCoreModels="using:FileTime.App.Core.Models"
|
xmlns:appCoreModels="using:FileTime.App.Core.Models"
|
||||||
|
xmlns:interactions="using:FileTime.Core.Interactions"
|
||||||
Title="FileTime"
|
Title="FileTime"
|
||||||
d:DesignHeight="450"
|
d:DesignHeight="450"
|
||||||
d:DesignWidth="800"
|
d:DesignWidth="800"
|
||||||
@@ -416,9 +417,12 @@
|
|||||||
</Grid>
|
</Grid>
|
||||||
<Grid
|
<Grid
|
||||||
IsVisible="{Binding ItemPreviewService.ItemPreview^,Converter={x:Static ObjectConverters.IsNotNull}}">
|
IsVisible="{Binding ItemPreviewService.ItemPreview^,Converter={x:Static ObjectConverters.IsNotNull}}">
|
||||||
<TextBlock HorizontalAlignment="Center" Text="Don't know how to preview this item." IsVisible="{Binding ItemPreviewService.ItemPreview^.Mode, Converter={StaticResource EqualityConverter}, ConverterParameter={x:Static appCoreModels:ItemPreviewMode.Unknown}}"/>
|
<TextBlock HorizontalAlignment="Center" Text="Don't know how to preview this item."
|
||||||
<TextBlock HorizontalAlignment="Center" Text="Empty" IsVisible="{Binding ItemPreviewService.ItemPreview^.Mode, Converter={StaticResource EqualityConverter}, ConverterParameter={x:Static appCoreModels:ItemPreviewMode.Empty}}"/>
|
IsVisible="{Binding ItemPreviewService.ItemPreview^.Mode, Converter={StaticResource EqualityConverter}, ConverterParameter={x:Static appCoreModels:ItemPreviewMode.Unknown}}" />
|
||||||
<ScrollViewer IsVisible="{Binding ItemPreviewService.ItemPreview^.Mode, Converter={StaticResource EqualityConverter}, ConverterParameter={x:Static appCoreModels:ItemPreviewMode.Text}}">
|
<TextBlock HorizontalAlignment="Center" Text="Empty"
|
||||||
|
IsVisible="{Binding ItemPreviewService.ItemPreview^.Mode, Converter={StaticResource EqualityConverter}, ConverterParameter={x:Static appCoreModels:ItemPreviewMode.Empty}}" />
|
||||||
|
<ScrollViewer
|
||||||
|
IsVisible="{Binding ItemPreviewService.ItemPreview^.Mode, Converter={StaticResource EqualityConverter}, ConverterParameter={x:Static appCoreModels:ItemPreviewMode.Text}}">
|
||||||
<TextBox
|
<TextBox
|
||||||
IsReadOnly="True"
|
IsReadOnly="True"
|
||||||
x:CompileBindings="False"
|
x:CompileBindings="False"
|
||||||
@@ -495,7 +499,72 @@
|
|||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
<!-- Borders -->
|
|
||||||
|
<Border
|
||||||
|
Background="{DynamicResource BarelyTransparentBackgroundColor}"
|
||||||
|
HorizontalAlignment="Stretch"
|
||||||
|
VerticalAlignment="Stretch"
|
||||||
|
IsVisible="{Binding DialogService.ReadInput^, Converter={x:Static ObjectConverters.IsNotNull}}">
|
||||||
|
<Border
|
||||||
|
Background="{DynamicResource ContainerBackgroundBrush}"
|
||||||
|
Padding="20"
|
||||||
|
HorizontalAlignment="Center"
|
||||||
|
VerticalAlignment="Center">
|
||||||
|
<Grid RowDefinitions="Auto,Auto">
|
||||||
|
|
||||||
|
<ItemsControl
|
||||||
|
x:Name="InputList"
|
||||||
|
Items="{Binding DialogService.ReadInput^.Inputs}">
|
||||||
|
<ItemsControl.ItemTemplate>
|
||||||
|
<DataTemplate>
|
||||||
|
<Grid MinWidth="500" ColumnDefinitions="250,*" Margin="10,5" x:Name="ItemRoot">
|
||||||
|
<TextBlock
|
||||||
|
HorizontalAlignment="Left"
|
||||||
|
VerticalAlignment="Top"
|
||||||
|
Text="{Binding Label}" />
|
||||||
|
<Grid Grid.Column="1">
|
||||||
|
<TextBox
|
||||||
|
x:DataType="interactions:TextInputElement"
|
||||||
|
IsVisible="{Binding Type, Converter={StaticResource EqualityConverter}, ConverterParameter={x:Static interactions:InputType.Text}}"
|
||||||
|
VerticalAlignment="Top"
|
||||||
|
Text="{Binding Value, Mode=TwoWay}" />
|
||||||
|
<TextBox
|
||||||
|
x:DataType="interactions:PasswordInputElement"
|
||||||
|
IsVisible="{Binding Type, Converter={StaticResource EqualityConverter}, ConverterParameter={x:Static interactions:InputType.Password}}"
|
||||||
|
PasswordChar="{Binding PasswordChar}"
|
||||||
|
VerticalAlignment="Top"
|
||||||
|
Text="{Binding Value, Mode=TwoWay}" />
|
||||||
|
<ListBox
|
||||||
|
x:DataType="interactions:IOptionsInputElement"
|
||||||
|
Classes="RadioButtonListBox"
|
||||||
|
IsVisible="{Binding Type, Converter={StaticResource EqualityConverter}, ConverterParameter={x:Static interactions:InputType.Options}}"
|
||||||
|
Items="{Binding Options}"
|
||||||
|
SelectedItem="{Binding Value}" />
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
</DataTemplate>
|
||||||
|
</ItemsControl.ItemTemplate>
|
||||||
|
</ItemsControl>
|
||||||
|
<StackPanel
|
||||||
|
DataContext="{Binding DialogService.ReadInput^}"
|
||||||
|
Grid.Row="1"
|
||||||
|
Orientation="Horizontal"
|
||||||
|
Margin="0,10,0,0">
|
||||||
|
<Button
|
||||||
|
HorizontalContentAlignment="Center"
|
||||||
|
Width="80"
|
||||||
|
Command="{Binding ProcessCommand}"
|
||||||
|
Content="Ok" />
|
||||||
|
<Button
|
||||||
|
HorizontalContentAlignment="Center"
|
||||||
|
Width="80"
|
||||||
|
Margin="10,0,0,0"
|
||||||
|
Command="{Binding CancelCommand}"
|
||||||
|
Content="Cancel" />
|
||||||
|
</StackPanel>
|
||||||
|
</Grid>
|
||||||
|
</Border>
|
||||||
|
</Border>
|
||||||
|
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ namespace FileTime.GuiApp.Views;
|
|||||||
public partial class MainWindow : Window
|
public partial class MainWindow : Window
|
||||||
{
|
{
|
||||||
private readonly ILogger<MainWindow>? _logger;
|
private readonly ILogger<MainWindow>? _logger;
|
||||||
private InputElementWrapper? _inputElementWrapper;
|
|
||||||
|
|
||||||
public MainWindowViewModel? ViewModel
|
public MainWindowViewModel? ViewModel
|
||||||
{
|
{
|
||||||
@@ -38,17 +37,15 @@ public partial class MainWindow : Window
|
|||||||
{
|
{
|
||||||
if (DataContext is not MainWindowViewModel)
|
if (DataContext is not MainWindowViewModel)
|
||||||
{
|
{
|
||||||
_logger?.LogInformation($"{nameof(MainWindow)} opened, starting {nameof(MainWindowViewModel)} initialization...");
|
_logger?.LogInformation(
|
||||||
|
$"{nameof(MainWindow)} opened, starting {nameof(MainWindowViewModel)} initialization...");
|
||||||
ViewModel = DI.ServiceProvider.GetRequiredService<MainWindowViewModel>();
|
ViewModel = DI.ServiceProvider.GetRequiredService<MainWindowViewModel>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnKeyDown(object sender, KeyEventArgs e)
|
private void OnKeyDown(object sender, KeyEventArgs e)
|
||||||
{
|
{
|
||||||
if (_inputElementWrapper == null)
|
ViewModel?.ProcessKeyDown(e.Key, e.KeyModifiers, h => e.Handled = h);
|
||||||
{
|
|
||||||
ViewModel?.ProcessKeyDown(e.Key, e.KeyModifiers, h => e.Handled = h);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void HeaderPointerPressed(object sender, PointerPressedEventArgs e)
|
private void HeaderPointerPressed(object sender, PointerPressedEventArgs e)
|
||||||
@@ -78,7 +75,7 @@ public partial class MainWindow : Window
|
|||||||
&& sender is StyledElement control)
|
&& sender is StyledElement control)
|
||||||
{
|
{
|
||||||
IAbsolutePath? path = null;
|
IAbsolutePath? path = null;
|
||||||
if (control.DataContext is IHaveAbsolutePath {Path: { }} haveAbsolutePath)
|
if (control.DataContext is IHaveAbsolutePath { Path: { } } haveAbsolutePath)
|
||||||
{
|
{
|
||||||
path = haveAbsolutePath.Path;
|
path = haveAbsolutePath.Path;
|
||||||
}
|
}
|
||||||
@@ -102,7 +99,8 @@ public partial class MainWindow : Window
|
|||||||
|
|
||||||
var resolvedItem = await path.ResolveAsync();
|
var resolvedItem = await path.ResolveAsync();
|
||||||
if (resolvedItem is not IContainer resolvedContainer) return;
|
if (resolvedItem is not IContainer resolvedContainer) return;
|
||||||
await ViewModel.UserCommandHandlerService.HandleCommandAsync(new OpenContainerCommand(new AbsolutePath(resolvedContainer)));
|
await ViewModel.UserCommandHandlerService.HandleCommandAsync(
|
||||||
|
new OpenContainerCommand(new AbsolutePath(resolvedContainer)));
|
||||||
e.Handled = true;
|
e.Handled = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user