Files
RpgRoller/RpgRoller/Components/Pages/Workspace.razor.cs
2026-04-05 01:40:26 +02:00

167 lines
6.0 KiB
C#

using System.Diagnostics.CodeAnalysis;
using Microsoft.AspNetCore.Components;
using Microsoft.JSInterop;
using RpgRoller.Components.Pages.HomeControls;
using RpgRoller.Contracts;
namespace RpgRoller.Components.Pages;
[ExcludeFromCodeCoverage]
public partial class Workspace : IAsyncDisposable
{
protected override async Task OnAfterRenderAsync(bool firstRender)
{
State.HasInteractiveRenderStarted = true;
if (!firstRender)
return;
await Session.InitializeAsync();
await InvokeAsync(StateHasChanged);
}
[JSInvokable]
public Task OnStateEventReceived(CampaignStateSnapshot state)
{
return Live.OnStateEventReceivedAsync(state);
}
[JSInvokable]
public Task OnConnectionStateChanged(string state)
{
return Live.OnConnectionStateChangedAsync(state);
}
public async ValueTask DisposeAsync()
{
await StopStateEventsAsync();
DotNetRef?.Dispose();
}
private bool CanEditCharacter(CharacterSummary character)
{
return Campaigns.CanEditCharacter(character);
}
private void ClearAuthenticatedState()
{
Session.ClearAuthenticatedState();
}
private Task EnsureAdminUsersLoadedAsync()
{
return Admin.EnsureAdminUsersLoadedAsync();
}
private Task StopStateEventsAsync()
{
return Live.StopStateEventsAsync();
}
private async Task StartStateEventsCoreAsync(Guid campaignId)
{
DotNetRef ??= DotNetObjectReference.Create(this);
await JS.InvokeVoidAsync("rpgRollerApi.startStateEvents", campaignId.ToString(), DotNetRef);
}
private async Task StopStateEventsCoreAsync()
{
try
{
await JS.InvokeVoidAsync("rpgRollerApi.stopStateEvents");
}
catch (JSDisconnectedException)
{
}
catch (InvalidOperationException ex) when (IsStaticRenderInteropException(ex))
{
}
}
private void ToggleScreenMenu()
{
State.IsScreenMenuOpen = !State.IsScreenMenuOpen;
}
private static bool IsStaticRenderInteropException(InvalidOperationException exception)
{
return exception.Message.Contains("statically rendered", StringComparison.OrdinalIgnoreCase);
}
[Inject]
private IJSRuntime JS { get; set; } = null!;
[Inject]
private RpgRollerApiClient ApiClient { get; set; } = null!;
[Inject]
private WorkspaceQueryService WorkspaceQuery { get; set; } = null!;
[Inject]
private NavigationManager Navigation { get; set; } = null!;
[Parameter]
public EventCallback<string?> LoggedOut { get; set; }
private WorkspaceState State { get; } = new();
private WorkspaceCampaignScopeCoordinator Scope => m_Scope ??= new(State, Feedback, JS, WorkspaceQuery, Play.EnsureSelectedCharacterActiveAsync, Play.RefreshSelectedCharacterSheetAsync, Play.RefreshCampaignLogAsync, Play.ResetCampaignLogDetailState, Play.ResetCampaignStateTracking, ClearAuthenticatedState, StopStateEventsAsync, message => LoggedOut.InvokeAsync(message));
private WorkspaceLiveStateController Live => m_Live ??= new(State, Feedback, StartStateEventsCoreAsync, StopStateEventsCoreAsync, Scope.RefreshCampaignRosterAsync, Play.RefreshSelectedCharacterSheetAsync, Play.RefreshCampaignLogAsync, () => InvokeAsync(StateHasChanged));
private WorkspacePlayCoordinator Play => m_Play ??= new(State, Feedback, ApiClient, WorkspaceQuery, CanEditCharacter, () => InvokeAsync(StateHasChanged));
private WorkspaceCampaignCoordinator Campaigns => m_Campaigns ??= new(State, Feedback, JS, ApiClient, Session.LoadKnownUsernamesAsync, Scope.ReloadCampaignsAsync, Scope.ReloadCharacterCampaignOptionsAsync, Scope.RefreshCampaignScopeAsync, Live.SyncStateEventsAsync);
private WorkspaceAdminCoordinator Admin => m_Admin ??= new(State, Feedback, JS, ApiClient, WorkspaceQuery, ClearAuthenticatedState, StopStateEventsAsync, message => LoggedOut.InvokeAsync(message));
private WorkspaceFeedbackService Feedback => m_Feedback ??= new(State, () => InvokeAsync(StateHasChanged));
private WorkspaceSessionCoordinator Session => m_Session ??= new(State, Feedback, JS, ApiClient, WorkspaceQuery, Scope.ReloadCampaignsAsync, Scope.ReloadCharacterCampaignOptionsAsync, Scope.RefreshCampaignScopeAsync, Live.SyncStateEventsAsync, Live.StopStateEventsAsync, EnsureAdminUsersLoadedAsync, Play.ResetCampaignLogDetailState, () => InvokeAsync(StateHasChanged), message => LoggedOut.InvokeAsync(message));
private IReadOnlyList<AppHeaderMenuItem> HeaderMenuItems
{
get
{
var items = new List<AppHeaderMenuItem>
{
new()
{
Label = "Play",
IsActive = State.IsPlayScreen,
OnSelected = () => Session.SwitchScreenAsync("play")
},
new()
{
Label = "Campaign Management",
IsActive = State.IsManagementScreen,
OnSelected = () => Session.SwitchScreenAsync("management")
}
};
if (State.IsCurrentUserAdmin)
{
items.Add(new()
{
Label = "Admin",
IsActive = State.IsAdminScreen,
OnSelected = () => Session.SwitchScreenAsync(ScreenAdmin)
});
}
return items;
}
}
private string AdminDatabaseDownloadUrl => Navigation.ToAbsoluteUri("api/admin/database").ToString();
private DotNetObjectReference<Workspace>? DotNetRef { get; set; }
private const string ScreenAdmin = "admin";
private WorkspaceAdminCoordinator? m_Admin;
private WorkspaceCampaignCoordinator? m_Campaigns;
private WorkspaceFeedbackService? m_Feedback;
private WorkspaceLiveStateController? m_Live;
private WorkspacePlayCoordinator? m_Play;
private WorkspaceCampaignScopeCoordinator? m_Scope;
private WorkspaceSessionCoordinator? m_Session;
}