fix: notify displaced tab when user joins voice from another session
When a user joins a voice channel while already connected from another tab, the server now sends a 'displaced' reason on voice_disconnected. The client tears down LiveKit and shows an informational toast.
This commit is contained in:
@@ -537,6 +537,14 @@ function handleVoiceJoin(event: Record<string, unknown>, userId: string): void {
|
|||||||
const left = connectionManager.leaveCurrentRoom(userId);
|
const left = connectionManager.leaveCurrentRoom(userId);
|
||||||
if (left) {
|
if (left) {
|
||||||
broadcastRoomLeave(left.roomId, left.room, userId);
|
broadcastRoomLeave(left.roomId, left.room, userId);
|
||||||
|
|
||||||
|
// Notify all of the user's tabs so the displaced tab tears down LiveKit
|
||||||
|
connectionManager.sendToUser(userId, {
|
||||||
|
type: 'voice_disconnected',
|
||||||
|
userId,
|
||||||
|
channelId: left.roomId,
|
||||||
|
reason: 'displaced',
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cancel any ringing DM rooms where this user is the caller
|
// Cancel any ringing DM rooms where this user is the caller
|
||||||
|
|||||||
@@ -330,7 +330,7 @@ export type ServerEvent =
|
|||||||
| { type: 'voice_space_deafened'; userId: string; channelId: string; spaceId: string; deafened: boolean }
|
| { type: 'voice_space_deafened'; userId: string; channelId: string; spaceId: string; deafened: boolean }
|
||||||
| { type: 'voice_permission_muted'; userId: string; spaceId: string; muted: boolean }
|
| { type: 'voice_permission_muted'; userId: string; spaceId: string; muted: boolean }
|
||||||
| { type: 'voice_moved'; userId: string; oldChannelId: string; newChannelId: string }
|
| { type: 'voice_moved'; userId: string; oldChannelId: string; newChannelId: string }
|
||||||
| { type: 'voice_disconnected'; userId: string; channelId: string }
|
| { type: 'voice_disconnected'; userId: string; channelId: string; reason?: 'displaced' }
|
||||||
| { type: 'user_updated'; user: User }
|
| { type: 'user_updated'; user: User }
|
||||||
| { type: 'member_banned'; spaceId: string; reason: string | null }
|
| { type: 'member_banned'; spaceId: string; reason: string | null }
|
||||||
| { type: 'category_created'; category: ChannelCategory; spaceId: string }
|
| { type: 'category_created'; category: ChannelCategory; spaceId: string }
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ import type { ServerEvent, ClientEvent, ActiveCallInfo } from '@backspace/shared
|
|||||||
import { resolveAssetUrl, normalizeUserAssets, normalizeMessageAssets } from '../utils/assetUrls';
|
import { resolveAssetUrl, normalizeUserAssets, normalizeMessageAssets } from '../utils/assetUrls';
|
||||||
import { broadcastVoiceStatus, broadcastDeafenViaLiveKit } from '../utils/voice';
|
import { broadcastVoiceStatus, broadcastDeafenViaLiveKit } from '../utils/voice';
|
||||||
import { registerSelfId } from '../utils/identity';
|
import { registerSelfId } from '../utils/identity';
|
||||||
|
import { getActiveRoom } from './useLiveKit';
|
||||||
|
import { useUIStore } from '../stores/uiStore';
|
||||||
|
|
||||||
// ─── Connection state ─────────────────────────────────────────────────────────
|
// ─── Connection state ─────────────────────────────────────────────────────────
|
||||||
|
|
||||||
@@ -428,7 +430,14 @@ function handleEvent(origin: string, event: ServerEvent): void {
|
|||||||
case 'voice_disconnected': {
|
case 'voice_disconnected': {
|
||||||
const myDisconnectId = isHome ? useAuthStore.getState().user?.id : getMyUserIdForOrigin(origin);
|
const myDisconnectId = isHome ? useAuthStore.getState().user?.id : getMyUserIdForOrigin(origin);
|
||||||
if (event.userId === myDisconnectId) {
|
if (event.userId === myDisconnectId) {
|
||||||
useVoiceStore.getState().handleForceDisconnect();
|
const { currentVoiceChannelId } = useVoiceStore.getState();
|
||||||
|
if (event.channelId === currentVoiceChannelId) {
|
||||||
|
useVoiceStore.getState().handleForceDisconnect();
|
||||||
|
getActiveRoom()?.disconnect();
|
||||||
|
if (event.reason === 'displaced') {
|
||||||
|
useUIStore.getState().addToast('Voice disconnected — joined from another session', 'info');
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user