feat: add support for broadcasting and handling channel deletions across clients

This commit is contained in:
Stone_Red
2026-07-17 16:35:59 +02:00
committed by HueByte
parent 4d25458717
commit a9519a52cc
11 changed files with 39 additions and 0 deletions
+9
View File
@@ -1071,6 +1071,15 @@ public sealed class AppOrchestrator : IDisposable
_conn.MessageDeleted += (channelName, messageId) =>
InvokeUI(() => _messageManager.RemoveMessage(channelName, messageId));
_conn.ChannelDeleted += channelName =>
{
InvokeUI(() =>
{
_conn.UntrackChannel(channelName);
_mainWindow.RemoveChannel(channelName);
});
};
_conn.ChannelNuked += channelName =>
{
InvokeUI(() =>
@@ -46,6 +46,7 @@ internal sealed class ConnectionManager : IAsyncDisposable
public event Action<string, string?>? UserBanned;
public event Action<string>? ForceDisconnected;
public event Action<string, Guid>? MessageDeleted;
public event Action<string>? ChannelDeleted;
public event Action<string>? ChannelNuked;
public event Action<ChannelDto>? ChannelUpdated;
public event Action<string>? Error;
@@ -300,6 +301,7 @@ internal sealed class ConnectionManager : IAsyncDisposable
connection.OnUserBanned += (user, reason) => UserBanned?.Invoke(user, reason);
connection.OnForceDisconnect += reason => ForceDisconnected?.Invoke(reason);
connection.OnMessageDeleted += (ch, id) => MessageDeleted?.Invoke(ch, id);
connection.OnChannelDeleted += ch => ChannelDeleted?.Invoke(ch);
connection.OnChannelNuked += ch => ChannelNuked?.Invoke(ch);
connection.OnChannelUpdated += ch =>
{
@@ -58,6 +58,7 @@ public sealed class EchoHubConnection : IAsyncDisposable
public event Action<string, string, string?>? OnUserKicked;
public event Action<string, string?>? OnUserBanned;
public event Action<string, Guid>? OnMessageDeleted;
public event Action<string>? OnChannelDeleted;
public event Action<string>? OnChannelNuked;
public event Action<string>? OnForceDisconnect;
public event Action<string>? OnError;
@@ -144,6 +145,11 @@ public sealed class EchoHubConnection : IAsyncDisposable
OnMessageDeleted?.Invoke(channelName, messageId);
});
_connection.On<string>(nameof(Core.Contracts.IEchoHubClient.ChannelDeleted), channelName =>
{
OnChannelDeleted?.Invoke(channelName);
});
_connection.On<string>(nameof(Core.Contracts.IEchoHubClient.ChannelNuked), channelName =>
{
OnChannelNuked?.Invoke(channelName);
@@ -12,6 +12,7 @@ public interface IChatBroadcaster
Task SendUserKickedAsync(string channelName, string username, string? reason);
Task SendUserBannedAsync(string username, string? reason);
Task SendMessageDeletedAsync(string channelName, Guid messageId);
Task SendChannelDeletedAsync(string channelName);
Task SendChannelNukedAsync(string channelName);
Task SendErrorAsync(string connectionId, string message);
Task ForceDisconnectUserAsync(List<string> connectionIds, string reason);
@@ -24,6 +24,7 @@ public interface IChatService
// Broadcasting (used by controllers and IRC gateway)
Task BroadcastMessageAsync(string channelName, MessageDto message);
Task BroadcastChannelUpdatedAsync(ChannelDto channel, string? channelName = null);
Task BroadcastChannelDeletedAsync(string channelName);
// Query operations (used by IRC gateway for WHOIS)
Task<List<string>> GetChannelsForUserAsync(string username);
@@ -15,6 +15,7 @@ public interface IEchoHubClient
Task UserKicked(string channelName, string username, string? reason);
Task UserBanned(string username, string? reason);
Task MessageDeleted(string channelName, Guid messageId);
Task ChannelDeleted(string channelName);
Task ChannelNuked(string channelName);
Task ForceDisconnect(string reason);
Task Error(string message);
+8
View File
@@ -101,6 +101,14 @@ public class IrcBroadcaster : IChatBroadcaster
}
}
public async Task SendChannelDeletedAsync(string channelName)
{
foreach (var conn in _gateway.GetConnectionsInChannel(channelName))
{
await conn.SendAsync($":{_gateway.Options.ServerName} NOTICE {conn.Nickname ?? "*"} :Channel #{channelName} has been deleted");
}
}
public async Task SendChannelNukedAsync(string channelName)
{
foreach (var conn in _gateway.GetConnectionsInChannel(channelName))
@@ -162,6 +162,8 @@ public class ChannelsController : ControllerBase
if (!result.IsSuccess)
return MapChannelError(result);
await _chatService.BroadcastChannelDeletedAsync(channel.ToLowerInvariant().Trim());
return NoContent();
}
@@ -320,6 +320,9 @@ public class ChatService : IChatService
public Task BroadcastChannelUpdatedAsync(ChannelDto channel, string? channelName = null)
=> BroadcastToAllAsync(b => b.SendChannelUpdatedAsync(channel, channelName));
public Task BroadcastChannelDeletedAsync(string channelName)
=> BroadcastToAllAsync(b => b.SendChannelDeletedAsync(channelName));
private async Task BroadcastToAllAsync(Func<IChatBroadcaster, Task> action)
{
foreach (var broadcaster in _broadcasters)
@@ -63,6 +63,9 @@ public class SignalRBroadcaster : IChatBroadcaster
public Task SendMessageDeletedAsync(string channelName, Guid messageId)
=> HubContext.Clients.Group(channelName).MessageDeleted(channelName, messageId);
public Task SendChannelDeletedAsync(string channelName)
=> HubContext.Clients.All.ChannelDeleted(channelName);
public Task SendChannelNukedAsync(string channelName)
=> HubContext.Clients.Group(channelName).ChannelNuked(channelName);
+3
View File
@@ -212,6 +212,9 @@ internal sealed class FakeChatService : IChatService
public Task BroadcastChannelUpdatedAsync(ChannelDto channel, string? channelName = null) =>
Task.CompletedTask;
public Task BroadcastChannelDeletedAsync(string channelName) =>
Task.CompletedTask;
public Task<List<string>> GetChannelsForUserAsync(string username) =>
Task.FromResult(ChannelsForUserToReturn);
}