Console DialogService

This commit is contained in:
2023-08-14 11:50:59 +02:00
parent 6797c26bf9
commit 1f4b938358
41 changed files with 807 additions and 269 deletions

View File

@@ -0,0 +1,11 @@
using FileTime.App.Core.ViewModels;
using FileTime.Core.Interactions;
using ObservableComputations;
namespace FileTime.App.Core.Services;
public interface IDialogServiceBase : IUserCommunicationService
{
ScalarComputing<ReadInputsViewModel?> ReadInput { get; }
ScalarComputing<MessageBoxViewModel?> LastMessageBox { get; }
}

View File

@@ -1,11 +1,11 @@
using DynamicData;
using System.Collections.ObjectModel;
using FileTime.App.Core.ViewModels;
namespace FileTime.App.Core.Services;
public interface IModalService
{
IObservable<IChangeSet<IModalViewModel>> OpenModals { get; }
ReadOnlyObservableCollection<IModalViewModel> OpenModals { get; }
void OpenModal(IModalViewModel modalToOpen);
void CloseModal(IModalViewModel modalToClose);

View File

@@ -0,0 +1,31 @@
using FileTime.Core.Interactions;
namespace FileTime.App.Core.ViewModels;
public class MessageBoxViewModel : IModalViewModel
{
private readonly Action<MessageBoxViewModel, MessageBoxResult> _handler;
public string Text { get; }
public bool ShowCancel { get; }
public string OkText { get; }
public string CancelText { get; }
public string Name => "MessageBoxViewModel";
public MessageBoxViewModel(
string text,
Action<MessageBoxViewModel, MessageBoxResult> handler,
bool showCancel = true,
string? okText = null,
string? cancelText = null)
{
_handler = handler;
Text = text;
ShowCancel = showCancel;
OkText = okText ?? "Yes";
CancelText = cancelText ?? "No";
}
public void Ok() => _handler.Invoke(this, MessageBoxResult.Ok);
public void Cancel() => _handler.Invoke(this, MessageBoxResult.Cancel);
}

View File

@@ -0,0 +1,31 @@
using System.Collections.ObjectModel;
using FileTime.Core.Interactions;
namespace FileTime.App.Core.ViewModels;
public class ReadInputsViewModel : IModalViewModel
{
public string Name => "ReadInputs";
public required List<IInputElement> Inputs { get; init; }
public required Action<ReadInputsViewModel> SuccessHandler { get; init; }
public required Action<ReadInputsViewModel>? CancelHandler { get; init; }
public ObservableCollection<IPreviewElement> Previews { get; } = new();
public ReadInputsViewModel()
{
}
public ReadInputsViewModel(
List<IInputElement> inputs,
Action<ReadInputsViewModel> successHandler,
Action<ReadInputsViewModel>? cancelHandler = null)
{
Inputs = inputs;
SuccessHandler = successHandler;
CancelHandler = cancelHandler;
}
public void Process() => SuccessHandler.Invoke(this);
public void Cancel() => CancelHandler?.Invoke(this);
}

View File

@@ -1,3 +1,4 @@
using System.Collections.ObjectModel;
using DeclarativeProperty;
using FileTime.App.Core.Configuration;
using FileTime.App.Core.Extensions;
@@ -23,7 +24,7 @@ public class DefaultModeKeyInputHandler : IDefaultModeKeyInputHandler
private readonly IUserCommandHandlerService _userCommandHandlerService;
private readonly IIdentifiableUserCommandService _identifiableUserCommandService;
private readonly IPossibleCommandsService _possibleCommandsService;
private readonly BindedCollection<IModalViewModel> _openModals;
private readonly ReadOnlyObservableCollection<IModalViewModel> _openModals;
public DefaultModeKeyInputHandler(
IAppState appState,
@@ -46,7 +47,7 @@ public class DefaultModeKeyInputHandler : IDefaultModeKeyInputHandler
.Map(t => t?.CurrentLocation)
.Switch();
_openModals = modalService.OpenModals.ToBindedCollection();
_openModals = modalService.OpenModals;
_keysToSkip.Add(new[] {new KeyConfig(Keys.Up)});
_keysToSkip.Add(new[] {new KeyConfig(Keys.Down)});
@@ -75,9 +76,9 @@ public class DefaultModeKeyInputHandler : IDefaultModeKeyInputHandler
{
var doGeneralReset = _appState.PreviousKeys.Count > 1;
if ((_openModals.Collection?.Count ?? 0) > 0)
if (_openModals.Count > 0)
{
_modalService.CloseModal(_openModals.Collection!.Last());
_modalService.CloseModal(_openModals.Last());
}
else if (_currentLocation.Value?.GetExtension<EscHandlerContainerExtension>() is { } escHandler)
{

View File

@@ -0,0 +1,130 @@
using DynamicData;
using FileTime.App.Core.ViewModels;
using FileTime.Core.Interactions;
using ObservableComputations;
namespace FileTime.App.Core.Services;
public abstract class DialogServiceBase : IDialogServiceBase
{
private readonly IModalService _modalService;
private OcConsumer _readInputConsumer = new();
private OcConsumer _lastMessageBoxConsumer = new();
public ScalarComputing<ReadInputsViewModel?> ReadInput { get; }
public ScalarComputing<MessageBoxViewModel?> LastMessageBox { get; }
protected DialogServiceBase(IModalService modalService)
{
_modalService = modalService;
ReadInput = modalService
.OpenModals
.OfTypeComputing<ReadInputsViewModel>()
.FirstComputing()
.For(_readInputConsumer);
LastMessageBox =
modalService
.OpenModals
.OfTypeComputing<MessageBoxViewModel>()
.LastComputing()
.For(_lastMessageBoxConsumer);
}
private void ReadInputs(
IEnumerable<IInputElement> inputs,
Action inputHandler,
Action? cancelHandler = null,
IEnumerable<IPreviewElement>? previews = null)
{
var modalViewModel = new ReadInputsViewModel
{
Inputs = inputs.ToList(),
SuccessHandler = HandleReadInputsSuccess,
CancelHandler = HandleReadInputsCancel
};
if (previews is not null)
{
modalViewModel.Previews.AddRange(previews);
}
_modalService.OpenModal(modalViewModel);
void HandleReadInputsSuccess(ReadInputsViewModel readInputsViewModel)
{
_modalService.CloseModal(readInputsViewModel);
inputHandler();
}
void HandleReadInputsCancel(ReadInputsViewModel readInputsViewModel)
{
_modalService.CloseModal(readInputsViewModel);
cancelHandler?.Invoke();
}
}
public Task<bool> ReadInputs(IEnumerable<IInputElement> fields, IEnumerable<IPreviewElement>? previews = null)
{
var taskCompletionSource = new TaskCompletionSource<bool>();
ReadInputs(
fields,
() => taskCompletionSource.SetResult(true),
() => taskCompletionSource.SetResult(false),
previews
);
return taskCompletionSource.Task;
}
public Task<bool> ReadInputs(params IInputElement[] fields)
{
var taskCompletionSource = new TaskCompletionSource<bool>();
ReadInputs(
fields,
() => taskCompletionSource.SetResult(true),
() => taskCompletionSource.SetResult(false)
);
return taskCompletionSource.Task;
}
public Task<bool> ReadInputs(IInputElement field, IEnumerable<IPreviewElement>? previews = null)
{
var taskCompletionSource = new TaskCompletionSource<bool>();
ReadInputs(
new[] {field},
() => taskCompletionSource.SetResult(true),
() => taskCompletionSource.SetResult(false),
previews
);
return taskCompletionSource.Task;
}
public abstract void ShowToastMessage(string text);
public Task<MessageBoxResult> ShowMessageBox(
string text,
bool showCancel = true,
string? okText = null,
string? cancelText = null)
{
var taskCompletionSource = new TaskCompletionSource<MessageBoxResult>();
_modalService.OpenModal(
new MessageBoxViewModel(
text,
(vm, result) =>
{
_modalService.CloseModal(vm);
taskCompletionSource.SetResult(result);
},
showCancel,
okText,
cancelText
)
);
return taskCompletionSource.Task;
}
}

View File

@@ -1,3 +1,4 @@
using System.Collections.ObjectModel;
using DynamicData;
using FileTime.App.Core.ViewModels;
using Microsoft.Extensions.DependencyInjection;
@@ -7,14 +8,14 @@ namespace FileTime.App.Core.Services;
public class ModalService : IModalService
{
private readonly IServiceProvider _serviceProvider;
private readonly SourceList<IModalViewModel> _openModals = new();
public IObservable<IChangeSet<IModalViewModel>> OpenModals { get; }
private readonly ObservableCollection<IModalViewModel> _openModals = new();
public ReadOnlyObservableCollection<IModalViewModel> OpenModals { get; }
public event EventHandler? AllModalClosed;
public ModalService(IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
OpenModals = _openModals.Connect().StartWithEmpty();
OpenModals = new ReadOnlyObservableCollection<IModalViewModel>(_openModals);
}
public void OpenModal(IModalViewModel modalToOpen) => _openModals.Add(modalToOpen);

View File

@@ -21,7 +21,6 @@ public class RapidTravelModeKeyInputHandler : IRapidTravelModeKeyInputHandler
private readonly IUserCommandHandlerService _userCommandHandlerService;
private readonly ILogger<RapidTravelModeKeyInputHandler> _logger;
private readonly IIdentifiableUserCommandService _identifiableUserCommandService;
private readonly BindedCollection<IModalViewModel> _openModals;
private ITabViewModel? _selectedTab;
public RapidTravelModeKeyInputHandler(
@@ -41,8 +40,6 @@ public class RapidTravelModeKeyInputHandler : IRapidTravelModeKeyInputHandler
_appState.SelectedTab.Subscribe(t => _selectedTab = t);
_openModals = modalService.OpenModals.ToBindedCollection();
_appState.RapidTravelTextDebounced.Subscribe((v, _) =>
{
if (_selectedTab?.Tab is not { } tab) return Task.CompletedTask;
@@ -62,9 +59,9 @@ public class RapidTravelModeKeyInputHandler : IRapidTravelModeKeyInputHandler
if (args.Key == Keys.Escape)
{
args.Handled = true;
if ((_openModals.Collection?.Count ?? 0) > 0)
if (_modalService.OpenModals.Count > 0)
{
_modalService.CloseModal(_openModals.Collection!.Last());
_modalService.CloseModal(_modalService.OpenModals.Last());
}
else
{