@using Shogi.Contracts.Api @using Shogi.Contracts.Types @using System.Text.RegularExpressions @using System.Security.Claims @implements IDisposable @inject ShogiApi ShogiApi @inject GameHubNode hubNode @inject NavigationManager navigator @if (session == null) { } else if (isSpectating) { } else { } @code { [CascadingParameter] private Task authenticationState { get; set; } = default!; [Parameter] [EditorRequired] public string SessionId { get; set; } = string.Empty; Session? session; private WhichPlayer perspective; private bool isSpectating; private List disposables = new List(2); protected override void OnInitialized() { navigator.RegisterLocationChangingHandler((a) => new ValueTask(hubNode.Unsubscribe(SessionId))); disposables.Add(hubNode.OnSessionJoined(async () => await FetchSession())); disposables.Add(hubNode.OnPieceMoved(async () => await FetchSession())); } protected override async Task OnParametersSetAsync() { await hubNode.Subscribe(SessionId); await FetchSession(); } async Task FetchSession() { if (!string.IsNullOrWhiteSpace(SessionId)) { this.session = await ShogiApi.GetSession(SessionId); if (this.session != null) { var state = await authenticationState; var accountId = state.User.Claims.First(c => c.Type == ClaimTypes.Name).Value; this.perspective = accountId == session.Player1 ? WhichPlayer.Player1 : WhichPlayer.Player2; this.isSpectating = !(accountId == this.session.Player1 || accountId == this.session.Player2); } StateHasChanged(); } } public void Dispose() { foreach (var d in disposables) { d.Dispose(); } disposables.Clear(); } }