fix: Broken voice states and connectivity drops
This commit is contained in:
@@ -18,6 +18,8 @@ import {
|
||||
EMPTY,
|
||||
Subject,
|
||||
catchError,
|
||||
firstValueFrom,
|
||||
from,
|
||||
switchMap,
|
||||
tap
|
||||
} from 'rxjs';
|
||||
@@ -337,35 +339,44 @@ export class ServersRailComponent {
|
||||
|
||||
this.joinPasswordError.set(null);
|
||||
|
||||
return this.serverDirectory.requestJoin({
|
||||
roomId: room.id,
|
||||
userId: currentUserId,
|
||||
userPublicKey: currentUser?.oderId || currentUserId,
|
||||
displayName: currentUser?.displayName || 'Anonymous',
|
||||
password: password?.trim() || undefined
|
||||
}, {
|
||||
sourceId: room.sourceId,
|
||||
sourceUrl: room.sourceUrl
|
||||
})
|
||||
.pipe(
|
||||
tap((response) => {
|
||||
this.closePasswordDialog();
|
||||
this.store.dispatch(
|
||||
RoomsActions.updateRoom({
|
||||
roomId: room.id,
|
||||
changes: this.toRoomRefreshChanges(room, response.server)
|
||||
return from(this.resolveRoomJoinTarget(room)).pipe(
|
||||
switchMap((joinTarget) => {
|
||||
if (!joinTarget.selector) {
|
||||
if (this.currentRoom()?.id === room.id) {
|
||||
this.store.dispatch(RoomsActions.setSignalServerReconnecting({ isReconnecting: true }));
|
||||
}
|
||||
|
||||
return EMPTY;
|
||||
}
|
||||
|
||||
return this.serverDirectory.requestJoin({
|
||||
roomId: room.id,
|
||||
userId: currentUserId,
|
||||
userPublicKey: currentUser?.oderId || currentUserId,
|
||||
displayName: currentUser?.displayName || 'Anonymous',
|
||||
password: password?.trim() || undefined
|
||||
}, joinTarget.selector)
|
||||
.pipe(
|
||||
tap((response) => {
|
||||
this.closePasswordDialog();
|
||||
this.store.dispatch(
|
||||
RoomsActions.updateRoom({
|
||||
roomId: room.id,
|
||||
changes: this.toRoomRefreshChanges(joinTarget.room, response.server, response.signalingUrl)
|
||||
})
|
||||
);
|
||||
|
||||
if (this.currentRoom()?.id === room.id) {
|
||||
this.store.dispatch(RoomsActions.setSignalServerReconnecting({ isReconnecting: false }));
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
if (this.currentRoom()?.id === room.id) {
|
||||
this.store.dispatch(RoomsActions.setSignalServerReconnecting({ isReconnecting: false }));
|
||||
}
|
||||
}),
|
||||
catchError((error: unknown) => {
|
||||
this.handleBackgroundJoinError(room, error);
|
||||
return EMPTY;
|
||||
})
|
||||
);
|
||||
}),
|
||||
catchError((error: unknown) => {
|
||||
this.handleBackgroundJoinError(room, error);
|
||||
return EMPTY;
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
private handleBackgroundJoinError(room: Room, error: unknown): void {
|
||||
@@ -414,7 +425,17 @@ export class ServersRailComponent {
|
||||
|| (typeof status === 'number' && status >= 500);
|
||||
}
|
||||
|
||||
private toRoomRefreshChanges(room: Room, server: ServerInfo): Partial<Room> {
|
||||
private toRoomRefreshChanges(room: Room, server: ServerInfo, signalingUrl?: string): Partial<Room> {
|
||||
const resolvedSource = this.serverDirectory.normaliseRoomSignalSource({
|
||||
sourceId: server.sourceId ?? room.sourceId,
|
||||
sourceName: server.sourceName ?? room.sourceName,
|
||||
sourceUrl: server.sourceUrl ?? room.sourceUrl,
|
||||
signalingUrl,
|
||||
fallbackName: server.sourceName ?? room.sourceName ?? room.name
|
||||
}, {
|
||||
ensureEndpoint: true
|
||||
});
|
||||
|
||||
return {
|
||||
name: server.name,
|
||||
description: server.description,
|
||||
@@ -432,9 +453,99 @@ export class ServersRailComponent {
|
||||
Array.isArray(server.channels) && server.channels.length > 0
|
||||
? server.channels
|
||||
: room.channels,
|
||||
sourceId: server.sourceId ?? room.sourceId,
|
||||
sourceName: server.sourceName ?? room.sourceName,
|
||||
sourceUrl: server.sourceUrl ?? room.sourceUrl
|
||||
...resolvedSource
|
||||
};
|
||||
}
|
||||
|
||||
private async resolveRoomJoinTarget(room: Room): Promise<{
|
||||
room: Room;
|
||||
selector: ReturnType<ServerDirectoryFacade['buildRoomSignalSelector']>;
|
||||
}> {
|
||||
let resolvedRoom = this.applyResolvedRoomSource(room, this.serverDirectory.normaliseRoomSignalSource({
|
||||
sourceId: room.sourceId,
|
||||
sourceName: room.sourceName,
|
||||
sourceUrl: room.sourceUrl,
|
||||
fallbackName: room.sourceName ?? room.name
|
||||
}, {
|
||||
ensureEndpoint: !!room.sourceUrl
|
||||
}));
|
||||
let selector = this.serverDirectory.buildRoomSignalSelector({
|
||||
sourceId: resolvedRoom.sourceId,
|
||||
sourceName: resolvedRoom.sourceName,
|
||||
sourceUrl: resolvedRoom.sourceUrl,
|
||||
fallbackName: resolvedRoom.sourceName ?? resolvedRoom.name
|
||||
}, {
|
||||
ensureEndpoint: !!resolvedRoom.sourceUrl
|
||||
});
|
||||
|
||||
const authoritativeServer = (
|
||||
selector
|
||||
? await firstValueFrom(this.serverDirectory.getServer(room.id, selector))
|
||||
: null
|
||||
) ?? await firstValueFrom(this.serverDirectory.findServerAcrossActiveEndpoints(room.id, {
|
||||
sourceId: resolvedRoom.sourceId,
|
||||
sourceName: resolvedRoom.sourceName,
|
||||
sourceUrl: resolvedRoom.sourceUrl,
|
||||
fallbackName: resolvedRoom.sourceName ?? resolvedRoom.name
|
||||
}));
|
||||
|
||||
if (!authoritativeServer) {
|
||||
return {
|
||||
room: resolvedRoom,
|
||||
selector
|
||||
};
|
||||
}
|
||||
|
||||
const authoritativeSource = this.serverDirectory.normaliseRoomSignalSource({
|
||||
sourceId: authoritativeServer.sourceId ?? resolvedRoom.sourceId,
|
||||
sourceName: authoritativeServer.sourceName ?? resolvedRoom.sourceName,
|
||||
sourceUrl: authoritativeServer.sourceUrl ?? resolvedRoom.sourceUrl,
|
||||
fallbackName: authoritativeServer.sourceName ?? resolvedRoom.sourceName ?? resolvedRoom.name
|
||||
}, {
|
||||
ensureEndpoint: !!(authoritativeServer.sourceUrl ?? resolvedRoom.sourceUrl)
|
||||
});
|
||||
|
||||
resolvedRoom = this.applyResolvedRoomSource(resolvedRoom, authoritativeSource);
|
||||
selector = this.serverDirectory.buildRoomSignalSelector({
|
||||
sourceId: resolvedRoom.sourceId,
|
||||
sourceName: resolvedRoom.sourceName,
|
||||
sourceUrl: resolvedRoom.sourceUrl,
|
||||
fallbackName: resolvedRoom.sourceName ?? resolvedRoom.name
|
||||
}, {
|
||||
ensureEndpoint: !!resolvedRoom.sourceUrl
|
||||
});
|
||||
|
||||
return {
|
||||
room: resolvedRoom,
|
||||
selector
|
||||
};
|
||||
}
|
||||
|
||||
private applyResolvedRoomSource(room: Room, source: Pick<Room, 'sourceId' | 'sourceName' | 'sourceUrl'>): Room {
|
||||
const nextRoom: Room = {
|
||||
...room,
|
||||
sourceId: source.sourceId,
|
||||
sourceName: source.sourceName,
|
||||
sourceUrl: source.sourceUrl
|
||||
};
|
||||
|
||||
if (
|
||||
room.sourceId === nextRoom.sourceId
|
||||
&& room.sourceName === nextRoom.sourceName
|
||||
&& room.sourceUrl === nextRoom.sourceUrl
|
||||
) {
|
||||
return room;
|
||||
}
|
||||
|
||||
this.store.dispatch(RoomsActions.updateRoom({
|
||||
roomId: room.id,
|
||||
changes: {
|
||||
sourceId: nextRoom.sourceId,
|
||||
sourceName: nextRoom.sourceName,
|
||||
sourceUrl: nextRoom.sourceUrl
|
||||
}
|
||||
}));
|
||||
|
||||
return nextRoom;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user