feat: add mark_unread WebSocket event handler
This commit is contained in:
@@ -168,6 +168,9 @@ export function handleClientEvent(
|
|||||||
case 'channel_ack':
|
case 'channel_ack':
|
||||||
handleChannelAck(event, userId);
|
handleChannelAck(event, userId);
|
||||||
break;
|
break;
|
||||||
|
case 'mark_unread':
|
||||||
|
handleMarkUnread(event, userId);
|
||||||
|
break;
|
||||||
case 'dm_call_start':
|
case 'dm_call_start':
|
||||||
handleDmCallStart(event, userId, username);
|
handleDmCallStart(event, userId, username);
|
||||||
break;
|
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) ───────────────────────────────────
|
// ─── DM Call Handlers (Unified Room API) ───────────────────────────────────
|
||||||
|
|
||||||
function handleDmCallStart(event: Record<string, unknown>, userId: string, username: string): void {
|
function handleDmCallStart(event: Record<string, unknown>, userId: string, username: string): void {
|
||||||
|
|||||||
Reference in New Issue
Block a user