conversations, unread count, autoscrolling to recent messages, cursor in text bar

This commit is contained in:
jackiettran
2025-11-09 22:16:26 -05:00
parent 7a5bff8f2b
commit 3442e880d8
5 changed files with 415 additions and 101 deletions

View File

@@ -3,6 +3,7 @@ const { Message, User } = require('../models');
const { authenticateToken } = require('../middleware/auth');
const logger = require('../utils/logger');
const { emitNewMessage, emitMessageRead } = require('../sockets/messageSocket');
const { Op } = require('sequelize');
const router = express.Router();
// Get all messages for the current user (inbox)
@@ -38,6 +39,100 @@ router.get('/', authenticateToken, async (req, res) => {
}
});
// Get conversations grouped by user pairs
router.get('/conversations', authenticateToken, async (req, res) => {
try {
const userId = req.user.id;
// Fetch all messages where user is sender or receiver
const allMessages = await Message.findAll({
where: {
[Op.or]: [
{ senderId: userId },
{ receiverId: userId }
]
},
include: [
{
model: User,
as: 'sender',
attributes: ['id', 'firstName', 'lastName', 'profileImage']
},
{
model: User,
as: 'receiver',
attributes: ['id', 'firstName', 'lastName', 'profileImage']
}
],
order: [['createdAt', 'DESC']]
});
// Group messages by conversation partner
const conversationsMap = new Map();
allMessages.forEach(message => {
// Determine the conversation partner
const partnerId = message.senderId === userId ? message.receiverId : message.senderId;
const partner = message.senderId === userId ? message.receiver : message.sender;
if (!conversationsMap.has(partnerId)) {
conversationsMap.set(partnerId, {
partnerId,
partner: partner ? {
id: partner.id,
firstName: partner.firstName,
lastName: partner.lastName,
profileImage: partner.profileImage
} : null,
lastMessage: null,
lastMessageAt: null,
unreadCount: 0
});
}
const conversation = conversationsMap.get(partnerId);
// Count unread messages (only those received by current user)
if (message.receiverId === userId && !message.isRead) {
conversation.unreadCount++;
}
// Keep the most recent message (messages are already sorted DESC)
if (!conversation.lastMessage) {
conversation.lastMessage = {
id: message.id,
content: message.content,
senderId: message.senderId,
createdAt: message.createdAt,
isRead: message.isRead
};
conversation.lastMessageAt = message.createdAt;
}
});
// Convert to array and sort by most recent message first
const conversations = Array.from(conversationsMap.values())
.filter(conv => conv.partner !== null) // Filter out conversations with deleted users
.sort((a, b) => new Date(b.lastMessageAt) - new Date(a.lastMessageAt));
const reqLogger = logger.withRequestId(req.id);
reqLogger.info("Conversations fetched", {
userId: req.user.id,
conversationCount: conversations.length
});
res.json(conversations);
} catch (error) {
const reqLogger = logger.withRequestId(req.id);
reqLogger.error("Conversations fetch failed", {
error: error.message,
stack: error.stack,
userId: req.user.id
});
res.status(500).json({ error: error.message });
}
});
// Get sent messages
router.get('/sent', authenticateToken, async (req, res) => {
try {