fix(presence): broadcast presence_update to friends + DM members + space members
Six WS sites that previously broadcast presence_update to spaces only now use collectProfileBroadcastTargetIds (the same recipient set as user_updated): - ws/handler.ts finalizeDisconnect (offline) - ws/handler.ts auth path (online) - ws/events.ts handlePresenceUpdate (manual idle/dnd/online) - ws/events.ts handleActivityUpdate (rich activity changes) - routes/users.ts showActivity-toggle clear - routes/users.ts status PATCH Friends with no shared space + DM-only co-members now see each other's online/offline transitions live, matching user_updated semantics. Federated stub presence broadcasts (Task B3) use the same helper, so cross-instance recipients are uniform. Updates one assertion in social.federated.test.ts that asserted the old snowflake-style stub username (now realname-based per A1).
This commit is contained in:
@@ -11,6 +11,7 @@ import type { CallRelayResult, CallFanoutFailure } from '../utils/federationOutb
|
||||
import { mapCallReasonToEventReason } from '../utils/federationOutbox.js';
|
||||
import { ACTIVITY_LIMITS } from '@backspace/shared/src/activities.js';
|
||||
import { sanitizeUser } from '../utils/sanitize.js';
|
||||
import { collectProfileBroadcastTargetIds } from '../utils/userDeletion.js';
|
||||
import { deleteAttachmentFiles } from '../utils/fileCleanup.js';
|
||||
import { resolveEmbeds, reResolveEmbeds, embedRowToEmbed } from '../utils/embedResolver.js';
|
||||
import { appendMutationLog, queueOutboxEvent, queueDmRelay, getGroupDmTargetOrigins, sendCallRelay, computeFederatedId, sendTypingRelay, queueReadStateRelay } from '../utils/federationOutbox.js';
|
||||
@@ -497,17 +498,15 @@ function handlePresenceUpdate(event: Record<string, unknown>, userId: string): v
|
||||
connectionManager.setUserStatus(userId, status);
|
||||
const activities = connectionManager.getUserActivities(userId);
|
||||
|
||||
// Broadcast to all spaces user is in
|
||||
const userSpaces = connectionManager.getUserSpaces(userId);
|
||||
// Broadcast to friends + DM co-members + space co-members.
|
||||
const payload = {
|
||||
type: 'presence_update' as const,
|
||||
userId,
|
||||
status,
|
||||
...(activities.length > 0 ? { activities } : {}),
|
||||
};
|
||||
for (const spaceId of userSpaces) {
|
||||
connectionManager.sendToSpace(spaceId, payload, userId);
|
||||
}
|
||||
const targets = collectProfileBroadcastTargetIds(userId);
|
||||
for (const uid of targets) connectionManager.sendToUser(uid, payload);
|
||||
|
||||
// Also send to self (other tabs)
|
||||
connectionManager.sendToUser(userId, payload);
|
||||
@@ -534,11 +533,9 @@ function handleActivityUpdate(event: Record<string, unknown>, userId: string): v
|
||||
connectionManager.setUserActivities(userId, activities);
|
||||
const status = connectionManager.getUserStatus(userId);
|
||||
|
||||
const userSpaces = connectionManager.getUserSpaces(userId);
|
||||
const payload = { type: 'presence_update' as const, userId, status, activities };
|
||||
for (const spaceId of userSpaces) {
|
||||
connectionManager.sendToSpace(spaceId, payload, userId);
|
||||
}
|
||||
const targets = collectProfileBroadcastTargetIds(userId);
|
||||
for (const uid of targets) connectionManager.sendToUser(uid, payload);
|
||||
connectionManager.sendToUser(userId, payload);
|
||||
|
||||
// S2S: project to all active peers (activities + current status).
|
||||
|
||||
Reference in New Issue
Block a user