[frontend/components] Improve streaming status indicator

This commit is contained in:
Lilian 2025-02-02 22:28:05 +01:00
parent ed627474a3
commit 75f14d0302
No known key found for this signature in database
3 changed files with 95 additions and 23 deletions

View file

@ -6,7 +6,36 @@
@inject GlobalComponentSvc GlobalComponentSvc @inject GlobalComponentSvc GlobalComponentSvc
@inject IStringLocalizer<Localization> Loc @inject IStringLocalizer<Localization> Loc
<div class="connection-status @(_hubConnectionState == HubConnectionState.Connected ? "fadeout" : "")">
@switch (_hubConnectionState)
{
case HubConnectionState.Connected:
<div class="state">
@Loc["Connected"]
</div>
break;
case HubConnectionState.Connecting:
<div class="state">
<svg class="animate-spin" viewBox="0 0 24 24"></svg> @Loc["Connecting"]
</div>
break;
case HubConnectionState.Disconnected:
<div @onclick="Reconnect" class="state disconnected">
@Loc["Disconnected"]
</div>
break;
case HubConnectionState.Reconnecting:
<div class="state">
<svg class="animate-spin" viewBox="0 0 24 24"></svg> @Loc["Reconnecting"]
</div>
break;
}
</div>
@code { @code {
private HubConnectionState _hubConnectionState = HubConnectionState.Connected;
protected override async Task OnInitializedAsync() protected override async Task OnInitializedAsync()
{ {
await StreamingService.ConnectAsync(); await StreamingService.ConnectAsync();
@ -15,31 +44,12 @@
private void HandleConnectionChange(object? _, HubConnectionState hubConnectionState) private void HandleConnectionChange(object? _, HubConnectionState hubConnectionState)
{ {
switch (hubConnectionState) _hubConnectionState = hubConnectionState;
{ StateHasChanged();
case HubConnectionState.Disconnected:
{
var banner = new BannerContainer.Banner { Text = @Loc["Connection lost, tap to reconnect."], OnClose = null, OnTap = Reconnect };
GlobalComponentSvc.BannerComponent?.AddBanner(banner);
break;
}
case HubConnectionState.Reconnecting:
{
var banner = new BannerContainer.Banner { Text = @Loc["Reconnecting"], OnClose = null, OnTap = null };
GlobalComponentSvc.BannerComponent?.AddBanner(banner);
break;
}
case HubConnectionState.Connected:
{
var banner = new BannerContainer.Banner { Text = @Loc["Connected"], OnClose = null, OnTap = null };
GlobalComponentSvc.BannerComponent?.AddBanner(banner);
break;
}
}
} }
private void Reconnect() private async Task Reconnect()
{ {
_ = StreamingService.ReconnectAsync(); await StreamingService.ReconnectAsync();
} }
} }

View file

@ -0,0 +1,61 @@
.connection-status {
display: block;
background-color: var(--background-color);
border: solid var(--notice-color) 0.1rem;
border-radius: 0.5rem;
padding: 0.25rem 0.5rem;
position: fixed;
bottom: 10%;
right: 5%;
z-index: 99;
/*allow-discrete is a valid value here*/
/*noinspection CssInvalidPropertyValue*/
transition: opacity 1s ease-in,
display 1s ease-in allow-discrete;
&.fadeout {
opacity: 0;
display: none;
}
}
.state {
display: flex;
align-items: center;
}
@keyframes spin {
to {
transform: rotate(360deg);
}
}
.animate-spin {
animation: spin 1s linear infinite;
}
svg {
display: inline;
height: 1rem;
width: 1rem;
border-radius: 9999px;
border-width: 2px;
border-color: transparent;
background-color: transparent;
border-right-color: white;
border-top-color: white;
border-style: solid;
margin-right: 0.5rem;
}
.disconnected {
cursor: pointer;
}
/*@starting-style is widely supported*/
/*noinspection CssInvalidAtRule*/
@starting-style {
.connection-status.fadeout {
opacity: 1;
display: block;
}
}

View file

@ -31,6 +31,7 @@ internal class NotificationStore : NoteMessageProvider, IAsyncDisposable
{ {
if (_initialized) return; if (_initialized) return;
await _streamingService.ConnectAsync(); await _streamingService.ConnectAsync();
_initialized = true;
} }
public async ValueTask DisposeAsync() public async ValueTask DisposeAsync()