fix: make server mute/deafen state survive page reload

- Client ready handler now builds restriction Sets atomically in a single
  setState call, eliminating intermediate empty-Set state that caused amber
  icons to flash rose on reload
- buildReadyPayload queries all voice restrictions from DB across the
  user's spaces instead of relying on in-memory state (which is lost on
  disconnect timeout)
- voice_join early-return path now re-broadcasts restrictions to the
  reconnecting user, covering fast reload where the user is still in the room
This commit is contained in:
Jannis Braun
2026-03-09 18:56:00 +01:00
parent c2ddfe0cb7
commit d09d956a9d
3 changed files with 50 additions and 31 deletions
+29
View File
@@ -425,6 +425,35 @@ function handleVoiceJoin(event: Record<string, unknown>, userId: string): void {
isScreenSharing: status.isScreenSharing,
});
}
// Re-broadcast persistent restrictions (covers page reload while in voice)
const db = getDb();
const restrictions = db.select()
.from(schema.voiceRestrictions)
.where(and(
eq(schema.voiceRestrictions.spaceId, spaceId),
eq(schema.voiceRestrictions.userId, userId),
))
.all();
for (const r of restrictions) {
if (r.restrictionType === 'mute') {
connectionManager.setServerMuted(userId, true);
connectionManager.sendToUser(userId, {
type: 'voice_server_muted',
userId,
channelId,
muted: true,
});
} else if (r.restrictionType === 'deafen') {
connectionManager.setServerDeafened(userId, true);
connectionManager.sendToUser(userId, {
type: 'voice_server_deafened',
userId,
channelId,
deafened: true,
});
}
}
return;
}