fix: Broken voice states and connectivity drops

This commit is contained in:
2026-04-11 12:32:22 +02:00
parent 0865c2fe33
commit ef1182d46f
28 changed files with 1244 additions and 162 deletions

View File

@@ -0,0 +1,46 @@
import {
areRoomSignalSourcesEqual,
buildRoomSignalSelector,
buildRoomSignalSource,
getSourceUrlFromSignalingUrl
} from './room-signal-source';
describe('room-signal-source helpers', () => {
it('converts signaling urls back to normalized source urls', () => {
expect(getSourceUrlFromSignalingUrl('wss://signal.toju.app')).toBe('https://signal.toju.app');
expect(getSourceUrlFromSignalingUrl('ws://46.59.68.77:3001')).toBe('http://46.59.68.77:3001');
});
it('prefers the resolved endpoint when normalizing a room source', () => {
expect(buildRoomSignalSource({
sourceId: 'stale-id',
sourceName: 'Stale Source',
sourceUrl: 'https://old.example.com',
signalingUrl: 'wss://signal.toju.app'
}, {
id: 'primary-id',
name: 'Primary Signal',
url: 'https://signal.toju.app/'
})).toEqual({
sourceId: 'primary-id',
sourceName: 'Primary Signal',
sourceUrl: 'https://signal.toju.app'
});
});
it('builds selectors from signaling urls when no source url is persisted yet', () => {
expect(buildRoomSignalSelector({
signalingUrl: 'wss://signal-sweden.toju.app',
fallbackName: 'Toju Signal Sweden'
})).toEqual({
sourceUrl: 'https://signal-sweden.toju.app'
});
});
it('treats equivalent persisted and signaling-derived sources as equal', () => {
expect(areRoomSignalSourcesEqual(
{ sourceUrl: 'https://signal.toju.app/' },
{ signalingUrl: 'wss://signal.toju.app' }
)).toBeTrue();
});
});

View File

@@ -0,0 +1,95 @@
import type { ServerEndpoint, ServerSourceSelector } from './server-directory.models';
import { normaliseConfiguredServerUrl, sanitiseServerBaseUrl } from './server-endpoint-defaults';
export interface RoomSignalSource {
sourceId?: string;
sourceName?: string;
sourceUrl?: string;
}
export interface RoomSignalSourceInput extends RoomSignalSource {
fallbackName?: string;
signalingUrl?: string;
}
const DEFAULT_SIGNAL_SOURCE_NAME = 'Signal Server';
export function getSourceUrlFromSignalingUrl(signalingUrl?: string): string | undefined {
const normalizedUrl = normalizeString(signalingUrl);
if (!normalizedUrl) {
return undefined;
}
const resolvedUrl = normaliseConfiguredServerUrl(normalizedUrl, 'https');
return resolvedUrl || undefined;
}
export function buildRoomSignalSource(
source?: RoomSignalSourceInput | null,
endpoint?: Pick<ServerEndpoint, 'id' | 'name' | 'url'> | null
): RoomSignalSource {
const sourceId = normalizeString(endpoint?.id) ?? normalizeString(source?.sourceId);
const sourceUrl = endpoint
? sanitiseServerBaseUrl(endpoint.url)
: (normalizeUrl(source?.sourceUrl) ?? getSourceUrlFromSignalingUrl(source?.signalingUrl));
const sourceName = normalizeString(endpoint?.name)
?? normalizeString(source?.sourceName)
?? normalizeString(source?.fallbackName)
?? (sourceUrl ? DEFAULT_SIGNAL_SOURCE_NAME : undefined);
return {
sourceId,
sourceName,
sourceUrl
};
}
export function buildRoomSignalSelector(
source?: RoomSignalSourceInput | null
): ServerSourceSelector | undefined {
const normalizedSource = buildRoomSignalSource(source);
if (normalizedSource.sourceId) {
return { sourceId: normalizedSource.sourceId };
}
if (normalizedSource.sourceUrl) {
return { sourceUrl: normalizedSource.sourceUrl };
}
return undefined;
}
export function hasRoomSignalSource(source?: RoomSignalSourceInput | null): boolean {
return !!buildRoomSignalSelector(source);
}
export function areRoomSignalSourcesEqual(
left?: RoomSignalSourceInput | null,
right?: RoomSignalSourceInput | null
): boolean {
const normalizedLeft = buildRoomSignalSource(left);
const normalizedRight = buildRoomSignalSource(right);
return normalizedLeft.sourceId === normalizedRight.sourceId
&& normalizedLeft.sourceName === normalizedRight.sourceName
&& normalizedLeft.sourceUrl === normalizedRight.sourceUrl;
}
function normalizeString(value: string | undefined | null): string | undefined {
if (typeof value !== 'string') {
return undefined;
}
const trimmed = value.trim();
return trimmed || undefined;
}
function normalizeUrl(value: string | undefined | null): string | undefined {
const normalizedValue = normalizeString(value);
return normalizedValue ? sanitiseServerBaseUrl(normalizedValue) : undefined;
}

View File

@@ -45,12 +45,14 @@ export interface DefaultServerDefinition {
}
export interface ServerEndpointVersions {
serverInstanceId?: string | null;
serverVersion?: string | null;
clientVersion?: string | null;
}
export interface ServerEndpoint {
id: string;
instanceId?: string;
name: string;
url: string;
isActive: boolean;
@@ -135,6 +137,7 @@ export interface ServerVersionCompatibilityResult {
}
export interface ServerHealthCheckPayload {
serverInstanceId?: unknown;
serverVersion?: unknown;
}