Фикс чата
This commit is contained in:
@@ -105,21 +105,35 @@ public sealed class MessageRepository : IMessageRepository
|
||||
public async Task AddReadReceiptsAsync(Guid userId, List<Guid> messageIds, CancellationToken cancellationToken)
|
||||
{
|
||||
var filter = Builders<Message>.Filter.In(m => m.Id, messageIds);
|
||||
|
||||
var messages = await _messages.Find(filter).ToListAsync(cancellationToken);
|
||||
if (!messages.Any()) return;
|
||||
|
||||
var chatId = messages.First().ChatId;
|
||||
var maxDate = messages.Max(m => m.CreatedAt);
|
||||
|
||||
var notReadFilter = Builders<Message>.Filter.Not(
|
||||
Builders<Message>.Filter.ElemMatch<ReadReceipt>(
|
||||
"ReadBy",
|
||||
Builders<ReadReceipt>.Filter.Eq(r => r.UserId, userId)
|
||||
)
|
||||
);
|
||||
|
||||
var finalFilter = Builders<Message>.Filter.And(
|
||||
Builders<Message>.Filter.Eq(m => m.ChatId, chatId),
|
||||
Builders<Message>.Filter.Ne(m => m.SenderId, userId),
|
||||
Builders<Message>.Filter.Lte(m => m.CreatedAt, maxDate),
|
||||
notReadFilter
|
||||
);
|
||||
|
||||
var unreadMessagesToMark = await _messages.Find(finalFilter).ToListAsync(cancellationToken);
|
||||
|
||||
var writes = new List<WriteModel<Message>>();
|
||||
foreach (var msg in messages)
|
||||
foreach (var msg in unreadMessagesToMark)
|
||||
{
|
||||
if (!msg.ReadBy.Any(r => r.UserId == userId))
|
||||
{
|
||||
var receipt = new ReadReceipt(msg.Id, userId);
|
||||
|
||||
var pushUpdate = Builders<Message>.Update.Push("ReadBy", receipt);
|
||||
|
||||
var updateModel = new UpdateOneModel<Message>(Builders<Message>.Filter.Eq(m => m.Id, msg.Id), pushUpdate);
|
||||
writes.Add(updateModel);
|
||||
}
|
||||
var receipt = new ReadReceipt(msg.Id, userId);
|
||||
var pushUpdate = Builders<Message>.Update.Push("ReadBy", receipt);
|
||||
var updateModel = new UpdateOneModel<Message>(Builders<Message>.Filter.Eq(m => m.Id, msg.Id), pushUpdate);
|
||||
writes.Add(updateModel);
|
||||
}
|
||||
|
||||
if (writes.Any())
|
||||
@@ -180,8 +194,10 @@ public sealed class MessageRepository : IMessageRepository
|
||||
public async Task<int> GetUnreadCountAsync(Guid chatId, Guid userId, CancellationToken cancellationToken)
|
||||
{
|
||||
var notReadFilter = Builders<Message>.Filter.Not(
|
||||
Builders<Message>.Filter.ElemMatch("ReadBy",
|
||||
Builders<BsonDocument>.Filter.Eq("UserId", userId))
|
||||
Builders<Message>.Filter.ElemMatch<ReadReceipt>(
|
||||
"ReadBy",
|
||||
Builders<ReadReceipt>.Filter.Eq(r => r.UserId, userId)
|
||||
)
|
||||
);
|
||||
|
||||
var finalFilter = Builders<Message>.Filter.And(
|
||||
|
||||
@@ -200,9 +200,21 @@ export default function ChatView({ onStartCall, onStartGroupCall }: { onStartCal
|
||||
container.scrollTop = targetEl.offsetTop - 60;
|
||||
} else {
|
||||
container.scrollTop = container.scrollHeight;
|
||||
requestAnimationFrame(() => {
|
||||
if (container) container.scrollTop = container.scrollHeight;
|
||||
});
|
||||
setTimeout(() => {
|
||||
if (container) container.scrollTop = container.scrollHeight;
|
||||
}, 100);
|
||||
}
|
||||
} else {
|
||||
container.scrollTop = container.scrollHeight;
|
||||
requestAnimationFrame(() => {
|
||||
if (container) container.scrollTop = container.scrollHeight;
|
||||
});
|
||||
setTimeout(() => {
|
||||
if (container) container.scrollTop = container.scrollHeight;
|
||||
}, 100);
|
||||
}
|
||||
setScrollReady(true);
|
||||
}
|
||||
|
||||
@@ -407,13 +407,18 @@ function MessageBubble({
|
||||
</button>
|
||||
)}
|
||||
|
||||
{(() => {
|
||||
const hasReactions = Object.keys(reactionGroups).length > 0;
|
||||
const needsFrame = !!message.content || !!message.forwardedFrom || !!message.replyTo || hasReactions;
|
||||
|
||||
return (
|
||||
<div
|
||||
id={`msg-${message.id}`}
|
||||
onContextMenu={handleContextMenu}
|
||||
onDoubleClick={handleReply}
|
||||
title={t('reply') ? `${t('reply')} (Double Click)` : 'Double click to reply'}
|
||||
className={`cursor-pointer max-w-full min-w-0 rounded-[1.25rem] overflow-hidden transition-all duration-300 ${
|
||||
hasImage && !message.content && !message.forwardedFrom && !message.replyTo
|
||||
hasImage && !needsFrame
|
||||
? 'p-0 shadow-none border-none'
|
||||
: isMine
|
||||
? 'bubble-sent text-white shadow-sm px-3.5 py-2 hover:shadow-md hover:brightness-105 rounded-br-sm'
|
||||
@@ -538,11 +543,11 @@ function MessageBubble({
|
||||
|
||||
return (
|
||||
<div className={`
|
||||
${(message.content || message.forwardedFrom) ? '-mx-4' : ''}
|
||||
${(message.content || message.forwardedFrom) ? (message.forwardedFrom ? 'mt-2' : '-mt-2.5') : ''}
|
||||
${(message.content || message.forwardedFrom) ? (message.content ? 'mb-2' : '-mb-2.5') : ''}
|
||||
${isSingleGif && !(message.content || message.forwardedFrom) ? 'max-w-[260px] rounded-[1.25rem]' : ''}
|
||||
${isSingleGif && (message.content || message.forwardedFrom) ? 'max-h-[260px] mx-auto' : ''}
|
||||
${needsFrame ? '-mx-4' : ''}
|
||||
${needsFrame ? (message.forwardedFrom ? 'mt-2' : '-mt-2.5') : ''}
|
||||
${needsFrame ? (message.content ? 'mb-2' : '-mb-2.5') : ''}
|
||||
${isSingleGif && !needsFrame ? 'max-w-[260px] rounded-[1.25rem]' : ''}
|
||||
${isSingleGif && needsFrame ? 'max-h-[260px] mx-auto' : ''}
|
||||
bg-black/20 overflow-hidden relative
|
||||
`}>
|
||||
<div className={`grid gap-[2px] ${galleryMedia.length >= 3
|
||||
@@ -827,6 +832,8 @@ function MessageBubble({
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
})()}
|
||||
</div>
|
||||
|
||||
{isMine && (
|
||||
|
||||
Reference in New Issue
Block a user