123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102 |
- using Bridge.Html5;
- using System;
- using System.Collections.Generic;
- namespace FrontendRouting
- {
- public static class FeRoutingManager
- {
- public static event EventHandler Navigated;
- private static readonly Dictionary<string, FeRoutingView> Routes = new Dictionary<string, FeRoutingView>();
- private static FeRoutingView _currentView;
- private static string _basePath;
- private static FeRoutingView _pageNoFoundView = new DefaultPageNoFoundView();
- private static Node _parentNode = Window.Document.Body;
- public static FeRoutingView PageNoFoundView
- {
- get => _pageNoFoundView;
- set => _pageNoFoundView = value ?? throw new ArgumentNullException(nameof(value));
- }
- public static Node ParentNode
- {
- get => _parentNode;
- set
- {
- _currentView?.Leave();
- _parentNode = value ?? throw new ArgumentNullException(nameof(value));
- _currentView?.Enter(_parentNode);
- }
- }
- public static void Register(string path, FeRoutingView view)
- {
- if (false == path.StartsWith("/")) throw new ArgumentException($"{nameof(path)} must starts with /", nameof(path));
- if (Routes.ContainsKey(path)) throw new ArgumentException($"Route path `{path}' already registed", nameof(path));
- Routes.Add(path, view);
- }
- public static void UnRegister(string path)
- {
- Routes.Remove(path);
- }
- public static void Run(string basePath = "/")
- {
- if (null != _basePath) throw new InvalidOperationException("Already running");
- if (false == basePath.StartsWith("/")) throw new ArgumentException($"{nameof(basePath)} must starts with /", nameof(basePath));
- _basePath = basePath;
- Go(null);
- Window.AddEventListener(EventType.PopState, Window_PopState);
- }
- private static void Window_PopState(Event arg)
- {
- if (Go(null)) return;
- arg.PreventDefault();
- Window.History.Go(1);
- }
- public static bool Go(string path, bool replace = false)
- {
- if (null != _currentView) return _currentView.BeforeLeave(() => GoInternal(path, replace));
- return GoInternal(path, replace);
- }
- private static bool GoInternal(string path, bool replace)
- {
- if (null != path)
- {
- if (replace) Window.History.ReplaceState(null, null, path);
- else Window.History.PushState(null, null, path);
- }
- var routeKey = Window.Location.PathName;
- if (routeKey.StartsWith(_basePath)) routeKey = routeKey.Substring(_basePath.Length - 1);
- var targetView = Routes.TryGetValue(routeKey, out var controller)
- ? controller
- : PageNoFoundView;
- if (targetView.BeforeEnter(_currentView))
- {
- _currentView?.Leave();
- _currentView = targetView;
- _currentView.Enter(_parentNode);
- OnNavigated();
- return true;
- }
- return false;
- }
- private static void OnNavigated()
- {
- Navigated?.Invoke(null, EventArgs.Empty);
- }
- }
- }
|