using Avalonia.Controls; using Avalonia.Layout; using CommunityToolkit.Mvvm.ComponentModel; using DialogHostAvalonia; using InABox.Avalonia.Components; using InABox.Avalonia.Router; namespace InABox.Avalonia; public interface IViewModelBase { Task Activate(); Task Deactivate(); bool OnBackButtonPressed(); bool BackButtonVisible { get; set; } bool ProgressVisible { get; set; } AvaloniaMenuItemCollection PrimaryMenu { get; set; } AvaloniaMenuItemCollection SecondaryMenu { get; set; } } public interface IPopupViewModel { bool IsClosed { get; } } /// /// Indicates that this view model can be a module or a popup. /// public interface IDualFunctionViewModel : IPopupViewModel, IViewModelBase { bool IsPopup { get; set; } } public interface IAlignedPopup { HorizontalAlignment HorizontalAlignment { get; } VerticalAlignment VerticalAlignment { get; } } public interface IPopupViewModel : IPopupViewModel { TResult? GetResult(); } public static class Navigation { private static readonly HistoryRouter _router; // private static Dictionary> ViewModelFactory = new(); // // public static void Register(Func create) where TViewModel : IViewModelBase // { // ViewModelFactory[typeof(TViewModel)] = create; // } static Navigation() { _router = new HistoryRouter(x => { // if (ViewModelFactory.TryGetValue(x, out var create)) // { // var result = create(); // return result; // } var model = Activator.CreateInstance(x); return model as IViewModelBase; }); _router.CurrentViewModelChanging += (@base, direction) => CurrentViewModelChanging?.Invoke(@base, direction); _router.CurrentViewModelChanged += @base => CurrentViewModelChanged?.Invoke(@base); } public static void Back() { _router.Back(); } public static void Navigate(Action? configure = null) where T : IViewModelBase { _router.GoTo(configure); } public static async Task Popup(Action? configure = null, bool canTapAway = true) where T : IViewModelBase, IPopupViewModel { var viewModel = _router.InstantiateViewModel(configure); return await Popup(viewModel, canTapAway); } public static async Task Popup(T viewModel, bool canTapAway = true) where T : IViewModelBase, IPopupViewModel { if (viewModel is IDualFunctionViewModel dualFunction) { dualFunction.IsPopup = true; } await viewModel.Activate(); var _result = await DialogHostAvalonia.DialogHost.Show(viewModel, (object sender, DialogClosingEventArgs eventArgs) => { if(!canTapAway && !viewModel.IsClosed) { eventArgs.Cancel(); } }); await viewModel.Deactivate(); return _result; } public static async Task Popup(Action? configure = null, bool canTapAway = true) where T : IViewModelBase, IPopupViewModel { var viewModel = _router.InstantiateViewModel(configure); return await Popup(viewModel, canTapAway); } public static async Task Popup(T viewModel, bool canTapAway = true) where T : IViewModelBase, IPopupViewModel { if (viewModel is IDualFunctionViewModel dualFunction) { dualFunction.IsPopup = true; } await viewModel.Activate(); var _result = await DialogHostAvalonia.DialogHost.Show(viewModel, (object sender, DialogClosingEventArgs eventArgs) => { if(!canTapAway && !viewModel.IsClosed) { eventArgs.Cancel(); } }); await viewModel.Deactivate(); return viewModel.GetResult(); } public static void Reset(Action? configure = null) where T : IViewModelBase { _router.Reset(configure); } public static event Action? CurrentViewModelChanging; public static event Action? CurrentViewModelChanged; } public class BasePopupViewModel : ObservableObject, IPopupViewModel, IViewModelBase { #region IPopupViewModel public bool IsClosed { get; private set; } protected TResult? _result; public TResult? GetResult() { return _result; } public void Close(TResult? result) { _result = result; IsClosed = true; DialogHost.GetDialogSession(null)?.Close(); } #endregion #region IViewModel public bool BackButtonVisible { get; set; } public bool ProgressVisible { get; set; } public AvaloniaMenuItemCollection PrimaryMenu { get; set; } = new(); public AvaloniaMenuItemCollection SecondaryMenu { get; set; } = new(); public virtual Task Activate() { return Task.CompletedTask; } public virtual Task Deactivate() { return Task.CompletedTask; } public virtual bool OnBackButtonPressed() { return true; } #endregion }