Skip to content

Commit

Permalink
InvokeAsync(StateHasChanged) from StateHasChanged() (#239)
Browse files Browse the repository at this point in the history
* InvokeAsync(StateHasChanged) from StateHasChanged()

* sdfsd

* send message to specific users

* Update ChatRoom.razor

test

* resolve comments

---------

Co-authored-by: JialinXin <[email protected]>
  • Loading branch information
ismusidhu and JialinXin authored Jul 29, 2024
1 parent 7780263 commit d28251d
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 11 deletions.
48 changes: 42 additions & 6 deletions samples/BlazorChat/BlazorChatSampleHub.cs
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -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);
}
}
Expand Down
50 changes: 45 additions & 5 deletions samples/BlazorChat/Pages/ChatRoom.razor
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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>
Expand All @@ -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;

Expand Down Expand Up @@ -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();

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

Expand Down
1 change: 1 addition & 0 deletions samples/BlazorChat/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ public void ConfigureServices(IServiceCollection services)
{
services.AddRazorPages();
services.AddServerSideBlazor();
services.AddSignalR().AddAzureSignalR("Endpoint=https://jixinaue.service.signalr.net;AccessKey=cOKNRVvika0bEO93RytJUUyPPZu9dUl+M8mD2LK461U=;Version=1.0;");
services.AddSingleton<WeatherForecastService>();
}

Expand Down

0 comments on commit d28251d

Please sign in to comment.