Console DialogService
This commit is contained in:
@@ -21,6 +21,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\AppCommon\FileTime.App.Core.Abstraction\FileTime.App.Core.Abstraction.csproj" />
|
||||
<ProjectReference Include="..\..\..\AppCommon\FileTime.App.Core\FileTime.App.Core.csproj" />
|
||||
<ProjectReference Include="..\..\..\Core\FileTime.Core.Models\FileTime.Core.Models.csproj" />
|
||||
<ProjectReference Include="..\..\..\Providers\FileTime.Providers.LocalAdmin.Abstractions\FileTime.Providers.LocalAdmin.Abstractions.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
using FileTime.Core.Interactions;
|
||||
using FileTime.GuiApp.App.ViewModels;
|
||||
using FileTime.App.Core.Services;
|
||||
|
||||
namespace FileTime.GuiApp.App.Services;
|
||||
|
||||
public interface IDialogService : IUserCommunicationService
|
||||
public interface IDialogService : IDialogServiceBase
|
||||
{
|
||||
IObservable<ReadInputsViewModel?> ReadInput { get; }
|
||||
IObservable<MessageBoxViewModel?> LastMessageBox { get; }
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
using FileTime.App.Core.ViewModels;
|
||||
using FileTime.Core.Interactions;
|
||||
using MvvmGen;
|
||||
|
||||
namespace FileTime.GuiApp.App.ViewModels;
|
||||
|
||||
[ViewModel]
|
||||
public partial 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) : this()
|
||||
{
|
||||
_handler = handler;
|
||||
Text = text;
|
||||
ShowCancel = showCancel;
|
||||
OkText = okText ?? "Yes";
|
||||
CancelText = cancelText ?? "No";
|
||||
}
|
||||
|
||||
[Command]
|
||||
public void Ok() => _handler.Invoke(this, MessageBoxResult.Ok);
|
||||
|
||||
[Command]
|
||||
public void Cancel() => _handler.Invoke(this, MessageBoxResult.Cancel);
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
using System.Collections.ObjectModel;
|
||||
using FileTime.App.Core.ViewModels;
|
||||
using FileTime.Core.Interactions;
|
||||
|
||||
namespace FileTime.GuiApp.App.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);
|
||||
}
|
||||
@@ -1,145 +1,24 @@
|
||||
using System.Reactive.Linq;
|
||||
using Avalonia.Threading;
|
||||
using DynamicData;
|
||||
using FileTime.App.Core.Services;
|
||||
using FileTime.Core.Interactions;
|
||||
using FileTime.GuiApp.App.ViewModels;
|
||||
|
||||
namespace FileTime.GuiApp.App.Services;
|
||||
|
||||
public class DialogService : IDialogService
|
||||
public class DialogService : DialogServiceBase, IDialogService
|
||||
{
|
||||
private readonly IModalService _modalService;
|
||||
private readonly IGuiAppState _guiAppState;
|
||||
|
||||
public IObservable<ReadInputsViewModel?> ReadInput { get; }
|
||||
public IObservable<MessageBoxViewModel?> LastMessageBox { get; }
|
||||
|
||||
public DialogService(IModalService modalService, IGuiAppState guiAppState)
|
||||
public DialogService(IModalService modalService, IGuiAppState guiAppState) : base(modalService)
|
||||
{
|
||||
_modalService = modalService;
|
||||
_guiAppState = guiAppState;
|
||||
ReadInput = modalService
|
||||
.OpenModals
|
||||
.ToCollection()
|
||||
.Select(modals =>
|
||||
(ReadInputsViewModel?) modals.FirstOrDefault(m => m is ReadInputsViewModel)
|
||||
)
|
||||
.Publish(null)
|
||||
.RefCount();
|
||||
|
||||
LastMessageBox =
|
||||
modalService
|
||||
.OpenModals
|
||||
.Filter(m => m is MessageBoxViewModel)
|
||||
.Transform(m => (MessageBoxViewModel) m)
|
||||
.ToCollection()
|
||||
.Select(m => m.LastOrDefault());
|
||||
}
|
||||
|
||||
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 void ShowToastMessage(string text)
|
||||
{
|
||||
Task.Run(async () =>
|
||||
{
|
||||
await Dispatcher.UIThread.InvokeAsync(() => _guiAppState.PopupTexts.Add(text));
|
||||
await Task.Delay(5000);
|
||||
await Dispatcher.UIThread.InvokeAsync(() => _guiAppState.PopupTexts.Remove(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;
|
||||
}
|
||||
public override void ShowToastMessage(string text)
|
||||
=>
|
||||
Task.Run(async () =>
|
||||
{
|
||||
await Dispatcher.UIThread.InvokeAsync(() => _guiAppState.PopupTexts.Add(text));
|
||||
await Task.Delay(5000);
|
||||
await Dispatcher.UIThread.InvokeAsync(() => _guiAppState.PopupTexts.Remove(text));
|
||||
});
|
||||
}
|
||||
@@ -22,8 +22,6 @@
|
||||
xmlns="https://github.com/avaloniaui"
|
||||
xmlns:appCoreModels="using:FileTime.App.Core.Models"
|
||||
xmlns:appInteractions="using:FileTime.App.Core.Interactions"
|
||||
xmlns:config="using:FileTime.GuiApp.App.Configuration"
|
||||
xmlns:configuration="clr-namespace:FileTime.App.Core.Configuration;assembly=FileTime.App.Core.Abstraction"
|
||||
xmlns:corevm="using:FileTime.App.Core.ViewModels"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:i="clr-namespace:Avalonia.Xaml.Interactivity;assembly=Avalonia.Xaml.Interactivity"
|
||||
@@ -787,7 +785,7 @@
|
||||
<Border
|
||||
Background="{DynamicResource BarelyTransparentBackgroundColor}"
|
||||
HorizontalAlignment="Stretch"
|
||||
IsVisible="{Binding DialogService.ReadInput^, Converter={x:Static ObjectConverters.IsNotNull}}"
|
||||
IsVisible="{Binding DialogService.ReadInput.Value, Converter={x:Static ObjectConverters.IsNotNull}}"
|
||||
VerticalAlignment="Stretch"
|
||||
x:Name="ReadInputContainer">
|
||||
<Border
|
||||
@@ -798,7 +796,7 @@
|
||||
<Grid RowDefinitions="Auto,Auto,Auto">
|
||||
|
||||
<ItemsControl
|
||||
ItemsSource="{Binding DialogService.ReadInput^.Inputs}"
|
||||
ItemsSource="{Binding DialogService.ReadInput.Value.Inputs}"
|
||||
KeyUp="InputList_OnKeyUp"
|
||||
x:Name="InputList">
|
||||
<ItemsControl.ItemTemplate>
|
||||
@@ -839,7 +837,7 @@
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
|
||||
<ItemsControl Grid.Row="1" ItemsSource="{Binding DialogService.ReadInput^.Previews}">
|
||||
<ItemsControl Grid.Row="1" ItemsSource="{Binding DialogService.ReadInput.Value.Previews}">
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<Grid>
|
||||
@@ -913,7 +911,7 @@
|
||||
</ItemsControl>
|
||||
|
||||
<StackPanel
|
||||
DataContext="{Binding DialogService.ReadInput^}"
|
||||
DataContext="{Binding DialogService.ReadInput.Value}"
|
||||
Grid.Row="2"
|
||||
Margin="0,10,0,0"
|
||||
Orientation="Horizontal">
|
||||
@@ -935,7 +933,7 @@
|
||||
|
||||
<Border
|
||||
Background="{DynamicResource BarelyTransparentBackgroundColor}"
|
||||
DataContext="{Binding DialogService.LastMessageBox^}"
|
||||
DataContext="{Binding DialogService.LastMessageBox.Value}"
|
||||
HorizontalAlignment="Stretch"
|
||||
IsVisible="{Binding Converter={x:Static ObjectConverters.IsNotNull}, FallbackValue=False}"
|
||||
VerticalAlignment="Stretch">
|
||||
@@ -952,12 +950,12 @@
|
||||
Margin="0,10,0,0"
|
||||
Orientation="Horizontal">
|
||||
<Button
|
||||
Command="{Binding OkCommand}"
|
||||
Command="{Binding Ok}"
|
||||
Content="{Binding OkText}"
|
||||
HorizontalContentAlignment="Center"
|
||||
Width="80" />
|
||||
<Button
|
||||
Command="{Binding CancelCommand}"
|
||||
Command="{Binding Cancel}"
|
||||
Content="{Binding CancelText}"
|
||||
HorizontalContentAlignment="Center"
|
||||
IsVisible="{Binding ShowCancel}"
|
||||
|
||||
@@ -20,9 +20,6 @@ public partial class MainWindow : Window, IUiAccessor
|
||||
private readonly Action? _initializer;
|
||||
private ILogger<MainWindow>? _logger;
|
||||
private IModalService? _modalService;
|
||||
private IReadOnlyCollection<IModalViewModel>? _openModals;
|
||||
private ReadInputsViewModel? _inputViewModel;
|
||||
private IDisposable? _inputViewModelSubscription;
|
||||
private bool _isShuttingDown;
|
||||
private bool _shutdownCompleted;
|
||||
private readonly object _isClosingLock = new();
|
||||
@@ -61,19 +58,9 @@ public partial class MainWindow : Window, IUiAccessor
|
||||
|
||||
_logger = DI.ServiceProvider.GetService<ILogger<MainWindow>>();
|
||||
_modalService = DI.ServiceProvider.GetRequiredService<IModalService>();
|
||||
_modalService.OpenModals.ToCollection().Subscribe(m => _openModals = m);
|
||||
DI.ServiceProvider.GetRequiredService<Services.SystemClipboardService>().UiAccessor = this;
|
||||
DI.ServiceProvider.GetRequiredService<SystemClipboardService>().UiAccessor = this;
|
||||
|
||||
ReadInputContainer.PropertyChanged += ReadInputContainerOnPropertyChanged;
|
||||
DataContextChanged += (_, _) =>
|
||||
{
|
||||
if (DataContext is not MainWindowViewModel mainWindowViewModel) return;
|
||||
|
||||
_inputViewModelSubscription?.Dispose();
|
||||
_inputViewModelSubscription = mainWindowViewModel.DialogService.ReadInput.Subscribe(
|
||||
inputViewModel => _inputViewModel = inputViewModel
|
||||
);
|
||||
};
|
||||
|
||||
_logger?.LogInformation(
|
||||
$"{nameof(MainWindow)} opened, starting {nameof(MainWindowViewModel)} initialization...");
|
||||
@@ -99,7 +86,7 @@ public partial class MainWindow : Window, IUiAccessor
|
||||
|
||||
private void OnKeyDown(object sender, KeyEventArgs e)
|
||||
{
|
||||
if ((_openModals?.Count ?? 0) > 0) return;
|
||||
if (_modalService!.OpenModals.Count > 0) return;
|
||||
ViewModel?.ProcessKeyDown(e);
|
||||
}
|
||||
|
||||
@@ -177,15 +164,14 @@ public partial class MainWindow : Window, IUiAccessor
|
||||
|
||||
private void InputList_OnKeyUp(object? sender, KeyEventArgs e)
|
||||
{
|
||||
var inputViewModel = ViewModel!.DialogService.ReadInput.Value;
|
||||
if (e.Key == Key.Escape)
|
||||
{
|
||||
_inputViewModel?.Cancel();
|
||||
_inputViewModel = null;
|
||||
inputViewModel?.Cancel();
|
||||
}
|
||||
else if (e.Key == Key.Enter)
|
||||
{
|
||||
_inputViewModel?.Process();
|
||||
_inputViewModel = null;
|
||||
inputViewModel?.Process();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user