HistoryRouter.cs 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. namespace InABox.Avalonia.Router;
  2. public enum RouterDirection
  3. {
  4. Forward,
  5. Backward
  6. }
  7. public class HistoryRouter<TViewModelBase>: Router<TViewModelBase> where TViewModelBase: class
  8. {
  9. private int _historyIndex = -1;
  10. private List<TViewModelBase> _history = new();
  11. private readonly uint _historyMaxSize = 100;
  12. public bool HasNext => _history.Count > 0 && _historyIndex < _history.Count - 1;
  13. public bool HasPrev => _historyIndex > 0;
  14. public event Action<TViewModelBase,RouterDirection>? CurrentViewModelChanging;
  15. public HistoryRouter(Func<Type, TViewModelBase> createViewModel) : base(createViewModel)
  16. {
  17. }
  18. // pushState
  19. // popState
  20. // replaceState
  21. public void Push(TViewModelBase item)
  22. {
  23. if (HasNext)
  24. {
  25. _history = _history.Take(_historyIndex + 1).ToList();
  26. }
  27. _history.Add(item);
  28. _historyIndex = _history.Count - 1;
  29. if (_history.Count > _historyMaxSize)
  30. {
  31. _history.RemoveAt(0);
  32. }
  33. }
  34. public TViewModelBase? Go(int offset = 0)
  35. {
  36. if (offset == 0)
  37. {
  38. return default;
  39. }
  40. var newIndex = _historyIndex + offset;
  41. if (newIndex < 0 || newIndex > _history.Count - 1)
  42. {
  43. return default;
  44. }
  45. _historyIndex = newIndex;
  46. var viewModel = _history.ElementAt(_historyIndex);
  47. CurrentViewModelChanging?.Invoke(viewModel, offset >= 0 ? RouterDirection.Forward : RouterDirection.Backward);
  48. CurrentViewModel = viewModel;
  49. return viewModel;
  50. }
  51. public TViewModelBase? Back() => HasPrev ? Go(-1) : default;
  52. public TViewModelBase? Forward() => HasNext ? Go(1) : default;
  53. private T InternalGoTo<T>(RouterDirection direction, Action<T>? configure = null) where T: TViewModelBase
  54. {
  55. var destination = InstantiateViewModel<T>(configure);
  56. CurrentViewModelChanging?.Invoke(destination, direction);
  57. CurrentViewModel = destination;
  58. Push(destination);
  59. return destination;
  60. }
  61. public T Reset<T>(Action<T>? configure = null) where T: TViewModelBase
  62. {
  63. _historyIndex = -1;
  64. _history.Clear();
  65. return InternalGoTo<T>(RouterDirection.Backward, configure);
  66. }
  67. public override T GoTo<T>(Action<T>? configure = null)
  68. {
  69. return InternalGoTo<T>(RouterDirection.Forward, configure);
  70. }
  71. }