diff --git a/JSMR.UI.Blazor/Components/SkeletonGrid.razor b/JSMR.UI.Blazor/Components/SkeletonGrid.razor
new file mode 100644
index 0000000..f4de246
--- /dev/null
+++ b/JSMR.UI.Blazor/Components/SkeletonGrid.razor
@@ -0,0 +1,17 @@
+
+ @for (int i = 0; i < Count; i++)
+ {
+
+ }
+
+
+@code {
+ [Parameter]
+ public int Count { get; set; } = 12;
+}
diff --git a/JSMR.UI.Blazor/Pages/VoiceWorks.razor b/JSMR.UI.Blazor/Pages/VoiceWorks.razor
index 1bbb102..63d3c7d 100644
--- a/JSMR.UI.Blazor/Pages/VoiceWorks.razor
+++ b/JSMR.UI.Blazor/Pages/VoiceWorks.razor
@@ -15,7 +15,6 @@
Voice Works
-
@if (searchResults is not null)
@@ -28,7 +27,9 @@
}
@code {
+ private bool _suppressNextLocation;
private bool _isAlive = true;
+ //private bool IsLoading;
private CancellationTokenSource _cts = new();
VoiceWorkFilterState FilterState = new();
@@ -44,21 +45,26 @@
private async void OnLocationChanged(object? sender, LocationChangedEventArgs e)
{
+ if (_suppressNextLocation)
+ {
+ _suppressNextLocation = false;
+ return;
+ }
+
if (!_isAlive)
return;
if (!IsThisPage(e.Location))
return;
- // Parse query from the new URL and update state if it actually changed.
string query = NavigationManager.ToAbsoluteUri(e.Location).Query;
VoiceWorkFilterState next = VoiceWorkFilterState.FromQuery(query);
if (next != FilterState)
{
FilterState = next;
- await RunSearchAsync();
await InvokeAsync(StateHasChanged);
+ RunSearchAsync();
}
}
@@ -74,7 +80,13 @@
if (next == FilterState)
return;
+ FilterState = next;
+
+ // Optional immediate paint if you want instant visual feedback on filters:
+ //await InvokeAsync(StateHasChanged);
+
UpdateUrl(next, false);
+ RunSearchAsync();
}
void UpdateUrl(VoiceWorkFilterState next, bool replace)
@@ -82,6 +94,8 @@
string basePath = new Uri(NavigationManager.Uri).GetLeftPart(UriPartial.Path);
string uri = QueryHelpers.AddQueryString(basePath, next.ToQuery());
+ _suppressNextLocation = true;
+
NavigationManager.NavigateTo(uri, replace: replace);
}
@@ -91,6 +105,9 @@
try
{
+ //IsLoading = true; // show skeletons NOW
+ //StateHasChanged(); // paint immediately
+
_cts.Cancel();
_cts = new();
@@ -99,7 +116,15 @@
}
catch (OperationCanceledException)
{
-
+
+ }
+ finally
+ {
+ if (_isAlive)
+ {
+ //IsLoading = false; // hide skeletons
+ await InvokeAsync(StateHasChanged);
+ }
}
}