Replace custom socket implementation with SignalR.

Replace MSAL and custom cookie auth with Microsoft.Identity.EntityFramework
Also some UI redesign to accommodate different login experience.
This commit is contained in:
2024-08-25 03:46:44 +00:00
parent d688afaeae
commit 51d234d871
172 changed files with 3857 additions and 4045 deletions

View File

@@ -0,0 +1,128 @@
@using Shogi.Contracts.Api;
@using Shogi.Contracts.Types;
@using System.Text.RegularExpressions;
@using System.Net;
@inject PromotePrompt PromotePrompt;
@inject ShogiApi ShogiApi;
<GameBoardPresentation Session="Session"
Perspective="Perspective"
OnClickHand="OnClickHand"
OnClickTile="OnClickTile"
SelectedPosition="@selectedBoardPosition"
SelectedPieceFromHand="@selectedPieceFromHand"
IsMyTurn="IsMyTurn" />
@code {
[Parameter, EditorRequired]
public WhichPlayer Perspective { get; set; }
[Parameter, EditorRequired]
public Session Session { get; set; } = default!;
private bool IsMyTurn => Session?.BoardState.WhoseTurn == Perspective;
private string? selectedBoardPosition;
private WhichPiece? selectedPieceFromHand;
protected override void OnParametersSet()
{
base.OnParametersSet();
selectedBoardPosition = null;
selectedPieceFromHand = null;
if (Session == null)
{
throw new ArgumentException($"{nameof(Session)} cannot be null.", nameof(Session));
}
}
bool ShouldPromptForPromotion(string position)
{
if (Perspective == WhichPlayer.Player1 && Regex.IsMatch(position, ".[7-9]"))
{
return true;
}
if (Perspective == WhichPlayer.Player2 && Regex.IsMatch(position, ".[1-3]"))
{
return true;
}
return false;
}
async Task OnClickTile(Piece? pieceAtPosition, string position)
{
if (!IsMyTurn) return;
if (selectedBoardPosition == position)
{
// Deselect the selected position.
selectedBoardPosition = null;
StateHasChanged();
return;
}
if (selectedBoardPosition == null && pieceAtPosition?.Owner == Perspective)
{
// Select an owned piece.
selectedBoardPosition = position;
// Prevent selecting pieces from the hand and board at the same time.
selectedPieceFromHand = null;
StateHasChanged();
return;
}
if (selectedPieceFromHand is not null)
{
if (pieceAtPosition is null)
{
// Placing a piece from the hand to an empty space.
var success = await ShogiApi.Move(
Session.SessionId.ToString(),
new MovePieceCommand(selectedPieceFromHand.Value, position));
if (!success)
{
selectedPieceFromHand = null;
}
}
StateHasChanged();
return;
}
if (selectedBoardPosition != null)
{
if (pieceAtPosition == null || pieceAtPosition?.Owner != Perspective)
{
// Moving to an empty space or capturing an opponent's piece.
if (ShouldPromptForPromotion(position) || ShouldPromptForPromotion(selectedBoardPosition))
{
PromotePrompt.Show(
Session.SessionId.ToString(),
new MovePieceCommand(selectedBoardPosition, position, false));
}
else
{
var success = await ShogiApi.Move(Session.SessionId.ToString(), new MovePieceCommand(selectedBoardPosition, position, false));
if (!success)
{
selectedBoardPosition = null;
}
}
StateHasChanged();
return;
}
}
}
async Task OnClickHand(Piece piece)
{
if (!IsMyTurn) return;
// Prevent selecting from both the hand and the board.
selectedBoardPosition = null;
selectedPieceFromHand = piece.WhichPiece == selectedPieceFromHand
// Deselecting the already-selected piece
? selectedPieceFromHand = null
: selectedPieceFromHand = piece.WhichPiece;
StateHasChanged();
}
}