From 0b3fe30fec8d3e34c62285b4995e21b845fc9272 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81d=C3=A1m=20Kov=C3=A1cs?= Date: Thu, 9 Jun 2022 17:49:34 +0200 Subject: [PATCH] WIP --- .../Services/IModalService.cs | 6 +- .../UserCommand/DeleteCommand.cs | 19 ++++++ ...dalViewModelBase.cs => IModalViewModel.cs} | 2 +- ...emManipulationUserCommandHandlerService.cs | 65 ++++++++++++++++++- ...faultIdentifiableCommandHandlerRegister.cs | 2 + .../Interactions/IUserCommunicationService.cs | 1 + .../Interactions/MessageBoxResult.cs | 7 ++ .../Models/IContainer.cs | 1 + .../Delete/DeleteCommand.cs | 25 +++++++ .../ContentProviderBase.cs | 1 + src/Core/FileTime.Core.Models/Container.cs | 1 + .../Configuration/MainConfiguration.cs | 4 +- .../Services/IDialogService.cs | 2 + .../ViewModels/IGuiAppState.cs | 1 - .../ViewModels/MessageBoxViewModel.cs | 31 +++++++++ .../ViewModels/ReadInputsViewModel.cs | 2 +- .../ViewModels/GuiAppState.cs | 2 - .../Services/DefaultModeKeyInputHandler.cs | 21 ++++-- .../FileTime.GuiApp/Services/DialogService.cs | 27 +++++++- .../FileTime.GuiApp/Services/ModalService.cs | 8 +-- .../RapidTravelModeKeyInputHandler.cs | 4 +- .../FileTime.GuiApp/Views/MainWindow.axaml | 52 +++++++++++++-- .../FileTime.GuiApp/Views/MainWindow.axaml.cs | 2 +- .../LocalContentProvider.cs | 2 + 24 files changed, 254 insertions(+), 34 deletions(-) create mode 100644 src/AppCommon/FileTime.App.Core.Abstraction/UserCommand/DeleteCommand.cs rename src/AppCommon/FileTime.App.Core.Abstraction/ViewModels/{IModalViewModelBase.cs => IModalViewModel.cs} (65%) create mode 100644 src/Core/FileTime.Core.Abstraction/Interactions/MessageBoxResult.cs create mode 100644 src/Core/FileTime.Core.Command/Delete/DeleteCommand.cs create mode 100644 src/GuiApp/Avalonia/FileTime.GuiApp.Abstractions/ViewModels/MessageBoxViewModel.cs diff --git a/src/AppCommon/FileTime.App.Core.Abstraction/Services/IModalService.cs b/src/AppCommon/FileTime.App.Core.Abstraction/Services/IModalService.cs index 36f91c7..ae7f9f5 100644 --- a/src/AppCommon/FileTime.App.Core.Abstraction/Services/IModalService.cs +++ b/src/AppCommon/FileTime.App.Core.Abstraction/Services/IModalService.cs @@ -5,8 +5,8 @@ namespace FileTime.App.Core.Services; public interface IModalService { - IObservable> OpenModals { get; } + IObservable> OpenModals { get; } - void OpenModal(IModalViewModelBase modalToOpen); - void CloseModal(IModalViewModelBase modalToClose); + void OpenModal(IModalViewModel modalToOpen); + void CloseModal(IModalViewModel modalToClose); } \ No newline at end of file diff --git a/src/AppCommon/FileTime.App.Core.Abstraction/UserCommand/DeleteCommand.cs b/src/AppCommon/FileTime.App.Core.Abstraction/UserCommand/DeleteCommand.cs new file mode 100644 index 0000000..8568a70 --- /dev/null +++ b/src/AppCommon/FileTime.App.Core.Abstraction/UserCommand/DeleteCommand.cs @@ -0,0 +1,19 @@ +namespace FileTime.App.Core.UserCommand; + +public class DeleteCommand : IIdentifiableUserCommand +{ + public const string SoftDeleteCommandName = "soft_delete"; + public const string HardDeleteCommandName = "hard_delete"; + + public static DeleteCommand SoftDelete { get; } = new DeleteCommand(SoftDeleteCommandName, false); + public static DeleteCommand HardDelete { get; } = new DeleteCommand(HardDeleteCommandName, true); + + private DeleteCommand(string commandName, bool hardDelete) + { + UserCommandID = commandName; + IsHardDelete = hardDelete; + } + + public string UserCommandID { get; } + public bool IsHardDelete { get; } +} \ No newline at end of file diff --git a/src/AppCommon/FileTime.App.Core.Abstraction/ViewModels/IModalViewModelBase.cs b/src/AppCommon/FileTime.App.Core.Abstraction/ViewModels/IModalViewModel.cs similarity index 65% rename from src/AppCommon/FileTime.App.Core.Abstraction/ViewModels/IModalViewModelBase.cs rename to src/AppCommon/FileTime.App.Core.Abstraction/ViewModels/IModalViewModel.cs index 78d73b9..72030f6 100644 --- a/src/AppCommon/FileTime.App.Core.Abstraction/ViewModels/IModalViewModelBase.cs +++ b/src/AppCommon/FileTime.App.Core.Abstraction/ViewModels/IModalViewModel.cs @@ -1,6 +1,6 @@ namespace FileTime.App.Core.ViewModels; -public interface IModalViewModelBase +public interface IModalViewModel { string Name { get; } } \ No newline at end of file diff --git a/src/AppCommon/FileTime.App.Core/Services/UserCommandHandler/ItemManipulationUserCommandHandlerService.cs b/src/AppCommon/FileTime.App.Core/Services/UserCommandHandler/ItemManipulationUserCommandHandlerService.cs index 42f0e6b..e6f58fa 100644 --- a/src/AppCommon/FileTime.App.Core/Services/UserCommandHandler/ItemManipulationUserCommandHandlerService.cs +++ b/src/AppCommon/FileTime.App.Core/Services/UserCommandHandler/ItemManipulationUserCommandHandlerService.cs @@ -6,6 +6,7 @@ using FileTime.App.Core.ViewModels; using FileTime.Core.Command; using FileTime.Core.Command.CreateContainer; using FileTime.Core.Command.CreateElement; +using FileTime.Core.Extensions; using FileTime.Core.Interactions; using FileTime.Core.Models; using FileTime.Core.Timeline; @@ -23,6 +24,7 @@ public class ItemManipulationUserCommandHandlerService : UserCommandHandlerServi private readonly IClipboardService _clipboardService; private readonly IUserCommunicationService _userCommunicationService; private readonly ILogger _logger; + private readonly ITimelessContentProvider _timelessContentProvider; private readonly ICommandScheduler _commandScheduler; private readonly IServiceProvider _serviceProvider; private readonly BindedCollection? _markedItems; @@ -42,6 +44,7 @@ public class ItemManipulationUserCommandHandlerService : UserCommandHandlerServi _clipboardService = clipboardService; _userCommunicationService = userCommunicationService; _logger = logger; + _timelessContentProvider = timelessContentProvider; _commandScheduler = commandScheduler; _serviceProvider = serviceProvider; @@ -54,6 +57,7 @@ public class ItemManipulationUserCommandHandlerService : UserCommandHandlerServi AddCommandHandlers(new IUserCommandHandler[] { new TypeUserCommandHandler(Copy), + new TypeUserCommandHandler(Delete), new TypeUserCommandHandler(MarkItem), new TypeUserCommandHandler(Paste), new TypeUserCommandHandler(CreateContainer), @@ -143,7 +147,7 @@ public class ItemManipulationUserCommandHandlerService : UserCommandHandlerServi _clipboardService.Clear(); if (command is IRequireInputCommand requireInput) await requireInput.ReadInputs(); - + await AddCommand(command); } @@ -181,6 +185,65 @@ public class ItemManipulationUserCommandHandlerService : UserCommandHandlerServi await AddCommand(command); } + private async Task Delete(DeleteCommand command) + { + IList? itemsToDelete = null; + var shouldDelete = false; + string? questionText = null; + if ((_markedItems?.Collection?.Count ?? 0) > 0) + { + itemsToDelete = new List(_markedItems!.Collection!); + } + else if (_currentSelectedItem?.BaseItem?.FullName is not null) + { + itemsToDelete = new List() + { + _currentSelectedItem.BaseItem.FullName + }; + } + + if ((itemsToDelete?.Count ?? 0) == 0) return; + + if (itemsToDelete!.Count == 1) + { + var resolvedOnlyItem = await _timelessContentProvider.GetItemByFullNameAsync(itemsToDelete[0], PointInTime.Present); + + if (resolvedOnlyItem is IContainer {AllowRecursiveDeletion: true} onlyContainer + && await onlyContainer.Items.GetItemsAsync() is { } children + && children.Any()) + { + questionText = $"The container '{onlyContainer.DisplayName}' is not empty. Proceed with delete?"; + } + else + { + shouldDelete = true; + } + } + + if (itemsToDelete?.Count == 0) return; + + if (questionText is { }) + { + var proceedDelete = await _userCommunicationService.ShowMessageBox(questionText!); + + if (proceedDelete == MessageBoxResult.Cancel) return; + } + else if (!shouldDelete) + { + return; + } + + var deleteCommand = new FileTime.Core.Command.Delete.DeleteCommand() + { + HardDelete = command.IsHardDelete + }; + + deleteCommand.ItemsToDelete.AddRange(itemsToDelete!); + await AddCommand(deleteCommand); + + _selectedTab?.ClearMarkedItems(); + } + private async Task AddCommand(ICommand command) { await _commandScheduler.AddCommand(command); diff --git a/src/AppCommon/FileTime.App.Core/StartupServices/DefaultIdentifiableCommandHandlerRegister.cs b/src/AppCommon/FileTime.App.Core/StartupServices/DefaultIdentifiableCommandHandlerRegister.cs index 727dd64..3623b33 100644 --- a/src/AppCommon/FileTime.App.Core/StartupServices/DefaultIdentifiableCommandHandlerRegister.cs +++ b/src/AppCommon/FileTime.App.Core/StartupServices/DefaultIdentifiableCommandHandlerRegister.cs @@ -16,6 +16,8 @@ public class DefaultIdentifiableCommandHandlerRegister : IStartupHandler AddUserCommand(CopyNativePathCommand.Instance); AddUserCommand(CreateContainer.Instance); AddUserCommand(CreateElement.Instance); + AddUserCommand(DeleteCommand.HardDelete); + AddUserCommand(DeleteCommand.SoftDelete); AddUserCommand(EnterRapidTravelCommand.Instance); AddUserCommand(ExitRapidTravelCommand.Instance); AddUserCommand(GoToHomeCommand.Instance); diff --git a/src/Core/FileTime.Core.Abstraction/Interactions/IUserCommunicationService.cs b/src/Core/FileTime.Core.Abstraction/Interactions/IUserCommunicationService.cs index e59f6f7..99697d7 100644 --- a/src/Core/FileTime.Core.Abstraction/Interactions/IUserCommunicationService.cs +++ b/src/Core/FileTime.Core.Abstraction/Interactions/IUserCommunicationService.cs @@ -4,4 +4,5 @@ public interface IUserCommunicationService { Task ReadInputs(params IInputElement[] fields); void ShowToastMessage(string text); + Task ShowMessageBox(string text); } \ No newline at end of file diff --git a/src/Core/FileTime.Core.Abstraction/Interactions/MessageBoxResult.cs b/src/Core/FileTime.Core.Abstraction/Interactions/MessageBoxResult.cs new file mode 100644 index 0000000..31e20ba --- /dev/null +++ b/src/Core/FileTime.Core.Abstraction/Interactions/MessageBoxResult.cs @@ -0,0 +1,7 @@ +namespace FileTime.Core.Interactions; + +public enum MessageBoxResult +{ + Ok, + Cancel +} \ No newline at end of file diff --git a/src/Core/FileTime.Core.Abstraction/Models/IContainer.cs b/src/Core/FileTime.Core.Abstraction/Models/IContainer.cs index 5390a31..84f5c90 100644 --- a/src/Core/FileTime.Core.Abstraction/Models/IContainer.cs +++ b/src/Core/FileTime.Core.Abstraction/Models/IContainer.cs @@ -6,4 +6,5 @@ public interface IContainer : IItem { IObservable>?> Items { get; } IObservable IsLoading { get; } + bool AllowRecursiveDeletion { get; } } \ No newline at end of file diff --git a/src/Core/FileTime.Core.Command/Delete/DeleteCommand.cs b/src/Core/FileTime.Core.Command/Delete/DeleteCommand.cs new file mode 100644 index 0000000..ca1e8f2 --- /dev/null +++ b/src/Core/FileTime.Core.Command/Delete/DeleteCommand.cs @@ -0,0 +1,25 @@ +using FileTime.Core.Models; +using FileTime.Core.Timeline; + +namespace FileTime.Core.Command.Delete; + +public class DeleteCommand : IExecutableCommand +{ + public bool HardDelete { get; init; } + public List ItemsToDelete { get; } = new List(); + + public Task CanRun(PointInTime currentTime) + { + throw new NotImplementedException(); + } + + public Task SimulateCommand(PointInTime currentTime) + { + throw new NotImplementedException(); + } + + public Task Execute() + { + throw new NotImplementedException(); + } +} \ No newline at end of file diff --git a/src/Core/FileTime.Core.ContentAccess/ContentProviderBase.cs b/src/Core/FileTime.Core.ContentAccess/ContentProviderBase.cs index 68a67b4..8dd8582 100644 --- a/src/Core/FileTime.Core.ContentAccess/ContentProviderBase.cs +++ b/src/Core/FileTime.Core.ContentAccess/ContentProviderBase.cs @@ -41,6 +41,7 @@ public abstract class ContentProviderBase : IContentProvider public string? Attributes => null; protected BehaviorSubject IsLoading { get; } = new(false); + public bool AllowRecursiveDeletion => false; IObservable IContainer.IsLoading => IsLoading.AsObservable(); diff --git a/src/Core/FileTime.Core.Models/Container.cs b/src/Core/FileTime.Core.Models/Container.cs index e8968e8..49beda4 100644 --- a/src/Core/FileTime.Core.Models/Container.cs +++ b/src/Core/FileTime.Core.Models/Container.cs @@ -22,6 +22,7 @@ public record Container( bool CanRename, string? Attributes, IContentProvider Provider, + bool AllowRecursiveDeletion, PointInTime PointInTime, IObservable> Exceptions, ReadOnlyExtensionCollection Extensions, diff --git a/src/GuiApp/Avalonia/FileTime.GuiApp.Abstractions/Configuration/MainConfiguration.cs b/src/GuiApp/Avalonia/FileTime.GuiApp.Abstractions/Configuration/MainConfiguration.cs index 90cf14c..b99a206 100644 --- a/src/GuiApp/Avalonia/FileTime.GuiApp.Abstractions/Configuration/MainConfiguration.cs +++ b/src/GuiApp/Avalonia/FileTime.GuiApp.Abstractions/Configuration/MainConfiguration.cs @@ -63,7 +63,7 @@ public static class MainConfiguration new CommandBindingConfiguration(GoToPathCommand.CommandName, new[] { Key.G, Key.P }), new CommandBindingConfiguration(GoToProviderCommand.CommandName, new[] { Key.G, Key.T }), new CommandBindingConfiguration(GoToRootCommand.CommandName, new[] { Key.G, Key.R }), - //new CommandBindingConfiguration(ConfigCommand.HardDelete, new[] { new KeyConfig(Key.D,shift: true), new KeyConfig(Key.D, shift: true) }), + new CommandBindingConfiguration(DeleteCommand.HardDeleteCommandName, new[] { new KeyConfig(Key.D,shift: true), new KeyConfig(Key.D, shift: true) }), new CommandBindingConfiguration(MarkCommand.CommandName, Key.Space), new CommandBindingConfiguration(MoveCursorToLastCommand.CommandName, new KeyConfig(Key.G, shift: true)), new CommandBindingConfiguration(MoveCursorToFirstCommand.CommandName, new[] { Key.G, Key.G }), @@ -82,7 +82,7 @@ public static class MainConfiguration //new CommandBindingConfiguration(ConfigCommand.RunCommand, new KeyConfig(Key.D4, shift: true)), //new CommandBindingConfiguration(ConfigCommand.ScanContainerSize, new[] { Key.C, Key.S }), //new CommandBindingConfiguration(ConfigCommand.ShowAllShortcut, Key.F1), - //new CommandBindingConfiguration(ConfigCommand.SoftDelete, new[] { new KeyConfig(Key.D), new KeyConfig(Key.D, shift: true) }), + new CommandBindingConfiguration(DeleteCommand.SoftDeleteCommandName, new[] { new KeyConfig(Key.D), new KeyConfig(Key.D, shift: true) }), new CommandBindingConfiguration(SwitchToTabCommand.SwitchToLastTabCommandName, Key.D9), new CommandBindingConfiguration(SwitchToTabCommand.SwitchToTab1CommandName, Key.D1), new CommandBindingConfiguration(SwitchToTabCommand.SwitchToTab2CommandName, Key.D2), diff --git a/src/GuiApp/Avalonia/FileTime.GuiApp.Abstractions/Services/IDialogService.cs b/src/GuiApp/Avalonia/FileTime.GuiApp.Abstractions/Services/IDialogService.cs index 1966da5..4ab0ea6 100644 --- a/src/GuiApp/Avalonia/FileTime.GuiApp.Abstractions/Services/IDialogService.cs +++ b/src/GuiApp/Avalonia/FileTime.GuiApp.Abstractions/Services/IDialogService.cs @@ -1,3 +1,4 @@ +using FileTime.App.Core.Models; using FileTime.Core.Interactions; using FileTime.GuiApp.ViewModels; @@ -6,5 +7,6 @@ namespace FileTime.GuiApp.Services; public interface IDialogService : IUserCommunicationService { IObservable ReadInput { get; } + IObservable LastMessageBox { 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/ViewModels/IGuiAppState.cs b/src/GuiApp/Avalonia/FileTime.GuiApp.Abstractions/ViewModels/IGuiAppState.cs index 99259a6..7d980ea 100644 --- a/src/GuiApp/Avalonia/FileTime.GuiApp.Abstractions/ViewModels/IGuiAppState.cs +++ b/src/GuiApp/Avalonia/FileTime.GuiApp.Abstractions/ViewModels/IGuiAppState.cs @@ -10,7 +10,6 @@ public interface IGuiAppState : IAppState List PreviousKeys { get; } bool IsAllShortcutVisible { get; set; } bool NoCommandFound { get; set; } - string? MessageBoxText { get; set; } List PossibleCommands { get; set; } BindedCollection RootDriveInfos { get; set; } IReadOnlyList Places { get; set; } diff --git a/src/GuiApp/Avalonia/FileTime.GuiApp.Abstractions/ViewModels/MessageBoxViewModel.cs b/src/GuiApp/Avalonia/FileTime.GuiApp.Abstractions/ViewModels/MessageBoxViewModel.cs new file mode 100644 index 0000000..a718d5a --- /dev/null +++ b/src/GuiApp/Avalonia/FileTime.GuiApp.Abstractions/ViewModels/MessageBoxViewModel.cs @@ -0,0 +1,31 @@ +using FileTime.App.Core.ViewModels; +using FileTime.Core.Interactions; +using MvvmGen; + +namespace FileTime.GuiApp.ViewModels; + +[ViewModel] +public partial class MessageBoxViewModel : IModalViewModel +{ + private readonly Action _handler; + public string Text { get; } + public string Name => "MessageBoxViewModel"; + + public MessageBoxViewModel(string text, Action handler) + { + _handler = handler; + Text = text; + } + + [Command] + public void Ok() + { + _handler.Invoke(this, MessageBoxResult.Ok); + } + + [Command] + public void Cancel() + { + _handler.Invoke(this, MessageBoxResult.Cancel); + } +} \ 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 index 5fb4d2e..eb3843b 100644 --- a/src/GuiApp/Avalonia/FileTime.GuiApp.Abstractions/ViewModels/ReadInputsViewModel.cs +++ b/src/GuiApp/Avalonia/FileTime.GuiApp.Abstractions/ViewModels/ReadInputsViewModel.cs @@ -7,7 +7,7 @@ namespace FileTime.GuiApp.ViewModels; [ViewModel] [Inject(typeof(Action), "_cancel")] [Inject(typeof(Action), "_process")] -public partial class ReadInputsViewModel : IModalViewModelBase +public partial class ReadInputsViewModel : IModalViewModel { public string Name => "ReadInputs"; public List Inputs { get; set; } diff --git a/src/GuiApp/Avalonia/FileTime.GuiApp.CustomImpl/ViewModels/GuiAppState.cs b/src/GuiApp/Avalonia/FileTime.GuiApp.CustomImpl/ViewModels/GuiAppState.cs index 843abbf..ed11a65 100644 --- a/src/GuiApp/Avalonia/FileTime.GuiApp.CustomImpl/ViewModels/GuiAppState.cs +++ b/src/GuiApp/Avalonia/FileTime.GuiApp.CustomImpl/ViewModels/GuiAppState.cs @@ -14,8 +14,6 @@ public partial class GuiAppState : AppStateBase, IGuiAppState [Property] private bool _noCommandFound; - [Property] private string? _messageBoxText; - [Property] private List _possibleCommands = new(); [Property] private BindedCollection _rootDriveInfos = new(); diff --git a/src/GuiApp/Avalonia/FileTime.GuiApp/Services/DefaultModeKeyInputHandler.cs b/src/GuiApp/Avalonia/FileTime.GuiApp/Services/DefaultModeKeyInputHandler.cs index 0f6b015..4af8633 100644 --- a/src/GuiApp/Avalonia/FileTime.GuiApp/Services/DefaultModeKeyInputHandler.cs +++ b/src/GuiApp/Avalonia/FileTime.GuiApp/Services/DefaultModeKeyInputHandler.cs @@ -1,5 +1,6 @@ using System.Reactive.Linq; using Avalonia.Input; +using FileTime.App.Core.Models; using FileTime.App.Core.Services; using FileTime.App.Core.UserCommand; using FileTime.App.Core.ViewModels; @@ -15,6 +16,7 @@ namespace FileTime.GuiApp.Services; public class DefaultModeKeyInputHandler : IDefaultModeKeyInputHandler { private readonly IGuiAppState _appState; + private readonly IModalService _modalService; private readonly IKeyboardConfigurationService _keyboardConfigurationService; private readonly List _keysToSkip = new(); private ITabViewModel? _selectedTab; @@ -22,22 +24,27 @@ public class DefaultModeKeyInputHandler : IDefaultModeKeyInputHandler private readonly ILogger _logger; private readonly IUserCommandHandlerService _userCommandHandlerService; private readonly IIdentifiableUserCommandService _identifiableUserCommandService; + private readonly BindedCollection _openModals; public DefaultModeKeyInputHandler( IGuiAppState appState, + IModalService modalService, IKeyboardConfigurationService keyboardConfigurationService, ILogger logger, IUserCommandHandlerService userCommandHandlerService, IIdentifiableUserCommandService identifiableUserCommandService) { _appState = appState; + _identifiableUserCommandService = identifiableUserCommandService; _keyboardConfigurationService = keyboardConfigurationService; _logger = logger; + _modalService = modalService; _userCommandHandlerService = userCommandHandlerService; - _identifiableUserCommandService = identifiableUserCommandService; _appState.SelectedTab.Subscribe(t => _selectedTab = t); _appState.SelectedTab.Select(t => t == null ? Observable.Return(null) : t.CurrentLocation!).Switch().Subscribe(l => _currentLocation = l); + + _openModals = new BindedCollection(modalService.OpenModals); _keysToSkip.Add(new KeyConfig[] { new KeyConfig(Key.Up) }); _keysToSkip.Add(new KeyConfig[] { new KeyConfig(Key.Down) }); @@ -59,10 +66,11 @@ public class DefaultModeKeyInputHandler : IDefaultModeKeyInputHandler if (key == Key.Escape) { - var doGeneralReset = false; - if (_appState.PreviousKeys.Count > 1 || _appState.IsAllShortcutVisible || _appState.MessageBoxText != null) + bool doGeneralReset = _appState.PreviousKeys.Count > 1 || _appState.IsAllShortcutVisible; + + if ((_openModals.Collection?.Count ?? 0) > 0) { - doGeneralReset = true; + _modalService.CloseModal(_openModals.Collection!.Last()); } /*else if (_currentLocation.Container.CanHandleEscape) { @@ -90,18 +98,17 @@ public class DefaultModeKeyInputHandler : IDefaultModeKeyInputHandler { setHandled(true); _appState.IsAllShortcutVisible = false; - _appState.MessageBoxText = null; _appState.PreviousKeys.Clear(); _appState.PossibleCommands = new(); } } - else if (key == Key.Enter + /*else if (key == Key.Enter && _appState.MessageBoxText != null) { _appState.PreviousKeys.Clear(); //_dialogService.ProcessMessageBox(); setHandled(true); - } + }*/ else if (selectedCommandBinding != null) { setHandled(true); diff --git a/src/GuiApp/Avalonia/FileTime.GuiApp/Services/DialogService.cs b/src/GuiApp/Avalonia/FileTime.GuiApp/Services/DialogService.cs index 6adfc14..6019e7b 100644 --- a/src/GuiApp/Avalonia/FileTime.GuiApp/Services/DialogService.cs +++ b/src/GuiApp/Avalonia/FileTime.GuiApp/Services/DialogService.cs @@ -1,6 +1,8 @@ +using System.Collections.ObjectModel; using System.Reactive.Linq; using Avalonia.Threading; using DynamicData; +using FileTime.App.Core.Models; using FileTime.App.Core.Services; using FileTime.Core.Interactions; using FileTime.GuiApp.ViewModels; @@ -13,6 +15,7 @@ public class DialogService : IDialogService private readonly IGuiAppState _guiAppState; public IObservable ReadInput { get; } + public IObservable LastMessageBox { get; } public DialogService(IModalService modalService, IGuiAppState guiAppState) { @@ -22,10 +25,18 @@ public class DialogService : IDialogService .OpenModals .ToCollection() .Select(modals => - (ReadInputsViewModel?)modals.FirstOrDefault(m => m is ReadInputsViewModel) + (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()); } public void ReadInputs(IEnumerable inputs, Action inputHandler, Action? cancelHandler = null) @@ -50,6 +61,18 @@ public class DialogService : IDialogService }); } + public Task ShowMessageBox(string text) + { + var taskCompletionSource = new TaskCompletionSource(); + _modalService.OpenModal(new MessageBoxViewModel(text, (vm, result) => + { + _modalService.CloseModal(vm); + taskCompletionSource.SetResult(result); + })); + + return taskCompletionSource.Task; + } + private void HandleReadInputsSuccess(ReadInputsViewModel readInputsViewModel) { _modalService.CloseModal(readInputsViewModel); @@ -66,7 +89,7 @@ public class DialogService : IDialogService { 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/ModalService.cs b/src/GuiApp/Avalonia/FileTime.GuiApp/Services/ModalService.cs index f928f4a..045acfc 100644 --- a/src/GuiApp/Avalonia/FileTime.GuiApp/Services/ModalService.cs +++ b/src/GuiApp/Avalonia/FileTime.GuiApp/Services/ModalService.cs @@ -6,15 +6,15 @@ namespace FileTime.GuiApp.Services; public class ModalService : IModalService { - private readonly SourceList _openModals = new(); - public IObservable> OpenModals { get; } + private readonly SourceList _openModals = new(); + public IObservable> OpenModals { get; } public ModalService() { OpenModals = _openModals.Connect().StartWithEmpty(); } - public void OpenModal(IModalViewModelBase modalToOpen) => _openModals.Add(modalToOpen); + public void OpenModal(IModalViewModel modalToOpen) => _openModals.Add(modalToOpen); - public void CloseModal(IModalViewModelBase modalToClose) => _openModals.Remove(modalToClose); + public void CloseModal(IModalViewModel modalToClose) => _openModals.Remove(modalToClose); } \ No newline at end of file diff --git a/src/GuiApp/Avalonia/FileTime.GuiApp/Services/RapidTravelModeKeyInputHandler.cs b/src/GuiApp/Avalonia/FileTime.GuiApp/Services/RapidTravelModeKeyInputHandler.cs index e264a8a..ee33bcf 100644 --- a/src/GuiApp/Avalonia/FileTime.GuiApp/Services/RapidTravelModeKeyInputHandler.cs +++ b/src/GuiApp/Avalonia/FileTime.GuiApp/Services/RapidTravelModeKeyInputHandler.cs @@ -22,7 +22,7 @@ public class RapidTravelModeKeyInputHandler : IRapidTravelModeKeyInputHandler private readonly IUserCommandHandlerService _userCommandHandlerService; private readonly ILogger _logger; private readonly IIdentifiableUserCommandService _identifiableUserCommandService; - private readonly BindedCollection _openModals; + private readonly BindedCollection _openModals; private ITabViewModel? _selectedTab; public RapidTravelModeKeyInputHandler( @@ -42,7 +42,7 @@ public class RapidTravelModeKeyInputHandler : IRapidTravelModeKeyInputHandler _appState.SelectedTab.Subscribe(t => _selectedTab = t); - _openModals = new BindedCollection(modalService.OpenModals); + _openModals = new BindedCollection(modalService.OpenModals); } public async Task HandleInputKey(Key key, SpecialKeysStatus specialKeysStatus, Action setHandled) diff --git a/src/GuiApp/Avalonia/FileTime.GuiApp/Views/MainWindow.axaml b/src/GuiApp/Avalonia/FileTime.GuiApp/Views/MainWindow.axaml index 30e857c..2333405 100644 --- a/src/GuiApp/Avalonia/FileTime.GuiApp/Views/MainWindow.axaml +++ b/src/GuiApp/Avalonia/FileTime.GuiApp/Views/MainWindow.axaml @@ -326,7 +326,8 @@ - + - - + +