InvokeAsync(StateHasChanged) from StateHasChanged() (#239)
* InvokeAsync(StateHasChanged) from StateHasChanged() * sdfsd * send message to specific users * Update ChatRoom.razor test * resolve comments --------- Co-authored-by: JialinXin <jixin@microsoft.com>
This commit is contained in:
Родитель
7780263313
Коммит
d28251d1d7
|
@ -1,4 +1,7 @@
|
|||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Microsoft.AspNetCore.SignalR;
|
||||
|
@ -8,21 +11,54 @@ namespace BlazorChat
|
|||
public class BlazorChatSampleHub : Hub
|
||||
{
|
||||
public const string HubUrl = "/chat";
|
||||
// cache with <UserName,ConnectionIds>
|
||||
private static ConcurrentDictionary<string, List<string>> _connectedUsers = new ConcurrentDictionary<string, List<string>>(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
public async Task Broadcast(string username, string message)
|
||||
public async Task Broadcast(string username, string recipient, string message)
|
||||
{
|
||||
await Clients.All.SendAsync("Broadcast", username, message);
|
||||
if (string.IsNullOrEmpty(recipient))
|
||||
{
|
||||
await Clients.All.SendAsync("Broadcast", username, message);
|
||||
}
|
||||
else if (_connectedUsers.TryGetValue(recipient, out var connections) && connections.Count > 0)
|
||||
{
|
||||
await Clients.Clients(connections).SendAsync("SendToUser", username, recipient, message);
|
||||
}
|
||||
}
|
||||
|
||||
public override Task OnConnectedAsync()
|
||||
public override async Task OnConnectedAsync()
|
||||
{
|
||||
Console.WriteLine($"{Context.ConnectionId} connected");
|
||||
return base.OnConnectedAsync();
|
||||
var username = Context.GetHttpContext().Request.Query["username"];
|
||||
if (_connectedUsers.TryGetValue(username, out var connections))
|
||||
{
|
||||
connections.Add(Context.ConnectionId);
|
||||
}
|
||||
else
|
||||
{
|
||||
connections = new List<string>() { Context.ConnectionId };
|
||||
}
|
||||
_connectedUsers[username] = connections;
|
||||
Console.WriteLine($"{Context.ConnectionId}:${username} connected");
|
||||
|
||||
await Clients.All.SendAsync("UpdateConnectedUsers", _connectedUsers.Keys);
|
||||
await base.OnConnectedAsync();
|
||||
}
|
||||
|
||||
public override async Task OnDisconnectedAsync(Exception e)
|
||||
{
|
||||
Console.WriteLine($"Disconnected {e?.Message} {Context.ConnectionId}");
|
||||
var username = Context.GetHttpContext().Request.Query["username"];
|
||||
if (_connectedUsers.TryGetValue(username, out var connections) && connections.Contains(Context.ConnectionId))
|
||||
{
|
||||
connections.Remove(Context.ConnectionId);
|
||||
_connectedUsers[username] = connections;
|
||||
if (connections.Count == 0)
|
||||
{
|
||||
_connectedUsers.Remove(username, out var removed);
|
||||
}
|
||||
}
|
||||
Console.WriteLine($"Disconnected {e?.Message} {Context.ConnectionId}:${username}");
|
||||
|
||||
await Clients.All.SendAsync("UpdateConnectedUsers", _connectedUsers.Keys);
|
||||
await base.OnDisconnectedAsync(e);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,6 +29,15 @@ else
|
|||
<span>You are connected as <b>@_username</b></span>
|
||||
<button class="btn btn-sm btn-warning ml-md-auto" @onclick="@DisconnectAsync">Disconnect</button>
|
||||
</div>
|
||||
|
||||
<h2>Connected users:</h2>
|
||||
<ul>
|
||||
@foreach (var user in _connectedUsers)
|
||||
{
|
||||
<li>@user</li>
|
||||
}
|
||||
</ul>
|
||||
|
||||
// display messages
|
||||
<div id="scrollbox">
|
||||
@foreach (var item in _messages)
|
||||
|
@ -40,12 +49,20 @@ else
|
|||
else
|
||||
{
|
||||
<div class="@item.CSS">
|
||||
<div class="user">@item.Username</div>
|
||||
<div class="user">From: @item.Username</div>
|
||||
@if (!string.IsNullOrWhiteSpace(item.RecieverUsername))
|
||||
{
|
||||
<div class="user">To: @item.RecieverUsername</div>
|
||||
}
|
||||
<div class="msg">@item.Body</div>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
<hr />
|
||||
<div id="sentto">
|
||||
<label for="recipientUsername">Send message to:</label>
|
||||
<input type="text" id="recipientUsername" @bind="_recipientUsername" />
|
||||
</div>
|
||||
<textarea class="input-lg" placeholder="enter your comment" @bind="@_newMessage"></textarea>
|
||||
<button class="btn btn-default" @onclick="@(() => SendAsync(_newMessage))">Send</button>
|
||||
</div>
|
||||
|
@ -61,12 +78,18 @@ else
|
|||
// on-screen message
|
||||
private string _message;
|
||||
|
||||
// on-screen recipientUsername
|
||||
private string _recipientUsername;
|
||||
|
||||
// new message input
|
||||
private string _newMessage;
|
||||
|
||||
// list of messages in chat
|
||||
private List<Message> _messages = new List<Message>();
|
||||
|
||||
// list of messages in chat
|
||||
private List<string> _connectedUsers = new List<string>();
|
||||
|
||||
private string _hubUrl;
|
||||
private HubConnection _hubConnection;
|
||||
|
||||
|
@ -94,10 +117,16 @@ else
|
|||
_hubUrl = baseUrl.TrimEnd('/') + BlazorChatSampleHub.HubUrl;
|
||||
|
||||
_hubConnection = new HubConnectionBuilder()
|
||||
.WithUrl(_hubUrl)
|
||||
.WithUrl($"{_hubUrl}?username={_username}")
|
||||
.Build();
|
||||
|
||||
_hubConnection.On<IEnumerable<string>>("UpdateConnectedUsers", (userList) =>
|
||||
{
|
||||
_connectedUsers = userList.ToList();
|
||||
InvokeAsync(StateHasChanged);
|
||||
});
|
||||
_hubConnection.On<string, string>("Broadcast", BroadcastMessage);
|
||||
_hubConnection.On<string, string, string>("SendToUser", SendToUser);
|
||||
|
||||
await _hubConnection.StartAsync();
|
||||
|
||||
|
@ -117,7 +146,18 @@ else
|
|||
_messages.Add(new Message(name, message, isMine));
|
||||
|
||||
// Inform blazor the UI needs updating
|
||||
StateHasChanged();
|
||||
InvokeAsync(StateHasChanged);
|
||||
}
|
||||
|
||||
private void SendToUser(string senderUsername, string recieverUsername, string message)
|
||||
{
|
||||
bool isMine = senderUsername.Equals(_username, StringComparison.OrdinalIgnoreCase);
|
||||
var messageObj = new Message(senderUsername, message, isMine);
|
||||
messageObj.RecieverUsername = recieverUsername;
|
||||
_messages.Add(messageObj);
|
||||
|
||||
// Inform blazor the UI needs updating
|
||||
InvokeAsync(StateHasChanged);
|
||||
}
|
||||
|
||||
private async Task DisconnectAsync()
|
||||
|
@ -138,8 +178,7 @@ else
|
|||
{
|
||||
if (_isChatting && !string.IsNullOrWhiteSpace(message))
|
||||
{
|
||||
await _hubConnection.SendAsync("Broadcast", _username, message);
|
||||
|
||||
await _hubConnection.SendAsync("Broadcast", _username, _recipientUsername, message);
|
||||
_newMessage = string.Empty;
|
||||
}
|
||||
}
|
||||
|
@ -154,6 +193,7 @@ else
|
|||
}
|
||||
|
||||
public string Username { get; set; }
|
||||
public string RecieverUsername { get; set; }
|
||||
public string Body { get; set; }
|
||||
public bool Mine { get; set; }
|
||||
|
||||
|
|
|
@ -28,6 +28,7 @@ namespace BlazorChat
|
|||
{
|
||||
services.AddRazorPages();
|
||||
services.AddServerSideBlazor();
|
||||
services.AddSignalR().AddAzureSignalR("Endpoint=https://jixinaue.service.signalr.net;AccessKey=cOKNRVvika0bEO93RytJUUyPPZu9dUl+M8mD2LK461U=;Version=1.0;");
|
||||
services.AddSingleton<WeatherForecastService>();
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче