скрытие статуса online через сокеты и поле isInvisible в профиле
This commit is contained in:
@@ -21,6 +21,7 @@ using Knot.Modules.Conversations.Application.DTOs;
|
||||
using Knot.Contracts.Messaging.Application.Abstractions;
|
||||
using Knot.Contracts.Messaging.Domain;
|
||||
using Knot.Contracts.Conversations.Application.Abstractions;
|
||||
using Knot.Contracts.Profiles.Domain;
|
||||
|
||||
namespace Knot.Modules.Conversations.Infrastructure.SignalR;
|
||||
|
||||
@@ -51,6 +52,7 @@ public sealed class ChatHub : Hub
|
||||
private readonly ILogger<ChatHub> _logger;
|
||||
private readonly IMemoryCache _cache;
|
||||
private readonly IUserDisplayNameProvider _userProvider;
|
||||
private readonly IProfileRepository _profileRepository;
|
||||
|
||||
public ChatHub(
|
||||
ISender sender,
|
||||
@@ -60,7 +62,8 @@ public sealed class ChatHub : Hub
|
||||
IMessageRepository messageRepository,
|
||||
ILogger<ChatHub> logger,
|
||||
IMemoryCache cache,
|
||||
IUserDisplayNameProvider userProvider)
|
||||
IUserDisplayNameProvider userProvider,
|
||||
IProfileRepository profileRepository)
|
||||
{
|
||||
_sender = sender;
|
||||
_userContext = userContext;
|
||||
@@ -70,6 +73,7 @@ public sealed class ChatHub : Hub
|
||||
_logger = logger;
|
||||
_cache = cache;
|
||||
_userProvider = userProvider;
|
||||
_profileRepository = profileRepository;
|
||||
}
|
||||
|
||||
public override async Task OnConnectedAsync()
|
||||
@@ -95,7 +99,11 @@ public sealed class ChatHub : Hub
|
||||
|
||||
userId, Context.ConnectionId, userChats.Count);
|
||||
|
||||
await Clients.Others.SendAsync("user_online", new { userId });
|
||||
var isInvisible = await IsUserInvisibleAsync(_userContext.UserId, Context.ConnectionAborted);
|
||||
if (!isInvisible)
|
||||
{
|
||||
await BroadcastPresenceToVisibleUsersAsync("user_online", new { userId }, _userContext.UserId);
|
||||
}
|
||||
}
|
||||
await base.OnConnectedAsync();
|
||||
}
|
||||
@@ -111,7 +119,14 @@ public sealed class ChatHub : Hub
|
||||
if (set.Count == 0)
|
||||
{
|
||||
_userConnections.TryRemove(userId, out _);
|
||||
await Clients.Others.SendAsync("user_offline", new { userId, lastSeen = DateTime.UtcNow });
|
||||
var isInvisible = await IsUserInvisibleAsync(_userContext.UserId, Context.ConnectionAborted);
|
||||
if (!isInvisible)
|
||||
{
|
||||
await BroadcastPresenceToVisibleUsersAsync(
|
||||
"user_offline",
|
||||
new { userId, lastSeen = DateTime.UtcNow },
|
||||
_userContext.UserId);
|
||||
}
|
||||
}
|
||||
}
|
||||
_cache.Set("Global_OnlineUsersCount", _userConnections.Count);
|
||||
@@ -120,6 +135,52 @@ public sealed class ChatHub : Hub
|
||||
await base.OnDisconnectedAsync(exception);
|
||||
}
|
||||
|
||||
private async Task<bool> IsUserInvisibleAsync(Guid userId, CancellationToken ct)
|
||||
{
|
||||
var profile = await _profileRepository.GetAsync(userId, ct);
|
||||
return profile?.IsInvisible ?? false;
|
||||
}
|
||||
|
||||
private async Task BroadcastPresenceToVisibleUsersAsync(string eventName, object payload, Guid sourceUserId)
|
||||
{
|
||||
var recipients = _userConnections.Keys
|
||||
.Where(id => id != sourceUserId.ToString())
|
||||
.Select(id => Guid.TryParse(id, out var parsed) ? parsed : Guid.Empty)
|
||||
.Where(id => id != Guid.Empty)
|
||||
.Distinct()
|
||||
.ToList();
|
||||
|
||||
if (recipients.Count == 0)
|
||||
return;
|
||||
|
||||
var recipientProfiles = await _profileRepository.GetAsync(recipients, Context.ConnectionAborted);
|
||||
var invisibleRecipientIds = recipientProfiles
|
||||
.Where(p => p.IsInvisible)
|
||||
.Select(p => p.UserId)
|
||||
.ToHashSet();
|
||||
|
||||
foreach (var kvp in _userConnections)
|
||||
{
|
||||
if (!Guid.TryParse(kvp.Key, out var recipientId))
|
||||
continue;
|
||||
if (recipientId == sourceUserId)
|
||||
continue;
|
||||
if (invisibleRecipientIds.Contains(recipientId))
|
||||
continue;
|
||||
|
||||
string[] connectionIds;
|
||||
lock (kvp.Value)
|
||||
{
|
||||
connectionIds = kvp.Value.ToArray();
|
||||
}
|
||||
|
||||
foreach (var connectionId in connectionIds)
|
||||
{
|
||||
await Clients.Client(connectionId).SendAsync(eventName, payload);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ────────────────────────────────────────────────────────────────
|
||||
// Chat methods
|
||||
// ────────────────────────────────────────────────────────────────
|
||||
|
||||
Reference in New Issue
Block a user