fix: SoundController isSelf must check BOTH local ID and homeUserId
The identity flip during disconnect: updateParticipants resolves
homeUserId → localSnowflake when activeDmCall is set, but reverts
to raw homeUserId when activeDmCall is cleared (before LiveKit
disconnect completes). SoundController sees the snowflake "leave"
and the homeUserId "join" — two phantom events for the same person.
Previous fix only checked homeUserId OR id. Now checks BOTH via
isSelf(id) which matches against a Set of {id, homeUserId}. This
recognizes the user as "self" regardless of which identity format
the participant currently has.
This commit is contained in:
@@ -12,10 +12,14 @@ function getSfxVolume(): number {
|
|||||||
export function SoundController() {
|
export function SoundController() {
|
||||||
const audioManager = AudioManager.getInstance();
|
const audioManager = AudioManager.getInstance();
|
||||||
const currentUser = useAuthStore((s) => s.user);
|
const currentUser = useAuthStore((s) => s.user);
|
||||||
// Federation-aware self-ID: in federated calls, LiveKit participant identity
|
// Federation-aware self-check: in federated calls, the participant userId
|
||||||
// uses homeUserId (from the home instance), not the local snowflake ID.
|
// can flip between localSnowflake (when activeDmCall resolves identity) and
|
||||||
// Without this, the SoundController thinks our own presence is a stranger.
|
// homeUserId (when activeDmCall is cleared during disconnect). We must
|
||||||
const myId = currentUser?.homeUserId || currentUser?.id;
|
// recognize BOTH as "self" to prevent phantom join/leave sounds.
|
||||||
|
const myIds = new Set<string>();
|
||||||
|
if (currentUser?.id) myIds.add(currentUser.id);
|
||||||
|
if (currentUser?.homeUserId) myIds.add(currentUser.homeUserId);
|
||||||
|
const isSelf = (id: string) => myIds.has(id);
|
||||||
|
|
||||||
// Refs to track previous states
|
// Refs to track previous states
|
||||||
const isInitialMount = useRef(true);
|
const isInitialMount = useRef(true);
|
||||||
@@ -90,28 +94,28 @@ export function SoundController() {
|
|||||||
if (state.isLiveKitConnected && !justDisconnected) {
|
if (state.isLiveKitConnected && !justDisconnected) {
|
||||||
// Someone joined voice (Others only)
|
// Someone joined voice (Others only)
|
||||||
state.participants.forEach(p => {
|
state.participants.forEach(p => {
|
||||||
if (!prevParticipantIds.current.has(p.userId) && p.userId !== myId) {
|
if (!prevParticipantIds.current.has(p.userId) && !isSelf(p.userId)) {
|
||||||
audioManager.playSound('user_join', sfxOpts);
|
audioManager.playSound('user_join', sfxOpts);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Someone left voice (Others only)
|
// Someone left voice (Others only)
|
||||||
prevParticipantIds.current.forEach(userId => {
|
prevParticipantIds.current.forEach(userId => {
|
||||||
if (!currentParticipantIds.has(userId) && userId !== myId) {
|
if (!currentParticipantIds.has(userId) && !isSelf(userId)) {
|
||||||
audioManager.playSound('user_leave', sfxOpts);
|
audioManager.playSound('user_leave', sfxOpts);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Someone started screen sharing (Others only)
|
// Someone started screen sharing (Others only)
|
||||||
state.participants.forEach(p => {
|
state.participants.forEach(p => {
|
||||||
if (p.isScreenSharing && !prevScreenShareUserIds.current.has(p.userId) && p.userId !== myId) {
|
if (p.isScreenSharing && !prevScreenShareUserIds.current.has(p.userId) && !isSelf(p.userId)) {
|
||||||
audioManager.playSound('stream_user_joined', sfxOpts);
|
audioManager.playSound('stream_user_joined', sfxOpts);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Someone stopped screen sharing (Others only)
|
// Someone stopped screen sharing (Others only)
|
||||||
prevScreenShareUserIds.current.forEach(userId => {
|
prevScreenShareUserIds.current.forEach(userId => {
|
||||||
if (!currentScreenShareUserIds.has(userId) && userId !== myId) {
|
if (!currentScreenShareUserIds.has(userId) && !isSelf(userId)) {
|
||||||
audioManager.playSound('stream_user_left', sfxOpts);
|
audioManager.playSound('stream_user_left', sfxOpts);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -183,7 +187,7 @@ export function SoundController() {
|
|||||||
if (incomingCallLoop.current) incomingCallLoop.current.stop();
|
if (incomingCallLoop.current) incomingCallLoop.current.stop();
|
||||||
if (outgoingCallLoop.current) outgoingCallLoop.current.stop();
|
if (outgoingCallLoop.current) outgoingCallLoop.current.stop();
|
||||||
};
|
};
|
||||||
}, [audioManager, myId]);
|
}, [audioManager, currentUser?.id, currentUser?.homeUserId]);
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user