К содержимому

6. Guards и переходы ​

ISusRouteGuard — защита навигации ​

csharp
public interface ISusRouteGuard
{
    bool CanEnter(SusRoute from, SusRoute to);
    bool CanLeave(SusRoute from, SusRoute to);
}

Глобальный guard (все переходы) ​

csharp
router.BeforeEach((from, to) =>
{
    if (to.Record?.Config?.Meta?.ContainsKey("requiresAuth") == true
        && to.Record.Config.Meta["requiresAuth"] is true
        && !AuthService.IsLoggedIn)
    {
        router.Push("/login");
        return false;
    }
    return true;
});

Guard на маршрут ​

csharp
public class AdminGuard : ISusRouteGuard
{
    public bool CanEnter(SusRoute from, SusRoute to) => User.IsAdmin;
    public bool CanLeave(SusRoute from, SusRoute to) => true;
}

router.Register("/admin", typeof(AdminScreen), new SusRouteConfig
{
    Guard = new AdminGuard(),
    Meta = new() { ["requiresAuth"] = true, ["role"] = "admin" }
});

BeforeResolve — перед созданием экрана ​

csharp
router.BeforeResolve((from, to) =>
{
    if (to.FullPath == "/battle/0") return false; // invalid id
    return true;
});

Асинхронные guard'ы (BeforeEachAsync / BeforeResolveAsync) ​

Для проверок, которым нужен await (запрос к серверу, загрузка данных), доступны асинхронные guard'ы:

csharp
router.BeforeEachAsync(async (from, to) =>
{
    var ok = await AuthService.CheckSessionAsync();
    return ok;
});

router.BeforeResolveAsync(async (from, to) =>
{
    return await DataService.PreloadAsync(to.FullPath);
});

Порядок при PushAsync / ReplaceAsync:

  1. BeforeEachAsync (все, последовательно, await)
  2. BeforeResolveAsync (все, последовательно, await)
  3. синхронный конвейер (BeforeLeave → BeforeEach → CanEnter → BeforeResolve → создание экрана)

⚠️ Ограничение: синхронная навигация (Push / Replace / Back / Forward) не запускает асинхронные guard'ы — их нельзя await ить синхронно. Если асинхронные guard'ы зарегистрированы, но вызван синхронный Push, они пропускаются (Editor/Development-сборки логируют предупреждение [GuardAudit]). Для маршрутов с асинхронными проверками используйте PushAsync / ReplaceAsync.

SusRouteTransition — анимации переходов ​

API ​

csharp
public class SusRouteTransition
{
    public float Duration { get; }
    public static SusRouteTransition None();
    public static SusRouteTransition Fade(float duration = 0.2f);
    public static SusRouteTransition SlideLeft(float duration = 0.3f);
    public static SusRouteTransition SlideRight(float duration = 0.3f);

    public void PlayIn(VisualElement target);
    public void PlayOut(VisualElement target);
}

Реализация (на коде) ​

Анимации используют schedule.Execute плюс манипуляции style.opacity / style.translate:

csharp
public static SusRouteTransition Fade(float d = 0.2f) => new(
    playIn: el => { /* opacity 0 → 1 over d seconds */ },
    playOut: el => { /* opacity 1 → 0 over d seconds */ },
    duration: d
);

public static SusRouteTransition SlideLeft(float d = 0.3f) => new(
    playIn: el => { /* translate X: 100px → 0 over d seconds */ },
    playOut: el => { /* translate X: 0 → -100px over d seconds */ },
    duration: d
);

Использование ​

csharp
new SusRouteConfig { Transition = SusRouteTransition.Fade(0.2f) }
new SusRouteConfig { Transition = SusRouteTransition.SlideLeft(0.3f) }
new SusRouteConfig { Transition = SusRouteTransition.SlideRight(0.3f) }
new SusRouteConfig { Transition = SusRouteTransition.None() }

Анимации проигрываются в SusRouteView.OnRouteChanged: PlayOut на старом экране, PlayIn на новом.