зеркало из
1
0
Форкнуть 0

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:
IsmailS 2024-07-29 14:44:08 +05:30 коммит произвёл GitHub
Родитель 7780263313
Коммит d28251d1d7
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B5690EEEBB952194
3 изменённых файлов: 88 добавлений и 11 удалений

Просмотреть файл

@ -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>();
}