Extract workspace live state controller
This commit is contained in:
@@ -213,90 +213,29 @@ public partial class Workspace : IAsyncDisposable
|
||||
private bool CanEditSkill(CharacterSheetSkill skill) => Play.CanEditSkill(skill);
|
||||
|
||||
[JSInvokable]
|
||||
public async Task OnStateEventReceived(CampaignStateSnapshot state)
|
||||
{
|
||||
if (StateRefreshInProgress)
|
||||
return;
|
||||
|
||||
if (!SelectedCampaignId.HasValue || state.CampaignId != SelectedCampaignId.Value)
|
||||
return;
|
||||
|
||||
StateRefreshInProgress = true;
|
||||
try
|
||||
{
|
||||
if (CurrentCampaignState is null)
|
||||
{
|
||||
CurrentCampaignState = state;
|
||||
return;
|
||||
}
|
||||
|
||||
var previousState = CurrentCampaignState;
|
||||
var previousSelectedCharacterId = SelectedCharacterId;
|
||||
var previousSelectedCharacterVersion = GetCharacterVersion(previousState, previousSelectedCharacterId);
|
||||
var rosterChanged = state.RosterVersion != previousState.RosterVersion;
|
||||
var logChanged = IsPlayScreen && state.LogVersion != previousState.LogVersion;
|
||||
|
||||
if (rosterChanged)
|
||||
await RefreshCampaignRosterAsync();
|
||||
|
||||
var selectedCharacterChanged = previousSelectedCharacterId != SelectedCharacterId;
|
||||
var selectedCharacterVersionChanged = IsPlayScreen &&
|
||||
!selectedCharacterChanged &&
|
||||
GetCharacterVersion(state, SelectedCharacterId) != previousSelectedCharacterVersion;
|
||||
|
||||
if (IsPlayScreen && (selectedCharacterChanged || selectedCharacterVersionChanged))
|
||||
await RefreshSelectedCharacterSheetAsync();
|
||||
|
||||
if (logChanged)
|
||||
await RefreshCampaignLogAsync(CampaignLogCursor);
|
||||
|
||||
CurrentCampaignState = state;
|
||||
}
|
||||
finally
|
||||
{
|
||||
StateRefreshInProgress = false;
|
||||
await InvokeAsync(StateHasChanged);
|
||||
}
|
||||
}
|
||||
public Task OnStateEventReceived(CampaignStateSnapshot state) => Live.OnStateEventReceivedAsync(state);
|
||||
|
||||
[JSInvokable]
|
||||
public Task OnConnectionStateChanged(string state)
|
||||
public Task OnConnectionStateChanged(string state) => Live.OnConnectionStateChangedAsync(state);
|
||||
|
||||
private Task SyncStateEventsAsync() => Live.SyncStateEventsAsync();
|
||||
|
||||
private Task StopStateEventsAsync() => Live.StopStateEventsAsync();
|
||||
|
||||
public async ValueTask DisposeAsync()
|
||||
{
|
||||
ConnectionState = state switch
|
||||
{
|
||||
"connected" => "connected",
|
||||
"reconnecting" => "reconnecting",
|
||||
_ => "offline"
|
||||
};
|
||||
|
||||
if (ConnectionState == "reconnecting")
|
||||
Announce("Reconnecting to live updates.");
|
||||
|
||||
if (ConnectionState == "offline")
|
||||
Announce("Live updates offline. Use manual refresh.");
|
||||
|
||||
return InvokeAsync(StateHasChanged);
|
||||
await StopStateEventsAsync();
|
||||
DotNetRef?.Dispose();
|
||||
}
|
||||
|
||||
private async Task SyncStateEventsAsync()
|
||||
private async Task StartStateEventsCoreAsync(Guid campaignId)
|
||||
{
|
||||
if (User is null || !SelectedCampaignId.HasValue || IsAdminScreen)
|
||||
{
|
||||
await StopStateEventsAsync();
|
||||
ConnectionState = "offline";
|
||||
return;
|
||||
}
|
||||
|
||||
DotNetRef ??= DotNetObjectReference.Create(this);
|
||||
await JS.InvokeVoidAsync("rpgRollerApi.startStateEvents", SelectedCampaignId.Value.ToString(), DotNetRef);
|
||||
ConnectionState = "reconnecting";
|
||||
await JS.InvokeVoidAsync("rpgRollerApi.startStateEvents", campaignId.ToString(), DotNetRef);
|
||||
}
|
||||
|
||||
private async Task StopStateEventsAsync()
|
||||
private async Task StopStateEventsCoreAsync()
|
||||
{
|
||||
if (!HasInteractiveRenderStarted)
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
await JS.InvokeVoidAsync("rpgRollerApi.stopStateEvents");
|
||||
@@ -309,12 +248,6 @@ public partial class Workspace : IAsyncDisposable
|
||||
}
|
||||
}
|
||||
|
||||
public async ValueTask DisposeAsync()
|
||||
{
|
||||
await StopStateEventsAsync();
|
||||
DotNetRef?.Dispose();
|
||||
}
|
||||
|
||||
private static bool IsStaticRenderInteropException(InvalidOperationException exception)
|
||||
{
|
||||
return exception.Message.Contains("statically rendered", StringComparison.OrdinalIgnoreCase);
|
||||
@@ -401,16 +334,6 @@ public partial class Workspace : IAsyncDisposable
|
||||
|
||||
private void ResetCampaignStateTracking() => Play.ResetCampaignStateTracking();
|
||||
|
||||
private static long GetCharacterVersion(CampaignStateSnapshot snapshot, Guid? characterId)
|
||||
{
|
||||
if (!characterId.HasValue)
|
||||
return 0;
|
||||
|
||||
return snapshot.CharacterVersions
|
||||
.FirstOrDefault(version => version.CharacterId == characterId.Value)
|
||||
?.Version ?? 0;
|
||||
}
|
||||
|
||||
[Inject]
|
||||
private IJSRuntime JS { get; set; } = null!;
|
||||
|
||||
@@ -492,6 +415,15 @@ public partial class Workspace : IAsyncDisposable
|
||||
private bool IsPlayScreen => State.IsPlayScreen;
|
||||
private bool IsManagementScreen => State.IsManagementScreen;
|
||||
private bool IsAdminScreen => State.IsAdminScreen;
|
||||
private WorkspaceLiveStateController Live => m_Live ??= new(
|
||||
State,
|
||||
Feedback,
|
||||
StartStateEventsCoreAsync,
|
||||
StopStateEventsCoreAsync,
|
||||
RefreshCampaignRosterAsync,
|
||||
RefreshSelectedCharacterSheetAsync,
|
||||
RefreshCampaignLogAsync,
|
||||
() => InvokeAsync(StateHasChanged));
|
||||
private WorkspacePlayCoordinator Play => m_Play ??= new(
|
||||
State,
|
||||
Feedback,
|
||||
@@ -561,6 +493,7 @@ public partial class Workspace : IAsyncDisposable
|
||||
private const string MobilePanelSessionKey = "play-panel";
|
||||
private const int CampaignLogWindowSize = 25;
|
||||
|
||||
private WorkspaceLiveStateController? m_Live;
|
||||
private WorkspacePlayCoordinator? m_Play;
|
||||
private WorkspaceCampaignCoordinator? m_CampaignsFlow;
|
||||
private WorkspaceAdminCoordinator? m_Admin;
|
||||
|
||||
Reference in New Issue
Block a user