Add shared table context state
This commit is contained in:
@@ -5,11 +5,10 @@
|
||||
@using System.Diagnostics.CodeAnalysis
|
||||
@using System.Linq
|
||||
@inject NavigationManager NavigationManager
|
||||
@inject IJSRuntime JSRuntime
|
||||
@inject LookupService LookupService
|
||||
@inject RolemasterDb.App.Frontend.AppState.PinnedTablesState PinnedTablesState
|
||||
@inject RolemasterDb.App.Frontend.AppState.RecentTablesState RecentTablesState
|
||||
@inject RolemasterDb.App.Frontend.AppState.TableContextUrlSerializer TableContextUrlSerializer
|
||||
@inject RolemasterDb.App.Frontend.AppState.TableContextState TableContextState
|
||||
|
||||
<PageTitle>Critical Tables</PageTitle>
|
||||
|
||||
@@ -82,6 +81,10 @@
|
||||
{
|
||||
<p class="muted">No critical tables are available yet.</p>
|
||||
}
|
||||
else if (!hasResolvedStoredTableSelection)
|
||||
{
|
||||
<p class="muted">Restoring table context...</p>
|
||||
}
|
||||
else if (isDetailLoading)
|
||||
{
|
||||
<p class="muted">Loading the selected table...</p>
|
||||
@@ -227,7 +230,7 @@
|
||||
}
|
||||
|
||||
@code {
|
||||
private const string SelectedTableStorageKey = "rolemaster.tables.selectedTable";
|
||||
private const string ContextDestination = "tables";
|
||||
private LookupReferenceData? referenceData;
|
||||
private CriticalTableDetail? tableDetail;
|
||||
private string selectedTableSlug = string.Empty;
|
||||
@@ -285,9 +288,8 @@
|
||||
{
|
||||
selectedTableSlug = tableSlug;
|
||||
isTableMenuOpen = false;
|
||||
await PersistSelectedTableAsync(tableSlug);
|
||||
await LoadTableDetailAsync();
|
||||
SyncTableContextUrl();
|
||||
await PersistAndSyncTableContextAsync();
|
||||
}
|
||||
|
||||
private async Task LoadTableDetailAsync()
|
||||
@@ -336,35 +338,26 @@
|
||||
|
||||
if (!hasResolvedStoredTableSelection && referenceData?.CriticalTables.Count > 0)
|
||||
{
|
||||
try
|
||||
var initialContext = await TableContextState.RestoreAsync(
|
||||
NavigationManager.Uri,
|
||||
ContextDestination,
|
||||
referenceData.CriticalTables,
|
||||
RolemasterDb.App.Frontend.AppState.TableContextMode.Reference);
|
||||
|
||||
hasResolvedStoredTableSelection = true;
|
||||
|
||||
var resolvedTableSlug = initialContext.TableSlug ?? string.Empty;
|
||||
if (string.IsNullOrWhiteSpace(selectedTableSlug) ||
|
||||
!string.Equals(resolvedTableSlug, selectedTableSlug, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
var routeContext = TableContextUrlSerializer.Parse(NavigationManager.Uri);
|
||||
var storedTableSlug = await JSRuntime.InvokeAsync<string?>("localStorage.getItem", SelectedTableStorageKey);
|
||||
hasResolvedStoredTableSelection = true;
|
||||
|
||||
var resolvedTableSlug = ResolveSelectedTableSlug(routeContext.TableSlug ?? storedTableSlug);
|
||||
if (string.IsNullOrWhiteSpace(selectedTableSlug) ||
|
||||
!string.Equals(resolvedTableSlug, selectedTableSlug, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
selectedTableSlug = resolvedTableSlug;
|
||||
await LoadTableDetailAsync();
|
||||
await PersistSelectedTableAsync(selectedTableSlug);
|
||||
SyncTableContextUrl();
|
||||
await InvokeAsync(StateHasChanged);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!string.Equals(storedTableSlug, selectedTableSlug, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
await PersistSelectedTableAsync(selectedTableSlug);
|
||||
}
|
||||
|
||||
SyncTableContextUrl();
|
||||
}
|
||||
catch (InvalidOperationException)
|
||||
{
|
||||
// During prerender localStorage is unavailable. Retry after interactive render.
|
||||
selectedTableSlug = resolvedTableSlug;
|
||||
await LoadTableDetailAsync();
|
||||
await PersistAndSyncTableContextAsync();
|
||||
await InvokeAsync(StateHasChanged);
|
||||
return;
|
||||
}
|
||||
|
||||
await PersistAndSyncTableContextAsync();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -781,46 +774,6 @@
|
||||
private string GetSelectedTableLabel() =>
|
||||
SelectedTableReference?.Label ?? "Select a table";
|
||||
|
||||
private string ResolveSelectedTableSlug(string? storedTableSlug)
|
||||
{
|
||||
if (referenceData is null || referenceData.CriticalTables.Count == 0)
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(storedTableSlug) &&
|
||||
referenceData.CriticalTables.Any(item => string.Equals(item.Key, storedTableSlug, StringComparison.OrdinalIgnoreCase)))
|
||||
{
|
||||
return storedTableSlug;
|
||||
}
|
||||
|
||||
return referenceData.CriticalTables.First().Key;
|
||||
}
|
||||
|
||||
private Task PersistSelectedTableAsync(string tableSlug) =>
|
||||
JSRuntime.InvokeVoidAsync("localStorage.setItem", SelectedTableStorageKey, tableSlug).AsTask();
|
||||
|
||||
private void SyncTableContextUrl()
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(selectedTableSlug))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var targetUri = TableContextUrlSerializer.BuildRelativeUri(
|
||||
"/tables",
|
||||
new RolemasterDb.App.Frontend.AppState.TableContextSnapshot(
|
||||
TableSlug: selectedTableSlug,
|
||||
Mode: RolemasterDb.App.Frontend.AppState.TableContextMode.Reference));
|
||||
|
||||
if (string.Equals(NavigationManager.ToBaseRelativePath(NavigationManager.Uri), targetUri.TrimStart('/'), StringComparison.Ordinal))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
NavigationManager.NavigateTo(targetUri, replace: true);
|
||||
}
|
||||
|
||||
private Task TogglePinnedTableAsync()
|
||||
{
|
||||
if (SelectedTableReference is not { } selectedTable)
|
||||
@@ -849,6 +802,25 @@
|
||||
selectedTable.CurationPercentage);
|
||||
}
|
||||
|
||||
private async Task PersistAndSyncTableContextAsync()
|
||||
{
|
||||
var snapshot = BuildCurrentTableContext();
|
||||
await TableContextState.PersistAsync(ContextDestination, snapshot);
|
||||
|
||||
var targetUri = TableContextState.BuildUri("/tables", snapshot);
|
||||
if (string.Equals(NavigationManager.ToBaseRelativePath(NavigationManager.Uri), targetUri.TrimStart('/'), StringComparison.Ordinal))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
NavigationManager.NavigateTo(targetUri, replace: true);
|
||||
}
|
||||
|
||||
private RolemasterDb.App.Frontend.AppState.TableContextSnapshot BuildCurrentTableContext() =>
|
||||
new(
|
||||
TableSlug: selectedTableSlug,
|
||||
Mode: RolemasterDb.App.Frontend.AppState.TableContextMode.Reference);
|
||||
|
||||
private string GetTableOptionCssClass(CriticalTableReference table)
|
||||
{
|
||||
var classes = new List<string>();
|
||||
|
||||
Reference in New Issue
Block a user