Files
RpgRoller/RpgRoller/Components/Pages/WorkspaceLiveStateController.cs
2026-04-05 02:05:24 +02:00

99 lines
3.6 KiB
C#

using System.Diagnostics.CodeAnalysis;
using RpgRoller.Contracts;
namespace RpgRoller.Components.Pages;
[ExcludeFromCodeCoverage]
public sealed class WorkspaceLiveStateController(WorkspaceState state, WorkspaceFeedbackService feedback, Func<Guid, Task> startStateEventsAsync, Func<Task> stopStateEventsCoreAsync, Func<Task> refreshCampaignRosterAsync, Func<Task> refreshSelectedCharacterSheetAsync, Func<Guid?, Task> refreshCampaignLogAsync, Func<Task> requestRefreshAsync)
{
public async Task OnStateEventReceivedAsync(CampaignStateSnapshot state1)
{
if (state.StateRefreshInProgress)
return;
if (!state.SelectedCampaignId.HasValue || state1.CampaignId != state.SelectedCampaignId.Value)
return;
state.StateRefreshInProgress = true;
try
{
if (state.CurrentCampaignState is null)
{
state.CurrentCampaignState = state1;
return;
}
var previousState = state.CurrentCampaignState;
var previousSelectedCharacterId = state.SelectedCharacterId;
var previousSelectedCharacterVersion = GetCharacterVersion(previousState, previousSelectedCharacterId);
var rosterChanged = state1.RosterVersion != previousState.RosterVersion;
var logChanged = state.IsPlayScreen && state1.LogVersion != previousState.LogVersion;
if (rosterChanged)
await refreshCampaignRosterAsync();
var selectedCharacterChanged = previousSelectedCharacterId != state.SelectedCharacterId;
var selectedCharacterVersionChanged = state.IsPlayScreen && !selectedCharacterChanged && GetCharacterVersion(state1, state.SelectedCharacterId) != previousSelectedCharacterVersion;
if (state.IsPlayScreen && (selectedCharacterChanged || selectedCharacterVersionChanged))
await refreshSelectedCharacterSheetAsync();
if (logChanged)
await refreshCampaignLogAsync(state.CampaignLogCursor);
state.CurrentCampaignState = state1;
}
finally
{
state.StateRefreshInProgress = false;
await requestRefreshAsync();
}
}
public async Task OnConnectionStateChangedAsync(string state1)
{
state.ConnectionState = state1 switch
{
"connected" => "connected",
"reconnecting" => "reconnecting",
_ => "offline"
};
if (state.ConnectionState == "reconnecting")
feedback.Announce("Reconnecting to live updates.");
if (state.ConnectionState == "offline")
feedback.Announce("Live updates offline. Use manual refresh.");
await requestRefreshAsync();
}
public async Task SyncStateEventsAsync()
{
if (state.User is null || !state.SelectedCampaignId.HasValue || state.IsAdminScreen)
{
await StopStateEventsAsync();
state.ConnectionState = "offline";
return;
}
await startStateEventsAsync(state.SelectedCampaignId.Value);
state.ConnectionState = "reconnecting";
}
public async Task StopStateEventsAsync()
{
if (!state.HasInteractiveRenderStarted)
return;
await stopStateEventsCoreAsync();
}
private static long GetCharacterVersion(CampaignStateSnapshot snapshot, Guid? characterId)
{
if (!characterId.HasValue)
return 0;
return snapshot.CharacterVersions.FirstOrDefault(version => version.CharacterId == characterId.Value)?.Version ?? 0;
}
}