feat: real-time sync, notification & social system overhaul

- Add WS events: dm_channel_created, dm_channel_closed, friend_removed,
  channel_created/updated/deleted, server_updated
- Fix first-ever DM: broadcast dm_channel_created to recipient
- Add DELETE /api/dm/:id for closing DMs with re-open support
- Wire Close DM button in sidebar
- Fix dm_message_created for unknown channels (safety net)
- Broadcast friend_removed on friend deletion
- Sound system: track realtimeMessageEvents separately from API loads,
  play notification for messages in all channels, not just current
- Optimistic updates: send/edit/delete messages appear instantly with
  rollback on failure, temp message deduplication on WS echo
- Channel CRUD broadcasts to all server members
- Server update broadcast on PATCH
- Server join registers user in connectionManager immediately
- Reconnect: only reload current channel, preserve other channel caches
- Activity panel, right panel, member list toggle components
This commit is contained in:
Jannis Braun
2026-02-22 22:15:11 +01:00
parent 708bdf5468
commit 6b8fd44a3a
35 changed files with 1002 additions and 262 deletions
+28 -2
View File
@@ -4,6 +4,7 @@ import { getDb, schema } from '../db/index.js';
import { authenticate } from '../utils/auth.js';
import { generateSnowflake } from '../utils/snowflake.js';
import { isMember, isAdmin, getChannelServerId } from '../utils/permissions.js';
import { connectionManager } from '../ws/handler.js';
import type {
CreateChannelRequest,
UpdateChannelRequest,
@@ -106,7 +107,16 @@ export async function channelRoutes(app: FastifyInstance): Promise<void> {
return reply.code(500).send({ error: 'Failed to create channel', statusCode: 500 });
}
return reply.code(201).send(rowToChannel(channel));
const channelData = rowToChannel(channel);
// Broadcast channel_created to all server members
connectionManager.sendToServer(id, {
type: 'channel_created',
channel: channelData,
serverId: id,
});
return reply.code(201).send(channelData);
});
// PATCH /api/channels/:id - Update a channel (admin+)
@@ -159,7 +169,16 @@ export async function channelRoutes(app: FastifyInstance): Promise<void> {
return reply.code(500).send({ error: 'Failed to update channel', statusCode: 500 });
}
return reply.code(200).send(rowToChannel(updated));
const channelData = rowToChannel(updated);
// Broadcast channel_updated to all server members
connectionManager.sendToServer(serverId, {
type: 'channel_updated',
channel: channelData,
serverId,
});
return reply.code(200).send(channelData);
});
// DELETE /api/channels/:id - Delete a channel (admin+)
@@ -183,6 +202,13 @@ export async function channelRoutes(app: FastifyInstance): Promise<void> {
db.delete(schema.messages).where(eq(schema.messages.channelId, id)).run();
db.delete(schema.channels).where(eq(schema.channels.id, id)).run();
// Broadcast channel_deleted to all server members
connectionManager.sendToServer(serverId, {
type: 'channel_deleted',
channelId: id,
serverId,
});
return reply.code(200).send({ success: true });
});
}