fix: leave and reconnect sound randomly playing, also fix leave sound when muting

This commit is contained in:
2026-04-04 03:09:44 +02:00
parent de2d3300d4
commit 8674579b19
2 changed files with 49 additions and 6 deletions

View File

@@ -15,3 +15,4 @@ export const DEFAULT_MAX_USERS = 50;
export const DEFAULT_AUDIO_BITRATE_KBPS = 96;
export const DEFAULT_VOLUME = 100;
export const SEARCH_DEBOUNCE_MS = 300;
export const RECONNECT_SOUND_GRACE_MS = 15_000;

View File

@@ -64,7 +64,7 @@ import {
} from '../../shared-kernel';
import { NotificationAudioService, AppSound } from '../../core/services/notification-audio.service';
import { hasRoomBanForUser } from '../../core/helpers/room-ban.helpers';
import { ROOM_URL_PATTERN } from '../../core/constants';
import { RECONNECT_SOUND_GRACE_MS, ROOM_URL_PATTERN } from '../../core/constants';
import { VoiceSessionFacade } from '../../domains/voice-session';
import {
findRoomMember,
@@ -190,6 +190,12 @@ export class RoomsEffects {
* preventing false join/leave sounds during state refreshes.
*/
private knownVoiceUsers = new Set<string>();
/**
* When a user leaves (e.g. socket drops), record the timestamp so
* that a rapid re-join (reconnect) does not trigger a false
* join/leave sound within {@link RECONNECT_SOUND_GRACE_MS}.
*/
private recentlyLeftVoiceTimestamps = new Map<string, number>();
private roomNavigationRequestVersion = 0;
private latestNavigatedRoomId: string | null = null;
@@ -1287,6 +1293,10 @@ export class RoomsEffects {
: undefined;
if (!remainingServerIds || remainingServerIds.length === 0) {
if (this.knownVoiceUsers.has(signalingMessage.oderId)) {
this.recentlyLeftVoiceTimestamps.set(signalingMessage.oderId, Date.now());
}
this.knownVoiceUsers.delete(signalingMessage.oderId);
}
@@ -1452,13 +1462,20 @@ export class RoomsEffects {
const nowConnected = vs.isConnected ?? false;
const wasKnown = this.knownVoiceUsers.has(userId);
const wasInCurrentVoiceRoom = this.isSameVoiceRoom(existingUser?.voiceState, currentUser?.voiceState);
const isInCurrentVoiceRoom = this.isSameVoiceRoom(vs, currentUser?.voiceState);
// Merge with existing state so partial updates (e.g. mute toggle
// that omits roomId/serverId) don't look like a room change.
const mergedVoiceState = { ...existingUser?.voiceState, ...vs };
const isInCurrentVoiceRoom = this.isSameVoiceRoom(mergedVoiceState, currentUser?.voiceState);
if (weAreInVoice) {
if (((!wasKnown && isInCurrentVoiceRoom) || (userExists && !wasInCurrentVoiceRoom && isInCurrentVoiceRoom)) && nowConnected) {
this.audioService.play(AppSound.Joining);
} else if (wasInCurrentVoiceRoom && !isInCurrentVoiceRoom) {
this.audioService.play(AppSound.Leave);
const isReconnect = this.consumeRecentLeave(userId);
if (!isReconnect) {
if (((!wasKnown && isInCurrentVoiceRoom) || (userExists && !wasInCurrentVoiceRoom && isInCurrentVoiceRoom)) && nowConnected) {
this.audioService.play(AppSound.Joining);
} else if (wasInCurrentVoiceRoom && !isInCurrentVoiceRoom) {
this.audioService.play(AppSound.Leave);
}
}
}
@@ -1630,6 +1647,31 @@ export class RoomsEffects {
&& voiceState.serverId === currentUserVoiceState.serverId;
}
/**
* Returns `true` and cleans up the entry if the given user left
* recently enough to be considered a reconnect. Also prunes any
* stale entries older than the grace window.
*/
private consumeRecentLeave(userId: string): boolean {
const now = Date.now();
// Prune stale entries while iterating.
for (const [id, ts] of this.recentlyLeftVoiceTimestamps) {
if (now - ts > RECONNECT_SOUND_GRACE_MS) {
this.recentlyLeftVoiceTimestamps.delete(id);
}
}
const leaveTs = this.recentlyLeftVoiceTimestamps.get(userId);
if (leaveTs !== undefined && now - leaveTs <= RECONNECT_SOUND_GRACE_MS) {
this.recentlyLeftVoiceTimestamps.delete(userId);
return true;
}
return false;
}
private resolveRoom(roomId: string | undefined, currentRoom: Room | null, savedRooms: Room[]): Room | null {
if (!roomId)
return currentRoom;