Model ConnectionState as a discriminated union

The enum mixed our own lifecycle states with a copy of livekit-client's
connection states, and errors were smuggled through the same observable as
a separate union member. A discriminated union keeps the LiveKit state
nested under "authenticated", carries the error as data, and lets the
local member represent the time before a connection exists as an
"initializing" state instead of null.
This commit is contained in:
Robin
2026-10-12 10:08:22 +02:00
committed by Johannes Marbach
parent 3f030e64dd
commit 4e4ab23cda
5 changed files with 134 additions and 97 deletions
@@ -6,6 +6,7 @@ Please see LICENSE in the repository root for full details.
*/
import {
ConnectionState as LivekitConnectionState,
type Participant,
ParticipantEvent,
type LocalParticipant,
@@ -74,9 +75,8 @@ import {
} from "../../../config/ConfigOptions.ts";
import { Config } from "../../../config/Config.ts";
import {
ConnectionState,
type ConnectionState,
type Connection,
type FailedToStartError,
} from "../remoteMembers/Connection.ts";
import { type HomeserverConnected } from "./HomeserverConnected.ts";
import { type LocalTransport } from "./LocalTransport.ts";
@@ -113,7 +113,7 @@ export enum TrackState {
export type LocalMemberMediaState =
| {
tracks: TrackState;
connection: ConnectionState | FailedToStartError;
connection: ConnectionState;
}
| PublishState
| ElementCallError;
@@ -475,7 +475,9 @@ export const createLocalMembership$ = ({
};
const localConnectionState$ = localConnection$.pipe(
switchMap((connection) => (connection ? connection.state$ : of(null))),
switchMap((connection) =>
connection ? connection.state$ : of({ state: "initializing" as const }),
),
);
const mediaState$: Behavior<LocalMemberMediaState> = scope.behavior(
@@ -493,7 +495,9 @@ export const createLocalMembership$ = ({
: TrackState.WaitingForUser;
if (
localConnectionState !== ConnectionState.LivekitConnected ||
localConnectionState.state !== "authenticated" ||
localConnectionState.livekitState !==
LivekitConnectionState.Connected ||
trackState !== TrackState.Ready
)
return {
@@ -561,7 +565,11 @@ export const createLocalMembership$ = ({
combineLatest([
homeserverConnected.combined$,
localConnectionState$.pipe(
map((state) => state === ConnectionState.LivekitConnected),
map(
(state) =>
state.state === "authenticated" &&
state.livekitState === LivekitConnectionState.Connected,
),
),
]).pipe(
map(([[hsConnected, hsReason], livekitConnected]) => {