Extract workspace session coordinator
This commit is contained in:
@@ -16,114 +16,18 @@ public partial class Workspace : IAsyncDisposable
|
||||
if (!firstRender)
|
||||
return;
|
||||
|
||||
await InitializeAsync();
|
||||
await Session.InitializeAsync();
|
||||
await InvokeAsync(StateHasChanged);
|
||||
}
|
||||
|
||||
private async Task InitializeAsync()
|
||||
private Task RetryAfterHealthIssueAsync()
|
||||
{
|
||||
var storedScreen = await JS.InvokeAsync<string?>("rpgRollerApi.getSessionValue", ScreenSessionKey);
|
||||
CurrentScreen = NormalizeRequestedScreen(storedScreen) ?? ScreenPlay;
|
||||
|
||||
var storedPanel = await JS.InvokeAsync<string?>("rpgRollerApi.getSessionValue", MobilePanelSessionKey);
|
||||
if (string.Equals(storedPanel, "log", StringComparison.OrdinalIgnoreCase))
|
||||
MobilePanel = "log";
|
||||
|
||||
var storedRollVisibility = await JS.InvokeAsync<string?>("rpgRollerApi.getSessionValue", RollVisibilitySessionKey);
|
||||
RollVisibility = NormalizeRollVisibility(storedRollVisibility);
|
||||
|
||||
Guid? preferredCampaignId = null;
|
||||
var storedCampaignId = await JS.InvokeAsync<string?>("rpgRollerApi.getSessionValue", CampaignSessionKey);
|
||||
if (Guid.TryParse(storedCampaignId, out var parsedCampaignId))
|
||||
preferredCampaignId = parsedCampaignId;
|
||||
|
||||
await CheckHealthAsync();
|
||||
await LoadRulesetsAsync();
|
||||
|
||||
var reloaded = await ReloadAuthenticatedSessionAsync(preferredCampaignId);
|
||||
if (!reloaded)
|
||||
await LoggedOut.InvokeAsync("Session expired. Please log in again.");
|
||||
return Session.RetryAfterHealthIssueAsync();
|
||||
}
|
||||
|
||||
private async Task RetryAfterHealthIssueAsync()
|
||||
private Task LoadKnownUsernamesAsync()
|
||||
{
|
||||
await CheckHealthAsync();
|
||||
if (!HasHealthIssue && User is not null)
|
||||
{
|
||||
var reloaded = await ReloadAuthenticatedSessionAsync(SelectedCampaignId);
|
||||
if (!reloaded)
|
||||
await LoggedOut.InvokeAsync("Session expired. Please log in again.");
|
||||
}
|
||||
}
|
||||
|
||||
private async Task CheckHealthAsync()
|
||||
{
|
||||
HasHealthIssue = false;
|
||||
HealthIssueMessage = string.Empty;
|
||||
await Task.CompletedTask;
|
||||
}
|
||||
|
||||
private async Task LoadRulesetsAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
Rulesets = (await WorkspaceQuery.GetRulesetsAsync()).ToList();
|
||||
}
|
||||
catch (ApiRequestException ex)
|
||||
{
|
||||
SetStatus(ex.Message, true);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task LoadKnownUsernamesAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
var usernames = await WorkspaceQuery.GetUsernamesAsync();
|
||||
KnownUsernames = usernames.OrderBy(username => username, StringComparer.OrdinalIgnoreCase).ToList();
|
||||
}
|
||||
catch (ApiRequestException ex)
|
||||
{
|
||||
KnownUsernames = [];
|
||||
SetStatus(ex.Message, true);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<bool> ReloadAuthenticatedSessionAsync(Guid? preferredCampaignId)
|
||||
{
|
||||
var me = await TryGetMeAsync();
|
||||
if (me is null)
|
||||
{
|
||||
ClearAuthenticatedState();
|
||||
await StopStateEventsAsync();
|
||||
return false;
|
||||
}
|
||||
|
||||
User = me.User;
|
||||
ActiveCharacterId = me.ActiveCharacterId;
|
||||
await EnsureScreenAccessAsync();
|
||||
|
||||
await ReloadCampaignsAsync(preferredCampaignId ?? me.CurrentCampaignId);
|
||||
await ReloadCharacterCampaignOptionsAsync();
|
||||
await RefreshCampaignScopeAsync();
|
||||
await SyncStateEventsAsync();
|
||||
|
||||
if (IsAdminScreen)
|
||||
await EnsureAdminUsersLoadedAsync();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private async Task<MeResponse?> TryGetMeAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
return await WorkspaceQuery.GetMeAsync();
|
||||
}
|
||||
catch (ApiRequestException ex) when (ex.StatusCode == 401)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return Session.LoadKnownUsernamesAsync();
|
||||
}
|
||||
|
||||
private async Task ReloadCampaignsAsync(Guid? preferredCampaignId)
|
||||
@@ -263,52 +167,9 @@ public partial class Workspace : IAsyncDisposable
|
||||
}
|
||||
}
|
||||
|
||||
private async Task LogoutAsync()
|
||||
{
|
||||
if (IsMutating)
|
||||
return;
|
||||
private Task LogoutAsync() => Session.LogoutAsync();
|
||||
|
||||
IsMutating = true;
|
||||
try
|
||||
{
|
||||
await ApiClient.RequestWithoutPayloadAsync("POST", "/api/auth/logout");
|
||||
}
|
||||
catch (ApiRequestException)
|
||||
{
|
||||
}
|
||||
finally
|
||||
{
|
||||
IsMutating = false;
|
||||
}
|
||||
|
||||
ClearAuthenticatedState();
|
||||
await StopStateEventsAsync();
|
||||
await LoggedOut.InvokeAsync("Logged out.");
|
||||
}
|
||||
|
||||
private async Task SwitchScreenAsync(string screen)
|
||||
{
|
||||
var targetScreen = NormalizeRequestedScreen(screen) ?? ScreenPlay;
|
||||
if (string.Equals(targetScreen, ScreenAdmin, StringComparison.OrdinalIgnoreCase) && !IsCurrentUserAdmin)
|
||||
targetScreen = ScreenPlay;
|
||||
|
||||
CurrentScreen = targetScreen;
|
||||
IsScreenMenuOpen = false;
|
||||
await PersistScreenPreferenceAsync(CurrentScreen);
|
||||
await InvokeAsync(StateHasChanged);
|
||||
|
||||
if (User is not null)
|
||||
{
|
||||
await RefreshCampaignScopeAsync();
|
||||
await SyncStateEventsAsync();
|
||||
}
|
||||
|
||||
if (IsAdminScreen)
|
||||
{
|
||||
await EnsureAdminUsersLoadedAsync();
|
||||
await InvokeAsync(StateHasChanged);
|
||||
}
|
||||
}
|
||||
private Task SwitchScreenAsync(string screen) => Session.SwitchScreenAsync(screen);
|
||||
|
||||
private Task SwitchToPlayAsync()
|
||||
{
|
||||
@@ -325,21 +186,6 @@ public partial class Workspace : IAsyncDisposable
|
||||
return SwitchScreenAsync(ScreenAdmin);
|
||||
}
|
||||
|
||||
private async Task EnsureScreenAccessAsync()
|
||||
{
|
||||
if (IsCurrentUserAdmin)
|
||||
return;
|
||||
|
||||
AdminUsers = [];
|
||||
HasLoadedAdminUsers = false;
|
||||
|
||||
if (!IsAdminScreen)
|
||||
return;
|
||||
|
||||
CurrentScreen = ScreenPlay;
|
||||
await PersistScreenPreferenceAsync(CurrentScreen);
|
||||
}
|
||||
|
||||
private async Task EnsureAdminUsersLoadedAsync()
|
||||
{
|
||||
if (!IsCurrentUserAdmin || HasLoadedAdminUsers || IsAdminDataLoading)
|
||||
@@ -762,44 +608,7 @@ public partial class Workspace : IAsyncDisposable
|
||||
Announce("Roll result updated.");
|
||||
}
|
||||
|
||||
private async Task OnRollVisibilityChanged(string visibility)
|
||||
{
|
||||
RollVisibility = NormalizeRollVisibility(visibility);
|
||||
await JS.InvokeVoidAsync("rpgRollerApi.setSessionValue", RollVisibilitySessionKey, RollVisibility);
|
||||
}
|
||||
|
||||
private static string NormalizeRollVisibility(string? visibility)
|
||||
{
|
||||
return string.Equals(visibility, "private", StringComparison.OrdinalIgnoreCase) ? "private" : "public";
|
||||
}
|
||||
|
||||
private static string? NormalizeRequestedScreen(string? screen)
|
||||
{
|
||||
if (string.Equals(screen, ScreenAdmin, StringComparison.OrdinalIgnoreCase))
|
||||
return ScreenAdmin;
|
||||
|
||||
if (string.Equals(screen, "management", StringComparison.OrdinalIgnoreCase))
|
||||
return "management";
|
||||
|
||||
if (string.Equals(screen, ScreenPlay, StringComparison.OrdinalIgnoreCase))
|
||||
return ScreenPlay;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private async Task PersistScreenPreferenceAsync(string screen)
|
||||
{
|
||||
try
|
||||
{
|
||||
await JS.InvokeVoidAsync("rpgRollerApi.setSessionValue", ScreenSessionKey, screen);
|
||||
}
|
||||
catch (JSDisconnectedException)
|
||||
{
|
||||
}
|
||||
catch (InvalidOperationException ex) when (IsStaticRenderInteropException(ex))
|
||||
{
|
||||
}
|
||||
}
|
||||
private Task OnRollVisibilityChanged(string visibility) => Session.OnRollVisibilityChangedAsync(visibility);
|
||||
|
||||
private bool CanEditSkill(CharacterSheetSkill skill)
|
||||
{
|
||||
@@ -1051,34 +860,7 @@ public partial class Workspace : IAsyncDisposable
|
||||
FreshCampaignLogRollId = rollId;
|
||||
}
|
||||
|
||||
private void ClearAuthenticatedState()
|
||||
{
|
||||
User = null;
|
||||
ActiveCharacterId = null;
|
||||
SelectedCampaignId = null;
|
||||
SelectedCampaign = null;
|
||||
Campaigns = [];
|
||||
CharacterCampaignOptions = [];
|
||||
SelectedCharacterSkills = [];
|
||||
SelectedCharacterSkillGroups = [];
|
||||
CampaignLog = [];
|
||||
CampaignLogCursor = null;
|
||||
ResetCampaignLogDetailState();
|
||||
SelectedCharacterId = null;
|
||||
LastRoll = null;
|
||||
KnownUsernames = [];
|
||||
ShowCreateCharacterModal = false;
|
||||
ShowEditCharacterModal = false;
|
||||
CanEditCharacterOwner = false;
|
||||
CreateCharacterInitialModel = new();
|
||||
EditCharacterInitialModel = new();
|
||||
CreateCharacterFormVersion = 0;
|
||||
EditCharacterFormVersion = 0;
|
||||
AdminUsers = [];
|
||||
HasLoadedAdminUsers = false;
|
||||
IsAdminDataLoading = false;
|
||||
Feedback.ClearToasts();
|
||||
}
|
||||
private void ClearAuthenticatedState() => Session.ClearAuthenticatedState();
|
||||
|
||||
private void SetStatus(string message, bool isError)
|
||||
{
|
||||
@@ -1197,6 +979,21 @@ public partial class Workspace : IAsyncDisposable
|
||||
private bool IsManagementScreen => State.IsManagementScreen;
|
||||
private bool IsAdminScreen => State.IsAdminScreen;
|
||||
private WorkspaceFeedbackService Feedback => m_Feedback ??= new(State, () => InvokeAsync(StateHasChanged));
|
||||
private WorkspaceSessionCoordinator Session => m_Session ??= new(
|
||||
State,
|
||||
Feedback,
|
||||
JS,
|
||||
ApiClient,
|
||||
WorkspaceQuery,
|
||||
ReloadCampaignsAsync,
|
||||
ReloadCharacterCampaignOptionsAsync,
|
||||
RefreshCampaignScopeAsync,
|
||||
SyncStateEventsAsync,
|
||||
StopStateEventsAsync,
|
||||
EnsureAdminUsersLoadedAsync,
|
||||
ResetCampaignLogDetailState,
|
||||
() => InvokeAsync(StateHasChanged),
|
||||
message => LoggedOut.InvokeAsync(message));
|
||||
private IReadOnlyList<AppHeaderMenuItem> HeaderMenuItems
|
||||
{
|
||||
get
|
||||
@@ -1219,14 +1016,11 @@ public partial class Workspace : IAsyncDisposable
|
||||
private string AppCssClass => State.AppCssClass;
|
||||
private string AdminDatabaseDownloadUrl => Navigation.ToAbsoluteUri("api/admin/database").ToString();
|
||||
|
||||
private const string ScreenPlay = "play";
|
||||
private const string ScreenManagement = "management";
|
||||
private const string ScreenAdmin = "admin";
|
||||
private const string ScreenSessionKey = "screen";
|
||||
private const string CampaignSessionKey = "campaign";
|
||||
private const string MobilePanelSessionKey = "play-panel";
|
||||
private const string RollVisibilitySessionKey = "roll-visibility";
|
||||
private const int CampaignLogWindowSize = 25;
|
||||
|
||||
private WorkspaceFeedbackService? m_Feedback;
|
||||
private WorkspaceSessionCoordinator? m_Session;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user