[shared/signalr] Strongly typed SignalR bootstrap
This commit is contained in:
parent
e4c4ec186c
commit
76b283b3ba
7 changed files with 123 additions and 59 deletions
|
@ -1,10 +1,11 @@
|
||||||
|
using Iceshrimp.Shared.HubSchemas;
|
||||||
using Microsoft.AspNetCore.SignalR;
|
using Microsoft.AspNetCore.SignalR;
|
||||||
namespace Iceshrimp.Backend.Hubs;
|
namespace Iceshrimp.Backend.Hubs;
|
||||||
|
|
||||||
public class ExampleHub : Hub
|
public class ExampleHub : Hub<IExampleHubClient>, IExampleHubServer
|
||||||
{
|
{
|
||||||
public async Task SendMessage(string user, string message)
|
public async Task SendMessage(string user, string message)
|
||||||
{
|
{
|
||||||
await Clients.All.SendAsync("ReceiveMessage", "SignalR", "ping!");
|
await Clients.All.ReceiveMessage("SignalR", "ping!");
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,13 +1,21 @@
|
||||||
|
using Iceshrimp.Shared.HubSchemas;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.SignalR;
|
using Microsoft.AspNetCore.SignalR;
|
||||||
|
|
||||||
namespace Iceshrimp.Backend.Hubs;
|
namespace Iceshrimp.Backend.Hubs;
|
||||||
|
|
||||||
[Authorize(Policy = "HubAuthorization")]
|
[Authorize(Policy = "HubAuthorization")]
|
||||||
public class StreamingHub : Hub
|
public class StreamingHub : Hub<IStreamingHubClient>, IStreamingHubServer
|
||||||
{
|
{
|
||||||
public async Task SendMessage(string user, string message)
|
public async Task SendMessage(string user, string message)
|
||||||
{
|
{
|
||||||
await Clients.All.SendAsync("ReceiveMessage", "SignalR", "ping!");
|
await Clients.All.ReceiveMessage("SignalR", "ping!");
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task OnConnectedAsync()
|
||||||
|
{
|
||||||
|
await base.OnConnectedAsync();
|
||||||
|
var userId = Context.UserIdentifier;
|
||||||
|
//Clients.User(userId);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -17,6 +17,7 @@
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Http.Abstractions" Version="2.2.0"/>
|
<PackageReference Include="Microsoft.AspNetCore.Http.Abstractions" Version="2.2.0"/>
|
||||||
<PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="8.0.3"/>
|
<PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="8.0.3"/>
|
||||||
<PackageReference Include="Microsoft.AspNetCore.SignalR.Protocols.MessagePack" Version="8.0.3"/>
|
<PackageReference Include="Microsoft.AspNetCore.SignalR.Protocols.MessagePack" Version="8.0.3"/>
|
||||||
|
<PackageReference Include="TypedSignalR.Client" Version="3.5.2" OutputItemType="Analyzer" ReferenceOutputAssembly="false"/>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
@page "/hub"
|
@page "/hub"
|
||||||
@using Microsoft.AspNetCore.SignalR.Client
|
|
||||||
@inject NavigationManager Navigation
|
@inject NavigationManager Navigation
|
||||||
@implements IAsyncDisposable
|
@implements IAsyncDisposable
|
||||||
|
|
||||||
|
@ -29,48 +28,5 @@
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
private HubConnection? _hubConnection;
|
// See Hub.razor.cs
|
||||||
private List<string> _messages = [];
|
|
||||||
private string? _userInput;
|
|
||||||
private string? _messageInput;
|
|
||||||
|
|
||||||
protected override async Task OnInitializedAsync()
|
|
||||||
{
|
|
||||||
_hubConnection = new HubConnectionBuilder()
|
|
||||||
.WithUrl(Navigation.ToAbsoluteUri("/hubs/example"))
|
|
||||||
.AddMessagePackProtocol()
|
|
||||||
.Build();
|
|
||||||
|
|
||||||
//TODO: authentication is done like this:
|
|
||||||
//options => { options.AccessTokenProvider = () => Task.FromResult("the_access_token")!; })
|
|
||||||
|
|
||||||
_hubConnection.On<string, string>("ReceiveMessage", (user, message) =>
|
|
||||||
{
|
|
||||||
var encodedMsg = $"{user}: {message}";
|
|
||||||
_messages.Add(encodedMsg);
|
|
||||||
InvokeAsync(StateHasChanged);
|
|
||||||
});
|
|
||||||
|
|
||||||
await _hubConnection.StartAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task Send()
|
|
||||||
{
|
|
||||||
if (_hubConnection is not null)
|
|
||||||
{
|
|
||||||
await _hubConnection.SendAsync("SendMessage", _userInput, _messageInput);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsConnected =>
|
|
||||||
_hubConnection?.State == HubConnectionState.Connected;
|
|
||||||
|
|
||||||
public async ValueTask DisposeAsync()
|
|
||||||
{
|
|
||||||
if (_hubConnection is not null)
|
|
||||||
{
|
|
||||||
await _hubConnection.DisposeAsync();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
76
Iceshrimp.Frontend/Pages/Hub.razor.cs
Normal file
76
Iceshrimp.Frontend/Pages/Hub.razor.cs
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
using Iceshrimp.Shared.HubSchemas;
|
||||||
|
using Microsoft.AspNetCore.SignalR.Client;
|
||||||
|
using TypedSignalR.Client;
|
||||||
|
|
||||||
|
namespace Iceshrimp.Frontend.Pages;
|
||||||
|
|
||||||
|
public partial class Hub
|
||||||
|
{
|
||||||
|
private HubConnection? _hubConnection;
|
||||||
|
private IExampleHubServer? _hub;
|
||||||
|
private List<string> _messages = [];
|
||||||
|
private string _userInput = "";
|
||||||
|
private string _messageInput = "";
|
||||||
|
|
||||||
|
private class ExampleHubClient(Hub page) : IExampleHubClient, IHubConnectionObserver
|
||||||
|
{
|
||||||
|
public Task ReceiveMessage(string user, string message)
|
||||||
|
{
|
||||||
|
var encodedMsg = $"{user}: {message}";
|
||||||
|
page._messages.Add(encodedMsg);
|
||||||
|
page.InvokeAsync(page.StateHasChanged);
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task OnClosed(Exception? exception)
|
||||||
|
{
|
||||||
|
return ReceiveMessage("System", "Connection closed.");
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task OnReconnected(string? connectionId)
|
||||||
|
{
|
||||||
|
return ReceiveMessage("System", "Reconnected.");
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task OnReconnecting(Exception? exception)
|
||||||
|
{
|
||||||
|
return ReceiveMessage("System", "Reconnecting...");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override async Task OnInitializedAsync()
|
||||||
|
{
|
||||||
|
_hubConnection = new HubConnectionBuilder()
|
||||||
|
.WithUrl(Navigation.ToAbsoluteUri("/hubs/example"))
|
||||||
|
.AddMessagePackProtocol()
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
// This must be in a .razor.cs file for the code generator to work correctly
|
||||||
|
_hub = _hubConnection.CreateHubProxy<IExampleHubServer>();
|
||||||
|
|
||||||
|
//TODO: authentication is done like this:
|
||||||
|
//options => { options.AccessTokenProvider = () => Task.FromResult("the_access_token")!; })
|
||||||
|
|
||||||
|
_hubConnection.Register<IExampleHubClient>(new ExampleHubClient(this));
|
||||||
|
|
||||||
|
await _hubConnection.StartAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task Send()
|
||||||
|
{
|
||||||
|
if (_hub is not null)
|
||||||
|
{
|
||||||
|
await _hub.SendMessage(_userInput, _messageInput);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool IsConnected => _hubConnection?.State == HubConnectionState.Connected;
|
||||||
|
|
||||||
|
public async ValueTask DisposeAsync()
|
||||||
|
{
|
||||||
|
if (_hubConnection is not null)
|
||||||
|
{
|
||||||
|
await _hubConnection.DisposeAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
11
Iceshrimp.Shared/HubSchemas/ExampleHub.cs
Normal file
11
Iceshrimp.Shared/HubSchemas/ExampleHub.cs
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
namespace Iceshrimp.Shared.HubSchemas;
|
||||||
|
|
||||||
|
public interface IExampleHubServer
|
||||||
|
{
|
||||||
|
public Task SendMessage(string user, string message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface IExampleHubClient
|
||||||
|
{
|
||||||
|
public Task ReceiveMessage(string user, string message);
|
||||||
|
}
|
11
Iceshrimp.Shared/HubSchemas/StreamingHub.cs
Normal file
11
Iceshrimp.Shared/HubSchemas/StreamingHub.cs
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
namespace Iceshrimp.Shared.HubSchemas;
|
||||||
|
|
||||||
|
public interface IStreamingHubServer
|
||||||
|
{
|
||||||
|
public Task SendMessage(string user, string message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface IStreamingHubClient
|
||||||
|
{
|
||||||
|
public Task ReceiveMessage(string user, string message);
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue