feat: add mark_unread WebSocket event handler
This commit is contained in:
@@ -168,6 +168,9 @@ export function handleClientEvent(
|
||||
case 'channel_ack':
|
||||
handleChannelAck(event, userId);
|
||||
break;
|
||||
case 'mark_unread':
|
||||
handleMarkUnread(event, userId);
|
||||
break;
|
||||
case 'dm_call_start':
|
||||
handleDmCallStart(event, userId, username);
|
||||
break;
|
||||
@@ -1096,6 +1099,67 @@ function handleChannelAck(event: Record<string, unknown>, userId: string): void
|
||||
});
|
||||
}
|
||||
|
||||
function handleMarkUnread(event: Record<string, unknown>, userId: string): void {
|
||||
const channelId = event.channelId as string;
|
||||
const messageId = event.messageId as string;
|
||||
if (!channelId || !messageId) return;
|
||||
if (!/^\d+$/.test(messageId) && messageId !== '0') return;
|
||||
|
||||
// Validate channel membership
|
||||
const spaceId = getChannelSpaceId(channelId);
|
||||
if (spaceId) {
|
||||
if (!isMember(spaceId, userId)) return;
|
||||
} else {
|
||||
if (!isDmMember(channelId, userId)) return;
|
||||
}
|
||||
|
||||
const db = getDb();
|
||||
const now = Date.now();
|
||||
|
||||
if (messageId === '0') {
|
||||
// '0' sentinel: delete the read state entirely → channel appears fully unread
|
||||
db.delete(schema.readStates)
|
||||
.where(and(
|
||||
eq(schema.readStates.userId, userId),
|
||||
eq(schema.readStates.channelId, channelId),
|
||||
))
|
||||
.run();
|
||||
} else {
|
||||
// Set read state to the specified message (allows backward writes)
|
||||
const existing = db.select()
|
||||
.from(schema.readStates)
|
||||
.where(and(
|
||||
eq(schema.readStates.userId, userId),
|
||||
eq(schema.readStates.channelId, channelId),
|
||||
))
|
||||
.get();
|
||||
|
||||
if (existing) {
|
||||
db.update(schema.readStates)
|
||||
.set({ lastReadMessageId: messageId, updatedAt: now })
|
||||
.where(and(
|
||||
eq(schema.readStates.userId, userId),
|
||||
eq(schema.readStates.channelId, channelId),
|
||||
))
|
||||
.run();
|
||||
} else {
|
||||
db.insert(schema.readStates).values({
|
||||
userId,
|
||||
channelId,
|
||||
lastReadMessageId: messageId,
|
||||
updatedAt: now,
|
||||
}).run();
|
||||
}
|
||||
}
|
||||
|
||||
// Broadcast to all of this user's connections (multi-tab sync)
|
||||
connectionManager.sendToUser(userId, {
|
||||
type: 'mark_unread',
|
||||
channelId,
|
||||
messageId,
|
||||
});
|
||||
}
|
||||
|
||||
// ─── DM Call Handlers (Unified Room API) ───────────────────────────────────
|
||||
|
||||
function handleDmCallStart(event: Record<string, unknown>, userId: string, username: string): void {
|
||||
|
||||
Reference in New Issue
Block a user