@defcomm/meetingsdk 0.5.6 → 0.5.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +109 -51
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +109 -51
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/react/useLocalParticipant.tsx","../src/react/MeetingProvider.tsx","../src/config/ws.ts","../src/core/ActiveSpeakerDetector.ts","../src/core/MeetingState.ts","../src/core/SFUClient.ts","../src/core/VideoCore.ts","../src/react/useMeetingStore.ts","../src/react/useMeeting.ts","../src/react/useParticipants.ts","../src/react/useRemoteMedia.ts","../src/react/useMeetingPreview.ts","../src/react/useLiveTranscript.ts","../src/react/useNetworkQuality.ts","../src/react/usePubSub.ts"],"sourcesContent":["import { useCallback, useEffect, useRef, useState } from \"react\";\nimport { useMeetingContext } from \"./MeetingProvider\";\nimport { Participant } from \"../types/meeting\";\n\nexport const useLocalParticipant = () => {\n const { sdk } = useMeetingContext();\n\n // Guard the initial state to ensure it matches Participant | null\n const [localParticipant, setLocalParticipant] = useState<Participant | null>(\n () => {\n const current = sdk.state.localParticipant;\n return current && current.id ? (current as Participant) : null;\n },\n );\n\n useEffect(() => {\n const unsubscribe = sdk.state.subscribe(\"localParticipant\", () => {\n const current = sdk.state.localParticipant;\n\n // Safe Type-Guard: Only update if the object has a finalized id\n if (current && current.id) {\n setLocalParticipant({ ...current } as Participant);\n } else {\n setLocalParticipant(null);\n }\n });\n\n return unsubscribe;\n }, [sdk]);\n\n const lastStreamRef = useRef<MediaStream | null>(null);\n\n const videoRef = useCallback(\n (video: HTMLVideoElement | null) => {\n if (!video) return;\n\n const stream = localParticipant?.media?.stream;\n if (!stream) return;\n\n if (lastStreamRef.current === stream) return;\n lastStreamRef.current = stream;\n\n video.srcObject = stream;\n video.autoplay = true;\n video.playsInline = true;\n\n video.play().catch((err) => {\n console.warn(`Autoplay failed for local view:`, err);\n });\n },\n [localParticipant?.media?.stream],\n );\n\n return {\n participant: localParticipant,\n videoRef,\n };\n};\n","import React, {\n createContext,\n useContext,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport { VideoSDKCore } from \"../core/VideoCore\";\nimport {\n ChatInput,\n ChatMessage,\n Reaction,\n MeetingConfig,\n Participant,\n PubSubTopic,\n RecordingInfo,\n Recording,\n SFUConnectionState,\n JoinState,\n PubSubHandleForTopic,\n PubSubMessage,\n PubSubTopicConfig,\n LiveTranscript,\n NetworkQuality,\n} from \"../types/meeting\";\nimport { useMeetingStore } from \"./useMeetingStore\";\n\ntype MeetingContextValue = {\n sdk: VideoSDKCore;\n join: (\n config?: Omit<MeetingConfig, \"participantId\" | \"token\">,\n ) => Promise<void>;\n getJoinState: (roomCode: string) => Promise<JoinState>;\n leave: () => void;\n createRoom: (input: {\n name: string;\n description?: string;\n capacity?: number;\n is_private?: boolean;\n }) => Promise<any>;\n getRoom: (roomCode: string) => Promise<any>;\n deleteRoom: (roomCode: string) => Promise<any>;\n toggleMic: () => void;\n toggleCam: () => void;\n startScreenShare: () => Promise<MediaStream | null>;\n stopScreenShare: () => void;\n sendMessage: (input: ChatInput) => void;\n sendReaction: (emoji: string) => void;\n room: { id: string | null; name: string | null };\n localParticipant: Participant | null;\n participants: Map<string, Participant>;\n messages: ChatMessage[];\n presenterId: string | null;\n activeSpeakerIds: string[];\n liveTranscripts: LiveTranscript[];\n networkQuality: NetworkQuality | null;\n startLiveTranscription: () => Promise<void>;\n stopLiveTranscription: () => void;\n isLiveTranscriptionActive: () => boolean;\n recording: RecordingInfo | null;\n usePubSub: <T extends PubSubTopic>(topic: T) => PubSubHandleForTopic<T>;\n onPubSubMessage: <T extends PubSubTopic>(\n topic: T,\n cb: (message: PubSubMessage<PubSubTopicConfig[T][\"message\"]>) => void,\n ) => () => void;\n approveJoinRequest: (requestId: string) => void;\n rejectJoinRequest: (requestId: string) => void;\n cancelJoinRequest: (requestId?: string) => Promise<void> | undefined;\n muteAllAudio: () => Promise<void>;\n muteParticipant: (participantId: string) => Promise<void>;\n removeParticipant: (participantId: string) => Promise<void>;\n getModerators: (roomCode: string) => Promise<any> | undefined;\n addModerator: (roomCode: string, userId: string) => Promise<any> | undefined;\n removeModerator: (\n roomCode: string,\n userId: string,\n ) => Promise<any> | undefined;\n startRecording: () => Promise<void>;\n stopRecording: () => Promise<void>;\n getRecordingStatus: () => Promise<any>;\n onError: (cb: (err: any) => void) => () => void;\n onEntryRequested: (cb: (req: any) => void) => () => void;\n onEntryResponded: (cb: (payload: any, decision?: any) => void) => () => void;\n onJoinRequestCanceled: (cb: (requestId: string) => void) => () => void;\n onParticipantRemoved: (\n cb: (participantId: string, removedBy: string) => void,\n ) => () => void;\n onParticipantPermissionsChanged: (\n cb: (participantId: string, permissions: any) => void,\n ) => () => void;\n onMeetingLeft: (cb: () => void) => () => void;\n onTrackStateChanged: (cb: (track: any) => void) => () => void;\n onRecordingStarted: (cb: (recording: Recording) => void) => () => void;\n onRecordingStopped: (cb: (recording: any) => void) => () => void;\n onReaction: (cb: (reaction: Reaction) => void) => () => void;\n onConnectionStateChanged: (\n cb: (state: SFUConnectionState) => void,\n ) => () => void;\n onActiveSpeakersChanged: (\n cb: (participantIds: string[]) => void,\n ) => () => void;\n onNetworkQuality: (cb: (quality: NetworkQuality) => void) => () => void;\n\n onLiveTranscript: (cb: (transcript: LiveTranscript) => void) => () => void;\n};\n\nconst MeetingContext = createContext<MeetingContextValue | null>(null);\n\nexport const MeetingProvider = ({\n config,\n children,\n}: {\n config: MeetingConfig;\n children: React.ReactNode;\n}) => {\n const sdkRef = useRef<VideoSDKCore | null>(null);\n const errorListeners = useRef(new Set<(err: any) => void>());\n const entryRequestListeners = useRef(new Set<(req: any) => void>());\n const entryResponseListeners = useRef(\n new Set<(payload: any, decision?: any) => void>(),\n );\n const joinRequestCanceledListeners = useRef(\n new Set<(requestId: string) => void>(),\n );\n const participantRemovedListeners = useRef(\n new Set<(participantId: string, removedBy: string) => void>(),\n );\n const participantPermissionsChangedListeners = useRef(\n new Set<(participantId: string, permissions: any) => void>(),\n );\n const meetingLeftListeners = useRef(new Set<() => void>());\n const trackStateListeners = useRef(new Set<(track: any) => void>());\n const recordingStartedListeners = useRef(new Set<(recording: any) => void>());\n const recordingStoppedListeners = useRef(new Set<(recording: any) => void>());\n const reactionListeners = useRef(new Set<(reaction: Reaction) => void>());\n const pubSubListeners = useRef(\n new Map<PubSubTopic, Set<(message: PubSubMessage<any>) => void>>(),\n );\n const [reactionPubSubMessages, setReactionPubSubMessages] = useState<\n PubSubMessage<{ emoji: string }>[]\n >([]);\n const activeSpeakerListeners = useRef(\n new Set<(participantIds: string[]) => void>(),\n );\n const liveTranscriptListeners = useRef(\n new Set<(transcript: LiveTranscript) => void>(),\n );\n const networkQualityListeners = useRef(\n new Set<(quality: NetworkQuality) => void>(),\n );\n const connectionStateListeners = useRef(\n new Set<(state: SFUConnectionState) => void>(),\n );\n\n if (!sdkRef.current) {\n sdkRef.current = new VideoSDKCore(\n {\n participantId: config.participantId,\n token: config.token,\n },\n {\n onError: (err) => {\n errorListeners.current.forEach((fn) => fn(err));\n },\n\n onEntryRequested: (req) => {\n entryRequestListeners.current.forEach((fn) => fn(req));\n },\n\n onEntryResponded: (p, d) => {\n entryResponseListeners.current.forEach((fn) => fn(p, d));\n },\n\n onJoinRequestCanceled: (requestId) => {\n joinRequestCanceledListeners.current.forEach((fn) => fn(requestId));\n },\n\n onParticipantRemoved: (participantId, removedBy) => {\n participantRemovedListeners.current.forEach((fn) =>\n fn(participantId, removedBy),\n );\n },\n\n onParticipantPermissionsChanged: (participantId, permissions) => {\n participantPermissionsChangedListeners.current.forEach((fn) =>\n fn(participantId, permissions),\n );\n },\n\n onMeetingLeft: () => {\n meetingLeftListeners.current.forEach((fn) => fn());\n },\n\n onTrackStateChanged: (track) => {\n trackStateListeners.current.forEach((fn) => fn(track));\n },\n\n onRecordingStarted: (recording) => {\n recordingStartedListeners.current.forEach((fn) => fn(recording));\n },\n\n onRecordingStopped: (recording) => {\n recordingStoppedListeners.current.forEach((fn) => fn(recording));\n },\n\n onChatMessage: (message) => {\n const msg: ChatMessage = {\n id: message.id,\n text: message.text,\n sender_id: message.sender_id,\n sender_name: message.sender_name,\n timestamp: Number(message.timestamp),\n reply_to: message.reply_to ?? null,\n target: message.target ?? null,\n };\n\n const pubSubMessage: PubSubMessage<ChatMessage> = {\n id: msg.id,\n topic: \"SECURE_CHAT\",\n sender_id: msg.sender_id,\n sender_name: msg.sender_name,\n timestamp: msg.timestamp,\n data: msg,\n };\n\n pubSubListeners.current\n .get(\"SECURE_CHAT\")\n ?.forEach((fn) => fn(pubSubMessage));\n },\n\n onReaction: (reaction) => {\n reactionListeners.current.forEach((fn) => fn(reaction));\n\n const timestamp =\n typeof reaction.timestamp === \"number\"\n ? reaction.timestamp\n : Date.parse(reaction.timestamp);\n\n const message: PubSubMessage<{ emoji: string }> = {\n id: reaction.id,\n topic: \"REACTION\",\n sender_id: reaction.participant_id,\n sender_name: reaction.sender_name,\n timestamp,\n data: {\n emoji: reaction.emoji,\n },\n };\n\n console.log(\"[MeetingProvider] PUBSUB REACTION\", message);\n setReactionPubSubMessages((previous) =>\n [...previous, message].slice(-50),\n );\n\n pubSubListeners.current.get(\"REACTION\")?.forEach((fn) => fn(message));\n },\n onLiveTranscript: (transcript) => {\n liveTranscriptListeners.current.forEach((fn) => fn(transcript));\n },\n\n onNetworkQuality: (quality) => {\n networkQualityListeners.current.forEach((fn) => fn(quality));\n },\n\n onConnectionStateChanged: (state) => {\n connectionStateListeners.current.forEach((fn) =>\n fn(state as SFUConnectionState),\n );\n },\n },\n );\n }\n const sdk = sdkRef.current;\n const activeSpeakerIds = useMeetingStore(sdk.state, \"activeSpeakers\", (s) =>\n Array.from(s.activeSpeakerIds),\n );\n const recording = useMeetingStore(sdk.state, \"recording\", (s) => s.recording);\n const presenterId = useMeetingStore(\n sdk.state,\n \"presenter\",\n (s) => s.presenterId,\n );\n const participants = useMeetingStore(\n sdk.state,\n \"participants\",\n (s) => s.participants,\n );\n const localParticipant = useMeetingStore(\n sdk.state,\n \"localParticipant\",\n (s) => s.localParticipant,\n );\n const messages = useMeetingStore(sdk.state, \"chat\", (s) =>\n s.getChatMessages(),\n );\n const liveTranscripts = useMeetingStore(sdk.state, \"transcript\", (s) =>\n s.getLiveTranscripts(),\n );\n const networkQuality = useMeetingStore(\n sdk.state,\n \"networkQuality\",\n (s) => s.networkQuality,\n );\n\n const value = useMemo<MeetingContextValue>(() => {\n return {\n sdk,\n join: (joinConfig?: Omit<MeetingConfig, \"participantId\" | \"token\">) =>\n sdk.joinMeeting({\n ...config,\n ...joinConfig,\n }),\n getJoinState: (roomCode: string) => sdk.getJoinState(roomCode),\n leave: () => sdk.disconnect(),\n createRoom: sdk.createRoom.bind(sdk),\n getRoom: sdk.getRoom.bind(sdk),\n deleteRoom: sdk.deleteRoom.bind(sdk),\n toggleMic: sdk.toggleMic.bind(sdk),\n toggleCam: sdk.toggleCam.bind(sdk),\n startScreenShare: sdk.startScreenShare.bind(sdk),\n stopScreenShare: sdk.stopScreenShare.bind(sdk),\n sendMessage: sdk.sendChatMessage.bind(sdk),\n sendReaction: sdk.sendReaction.bind(sdk),\n room: sdk.getMeeting(),\n localParticipant,\n participants,\n messages,\n presenterId,\n activeSpeakerIds,\n liveTranscripts,\n networkQuality,\n startLiveTranscription: sdk.startLiveTranscription.bind(sdk),\n stopLiveTranscription: sdk.stopLiveTranscription.bind(sdk),\n isLiveTranscriptionActive: sdk.isLiveTranscriptionActive.bind(sdk),\n recording,\n usePubSub: <T extends PubSubTopic>(topic: T): PubSubHandleForTopic<T> => {\n if (topic === \"SECURE_CHAT\") {\n const chatMessages: PubSubMessage<ChatMessage>[] = messages.map(\n (message) => ({\n id: message.id,\n topic: \"SECURE_CHAT\",\n sender_id: message.sender_id,\n sender_name: message.sender_name,\n timestamp: message.timestamp,\n data: message,\n }),\n );\n\n return {\n messages: chatMessages,\n publish: ((data: ChatInput) => {\n sdk.publishPubSub(\"SECURE_CHAT\", data);\n }) as PubSubHandleForTopic<T>[\"publish\"],\n } as PubSubHandleForTopic<T>;\n }\n\n if (topic === \"REACTION\") {\n return {\n messages: reactionPubSubMessages,\n publish: ((data: { emoji: string }) => {\n if (!data?.emoji) {\n console.warn(\"[PubSub] REACTION requires an emoji\");\n return;\n }\n sdk.publishPubSub(\"REACTION\", data);\n }) as PubSubHandleForTopic<T>[\"publish\"],\n } as PubSubHandleForTopic<T>;\n }\n\n throw new Error(`Unsupported PubSub topic: \"${topic}\"`);\n },\n onPubSubMessage: <T extends PubSubTopic>(\n topic: T,\n cb: (message: PubSubMessage<PubSubTopicConfig[T][\"message\"]>) => void,\n ) => {\n let listeners = pubSubListeners.current.get(topic);\n\n if (!listeners) {\n listeners = new Set();\n pubSubListeners.current.set(topic, listeners);\n }\n\n listeners.add(cb as (message: PubSubMessage<any>) => void);\n\n return () => {\n listeners?.delete(cb as (message: PubSubMessage<any>) => void);\n\n if (listeners?.size === 0) {\n pubSubListeners.current.delete(topic);\n }\n };\n },\n approveJoinRequest: sdk.approveJoinRequest.bind(sdk),\n rejectJoinRequest: sdk.rejectJoinRequest.bind(sdk),\n cancelJoinRequest: sdk.cancelJoinRequest.bind(sdk),\n muteAllAudio: sdk.muteAllAudio.bind(sdk),\n muteParticipant: sdk.muteParticipant.bind(sdk),\n removeParticipant: sdk.removeParticipant.bind(sdk),\n getModerators: sdk.getModerators.bind(sdk),\n addModerator: sdk.addModerator.bind(sdk),\n removeModerator: sdk.removeModerator.bind(sdk),\n startRecording: sdk.startRecording.bind(sdk),\n stopRecording: sdk.stopRecording.bind(sdk),\n getRecordingStatus: sdk.getRecordingStatus.bind(sdk),\n\n onError: (cb: (err: any) => void) => {\n errorListeners.current.add(cb);\n\n return () => {\n errorListeners.current.delete(cb);\n };\n },\n\n onEntryRequested: (cb: (err: any) => void) => {\n entryRequestListeners.current.add(cb);\n\n return () => {\n entryRequestListeners.current.delete(cb);\n };\n },\n onEntryResponded: (cb: (err: any) => void) => {\n entryResponseListeners.current.add(cb);\n\n return () => {\n entryResponseListeners.current.delete(cb);\n };\n },\n onJoinRequestCanceled: (cb: (requestId: string) => void) => {\n joinRequestCanceledListeners.current.add(cb);\n return () => {\n joinRequestCanceledListeners.current.delete(cb);\n };\n },\n onParticipantRemoved: (\n cb: (participantId: string, removedBy: string) => void,\n ) => {\n participantRemovedListeners.current.add(cb);\n return () => {\n participantRemovedListeners.current.delete(cb);\n };\n },\n onParticipantPermissionsChanged: (\n cb: (participantId: string, permissions: any) => void,\n ) => {\n participantPermissionsChangedListeners.current.add(cb);\n return () => {\n participantPermissionsChangedListeners.current.delete(cb);\n };\n },\n onMeetingLeft: (cb: () => void) => {\n meetingLeftListeners.current.add(cb);\n return () => {\n meetingLeftListeners.current.delete(cb);\n };\n },\n onTrackStateChanged: (cb: (track: any) => void) => {\n trackStateListeners.current.add(cb);\n return () => trackStateListeners.current.delete(cb);\n },\n onRecordingStarted: (cb: (recording: any) => void) => {\n recordingStartedListeners.current.add(cb);\n return () => recordingStartedListeners.current.delete(cb);\n },\n onRecordingStopped: (cb: (recording: any) => void) => {\n recordingStoppedListeners.current.add(cb);\n return () => recordingStoppedListeners.current.delete(cb);\n },\n onReaction: (cb: (reaction: Reaction) => void) => {\n reactionListeners.current.add(cb);\n return () => reactionListeners.current.delete(cb);\n },\n onLiveTranscript: (cb: {\n (transcript: LiveTranscript): void;\n (transcript: LiveTranscript): void;\n }) => {\n liveTranscriptListeners.current.add(cb);\n return () => liveTranscriptListeners.current.delete(cb);\n },\n onNetworkQuality: (cb: {\n (quality: NetworkQuality): void;\n (quality: NetworkQuality): void;\n }) => {\n networkQualityListeners.current.add(cb);\n return () => networkQualityListeners.current.delete(cb);\n },\n onConnectionStateChanged: (cb) => {\n connectionStateListeners.current.add(cb);\n\n return () => {\n connectionStateListeners.current.delete(cb);\n };\n },\n onActiveSpeakersChanged: (cb) => {\n activeSpeakerListeners.current.add(cb);\n\n return () => {\n activeSpeakerListeners.current.delete(cb);\n };\n },\n };\n }, [\n config,\n sdk,\n localParticipant,\n participants,\n messages,\n presenterId,\n recording,\n activeSpeakerIds,\n liveTranscripts,\n networkQuality,\n reactionPubSubMessages,\n ]);\n\n return (\n <MeetingContext.Provider value={value}>{children}</MeetingContext.Provider>\n );\n};\n\nexport const useMeetingContext = () => {\n const ctx = useContext(MeetingContext);\n if (!ctx)\n throw new Error(\"useMeetingContext must be used inside <MeetingProvider>\");\n return ctx;\n};\n","/**\n * SDK Configuration for WebSocket and SFU connections\n * Updated to support the new Selective Forwarding Unit (SFU) architecture\n */\n\nexport interface SDKConfig {\n apiBase: string;\n wsBase: string;\n iceServers?: RTCIceServer[];\n connectionTimeout?: number;\n maxReconnectAttempts?: number;\n}\n\nexport const SDK_CONFIG: SDKConfig = {\n apiBase: \"https://meetingsdk.defcomm.ng/api\",\n wsBase: \"wss://meetingsdk.defcomm.ng/ws\",\n // Public STUN/TURN servers (fallback)\n iceServers: [\n { urls: [\"stun:stun.l.google.com:19302\"] },\n { urls: [\"stun:stun1.l.google.com:19302\"] },\n ],\n // Connection and reconnection settings\n connectionTimeout: 10000,\n maxReconnectAttempts: 5,\n};\n","type SpeakerState = {\n participantId: string;\n track: MediaStreamTrack;\n stream: MediaStream;\n source: MediaStreamAudioSourceNode;\n analyser: AnalyserNode;\n data: Float32Array<ArrayBuffer>;\n active: boolean;\n lastActiveAt: number;\n};\n\nexport interface ActiveSpeakerDetectorOptions {\n intervalMs?: number;\n threshold?: number;\n releaseThreshold?: number;\n releaseMs?: number;\n onActiveSpeakersChanged?: (participantIds: string[]) => void;\n}\n\nexport class ActiveSpeakerDetector {\n private audioContext: AudioContext | null = null;\n\n private speakers = new Map<string, SpeakerState>();\n\n private timer: ReturnType<typeof setInterval> | null = null;\n\n private readonly intervalMs: number;\n private readonly threshold: number;\n private readonly releaseThreshold: number;\n private readonly releaseMs: number;\n\n private onActiveSpeakersChanged: (participantIds: string[]) => void;\n\n private lastEmitted = \"\";\n\n constructor(options: ActiveSpeakerDetectorOptions = {}) {\n this.intervalMs = options.intervalMs ?? 100;\n this.threshold = options.threshold ?? 0.025;\n this.releaseThreshold = options.releaseThreshold ?? 0.015;\n this.releaseMs = options.releaseMs ?? 600;\n\n this.onActiveSpeakersChanged =\n options.onActiveSpeakersChanged ?? (() => {});\n }\n\n private ensureAudioContext(): AudioContext {\n if (!this.audioContext) {\n const AudioContextClass =\n window.AudioContext ||\n (\n window as typeof window & {\n webkitAudioContext?: typeof AudioContext;\n }\n ).webkitAudioContext;\n\n if (!AudioContextClass) {\n throw new Error(\"Web Audio API is not supported by this browser\");\n }\n\n this.audioContext = new AudioContextClass();\n }\n\n return this.audioContext;\n }\n\n async resume() {\n if (!this.audioContext) return;\n\n if (this.audioContext.state === \"suspended\") {\n try {\n await this.audioContext.resume();\n } catch {\n // Browser may require a user gesture.\n }\n }\n }\n\n addTrack(participantId: string, track: MediaStreamTrack) {\n if (!participantId) return;\n\n if (track.kind !== \"audio\") return;\n\n this.removeParticipant(participantId);\n const context = this.ensureAudioContext();\n const stream = new MediaStream([track]);\n const source = context.createMediaStreamSource(stream);\n const analyser = context.createAnalyser();\n\n analyser.fftSize = 512;\n analyser.smoothingTimeConstant = 0.65;\n analyser.minDecibels = -90;\n analyser.maxDecibels = -10;\n\n source.connect(analyser);\n\n const data = new Float32Array(analyser.fftSize);\n\n const state: SpeakerState = {\n participantId,\n track,\n stream,\n source,\n analyser,\n data,\n active: false,\n lastActiveAt: 0,\n };\n\n this.speakers.set(participantId, state);\n\n track.addEventListener(\n \"ended\",\n () => {\n this.removeParticipant(participantId);\n },\n { once: true },\n );\n\n this.start();\n\n void this.resume();\n }\n\n removeParticipant(participantId: string) {\n const state = this.speakers.get(participantId);\n\n if (!state) return;\n\n state.active = false;\n\n try {\n state.source.disconnect();\n } catch {\n // Already disconnected.\n }\n\n state.stream.getTracks().forEach((track) => {\n if (track !== state.track) {\n track.stop();\n }\n });\n\n this.speakers.delete(participantId);\n\n this.emitIfChanged();\n }\n\n removeTrack(track: MediaStreamTrack) {\n for (const [participantId, state] of this.speakers) {\n if (state.track === track) {\n this.removeParticipant(participantId);\n }\n }\n }\n\n clear() {\n for (const participantId of this.speakers.keys()) {\n this.removeParticipant(participantId);\n }\n\n this.speakers.clear();\n\n this.stop();\n\n this.emitIfChanged(true);\n }\n\n start() {\n if (this.timer) return;\n\n this.timer = setInterval(() => this.sample(), this.intervalMs);\n }\n\n stop() {\n if (!this.timer) return;\n\n clearInterval(this.timer);\n this.timer = null;\n }\n\n private sample() {\n const now = performance.now();\n\n for (const state of this.speakers.values()) {\n if (\n state.track.readyState !== \"live\" ||\n state.track.muted ||\n !state.track.enabled\n ) {\n if (state.active) {\n state.active = false;\n }\n\n continue;\n }\n\n state.analyser.getFloatTimeDomainData(state.data);\n\n let sumSquares = 0;\n\n for (let i = 0; i < state.data.length; i++) {\n const sample = state.data[i];\n sumSquares += sample * sample;\n }\n\n const rms = Math.sqrt(sumSquares / state.data.length);\n\n if (!state.active) {\n if (rms >= this.threshold) {\n state.active = true;\n state.lastActiveAt = now;\n }\n } else {\n if (rms >= this.releaseThreshold) {\n state.lastActiveAt = now;\n } else if (now - state.lastActiveAt >= this.releaseMs) {\n state.active = false;\n }\n }\n }\n\n this.emitIfChanged();\n }\n\n private getActiveSpeakerIds(): string[] {\n return Array.from(this.speakers.values())\n .filter((speaker) => speaker.active)\n .map((speaker) => speaker.participantId);\n }\n\n private emitIfChanged(force = false) {\n const ids = this.getActiveSpeakerIds().sort();\n\n const key = ids.join(\"|\");\n\n if (!force && key === this.lastEmitted) {\n return;\n }\n\n this.lastEmitted = key;\n\n this.onActiveSpeakersChanged(ids);\n }\n\n async destroy() {\n this.clear();\n\n if (this.audioContext) {\n try {\n await this.audioContext.close();\n } catch {\n // Ignore already closed context.\n }\n\n this.audioContext = null;\n }\n }\n}\n","import {\n ChatMessage,\n Listener,\n Participant,\n ParticipantMedia,\n StateScope,\n} from \"../types/meeting\";\n\ntype LocalParticipantPatch = {\n id?: string;\n name?: string;\n isHost?: boolean;\n isModerator?: boolean;\n permissions?: any;\n media?: Partial<ParticipantMedia>;\n};\n\nexport class MeetingState {\n participants = new Map<string, Participant>();\n localParticipant: Participant | null = null;\n localStream: MediaStream | null = null;\n chatMessages = new Map<string, ChatMessage>();\n presenterId: string | null = null;\n activeSpeakerIds = new Set<string>();\n recording: import(\"../types/meeting\").RecordingInfo | null = null;\n liveTranscripts: import(\"../types/meeting\").LiveTranscript[] = [];\n networkQuality: import(\"../types/meeting\").NetworkQuality | null = null;\n\n private listeners = new Map<StateScope, Set<Listener>>();\n\n // ---- reactive system ----\n\n subscribe(scope: StateScope, fn: Listener): () => void {\n if (!this.listeners.has(scope)) {\n this.listeners.set(scope, new Set());\n }\n this.listeners.get(scope)!.add(fn);\n\n return () => {\n this.listeners.get(scope)?.delete(fn);\n };\n }\n\n notify(scope: StateScope) {\n this.listeners.get(scope)?.forEach((fn) => fn());\n }\n\n setPresenterId(id: string | null) {\n if (this.presenterId === id) return;\n this.presenterId = id;\n this.notify(\"presenter\");\n this.notify(\"participants\");\n }\n\n setActiveSpeakers(ids: string[]) {\n const next = new Set(ids);\n\n if (\n next.size === this.activeSpeakerIds.size &&\n [...next].every((id) => this.activeSpeakerIds.has(id))\n ) {\n return;\n }\n\n this.activeSpeakerIds = next;\n\n this.notify(\"activeSpeakers\");\n }\n\n setRecording(recording: import(\"../types/meeting\").RecordingInfo | null) {\n this.recording = recording;\n this.notify(\"recording\");\n }\n\n clearRecording() {\n this.recording = null;\n this.notify(\"recording\");\n }\n\n addLiveTranscript(transcript: import(\"../types/meeting\").LiveTranscript) {\n this.liveTranscripts = [...this.liveTranscripts.slice(-499), transcript];\n this.notify(\"transcript\");\n }\n\n getLiveTranscripts() {\n return this.liveTranscripts;\n }\n\n clearLiveTranscripts() {\n this.liveTranscripts = [];\n this.notify(\"transcript\");\n }\n\n setNetworkQuality(quality: import(\"../types/meeting\").NetworkQuality | null) {\n this.networkQuality = quality;\n this.notify(\"networkQuality\");\n }\n\n // ---- participants ----\n\n addParticipant(p: Participant) {\n if (this.participants.has(p.id)) return false;\n // Fix: Immutable Map update\n const next = new Map(this.participants);\n next.set(p.id, p);\n this.participants = next;\n\n this.notify(\"participants\");\n return true;\n }\n\n removeParticipant(id: string) {\n // Fix: Immutable Map update\n const next = new Map(this.participants);\n next.delete(id);\n this.participants = next;\n\n this.notify(\"participants\");\n }\n\n updateParticipantMedia(\n id: string,\n patch: Partial<NonNullable<Participant[\"media\"]>>,\n ) {\n const p = this.participants.get(id);\n if (!p) return;\n\n const updated: Participant = {\n ...p,\n media: {\n stream: null,\n screenStream: undefined,\n cameraTrack: undefined,\n screenTrack: undefined,\n audioTrack: undefined,\n micEnabled: p.media?.micEnabled ?? false,\n camEnabled: p.media?.camEnabled ?? false,\n isScreenSharing: p.media?.isScreenSharing ?? false,\n ...p.media,\n ...patch,\n },\n };\n\n // Keep your clean immutable map update\n const next = new Map(this.participants);\n next.set(id, updated);\n this.participants = next;\n\n this.notify(`participant:${id}`);\n this.notify(\"participants\");\n }\n\n updateLocalParticipant(patch: LocalParticipantPatch) {\n const prev = this.localParticipant;\n\n if (!prev) {\n this.localParticipant = {\n id: patch.id ?? \"\",\n name: patch.name ?? \"\",\n isHost: patch.isHost ?? false,\n isModerator: patch.isModerator ?? false,\n permissions: patch.permissions,\n media: {\n stream: patch.media?.stream ?? null, // ◄ FIX: Capture the stream from the patch here\n screenStream: patch.media?.screenStream,\n cameraTrack: patch.media?.cameraTrack,\n screenTrack: patch.media?.screenTrack,\n audioTrack: patch.media?.audioTrack,\n micEnabled: patch.media?.micEnabled ?? true,\n camEnabled: patch.media?.camEnabled ?? true,\n isScreenSharing: patch.media?.isScreenSharing ?? false,\n },\n };\n\n this.notify(\"localParticipant\");\n return;\n }\n\n const prevMedia = prev.media ?? {\n stream: null,\n screenStream: undefined,\n cameraTrack: undefined,\n screenTrack: undefined,\n audioTrack: undefined,\n micEnabled: true,\n camEnabled: true,\n isScreenSharing: false,\n };\n\n const nextMedia: ParticipantMedia = {\n stream: patch.media?.stream ?? prevMedia.stream,\n screenStream: patch.media?.screenStream ?? prevMedia.screenStream,\n cameraTrack: patch.media?.cameraTrack ?? prevMedia.cameraTrack,\n screenTrack: patch.media?.screenTrack ?? prevMedia.screenTrack,\n audioTrack: patch.media?.audioTrack ?? prevMedia.audioTrack,\n micEnabled: patch.media?.micEnabled ?? prevMedia.micEnabled,\n camEnabled: patch.media?.camEnabled ?? prevMedia.camEnabled,\n isScreenSharing:\n patch.media?.isScreenSharing ?? prevMedia.isScreenSharing,\n };\n\n this.localParticipant = {\n ...prev,\n id: patch.id ?? prev.id,\n name: patch.name ?? prev.name,\n isHost: patch.isHost ?? prev.isHost,\n isModerator: patch.isModerator ?? prev.isModerator,\n permissions: patch.permissions ?? prev.permissions,\n media: nextMedia,\n };\n\n this.notify(\"localParticipant\");\n }\n\n // ---- chat ----\n\n addChatMessage(msg: ChatMessage) {\n this.chatMessages.set(msg.id, msg);\n this.notify(\"chat\");\n }\n\n getChatMessages() {\n return Array.from(this.chatMessages.values()).sort(\n (a, b) => a.timestamp - b.timestamp,\n );\n }\n\n clearChat() {\n this.chatMessages.clear();\n this.notify(\"chat\");\n }\n\n // ---- helpers ----\n\n getParticipants() {\n return Array.from(this.participants.values());\n }\n\n getParticipant(id: string) {\n return this.participants.get(id) ?? null;\n }\n\n resetRemoteState() {\n this.participants.clear();\n this.chatMessages.clear();\n this.presenterId = null;\n this.activeSpeakerIds = new Set();\n this.liveTranscripts = [];\n this.networkQuality = null;\n this.notify(\"participants\");\n this.notify(\"chat\");\n this.notify(\"presenter\");\n this.notify(\"activeSpeakers\");\n this.notify(\"transcript\");\n this.notify(\"networkQuality\");\n }\n}\n","import { JoinState, LiveTranscript, NetworkQuality, Reaction, SFUConnectionState } from \"../types/meeting\";\n\nexport interface TrackInfo {\n track_id: string;\n participant_id: string;\n kind: \"audio\" | \"video\";\n source?: \"camera\" | \"screen\" | \"audio\" | string;\n [key: string]: any;\n}\n\nexport interface ParticipantInfo {\n participant_id: string;\n user_metadata?: { name?: string; [key: string]: any };\n display_name?: string;\n [key: string]: any;\n}\n\nexport interface JoinPendingInfo {\n request_id: string;\n room_code?: string;\n message?: string;\n}\n\ninterface SFUClientOptions {\n apiBase?: string;\n wsBase?: string;\n participantId?: string;\n token?: string;\n onStateChange?: (state: SFUConnectionState) => void;\n onParticipantJoined?: (participant: ParticipantInfo) => void;\n onParticipantLeft?: (participant: string | ParticipantInfo) => void;\n onParticipantPresence?: (participantId: string, presence: string) => void;\n onTrackPublished?: (track: TrackInfo) => void;\n onTrackUnpublished?: (track: TrackInfo) => void;\n onRemoteTrack?: (\n track: MediaStreamTrack,\n stream: MediaStream,\n metadata: TrackInfo,\n ) => void;\n onConnected?: (payload: any, resumed: boolean) => void;\n onDisconnected?: () => void;\n onReconnecting?: (attempt: number) => void;\n onJoinPending?: (info: JoinPendingInfo) => void;\n onJoinApproved?: (requestId: string) => void;\n onJoinRejected?: (requestId: string, reason?: string) => void;\n onJoinRequested?: (request: any) => void;\n onJoinRequestCanceled?: (requestId: string) => void;\n onParticipantRemoved?: (participantId: string, removedBy: string) => void;\n onParticipantPermissionsChanged?: (\n participantId: string,\n permissions: any,\n ) => void;\n onScreenShareStarted?: (participantId: string, track?: TrackInfo) => void;\n onScreenShareStopped?: (participantId: string, trackId?: string) => void;\n onTrackStateChanged?: (track: TrackInfo) => void;\n onRecordingStarted?: (recording: {\n recording_id: string;\n started_at: string;\n }) => void;\n onRecordingStopped?: (recording: {\n recording_id: string;\n stopped_at: string;\n }) => void;\n onError?: (error: any) => void;\n onChatMessage?: (message: any) => void;\n onReaction?: (reaction: Reaction) => void;\n onRoomUpdate?: (data: any) => void;\n onLiveTranscript?: (transcript: LiveTranscript) => void;\n onNetworkQuality?: (quality: NetworkQuality) => void;\n onParticipantMediaState?: (\n participantId: string,\n audioMuted: boolean,\n videoMuted: boolean,\n ) => void;\n autoSubscribe?: boolean;\n}\n\ntype PeerName = \"publisher\" | \"subscriber\";\ntype JoinWaiter = {\n resolve: (value: any) => void;\n reject: (error: any) => void;\n};\n\nexport class SFUClient {\n private apiBase: string;\n private wsBase: string;\n private participantId: string;\n\n private ws: WebSocket | null = null;\n private publisher: RTCPeerConnection | null = null;\n private subscriber: RTCPeerConnection | null = null;\n\n private localStream: MediaStream | null = null;\n private screenStream: MediaStream | null = null;\n private videoSender: RTCRtpSender | null = null;\n private audioSender: RTCRtpSender | null = null;\n private screenSender: RTCRtpSender | null = null;\n private audioTransceiver: RTCRtpTransceiver | null = null;\n private cameraTransceiver: RTCRtpTransceiver | null = null;\n private screenTransceiver: RTCRtpTransceiver | null = null;\n\n private iceServers: RTCIceServer[] = [];\n private requestId = 0;\n private publisherRevision = 0;\n private screenShareGeneration = 0;\n private currentParticipantId: string | null = null;\n // Provider/application token used for authenticated REST calls.\n private authToken: string | null = null;\n // Room/SFU token returned by /token and used for the WebSocket.\n private token: string | null = null;\n private room: string | null = null;\n private resumeToken: string | null = null;\n private pendingJoinRequestId: string | null = null;\n private joinOptions: {\n displayName?: string;\n avatarUrl?: string;\n } = {};\n\n private state: SFUConnectionState = \"idle\";\n private intentionalClose = false;\n private leaveAcknowledged = false;\n private joiningWithResume = false;\n private desiredAudioMuted = false;\n private desiredVideoMuted = false;\n private reconnectTimer: ReturnType<typeof setTimeout> | null = null;\n private reconnectAttempt = 0;\n private maxReconnectAttempts = 8;\n private reconnectBaseMs = 750;\n private joinWaiter: JoinWaiter | null = null;\n\n private transportRecoveryInProgress = false;\n private transportRecoveryTimer: ReturnType<typeof setTimeout> | null = null;\n\n private pendingIce: Record<PeerName, RTCIceCandidateInit[]> = {\n publisher: [],\n subscriber: [],\n };\n\n private subscriberNegotiating = false;\n private offerQueue: any[] = [];\n private subscriptionQueue: string[] = [];\n private subscriptionRunning = false;\n private subscriptionWaiters: Array<{\n trackIds: string[];\n resolve: () => void;\n reject: (error: any) => void;\n }> = [];\n\n private subscribedTracks = new Set<string>();\n private trackMetadata = new Map<string, TrackInfo>();\n private participants = new Map<string, ParticipantInfo>();\n private remoteStreams = new Map<string, MediaStream>();\n private remoteScreenStreams = new Map<string, MediaStream>();\n private trackToParticipant = new Map<string, string>();\n private trackToSource = new Map<string, string>();\n private localTrackIds = new Map<\"audio\" | \"camera\" | \"screen\", string>();\n\n private subscriberStatsTimer: ReturnType<typeof setInterval> | null = null;\n private liveTranscriptionActive = false;\n private liveTranscriptionSequence = 0;\n private liveTranscriptionStartedAt = 0;\n private liveTranscriptionRecorder: MediaRecorder | null = null;\n private liveTranscriptionLoopPromise: Promise<void> | null = null;\n private networkProfile: string | null = null;\n\n private onStateChange: (state: SFUConnectionState) => void;\n private onParticipantJoined: (p: ParticipantInfo) => void;\n private onParticipantLeft: (p: string | ParticipantInfo) => void;\n private onParticipantPresence: (id: string, presence: string) => void;\n private onTrackPublished: (t: TrackInfo) => void;\n private onTrackUnpublished: (t: TrackInfo) => void;\n private onRemoteTrack: (\n t: MediaStreamTrack,\n s: MediaStream,\n m: TrackInfo,\n ) => void;\n private onConnected: (p: any, resumed: boolean) => void;\n private onDisconnected: () => void;\n private onReconnecting: (attempt: number) => void;\n private onJoinPending: (info: JoinPendingInfo) => void;\n private onJoinApproved: (requestId: string) => void;\n private onJoinRejected: (requestId: string, reason?: string) => void;\n private onJoinRequested: (request: any) => void;\n private onJoinRequestCanceled: (requestId: string) => void;\n private onParticipantRemoved: (\n participantId: string,\n removedBy: string,\n ) => void;\n private onParticipantPermissionsChanged: (\n participantId: string,\n permissions: any,\n ) => void;\n private onScreenShareStarted: (\n participantId: string,\n track?: TrackInfo,\n ) => void;\n private onScreenShareStopped: (\n participantId: string,\n trackId?: string,\n ) => void;\n private onTrackStateChanged: (track: TrackInfo) => void;\n private onRecordingStarted: (recording: {\n recording_id: string;\n started_at: string;\n }) => void;\n private onRecordingStopped: (recording: {\n recording_id: string;\n stopped_at: string;\n }) => void;\n private onError: (e: any) => void;\n private onChatMessage: (message: any) => void;\n private onReaction: (reaction: any) => void;\n private onRoomUpdate: (data: any) => void;\n private onLiveTranscript: (transcript: LiveTranscript) => void;\n private onNetworkQuality: (quality: NetworkQuality) => void;\n private onParticipantMediaState: (\n participantId: string,\n audioMuted: boolean,\n videoMuted: boolean,\n ) => void;\n private autoSubscribe: boolean;\n\n constructor(options: SFUClientOptions = {}) {\n this.apiBase = options.apiBase || \"https://api.example.com/api\";\n this.wsBase = options.wsBase || \"wss://api.example.com/ws\";\n this.participantId = options.participantId || this.createId();\n this.authToken = options.token ?? null;\n\n this.onStateChange = options.onStateChange || (() => {});\n this.onParticipantJoined = options.onParticipantJoined || (() => {});\n this.onParticipantLeft = options.onParticipantLeft || (() => {});\n this.onParticipantPresence = options.onParticipantPresence || (() => {});\n this.onTrackPublished = options.onTrackPublished || (() => {});\n this.onTrackUnpublished = options.onTrackUnpublished || (() => {});\n this.onRemoteTrack = options.onRemoteTrack || (() => {});\n this.onConnected = options.onConnected || (() => {});\n this.onDisconnected = options.onDisconnected || (() => {});\n this.onReconnecting = options.onReconnecting || (() => {});\n this.onJoinPending = options.onJoinPending || (() => {});\n this.onJoinApproved = options.onJoinApproved || (() => {});\n this.onJoinRejected = options.onJoinRejected || (() => {});\n this.onJoinRequested = options.onJoinRequested || (() => {});\n this.onJoinRequestCanceled = options.onJoinRequestCanceled || (() => {});\n this.onParticipantRemoved = options.onParticipantRemoved || (() => {});\n this.onParticipantPermissionsChanged =\n options.onParticipantPermissionsChanged || (() => {});\n this.onScreenShareStarted = options.onScreenShareStarted || (() => {});\n this.onScreenShareStopped = options.onScreenShareStopped || (() => {});\n this.onTrackStateChanged = options.onTrackStateChanged || (() => {});\n this.onRecordingStarted = options.onRecordingStarted || (() => {});\n this.onRecordingStopped = options.onRecordingStopped || (() => {});\n this.onError = options.onError || console.error;\n this.onChatMessage = options.onChatMessage || (() => {});\n this.onReaction = options.onReaction || (() => {});\n this.onRoomUpdate = options.onRoomUpdate || (() => {});\n this.onLiveTranscript = options.onLiveTranscript || (() => {});\n this.onNetworkQuality = options.onNetworkQuality || (() => {});\n this.onParticipantMediaState =\n options.onParticipantMediaState || (() => {});\n this.autoSubscribe = options.autoSubscribe !== false;\n }\n\n private heartbeatTimer: ReturnType<typeof setInterval> | null = null;\n\n private startHeartbeat() {\n this.stopHeartbeat();\n\n this.heartbeatTimer = setInterval(() => {\n if (this.ws?.readyState !== WebSocket.OPEN) return;\n\n this.send({\n type: \"ping\",\n payload: {\n nonce: crypto.randomUUID(),\n },\n });\n }, 10_000);\n }\n\n private stopHeartbeat() {\n if (this.heartbeatTimer) {\n clearInterval(this.heartbeatTimer);\n this.heartbeatTimer = null;\n }\n }\n\n private createId(): string {\n return typeof crypto !== \"undefined\" && crypto.randomUUID\n ? crypto.randomUUID()\n : `id_${Math.random().toString(36).slice(2)}_${Date.now()}`;\n }\n\n private resumeStorageKey(roomCode: string) {\n return `defcomm:sfu:resume:${roomCode}`;\n }\n\n private loadResumeToken(roomCode: string): string | null {\n try {\n return localStorage.getItem(this.resumeStorageKey(roomCode));\n } catch {\n return null;\n }\n }\n\n private saveResumeToken(roomCode: string, token: string) {\n try {\n localStorage.setItem(this.resumeStorageKey(roomCode), token);\n } catch {\n // Storage can be unavailable in private/SSR environments.\n }\n }\n\n private clearResumeToken(roomCode: string | null) {\n if (!roomCode) return;\n try {\n localStorage.removeItem(this.resumeStorageKey(roomCode));\n } catch {\n // ignore\n }\n }\n\n private setState(next: SFUConnectionState) {\n if (this.state === next) return;\n this.state = next;\n this.onStateChange(next);\n }\n\n getConnectionState(): SFUConnectionState {\n return this.state;\n }\n\n getParticipantId(): string | null {\n return this.currentParticipantId;\n }\n\n getResumeToken(): string | null {\n return this.resumeToken;\n }\n\n getLocalStream(): MediaStream | null {\n return this.localStream;\n }\n\n getScreenStream(): MediaStream | null {\n return this.screenStream;\n }\n\n getRemoteScreenStream(participantId: string): MediaStream | null {\n return this.remoteScreenStreams.get(participantId) || null;\n }\n\n setLocalStream(stream: MediaStream | null) {\n this.localStream = stream;\n }\n\n private nextRequestId(): string {\n return (++this.requestId).toString();\n }\n\n private async request(url: string, options: RequestInit = {}) {\n const headers = new Headers(options.headers);\n\n headers.set(\"Content-Type\", \"application/json\");\n\n // The token supplied through MeetingProvider is available before join\n // and authenticates REST requests such as join-state and /token.\n if (this.authToken) {\n headers.set(\"Authorization\", `Bearer ${this.authToken}`);\n }\n\n const res = await fetch(url, {\n ...options,\n headers,\n });\n\n if (!res.ok) {\n let body: any = {};\n try {\n body = await res.json();\n } catch {\n // ignore non-json error bodies\n }\n\n throw new Error(\n body.message || `Request failed: ${res.status} ${res.statusText}`,\n );\n }\n\n return res.json();\n }\n\n async createRoom(input: {\n name: string;\n description?: string;\n capacity?: number;\n is_private?: boolean;\n }) {\n return this.request(`${this.apiBase}/rooms`, {\n method: \"POST\",\n body: JSON.stringify({\n name: input.name,\n description: input.description ?? \"\",\n capacity: input.capacity ?? 20,\n is_private: input.is_private ?? false,\n }),\n });\n }\n\n async getRoom(roomCode: string) {\n return this.request(\n `${this.apiBase}/rooms/${encodeURIComponent(roomCode)}`,\n );\n }\n\n async getJoinState(roomCode: string): Promise<JoinState> {\n return this.request(\n `${this.apiBase}/rooms/${encodeURIComponent(roomCode)}/join-state`,\n );\n }\n\n async deleteRoom(roomCode: string) {\n return this.request(\n `${this.apiBase}/rooms/${encodeURIComponent(roomCode)}`,\n {\n method: \"DELETE\",\n },\n );\n }\n\n async getToken(\n roomCode: string,\n options: {\n displayName?: string;\n avatarUrl?: string;\n participantId?: string;\n audioMuted?: boolean;\n videoMuted?: boolean;\n } = {},\n ) {\n const nextRoom = roomCode.trim();\n if (this.room && this.room !== nextRoom) {\n this.resumeToken = null;\n }\n\n this.room = nextRoom;\n this.joinOptions = {\n displayName: options.displayName,\n avatarUrl: options.avatarUrl,\n };\n if (options.participantId) this.participantId = options.participantId;\n if (typeof options.audioMuted === \"boolean\")\n this.desiredAudioMuted = options.audioMuted;\n if (typeof options.videoMuted === \"boolean\")\n this.desiredVideoMuted = options.videoMuted;\n if (!this.resumeToken) {\n this.resumeToken = this.loadResumeToken(this.room);\n }\n\n const data = await this.request(`${this.apiBase}/token`, {\n method: \"POST\",\n body: JSON.stringify({\n room_code: this.room,\n user_id: this.participantId,\n display_name: options.displayName,\n avatar_url: options.avatarUrl,\n }),\n });\n\n this.token = data?.token;\n if (!this.token) throw new Error(\"Token endpoint returned no token\");\n\n return this.connect(this.token, this.joinOptions);\n }\n\n private async refreshAccessToken() {\n if (!this.room) throw new Error(\"Cannot refresh token without a room\");\n\n const data = await this.request(`${this.apiBase}/token`, {\n method: \"POST\",\n body: JSON.stringify({\n room_code: this.room,\n user_id: this.participantId,\n display_name: this.joinOptions.displayName,\n avatar_url: this.joinOptions.avatarUrl,\n }),\n });\n\n if (!data?.token) throw new Error(\"Token refresh returned no token\");\n this.token = data.token;\n return this.token;\n }\n\n private connect(token: string, options: any = {}) {\n this.token = token;\n this.intentionalClose = false;\n this.setState(this.reconnectAttempt > 0 ? \"reconnecting\" : \"connecting\");\n\n return new Promise<void>((resolve, reject) => {\n this.joinWaiter = { resolve, reject };\n this.openWebSocket(options);\n });\n }\n\n private openWebSocket(options: any = {}) {\n if (!this.token || !this.room) {\n const error = new Error(\"Cannot connect without token and room\");\n this.failJoin(error);\n return;\n }\n\n if (this.ws) {\n try {\n this.ws.onclose = null;\n this.ws.close();\n } catch {\n // ignore\n }\n }\n\n const ws = new WebSocket(\n `${this.wsBase}?access_token=${encodeURIComponent(this.token)}`,\n );\n this.ws = ws;\n\n ws.onopen = () => {\n this.startHeartbeat();\n this.setState(\"joining\");\n this.joiningWithResume = Boolean(this.resumeToken);\n\n const joinPayload: any = {\n token: this.token,\n room_code: this.room,\n resume_token: this.resumeToken,\n display_name: options.displayName,\n avatar_url: options.avatarUrl,\n audio_muted: this.desiredAudioMuted,\n video_muted: this.desiredVideoMuted,\n };\n\n // After approval the Rust server requires the original pending request id.\n if (this.pendingJoinRequestId) {\n this.send({\n type: \"join\",\n request_id: this.pendingJoinRequestId,\n payload: joinPayload,\n });\n } else {\n this.send({ type: \"join\", payload: joinPayload });\n }\n };\n\n ws.onerror = (event) => {\n this.onError(event);\n };\n\n ws.onclose = () => {\n this.stopHeartbeat();\n if (this.ws !== ws) return;\n this.ws = null;\n\n if (this.intentionalClose || this.state === \"leaving\") {\n this.setState(\"disconnected\");\n this.onDisconnected();\n return;\n }\n\n // Keep MediaStreams and logical participant state alive.\n this.setState(\"reconnecting\");\n this.onDisconnected();\n this.scheduleReconnect();\n };\n\n ws.onmessage = async (event) => {\n if (this.ws !== ws) return;\n try {\n const message = JSON.parse(event.data);\n await this.handleServerMessage(message);\n } catch (error) {\n this.onError(error);\n }\n };\n }\n\n private scheduleReconnect() {\n if (this.reconnectTimer || this.intentionalClose) return;\n if (this.reconnectAttempt >= this.maxReconnectAttempts) {\n this.setState(\"disconnected\");\n this.failJoin(new Error(\"SFU reconnect attempts exhausted\"));\n return;\n }\n\n this.reconnectAttempt += 1;\n const delay = Math.min(\n 15000,\n this.reconnectBaseMs * Math.pow(2, this.reconnectAttempt - 1),\n );\n\n this.onReconnecting(this.reconnectAttempt);\n\n this.reconnectTimer = setTimeout(async () => {\n this.reconnectTimer = null;\n try {\n await this.refreshAccessToken();\n this.openWebSocket(this.joinOptions);\n } catch (error) {\n this.onError(error);\n this.scheduleReconnect();\n }\n }, delay);\n }\n\n private failJoin(error: any) {\n if (this.joinWaiter) {\n const waiter = this.joinWaiter;\n this.joinWaiter = null;\n waiter.reject(error);\n }\n }\n\n private resolveJoin(value: any) {\n if (!this.joinWaiter) return;\n const waiter = this.joinWaiter;\n this.joinWaiter = null;\n waiter.resolve(value);\n }\n\n private async handleServerMessage(message: any) {\n const type = message?.type;\n const payload = message?.payload || {};\n\n switch (type) {\n case \"joined\": {\n await this.handleJoined(payload);\n break;\n }\n\n case \"left\": {\n this.leaveAcknowledged = true;\n break;\n }\n\n case \"join_pending\": {\n const requestId = payload.request_id || message.request_id;\n if (!requestId) throw new Error(\"join_pending has no request_id\");\n\n this.pendingJoinRequestId = requestId;\n this.setState(\"waiting_approval\");\n this.onJoinPending({\n request_id: requestId,\n room_code: payload.room_code || this.room || undefined,\n message: payload.message,\n });\n break;\n }\n\n case \"join_approved\": {\n const requestId = payload.request_id || message.request_id;\n if (!requestId) break;\n this.pendingJoinRequestId = requestId;\n this.onJoinApproved(requestId);\n\n // Approval is a direct signal to the waiting session. Continue the join\n // with the same request id; the Rust Room layer performs the admission.\n if (this.ws?.readyState === WebSocket.OPEN) {\n this.setState(\"joining\");\n this.send({\n type: \"join\",\n request_id: requestId,\n payload: {\n token: this.token,\n room_code: this.room,\n resume_token: this.resumeToken,\n display_name: this.joinOptions.displayName,\n avatar_url: this.joinOptions.avatarUrl,\n // Preserve the media state requested before host approval.\n // The approval continuation is a second JOIN, so these values\n // must be sent again instead of falling back to the SFU defaults.\n audio_muted: this.desiredAudioMuted,\n video_muted: this.desiredVideoMuted,\n },\n });\n }\n break;\n }\n\n case \"join_rejected\": {\n const requestId = payload.request_id || message.request_id;\n const reason = payload.reason;\n this.onJoinRejected(requestId, reason);\n this.pendingJoinRequestId = null;\n this.intentionalClose = true;\n this.failJoin(new Error(reason || \"Join request rejected\"));\n break;\n }\n\n case \"join_requested\":\n case \"join_request\": {\n this.onJoinRequested(payload.request || payload);\n break;\n }\n\n case \"join_request_canceled\": {\n this.onJoinRequestCanceled(payload.request_id || message.request_id);\n break;\n }\n\n case \"participant_removed\": {\n const participantId = payload.participant_id;\n if (!participantId) break;\n const removedBy = payload.removed_by || \"\";\n this.participants.delete(participantId);\n this.removeRemoteParticipant(participantId);\n if (participantId === this.currentParticipantId) {\n this.intentionalClose = true;\n this.pendingJoinRequestId = null;\n this.setState(\"disconnected\");\n try {\n this.ws?.close();\n } catch {}\n }\n this.onParticipantRemoved(participantId, removedBy);\n break;\n }\n\n case \"participant_permissions_changed\": {\n const participantId = payload.participant_id;\n if (!participantId) break;\n const participant = this.participants.get(participantId);\n if (participant) {\n this.participants.set(participantId, {\n ...participant,\n permissions: payload.permissions,\n });\n }\n this.onParticipantPermissionsChanged(\n participantId,\n payload.permissions,\n );\n break;\n }\n\n case \"publish_answer\": {\n if (!this.publisher) break;\n await this.publisher.setRemoteDescription({\n type: \"answer\",\n sdp: payload.sdp,\n });\n await this.flushPendingIce(\"publisher\");\n break;\n }\n\n case \"subscribe_offer\": {\n this.offerQueue.push(payload);\n if (!this.subscriberNegotiating) await this.processOfferQueue();\n break;\n }\n\n case \"ice_candidate\":\n case \"publisher_ice_candidate\":\n case \"subscriber_ice_candidate\": {\n const candidatePayload = {\n ...payload,\n peer:\n payload.peer ||\n (type === \"publisher_ice_candidate\" ? \"publisher\" : \"subscriber\"),\n };\n await this.handleIce(candidatePayload);\n break;\n }\n\n case \"participant_joined\": {\n const participant = payload.participant || payload;\n const participantId =\n participant?.participant_id || payload.participant_id;\n if (!participantId || participantId === this.currentParticipantId)\n break;\n\n if (participant) this.participants.set(participantId, participant);\n this.onParticipantJoined(participant);\n break;\n }\n\n case \"participant_left\": {\n const participantId = payload.participant_id;\n if (!participantId) break;\n this.participants.delete(participantId);\n this.removeRemoteParticipant(participantId);\n this.onParticipantLeft(participantId);\n break;\n }\n\n case \"participant_media_state\": {\n const participantId = payload.participant_id;\n if (!participantId) break;\n this.onParticipantMediaState(\n participantId,\n Boolean(payload.audio_muted),\n Boolean(payload.video_muted),\n );\n break;\n }\n\n case \"participant_presence\":\n case \"participant_presence_changed\": {\n const participantId = payload.participant_id;\n const presence = payload.presence;\n if (participantId && presence) {\n this.onParticipantPresence(participantId, String(presence));\n }\n break;\n }\n\n case \"track_published\": {\n const track: TrackInfo = payload.track || payload;\n if (!track?.track_id) break;\n this.rememberTrack(track);\n\n if (track.participant_id === this.currentParticipantId) {\n if (track.source === \"audio\") {\n this.localTrackIds.set(\"audio\", track.track_id);\n const muted = !(\n this.localStream?.getAudioTracks()[0]?.enabled ?? true\n );\n this.send({\n type: \"track_state\",\n payload: { track_id: track.track_id, muted },\n });\n }\n if (track.source === \"camera\") {\n this.localTrackIds.set(\"camera\", track.track_id);\n const muted = !(\n this.localStream?.getVideoTracks()[0]?.enabled ?? true\n );\n this.send({\n type: \"track_state\",\n payload: { track_id: track.track_id, muted },\n });\n }\n if (track.source === \"screen\")\n this.localTrackIds.set(\"screen\", track.track_id);\n break;\n }\n\n this.onTrackPublished(track);\n if (this.autoSubscribe) await this.subscribe(track.track_id);\n break;\n }\n\n case \"track_unpublished\": {\n const trackId = payload.track_id || payload.track?.track_id;\n if (!trackId) break;\n const track =\n this.trackMetadata.get(trackId) ||\n ({\n track_id: trackId,\n participant_id: this.trackToParticipant.get(trackId) || \"\",\n source: this.trackToSource.get(trackId),\n kind: \"video\",\n } as TrackInfo);\n\n this.trackMetadata.delete(trackId);\n this.subscribedTracks.delete(trackId);\n this.trackToParticipant.delete(trackId);\n this.trackToSource.delete(trackId);\n\n for (const [source, localId] of this.localTrackIds) {\n if (localId === trackId) this.localTrackIds.delete(source);\n }\n\n if (track.participant_id === this.currentParticipantId) break;\n this.onTrackUnpublished(track);\n break;\n }\n\n case \"track_state_changed\": {\n const trackId = payload.track_id || payload.track?.track_id;\n if (!trackId) break;\n\n const existing = this.trackMetadata.get(trackId);\n const track: TrackInfo = {\n ...(existing || {}),\n ...(payload.track || {}),\n track_id: trackId,\n participant_id:\n payload.participant_id ||\n existing?.participant_id ||\n payload.track?.participant_id,\n kind:\n payload.kind || payload.track?.kind || existing?.kind || \"video\",\n source: payload.source || payload.track?.source || existing?.source,\n muted: Boolean(payload.muted),\n };\n\n if (!track.participant_id) break;\n this.rememberTrack(track);\n this.onTrackStateChanged(track);\n break;\n }\n\n case \"subscription_updated\": {\n // Authoritative acknowledgement of the current subscriber set.\n break;\n }\n\n case \"recording_started\": {\n this.onRecordingStarted({\n recording_id: payload.recording_id,\n started_at: payload.started_at,\n });\n break;\n }\n\n case \"recording_stopped\": {\n this.onRecordingStopped({\n recording_id: payload.recording_id,\n stopped_at: payload.stopped_at,\n });\n break;\n }\n\n case \"reconnecting\": {\n this.setState(\"reconnecting\");\n break;\n }\n\n case \"screen_share_started\": {\n const participantId = payload.participant_id;\n const track = payload.track as TrackInfo | undefined;\n if (track) this.rememberTrack(track);\n if (participantId) this.onScreenShareStarted(participantId, track);\n break;\n }\n\n case \"screen_share_stopped\": {\n const participantId = payload.participant_id;\n const trackId = payload.track_id;\n\n // Keep the underlying remote screen track alive across a logical\n // stop/start. The SFU and publisher reuse the same RTP track.\n this.onScreenShareStopped(participantId, trackId);\n break;\n }\n\n case \"room_state\": {\n const participants = payload.participants || [];\n this.onRoomStateReconciled(payload);\n this.onRoomUpdate(payload);\n for (const participant of participants) {\n const pid = participant?.participant_id;\n if (!pid) continue;\n if (pid !== this.currentParticipantId) {\n this.participants.set(pid, participant);\n this.onParticipantPresence(\n pid,\n String(participant.presence || \"connected\"),\n );\n this.onParticipantMediaState(\n pid,\n Boolean(participant.audio_muted),\n Boolean(participant.video_muted),\n );\n }\n }\n for (const [pid] of this.participants) {\n if (!participants.some((p: any) => p?.participant_id === pid)) {\n this.participants.delete(pid);\n this.removeRemoteParticipant(pid);\n this.onParticipantLeft(pid);\n }\n }\n for (const track of payload.tracks || []) this.rememberTrack(track);\n if (Array.isArray(payload.chat_history)) {\n for (const message of payload.chat_history)\n this.onChatMessage(message);\n }\n break;\n }\n\n case \"chat_message\": {\n const msg = payload.message || payload;\n if (msg?.id) this.onChatMessage(msg);\n break;\n }\n\n case \"reaction\": {\n const reaction = payload.reaction || payload;\n console.log(\"[SFUClient] RECEIVED REACTION\", reaction);\n if (reaction?.id && reaction?.emoji) this.onReaction(reaction);\n break;\n }\n\n case \"live_transcript\": {\n const transcript: LiveTranscript = {\n transcript_id: String(payload.transcript_id),\n participant_id: String(payload.participant_id),\n speaker_name: payload.speaker_name ?? null,\n sequence: Number(payload.sequence ?? 0),\n text: String(payload.text ?? \"\"),\n offset_ms: payload.offset_ms == null ? null : Number(payload.offset_ms),\n start_ms: payload.start_ms == null ? null : Number(payload.start_ms),\n end_ms: payload.end_ms == null ? null : Number(payload.end_ms),\n timestamp: String(payload.timestamp ?? new Date().toISOString()),\n };\n if (transcript.text.trim()) this.onLiveTranscript(transcript);\n break;\n }\n\n case \"network_quality\": {\n const raw = payload.quality || payload;\n const quality: NetworkQuality = {\n participant_id: String(raw.participant_id ?? this.currentParticipantId ?? this.participantId),\n quality: String(raw.quality ?? \"unknown\"),\n score: Number(raw.score ?? 0),\n recommended_action: String(raw.recommended_action ?? \"maintain\"),\n packet_loss_percent: Number(raw.packet_loss_percent ?? 0),\n upload_kbps: Number(raw.upload_kbps ?? 0),\n forwarded_drop_percent: Number(raw.forwarded_drop_percent ?? 0),\n queued_packets: Number(raw.queued_packets ?? 0),\n packets_received: Number(raw.packets_received ?? 0),\n packets_lost: Number(raw.packets_lost ?? 0),\n observed_at: String(raw.observed_at ?? new Date().toISOString()),\n };\n this.onNetworkQuality(quality);\n void this.applyNetworkRecommendation(quality.recommended_action);\n break;\n }\n\n case \"error\": {\n const message = payload.message || \"SFU signaling error\";\n if (\n this.state === \"reconnecting\" &&\n message.includes(\"participant session is stale\")\n ) {\n console.debug(\n \"[SFU] Ignoring stale-session error during recovery\",\n message,\n );\n return;\n }\n const error = new Error(message);\n if (this.state === \"joining\" || this.state === \"waiting_approval\") {\n this.onError(error);\n this.failJoin(error);\n return;\n }\n this.onError(error);\n break;\n }\n\n default:\n console.debug(\"[SFU] Ignoring unknown server message\", message);\n }\n }\n\n private onRoomStateReconciled(payload: any) {\n const participants = payload.participants || [];\n const local = participants.find(\n (p: any) => p?.participant_id === this.currentParticipantId,\n );\n if (local) {\n this.desiredAudioMuted = Boolean(local.audio_muted);\n this.desiredVideoMuted = Boolean(local.video_muted);\n }\n }\n\n private rememberTrack(track: TrackInfo) {\n if (!track?.track_id || !track?.participant_id) return;\n\n const normalizedSource = track.source\n ? String(track.source).trim().toLowerCase()\n : undefined;\n\n const normalized: TrackInfo = {\n ...track,\n source: normalizedSource,\n };\n\n this.trackMetadata.set(normalized.track_id, normalized);\n this.trackToParticipant.set(normalized.track_id, normalized.participant_id);\n\n if (normalizedSource) {\n this.trackToSource.set(normalized.track_id, normalizedSource);\n } else {\n this.trackToSource.delete(normalized.track_id);\n }\n }\n\n private async handleJoined(payload: any) {\n const resumed = this.joiningWithResume;\n this.joiningWithResume = false;\n\n this.iceServers = payload.ice_servers || this.iceServers || [];\n this.currentParticipantId = payload.participant_id;\n this.resumeToken =\n payload.resume_token || payload.resumeToken || this.resumeToken;\n if (this.room && this.resumeToken) {\n this.saveResumeToken(this.room, this.resumeToken);\n }\n this.pendingJoinRequestId = null;\n this.reconnectAttempt = 0;\n\n this.participants.clear();\n this.trackMetadata.clear();\n this.trackToParticipant.clear();\n this.trackToSource.clear();\n this.localTrackIds.clear();\n\n for (const participant of payload.participants || []) {\n if (participant?.participant_id) {\n this.participants.set(participant.participant_id, participant);\n }\n }\n\n for (const track of payload.tracks || []) {\n if (track?.track_id) this.rememberTrack(track);\n }\n\n await this.initializePeerConnections();\n this.setState(\"connected\");\n this.onConnected(payload, resumed);\n if (payload.recording?.status === \"recording\") {\n console.log(\"[SFU] Recording already active when joining\", {\n recording_id: payload.recording.recording_id,\n started_at: payload.recording.started_at,\n status: payload.recording.status,\n });\n\n this.onRecordingStarted({\n recording_id: payload.recording.recording_id,\n started_at: payload.recording.started_at,\n });\n }\n\n for (const participant of this.participants.values()) {\n if (participant.participant_id !== this.currentParticipantId) {\n this.onParticipantJoined(participant);\n this.onParticipantPresence(\n participant.participant_id,\n String(participant.presence || \"connected\"),\n );\n this.onParticipantMediaState(\n participant.participant_id,\n Boolean(participant.audio_muted),\n Boolean(participant.video_muted),\n );\n }\n }\n\n if (Array.isArray(payload.chat_history)) {\n for (const message of payload.chat_history) this.onChatMessage(message);\n }\n this.onRoomUpdate(payload);\n\n if (this.localStream) {\n await this.publishExistingTracks();\n }\n\n if (this.autoSubscribe) {\n const trackIds = [...this.trackMetadata.values()]\n .filter((track) => track.participant_id !== this.currentParticipantId)\n .map((track) => track.track_id);\n if (trackIds.length) await this.subscribeMultiple(trackIds);\n }\n\n this.resolveJoin(payload);\n }\n\n private async initializePeerConnections() {\n this.closePeerConnectionsOnly();\n this.publisherRevision = 0;\n\n const config: RTCConfiguration = { iceServers: this.iceServers };\n this.publisher = new RTCPeerConnection(config);\n this.subscriber = new RTCPeerConnection(config);\n\n // Keep audio, camera, and screen on three permanent publisher m-lines.\n // This mirrors the working client: screen sharing must never reuse the\n // camera sender/transceiver.\n this.audioTransceiver = this.publisher.addTransceiver(\"audio\", {\n direction: \"sendonly\",\n });\n this.cameraTransceiver = this.publisher.addTransceiver(\"video\", {\n direction: \"sendonly\",\n });\n this.screenTransceiver = this.publisher.addTransceiver(\"video\", {\n direction: \"inactive\",\n });\n\n this.audioSender = this.audioTransceiver.sender;\n this.videoSender = this.cameraTransceiver.sender;\n this.screenSender = this.screenTransceiver.sender;\n\n this.publisher.onicecandidate = (event) => {\n if (event.candidate) this.sendCandidate(\"publisher\", event.candidate);\n };\n\n this.subscriber.onicecandidate = (event) => {\n if (event.candidate) this.sendCandidate(\"subscriber\", event.candidate);\n };\n\n this.publisher.onconnectionstatechange = () => {\n const publisher = this.publisher;\n if (!publisher) return;\n\n const state = publisher.connectionState;\n\n console.debug(\"[SFU] Publisher connection state\", {\n connectionState: publisher.connectionState,\n iceConnectionState: publisher.iceConnectionState,\n iceGatheringState: publisher.iceGatheringState,\n signalingState: publisher.signalingState,\n });\n\n if (state === \"failed\") {\n this.recoverWebRTC(\"publisher_failed\");\n }\n };\n\n this.subscriber.onconnectionstatechange = () => {\n const subscriber = this.subscriber;\n if (!subscriber) return;\n\n const state = subscriber.connectionState;\n\n console.debug(\"[SFU] Subscriber connection state\", {\n connectionState: subscriber.connectionState,\n iceConnectionState: subscriber.iceConnectionState,\n iceGatheringState: subscriber.iceGatheringState,\n signalingState: subscriber.signalingState,\n });\n\n if (state === \"failed\") {\n this.recoverWebRTC(\"subscriber_failed\");\n }\n };\n this.publisher.oniceconnectionstatechange = () => {\n const publisher = this.publisher;\n if (!publisher) return;\n\n console.debug(\"[SFU] Publisher ICE state\", {\n iceConnectionState: publisher.iceConnectionState,\n connectionState: publisher.connectionState,\n });\n };\n\n this.subscriber.oniceconnectionstatechange = () => {\n const subscriber = this.subscriber;\n if (!subscriber) return;\n\n console.debug(\"[SFU] Subscriber ICE state\", {\n iceConnectionState: subscriber.iceConnectionState,\n connectionState: subscriber.connectionState,\n });\n };\n\n this.subscriber.ontrack = (event) => {\n void this.handleRemoteTrack(event);\n };\n\n if (!this.subscriberStatsTimer) {\n this.subscriberStatsTimer = setInterval(() => {\n void this.logSubscriberVideoStats();\n }, 3000);\n }\n }\n\n private async handleRemoteTrack(event: RTCTrackEvent) {\n const stream = event.streams?.[0] || null;\n const metadata = this.resolveRemoteTrackMetadata(event.track, stream);\n\n if (!metadata?.participant_id) {\n this.onError(\n new Error(\n `Remote ${event.track.kind} track ${event.track.id} has no SFU participant mapping`,\n ),\n );\n return;\n }\n\n const participantId = metadata.participant_id;\n const source = String(\n metadata.source || this.trackToSource.get(metadata.track_id) || \"\",\n )\n .trim()\n .toLowerCase();\n\n console.debug(\"[SFU] Remote track source resolved\", {\n participantId,\n browserTrackId: event.track.id,\n serverTrackId: metadata.track_id,\n kind: event.track.kind,\n source,\n });\n\n // Screen is a completely separate media path. Never put it in the\n // participant's normal camera/audio MediaStream.\n if (source === \"screen\" || source === \"screen_share\") {\n let screenStream = this.remoteScreenStreams.get(participantId);\n\n if (!screenStream) {\n screenStream = new MediaStream();\n this.remoteScreenStreams.set(participantId, screenStream);\n }\n\n for (const existing of screenStream.getVideoTracks()) {\n if (existing.id !== event.track.id) {\n screenStream.removeTrack(existing);\n existing.stop();\n }\n }\n\n if (\n !screenStream.getTracks().some((track) => track.id === event.track.id)\n ) {\n screenStream.addTrack(event.track);\n }\n\n event.track.onended = () => {\n try {\n screenStream?.removeTrack(event.track);\n } catch {}\n\n if (screenStream?.getTracks().length === 0) {\n this.remoteScreenStreams.delete(participantId);\n this.onScreenShareStopped(participantId, metadata.track_id);\n }\n };\n\n this.onScreenShareStarted(participantId, metadata);\n this.onRemoteTrack(event.track, screenStream, {\n ...metadata,\n source: \"screen\",\n });\n return;\n }\n\n // Only audio and camera video belong to the normal participant stream.\n if (event.track.kind === \"video\" && source !== \"camera\") {\n this.onError(\n new Error(\n `Refusing to route unknown remote video source to camera: ${metadata.track_id}`,\n ),\n );\n return;\n }\n\n let remoteStream = this.remoteStreams.get(participantId);\n if (!remoteStream) {\n remoteStream = new MediaStream();\n this.remoteStreams.set(participantId, remoteStream);\n }\n\n for (const existing of remoteStream.getTracks()) {\n if (\n existing.kind === event.track.kind &&\n existing.id !== event.track.id\n ) {\n remoteStream.removeTrack(existing);\n existing.stop();\n }\n }\n\n if (\n !remoteStream.getTracks().some((track) => track.id === event.track.id)\n ) {\n remoteStream.addTrack(event.track);\n }\n\n event.track.onended = () => {\n try {\n remoteStream?.removeTrack(event.track);\n } catch {}\n };\n\n this.onRemoteTrack(event.track, remoteStream, {\n ...metadata,\n source: event.track.kind === \"audio\" ? \"audio\" : \"camera\",\n });\n }\n\n private normalizeRemoteTrackId(browserTrackId: string): string {\n return browserTrackId?.startsWith(\"track-\")\n ? browserTrackId.slice(\"track-\".length)\n : browserTrackId;\n }\n\n private resolveRemoteTrackMetadata(\n track: MediaStreamTrack,\n stream: MediaStream | null,\n ): TrackInfo | null {\n const candidates = [\n this.normalizeRemoteTrackId(track.id),\n track.id,\n stream?.id ? this.normalizeRemoteTrackId(stream.id) : null,\n stream?.id || null,\n ].filter(Boolean) as string[];\n\n for (const id of candidates) {\n const metadata = this.trackMetadata.get(id);\n if (metadata) return metadata;\n }\n\n // Never guess by participant + kind. A participant can publish camera\n // and screen simultaneously; guessing is exactly how a screen track can\n // end up in the camera tile.\n return null;\n }\n\n private sendCandidate(peer: PeerName, candidate: RTCIceCandidate) {\n this.send({\n type: \"ice_candidate\",\n payload: {\n peer,\n candidate: candidate.candidate,\n sdp_mid: candidate.sdpMid,\n sdp_mline_index: candidate.sdpMLineIndex,\n username_fragment: candidate.usernameFragment,\n },\n });\n }\n\n private async handleIce(payload: any) {\n const peer: PeerName =\n payload.peer === \"publisher\" ? \"publisher\" : \"subscriber\";\n const pc = peer === \"publisher\" ? this.publisher : this.subscriber;\n\n const candidate: RTCIceCandidateInit = {\n candidate: payload.candidate,\n sdpMid: payload.sdp_mid ?? payload.sdpMid ?? null,\n sdpMLineIndex: payload.sdp_mline_index ?? payload.sdpMLineIndex ?? null,\n usernameFragment:\n payload.username_fragment ?? payload.usernameFragment ?? null,\n };\n\n if (!pc || !pc.remoteDescription) {\n this.pendingIce[peer].push(candidate);\n return;\n }\n\n try {\n await pc.addIceCandidate(candidate);\n } catch (error) {\n this.onError(\n new Error(`Failed to add ${peer} ICE candidate: ${String(error)}`),\n );\n }\n }\n\n private async flushPendingIce(peer: PeerName) {\n const pc = peer === \"publisher\" ? this.publisher : this.subscriber;\n if (!pc || !pc.remoteDescription) return;\n\n const queue = this.pendingIce[peer];\n while (queue.length) {\n const candidate = queue.shift()!;\n try {\n await pc.addIceCandidate(candidate);\n } catch (error) {\n this.onError(\n new Error(\n `Failed to add queued ${peer} ICE candidate: ${String(error)}`,\n ),\n );\n }\n }\n }\n\n private async processOfferQueue() {\n if (!this.subscriber) return;\n\n while (this.offerQueue.length) {\n if (this.subscriberNegotiating) return;\n this.subscriberNegotiating = true;\n const offer = this.offerQueue.shift();\n\n try {\n await this.subscriber.setRemoteDescription({\n type: \"offer\",\n sdp: offer.sdp,\n });\n await this.flushPendingIce(\"subscriber\");\n\n const answer = await this.subscriber.createAnswer();\n await this.subscriber.setLocalDescription(answer);\n\n this.send({\n type: \"subscribe_answer\",\n payload: {\n revision: offer.revision,\n sdp: answer.sdp,\n },\n });\n\n // One subscribe request produces one subscriber offer. Resolve only\n // the waiter belonging to this offer; resolving the entire queue can\n // make later subscribe calls look complete before they were negotiated.\n const waiter = this.subscriptionWaiters.shift();\n waiter?.resolve();\n } catch (error) {\n const waiter = this.subscriptionWaiters.shift();\n if (waiter) {\n waiter.trackIds.forEach((id) => this.subscribedTracks.delete(id));\n waiter.reject(error);\n }\n this.onError(\n new Error(`Failed to process subscriber offer: ${String(error)}`),\n );\n } finally {\n this.subscriberNegotiating = false;\n }\n }\n }\n\n private async subscribe(trackId: string) {\n if (!trackId || this.subscribedTracks.has(trackId)) return;\n this.subscribedTracks.add(trackId);\n this.subscriptionQueue.push(trackId);\n if (!this.subscriptionRunning) await this.processSubscriptionQueue();\n }\n\n private async subscribeMultiple(trackIds: string[]) {\n const uniqueIds = [...new Set(trackIds.filter(Boolean))].filter(\n (id) => !this.subscribedTracks.has(id),\n );\n if (!uniqueIds.length || !this.isSocketOpen()) return;\n\n uniqueIds.forEach((id) => this.subscribedTracks.add(id));\n return new Promise<void>((resolve, reject) => {\n const sent = this.send({\n type: \"subscribe\",\n payload: { track_ids: uniqueIds },\n });\n\n if (!sent) {\n uniqueIds.forEach((id) => this.subscribedTracks.delete(id));\n reject(new Error(\"Signaling socket is not open\"));\n return;\n }\n\n this.subscriptionWaiters.push({\n trackIds: uniqueIds,\n resolve,\n reject,\n });\n });\n }\n\n private async processSubscriptionQueue() {\n this.subscriptionRunning = true;\n try {\n while (this.subscriptionQueue.length) {\n const trackId = this.subscriptionQueue.shift()!;\n if (!this.isSocketOpen()) {\n this.subscribedTracks.delete(trackId);\n continue;\n }\n\n await new Promise<void>((resolve, reject) => {\n const sent = this.send({\n type: \"subscribe\",\n payload: { track_ids: [trackId] },\n });\n\n if (!sent) {\n this.subscribedTracks.delete(trackId);\n reject(new Error(\"Signaling socket is not open\"));\n return;\n }\n\n this.subscriptionWaiters.push({\n trackIds: [trackId],\n resolve,\n reject,\n });\n });\n }\n } finally {\n this.subscriptionRunning = false;\n }\n }\n\n async publish({ audio = true, video = true } = {}) {\n if (!this.publisher)\n throw new Error(\"Publisher PeerConnection is not initialized\");\n\n if (!this.localStream) {\n this.localStream = await navigator.mediaDevices.getUserMedia({\n audio,\n video,\n });\n }\n\n await this.publishExistingTracks(audio, video);\n return this.localStream;\n }\n\n private async publishExistingTracks(audio = true, video = true) {\n if (!this.publisher || !this.localStream) return;\n\n if (\n !this.audioTransceiver ||\n !this.cameraTransceiver ||\n !this.screenTransceiver\n ) {\n throw new Error(\"Publisher transceivers are not initialized\");\n }\n\n const audioTrack = this.localStream\n .getAudioTracks()\n .find((track) => track.readyState === \"live\");\n const cameraTrack = this.localStream\n .getVideoTracks()\n .find((track) => track.readyState === \"live\");\n const screenTrack = this.screenStream\n ?.getVideoTracks()\n .find((track) => track.readyState === \"live\");\n\n await this.audioSender?.replaceTrack(\n audio && audioTrack ? audioTrack : null,\n );\n this.audioTransceiver.direction =\n audio && audioTrack ? \"sendonly\" : \"inactive\";\n\n await this.videoSender?.replaceTrack(\n video && cameraTrack ? cameraTrack : null,\n );\n this.cameraTransceiver.direction =\n video && cameraTrack ? \"sendonly\" : \"inactive\";\n\n await this.screenSender?.replaceTrack(screenTrack || null);\n this.screenTransceiver.direction = screenTrack ? \"sendonly\" : \"inactive\";\n\n if (!audioTrack && !cameraTrack && !screenTrack) return;\n\n const offer = await this.publisher.createOffer();\n await this.publisher.setLocalDescription(offer);\n\n this.send({\n type: \"publish_offer\",\n payload: {\n revision: ++this.publisherRevision,\n sdp: offer.sdp,\n },\n });\n\n if (screenTrack) {\n this.send({ type: \"start_screen_share\" });\n }\n }\n\n async shareScreen() {\n if (!this.publisher) {\n throw new Error(\"Publisher PeerConnection is not initialized\");\n }\n\n if (!this.screenTransceiver || !this.screenSender) {\n throw new Error(\"Screen transceiver is not initialized\");\n }\n\n const existing = this.screenStream;\n const existingTrack = this.screenSender.track;\n\n // Already sharing.\n if (existing || (existingTrack && existingTrack.readyState === \"live\")) {\n return existing;\n }\n\n try {\n await this.screenSender.replaceTrack(null);\n } catch {}\n\n this.screenTransceiver.direction = \"inactive\";\n\n const screenStream = await navigator.mediaDevices.getDisplayMedia({\n video: true,\n audio: false,\n });\n\n const screenTrack = screenStream.getVideoTracks()[0];\n\n if (!screenTrack) {\n screenStream.getTracks().forEach((track) => track.stop());\n throw new Error(\"Screen share returned no video track\");\n }\n\n const generation = ++this.screenShareGeneration;\n\n this.screenStream = screenStream;\n\n try {\n await this.screenSender.replaceTrack(screenTrack);\n\n this.screenTransceiver.direction = \"sendonly\";\n\n this.send({\n type: \"start_screen_share\",\n });\n\n const offer = await this.publisher.createOffer();\n\n await this.publisher.setLocalDescription(offer);\n\n const localDescription = this.publisher.localDescription;\n\n if (!localDescription?.sdp) {\n throw new Error(\"Publisher did not produce a valid screen-share SDP\");\n }\n\n this.send({\n type: \"publish_offer\",\n payload: {\n revision: ++this.publisherRevision,\n sdp: localDescription.sdp,\n },\n });\n\n screenTrack.onended = () => {\n if (generation !== this.screenShareGeneration) {\n return;\n }\n\n void this.stopScreenShare();\n };\n\n return this.screenStream;\n } catch (error) {\n try {\n await this.screenSender.replaceTrack(null);\n } catch {}\n\n this.screenTransceiver.direction = \"inactive\";\n\n screenTrack.onended = null;\n\n screenStream.getTracks().forEach((track) => {\n try {\n track.stop();\n } catch {}\n });\n\n this.screenStream = null;\n\n try {\n this.send({\n type: \"stop_screen_share\",\n });\n } catch {}\n\n throw error;\n }\n }\n\n async stopScreenShare() {\n const stream = this.screenStream;\n const senderTrack = this.screenSender?.track || null;\n\n if (!stream && !senderTrack) {\n return;\n }\n\n ++this.screenShareGeneration;\n\n if (senderTrack) {\n senderTrack.onended = null;\n }\n\n try {\n await this.screenSender?.replaceTrack(null);\n } catch (error) {\n this.onError(error);\n }\n\n if (this.screenTransceiver) {\n this.screenTransceiver.direction = \"inactive\";\n }\n\n try {\n if (this.publisher) {\n const offer = await this.publisher.createOffer();\n\n await this.publisher.setLocalDescription(offer);\n\n const localDescription = this.publisher.localDescription;\n\n if (localDescription?.sdp) {\n this.send({\n type: \"publish_offer\",\n payload: {\n revision: ++this.publisherRevision,\n sdp: localDescription.sdp,\n },\n });\n }\n }\n } catch (error) {\n this.onError(error);\n }\n\n this.send({\n type: \"stop_screen_share\",\n });\n\n stream?.getTracks().forEach((track) => {\n try {\n track.stop();\n } catch {}\n });\n\n this.screenStream = null;\n\n if (this.currentParticipantId) {\n this.onScreenShareStopped(this.currentParticipantId);\n }\n }\n\n muteAudio(muted: boolean) {\n this.desiredAudioMuted = muted;\n this.localStream?.getAudioTracks().forEach((track) => {\n track.enabled = !muted;\n });\n\n this.send({\n type: \"set_media_state\",\n payload: { audio_muted: muted, video_muted: this.desiredVideoMuted },\n });\n\n const trackId = this.localTrackIds.get(\"audio\");\n if (trackId) {\n this.send({\n type: \"track_state\",\n payload: {\n track_id: trackId,\n muted,\n },\n });\n }\n }\n\n muteVideo(muted: boolean) {\n this.desiredVideoMuted = muted;\n this.localStream?.getVideoTracks().forEach((track) => {\n track.enabled = !muted;\n });\n\n this.send({\n type: \"set_media_state\",\n payload: { audio_muted: this.desiredAudioMuted, video_muted: muted },\n });\n\n const trackId = this.localTrackIds.get(\"camera\");\n if (trackId) {\n this.send({\n type: \"track_state\",\n payload: {\n track_id: trackId,\n muted,\n },\n });\n }\n }\n\n sendChatMessage(input: {\n message: string;\n reply_to?: any;\n target?: string | null;\n }) {\n return this.send({\n type: \"send_chat\",\n payload: {\n message: input.message,\n reply_to: input.reply_to ?? null,\n target: input.target ?? null,\n },\n });\n }\n\n private getLiveTranscriptionMimeType(): string {\n if (typeof MediaRecorder === \"undefined\") {\n throw new Error(\"MediaRecorder is not supported by this browser\");\n }\n\n const candidates = [\n \"audio/webm;codecs=opus\",\n \"audio/webm\",\n \"audio/ogg;codecs=opus\",\n ];\n\n return candidates.find((type) => MediaRecorder.isTypeSupported(type)) || \"\";\n }\n\n async startLiveTranscription(\n audioTrack: MediaStreamTrack,\n speakerName?: string,\n ): Promise<void> {\n if (this.liveTranscriptionActive) return;\n if (!this.room) throw new Error(\"Cannot start live transcription without a room\");\n if (!this.authToken) throw new Error(\"Cannot start live transcription without an authenticated token\");\n if (!audioTrack || audioTrack.kind !== \"audio\") {\n throw new Error(\"A live microphone audio track is required\");\n }\n\n const mimeType = this.getLiveTranscriptionMimeType();\n this.liveTranscriptionActive = true;\n this.liveTranscriptionSequence = 0;\n this.liveTranscriptionStartedAt = Date.now();\n\n const stream = new MediaStream([audioTrack]);\n this.liveTranscriptionLoopPromise = this.runLiveTranscriptionLoop(\n stream,\n mimeType,\n ).finally(() => {\n this.liveTranscriptionRecorder = null;\n this.liveTranscriptionLoopPromise = null;\n });\n\n void speakerName;\n await Promise.resolve();\n }\n\n private async captureLiveChunk(\n stream: MediaStream,\n mimeType: string,\n ): Promise<Blob | null> {\n return new Promise((resolve, reject) => {\n const chunks: Blob[] = [];\n const recorder = mimeType\n ? new MediaRecorder(stream, { mimeType })\n : new MediaRecorder(stream);\n\n this.liveTranscriptionRecorder = recorder;\n\n const timeout = setTimeout(() => {\n if (recorder.state !== \"inactive\") recorder.stop();\n }, 4500);\n\n recorder.ondataavailable = (event) => {\n if (event.data.size > 0) chunks.push(event.data);\n };\n\n recorder.onerror = () => {\n clearTimeout(timeout);\n reject(new Error(\"Live transcription recorder failed\"));\n };\n\n recorder.onstop = () => {\n clearTimeout(timeout);\n this.liveTranscriptionRecorder = null;\n resolve(\n chunks.length\n ? new Blob(chunks, { type: recorder.mimeType || mimeType || \"audio/webm\" })\n : null,\n );\n };\n\n recorder.start();\n });\n }\n\n private async runLiveTranscriptionLoop(\n stream: MediaStream,\n mimeType: string,\n ): Promise<void> {\n while (\n this.liveTranscriptionActive &&\n stream.getAudioTracks()[0]?.readyState === \"live\"\n ) {\n try {\n const blob = await this.captureLiveChunk(stream, mimeType);\n if (!this.liveTranscriptionActive) break;\n if (!blob || blob.size === 0) continue;\n\n const sequence = this.liveTranscriptionSequence++;\n const offsetMs = Math.max(0, Date.now() - this.liveTranscriptionStartedAt);\n await this.uploadLiveTranscriptionChunk(blob, sequence, offsetMs, mimeType);\n } catch (error) {\n this.onError(error);\n await new Promise((resolve) => setTimeout(resolve, 750));\n }\n }\n }\n\n private async uploadLiveTranscriptionChunk(\n blob: Blob,\n sequence: number,\n offsetMs: number,\n mimeType: string,\n ) {\n if (!this.room || !this.authToken) return;\n\n const form = new FormData();\n form.append(\"sequence\", String(sequence));\n form.append(\"offset_ms\", String(offsetMs));\n const extension = mimeType.includes(\"ogg\") || blob.type.includes(\"ogg\") ? \"ogg\" : \"webm\";\n form.append(\"audio\", blob, `live-${sequence}.${extension}`);\n\n const response = await fetch(\n `${this.apiBase}/rooms/${encodeURIComponent(this.room)}/live-transcription`,\n {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${this.authToken}`,\n Accept: \"application/json\",\n },\n body: form,\n },\n );\n\n if (!response.ok) {\n let detail = `Live transcription request failed: ${response.status}`;\n try {\n const body = await response.json();\n detail = body?.message || body?.detail || detail;\n } catch {\n // Ignore non-JSON error responses.\n }\n throw new Error(detail);\n }\n }\n\n stopLiveTranscription() {\n this.liveTranscriptionActive = false;\n try {\n if (this.liveTranscriptionRecorder?.state !== \"inactive\") {\n this.liveTranscriptionRecorder?.stop();\n }\n } catch {\n // Ignore recorder shutdown errors during teardown.\n }\n this.liveTranscriptionRecorder = null;\n }\n\n isLiveTranscriptionActive() {\n return this.liveTranscriptionActive;\n }\n\n async applyNetworkRecommendation(action: string) {\n if (!this.videoSender || this.networkProfile === action) return;\n\n const params = this.videoSender.getParameters();\n const encodings = params.encodings?.length\n ? params.encodings\n : [{} as RTCRtpEncodingParameters];\n const encoding = encodings[0];\n\n switch (action) {\n case \"reduce_video\":\n encoding.maxBitrate = 700_000;\n encoding.maxFramerate = 20;\n break;\n case \"audio_priority\":\n encoding.maxBitrate = 350_000;\n encoding.maxFramerate = 10;\n break;\n default:\n encoding.maxBitrate = 1_500_000;\n encoding.maxFramerate = 30;\n break;\n }\n\n params.encodings = encodings;\n try {\n await this.videoSender.setParameters(params);\n this.networkProfile = action;\n } catch (error) {\n this.onError(error);\n }\n }\n\n async startRecording() {\n if (!this.send({ type: \"start_recording\" })) {\n throw new Error(\"SFU signaling is not connected\");\n }\n }\n\n async stopRecording() {\n if (!this.send({ type: \"stop_recording\" })) {\n throw new Error(\"SFU signaling is not connected\");\n }\n }\n\n async getRecordingStatus() {\n if (!this.room || !this.token) {\n throw new Error(\"SFU client is not connected\");\n }\n\n return this.request(\n `${this.apiBase}/rooms/${encodeURIComponent(this.room)}/recording`,\n {\n headers: {\n Authorization: `Bearer ${this.token}`,\n },\n },\n );\n }\n\n async approveJoinRequest(requestId: string) {\n if (!requestId) throw new Error(\"requestId is required\");\n if (\n !this.send({ type: \"approve_join\", payload: { request_id: requestId } })\n ) {\n throw new Error(\"SFU signaling is not connected\");\n }\n }\n\n async rejectJoinRequest(requestId: string, reason?: string) {\n if (!requestId) throw new Error(\"requestId is required\");\n if (\n !this.send({\n type: \"reject_join\",\n payload: { request_id: requestId, reason },\n })\n ) {\n throw new Error(\"SFU signaling is not connected\");\n }\n }\n\n async cancelJoinRequest(requestId?: string) {\n const id = requestId || this.pendingJoinRequestId;\n if (!id) return;\n if (\n !this.send({ type: \"cancel_join_request\", payload: { request_id: id } })\n ) {\n throw new Error(\"SFU signaling is not connected\");\n }\n this.pendingJoinRequestId = null;\n }\n\n async muteAllAudio() {\n if (!this.send({ type: \"mute_all_audio\" }))\n throw new Error(\"SFU signaling is not connected\");\n }\n\n async muteParticipant(participantId: string) {\n if (!participantId) throw new Error(\"participantId is required\");\n if (\n !this.send({\n type: \"mute_participant\",\n payload: { participant_id: participantId },\n })\n ) {\n throw new Error(\"SFU signaling is not connected\");\n }\n }\n\n async removeParticipant(participantId: string) {\n if (!participantId) throw new Error(\"participantId is required\");\n if (\n !this.send({\n type: \"remove_participant\",\n payload: { participant_id: participantId },\n })\n ) {\n throw new Error(\"SFU signaling is not connected\");\n }\n }\n\n async getModerators(roomCode: string) {\n return this.request(\n `${this.apiBase}/rooms/${encodeURIComponent(roomCode)}/moderators`,\n );\n }\n\n async addModerator(roomCode: string, userId: string) {\n return this.request(\n `${this.apiBase}/rooms/${encodeURIComponent(roomCode)}/moderators`,\n {\n method: \"POST\",\n body: JSON.stringify({ user_id: userId }),\n },\n );\n }\n\n async removeModerator(roomCode: string, userId: string) {\n return this.request(\n `${this.apiBase}/rooms/${encodeURIComponent(roomCode)}/moderators/${encodeURIComponent(userId)}`,\n {\n method: \"DELETE\",\n },\n );\n }\n\n private isSocketOpen() {\n return this.ws?.readyState === WebSocket.OPEN;\n }\n\n private send(message: any) {\n if (!this.isSocketOpen()) return false;\n this.ws!.send(\n JSON.stringify({\n request_id: this.nextRequestId(),\n ...message,\n }),\n );\n return true;\n }\n\n sendReaction(reaction: string): void {\n this.send({\n type: \"send_reaction\",\n payload: {\n emoji: reaction,\n },\n });\n }\n\n private removeRemoteParticipant(participantId: string) {\n const stream = this.remoteStreams.get(participantId);\n if (stream) {\n stream.getTracks().forEach((track) => track.stop());\n this.remoteStreams.delete(participantId);\n }\n\n const screenStream = this.remoteScreenStreams.get(participantId);\n if (screenStream) {\n screenStream.getTracks().forEach((track) => track.stop());\n this.remoteScreenStreams.delete(participantId);\n }\n\n for (const [trackId, metadata] of this.trackMetadata) {\n if (metadata.participant_id === participantId) {\n this.trackMetadata.delete(trackId);\n this.subscribedTracks.delete(trackId);\n this.trackToParticipant.delete(trackId);\n this.trackToSource.delete(trackId);\n }\n }\n }\n\n async leave() {\n this.stopLiveTranscription();\n this.stopHeartbeat();\n this.intentionalClose = true;\n this.setState(\"leaving\");\n\n if (this.reconnectTimer) {\n clearTimeout(this.reconnectTimer);\n this.reconnectTimer = null;\n }\n\n const roomCode = this.room;\n const ws = this.ws;\n this.leaveAcknowledged = false;\n\n if (ws?.readyState === WebSocket.OPEN) {\n await new Promise<void>((resolve) => {\n let settled = false;\n const finish = () => {\n if (settled) return;\n settled = true;\n resolve();\n };\n\n // The normal onmessage path remains authoritative. We only wait for\n // the server's `left` acknowledgement through a short polling window.\n const timeout = setTimeout(finish, 1200);\n\n const check = () => {\n if (this.leaveAcknowledged || this.ws !== ws) {\n clearTimeout(timeout);\n finish();\n return;\n }\n if (ws.readyState !== WebSocket.OPEN) {\n clearTimeout(timeout);\n finish();\n return;\n }\n setTimeout(check, 25);\n };\n\n ws.addEventListener(\n \"close\",\n () => {\n clearTimeout(timeout);\n finish();\n },\n { once: true },\n );\n\n this.send({ type: \"leave\" });\n check();\n });\n\n try {\n ws.close(1000, \"client_leave\");\n } catch {\n // ignore\n }\n }\n\n this.clearResumeToken(roomCode);\n this.cleanupAll();\n this.setState(\"disconnected\");\n }\n\n private closePeerConnectionsOnly() {\n if (this.publisher) {\n try {\n this.publisher.close();\n } catch {\n /* ignore */\n }\n this.publisher = null;\n }\n if (this.subscriber) {\n try {\n this.subscriber.close();\n } catch {\n /* ignore */\n }\n this.subscriber = null;\n }\n this.videoSender = null;\n this.audioSender = null;\n this.screenSender = null;\n this.audioTransceiver = null;\n this.cameraTransceiver = null;\n this.screenTransceiver = null;\n this.pendingIce = { publisher: [], subscriber: [] };\n this.offerQueue = [];\n this.subscriberNegotiating = false;\n this.subscriptionQueue = [];\n this.subscriptionRunning = false;\n this.subscriptionWaiters\n .splice(0)\n .forEach((w) => w.reject(new Error(\"PeerConnection recreated\")));\n this.subscribedTracks.clear();\n }\n\n private cleanupAll() {\n if (this.subscriberStatsTimer) {\n clearInterval(this.subscriberStatsTimer);\n this.subscriberStatsTimer = null;\n }\n\n this.closePeerConnectionsOnly();\n\n this.localStream?.getTracks().forEach((track) => track.stop());\n this.screenStream?.getTracks().forEach((track) => track.stop());\n this.localStream = null;\n this.screenStream = null;\n\n for (const stream of this.remoteStreams.values()) {\n stream.getTracks().forEach((track) => track.stop());\n }\n this.remoteStreams.clear();\n\n for (const stream of this.remoteScreenStreams.values()) {\n stream.getTracks().forEach((track) => track.stop());\n }\n this.remoteScreenStreams.clear();\n\n this.trackMetadata.clear();\n this.trackToParticipant.clear();\n this.trackToSource.clear();\n this.localTrackIds.clear();\n this.participants.clear();\n this.currentParticipantId = null;\n this.resumeToken = null;\n this.pendingJoinRequestId = null;\n this.token = null;\n this.room = null;\n\n if (this.ws) {\n try {\n this.ws.close();\n } catch {\n /* ignore */\n }\n this.ws = null;\n }\n }\n\n private async logSubscriberVideoStats() {\n if (!this.subscriber || this.subscriber.connectionState === \"closed\")\n return;\n try {\n const stats = await this.subscriber.getStats();\n stats.forEach((report: any) => {\n if (\n report.type === \"inbound-rtp\" &&\n (report.kind === \"video\" || report.mediaType === \"video\")\n ) {\n console.debug(\"[SFU] subscriber video\", {\n packetsReceived: report.packetsReceived,\n packetsLost: report.packetsLost,\n framesDecoded: report.framesDecoded,\n frameWidth: report.frameWidth,\n frameHeight: report.frameHeight,\n });\n }\n });\n } catch {\n // stats are diagnostic only\n }\n }\n\n private recoverWebRTC(reason: string) {\n if (this.intentionalClose) return;\n\n if (this.transportRecoveryInProgress) {\n console.debug(\"[SFU] WebRTC recovery already in progress\", {\n reason,\n });\n return;\n }\n\n this.transportRecoveryInProgress = true;\n\n console.warn(\"[SFU] WebRTC transport failed; starting recovery\", {\n reason,\n publisherState: this.publisher?.connectionState,\n publisherIceState: this.publisher?.iceConnectionState,\n subscriberState: this.subscriber?.connectionState,\n subscriberIceState: this.subscriber?.iceConnectionState,\n });\n\n this.setState(\"reconnecting\");\n\n this.transportRecoveryTimer = setTimeout(() => {\n this.transportRecoveryTimer = null;\n\n if (this.intentionalClose) {\n this.transportRecoveryInProgress = false;\n return;\n }\n\n const ws = this.ws;\n\n if (ws && ws.readyState === WebSocket.OPEN) {\n try {\n ws.close(4000, \"webrtc_recovery\");\n } catch (error) {\n console.warn(\"[SFU] Failed to close WebSocket for recovery\", error);\n\n this.transportRecoveryInProgress = false;\n this.scheduleReconnect();\n }\n\n return;\n }\n\n this.transportRecoveryInProgress = false;\n this.scheduleReconnect();\n }, 250);\n }\n}\n","import { SDK_CONFIG } from \"../config/ws\";\nimport {\n ChatInput,\n Events,\n PubSubTopic,\n PubSubTopicConfig,\n MeetingConfig,\n SDKError,\n RecordingInfo,\n VideoSDKCoreOptions,\n SFUConnectionState,\n LiveTranscript,\n NetworkQuality,\n} from \"../types/meeting\";\nimport { ActiveSpeakerDetector } from \"./ActiveSpeakerDetector\";\nimport { MeetingState } from \"./MeetingState\";\nimport { SFUClient, TrackInfo } from \"./SFUClient\";\n\nexport class VideoSDKCore {\n private sfuClient: SFUClient | null = null;\n private myId: string;\n private room: {\n id: string | null;\n name: string | null;\n } = {\n id: null,\n name: null,\n };\n private localStream: MediaStream | null = null;\n private screenStream: MediaStream | null = null;\n private isScreenSharing = false;\n private participantName = \"\";\n\n public readonly state: MeetingState;\n\n private intentionalDisconnect = false;\n\n private remoteStreams = new Map<string, MediaStream>();\n private remoteScreenStreams = new Map<string, MediaStream>();\n\n private activeSpeakerDetector: ActiveSpeakerDetector;\n\n private joinPromise: Promise<void> | null = null;\n private disconnectPromise: Promise<void> | null = null;\n\n private emitError(\n code: string,\n message: string,\n raw?: any,\n recoverable = true,\n ) {\n const err: SDKError = {\n code,\n message,\n raw,\n roomId: this.room.id,\n participantId: this.myId,\n recoverable,\n };\n\n this.events.onError?.(err);\n\n console.error(\"[MeetingSDK Error]\", err);\n }\n\n constructor(\n options: VideoSDKCoreOptions,\n private events: Events = {},\n private apiBase: string = SDK_CONFIG.apiBase,\n private wsBase: string = SDK_CONFIG.wsBase,\n ) {\n this.state = new MeetingState();\n this.events = events;\n this.activeSpeakerDetector = new ActiveSpeakerDetector({\n onActiveSpeakersChanged: (participantIds) => {\n this.state.setActiveSpeakers(participantIds);\n\n this.events.onActiveSpeakersChanged?.(participantIds);\n },\n });\n this.myId = options.participantId;\n this.sfuClient = this.createSFUClient(options.token);\n }\n\n // LOCAL MEDIA\n\n async initLocal(video: HTMLVideoElement, name: string) {\n this.participantName = name;\n\n try {\n this.localStream = await navigator.mediaDevices.getUserMedia({\n video: {\n width: { ideal: 1280 },\n height: { ideal: 720 },\n },\n audio: {\n echoCancellation: true,\n noiseSuppression: true,\n autoGainControl: true,\n },\n });\n\n const localAudioTrack = this.localStream.getAudioTracks()[0];\n\n if (localAudioTrack) {\n this.activeSpeakerDetector.addTrack(this.myId, localAudioTrack);\n }\n\n const hasVideo = this.localStream\n .getVideoTracks()\n .some((t) => t.readyState === \"live\");\n\n const hasAudio = this.localStream\n .getAudioTracks()\n .some((t) => t.readyState === \"live\");\n\n if (!hasVideo || !hasAudio) {\n throw new Error(`Missing tracks: video=${hasVideo}, audio=${hasAudio}`);\n }\n\n video.srcObject = this.localStream;\n\n this.updateLocalMedia();\n } catch (err: any) {\n this.emitError(\"GET_USER_MEDIA_FAILED\", err?.message, err, false);\n\n throw err;\n }\n }\n\n private updateLocalMedia(audioMuted = false, videoMuted = false) {\n if (!this.localStream) return;\n\n this.state.updateLocalParticipant({\n id: this.myId,\n name: this.participantName,\n\n media: {\n stream: this.localStream,\n cameraTrack: this.localStream.getVideoTracks()[0],\n audioTrack: this.localStream.getAudioTracks()[0],\n micEnabled:\n this.localStream.getAudioTracks()[0]?.enabled ?? !audioMuted,\n camEnabled:\n this.localStream.getVideoTracks()[0]?.enabled ?? !videoMuted,\n isScreenSharing: this.isScreenSharing,\n screenStream: this.screenStream,\n screenTrack: this.screenStream?.getVideoTracks()[0],\n },\n });\n\n this.state.localStream = this.localStream;\n }\n\n // ROOM MANAGEMENT\n async createRoom(input: {\n name: string;\n description?: string;\n capacity?: number;\n is_private?: boolean;\n }) {\n return this.sfuClient!.createRoom(input);\n }\n\n async getRoom(roomCode: string) {\n return this.sfuClient!.getRoom(roomCode);\n }\n\n async getJoinState(roomCode: string) {\n return this.sfuClient!.getJoinState(roomCode);\n }\n\n async deleteRoom(roomCode: string) {\n return this.sfuClient!.deleteRoom(roomCode);\n }\n\n // JOIN\n async joinMeeting(\n config: Omit<MeetingConfig, \"participantId\">,\n ): Promise<void> {\n const { roomId, name, audioMuted = false, videoMuted = false } = config;\n\n if (!roomId || !name) {\n throw new Error(\"roomId and name are required to join meeting\");\n }\n\n if (!this.myId) {\n throw new Error(\"participantId is required\");\n }\n\n if (\n this.sfuClient &&\n this.room.id === roomId &&\n this.sfuClient.getConnectionState() === \"connected\"\n ) {\n console.info(\"[SDK] Already connected; duplicate join ignored\", {\n roomId,\n participantId: this.myId,\n });\n\n return;\n }\n\n if (this.joinPromise) {\n console.info(\n \"[SDK] Join already in progress; waiting for existing join\",\n {\n roomId,\n participantId: this.myId,\n },\n );\n\n return this.joinPromise;\n }\n\n if (this.sfuClient && this.room.id && this.room.id !== roomId) {\n throw new Error(\n `Already connected to room ${this.room.id}. Leave the current meeting before joining another room.`,\n );\n }\n\n this.intentionalDisconnect = false;\n this.participantName = name;\n this.room.id = roomId;\n this.room.name = name;\n\n if (!this.localStream) {\n this.localStream = await navigator.mediaDevices.getUserMedia({\n video: true,\n audio: true,\n });\n\n const localAudioTrack = this.localStream.getAudioTracks()[0];\n\n if (localAudioTrack) {\n this.activeSpeakerDetector.addTrack(this.myId, localAudioTrack);\n }\n }\n\n this.localStream.getAudioTracks().forEach((track) => {\n track.enabled = !audioMuted;\n });\n\n this.localStream.getVideoTracks().forEach((track) => {\n track.enabled = !videoMuted;\n });\n\n this.updateLocalMedia(audioMuted, videoMuted);\n\n const promise = this.connect(roomId, name);\n\n this.joinPromise = promise;\n\n try {\n await promise;\n } finally {\n if (this.joinPromise === promise) {\n this.joinPromise = null;\n }\n }\n }\n\n // SFU CONNECTION\n private async connect(roomId: string, name: string): Promise<void> {\n if (!this.sfuClient) {\n throw new Error(\"SFU client is not initialized\");\n }\n\n const state = this.sfuClient.getConnectionState();\n\n if (\n this.room.id === roomId &&\n (state === \"connecting\" ||\n state === \"joining\" ||\n state === \"waiting_approval\" ||\n state === \"connected\" ||\n state === \"reconnecting\")\n ) {\n console.info(\"[SDK] Existing SFU connection is active; connect ignored\", {\n roomId,\n state,\n });\n return;\n }\n\n if (state !== \"idle\" && state !== \"disconnected\") {\n throw new Error(\n `SFU client is already active in state \"${state}\". Leave the current meeting before joining another room.`,\n );\n }\n\n this.sfuClient.setLocalStream(this.localStream);\n\n await this.sfuClient.getToken(roomId, {\n displayName: name,\n participantId: this.myId,\n audioMuted: !(this.localStream?.getAudioTracks()[0]?.enabled ?? true),\n videoMuted: !(this.localStream?.getVideoTracks()[0]?.enabled ?? true),\n });\n }\n\n private createSFUClient(token: string) {\n return new SFUClient({\n apiBase: this.apiBase,\n wsBase: this.wsBase,\n participantId: this.myId,\n token,\n autoSubscribe: true,\n // CONNECTION STATE\n\n onStateChange: (state) => {\n this.handleSFUState(state);\n },\n\n onConnected: (payload, resumed) => {\n const local = (payload?.participants || []).find(\n (participant: any) => participant?.participant_id === this.myId,\n );\n\n const permissions = local?.permissions ?? payload?.permissions ?? {};\n const isModerator = Boolean(permissions?.moderate);\n const isHost = Boolean(\n local?.is_host ?? local?.isHost ?? permissions?.host,\n );\n\n this.state.updateLocalParticipant({\n id: this.myId,\n name: local?.user_metadata?.name,\n isHost,\n isModerator,\n permissions,\n media: {\n micEnabled: !Boolean(local?.audio_muted),\n camEnabled: !Boolean(local?.video_muted),\n },\n });\n },\n\n onDisconnected: () => {\n console.log(\"[SFU] Signaling WebSocket disconnected; reconnecting\");\n },\n\n onReconnecting: (attempt) => {\n console.warn(`[SFU] Reconnecting, attempt ${attempt}`);\n },\n\n // ADMISSION CONTROL\n onLiveTranscript: (transcript: LiveTranscript) => {\n this.state.addLiveTranscript(transcript);\n this.events.onLiveTranscript?.(transcript);\n },\n\n onNetworkQuality: (quality: NetworkQuality) => {\n this.state.setNetworkQuality(quality);\n this.events.onNetworkQuality?.(quality);\n },\n\n onRoomUpdate: (payload) => {\n const participants = payload?.participants || [];\n const local = participants.find(\n (p: any) => p?.participant_id === this.myId,\n );\n if (local) {\n const media = this.state.localParticipant?.media;\n this.state.updateLocalParticipant({\n id: this.myId,\n name: this.participantName,\n media: {\n micEnabled: !Boolean(local.audio_muted),\n camEnabled: !Boolean(local.video_muted),\n isScreenSharing: Boolean(local.screen_sharing),\n screenStream: this.screenStream,\n screenTrack: this.screenStream?.getVideoTracks()[0],\n },\n });\n if (this.localStream) {\n this.localStream.getAudioTracks().forEach((track) => {\n track.enabled = !Boolean(local.audio_muted);\n });\n this.localStream.getVideoTracks().forEach((track) => {\n track.enabled = !Boolean(local.video_muted);\n });\n }\n if (local.screen_sharing) this.state.setPresenterId(this.myId);\n else if (this.state.presenterId === this.myId)\n this.state.setPresenterId(null);\n }\n const presenter = participants.find((p: any) => p?.screen_sharing);\n if (presenter) this.state.setPresenterId(presenter.participant_id);\n else if (!local?.screen_sharing) this.state.setPresenterId(null);\n for (const message of payload?.chat_history || []) {\n this.state.addChatMessage(message);\n }\n this.events.onRoomUpdate?.(payload);\n },\n\n onJoinPending: (info) => {\n console.log(\"[SFU] Join request pending\", info);\n },\n\n onJoinApproved: (requestId) => {\n console.log(\"[SFU] Join approved\", requestId);\n this.events.onJoinApproved?.(requestId);\n this.events.onEntryResponded?.(\n {\n participantId: this.myId,\n decision: \"approved\",\n },\n\n \"approved\",\n );\n },\n\n onJoinRejected: (requestId, reason) => {\n console.warn(\"[SFU] Join rejected\", requestId, reason);\n this.events.onJoinRejected?.(requestId);\n this.events.onEntryResponded?.(\n {\n participantId: this.myId,\n decision: \"rejected\",\n },\n\n \"rejected\",\n );\n\n this.emitError(\n \"JOIN_REJECTED\",\n reason || \"Your request to join was rejected\",\n {\n requestId,\n reason,\n },\n false,\n );\n },\n\n onChatMessage: (message) => {\n const msg = {\n id: message.id,\n text: message.text,\n sender_id: message.sender_id,\n sender_name: message.sender_name,\n timestamp: Number(message.timestamp),\n reply_to: message.reply_to ?? null,\n target: message.target ?? null,\n };\n this.state.addChatMessage(msg);\n this.events.onChatMessage?.(msg);\n },\n onReaction: (reaction) => {\n this.events.onReaction?.(reaction);\n },\n onJoinRequestCanceled: (requestId) => {\n this.events.onJoinRequestCanceled?.(requestId);\n },\n\n onParticipantRemoved: (participantId, removedBy) => {\n if (participantId === this.myId) {\n this.intentionalDisconnect = true;\n this.events.onUserLeft?.(participantId);\n try {\n this.localStream\n ?.getTracks()\n .forEach((track) => (track.enabled = false));\n } catch {}\n } else {\n this.cleanupRemoteParticipant(participantId);\n this.state.removeParticipant(participantId);\n this.events.onUserLeft?.(participantId);\n }\n this.events.onParticipantRemoved?.(participantId, removedBy);\n },\n\n onParticipantPermissionsChanged: (participantId, permissions) => {\n if (participantId === this.myId) {\n const current = this.state.localParticipant;\n this.state.updateLocalParticipant({\n id: this.myId,\n name: this.participantName,\n isHost: current?.isHost,\n isModerator: Boolean(permissions?.moderate),\n permissions,\n });\n }\n },\n\n onJoinRequested: (request) => {\n const requestId = request?.request_id || request?.requestId;\n const participantId = request?.user_id || request?.participantId;\n const nameValue =\n request?.user_metadata?.name ||\n request?.display_name ||\n request?.name ||\n \"Participant\";\n\n if (!requestId || !participantId) {\n return;\n }\n\n this.events.onEntryRequested?.({\n requestId,\n participantId,\n name: nameValue,\n });\n },\n\n // PARTICIPANTS\n onParticipantJoined: (participant) => {\n const pid = participant.participant_id;\n\n if (!pid || pid === this.myId) {\n return;\n }\n\n const pname =\n participant.user_metadata?.name ||\n participant.display_name ||\n \"Participant\";\n\n this.state.addParticipant({\n id: pid,\n name: pname,\n isModerator: Boolean(participant?.permissions?.moderate),\n permissions: participant?.permissions,\n connectionState: \"connected\",\n media: {\n micEnabled: true,\n camEnabled: true,\n isScreenSharing: false,\n stream: null,\n },\n });\n\n this.events.onUserJoined?.({\n id: pid,\n name: pname,\n });\n },\n\n onParticipantPresence: (participantId, presence) => {\n if (participantId === this.myId) {\n return;\n }\n\n const current = this.state.getParticipant(participantId);\n\n if (!current) {\n return;\n }\n\n const connectionState =\n presence === \"reconnecting\"\n ? \"reconnecting\"\n : presence === \"connected\" || presence === \"online\"\n ? \"connected\"\n : presence === \"disconnected\"\n ? \"disconnected\"\n : current.connectionState;\n\n this.state.updateParticipantMedia(participantId, {\n stream: current.media?.stream ?? null,\n });\n\n const next = new Map(this.state.participants);\n\n next.set(participantId, {\n ...current,\n connectionState,\n });\n\n this.state.participants = next;\n\n this.state.notify(`participant:${participantId}`);\n\n this.state.notify(\"participants\");\n },\n\n onParticipantLeft: (participant) => {\n const pid =\n typeof participant === \"string\"\n ? participant\n : participant.participant_id;\n\n if (!pid) {\n return;\n }\n\n console.log(\"[SFU] Participant permanently left\", pid);\n\n this.cleanupRemoteParticipant(pid);\n this.state.removeParticipant(pid);\n this.events.onUserLeft?.(pid);\n },\n\n // TRACKS\n onParticipantMediaState: (participantId, audioMuted, videoMuted) => {\n if (participantId === this.myId) {\n this.localStream\n ?.getAudioTracks()\n .forEach((track) => (track.enabled = !audioMuted));\n this.localStream\n ?.getVideoTracks()\n .forEach((track) => (track.enabled = !videoMuted));\n this.state.updateLocalParticipant({\n id: this.myId,\n name: this.participantName,\n media: { micEnabled: !audioMuted, camEnabled: !videoMuted },\n });\n this.events.onMuteStateChanged?.(participantId, \"audio\", audioMuted);\n this.events.onMuteStateChanged?.(participantId, \"video\", videoMuted);\n return;\n }\n const participant = this.state.getParticipant(participantId);\n if (!participant) return;\n this.state.updateParticipantMedia(participantId, {\n micEnabled: !audioMuted,\n camEnabled: !videoMuted,\n });\n this.events.onMuteStateChanged?.(participantId, \"audio\", audioMuted);\n this.events.onMuteStateChanged?.(participantId, \"video\", videoMuted);\n },\n\n onTrackPublished: (track) => {\n console.log(\"[SFU] Track published\", track);\n },\n\n onTrackUnpublished: (track) => {\n console.log(\"[SFU] Track unpublished\", track);\n const pid = track.participant_id;\n\n if (!pid) {\n return;\n }\n\n const current = this.state.getParticipant(pid);\n if (track.source === \"screen\") {\n const screen = this.remoteScreenStreams.get(pid);\n\n screen?.getTracks().forEach((t) => t.stop());\n\n this.remoteScreenStreams.delete(pid);\n\n this.state.updateParticipantMedia(pid, {\n isScreenSharing: false,\n screenStream: null,\n screenTrack: undefined,\n });\n\n this.events.onScreenShareStopped?.(pid);\n\n return;\n }\n\n if (!current) {\n return;\n }\n\n this.state.updateParticipantMedia(pid, {\n stream: current.media?.stream ?? null,\n micEnabled:\n track.kind === \"audio\"\n ? false\n : (current.media?.micEnabled ?? true),\n\n camEnabled:\n track.kind === \"video\"\n ? false\n : (current.media?.camEnabled ?? true),\n });\n },\n\n onTrackStateChanged: (track) => {\n const pid = track.participant_id;\n\n if (!pid || pid === this.myId) {\n return;\n }\n\n const current = this.state.getParticipant(pid);\n\n if (!current) {\n return;\n }\n\n if (track.source === \"audio\") {\n this.state.updateParticipantMedia(pid, {\n stream: current.media?.stream ?? null,\n micEnabled: !track.muted,\n });\n\n this.events.onMuteStateChanged?.(pid, \"audio\", track.muted);\n } else if (track.source === \"camera\") {\n this.state.updateParticipantMedia(pid, {\n stream: current.media?.stream ?? null,\n camEnabled: !track.muted,\n });\n\n this.events.onMuteStateChanged?.(pid, \"video\", track.muted);\n }\n\n this.events.onTrackStateChanged?.(track as any);\n },\n\n // RECORDING\n onRecordingStarted: (recording) => {\n this.state.setRecording({\n recording_id: recording.recording_id,\n started_at: recording.started_at,\n status: \"recording\",\n active: true,\n late_join: true,\n });\n\n this.events.onRecordingStarted?.(recording);\n },\n\n onRecordingStopped: (recording) => {\n this.state.setRecording({\n recording_id: recording.recording_id,\n stopped_at: recording.stopped_at,\n status: \"stopped\",\n active: false,\n });\n\n this.events.onRecordingStopped?.(recording);\n },\n\n // REMOTE MEDIA\n onRemoteTrack: (track, stream, metadata) => {\n this.handleRemoteTrack(track, stream, metadata);\n },\n\n // SCREEN SHARE\n onScreenShareStarted: (participantId, _track) => {\n console.log(\"[SFU] Screen share started\", participantId);\n\n if (participantId === this.myId) {\n if (!this.screenStream) {\n this.screenStream = this.sfuClient?.getScreenStream() ?? null;\n }\n\n this.state.setPresenterId(participantId);\n this.state.updateLocalParticipant({\n media: {\n isScreenSharing: true,\n screenStream: this.screenStream,\n screenTrack: this.screenStream?.getVideoTracks()[0],\n },\n });\n return;\n }\n\n this.state.setPresenterId(participantId);\n\n const existingRemoteScreen =\n this.sfuClient?.getRemoteScreenStream(participantId) ??\n this.remoteScreenStreams.get(participantId) ??\n null;\n\n if (existingRemoteScreen) {\n this.remoteScreenStreams.set(participantId, existingRemoteScreen);\n const screenTrack = existingRemoteScreen.getVideoTracks()[0];\n this.state.updateParticipantMedia(participantId, {\n isScreenSharing: true,\n screenStream: existingRemoteScreen,\n screenTrack,\n });\n this.events.onScreenShareStarted?.(\n participantId,\n existingRemoteScreen,\n );\n return;\n }\n\n const current = this.state.getParticipant(participantId);\n if (current) {\n this.state.updateParticipantMedia(participantId, {\n isScreenSharing: true,\n screenStream: current.media?.screenStream ?? null,\n screenTrack: current.media?.screenTrack,\n });\n }\n },\n\n onScreenShareStopped: (participantId) => {\n if (this.state.presenterId === participantId) {\n this.state.setPresenterId(null);\n }\n\n if (participantId === this.myId) {\n this.state.updateLocalParticipant({\n media: {\n isScreenSharing: false,\n screenStream: null,\n screenTrack: undefined,\n },\n });\n return;\n }\n\n this.state.updateParticipantMedia(participantId, {\n isScreenSharing: false,\n });\n\n this.events.onScreenShareStopped?.(participantId);\n },\n\n // ERROR\n onError: (error) => {\n console.error(\"[SFU] Error:\", error);\n\n if (\n error?.code === \"request_failed\" ||\n error?.code === \"authorization\"\n ) {\n this.emitError(\"PERMISSION_DENIED\", error.message, error, false);\n\n return;\n }\n\n this.emitError(\n \"SFU_ERROR\",\n error?.message || String(error),\n error,\n true,\n );\n },\n });\n }\n\n // SFU STATE\n private handleSFUState(state: SFUConnectionState) {\n this.events.onConnectionStateChanged?.(state);\n\n if (state === \"reconnecting\") {\n this.state.updateLocalParticipant({\n id: this.myId,\n name: this.participantName,\n });\n\n return;\n }\n\n if (state === \"disconnected\" && !this.intentionalDisconnect) {\n this.emitError(\n \"CONNECTION_LOST\",\n \"Unable to reconnect to SFU server\",\n null,\n true,\n );\n }\n }\n\n // REMOTE TRACKS\n private handleRemoteTrack(\n track: MediaStreamTrack,\n stream: MediaStream,\n metadata: TrackInfo,\n ) {\n const participantId = metadata?.participant_id;\n\n if (!participantId || participantId === this.myId) {\n return;\n }\n\n const source = String(metadata.source || \"\")\n .trim()\n .toLowerCase();\n\n /* SCREEN SHARE\n */\n if (source === \"screen\" || source === \"screen_share\") {\n let screenStream = this.remoteScreenStreams.get(participantId);\n\n if (!screenStream) {\n screenStream = new MediaStream();\n this.remoteScreenStreams.set(participantId, screenStream);\n }\n\n for (const old of screenStream.getVideoTracks()) {\n if (old.id !== track.id) {\n screenStream.removeTrack(old);\n old.stop();\n }\n }\n\n if (!screenStream.getTracks().some((t) => t.id === track.id)) {\n screenStream.addTrack(track);\n }\n\n this.state.updateParticipantMedia(participantId, {\n screenStream,\n screenTrack: track,\n isScreenSharing: true,\n });\n\n this.events.onScreenShareStarted?.(participantId, screenStream);\n\n return;\n }\n\n let remoteStream = this.remoteStreams.get(participantId);\n\n if (!remoteStream) {\n remoteStream = new MediaStream();\n\n this.remoteStreams.set(participantId, remoteStream);\n }\n\n for (const old of remoteStream.getTracks()) {\n if (old.kind === track.kind && old.id !== track.id) {\n remoteStream.removeTrack(old);\n old.stop();\n }\n }\n\n if (!remoteStream.getTracks().some((t) => t.id === track.id)) {\n remoteStream.addTrack(track);\n }\n\n const current = this.state.getParticipant(participantId);\n\n this.state.updateParticipantMedia(participantId, {\n stream: remoteStream,\n cameraTrack: track.kind === \"video\" ? track : current?.media?.cameraTrack,\n audioTrack: track.kind === \"audio\" ? track : current?.media?.audioTrack,\n });\n\n if (track.kind === \"audio\") {\n this.activeSpeakerDetector.addTrack(participantId, track);\n }\n\n this.events.onTrack?.(remoteStream, participantId);\n\n track.onended = () => {\n if (track.kind === \"video\") {\n this.state.updateParticipantMedia(participantId, {\n camEnabled: false,\n stream: remoteStream,\n });\n\n return;\n }\n\n this.state.updateParticipantMedia(participantId, {\n micEnabled: false,\n stream: remoteStream,\n });\n };\n }\n\n // MEETING\n getMeeting(): {\n id: string | null;\n name: string | null;\n } {\n return this.room;\n }\n\n // ADMISSION CONTROL\n async approveJoinRequest(requestId: string) {\n if (!this.sfuClient) {\n throw new Error(\"SFU client is not connected\");\n }\n\n return this.sfuClient.approveJoinRequest(requestId);\n }\n\n async rejectJoinRequest(requestId: string, reason?: string) {\n if (!this.sfuClient) {\n throw new Error(\"SFU client is not connected\");\n }\n\n return this.sfuClient.rejectJoinRequest(requestId, reason);\n }\n\n async cancelJoinRequest(requestId?: string) {\n return this.sfuClient?.cancelJoinRequest(requestId);\n }\n\n async muteAllAudio() {\n if (!this.sfuClient) throw new Error(\"SFU client is not connected\");\n return this.sfuClient.muteAllAudio();\n }\n\n async muteParticipant(participantId: string) {\n if (!this.sfuClient) throw new Error(\"SFU client is not connected\");\n return this.sfuClient.muteParticipant(participantId);\n }\n\n async removeParticipant(participantId: string) {\n if (!this.sfuClient) throw new Error(\"SFU client is not connected\");\n return this.sfuClient.removeParticipant(participantId);\n }\n\n async getModerators(roomCode: string) {\n return this.sfuClient?.getModerators(roomCode);\n }\n\n async addModerator(roomCode: string, userId: string) {\n return this.sfuClient?.addModerator(roomCode, userId);\n }\n\n async removeModerator(roomCode: string, userId: string) {\n return this.sfuClient?.removeModerator(roomCode, userId);\n }\n\n // MEDIA CONTROL\n toggleMic() {\n const mediaState = this.state.localParticipant?.media;\n\n if (!mediaState || !this.localStream) {\n return;\n }\n\n const nextEnabled = !mediaState.micEnabled;\n\n this.localStream.getAudioTracks().forEach((track) => {\n track.enabled = nextEnabled;\n });\n\n this.state.updateLocalParticipant({\n id: this.myId,\n name: this.participantName,\n media: {\n micEnabled: nextEnabled,\n },\n });\n\n this.sfuClient?.muteAudio(!nextEnabled);\n this.events.onMicToggled?.(this.myId, nextEnabled);\n }\n\n toggleCam() {\n const mediaState = this.state.localParticipant?.media;\n\n if (!mediaState || !this.localStream) {\n return;\n }\n\n const nextEnabled = !mediaState.camEnabled;\n\n this.localStream.getVideoTracks().forEach((track) => {\n track.enabled = nextEnabled;\n });\n\n this.state.updateLocalParticipant({\n id: this.myId,\n name: this.participantName,\n media: {\n camEnabled: nextEnabled,\n },\n });\n\n this.sfuClient?.muteVideo(!nextEnabled);\n\n this.events.onCamToggled?.(this.myId, nextEnabled);\n }\n\n // SCREEN SHARING\n async startScreenShare() {\n try {\n if (!navigator.mediaDevices?.getDisplayMedia) {\n throw new Error(\"Screen sharing not supported on this device\");\n }\n\n if (!this.sfuClient) {\n throw new Error(\"Cannot share screen before joining the meeting\");\n }\n\n this.screenStream = await this.sfuClient.shareScreen();\n\n this.isScreenSharing = true;\n\n this.state.updateLocalParticipant({\n media: {\n isScreenSharing: true,\n screenStream: this.screenStream,\n screenTrack: this.screenStream?.getVideoTracks()[0],\n },\n });\n\n return this.screenStream;\n } catch (err: any) {\n this.emitError(\n \"SCREEN_SHARE_FAILED\",\n err?.message || \"Failed to start screen sharing\",\n err,\n true,\n );\n\n this.isScreenSharing = false;\n this.screenStream = null;\n\n throw err;\n }\n }\n\n async stopScreenShare() {\n if (!this.sfuClient) {\n return;\n }\n\n try {\n await this.sfuClient.stopScreenShare();\n } finally {\n this.screenStream = null;\n this.isScreenSharing = false;\n\n this.state.updateLocalParticipant({\n media: {\n isScreenSharing: false,\n screenStream: null,\n screenTrack: undefined,\n },\n });\n }\n }\n\n // RECORDING\n async startRecording() {\n if (!this.sfuClient) {\n throw new Error(\"SFU client is not connected\");\n }\n\n await this.sfuClient.startRecording();\n }\n\n async stopRecording() {\n if (!this.sfuClient) {\n throw new Error(\"SFU client is not connected\");\n }\n\n await this.sfuClient.stopRecording();\n }\n\n async getRecordingStatus(): Promise<{\n recording: RecordingInfo | null;\n }> {\n if (!this.sfuClient) {\n throw new Error(\"SFU client is not connected\");\n }\n\n return this.sfuClient.getRecordingStatus();\n }\n\n // CHAT\n\n sendChatMessage(payload: ChatInput) {\n if (!this.sfuClient) {\n console.warn(\"SFU Client not connected\");\n return;\n }\n\n const message = payload.message.trim();\n if (!message) return;\n\n this.sfuClient.sendChatMessage({\n message,\n reply_to: payload.reply_to ?? null,\n target: payload.target ?? null,\n });\n }\n\n sendReaction(reaction: string): void {\n if (!this.sfuClient) {\n console.warn(\"SFU Client not connected\");\n return;\n }\n this.sfuClient.sendReaction(reaction);\n }\n\n /**\n * Generic PubSub publishing entry point.\n *\n * The public SDK exposes one PubSub API for all topics. The current SFU\n * protocol still has dedicated wire messages for chat and reactions, so\n * this method is the compatibility bridge. The application does not need\n * to know about those wire-level message types.\n */\n publishPubSub<T extends PubSubTopic>(\n topic: T,\n data: PubSubTopicConfig[T][\"publish\"],\n ): void {\n switch (topic) {\n case \"SECURE_CHAT\":\n this.sendChatMessage(data as ChatInput);\n return;\n\n case \"REACTION\":\n this.sendReaction((data as { emoji: string }).emoji);\n return;\n\n default: {\n const exhaustive: never = topic;\n throw new Error(`Unsupported PubSub topic: ${exhaustive}`);\n }\n }\n }\n\n async startLiveTranscription(): Promise<void> {\n if (!this.sfuClient) {\n throw new Error(\"SFU client is not connected\");\n }\n\n const audioTrack = this.localStream?.getAudioTracks()[0];\n if (!audioTrack) {\n throw new Error(\"Microphone audio track is not available\");\n }\n\n await this.sfuClient.startLiveTranscription(\n audioTrack,\n this.participantName,\n );\n }\n\n stopLiveTranscription(): void {\n this.sfuClient?.stopLiveTranscription();\n }\n\n isLiveTranscriptionActive(): boolean {\n return this.sfuClient?.isLiveTranscriptionActive() ?? false;\n }\n\n getNetworkQuality(): NetworkQuality | null {\n return this.state.networkQuality;\n }\n\n // CLEANUP\n private cleanupRemoteParticipant(participantId: string) {\n this.activeSpeakerDetector.removeParticipant(participantId);\n\n const stream = this.remoteStreams.get(participantId);\n\n stream?.getTracks().forEach((track) => track.stop());\n\n this.remoteStreams.delete(participantId);\n\n const screen = this.remoteScreenStreams.get(participantId);\n\n screen?.getTracks().forEach((track) => track.stop());\n\n this.remoteScreenStreams.delete(participantId);\n }\n\n // DISCONNECT\n async disconnect(): Promise<void> {\n if (this.disconnectPromise) {\n return this.disconnectPromise;\n }\n\n this.disconnectPromise = this.performDisconnect();\n\n try {\n await this.disconnectPromise;\n } finally {\n this.disconnectPromise = null;\n }\n }\n\n private async performDisconnect() {\n this.intentionalDisconnect = true;\n this.joinPromise = null;\n\n if (this.sfuClient) {\n await this.sfuClient.leave();\n }\n\n // LOCAL MEDIA\n if (this.localStream) {\n this.localStream.getTracks().forEach((track) => track.stop());\n\n this.localStream = null;\n }\n\n if (this.screenStream) {\n this.screenStream.getTracks().forEach((track) => track.stop());\n this.screenStream = null;\n }\n\n this.isScreenSharing = false;\n\n // REMOTE MEDIA\n for (const stream of this.remoteStreams.values()) {\n stream.getTracks().forEach((track) => track.stop());\n }\n\n this.remoteStreams.clear();\n for (const stream of this.remoteScreenStreams.values()) {\n stream.getTracks().forEach((track) => track.stop());\n }\n\n this.remoteScreenStreams.clear();\n this.room.id = null;\n this.room.name = null;\n\n this.state.localParticipant = null;\n this.state.clearLiveTranscripts();\n this.state.setNetworkQuality(null);\n\n this.state.notify(\"localParticipant\");\n\n this.state.resetRemoteState();\n this.events.onMeetingLeft?.();\n }\n}\n","import { useEffect, useState } from \"react\";\nimport { StateScope } from \"../types/meeting\";\nimport { MeetingState } from \"../core/MeetingState\";\n\nexport function useMeetingStore<T>(\n stateManager: MeetingState,\n scope: StateScope,\n selector: (state: MeetingState) => T,\n): T {\n const [state, setState] = useState(() => selector(stateManager));\n\n useEffect(() => {\n // Update local react state whenever the SDK notifies this scope\n const unsubscribe = stateManager.subscribe(scope, () => {\n setState(selector(stateManager));\n });\n\n return unsubscribe;\n }, [stateManager, scope, selector]);\n\n return state;\n}\n","import { useEffect } from \"react\";\nimport { useMeetingContext } from \"./MeetingProvider\";\nimport {\n SFUConnectionState,\n LiveTranscript,\n NetworkQuality,\n} from \"../types/meeting\";\n\nexport const useMeeting = (handlers?: {\n onError?: (err: any) => void;\n onEntryRequested?: (req: any) => void;\n onEntryResponded?: (payload: any, decision?: any) => void;\n onJoinRequestCanceled?: (requestId: string) => void;\n onParticipantRemoved?: (participantId: string, removedBy: string) => void;\n onParticipantPermissionsChanged?: (\n participantId: string,\n permissions: any,\n ) => void;\n onMeetingLeft?: () => void;\n onTrackStateChanged?: (track: any) => void;\n onRecordingStarted?: (recording: any) => void;\n onRecordingStopped?: (recording: any) => void;\n onReaction?: (reaction: any) => void;\n onActiveSpeakersChanged?: (participantIds: string[]) => void;\n onConnectionStateChanged?: (state: SFUConnectionState) => void;\n onLiveTranscript?: (transcript: LiveTranscript) => void;\n onNetworkQuality?: (quality: NetworkQuality) => void;\n}) => {\n const ctx = useMeetingContext();\n\n // Error Handler\n useEffect(() => {\n if (!handlers?.onError) return;\n return ctx.onError(handlers.onError);\n }, [handlers?.onError]);\n\n useEffect(() => {\n if (!handlers?.onActiveSpeakersChanged) return;\n\n return ctx.onActiveSpeakersChanged(handlers.onActiveSpeakersChanged);\n }, [handlers?.onActiveSpeakersChanged]);\n\n // Entry Request Handler\n useEffect(() => {\n if (!handlers?.onEntryRequested) return;\n return ctx.onEntryRequested(handlers.onEntryRequested);\n }, [handlers?.onEntryRequested]);\n\n // Entry Response Handler\n useEffect(() => {\n if (!handlers?.onEntryResponded) return;\n return ctx.onEntryResponded(handlers.onEntryResponded);\n }, [handlers?.onEntryResponded]);\n\n useEffect(() => {\n if (!handlers?.onJoinRequestCanceled) return;\n return ctx.onJoinRequestCanceled(handlers.onJoinRequestCanceled);\n }, [handlers?.onJoinRequestCanceled]);\n\n useEffect(() => {\n if (!handlers?.onParticipantRemoved) return;\n return ctx.onParticipantRemoved(handlers.onParticipantRemoved);\n }, [handlers?.onParticipantRemoved]);\n\n useEffect(() => {\n if (!handlers?.onParticipantPermissionsChanged) return;\n return ctx.onParticipantPermissionsChanged(\n handlers.onParticipantPermissionsChanged,\n );\n }, [handlers?.onParticipantPermissionsChanged]);\n\n // Meeting Left Handler\n useEffect(() => {\n if (!handlers?.onMeetingLeft) return;\n return ctx.onMeetingLeft(handlers.onMeetingLeft);\n }, [handlers?.onMeetingLeft]);\n\n useEffect(() => {\n if (!handlers?.onTrackStateChanged) return;\n return ctx.onTrackStateChanged(handlers.onTrackStateChanged);\n }, [handlers?.onTrackStateChanged]);\n\n useEffect(() => {\n if (!handlers?.onRecordingStarted) return;\n return ctx.onRecordingStarted(handlers.onRecordingStarted);\n }, [handlers?.onRecordingStarted]);\n\n useEffect(() => {\n if (!handlers?.onRecordingStopped) return;\n return ctx.onRecordingStopped(handlers.onRecordingStopped);\n }, [handlers?.onRecordingStopped]);\n\n useEffect(() => {\n if (!handlers?.onConnectionStateChanged) return;\n\n return ctx.onConnectionStateChanged(handlers.onConnectionStateChanged);\n }, [handlers?.onConnectionStateChanged]);\n\n useEffect(() => {\n if (!handlers?.onLiveTranscript) return;\n return ctx.onLiveTranscript(handlers.onLiveTranscript);\n }, [handlers?.onLiveTranscript]);\n\n useEffect(() => {\n if (!handlers?.onNetworkQuality) return;\n return ctx.onNetworkQuality(handlers.onNetworkQuality);\n }, [handlers?.onNetworkQuality]);\n\n useEffect(() => {\n if (!handlers?.onReaction) return;\n return ctx.onReaction(handlers.onReaction);\n }, [handlers?.onReaction]);\n\n const { sdk: _, ...publicApi } = ctx;\n return publicApi;\n};\n","import { useEffect, useState } from \"react\";\nimport { useMeetingContext } from \"./MeetingProvider\";\nimport { Participant } from \"../types/meeting\";\n\nexport const useParticipants = () => {\n const { sdk } = useMeetingContext();\n\n const [participants, setParticipants] = useState<Participant[]>(() =>\n sdk.state.getParticipants(),\n );\n\n useEffect(() => {\n const update = () => {\n setParticipants(sdk.state.getParticipants());\n };\n\n update();\n\n const unsub = sdk.state.subscribe(\"participants\", update);\n\n return unsub;\n }, [sdk]);\n\n return participants;\n};\n","import { useEffect, useRef, useState } from \"react\";\nimport { useMeetingContext } from \"./MeetingProvider\";\nimport { Participant } from \"../types/meeting\";\n\nexport const useRemoteMedia = (participantId: string) => {\n const { sdk } = useMeetingContext();\n const videoRef = useRef<HTMLVideoElement | null>(null);\n const audioRef = useRef<HTMLAudioElement | null>(null);\n\n const [participant, setParticipant] = useState<Participant | null>(\n () => sdk.state.getParticipant(participantId) || null,\n );\n\n useEffect(() => {\n const unsub = sdk.state.subscribe(`participant:${participantId}`, () => {\n const p = sdk.state.getParticipant(participantId);\n setParticipant(p ? { ...p } : null);\n });\n\n return unsub;\n }, [participantId, sdk]);\n\n useEffect(() => {\n const stream = participant?.media?.stream;\n if (!stream) return;\n\n // VIDEO\n if (videoRef.current) {\n videoRef.current.srcObject = stream;\n videoRef.current.muted = true;\n videoRef.current.playsInline = true;\n videoRef.current.play().catch(() => {});\n }\n\n // AUDIO\n if (audioRef.current) {\n audioRef.current.srcObject = stream;\n audioRef.current.play().catch(() => {});\n }\n }, [participant?.media?.stream]);\n\n return {\n videoRef,\n audioRef,\n isCamActive: !!participant?.media?.camEnabled,\n isMicEnabled: !!participant?.media?.micEnabled,\n connectionState: participant?.connectionState,\n };\n};\n","import { useEffect, useState } from \"react\";\nimport { SDK_CONFIG } from \"../config/ws\";\n\ntype LiveRoomState = {\n active: boolean;\n count: number;\n canJoin: boolean;\n approved: boolean;\n isHost: boolean;\n hasMoreParticipants: boolean;\n participants: {\n id: string;\n name: string;\n isHost: boolean;\n isPresenter: boolean;\n micEnabled: boolean;\n camEnabled: boolean;\n }[];\n room?: {\n id: string;\n name: string;\n room_code: string;\n capacity: number;\n is_private: boolean;\n };\n};\n\n/**\n * Current SFU does not expose the old `/watch/:room` mesh presence socket.\n * Preview therefore uses the authoritative REST room endpoint and polls it.\n * Live participant/media state begins after JOIN over the SFU WebSocket.\n */\nexport function useMeetingPreview(roomId: string, participantId: string) {\n const [room, setRoom] = useState<LiveRoomState | null>(null);\n const [error, setError] = useState<string | null>(null);\n const [isConnected, setIsConnected] = useState(false);\n const [isLoading, setIsLoading] = useState(true);\n\n useEffect(() => {\n if (!roomId) {\n setIsLoading(false);\n return;\n }\n\n let stopped = false;\n let timer: ReturnType<typeof setTimeout> | null = null;\n\n const load = async () => {\n try {\n const response = await fetch(\n `${SDK_CONFIG.apiBase}/rooms/${encodeURIComponent(roomId)}`,\n );\n\n if (!response.ok) {\n throw new Error(`Room lookup failed (${response.status})`);\n }\n\n const data = await response.json();\n if (stopped) return;\n\n setRoom({\n active: true,\n // The current REST room model intentionally does not expose a live\n // participant count. Do not fabricate one.\n count: 0,\n canJoin: !data.is_private,\n approved: false,\n isHost: false,\n hasMoreParticipants: false,\n participants: [],\n room: {\n id: data.id,\n name: data.name,\n room_code: data.room_code,\n capacity: data.capacity,\n is_private: data.is_private,\n },\n });\n setError(null);\n setIsConnected(true);\n setIsLoading(false);\n } catch (err: any) {\n if (stopped) return;\n setError(err?.message || \"Failed to load room\");\n setIsConnected(false);\n setIsLoading(false);\n } finally {\n if (!stopped) {\n timer = setTimeout(load, 5000);\n }\n }\n };\n\n void load();\n\n return () => {\n stopped = true;\n if (timer) clearTimeout(timer);\n };\n }, [roomId, participantId]);\n\n return {\n room,\n isConnected,\n isLoading,\n error,\n };\n}\n","import { useMeetingStore } from \"./useMeetingStore\";\nimport { useMeetingContext } from \"./MeetingProvider\";\n\nexport const useLiveTranscript = () => {\n const { sdk } = useMeetingContext();\n\n return useMeetingStore(sdk.state, \"transcript\", (state) =>\n state.getLiveTranscripts(),\n );\n};\n","import { useMeetingStore } from \"./useMeetingStore\";\nimport { useMeetingContext } from \"./MeetingProvider\";\n\nexport const useNetworkQuality = () => {\n const { sdk } = useMeetingContext();\n\n return useMeetingStore(\n sdk.state,\n \"networkQuality\",\n (state) => state.networkQuality,\n );\n};\n","import { useEffect } from \"react\";\nimport {\n PubSubMessage,\n PubSubTopic,\n PubSubTopicConfig,\n PubSubHandleForTopic,\n} from \"../types/meeting\";\nimport { useMeetingContext } from \"./MeetingProvider\";\n\nexport function usePubSub<T extends PubSubTopic>(\n topic: T,\n options?: {\n onMessageReceived?: (\n message: PubSubMessage<PubSubTopicConfig[T][\"message\"]>,\n ) => void;\n },\n): PubSubHandleForTopic<T> {\n const ctx = useMeetingContext();\n\n useEffect(() => {\n if (!options?.onMessageReceived) return;\n\n return ctx.onPubSubMessage<T>(\n topic,\n options.onMessageReceived,\n );\n }, [ctx, topic, options?.onMessageReceived]);\n\n return ctx.usePubSub<T>(topic);\n}\n"],"mappings":"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","names":["useEffect","useRef","useState","useState","message","useState","recording","useState","useEffect","useRef","useEffect","useEffect","useEffect","useState","useState","useEffect","useEffect","useRef","useState","useRef","useState","useEffect","useEffect","useState","useState","useEffect","useEffect","useEffect"]}
|
|
1
|
+
{"version":3,"sources":["../src/react/useLocalParticipant.tsx","../src/react/MeetingProvider.tsx","../src/config/ws.ts","../src/core/ActiveSpeakerDetector.ts","../src/core/MeetingState.ts","../src/core/SFUClient.ts","../src/core/VideoCore.ts","../src/react/useMeetingStore.ts","../src/react/useMeeting.ts","../src/react/useParticipants.ts","../src/react/useRemoteMedia.ts","../src/react/useMeetingPreview.ts","../src/react/useLiveTranscript.ts","../src/react/useNetworkQuality.ts","../src/react/usePubSub.ts"],"sourcesContent":["import { useCallback, useEffect, useRef, useState } from \"react\";\nimport { useMeetingContext } from \"./MeetingProvider\";\nimport { Participant } from \"../types/meeting\";\n\nexport const useLocalParticipant = () => {\n const { sdk } = useMeetingContext();\n\n // Guard the initial state to ensure it matches Participant | null\n const [localParticipant, setLocalParticipant] = useState<Participant | null>(\n () => {\n const current = sdk.state.localParticipant;\n return current && current.id ? (current as Participant) : null;\n },\n );\n\n useEffect(() => {\n const unsubscribe = sdk.state.subscribe(\"localParticipant\", () => {\n const current = sdk.state.localParticipant;\n\n // Safe Type-Guard: Only update if the object has a finalized id\n if (current && current.id) {\n setLocalParticipant({ ...current } as Participant);\n } else {\n setLocalParticipant(null);\n }\n });\n\n return unsubscribe;\n }, [sdk]);\n\n const lastStreamRef = useRef<MediaStream | null>(null);\n\n const videoRef = useCallback(\n (video: HTMLVideoElement | null) => {\n if (!video) return;\n\n const stream = localParticipant?.media?.stream;\n if (!stream) return;\n\n if (lastStreamRef.current === stream) return;\n lastStreamRef.current = stream;\n\n video.srcObject = stream;\n video.autoplay = true;\n video.playsInline = true;\n\n video.play().catch((err) => {\n console.warn(`Autoplay failed for local view:`, err);\n });\n },\n [localParticipant?.media?.stream],\n );\n\n return {\n participant: localParticipant,\n videoRef,\n };\n};\n","import React, {\n createContext,\n useContext,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport { VideoSDKCore } from \"../core/VideoCore\";\nimport {\n ChatInput,\n ChatMessage,\n Reaction,\n MeetingConfig,\n Participant,\n PubSubTopic,\n RecordingInfo,\n Recording,\n SFUConnectionState,\n JoinState,\n PubSubHandleForTopic,\n PubSubMessage,\n PubSubTopicConfig,\n LiveTranscript,\n NetworkQuality,\n} from \"../types/meeting\";\nimport { useMeetingStore } from \"./useMeetingStore\";\n\ntype MeetingContextValue = {\n sdk: VideoSDKCore;\n join: (\n config?: Omit<MeetingConfig, \"participantId\" | \"token\">,\n ) => Promise<void>;\n getJoinState: (roomCode: string) => Promise<JoinState>;\n leave: () => void;\n createRoom: (input: {\n name: string;\n description?: string;\n capacity?: number;\n is_private?: boolean;\n }) => Promise<any>;\n getRoom: (roomCode: string) => Promise<any>;\n deleteRoom: (roomCode: string) => Promise<any>;\n toggleMic: () => void;\n toggleCam: () => void;\n startScreenShare: () => Promise<MediaStream | null>;\n stopScreenShare: () => void;\n sendMessage: (input: ChatInput) => void;\n sendReaction: (emoji: string) => void;\n room: { id: string | null; name: string | null };\n localParticipant: Participant | null;\n participants: Map<string, Participant>;\n messages: ChatMessage[];\n presenterId: string | null;\n activeSpeakerIds: string[];\n liveTranscripts: LiveTranscript[];\n networkQuality: NetworkQuality | null;\n startLiveTranscription: () => Promise<void>;\n stopLiveTranscription: () => void;\n isLiveTranscriptionActive: () => boolean;\n recording: RecordingInfo | null;\n usePubSub: <T extends PubSubTopic>(topic: T) => PubSubHandleForTopic<T>;\n onPubSubMessage: <T extends PubSubTopic>(\n topic: T,\n cb: (message: PubSubMessage<PubSubTopicConfig[T][\"message\"]>) => void,\n ) => () => void;\n approveJoinRequest: (requestId: string) => void;\n rejectJoinRequest: (requestId: string) => void;\n cancelJoinRequest: (requestId?: string) => Promise<void> | undefined;\n muteAllAudio: () => Promise<void>;\n muteParticipant: (participantId: string) => Promise<void>;\n removeParticipant: (participantId: string) => Promise<void>;\n getModerators: (roomCode: string) => Promise<any> | undefined;\n addModerator: (roomCode: string, userId: string) => Promise<any> | undefined;\n removeModerator: (\n roomCode: string,\n userId: string,\n ) => Promise<any> | undefined;\n startRecording: () => Promise<void>;\n stopRecording: () => Promise<void>;\n getRecordingStatus: () => Promise<any>;\n onError: (cb: (err: any) => void) => () => void;\n onEntryRequested: (cb: (req: any) => void) => () => void;\n onEntryResponded: (cb: (payload: any, decision?: any) => void) => () => void;\n onJoinRequestCanceled: (cb: (requestId: string) => void) => () => void;\n onParticipantRemoved: (\n cb: (participantId: string, removedBy: string) => void,\n ) => () => void;\n onParticipantPermissionsChanged: (\n cb: (participantId: string, permissions: any) => void,\n ) => () => void;\n onMeetingLeft: (cb: () => void) => () => void;\n onTrackStateChanged: (cb: (track: any) => void) => () => void;\n onRecordingStarted: (cb: (recording: Recording) => void) => () => void;\n onRecordingStopped: (cb: (recording: any) => void) => () => void;\n onReaction: (cb: (reaction: Reaction) => void) => () => void;\n onConnectionStateChanged: (\n cb: (state: SFUConnectionState) => void,\n ) => () => void;\n onActiveSpeakersChanged: (\n cb: (participantIds: string[]) => void,\n ) => () => void;\n onNetworkQuality: (cb: (quality: NetworkQuality) => void) => () => void;\n\n onLiveTranscript: (cb: (transcript: LiveTranscript) => void) => () => void;\n};\n\nconst MeetingContext = createContext<MeetingContextValue | null>(null);\n\nexport const MeetingProvider = ({\n config,\n children,\n}: {\n config: MeetingConfig;\n children: React.ReactNode;\n}) => {\n const sdkRef = useRef<VideoSDKCore | null>(null);\n const errorListeners = useRef(new Set<(err: any) => void>());\n const entryRequestListeners = useRef(new Set<(req: any) => void>());\n const entryResponseListeners = useRef(\n new Set<(payload: any, decision?: any) => void>(),\n );\n const joinRequestCanceledListeners = useRef(\n new Set<(requestId: string) => void>(),\n );\n const participantRemovedListeners = useRef(\n new Set<(participantId: string, removedBy: string) => void>(),\n );\n const participantPermissionsChangedListeners = useRef(\n new Set<(participantId: string, permissions: any) => void>(),\n );\n const meetingLeftListeners = useRef(new Set<() => void>());\n const trackStateListeners = useRef(new Set<(track: any) => void>());\n const recordingStartedListeners = useRef(new Set<(recording: any) => void>());\n const recordingStoppedListeners = useRef(new Set<(recording: any) => void>());\n const reactionListeners = useRef(new Set<(reaction: Reaction) => void>());\n const pubSubListeners = useRef(\n new Map<PubSubTopic, Set<(message: PubSubMessage<any>) => void>>(),\n );\n const [reactionPubSubMessages, setReactionPubSubMessages] = useState<\n PubSubMessage<{ emoji: string }>[]\n >([]);\n const activeSpeakerListeners = useRef(\n new Set<(participantIds: string[]) => void>(),\n );\n const liveTranscriptListeners = useRef(\n new Set<(transcript: LiveTranscript) => void>(),\n );\n const networkQualityListeners = useRef(\n new Set<(quality: NetworkQuality) => void>(),\n );\n const connectionStateListeners = useRef(\n new Set<(state: SFUConnectionState) => void>(),\n );\n\n if (!sdkRef.current) {\n sdkRef.current = new VideoSDKCore(\n {\n participantId: config.participantId,\n token: config.token,\n },\n {\n onError: (err) => {\n errorListeners.current.forEach((fn) => fn(err));\n },\n\n onEntryRequested: (req) => {\n entryRequestListeners.current.forEach((fn) => fn(req));\n },\n\n onEntryResponded: (p, d) => {\n entryResponseListeners.current.forEach((fn) => fn(p, d));\n },\n\n onJoinRequestCanceled: (requestId) => {\n joinRequestCanceledListeners.current.forEach((fn) => fn(requestId));\n },\n\n onParticipantRemoved: (participantId, removedBy) => {\n participantRemovedListeners.current.forEach((fn) =>\n fn(participantId, removedBy),\n );\n },\n\n onParticipantPermissionsChanged: (participantId, permissions) => {\n participantPermissionsChangedListeners.current.forEach((fn) =>\n fn(participantId, permissions),\n );\n },\n\n onMeetingLeft: () => {\n meetingLeftListeners.current.forEach((fn) => fn());\n },\n\n onTrackStateChanged: (track) => {\n trackStateListeners.current.forEach((fn) => fn(track));\n },\n\n onRecordingStarted: (recording) => {\n recordingStartedListeners.current.forEach((fn) => fn(recording));\n },\n\n onRecordingStopped: (recording) => {\n recordingStoppedListeners.current.forEach((fn) => fn(recording));\n },\n\n onChatMessage: (message) => {\n const msg: ChatMessage = {\n id: message.id,\n text: message.text,\n sender_id: message.sender_id,\n sender_name: message.sender_name,\n timestamp: Number(message.timestamp),\n reply_to: message.reply_to ?? null,\n target: message.target ?? null,\n };\n\n const pubSubMessage: PubSubMessage<ChatMessage> = {\n id: msg.id,\n topic: \"SECURE_CHAT\",\n sender_id: msg.sender_id,\n sender_name: msg.sender_name,\n timestamp: msg.timestamp,\n data: msg,\n };\n\n pubSubListeners.current\n .get(\"SECURE_CHAT\")\n ?.forEach((fn) => fn(pubSubMessage));\n },\n\n onReaction: (reaction) => {\n reactionListeners.current.forEach((fn) => fn(reaction));\n\n const timestamp =\n typeof reaction.timestamp === \"number\"\n ? reaction.timestamp\n : Date.parse(reaction.timestamp);\n\n const message: PubSubMessage<{ emoji: string }> = {\n id: reaction.id,\n topic: \"REACTION\",\n sender_id: reaction.participant_id,\n sender_name: reaction.sender_name,\n timestamp,\n data: {\n emoji: reaction.emoji,\n },\n };\n\n console.log(\"[MeetingProvider] PUBSUB REACTION\", message);\n setReactionPubSubMessages((previous) =>\n [...previous, message].slice(-50),\n );\n\n pubSubListeners.current.get(\"REACTION\")?.forEach((fn) => fn(message));\n },\n onLiveTranscript: (transcript) => {\n liveTranscriptListeners.current.forEach((fn) => fn(transcript));\n },\n\n onNetworkQuality: (quality) => {\n networkQualityListeners.current.forEach((fn) => fn(quality));\n },\n\n onConnectionStateChanged: (state) => {\n connectionStateListeners.current.forEach((fn) =>\n fn(state as SFUConnectionState),\n );\n },\n },\n );\n }\n const sdk = sdkRef.current;\n const activeSpeakerIds = useMeetingStore(sdk.state, \"activeSpeakers\", (s) =>\n Array.from(s.activeSpeakerIds),\n );\n const recording = useMeetingStore(sdk.state, \"recording\", (s) => s.recording);\n const presenterId = useMeetingStore(\n sdk.state,\n \"presenter\",\n (s) => s.presenterId,\n );\n const participants = useMeetingStore(\n sdk.state,\n \"participants\",\n (s) => s.participants,\n );\n const localParticipant = useMeetingStore(\n sdk.state,\n \"localParticipant\",\n (s) => s.localParticipant,\n );\n const messages = useMeetingStore(sdk.state, \"chat\", (s) =>\n s.getChatMessages(),\n );\n const liveTranscripts = useMeetingStore(sdk.state, \"transcript\", (s) =>\n s.getLiveTranscripts(),\n );\n const networkQuality = useMeetingStore(\n sdk.state,\n \"networkQuality\",\n (s) => s.networkQuality,\n );\n\n const value = useMemo<MeetingContextValue>(() => {\n return {\n sdk,\n join: (joinConfig?: Omit<MeetingConfig, \"participantId\" | \"token\">) =>\n sdk.joinMeeting({\n ...config,\n ...joinConfig,\n }),\n getJoinState: (roomCode: string) => sdk.getJoinState(roomCode),\n leave: () => sdk.disconnect(),\n createRoom: sdk.createRoom.bind(sdk),\n getRoom: sdk.getRoom.bind(sdk),\n deleteRoom: sdk.deleteRoom.bind(sdk),\n toggleMic: sdk.toggleMic.bind(sdk),\n toggleCam: sdk.toggleCam.bind(sdk),\n startScreenShare: sdk.startScreenShare.bind(sdk),\n stopScreenShare: sdk.stopScreenShare.bind(sdk),\n sendMessage: sdk.sendChatMessage.bind(sdk),\n sendReaction: sdk.sendReaction.bind(sdk),\n room: sdk.getMeeting(),\n localParticipant,\n participants,\n messages,\n presenterId,\n activeSpeakerIds,\n liveTranscripts,\n networkQuality,\n startLiveTranscription: sdk.startLiveTranscription.bind(sdk),\n stopLiveTranscription: sdk.stopLiveTranscription.bind(sdk),\n isLiveTranscriptionActive: sdk.isLiveTranscriptionActive.bind(sdk),\n recording,\n usePubSub: <T extends PubSubTopic>(topic: T): PubSubHandleForTopic<T> => {\n if (topic === \"SECURE_CHAT\") {\n const chatMessages: PubSubMessage<ChatMessage>[] = messages.map(\n (message) => ({\n id: message.id,\n topic: \"SECURE_CHAT\",\n sender_id: message.sender_id,\n sender_name: message.sender_name,\n timestamp: message.timestamp,\n data: message,\n }),\n );\n\n return {\n messages: chatMessages,\n publish: ((data: ChatInput) => {\n sdk.publishPubSub(\"SECURE_CHAT\", data);\n }) as PubSubHandleForTopic<T>[\"publish\"],\n } as PubSubHandleForTopic<T>;\n }\n\n if (topic === \"REACTION\") {\n return {\n messages: reactionPubSubMessages,\n publish: ((data: { emoji: string }) => {\n if (!data?.emoji) {\n console.warn(\"[PubSub] REACTION requires an emoji\");\n return;\n }\n sdk.publishPubSub(\"REACTION\", data);\n }) as PubSubHandleForTopic<T>[\"publish\"],\n } as PubSubHandleForTopic<T>;\n }\n\n throw new Error(`Unsupported PubSub topic: \"${topic}\"`);\n },\n onPubSubMessage: <T extends PubSubTopic>(\n topic: T,\n cb: (message: PubSubMessage<PubSubTopicConfig[T][\"message\"]>) => void,\n ) => {\n let listeners = pubSubListeners.current.get(topic);\n\n if (!listeners) {\n listeners = new Set();\n pubSubListeners.current.set(topic, listeners);\n }\n\n listeners.add(cb as (message: PubSubMessage<any>) => void);\n\n return () => {\n listeners?.delete(cb as (message: PubSubMessage<any>) => void);\n\n if (listeners?.size === 0) {\n pubSubListeners.current.delete(topic);\n }\n };\n },\n approveJoinRequest: sdk.approveJoinRequest.bind(sdk),\n rejectJoinRequest: sdk.rejectJoinRequest.bind(sdk),\n cancelJoinRequest: sdk.cancelJoinRequest.bind(sdk),\n muteAllAudio: sdk.muteAllAudio.bind(sdk),\n muteParticipant: sdk.muteParticipant.bind(sdk),\n removeParticipant: sdk.removeParticipant.bind(sdk),\n getModerators: sdk.getModerators.bind(sdk),\n addModerator: sdk.addModerator.bind(sdk),\n removeModerator: sdk.removeModerator.bind(sdk),\n startRecording: sdk.startRecording.bind(sdk),\n stopRecording: sdk.stopRecording.bind(sdk),\n getRecordingStatus: sdk.getRecordingStatus.bind(sdk),\n\n onError: (cb: (err: any) => void) => {\n errorListeners.current.add(cb);\n\n return () => {\n errorListeners.current.delete(cb);\n };\n },\n\n onEntryRequested: (cb: (err: any) => void) => {\n entryRequestListeners.current.add(cb);\n\n return () => {\n entryRequestListeners.current.delete(cb);\n };\n },\n onEntryResponded: (cb: (err: any) => void) => {\n entryResponseListeners.current.add(cb);\n\n return () => {\n entryResponseListeners.current.delete(cb);\n };\n },\n onJoinRequestCanceled: (cb: (requestId: string) => void) => {\n joinRequestCanceledListeners.current.add(cb);\n return () => {\n joinRequestCanceledListeners.current.delete(cb);\n };\n },\n onParticipantRemoved: (\n cb: (participantId: string, removedBy: string) => void,\n ) => {\n participantRemovedListeners.current.add(cb);\n return () => {\n participantRemovedListeners.current.delete(cb);\n };\n },\n onParticipantPermissionsChanged: (\n cb: (participantId: string, permissions: any) => void,\n ) => {\n participantPermissionsChangedListeners.current.add(cb);\n return () => {\n participantPermissionsChangedListeners.current.delete(cb);\n };\n },\n onMeetingLeft: (cb: () => void) => {\n meetingLeftListeners.current.add(cb);\n return () => {\n meetingLeftListeners.current.delete(cb);\n };\n },\n onTrackStateChanged: (cb: (track: any) => void) => {\n trackStateListeners.current.add(cb);\n return () => trackStateListeners.current.delete(cb);\n },\n onRecordingStarted: (cb: (recording: any) => void) => {\n recordingStartedListeners.current.add(cb);\n return () => recordingStartedListeners.current.delete(cb);\n },\n onRecordingStopped: (cb: (recording: any) => void) => {\n recordingStoppedListeners.current.add(cb);\n return () => recordingStoppedListeners.current.delete(cb);\n },\n onReaction: (cb: (reaction: Reaction) => void) => {\n reactionListeners.current.add(cb);\n return () => reactionListeners.current.delete(cb);\n },\n onLiveTranscript: (cb: {\n (transcript: LiveTranscript): void;\n (transcript: LiveTranscript): void;\n }) => {\n liveTranscriptListeners.current.add(cb);\n return () => liveTranscriptListeners.current.delete(cb);\n },\n onNetworkQuality: (cb: {\n (quality: NetworkQuality): void;\n (quality: NetworkQuality): void;\n }) => {\n networkQualityListeners.current.add(cb);\n return () => networkQualityListeners.current.delete(cb);\n },\n onConnectionStateChanged: (cb) => {\n connectionStateListeners.current.add(cb);\n\n return () => {\n connectionStateListeners.current.delete(cb);\n };\n },\n onActiveSpeakersChanged: (cb) => {\n activeSpeakerListeners.current.add(cb);\n\n return () => {\n activeSpeakerListeners.current.delete(cb);\n };\n },\n };\n }, [\n config,\n sdk,\n localParticipant,\n participants,\n messages,\n presenterId,\n recording,\n activeSpeakerIds,\n liveTranscripts,\n networkQuality,\n reactionPubSubMessages,\n ]);\n\n return (\n <MeetingContext.Provider value={value}>{children}</MeetingContext.Provider>\n );\n};\n\nexport const useMeetingContext = () => {\n const ctx = useContext(MeetingContext);\n if (!ctx)\n throw new Error(\"useMeetingContext must be used inside <MeetingProvider>\");\n return ctx;\n};\n","/**\n * SDK Configuration for WebSocket and SFU connections\n * Updated to support the new Selective Forwarding Unit (SFU) architecture\n */\n\nexport interface SDKConfig {\n apiBase: string;\n wsBase: string;\n iceServers?: RTCIceServer[];\n connectionTimeout?: number;\n maxReconnectAttempts?: number;\n}\n\nexport const SDK_CONFIG: SDKConfig = {\n apiBase: \"https://meetingsdk.defcomm.ng/api\",\n wsBase: \"wss://meetingsdk.defcomm.ng/ws\",\n // Public STUN/TURN servers (fallback)\n iceServers: [\n { urls: [\"stun:stun.l.google.com:19302\"] },\n { urls: [\"stun:stun1.l.google.com:19302\"] },\n ],\n // Connection and reconnection settings\n connectionTimeout: 10000,\n maxReconnectAttempts: 5,\n};\n","type SpeakerState = {\n participantId: string;\n track: MediaStreamTrack;\n stream: MediaStream;\n source: MediaStreamAudioSourceNode;\n analyser: AnalyserNode;\n data: Float32Array<ArrayBuffer>;\n active: boolean;\n lastActiveAt: number;\n};\n\nexport interface ActiveSpeakerDetectorOptions {\n intervalMs?: number;\n threshold?: number;\n releaseThreshold?: number;\n releaseMs?: number;\n onActiveSpeakersChanged?: (participantIds: string[]) => void;\n}\n\nexport class ActiveSpeakerDetector {\n private audioContext: AudioContext | null = null;\n\n private speakers = new Map<string, SpeakerState>();\n\n private timer: ReturnType<typeof setInterval> | null = null;\n\n private readonly intervalMs: number;\n private readonly threshold: number;\n private readonly releaseThreshold: number;\n private readonly releaseMs: number;\n\n private onActiveSpeakersChanged: (participantIds: string[]) => void;\n\n private lastEmitted = \"\";\n\n constructor(options: ActiveSpeakerDetectorOptions = {}) {\n this.intervalMs = options.intervalMs ?? 100;\n this.threshold = options.threshold ?? 0.025;\n this.releaseThreshold = options.releaseThreshold ?? 0.015;\n this.releaseMs = options.releaseMs ?? 600;\n\n this.onActiveSpeakersChanged =\n options.onActiveSpeakersChanged ?? (() => {});\n }\n\n private ensureAudioContext(): AudioContext {\n if (!this.audioContext) {\n const AudioContextClass =\n window.AudioContext ||\n (\n window as typeof window & {\n webkitAudioContext?: typeof AudioContext;\n }\n ).webkitAudioContext;\n\n if (!AudioContextClass) {\n throw new Error(\"Web Audio API is not supported by this browser\");\n }\n\n this.audioContext = new AudioContextClass();\n }\n\n return this.audioContext;\n }\n\n async resume() {\n if (!this.audioContext) return;\n\n if (this.audioContext.state === \"suspended\") {\n try {\n await this.audioContext.resume();\n } catch {\n // Browser may require a user gesture.\n }\n }\n }\n\n addTrack(participantId: string, track: MediaStreamTrack) {\n if (!participantId) return;\n\n if (track.kind !== \"audio\") return;\n\n this.removeParticipant(participantId);\n const context = this.ensureAudioContext();\n const stream = new MediaStream([track]);\n const source = context.createMediaStreamSource(stream);\n const analyser = context.createAnalyser();\n\n analyser.fftSize = 512;\n analyser.smoothingTimeConstant = 0.65;\n analyser.minDecibels = -90;\n analyser.maxDecibels = -10;\n\n source.connect(analyser);\n\n const data = new Float32Array(analyser.fftSize);\n\n const state: SpeakerState = {\n participantId,\n track,\n stream,\n source,\n analyser,\n data,\n active: false,\n lastActiveAt: 0,\n };\n\n this.speakers.set(participantId, state);\n\n track.addEventListener(\n \"ended\",\n () => {\n this.removeParticipant(participantId);\n },\n { once: true },\n );\n\n this.start();\n\n void this.resume();\n }\n\n removeParticipant(participantId: string) {\n const state = this.speakers.get(participantId);\n\n if (!state) return;\n\n state.active = false;\n\n try {\n state.source.disconnect();\n } catch {\n // Already disconnected.\n }\n\n state.stream.getTracks().forEach((track) => {\n if (track !== state.track) {\n track.stop();\n }\n });\n\n this.speakers.delete(participantId);\n\n this.emitIfChanged();\n }\n\n removeTrack(track: MediaStreamTrack) {\n for (const [participantId, state] of this.speakers) {\n if (state.track === track) {\n this.removeParticipant(participantId);\n }\n }\n }\n\n clear() {\n for (const participantId of this.speakers.keys()) {\n this.removeParticipant(participantId);\n }\n\n this.speakers.clear();\n\n this.stop();\n\n this.emitIfChanged(true);\n }\n\n start() {\n if (this.timer) return;\n\n this.timer = setInterval(() => this.sample(), this.intervalMs);\n }\n\n stop() {\n if (!this.timer) return;\n\n clearInterval(this.timer);\n this.timer = null;\n }\n\n private sample() {\n const now = performance.now();\n\n for (const state of this.speakers.values()) {\n if (\n state.track.readyState !== \"live\" ||\n state.track.muted ||\n !state.track.enabled\n ) {\n if (state.active) {\n state.active = false;\n }\n\n continue;\n }\n\n state.analyser.getFloatTimeDomainData(state.data);\n\n let sumSquares = 0;\n\n for (let i = 0; i < state.data.length; i++) {\n const sample = state.data[i];\n sumSquares += sample * sample;\n }\n\n const rms = Math.sqrt(sumSquares / state.data.length);\n\n if (!state.active) {\n if (rms >= this.threshold) {\n state.active = true;\n state.lastActiveAt = now;\n }\n } else {\n if (rms >= this.releaseThreshold) {\n state.lastActiveAt = now;\n } else if (now - state.lastActiveAt >= this.releaseMs) {\n state.active = false;\n }\n }\n }\n\n this.emitIfChanged();\n }\n\n private getActiveSpeakerIds(): string[] {\n return Array.from(this.speakers.values())\n .filter((speaker) => speaker.active)\n .map((speaker) => speaker.participantId);\n }\n\n private emitIfChanged(force = false) {\n const ids = this.getActiveSpeakerIds().sort();\n\n const key = ids.join(\"|\");\n\n if (!force && key === this.lastEmitted) {\n return;\n }\n\n this.lastEmitted = key;\n\n this.onActiveSpeakersChanged(ids);\n }\n\n async destroy() {\n this.clear();\n\n if (this.audioContext) {\n try {\n await this.audioContext.close();\n } catch {\n // Ignore already closed context.\n }\n\n this.audioContext = null;\n }\n }\n}\n","import {\n ChatMessage,\n Listener,\n Participant,\n ParticipantMedia,\n StateScope,\n} from \"../types/meeting\";\n\ntype LocalParticipantPatch = {\n id?: string;\n name?: string;\n isHost?: boolean;\n isModerator?: boolean;\n permissions?: any;\n media?: Partial<ParticipantMedia>;\n};\n\nexport class MeetingState {\n participants = new Map<string, Participant>();\n localParticipant: Participant | null = null;\n localStream: MediaStream | null = null;\n chatMessages = new Map<string, ChatMessage>();\n presenterId: string | null = null;\n activeSpeakerIds = new Set<string>();\n recording: import(\"../types/meeting\").RecordingInfo | null = null;\n liveTranscripts: import(\"../types/meeting\").LiveTranscript[] = [];\n networkQuality: import(\"../types/meeting\").NetworkQuality | null = null;\n\n private listeners = new Map<StateScope, Set<Listener>>();\n\n // ---- reactive system ----\n\n subscribe(scope: StateScope, fn: Listener): () => void {\n if (!this.listeners.has(scope)) {\n this.listeners.set(scope, new Set());\n }\n this.listeners.get(scope)!.add(fn);\n\n return () => {\n this.listeners.get(scope)?.delete(fn);\n };\n }\n\n notify(scope: StateScope) {\n this.listeners.get(scope)?.forEach((fn) => fn());\n }\n\n setPresenterId(id: string | null) {\n if (this.presenterId === id) return;\n this.presenterId = id;\n this.notify(\"presenter\");\n this.notify(\"participants\");\n }\n\n setActiveSpeakers(ids: string[]) {\n const next = new Set(ids);\n\n if (\n next.size === this.activeSpeakerIds.size &&\n [...next].every((id) => this.activeSpeakerIds.has(id))\n ) {\n return;\n }\n\n this.activeSpeakerIds = next;\n\n this.notify(\"activeSpeakers\");\n }\n\n setRecording(recording: import(\"../types/meeting\").RecordingInfo | null) {\n this.recording = recording;\n this.notify(\"recording\");\n }\n\n clearRecording() {\n this.recording = null;\n this.notify(\"recording\");\n }\n\n addLiveTranscript(transcript: import(\"../types/meeting\").LiveTranscript) {\n this.liveTranscripts = [...this.liveTranscripts.slice(-499), transcript];\n this.notify(\"transcript\");\n }\n\n getLiveTranscripts() {\n return this.liveTranscripts;\n }\n\n clearLiveTranscripts() {\n this.liveTranscripts = [];\n this.notify(\"transcript\");\n }\n\n setNetworkQuality(quality: import(\"../types/meeting\").NetworkQuality | null) {\n this.networkQuality = quality;\n this.notify(\"networkQuality\");\n }\n\n // ---- participants ----\n\n addParticipant(p: Participant) {\n if (this.participants.has(p.id)) return false;\n // Fix: Immutable Map update\n const next = new Map(this.participants);\n next.set(p.id, p);\n this.participants = next;\n\n this.notify(\"participants\");\n return true;\n }\n\n removeParticipant(id: string) {\n // Fix: Immutable Map update\n const next = new Map(this.participants);\n next.delete(id);\n this.participants = next;\n\n this.notify(\"participants\");\n }\n\n updateParticipantMedia(\n id: string,\n patch: Partial<NonNullable<Participant[\"media\"]>>,\n ) {\n const p = this.participants.get(id);\n if (!p) return;\n\n const updated: Participant = {\n ...p,\n media: {\n stream: null,\n screenStream: undefined,\n cameraTrack: undefined,\n screenTrack: undefined,\n audioTrack: undefined,\n micEnabled: p.media?.micEnabled ?? false,\n camEnabled: p.media?.camEnabled ?? false,\n isScreenSharing: p.media?.isScreenSharing ?? false,\n ...p.media,\n ...patch,\n },\n };\n\n // Keep your clean immutable map update\n const next = new Map(this.participants);\n next.set(id, updated);\n this.participants = next;\n\n this.notify(`participant:${id}`);\n this.notify(\"participants\");\n }\n\n updateLocalParticipant(patch: LocalParticipantPatch) {\n const prev = this.localParticipant;\n\n if (!prev) {\n this.localParticipant = {\n id: patch.id ?? \"\",\n name: patch.name ?? \"\",\n isHost: patch.isHost ?? false,\n isModerator: patch.isModerator ?? false,\n permissions: patch.permissions,\n media: {\n stream: patch.media?.stream ?? null, // ◄ FIX: Capture the stream from the patch here\n screenStream: patch.media?.screenStream,\n cameraTrack: patch.media?.cameraTrack,\n screenTrack: patch.media?.screenTrack,\n audioTrack: patch.media?.audioTrack,\n micEnabled: patch.media?.micEnabled ?? true,\n camEnabled: patch.media?.camEnabled ?? true,\n isScreenSharing: patch.media?.isScreenSharing ?? false,\n },\n };\n\n this.notify(\"localParticipant\");\n return;\n }\n\n const prevMedia = prev.media ?? {\n stream: null,\n screenStream: undefined,\n cameraTrack: undefined,\n screenTrack: undefined,\n audioTrack: undefined,\n micEnabled: true,\n camEnabled: true,\n isScreenSharing: false,\n };\n\n const nextMedia: ParticipantMedia = {\n stream: patch.media?.stream ?? prevMedia.stream,\n screenStream: patch.media?.screenStream ?? prevMedia.screenStream,\n cameraTrack: patch.media?.cameraTrack ?? prevMedia.cameraTrack,\n screenTrack: patch.media?.screenTrack ?? prevMedia.screenTrack,\n audioTrack: patch.media?.audioTrack ?? prevMedia.audioTrack,\n micEnabled: patch.media?.micEnabled ?? prevMedia.micEnabled,\n camEnabled: patch.media?.camEnabled ?? prevMedia.camEnabled,\n isScreenSharing:\n patch.media?.isScreenSharing ?? prevMedia.isScreenSharing,\n };\n\n this.localParticipant = {\n ...prev,\n id: patch.id ?? prev.id,\n name: patch.name ?? prev.name,\n isHost: patch.isHost ?? prev.isHost,\n isModerator: patch.isModerator ?? prev.isModerator,\n permissions: patch.permissions ?? prev.permissions,\n media: nextMedia,\n };\n\n this.notify(\"localParticipant\");\n }\n\n // ---- chat ----\n\n addChatMessage(msg: ChatMessage) {\n this.chatMessages.set(msg.id, msg);\n this.notify(\"chat\");\n }\n\n getChatMessages() {\n return Array.from(this.chatMessages.values()).sort(\n (a, b) => a.timestamp - b.timestamp,\n );\n }\n\n clearChat() {\n this.chatMessages.clear();\n this.notify(\"chat\");\n }\n\n // ---- helpers ----\n\n getParticipants() {\n return Array.from(this.participants.values());\n }\n\n getParticipant(id: string) {\n return this.participants.get(id) ?? null;\n }\n\n resetRemoteState() {\n this.participants.clear();\n this.chatMessages.clear();\n this.presenterId = null;\n this.activeSpeakerIds = new Set();\n this.liveTranscripts = [];\n this.networkQuality = null;\n this.notify(\"participants\");\n this.notify(\"chat\");\n this.notify(\"presenter\");\n this.notify(\"activeSpeakers\");\n this.notify(\"transcript\");\n this.notify(\"networkQuality\");\n }\n}\n","import { JoinState, LiveTranscript, NetworkQuality, Reaction, SFUConnectionState } from \"../types/meeting\";\n\nexport interface TrackInfo {\n track_id: string;\n participant_id: string;\n kind: \"audio\" | \"video\";\n source?: \"camera\" | \"screen\" | \"audio\" | string;\n [key: string]: any;\n}\n\nexport interface ParticipantInfo {\n participant_id: string;\n user_metadata?: { name?: string; [key: string]: any };\n display_name?: string;\n [key: string]: any;\n}\n\nexport interface JoinPendingInfo {\n request_id: string;\n room_code?: string;\n message?: string;\n}\n\ninterface SFUClientOptions {\n apiBase?: string;\n wsBase?: string;\n participantId?: string;\n token?: string;\n onStateChange?: (state: SFUConnectionState) => void;\n onParticipantJoined?: (participant: ParticipantInfo) => void;\n onParticipantLeft?: (participant: string | ParticipantInfo) => void;\n onParticipantPresence?: (participantId: string, presence: string) => void;\n onTrackPublished?: (track: TrackInfo) => void;\n onTrackUnpublished?: (track: TrackInfo) => void;\n onRemoteTrack?: (\n track: MediaStreamTrack,\n stream: MediaStream,\n metadata: TrackInfo,\n ) => void;\n onConnected?: (payload: any, resumed: boolean) => void;\n onDisconnected?: () => void;\n onReconnecting?: (attempt: number) => void;\n onJoinPending?: (info: JoinPendingInfo) => void;\n onJoinApproved?: (requestId: string) => void;\n onJoinRejected?: (requestId: string, reason?: string) => void;\n onJoinRequested?: (request: any) => void;\n onJoinRequestCanceled?: (requestId: string) => void;\n onParticipantRemoved?: (participantId: string, removedBy: string) => void;\n onParticipantPermissionsChanged?: (\n participantId: string,\n permissions: any,\n ) => void;\n onScreenShareStarted?: (participantId: string, track?: TrackInfo) => void;\n onScreenShareStopped?: (participantId: string, trackId?: string) => void;\n onTrackStateChanged?: (track: TrackInfo) => void;\n onRecordingStarted?: (recording: {\n recording_id: string;\n started_at: string;\n }) => void;\n onRecordingStopped?: (recording: {\n recording_id: string;\n stopped_at: string;\n }) => void;\n onError?: (error: any) => void;\n onChatMessage?: (message: any) => void;\n onReaction?: (reaction: Reaction) => void;\n onRoomUpdate?: (data: any) => void;\n onLiveTranscript?: (transcript: LiveTranscript) => void;\n onNetworkQuality?: (quality: NetworkQuality) => void;\n onParticipantMediaState?: (\n participantId: string,\n audioMuted: boolean,\n videoMuted: boolean,\n ) => void;\n autoSubscribe?: boolean;\n}\n\ntype PeerName = \"publisher\" | \"subscriber\";\ntype JoinWaiter = {\n resolve: (value: any) => void;\n reject: (error: any) => void;\n};\n\nexport class SFUClient {\n private apiBase: string;\n private wsBase: string;\n private participantId: string;\n\n private ws: WebSocket | null = null;\n private publisher: RTCPeerConnection | null = null;\n private subscriber: RTCPeerConnection | null = null;\n\n private localStream: MediaStream | null = null;\n private screenStream: MediaStream | null = null;\n private videoSender: RTCRtpSender | null = null;\n private audioSender: RTCRtpSender | null = null;\n private screenSender: RTCRtpSender | null = null;\n private audioTransceiver: RTCRtpTransceiver | null = null;\n private cameraTransceiver: RTCRtpTransceiver | null = null;\n private screenTransceiver: RTCRtpTransceiver | null = null;\n\n private iceServers: RTCIceServer[] = [];\n private requestId = 0;\n private publisherRevision = 0;\n private screenShareGeneration = 0;\n private currentParticipantId: string | null = null;\n // Provider/application token used for authenticated REST calls.\n private authToken: string | null = null;\n // Room/SFU token returned by /token and used for the WebSocket.\n private token: string | null = null;\n private room: string | null = null;\n private resumeToken: string | null = null;\n private pendingJoinRequestId: string | null = null;\n private joinOptions: {\n displayName?: string;\n avatarUrl?: string;\n } = {};\n\n private state: SFUConnectionState = \"idle\";\n private intentionalClose = false;\n private leaveAcknowledged = false;\n private joiningWithResume = false;\n private desiredAudioMuted = false;\n private desiredVideoMuted = false;\n private reconnectTimer: ReturnType<typeof setTimeout> | null = null;\n private reconnectAttempt = 0;\n private maxReconnectAttempts = 8;\n private reconnectBaseMs = 750;\n private joinWaiter: JoinWaiter | null = null;\n\n private transportRecoveryInProgress = false;\n private transportRecoveryTimer: ReturnType<typeof setTimeout> | null = null;\n\n private pendingIce: Record<PeerName, RTCIceCandidateInit[]> = {\n publisher: [],\n subscriber: [],\n };\n\n private subscriberNegotiating = false;\n private offerQueue: any[] = [];\n private subscriptionQueue: string[] = [];\n private subscriptionRunning = false;\n private subscriptionWaiters: Array<{\n trackIds: string[];\n resolve: () => void;\n reject: (error: any) => void;\n }> = [];\n\n private subscribedTracks = new Set<string>();\n private trackMetadata = new Map<string, TrackInfo>();\n private participants = new Map<string, ParticipantInfo>();\n private remoteStreams = new Map<string, MediaStream>();\n private remoteScreenStreams = new Map<string, MediaStream>();\n private trackToParticipant = new Map<string, string>();\n private trackToSource = new Map<string, string>();\n private localTrackIds = new Map<\"audio\" | \"camera\" | \"screen\", string>();\n\n private subscriberStatsTimer: ReturnType<typeof setInterval> | null = null;\n private liveTranscriptionActive = false;\n private liveTranscriptionSequence = 0;\n private liveTranscriptionStartedAt = 0;\n private liveTranscriptionRecorder: MediaRecorder | null = null;\n private liveTranscriptionLoopPromise: Promise<void> | null = null;\n private networkProfile: string | null = null;\n\n private onStateChange: (state: SFUConnectionState) => void;\n private onParticipantJoined: (p: ParticipantInfo) => void;\n private onParticipantLeft: (p: string | ParticipantInfo) => void;\n private onParticipantPresence: (id: string, presence: string) => void;\n private onTrackPublished: (t: TrackInfo) => void;\n private onTrackUnpublished: (t: TrackInfo) => void;\n private onRemoteTrack: (\n t: MediaStreamTrack,\n s: MediaStream,\n m: TrackInfo,\n ) => void;\n private onConnected: (p: any, resumed: boolean) => void;\n private onDisconnected: () => void;\n private onReconnecting: (attempt: number) => void;\n private onJoinPending: (info: JoinPendingInfo) => void;\n private onJoinApproved: (requestId: string) => void;\n private onJoinRejected: (requestId: string, reason?: string) => void;\n private onJoinRequested: (request: any) => void;\n private onJoinRequestCanceled: (requestId: string) => void;\n private onParticipantRemoved: (\n participantId: string,\n removedBy: string,\n ) => void;\n private onParticipantPermissionsChanged: (\n participantId: string,\n permissions: any,\n ) => void;\n private onScreenShareStarted: (\n participantId: string,\n track?: TrackInfo,\n ) => void;\n private onScreenShareStopped: (\n participantId: string,\n trackId?: string,\n ) => void;\n private onTrackStateChanged: (track: TrackInfo) => void;\n private onRecordingStarted: (recording: {\n recording_id: string;\n started_at: string;\n }) => void;\n private onRecordingStopped: (recording: {\n recording_id: string;\n stopped_at: string;\n }) => void;\n private onError: (e: any) => void;\n private onChatMessage: (message: any) => void;\n private onReaction: (reaction: any) => void;\n private onRoomUpdate: (data: any) => void;\n private onLiveTranscript: (transcript: LiveTranscript) => void;\n private onNetworkQuality: (quality: NetworkQuality) => void;\n private onParticipantMediaState: (\n participantId: string,\n audioMuted: boolean,\n videoMuted: boolean,\n ) => void;\n private autoSubscribe: boolean;\n\n constructor(options: SFUClientOptions = {}) {\n this.apiBase = options.apiBase || \"https://api.example.com/api\";\n this.wsBase = options.wsBase || \"wss://api.example.com/ws\";\n this.participantId = options.participantId || this.createId();\n this.authToken = options.token ?? null;\n\n this.onStateChange = options.onStateChange || (() => {});\n this.onParticipantJoined = options.onParticipantJoined || (() => {});\n this.onParticipantLeft = options.onParticipantLeft || (() => {});\n this.onParticipantPresence = options.onParticipantPresence || (() => {});\n this.onTrackPublished = options.onTrackPublished || (() => {});\n this.onTrackUnpublished = options.onTrackUnpublished || (() => {});\n this.onRemoteTrack = options.onRemoteTrack || (() => {});\n this.onConnected = options.onConnected || (() => {});\n this.onDisconnected = options.onDisconnected || (() => {});\n this.onReconnecting = options.onReconnecting || (() => {});\n this.onJoinPending = options.onJoinPending || (() => {});\n this.onJoinApproved = options.onJoinApproved || (() => {});\n this.onJoinRejected = options.onJoinRejected || (() => {});\n this.onJoinRequested = options.onJoinRequested || (() => {});\n this.onJoinRequestCanceled = options.onJoinRequestCanceled || (() => {});\n this.onParticipantRemoved = options.onParticipantRemoved || (() => {});\n this.onParticipantPermissionsChanged =\n options.onParticipantPermissionsChanged || (() => {});\n this.onScreenShareStarted = options.onScreenShareStarted || (() => {});\n this.onScreenShareStopped = options.onScreenShareStopped || (() => {});\n this.onTrackStateChanged = options.onTrackStateChanged || (() => {});\n this.onRecordingStarted = options.onRecordingStarted || (() => {});\n this.onRecordingStopped = options.onRecordingStopped || (() => {});\n this.onError = options.onError || console.error;\n this.onChatMessage = options.onChatMessage || (() => {});\n this.onReaction = options.onReaction || (() => {});\n this.onRoomUpdate = options.onRoomUpdate || (() => {});\n this.onLiveTranscript = options.onLiveTranscript || (() => {});\n this.onNetworkQuality = options.onNetworkQuality || (() => {});\n this.onParticipantMediaState =\n options.onParticipantMediaState || (() => {});\n this.autoSubscribe = options.autoSubscribe !== false;\n }\n\n private heartbeatTimer: ReturnType<typeof setInterval> | null = null;\n\n private startHeartbeat() {\n this.stopHeartbeat();\n\n this.heartbeatTimer = setInterval(() => {\n if (this.ws?.readyState !== WebSocket.OPEN) return;\n\n this.send({\n type: \"ping\",\n payload: {\n nonce: crypto.randomUUID(),\n },\n });\n }, 10_000);\n }\n\n private stopHeartbeat() {\n if (this.heartbeatTimer) {\n clearInterval(this.heartbeatTimer);\n this.heartbeatTimer = null;\n }\n }\n\n private createId(): string {\n return typeof crypto !== \"undefined\" && crypto.randomUUID\n ? crypto.randomUUID()\n : `id_${Math.random().toString(36).slice(2)}_${Date.now()}`;\n }\n\n private resumeStorageKey(roomCode: string) {\n return `defcomm:sfu:resume:${roomCode}`;\n }\n\n private loadResumeToken(roomCode: string): string | null {\n try {\n return localStorage.getItem(this.resumeStorageKey(roomCode));\n } catch {\n return null;\n }\n }\n\n private saveResumeToken(roomCode: string, token: string) {\n try {\n localStorage.setItem(this.resumeStorageKey(roomCode), token);\n } catch {\n // Storage can be unavailable in private/SSR environments.\n }\n }\n\n private clearResumeToken(roomCode: string | null) {\n if (!roomCode) return;\n try {\n localStorage.removeItem(this.resumeStorageKey(roomCode));\n } catch {\n // ignore\n }\n }\n\n private setState(next: SFUConnectionState) {\n if (this.state === next) return;\n this.state = next;\n this.onStateChange(next);\n }\n\n getConnectionState(): SFUConnectionState {\n return this.state;\n }\n\n getParticipantId(): string | null {\n return this.currentParticipantId;\n }\n\n getResumeToken(): string | null {\n return this.resumeToken;\n }\n\n getLocalStream(): MediaStream | null {\n return this.localStream;\n }\n\n getScreenStream(): MediaStream | null {\n return this.screenStream;\n }\n\n getRemoteScreenStream(participantId: string): MediaStream | null {\n return this.remoteScreenStreams.get(participantId) || null;\n }\n\n setLocalStream(stream: MediaStream | null) {\n this.localStream = stream;\n }\n\n private nextRequestId(): string {\n return (++this.requestId).toString();\n }\n\n private async request(url: string, options: RequestInit = {}) {\n const headers = new Headers(options.headers);\n\n headers.set(\"Content-Type\", \"application/json\");\n\n // The token supplied through MeetingProvider is available before join\n // and authenticates REST requests such as join-state and /token.\n if (this.authToken) {\n headers.set(\"Authorization\", `Bearer ${this.authToken}`);\n }\n\n const res = await fetch(url, {\n ...options,\n headers,\n });\n\n if (!res.ok) {\n let body: any = {};\n try {\n body = await res.json();\n } catch {\n // ignore non-json error bodies\n }\n\n throw new Error(\n body.message || `Request failed: ${res.status} ${res.statusText}`,\n );\n }\n\n return res.json();\n }\n\n async createRoom(input: {\n name: string;\n description?: string;\n capacity?: number;\n is_private?: boolean;\n }) {\n return this.request(`${this.apiBase}/rooms`, {\n method: \"POST\",\n body: JSON.stringify({\n name: input.name,\n description: input.description ?? \"\",\n capacity: input.capacity ?? 20,\n is_private: input.is_private ?? false,\n }),\n });\n }\n\n async getRoom(roomCode: string) {\n return this.request(\n `${this.apiBase}/rooms/${encodeURIComponent(roomCode)}`,\n );\n }\n\n async getJoinState(roomCode: string): Promise<JoinState> {\n return this.request(\n `${this.apiBase}/rooms/${encodeURIComponent(roomCode)}/join-state`,\n );\n }\n\n async deleteRoom(roomCode: string) {\n return this.request(\n `${this.apiBase}/rooms/${encodeURIComponent(roomCode)}`,\n {\n method: \"DELETE\",\n },\n );\n }\n\n async getToken(\n roomCode: string,\n options: {\n displayName?: string;\n avatarUrl?: string;\n participantId?: string;\n audioMuted?: boolean;\n videoMuted?: boolean;\n } = {},\n ) {\n const nextRoom = roomCode.trim();\n if (this.room && this.room !== nextRoom) {\n this.resumeToken = null;\n }\n\n this.room = nextRoom;\n this.joinOptions = {\n displayName: options.displayName,\n avatarUrl: options.avatarUrl,\n };\n if (options.participantId) this.participantId = options.participantId;\n if (typeof options.audioMuted === \"boolean\")\n this.desiredAudioMuted = options.audioMuted;\n if (typeof options.videoMuted === \"boolean\")\n this.desiredVideoMuted = options.videoMuted;\n if (!this.resumeToken) {\n this.resumeToken = this.loadResumeToken(this.room);\n }\n\n const data = await this.request(`${this.apiBase}/token`, {\n method: \"POST\",\n body: JSON.stringify({\n room_code: this.room,\n user_id: this.participantId,\n display_name: options.displayName,\n avatar_url: options.avatarUrl,\n }),\n });\n\n this.token = data?.token;\n if (!this.token) throw new Error(\"Token endpoint returned no token\");\n\n return this.connect(this.token, this.joinOptions);\n }\n\n private async refreshAccessToken() {\n if (!this.room) throw new Error(\"Cannot refresh token without a room\");\n\n const data = await this.request(`${this.apiBase}/token`, {\n method: \"POST\",\n body: JSON.stringify({\n room_code: this.room,\n user_id: this.participantId,\n display_name: this.joinOptions.displayName,\n avatar_url: this.joinOptions.avatarUrl,\n }),\n });\n\n if (!data?.token) throw new Error(\"Token refresh returned no token\");\n this.token = data.token;\n return this.token;\n }\n\n private connect(token: string, options: any = {}) {\n this.token = token;\n this.intentionalClose = false;\n this.setState(this.reconnectAttempt > 0 ? \"reconnecting\" : \"connecting\");\n\n return new Promise<void>((resolve, reject) => {\n this.joinWaiter = { resolve, reject };\n this.openWebSocket(options);\n });\n }\n\n private openWebSocket(options: any = {}) {\n if (!this.token || !this.room) {\n const error = new Error(\"Cannot connect without token and room\");\n this.failJoin(error);\n return;\n }\n\n if (this.ws) {\n try {\n this.ws.onclose = null;\n this.ws.close();\n } catch {\n // ignore\n }\n }\n\n const ws = new WebSocket(\n `${this.wsBase}?access_token=${encodeURIComponent(this.token)}`,\n );\n this.ws = ws;\n\n ws.onopen = () => {\n this.startHeartbeat();\n this.setState(\"joining\");\n this.joiningWithResume = Boolean(this.resumeToken);\n\n const joinPayload: any = {\n token: this.token,\n room_code: this.room,\n resume_token: this.resumeToken,\n display_name: options.displayName,\n avatar_url: options.avatarUrl,\n audio_muted: this.desiredAudioMuted,\n video_muted: this.desiredVideoMuted,\n };\n\n // After approval the Rust server requires the original pending request id.\n if (this.pendingJoinRequestId) {\n this.send({\n type: \"join\",\n request_id: this.pendingJoinRequestId,\n payload: joinPayload,\n });\n } else {\n this.send({ type: \"join\", payload: joinPayload });\n }\n };\n\n ws.onerror = (event) => {\n this.onError(event);\n };\n\n ws.onclose = () => {\n this.stopHeartbeat();\n if (this.ws !== ws) return;\n this.ws = null;\n\n if (this.intentionalClose || this.state === \"leaving\") {\n this.setState(\"disconnected\");\n this.onDisconnected();\n return;\n }\n\n // Keep MediaStreams and logical participant state alive.\n this.setState(\"reconnecting\");\n this.onDisconnected();\n this.scheduleReconnect();\n };\n\n ws.onmessage = async (event) => {\n if (this.ws !== ws) return;\n try {\n const message = JSON.parse(event.data);\n await this.handleServerMessage(message);\n } catch (error) {\n this.onError(error);\n }\n };\n }\n\n private scheduleReconnect() {\n if (this.reconnectTimer || this.intentionalClose) return;\n if (this.reconnectAttempt >= this.maxReconnectAttempts) {\n this.setState(\"disconnected\");\n this.failJoin(new Error(\"SFU reconnect attempts exhausted\"));\n return;\n }\n\n this.reconnectAttempt += 1;\n const delay = Math.min(\n 15000,\n this.reconnectBaseMs * Math.pow(2, this.reconnectAttempt - 1),\n );\n\n this.onReconnecting(this.reconnectAttempt);\n\n this.reconnectTimer = setTimeout(async () => {\n this.reconnectTimer = null;\n try {\n await this.refreshAccessToken();\n this.openWebSocket(this.joinOptions);\n } catch (error) {\n this.onError(error);\n this.scheduleReconnect();\n }\n }, delay);\n }\n\n private failJoin(error: any) {\n if (this.joinWaiter) {\n const waiter = this.joinWaiter;\n this.joinWaiter = null;\n waiter.reject(error);\n }\n }\n\n private resolveJoin(value: any) {\n if (!this.joinWaiter) return;\n const waiter = this.joinWaiter;\n this.joinWaiter = null;\n waiter.resolve(value);\n }\n\n private async handleServerMessage(message: any) {\n const type = message?.type;\n const payload = message?.payload || {};\n\n switch (type) {\n case \"joined\": {\n await this.handleJoined(payload);\n break;\n }\n\n case \"left\": {\n this.leaveAcknowledged = true;\n break;\n }\n\n case \"join_pending\": {\n const requestId = payload.request_id || message.request_id;\n if (!requestId) throw new Error(\"join_pending has no request_id\");\n\n this.pendingJoinRequestId = requestId;\n this.setState(\"waiting_approval\");\n this.onJoinPending({\n request_id: requestId,\n room_code: payload.room_code || this.room || undefined,\n message: payload.message,\n });\n break;\n }\n\n case \"join_approved\": {\n const requestId = payload.request_id || message.request_id;\n if (!requestId) break;\n this.pendingJoinRequestId = requestId;\n this.onJoinApproved(requestId);\n\n // Approval is a direct signal to the waiting session. Continue the join\n // with the same request id; the Rust Room layer performs the admission.\n if (this.ws?.readyState === WebSocket.OPEN) {\n this.setState(\"joining\");\n this.send({\n type: \"join\",\n request_id: requestId,\n payload: {\n token: this.token,\n room_code: this.room,\n resume_token: this.resumeToken,\n display_name: this.joinOptions.displayName,\n avatar_url: this.joinOptions.avatarUrl,\n // Preserve the media state requested before host approval.\n // The approval continuation is a second JOIN, so these values\n // must be sent again instead of falling back to the SFU defaults.\n audio_muted: this.desiredAudioMuted,\n video_muted: this.desiredVideoMuted,\n },\n });\n }\n break;\n }\n\n case \"join_rejected\": {\n const requestId = payload.request_id || message.request_id;\n const reason = payload.reason;\n this.onJoinRejected(requestId, reason);\n this.pendingJoinRequestId = null;\n this.intentionalClose = true;\n this.failJoin(new Error(reason || \"Join request rejected\"));\n break;\n }\n\n case \"join_requested\":\n case \"join_request\": {\n this.onJoinRequested(payload.request || payload);\n break;\n }\n\n case \"join_request_canceled\": {\n this.onJoinRequestCanceled(payload.request_id || message.request_id);\n break;\n }\n\n case \"participant_removed\": {\n const participantId = payload.participant_id;\n if (!participantId) break;\n const removedBy = payload.removed_by || \"\";\n this.participants.delete(participantId);\n this.removeRemoteParticipant(participantId);\n if (participantId === this.currentParticipantId) {\n this.intentionalClose = true;\n this.pendingJoinRequestId = null;\n this.setState(\"disconnected\");\n try {\n this.ws?.close();\n } catch {}\n }\n this.onParticipantRemoved(participantId, removedBy);\n break;\n }\n\n case \"participant_permissions_changed\": {\n const participantId = payload.participant_id;\n if (!participantId) break;\n const participant = this.participants.get(participantId);\n if (participant) {\n this.participants.set(participantId, {\n ...participant,\n permissions: payload.permissions,\n });\n }\n this.onParticipantPermissionsChanged(\n participantId,\n payload.permissions,\n );\n break;\n }\n\n case \"publish_answer\": {\n if (!this.publisher) break;\n await this.publisher.setRemoteDescription({\n type: \"answer\",\n sdp: payload.sdp,\n });\n await this.flushPendingIce(\"publisher\");\n break;\n }\n\n case \"subscribe_offer\": {\n this.offerQueue.push(payload);\n if (!this.subscriberNegotiating) await this.processOfferQueue();\n break;\n }\n\n case \"ice_candidate\":\n case \"publisher_ice_candidate\":\n case \"subscriber_ice_candidate\": {\n const candidatePayload = {\n ...payload,\n peer:\n payload.peer ||\n (type === \"publisher_ice_candidate\" ? \"publisher\" : \"subscriber\"),\n };\n await this.handleIce(candidatePayload);\n break;\n }\n\n case \"participant_joined\": {\n const participant = payload.participant || payload;\n const participantId =\n participant?.participant_id || payload.participant_id;\n if (!participantId || participantId === this.currentParticipantId)\n break;\n\n if (participant) this.participants.set(participantId, participant);\n this.onParticipantJoined(participant);\n break;\n }\n\n case \"participant_left\": {\n const participantId = payload.participant_id;\n if (!participantId) break;\n this.participants.delete(participantId);\n this.removeRemoteParticipant(participantId);\n this.onParticipantLeft(participantId);\n break;\n }\n\n case \"participant_media_state\": {\n const participantId = payload.participant_id;\n if (!participantId) break;\n this.onParticipantMediaState(\n participantId,\n Boolean(payload.audio_muted),\n Boolean(payload.video_muted),\n );\n break;\n }\n\n case \"participant_presence\":\n case \"participant_presence_changed\": {\n const participantId = payload.participant_id;\n const presence = payload.presence;\n if (participantId && presence) {\n this.onParticipantPresence(participantId, String(presence));\n }\n break;\n }\n\n case \"track_published\": {\n const track: TrackInfo = payload.track || payload;\n if (!track?.track_id) break;\n this.rememberTrack(track);\n\n if (track.participant_id === this.currentParticipantId) {\n if (track.source === \"audio\") {\n this.localTrackIds.set(\"audio\", track.track_id);\n const muted = !(\n this.localStream?.getAudioTracks()[0]?.enabled ?? true\n );\n this.send({\n type: \"track_state\",\n payload: { track_id: track.track_id, muted },\n });\n }\n if (track.source === \"camera\") {\n this.localTrackIds.set(\"camera\", track.track_id);\n const muted = !(\n this.localStream?.getVideoTracks()[0]?.enabled ?? true\n );\n this.send({\n type: \"track_state\",\n payload: { track_id: track.track_id, muted },\n });\n }\n if (track.source === \"screen\")\n this.localTrackIds.set(\"screen\", track.track_id);\n break;\n }\n\n this.onTrackPublished(track);\n if (this.autoSubscribe) await this.subscribe(track.track_id);\n break;\n }\n\n case \"track_unpublished\": {\n const trackId = payload.track_id || payload.track?.track_id;\n if (!trackId) break;\n const track =\n this.trackMetadata.get(trackId) ||\n ({\n track_id: trackId,\n participant_id: this.trackToParticipant.get(trackId) || \"\",\n source: this.trackToSource.get(trackId),\n kind: \"video\",\n } as TrackInfo);\n\n this.trackMetadata.delete(trackId);\n this.subscribedTracks.delete(trackId);\n this.trackToParticipant.delete(trackId);\n this.trackToSource.delete(trackId);\n\n for (const [source, localId] of this.localTrackIds) {\n if (localId === trackId) this.localTrackIds.delete(source);\n }\n\n if (track.participant_id === this.currentParticipantId) break;\n this.onTrackUnpublished(track);\n break;\n }\n\n case \"track_state_changed\": {\n const trackId = payload.track_id || payload.track?.track_id;\n if (!trackId) break;\n\n const existing = this.trackMetadata.get(trackId);\n const track: TrackInfo = {\n ...(existing || {}),\n ...(payload.track || {}),\n track_id: trackId,\n participant_id:\n payload.participant_id ||\n existing?.participant_id ||\n payload.track?.participant_id,\n kind:\n payload.kind || payload.track?.kind || existing?.kind || \"video\",\n source: payload.source || payload.track?.source || existing?.source,\n muted: Boolean(payload.muted),\n };\n\n if (!track.participant_id) break;\n this.rememberTrack(track);\n this.onTrackStateChanged(track);\n break;\n }\n\n case \"subscription_updated\": {\n // Authoritative acknowledgement of the current subscriber set.\n break;\n }\n\n case \"recording_started\": {\n this.onRecordingStarted({\n recording_id: payload.recording_id,\n started_at: payload.started_at,\n });\n break;\n }\n\n case \"recording_stopped\": {\n this.onRecordingStopped({\n recording_id: payload.recording_id,\n stopped_at: payload.stopped_at,\n });\n break;\n }\n\n case \"reconnecting\": {\n this.setState(\"reconnecting\");\n break;\n }\n\n case \"screen_share_started\": {\n const participantId = payload.participant_id;\n const track = payload.track as TrackInfo | undefined;\n if (track) this.rememberTrack(track);\n if (participantId) this.onScreenShareStarted(participantId, track);\n break;\n }\n\n case \"screen_share_stopped\": {\n const participantId = payload.participant_id;\n const trackId = payload.track_id;\n\n // Keep the underlying remote screen track alive across a logical\n // stop/start. The SFU and publisher reuse the same RTP track.\n this.onScreenShareStopped(participantId, trackId);\n break;\n }\n\n case \"room_state\": {\n const participants = payload.participants || [];\n this.onRoomStateReconciled(payload);\n this.onRoomUpdate(payload);\n for (const participant of participants) {\n const pid = participant?.participant_id;\n if (!pid) continue;\n if (pid !== this.currentParticipantId) {\n this.participants.set(pid, participant);\n this.onParticipantPresence(\n pid,\n String(participant.presence || \"connected\"),\n );\n this.onParticipantMediaState(\n pid,\n Boolean(participant.audio_muted),\n Boolean(participant.video_muted),\n );\n }\n }\n for (const [pid] of this.participants) {\n if (!participants.some((p: any) => p?.participant_id === pid)) {\n this.participants.delete(pid);\n this.removeRemoteParticipant(pid);\n this.onParticipantLeft(pid);\n }\n }\n for (const track of payload.tracks || []) this.rememberTrack(track);\n if (Array.isArray(payload.chat_history)) {\n for (const message of payload.chat_history)\n this.onChatMessage(message);\n }\n break;\n }\n\n case \"chat_message\": {\n const msg = payload.message || payload;\n if (msg?.id) this.onChatMessage(msg);\n break;\n }\n\n case \"reaction\": {\n const reaction = payload.reaction || payload;\n console.log(\"[SFUClient] RECEIVED REACTION\", reaction);\n if (reaction?.id && reaction?.emoji) this.onReaction(reaction);\n break;\n }\n\n case \"live_transcript\": {\n const transcript: LiveTranscript = {\n transcript_id: String(payload.transcript_id),\n participant_id: String(payload.participant_id),\n speaker_name: payload.speaker_name ?? null,\n sequence: Number(payload.sequence ?? 0),\n text: String(payload.text ?? \"\"),\n offset_ms: payload.offset_ms == null ? null : Number(payload.offset_ms),\n start_ms: payload.start_ms == null ? null : Number(payload.start_ms),\n end_ms: payload.end_ms == null ? null : Number(payload.end_ms),\n timestamp: String(payload.timestamp ?? new Date().toISOString()),\n };\n if (transcript.text.trim()) this.onLiveTranscript(transcript);\n break;\n }\n\n case \"network_quality\": {\n const raw = payload.quality || payload;\n const quality: NetworkQuality = {\n participant_id: String(raw.participant_id ?? this.currentParticipantId ?? this.participantId),\n quality: String(raw.quality ?? \"unknown\"),\n score: Number(raw.score ?? 0),\n recommended_action: String(raw.recommended_action ?? \"maintain\"),\n packet_loss_percent: Number(raw.packet_loss_percent ?? 0),\n upload_kbps: Number(raw.upload_kbps ?? 0),\n forwarded_drop_percent: Number(raw.forwarded_drop_percent ?? 0),\n queued_packets: Number(raw.queued_packets ?? 0),\n packets_received: Number(raw.packets_received ?? 0),\n packets_lost: Number(raw.packets_lost ?? 0),\n observed_at: String(raw.observed_at ?? new Date().toISOString()),\n };\n this.onNetworkQuality(quality);\n void this.applyNetworkRecommendation(quality.recommended_action);\n break;\n }\n\n case \"error\": {\n const message = payload.message || \"SFU signaling error\";\n if (\n this.state === \"reconnecting\" &&\n message.includes(\"participant session is stale\")\n ) {\n console.debug(\n \"[SFU] Ignoring stale-session error during recovery\",\n message,\n );\n return;\n }\n const error = new Error(message);\n if (this.state === \"joining\" || this.state === \"waiting_approval\") {\n this.onError(error);\n this.failJoin(error);\n return;\n }\n this.onError(error);\n break;\n }\n\n default:\n console.debug(\"[SFU] Ignoring unknown server message\", message);\n }\n }\n\n private onRoomStateReconciled(payload: any) {\n const participants = payload.participants || [];\n const local = participants.find(\n (p: any) => p?.participant_id === this.currentParticipantId,\n );\n if (local) {\n this.desiredAudioMuted = Boolean(local.audio_muted);\n this.desiredVideoMuted = Boolean(local.video_muted);\n }\n }\n\n private rememberTrack(track: TrackInfo) {\n if (!track?.track_id || !track?.participant_id) return;\n\n const normalizedSource = track.source\n ? String(track.source).trim().toLowerCase()\n : undefined;\n\n const normalized: TrackInfo = {\n ...track,\n source: normalizedSource,\n };\n\n this.trackMetadata.set(normalized.track_id, normalized);\n this.trackToParticipant.set(normalized.track_id, normalized.participant_id);\n\n if (normalizedSource) {\n this.trackToSource.set(normalized.track_id, normalizedSource);\n } else {\n this.trackToSource.delete(normalized.track_id);\n }\n }\n\n private async handleJoined(payload: any) {\n const resumed = this.joiningWithResume;\n this.joiningWithResume = false;\n\n this.iceServers = payload.ice_servers || this.iceServers || [];\n this.currentParticipantId = payload.participant_id;\n this.resumeToken =\n payload.resume_token || payload.resumeToken || this.resumeToken;\n if (this.room && this.resumeToken) {\n this.saveResumeToken(this.room, this.resumeToken);\n }\n this.pendingJoinRequestId = null;\n this.reconnectAttempt = 0;\n\n this.participants.clear();\n this.trackMetadata.clear();\n this.trackToParticipant.clear();\n this.trackToSource.clear();\n this.localTrackIds.clear();\n\n for (const participant of payload.participants || []) {\n if (participant?.participant_id) {\n this.participants.set(participant.participant_id, participant);\n }\n }\n\n for (const track of payload.tracks || []) {\n if (track?.track_id) this.rememberTrack(track);\n }\n\n await this.initializePeerConnections();\n this.setState(\"connected\");\n this.onConnected(payload, resumed);\n if (payload.recording?.status === \"recording\") {\n console.log(\"[SFU] Recording already active when joining\", {\n recording_id: payload.recording.recording_id,\n started_at: payload.recording.started_at,\n status: payload.recording.status,\n });\n\n this.onRecordingStarted({\n recording_id: payload.recording.recording_id,\n started_at: payload.recording.started_at,\n });\n }\n\n for (const participant of this.participants.values()) {\n if (participant.participant_id !== this.currentParticipantId) {\n this.onParticipantJoined(participant);\n this.onParticipantPresence(\n participant.participant_id,\n String(participant.presence || \"connected\"),\n );\n this.onParticipantMediaState(\n participant.participant_id,\n Boolean(participant.audio_muted),\n Boolean(participant.video_muted),\n );\n }\n }\n\n if (Array.isArray(payload.chat_history)) {\n for (const message of payload.chat_history) this.onChatMessage(message);\n }\n this.onRoomUpdate(payload);\n\n if (this.localStream) {\n await this.publishExistingTracks();\n }\n\n if (this.autoSubscribe) {\n const trackIds = [...this.trackMetadata.values()]\n .filter((track) => track.participant_id !== this.currentParticipantId)\n .map((track) => track.track_id);\n if (trackIds.length) await this.subscribeMultiple(trackIds);\n }\n\n this.resolveJoin(payload);\n }\n\n private async initializePeerConnections() {\n this.closePeerConnectionsOnly();\n this.publisherRevision = 0;\n\n const config: RTCConfiguration = { iceServers: this.iceServers };\n this.publisher = new RTCPeerConnection(config);\n this.subscriber = new RTCPeerConnection(config);\n\n // Keep audio, camera, and screen on three permanent publisher m-lines.\n // This mirrors the working client: screen sharing must never reuse the\n // camera sender/transceiver.\n this.audioTransceiver = this.publisher.addTransceiver(\"audio\", {\n direction: \"sendonly\",\n });\n this.cameraTransceiver = this.publisher.addTransceiver(\"video\", {\n direction: \"sendonly\",\n });\n this.screenTransceiver = this.publisher.addTransceiver(\"video\", {\n direction: \"inactive\",\n });\n\n this.audioSender = this.audioTransceiver.sender;\n this.videoSender = this.cameraTransceiver.sender;\n this.screenSender = this.screenTransceiver.sender;\n\n this.publisher.onicecandidate = (event) => {\n if (event.candidate) this.sendCandidate(\"publisher\", event.candidate);\n };\n\n this.subscriber.onicecandidate = (event) => {\n if (event.candidate) this.sendCandidate(\"subscriber\", event.candidate);\n };\n\n this.publisher.onconnectionstatechange = () => {\n const publisher = this.publisher;\n if (!publisher) return;\n\n const state = publisher.connectionState;\n\n console.debug(\"[SFU] Publisher connection state\", {\n connectionState: publisher.connectionState,\n iceConnectionState: publisher.iceConnectionState,\n iceGatheringState: publisher.iceGatheringState,\n signalingState: publisher.signalingState,\n });\n\n if (state === \"failed\") {\n this.recoverWebRTC(\"publisher_failed\");\n }\n };\n\n this.subscriber.onconnectionstatechange = () => {\n const subscriber = this.subscriber;\n if (!subscriber) return;\n\n const state = subscriber.connectionState;\n\n console.debug(\"[SFU] Subscriber connection state\", {\n connectionState: subscriber.connectionState,\n iceConnectionState: subscriber.iceConnectionState,\n iceGatheringState: subscriber.iceGatheringState,\n signalingState: subscriber.signalingState,\n });\n\n if (state === \"failed\") {\n this.recoverWebRTC(\"subscriber_failed\");\n }\n };\n this.publisher.oniceconnectionstatechange = () => {\n const publisher = this.publisher;\n if (!publisher) return;\n\n console.debug(\"[SFU] Publisher ICE state\", {\n iceConnectionState: publisher.iceConnectionState,\n connectionState: publisher.connectionState,\n });\n };\n\n this.subscriber.oniceconnectionstatechange = () => {\n const subscriber = this.subscriber;\n if (!subscriber) return;\n\n console.debug(\"[SFU] Subscriber ICE state\", {\n iceConnectionState: subscriber.iceConnectionState,\n connectionState: subscriber.connectionState,\n });\n };\n\n this.subscriber.ontrack = (event) => {\n void this.handleRemoteTrack(event);\n };\n\n if (!this.subscriberStatsTimer) {\n this.subscriberStatsTimer = setInterval(() => {\n void this.logSubscriberVideoStats();\n }, 3000);\n }\n }\n\n private async handleRemoteTrack(event: RTCTrackEvent) {\n const stream = event.streams?.[0] || null;\n const metadata = this.resolveRemoteTrackMetadata(event.track, stream);\n\n if (!metadata?.participant_id) {\n this.onError(\n new Error(\n `Remote ${event.track.kind} track ${event.track.id} has no SFU participant mapping`,\n ),\n );\n return;\n }\n\n const participantId = metadata.participant_id;\n const source = String(\n metadata.source || this.trackToSource.get(metadata.track_id) || \"\",\n )\n .trim()\n .toLowerCase();\n\n console.debug(\"[SFU] Remote track source resolved\", {\n participantId,\n browserTrackId: event.track.id,\n serverTrackId: metadata.track_id,\n kind: event.track.kind,\n source,\n });\n\n // Screen is a completely separate media path. Never put it in the\n // participant's normal camera/audio MediaStream.\n if (source === \"screen\" || source === \"screen_share\") {\n let screenStream = this.remoteScreenStreams.get(participantId);\n\n if (!screenStream) {\n screenStream = new MediaStream();\n this.remoteScreenStreams.set(participantId, screenStream);\n }\n\n for (const existing of screenStream.getVideoTracks()) {\n if (existing.id !== event.track.id) {\n screenStream.removeTrack(existing);\n existing.stop();\n }\n }\n\n if (\n !screenStream.getTracks().some((track) => track.id === event.track.id)\n ) {\n screenStream.addTrack(event.track);\n }\n\n event.track.onended = () => {\n try {\n screenStream?.removeTrack(event.track);\n } catch {}\n\n if (screenStream?.getTracks().length === 0) {\n this.remoteScreenStreams.delete(participantId);\n this.onScreenShareStopped(participantId, metadata.track_id);\n }\n };\n\n this.onScreenShareStarted(participantId, metadata);\n this.onRemoteTrack(event.track, screenStream, {\n ...metadata,\n source: \"screen\",\n });\n return;\n }\n\n // Only audio and camera video belong to the normal participant stream.\n if (event.track.kind === \"video\" && source !== \"camera\") {\n this.onError(\n new Error(\n `Refusing to route unknown remote video source to camera: ${metadata.track_id}`,\n ),\n );\n return;\n }\n\n let remoteStream = this.remoteStreams.get(participantId);\n if (!remoteStream) {\n remoteStream = new MediaStream();\n this.remoteStreams.set(participantId, remoteStream);\n }\n\n for (const existing of remoteStream.getTracks()) {\n if (\n existing.kind === event.track.kind &&\n existing.id !== event.track.id\n ) {\n remoteStream.removeTrack(existing);\n existing.stop();\n }\n }\n\n if (\n !remoteStream.getTracks().some((track) => track.id === event.track.id)\n ) {\n remoteStream.addTrack(event.track);\n }\n\n event.track.onended = () => {\n try {\n remoteStream?.removeTrack(event.track);\n } catch {}\n };\n\n this.onRemoteTrack(event.track, remoteStream, {\n ...metadata,\n source: event.track.kind === \"audio\" ? \"audio\" : \"camera\",\n });\n }\n\n private normalizeRemoteTrackId(browserTrackId: string): string {\n return browserTrackId?.startsWith(\"track-\")\n ? browserTrackId.slice(\"track-\".length)\n : browserTrackId;\n }\n\n private resolveRemoteTrackMetadata(\n track: MediaStreamTrack,\n stream: MediaStream | null,\n ): TrackInfo | null {\n const candidates = [\n this.normalizeRemoteTrackId(track.id),\n track.id,\n stream?.id ? this.normalizeRemoteTrackId(stream.id) : null,\n stream?.id || null,\n ].filter(Boolean) as string[];\n\n for (const id of candidates) {\n const metadata = this.trackMetadata.get(id);\n if (metadata) return metadata;\n }\n\n // Never guess by participant + kind. A participant can publish camera\n // and screen simultaneously; guessing is exactly how a screen track can\n // end up in the camera tile.\n return null;\n }\n\n private sendCandidate(peer: PeerName, candidate: RTCIceCandidate) {\n this.send({\n type: \"ice_candidate\",\n payload: {\n peer,\n candidate: candidate.candidate,\n sdp_mid: candidate.sdpMid,\n sdp_mline_index: candidate.sdpMLineIndex,\n username_fragment: candidate.usernameFragment,\n },\n });\n }\n\n private async handleIce(payload: any) {\n const peer: PeerName =\n payload.peer === \"publisher\" ? \"publisher\" : \"subscriber\";\n const pc = peer === \"publisher\" ? this.publisher : this.subscriber;\n\n const candidate: RTCIceCandidateInit = {\n candidate: payload.candidate,\n sdpMid: payload.sdp_mid ?? payload.sdpMid ?? null,\n sdpMLineIndex: payload.sdp_mline_index ?? payload.sdpMLineIndex ?? null,\n usernameFragment:\n payload.username_fragment ?? payload.usernameFragment ?? null,\n };\n\n if (!pc || !pc.remoteDescription) {\n this.pendingIce[peer].push(candidate);\n return;\n }\n\n try {\n await pc.addIceCandidate(candidate);\n } catch (error) {\n this.onError(\n new Error(`Failed to add ${peer} ICE candidate: ${String(error)}`),\n );\n }\n }\n\n private async flushPendingIce(peer: PeerName) {\n const pc = peer === \"publisher\" ? this.publisher : this.subscriber;\n if (!pc || !pc.remoteDescription) return;\n\n const queue = this.pendingIce[peer];\n while (queue.length) {\n const candidate = queue.shift()!;\n try {\n await pc.addIceCandidate(candidate);\n } catch (error) {\n this.onError(\n new Error(\n `Failed to add queued ${peer} ICE candidate: ${String(error)}`,\n ),\n );\n }\n }\n }\n\n private async processOfferQueue() {\n if (!this.subscriber) return;\n\n while (this.offerQueue.length) {\n if (this.subscriberNegotiating) return;\n this.subscriberNegotiating = true;\n const offer = this.offerQueue.shift();\n\n try {\n await this.subscriber.setRemoteDescription({\n type: \"offer\",\n sdp: offer.sdp,\n });\n await this.flushPendingIce(\"subscriber\");\n\n const answer = await this.subscriber.createAnswer();\n await this.subscriber.setLocalDescription(answer);\n\n this.send({\n type: \"subscribe_answer\",\n payload: {\n revision: offer.revision,\n sdp: answer.sdp,\n },\n });\n\n // One subscribe request produces one subscriber offer. Resolve only\n // the waiter belonging to this offer; resolving the entire queue can\n // make later subscribe calls look complete before they were negotiated.\n const waiter = this.subscriptionWaiters.shift();\n waiter?.resolve();\n } catch (error) {\n const waiter = this.subscriptionWaiters.shift();\n if (waiter) {\n waiter.trackIds.forEach((id) => this.subscribedTracks.delete(id));\n waiter.reject(error);\n }\n this.onError(\n new Error(`Failed to process subscriber offer: ${String(error)}`),\n );\n } finally {\n this.subscriberNegotiating = false;\n }\n }\n }\n\n private async subscribe(trackId: string) {\n if (!trackId || this.subscribedTracks.has(trackId)) return;\n this.subscribedTracks.add(trackId);\n this.subscriptionQueue.push(trackId);\n if (!this.subscriptionRunning) await this.processSubscriptionQueue();\n }\n\n private async subscribeMultiple(trackIds: string[]) {\n const uniqueIds = [...new Set(trackIds.filter(Boolean))].filter(\n (id) => !this.subscribedTracks.has(id),\n );\n if (!uniqueIds.length || !this.isSocketOpen()) return;\n\n uniqueIds.forEach((id) => this.subscribedTracks.add(id));\n return new Promise<void>((resolve, reject) => {\n const sent = this.send({\n type: \"subscribe\",\n payload: { track_ids: uniqueIds },\n });\n\n if (!sent) {\n uniqueIds.forEach((id) => this.subscribedTracks.delete(id));\n reject(new Error(\"Signaling socket is not open\"));\n return;\n }\n\n this.subscriptionWaiters.push({\n trackIds: uniqueIds,\n resolve,\n reject,\n });\n });\n }\n\n private async processSubscriptionQueue() {\n this.subscriptionRunning = true;\n try {\n while (this.subscriptionQueue.length) {\n const trackId = this.subscriptionQueue.shift()!;\n if (!this.isSocketOpen()) {\n this.subscribedTracks.delete(trackId);\n continue;\n }\n\n await new Promise<void>((resolve, reject) => {\n const sent = this.send({\n type: \"subscribe\",\n payload: { track_ids: [trackId] },\n });\n\n if (!sent) {\n this.subscribedTracks.delete(trackId);\n reject(new Error(\"Signaling socket is not open\"));\n return;\n }\n\n this.subscriptionWaiters.push({\n trackIds: [trackId],\n resolve,\n reject,\n });\n });\n }\n } finally {\n this.subscriptionRunning = false;\n }\n }\n\n async publish({ audio = true, video = true } = {}) {\n if (!this.publisher)\n throw new Error(\"Publisher PeerConnection is not initialized\");\n\n if (!this.localStream) {\n this.localStream = await navigator.mediaDevices.getUserMedia({\n audio,\n video,\n });\n }\n\n await this.publishExistingTracks(audio, video);\n return this.localStream;\n }\n\n private async publishExistingTracks(audio = true, video = true) {\n if (!this.publisher || !this.localStream) return;\n\n if (\n !this.audioTransceiver ||\n !this.cameraTransceiver ||\n !this.screenTransceiver\n ) {\n throw new Error(\"Publisher transceivers are not initialized\");\n }\n\n const audioTrack = this.localStream\n .getAudioTracks()\n .find((track) => track.readyState === \"live\");\n const cameraTrack = this.localStream\n .getVideoTracks()\n .find((track) => track.readyState === \"live\");\n const screenTrack = this.screenStream\n ?.getVideoTracks()\n .find((track) => track.readyState === \"live\");\n\n await this.audioSender?.replaceTrack(\n audio && audioTrack ? audioTrack : null,\n );\n this.audioTransceiver.direction =\n audio && audioTrack ? \"sendonly\" : \"inactive\";\n\n await this.videoSender?.replaceTrack(\n video && cameraTrack ? cameraTrack : null,\n );\n this.cameraTransceiver.direction =\n video && cameraTrack ? \"sendonly\" : \"inactive\";\n\n await this.screenSender?.replaceTrack(screenTrack || null);\n this.screenTransceiver.direction = screenTrack ? \"sendonly\" : \"inactive\";\n\n if (!audioTrack && !cameraTrack && !screenTrack) return;\n\n const offer = await this.publisher.createOffer();\n await this.publisher.setLocalDescription(offer);\n\n this.send({\n type: \"publish_offer\",\n payload: {\n revision: ++this.publisherRevision,\n sdp: offer.sdp,\n },\n });\n\n if (screenTrack) {\n this.send({ type: \"start_screen_share\" });\n }\n }\n\n async shareScreen() {\n if (!this.publisher) {\n throw new Error(\"Publisher PeerConnection is not initialized\");\n }\n\n if (!this.screenTransceiver || !this.screenSender) {\n throw new Error(\"Screen transceiver is not initialized\");\n }\n\n const existing = this.screenStream;\n const existingTrack = this.screenSender.track;\n\n // Already sharing.\n if (existing || (existingTrack && existingTrack.readyState === \"live\")) {\n return existing;\n }\n\n try {\n await this.screenSender.replaceTrack(null);\n } catch {}\n\n this.screenTransceiver.direction = \"inactive\";\n\n const screenStream = await navigator.mediaDevices.getDisplayMedia({\n video: true,\n audio: false,\n });\n\n const screenTrack = screenStream.getVideoTracks()[0];\n\n if (!screenTrack) {\n screenStream.getTracks().forEach((track) => track.stop());\n throw new Error(\"Screen share returned no video track\");\n }\n\n const generation = ++this.screenShareGeneration;\n\n this.screenStream = screenStream;\n\n try {\n await this.screenSender.replaceTrack(screenTrack);\n\n this.screenTransceiver.direction = \"sendonly\";\n\n this.send({\n type: \"start_screen_share\",\n });\n\n const offer = await this.publisher.createOffer();\n\n await this.publisher.setLocalDescription(offer);\n\n const localDescription = this.publisher.localDescription;\n\n if (!localDescription?.sdp) {\n throw new Error(\"Publisher did not produce a valid screen-share SDP\");\n }\n\n this.send({\n type: \"publish_offer\",\n payload: {\n revision: ++this.publisherRevision,\n sdp: localDescription.sdp,\n },\n });\n\n screenTrack.onended = () => {\n if (generation !== this.screenShareGeneration) {\n return;\n }\n\n void this.stopScreenShare();\n };\n\n return this.screenStream;\n } catch (error) {\n try {\n await this.screenSender.replaceTrack(null);\n } catch {}\n\n this.screenTransceiver.direction = \"inactive\";\n\n screenTrack.onended = null;\n\n screenStream.getTracks().forEach((track) => {\n try {\n track.stop();\n } catch {}\n });\n\n this.screenStream = null;\n\n try {\n this.send({\n type: \"stop_screen_share\",\n });\n } catch {}\n\n throw error;\n }\n }\n\n async stopScreenShare() {\n const stream = this.screenStream;\n const senderTrack = this.screenSender?.track || null;\n\n if (!stream && !senderTrack) {\n return;\n }\n\n ++this.screenShareGeneration;\n\n if (senderTrack) {\n senderTrack.onended = null;\n }\n\n try {\n await this.screenSender?.replaceTrack(null);\n } catch (error) {\n this.onError(error);\n }\n\n if (this.screenTransceiver) {\n this.screenTransceiver.direction = \"inactive\";\n }\n\n try {\n if (this.publisher) {\n const offer = await this.publisher.createOffer();\n\n await this.publisher.setLocalDescription(offer);\n\n const localDescription = this.publisher.localDescription;\n\n if (localDescription?.sdp) {\n this.send({\n type: \"publish_offer\",\n payload: {\n revision: ++this.publisherRevision,\n sdp: localDescription.sdp,\n },\n });\n }\n }\n } catch (error) {\n this.onError(error);\n }\n\n this.send({\n type: \"stop_screen_share\",\n });\n\n stream?.getTracks().forEach((track) => {\n try {\n track.stop();\n } catch {}\n });\n\n this.screenStream = null;\n\n if (this.currentParticipantId) {\n this.onScreenShareStopped(this.currentParticipantId);\n }\n }\n\n muteAudio(muted: boolean) {\n this.desiredAudioMuted = muted;\n this.localStream?.getAudioTracks().forEach((track) => {\n track.enabled = !muted;\n });\n\n this.send({\n type: \"set_media_state\",\n payload: { audio_muted: muted, video_muted: this.desiredVideoMuted },\n });\n\n const trackId = this.localTrackIds.get(\"audio\");\n if (trackId) {\n this.send({\n type: \"track_state\",\n payload: {\n track_id: trackId,\n muted,\n },\n });\n }\n }\n\n muteVideo(muted: boolean) {\n this.desiredVideoMuted = muted;\n this.localStream?.getVideoTracks().forEach((track) => {\n track.enabled = !muted;\n });\n\n this.send({\n type: \"set_media_state\",\n payload: { audio_muted: this.desiredAudioMuted, video_muted: muted },\n });\n\n const trackId = this.localTrackIds.get(\"camera\");\n if (trackId) {\n this.send({\n type: \"track_state\",\n payload: {\n track_id: trackId,\n muted,\n },\n });\n }\n }\n\n sendChatMessage(input: {\n message: string;\n reply_to?: any;\n target?: string | null;\n }) {\n return this.send({\n type: \"send_chat\",\n payload: {\n message: input.message,\n reply_to: input.reply_to ?? null,\n target: input.target ?? null,\n },\n });\n }\n\n private getLiveTranscriptionMimeType(): string {\n if (typeof MediaRecorder === \"undefined\") {\n throw new Error(\"MediaRecorder is not supported by this browser\");\n }\n\n const candidates = [\n \"audio/webm;codecs=opus\",\n \"audio/webm\",\n \"audio/ogg;codecs=opus\",\n ];\n\n return candidates.find((type) =>\n MediaRecorder.isTypeSupported(type),\n ) || \"\";\n }\n\n async startLiveTranscription(): Promise<void> {\n if (this.liveTranscriptionActive) {\n return;\n }\n\n if (!this.room) {\n throw new Error(\"Cannot start live transcription without a room\");\n }\n\n if (!this.authToken) {\n throw new Error(\n \"Cannot start live transcription without an authenticated token\",\n );\n }\n\n const audioTrack = this.localStream?.getAudioTracks()[0];\n\n if (!audioTrack || audioTrack.readyState !== \"live\") {\n throw new Error(\n \"Cannot start live transcription without a live microphone track\",\n );\n }\n\n const mimeType = this.getLiveTranscriptionMimeType();\n const stream = new MediaStream([audioTrack]);\n\n this.liveTranscriptionActive = true;\n this.liveTranscriptionSequence = 0;\n this.liveTranscriptionStartedAt = Date.now();\n\n console.log(\"[Transcript] starting\", {\n room: this.room,\n trackId: audioTrack.id,\n readyState: audioTrack.readyState,\n enabled: audioTrack.enabled,\n mimeType,\n });\n\n this.liveTranscriptionLoopPromise =\n this.runLiveTranscriptionLoop(stream, mimeType).finally(() => {\n this.liveTranscriptionRecorder = null;\n this.liveTranscriptionLoopPromise = null;\n });\n\n await Promise.resolve();\n }\n\n private async captureLiveChunk(\n stream: MediaStream,\n mimeType: string,\n ): Promise<Blob | null> {\n return new Promise((resolve, reject) => {\n const chunks: Blob[] = [];\n const recorder = mimeType\n ? new MediaRecorder(stream, { mimeType })\n : new MediaRecorder(stream);\n\n this.liveTranscriptionRecorder = recorder;\n\n const timeout = window.setTimeout(() => {\n if (recorder.state !== \"inactive\") {\n recorder.stop();\n }\n }, 1500);\n\n recorder.onstart = () => {\n console.log(\"[Transcript] MediaRecorder started\", {\n mimeType: recorder.mimeType,\n });\n };\n\n recorder.ondataavailable = (event) => {\n if (event.data.size > 0) {\n chunks.push(event.data);\n }\n };\n\n recorder.onerror = () => {\n window.clearTimeout(timeout);\n reject(new Error(\"Live transcription recorder failed\"));\n };\n\n recorder.onstop = () => {\n window.clearTimeout(timeout);\n this.liveTranscriptionRecorder = null;\n\n resolve(\n chunks.length\n ? new Blob(chunks, {\n type:\n recorder.mimeType ||\n mimeType ||\n \"audio/webm\",\n })\n : null,\n );\n };\n\n // Short, repeatable chunks keep the transcript responsive.\n recorder.start();\n });\n }\n\n private async runLiveTranscriptionLoop(\n stream: MediaStream,\n mimeType: string,\n ): Promise<void> {\n while (\n this.liveTranscriptionActive &&\n stream.getAudioTracks()[0]?.readyState === \"live\"\n ) {\n try {\n const blob = await this.captureLiveChunk(stream, mimeType);\n\n if (!this.liveTranscriptionActive) {\n break;\n }\n\n if (!blob || blob.size === 0) {\n continue;\n }\n\n const sequence = this.liveTranscriptionSequence++;\n const offsetMs = Math.max(\n 0,\n Date.now() - this.liveTranscriptionStartedAt,\n );\n\n await this.uploadLiveTranscriptionChunk(\n blob,\n sequence,\n offsetMs,\n blob.type || mimeType,\n );\n } catch (error) {\n console.error(\n \"[Transcript] chunk processing failed\",\n error,\n );\n\n this.onError(error);\n\n await new Promise((resolve) =>\n setTimeout(resolve, 750),\n );\n }\n }\n }\n\n private async uploadLiveTranscriptionChunk(\n blob: Blob,\n sequence: number,\n offsetMs: number,\n mimeType: string,\n ): Promise<void> {\n if (!this.room || !this.authToken) {\n return;\n }\n\n const form = new FormData();\n\n form.append(\"sequence\", String(sequence));\n form.append(\"offset_ms\", String(offsetMs));\n\n const extension =\n mimeType.includes(\"ogg\") || blob.type.includes(\"ogg\")\n ? \"ogg\"\n : \"webm\";\n\n form.append(\n \"audio\",\n blob,\n `live-${sequence}.${extension}`,\n );\n\n const url =\n `${this.apiBase}/rooms/` +\n `${encodeURIComponent(this.room)}/` +\n `live-transcription`;\n\n console.log(\"[Transcript] POST\", {\n url,\n sequence,\n size: blob.size,\n mimeType,\n });\n\n const response = await fetch(url, {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${this.authToken}`,\n Accept: \"application/json\",\n },\n body: form,\n });\n\n const responseText = await response.text();\n\n console.log(\"[Transcript] response\", {\n status: response.status,\n body: responseText,\n });\n\n if (!response.ok) {\n throw new Error(\n `Live transcription request failed: ${response.status} ${responseText}`,\n );\n }\n }\n\n stopLiveTranscription(): void {\n console.log(\"[Transcript] stopping\");\n\n this.liveTranscriptionActive = false;\n\n try {\n if (\n this.liveTranscriptionRecorder &&\n this.liveTranscriptionRecorder.state !== \"inactive\"\n ) {\n this.liveTranscriptionRecorder.stop();\n }\n } catch (error) {\n console.warn(\n \"[Transcript] recorder shutdown failed\",\n error,\n );\n }\n\n this.liveTranscriptionRecorder = null;\n }\n\n isLiveTranscriptionActive(): boolean {\n return this.liveTranscriptionActive;\n }\n\n async applyNetworkRecommendation(action: string) {\n if (!this.videoSender || this.networkProfile === action) return;\n\n const params = this.videoSender.getParameters();\n const encodings = params.encodings?.length\n ? params.encodings\n : [{} as RTCRtpEncodingParameters];\n const encoding = encodings[0];\n\n switch (action) {\n case \"reduce_video\":\n encoding.maxBitrate = 700_000;\n encoding.maxFramerate = 20;\n break;\n case \"audio_priority\":\n encoding.maxBitrate = 350_000;\n encoding.maxFramerate = 10;\n break;\n default:\n encoding.maxBitrate = 1_500_000;\n encoding.maxFramerate = 30;\n break;\n }\n\n params.encodings = encodings;\n try {\n await this.videoSender.setParameters(params);\n this.networkProfile = action;\n } catch (error) {\n this.onError(error);\n }\n }\n\n async startRecording() {\n if (!this.send({ type: \"start_recording\" })) {\n throw new Error(\"SFU signaling is not connected\");\n }\n }\n\n async stopRecording() {\n if (!this.send({ type: \"stop_recording\" })) {\n throw new Error(\"SFU signaling is not connected\");\n }\n }\n\n async getRecordingStatus() {\n if (!this.room || !this.token) {\n throw new Error(\"SFU client is not connected\");\n }\n\n return this.request(\n `${this.apiBase}/rooms/${encodeURIComponent(this.room)}/recording`,\n {\n headers: {\n Authorization: `Bearer ${this.token}`,\n },\n },\n );\n }\n\n async approveJoinRequest(requestId: string) {\n if (!requestId) throw new Error(\"requestId is required\");\n if (\n !this.send({ type: \"approve_join\", payload: { request_id: requestId } })\n ) {\n throw new Error(\"SFU signaling is not connected\");\n }\n }\n\n async rejectJoinRequest(requestId: string, reason?: string) {\n if (!requestId) throw new Error(\"requestId is required\");\n if (\n !this.send({\n type: \"reject_join\",\n payload: { request_id: requestId, reason },\n })\n ) {\n throw new Error(\"SFU signaling is not connected\");\n }\n }\n\n async cancelJoinRequest(requestId?: string) {\n const id = requestId || this.pendingJoinRequestId;\n if (!id) return;\n if (\n !this.send({ type: \"cancel_join_request\", payload: { request_id: id } })\n ) {\n throw new Error(\"SFU signaling is not connected\");\n }\n this.pendingJoinRequestId = null;\n }\n\n async muteAllAudio() {\n if (!this.send({ type: \"mute_all_audio\" }))\n throw new Error(\"SFU signaling is not connected\");\n }\n\n async muteParticipant(participantId: string) {\n if (!participantId) throw new Error(\"participantId is required\");\n if (\n !this.send({\n type: \"mute_participant\",\n payload: { participant_id: participantId },\n })\n ) {\n throw new Error(\"SFU signaling is not connected\");\n }\n }\n\n async removeParticipant(participantId: string) {\n if (!participantId) throw new Error(\"participantId is required\");\n if (\n !this.send({\n type: \"remove_participant\",\n payload: { participant_id: participantId },\n })\n ) {\n throw new Error(\"SFU signaling is not connected\");\n }\n }\n\n async getModerators(roomCode: string) {\n return this.request(\n `${this.apiBase}/rooms/${encodeURIComponent(roomCode)}/moderators`,\n );\n }\n\n async addModerator(roomCode: string, userId: string) {\n return this.request(\n `${this.apiBase}/rooms/${encodeURIComponent(roomCode)}/moderators`,\n {\n method: \"POST\",\n body: JSON.stringify({ user_id: userId }),\n },\n );\n }\n\n async removeModerator(roomCode: string, userId: string) {\n return this.request(\n `${this.apiBase}/rooms/${encodeURIComponent(roomCode)}/moderators/${encodeURIComponent(userId)}`,\n {\n method: \"DELETE\",\n },\n );\n }\n\n private isSocketOpen() {\n return this.ws?.readyState === WebSocket.OPEN;\n }\n\n private send(message: any) {\n if (!this.isSocketOpen()) return false;\n this.ws!.send(\n JSON.stringify({\n request_id: this.nextRequestId(),\n ...message,\n }),\n );\n return true;\n }\n\n sendReaction(reaction: string): void {\n this.send({\n type: \"send_reaction\",\n payload: {\n emoji: reaction,\n },\n });\n }\n\n private removeRemoteParticipant(participantId: string) {\n const stream = this.remoteStreams.get(participantId);\n if (stream) {\n stream.getTracks().forEach((track) => track.stop());\n this.remoteStreams.delete(participantId);\n }\n\n const screenStream = this.remoteScreenStreams.get(participantId);\n if (screenStream) {\n screenStream.getTracks().forEach((track) => track.stop());\n this.remoteScreenStreams.delete(participantId);\n }\n\n for (const [trackId, metadata] of this.trackMetadata) {\n if (metadata.participant_id === participantId) {\n this.trackMetadata.delete(trackId);\n this.subscribedTracks.delete(trackId);\n this.trackToParticipant.delete(trackId);\n this.trackToSource.delete(trackId);\n }\n }\n }\n\n async leave() {\n this.stopLiveTranscription();\n this.stopHeartbeat();\n this.intentionalClose = true;\n this.setState(\"leaving\");\n\n if (this.reconnectTimer) {\n clearTimeout(this.reconnectTimer);\n this.reconnectTimer = null;\n }\n\n const roomCode = this.room;\n const ws = this.ws;\n this.leaveAcknowledged = false;\n\n if (ws?.readyState === WebSocket.OPEN) {\n await new Promise<void>((resolve) => {\n let settled = false;\n const finish = () => {\n if (settled) return;\n settled = true;\n resolve();\n };\n\n // The normal onmessage path remains authoritative. We only wait for\n // the server's `left` acknowledgement through a short polling window.\n const timeout = setTimeout(finish, 1200);\n\n const check = () => {\n if (this.leaveAcknowledged || this.ws !== ws) {\n clearTimeout(timeout);\n finish();\n return;\n }\n if (ws.readyState !== WebSocket.OPEN) {\n clearTimeout(timeout);\n finish();\n return;\n }\n setTimeout(check, 25);\n };\n\n ws.addEventListener(\n \"close\",\n () => {\n clearTimeout(timeout);\n finish();\n },\n { once: true },\n );\n\n this.send({ type: \"leave\" });\n check();\n });\n\n try {\n ws.close(1000, \"client_leave\");\n } catch {\n // ignore\n }\n }\n\n this.clearResumeToken(roomCode);\n this.cleanupAll();\n this.setState(\"disconnected\");\n }\n\n private closePeerConnectionsOnly() {\n if (this.publisher) {\n try {\n this.publisher.close();\n } catch {\n /* ignore */\n }\n this.publisher = null;\n }\n if (this.subscriber) {\n try {\n this.subscriber.close();\n } catch {\n /* ignore */\n }\n this.subscriber = null;\n }\n this.videoSender = null;\n this.audioSender = null;\n this.screenSender = null;\n this.audioTransceiver = null;\n this.cameraTransceiver = null;\n this.screenTransceiver = null;\n this.pendingIce = { publisher: [], subscriber: [] };\n this.offerQueue = [];\n this.subscriberNegotiating = false;\n this.subscriptionQueue = [];\n this.subscriptionRunning = false;\n this.subscriptionWaiters\n .splice(0)\n .forEach((w) => w.reject(new Error(\"PeerConnection recreated\")));\n this.subscribedTracks.clear();\n }\n\n private cleanupAll() {\n if (this.subscriberStatsTimer) {\n clearInterval(this.subscriberStatsTimer);\n this.subscriberStatsTimer = null;\n }\n\n this.closePeerConnectionsOnly();\n\n this.localStream?.getTracks().forEach((track) => track.stop());\n this.screenStream?.getTracks().forEach((track) => track.stop());\n this.localStream = null;\n this.screenStream = null;\n\n for (const stream of this.remoteStreams.values()) {\n stream.getTracks().forEach((track) => track.stop());\n }\n this.remoteStreams.clear();\n\n for (const stream of this.remoteScreenStreams.values()) {\n stream.getTracks().forEach((track) => track.stop());\n }\n this.remoteScreenStreams.clear();\n\n this.trackMetadata.clear();\n this.trackToParticipant.clear();\n this.trackToSource.clear();\n this.localTrackIds.clear();\n this.participants.clear();\n this.currentParticipantId = null;\n this.resumeToken = null;\n this.pendingJoinRequestId = null;\n this.token = null;\n this.room = null;\n\n if (this.ws) {\n try {\n this.ws.close();\n } catch {\n /* ignore */\n }\n this.ws = null;\n }\n }\n\n private async logSubscriberVideoStats() {\n if (!this.subscriber || this.subscriber.connectionState === \"closed\")\n return;\n try {\n const stats = await this.subscriber.getStats();\n stats.forEach((report: any) => {\n if (\n report.type === \"inbound-rtp\" &&\n (report.kind === \"video\" || report.mediaType === \"video\")\n ) {\n console.debug(\"[SFU] subscriber video\", {\n packetsReceived: report.packetsReceived,\n packetsLost: report.packetsLost,\n framesDecoded: report.framesDecoded,\n frameWidth: report.frameWidth,\n frameHeight: report.frameHeight,\n });\n }\n });\n } catch {\n // stats are diagnostic only\n }\n }\n\n private recoverWebRTC(reason: string) {\n if (this.intentionalClose) return;\n\n if (this.transportRecoveryInProgress) {\n console.debug(\"[SFU] WebRTC recovery already in progress\", {\n reason,\n });\n return;\n }\n\n this.transportRecoveryInProgress = true;\n\n console.warn(\"[SFU] WebRTC transport failed; starting recovery\", {\n reason,\n publisherState: this.publisher?.connectionState,\n publisherIceState: this.publisher?.iceConnectionState,\n subscriberState: this.subscriber?.connectionState,\n subscriberIceState: this.subscriber?.iceConnectionState,\n });\n\n this.setState(\"reconnecting\");\n\n this.transportRecoveryTimer = setTimeout(() => {\n this.transportRecoveryTimer = null;\n\n if (this.intentionalClose) {\n this.transportRecoveryInProgress = false;\n return;\n }\n\n const ws = this.ws;\n\n if (ws && ws.readyState === WebSocket.OPEN) {\n try {\n ws.close(4000, \"webrtc_recovery\");\n } catch (error) {\n console.warn(\"[SFU] Failed to close WebSocket for recovery\", error);\n\n this.transportRecoveryInProgress = false;\n this.scheduleReconnect();\n }\n\n return;\n }\n\n this.transportRecoveryInProgress = false;\n this.scheduleReconnect();\n }, 250);\n }\n}\n","import { SDK_CONFIG } from \"../config/ws\";\nimport {\n ChatInput,\n Events,\n PubSubTopic,\n PubSubTopicConfig,\n MeetingConfig,\n SDKError,\n RecordingInfo,\n VideoSDKCoreOptions,\n SFUConnectionState,\n LiveTranscript,\n NetworkQuality,\n} from \"../types/meeting\";\nimport { ActiveSpeakerDetector } from \"./ActiveSpeakerDetector\";\nimport { MeetingState } from \"./MeetingState\";\nimport { SFUClient, TrackInfo } from \"./SFUClient\";\n\nexport class VideoSDKCore {\n private sfuClient: SFUClient | null = null;\n private myId: string;\n private room: {\n id: string | null;\n name: string | null;\n } = {\n id: null,\n name: null,\n };\n private localStream: MediaStream | null = null;\n private screenStream: MediaStream | null = null;\n private isScreenSharing = false;\n private participantName = \"\";\n\n public readonly state: MeetingState;\n\n private intentionalDisconnect = false;\n\n private remoteStreams = new Map<string, MediaStream>();\n private remoteScreenStreams = new Map<string, MediaStream>();\n\n private activeSpeakerDetector: ActiveSpeakerDetector;\n\n private joinPromise: Promise<void> | null = null;\n private disconnectPromise: Promise<void> | null = null;\n\n private emitError(\n code: string,\n message: string,\n raw?: any,\n recoverable = true,\n ) {\n const err: SDKError = {\n code,\n message,\n raw,\n roomId: this.room.id,\n participantId: this.myId,\n recoverable,\n };\n\n this.events.onError?.(err);\n\n console.error(\"[MeetingSDK Error]\", err);\n }\n\n constructor(\n options: VideoSDKCoreOptions,\n private events: Events = {},\n private apiBase: string = SDK_CONFIG.apiBase,\n private wsBase: string = SDK_CONFIG.wsBase,\n ) {\n this.state = new MeetingState();\n this.events = events;\n this.activeSpeakerDetector = new ActiveSpeakerDetector({\n onActiveSpeakersChanged: (participantIds) => {\n this.state.setActiveSpeakers(participantIds);\n\n this.events.onActiveSpeakersChanged?.(participantIds);\n },\n });\n this.myId = options.participantId;\n this.sfuClient = this.createSFUClient(options.token);\n }\n\n // LOCAL MEDIA\n\n async initLocal(video: HTMLVideoElement, name: string) {\n this.participantName = name;\n\n try {\n this.localStream = await navigator.mediaDevices.getUserMedia({\n video: {\n width: { ideal: 1280 },\n height: { ideal: 720 },\n },\n audio: {\n echoCancellation: true,\n noiseSuppression: true,\n autoGainControl: true,\n },\n });\n\n const localAudioTrack = this.localStream.getAudioTracks()[0];\n\n if (localAudioTrack) {\n this.activeSpeakerDetector.addTrack(this.myId, localAudioTrack);\n }\n\n const hasVideo = this.localStream\n .getVideoTracks()\n .some((t) => t.readyState === \"live\");\n\n const hasAudio = this.localStream\n .getAudioTracks()\n .some((t) => t.readyState === \"live\");\n\n if (!hasVideo || !hasAudio) {\n throw new Error(`Missing tracks: video=${hasVideo}, audio=${hasAudio}`);\n }\n\n video.srcObject = this.localStream;\n\n this.updateLocalMedia();\n } catch (err: any) {\n this.emitError(\"GET_USER_MEDIA_FAILED\", err?.message, err, false);\n\n throw err;\n }\n }\n\n private updateLocalMedia(audioMuted = false, videoMuted = false) {\n if (!this.localStream) return;\n\n this.state.updateLocalParticipant({\n id: this.myId,\n name: this.participantName,\n\n media: {\n stream: this.localStream,\n cameraTrack: this.localStream.getVideoTracks()[0],\n audioTrack: this.localStream.getAudioTracks()[0],\n micEnabled:\n this.localStream.getAudioTracks()[0]?.enabled ?? !audioMuted,\n camEnabled:\n this.localStream.getVideoTracks()[0]?.enabled ?? !videoMuted,\n isScreenSharing: this.isScreenSharing,\n screenStream: this.screenStream,\n screenTrack: this.screenStream?.getVideoTracks()[0],\n },\n });\n\n this.state.localStream = this.localStream;\n }\n\n // ROOM MANAGEMENT\n async createRoom(input: {\n name: string;\n description?: string;\n capacity?: number;\n is_private?: boolean;\n }) {\n return this.sfuClient!.createRoom(input);\n }\n\n async getRoom(roomCode: string) {\n return this.sfuClient!.getRoom(roomCode);\n }\n\n async getJoinState(roomCode: string) {\n return this.sfuClient!.getJoinState(roomCode);\n }\n\n async deleteRoom(roomCode: string) {\n return this.sfuClient!.deleteRoom(roomCode);\n }\n\n // JOIN\n async joinMeeting(\n config: Omit<MeetingConfig, \"participantId\">,\n ): Promise<void> {\n const { roomId, name, audioMuted = false, videoMuted = false } = config;\n\n if (!roomId || !name) {\n throw new Error(\"roomId and name are required to join meeting\");\n }\n\n if (!this.myId) {\n throw new Error(\"participantId is required\");\n }\n\n if (\n this.sfuClient &&\n this.room.id === roomId &&\n this.sfuClient.getConnectionState() === \"connected\"\n ) {\n console.info(\"[SDK] Already connected; duplicate join ignored\", {\n roomId,\n participantId: this.myId,\n });\n\n return;\n }\n\n if (this.joinPromise) {\n console.info(\n \"[SDK] Join already in progress; waiting for existing join\",\n {\n roomId,\n participantId: this.myId,\n },\n );\n\n return this.joinPromise;\n }\n\n if (this.sfuClient && this.room.id && this.room.id !== roomId) {\n throw new Error(\n `Already connected to room ${this.room.id}. Leave the current meeting before joining another room.`,\n );\n }\n\n this.intentionalDisconnect = false;\n this.participantName = name;\n this.room.id = roomId;\n this.room.name = name;\n\n if (!this.localStream) {\n this.localStream = await navigator.mediaDevices.getUserMedia({\n video: true,\n audio: true,\n });\n\n const localAudioTrack = this.localStream.getAudioTracks()[0];\n\n if (localAudioTrack) {\n this.activeSpeakerDetector.addTrack(this.myId, localAudioTrack);\n }\n }\n\n this.localStream.getAudioTracks().forEach((track) => {\n track.enabled = !audioMuted;\n });\n\n this.localStream.getVideoTracks().forEach((track) => {\n track.enabled = !videoMuted;\n });\n\n this.updateLocalMedia(audioMuted, videoMuted);\n\n const promise = this.connect(roomId, name);\n\n this.joinPromise = promise;\n\n try {\n await promise;\n } finally {\n if (this.joinPromise === promise) {\n this.joinPromise = null;\n }\n }\n }\n\n // SFU CONNECTION\n private async connect(roomId: string, name: string): Promise<void> {\n if (!this.sfuClient) {\n throw new Error(\"SFU client is not initialized\");\n }\n\n const state = this.sfuClient.getConnectionState();\n\n if (\n this.room.id === roomId &&\n (state === \"connecting\" ||\n state === \"joining\" ||\n state === \"waiting_approval\" ||\n state === \"connected\" ||\n state === \"reconnecting\")\n ) {\n console.info(\"[SDK] Existing SFU connection is active; connect ignored\", {\n roomId,\n state,\n });\n return;\n }\n\n if (state !== \"idle\" && state !== \"disconnected\") {\n throw new Error(\n `SFU client is already active in state \"${state}\". Leave the current meeting before joining another room.`,\n );\n }\n\n this.sfuClient.setLocalStream(this.localStream);\n\n await this.sfuClient.getToken(roomId, {\n displayName: name,\n participantId: this.myId,\n audioMuted: !(this.localStream?.getAudioTracks()[0]?.enabled ?? true),\n videoMuted: !(this.localStream?.getVideoTracks()[0]?.enabled ?? true),\n });\n }\n\n private createSFUClient(token: string) {\n return new SFUClient({\n apiBase: this.apiBase,\n wsBase: this.wsBase,\n participantId: this.myId,\n token,\n autoSubscribe: true,\n // CONNECTION STATE\n\n onStateChange: (state) => {\n this.handleSFUState(state);\n },\n\n onConnected: (payload, resumed) => {\n const local = (payload?.participants || []).find(\n (participant: any) => participant?.participant_id === this.myId,\n );\n\n const permissions = local?.permissions ?? payload?.permissions ?? {};\n const isModerator = Boolean(permissions?.moderate);\n const isHost = Boolean(\n local?.is_host ?? local?.isHost ?? permissions?.host,\n );\n\n this.state.updateLocalParticipant({\n id: this.myId,\n name: local?.user_metadata?.name,\n isHost,\n isModerator,\n permissions,\n media: {\n micEnabled: !Boolean(local?.audio_muted),\n camEnabled: !Boolean(local?.video_muted),\n },\n });\n },\n\n onDisconnected: () => {\n console.log(\"[SFU] Signaling WebSocket disconnected; reconnecting\");\n },\n\n onReconnecting: (attempt) => {\n console.warn(`[SFU] Reconnecting, attempt ${attempt}`);\n },\n\n // ADMISSION CONTROL\n onLiveTranscript: (transcript: LiveTranscript) => {\n this.state.addLiveTranscript(transcript);\n this.events.onLiveTranscript?.(transcript);\n },\n\n onNetworkQuality: (quality: NetworkQuality) => {\n this.state.setNetworkQuality(quality);\n this.events.onNetworkQuality?.(quality);\n },\n\n onRoomUpdate: (payload) => {\n const participants = payload?.participants || [];\n const local = participants.find(\n (p: any) => p?.participant_id === this.myId,\n );\n if (local) {\n const media = this.state.localParticipant?.media;\n this.state.updateLocalParticipant({\n id: this.myId,\n name: this.participantName,\n media: {\n micEnabled: !Boolean(local.audio_muted),\n camEnabled: !Boolean(local.video_muted),\n isScreenSharing: Boolean(local.screen_sharing),\n screenStream: this.screenStream,\n screenTrack: this.screenStream?.getVideoTracks()[0],\n },\n });\n if (this.localStream) {\n this.localStream.getAudioTracks().forEach((track) => {\n track.enabled = !Boolean(local.audio_muted);\n });\n this.localStream.getVideoTracks().forEach((track) => {\n track.enabled = !Boolean(local.video_muted);\n });\n }\n if (local.screen_sharing) this.state.setPresenterId(this.myId);\n else if (this.state.presenterId === this.myId)\n this.state.setPresenterId(null);\n }\n const presenter = participants.find((p: any) => p?.screen_sharing);\n if (presenter) this.state.setPresenterId(presenter.participant_id);\n else if (!local?.screen_sharing) this.state.setPresenterId(null);\n for (const message of payload?.chat_history || []) {\n this.state.addChatMessage(message);\n }\n this.events.onRoomUpdate?.(payload);\n },\n\n onJoinPending: (info) => {\n console.log(\"[SFU] Join request pending\", info);\n },\n\n onJoinApproved: (requestId) => {\n console.log(\"[SFU] Join approved\", requestId);\n this.events.onJoinApproved?.(requestId);\n this.events.onEntryResponded?.(\n {\n participantId: this.myId,\n decision: \"approved\",\n },\n\n \"approved\",\n );\n },\n\n onJoinRejected: (requestId, reason) => {\n console.warn(\"[SFU] Join rejected\", requestId, reason);\n this.events.onJoinRejected?.(requestId);\n this.events.onEntryResponded?.(\n {\n participantId: this.myId,\n decision: \"rejected\",\n },\n\n \"rejected\",\n );\n\n this.emitError(\n \"JOIN_REJECTED\",\n reason || \"Your request to join was rejected\",\n {\n requestId,\n reason,\n },\n false,\n );\n },\n\n onChatMessage: (message) => {\n const msg = {\n id: message.id,\n text: message.text,\n sender_id: message.sender_id,\n sender_name: message.sender_name,\n timestamp: Number(message.timestamp),\n reply_to: message.reply_to ?? null,\n target: message.target ?? null,\n };\n this.state.addChatMessage(msg);\n this.events.onChatMessage?.(msg);\n },\n onReaction: (reaction) => {\n this.events.onReaction?.(reaction);\n },\n onJoinRequestCanceled: (requestId) => {\n this.events.onJoinRequestCanceled?.(requestId);\n },\n\n onParticipantRemoved: (participantId, removedBy) => {\n if (participantId === this.myId) {\n this.intentionalDisconnect = true;\n this.events.onUserLeft?.(participantId);\n try {\n this.localStream\n ?.getTracks()\n .forEach((track) => (track.enabled = false));\n } catch {}\n } else {\n this.cleanupRemoteParticipant(participantId);\n this.state.removeParticipant(participantId);\n this.events.onUserLeft?.(participantId);\n }\n this.events.onParticipantRemoved?.(participantId, removedBy);\n },\n\n onParticipantPermissionsChanged: (participantId, permissions) => {\n if (participantId === this.myId) {\n const current = this.state.localParticipant;\n this.state.updateLocalParticipant({\n id: this.myId,\n name: this.participantName,\n isHost: current?.isHost,\n isModerator: Boolean(permissions?.moderate),\n permissions,\n });\n }\n },\n\n onJoinRequested: (request) => {\n const requestId = request?.request_id || request?.requestId;\n const participantId = request?.user_id || request?.participantId;\n const nameValue =\n request?.user_metadata?.name ||\n request?.display_name ||\n request?.name ||\n \"Participant\";\n\n if (!requestId || !participantId) {\n return;\n }\n\n this.events.onEntryRequested?.({\n requestId,\n participantId,\n name: nameValue,\n });\n },\n\n // PARTICIPANTS\n onParticipantJoined: (participant) => {\n const pid = participant.participant_id;\n\n if (!pid || pid === this.myId) {\n return;\n }\n\n const pname =\n participant.user_metadata?.name ||\n participant.display_name ||\n \"Participant\";\n\n this.state.addParticipant({\n id: pid,\n name: pname,\n isModerator: Boolean(participant?.permissions?.moderate),\n permissions: participant?.permissions,\n connectionState: \"connected\",\n media: {\n micEnabled: true,\n camEnabled: true,\n isScreenSharing: false,\n stream: null,\n },\n });\n\n this.events.onUserJoined?.({\n id: pid,\n name: pname,\n });\n },\n\n onParticipantPresence: (participantId, presence) => {\n if (participantId === this.myId) {\n return;\n }\n\n const current = this.state.getParticipant(participantId);\n\n if (!current) {\n return;\n }\n\n const connectionState =\n presence === \"reconnecting\"\n ? \"reconnecting\"\n : presence === \"connected\" || presence === \"online\"\n ? \"connected\"\n : presence === \"disconnected\"\n ? \"disconnected\"\n : current.connectionState;\n\n this.state.updateParticipantMedia(participantId, {\n stream: current.media?.stream ?? null,\n });\n\n const next = new Map(this.state.participants);\n\n next.set(participantId, {\n ...current,\n connectionState,\n });\n\n this.state.participants = next;\n\n this.state.notify(`participant:${participantId}`);\n\n this.state.notify(\"participants\");\n },\n\n onParticipantLeft: (participant) => {\n const pid =\n typeof participant === \"string\"\n ? participant\n : participant.participant_id;\n\n if (!pid) {\n return;\n }\n\n console.log(\"[SFU] Participant permanently left\", pid);\n\n this.cleanupRemoteParticipant(pid);\n this.state.removeParticipant(pid);\n this.events.onUserLeft?.(pid);\n },\n\n // TRACKS\n onParticipantMediaState: (participantId, audioMuted, videoMuted) => {\n if (participantId === this.myId) {\n this.localStream\n ?.getAudioTracks()\n .forEach((track) => (track.enabled = !audioMuted));\n this.localStream\n ?.getVideoTracks()\n .forEach((track) => (track.enabled = !videoMuted));\n this.state.updateLocalParticipant({\n id: this.myId,\n name: this.participantName,\n media: { micEnabled: !audioMuted, camEnabled: !videoMuted },\n });\n this.events.onMuteStateChanged?.(participantId, \"audio\", audioMuted);\n this.events.onMuteStateChanged?.(participantId, \"video\", videoMuted);\n return;\n }\n const participant = this.state.getParticipant(participantId);\n if (!participant) return;\n this.state.updateParticipantMedia(participantId, {\n micEnabled: !audioMuted,\n camEnabled: !videoMuted,\n });\n this.events.onMuteStateChanged?.(participantId, \"audio\", audioMuted);\n this.events.onMuteStateChanged?.(participantId, \"video\", videoMuted);\n },\n\n onTrackPublished: (track) => {\n console.log(\"[SFU] Track published\", track);\n },\n\n onTrackUnpublished: (track) => {\n console.log(\"[SFU] Track unpublished\", track);\n const pid = track.participant_id;\n\n if (!pid) {\n return;\n }\n\n const current = this.state.getParticipant(pid);\n if (track.source === \"screen\") {\n const screen = this.remoteScreenStreams.get(pid);\n\n screen?.getTracks().forEach((t) => t.stop());\n\n this.remoteScreenStreams.delete(pid);\n\n this.state.updateParticipantMedia(pid, {\n isScreenSharing: false,\n screenStream: null,\n screenTrack: undefined,\n });\n\n this.events.onScreenShareStopped?.(pid);\n\n return;\n }\n\n if (!current) {\n return;\n }\n\n this.state.updateParticipantMedia(pid, {\n stream: current.media?.stream ?? null,\n micEnabled:\n track.kind === \"audio\"\n ? false\n : (current.media?.micEnabled ?? true),\n\n camEnabled:\n track.kind === \"video\"\n ? false\n : (current.media?.camEnabled ?? true),\n });\n },\n\n onTrackStateChanged: (track) => {\n const pid = track.participant_id;\n\n if (!pid || pid === this.myId) {\n return;\n }\n\n const current = this.state.getParticipant(pid);\n\n if (!current) {\n return;\n }\n\n if (track.source === \"audio\") {\n this.state.updateParticipantMedia(pid, {\n stream: current.media?.stream ?? null,\n micEnabled: !track.muted,\n });\n\n this.events.onMuteStateChanged?.(pid, \"audio\", track.muted);\n } else if (track.source === \"camera\") {\n this.state.updateParticipantMedia(pid, {\n stream: current.media?.stream ?? null,\n camEnabled: !track.muted,\n });\n\n this.events.onMuteStateChanged?.(pid, \"video\", track.muted);\n }\n\n this.events.onTrackStateChanged?.(track as any);\n },\n\n // RECORDING\n onRecordingStarted: (recording) => {\n this.state.setRecording({\n recording_id: recording.recording_id,\n started_at: recording.started_at,\n status: \"recording\",\n active: true,\n late_join: true,\n });\n\n this.events.onRecordingStarted?.(recording);\n },\n\n onRecordingStopped: (recording) => {\n this.state.setRecording({\n recording_id: recording.recording_id,\n stopped_at: recording.stopped_at,\n status: \"stopped\",\n active: false,\n });\n\n this.events.onRecordingStopped?.(recording);\n },\n\n // REMOTE MEDIA\n onRemoteTrack: (track, stream, metadata) => {\n this.handleRemoteTrack(track, stream, metadata);\n },\n\n // SCREEN SHARE\n onScreenShareStarted: (participantId, _track) => {\n console.log(\"[SFU] Screen share started\", participantId);\n\n if (participantId === this.myId) {\n if (!this.screenStream) {\n this.screenStream = this.sfuClient?.getScreenStream() ?? null;\n }\n\n this.state.setPresenterId(participantId);\n this.state.updateLocalParticipant({\n media: {\n isScreenSharing: true,\n screenStream: this.screenStream,\n screenTrack: this.screenStream?.getVideoTracks()[0],\n },\n });\n return;\n }\n\n this.state.setPresenterId(participantId);\n\n const existingRemoteScreen =\n this.sfuClient?.getRemoteScreenStream(participantId) ??\n this.remoteScreenStreams.get(participantId) ??\n null;\n\n if (existingRemoteScreen) {\n this.remoteScreenStreams.set(participantId, existingRemoteScreen);\n const screenTrack = existingRemoteScreen.getVideoTracks()[0];\n this.state.updateParticipantMedia(participantId, {\n isScreenSharing: true,\n screenStream: existingRemoteScreen,\n screenTrack,\n });\n this.events.onScreenShareStarted?.(\n participantId,\n existingRemoteScreen,\n );\n return;\n }\n\n const current = this.state.getParticipant(participantId);\n if (current) {\n this.state.updateParticipantMedia(participantId, {\n isScreenSharing: true,\n screenStream: current.media?.screenStream ?? null,\n screenTrack: current.media?.screenTrack,\n });\n }\n },\n\n onScreenShareStopped: (participantId) => {\n if (this.state.presenterId === participantId) {\n this.state.setPresenterId(null);\n }\n\n if (participantId === this.myId) {\n this.state.updateLocalParticipant({\n media: {\n isScreenSharing: false,\n screenStream: null,\n screenTrack: undefined,\n },\n });\n return;\n }\n\n this.state.updateParticipantMedia(participantId, {\n isScreenSharing: false,\n });\n\n this.events.onScreenShareStopped?.(participantId);\n },\n\n // ERROR\n onError: (error) => {\n console.error(\"[SFU] Error:\", error);\n\n if (\n error?.code === \"request_failed\" ||\n error?.code === \"authorization\"\n ) {\n this.emitError(\"PERMISSION_DENIED\", error.message, error, false);\n\n return;\n }\n\n this.emitError(\n \"SFU_ERROR\",\n error?.message || String(error),\n error,\n true,\n );\n },\n });\n }\n\n // SFU STATE\n private handleSFUState(state: SFUConnectionState) {\n this.events.onConnectionStateChanged?.(state);\n\n if (state === \"reconnecting\") {\n this.state.updateLocalParticipant({\n id: this.myId,\n name: this.participantName,\n });\n\n return;\n }\n\n if (state === \"disconnected\" && !this.intentionalDisconnect) {\n this.emitError(\n \"CONNECTION_LOST\",\n \"Unable to reconnect to SFU server\",\n null,\n true,\n );\n }\n }\n\n // REMOTE TRACKS\n private handleRemoteTrack(\n track: MediaStreamTrack,\n stream: MediaStream,\n metadata: TrackInfo,\n ) {\n const participantId = metadata?.participant_id;\n\n if (!participantId || participantId === this.myId) {\n return;\n }\n\n const source = String(metadata.source || \"\")\n .trim()\n .toLowerCase();\n\n /* SCREEN SHARE\n */\n if (source === \"screen\" || source === \"screen_share\") {\n let screenStream = this.remoteScreenStreams.get(participantId);\n\n if (!screenStream) {\n screenStream = new MediaStream();\n this.remoteScreenStreams.set(participantId, screenStream);\n }\n\n for (const old of screenStream.getVideoTracks()) {\n if (old.id !== track.id) {\n screenStream.removeTrack(old);\n old.stop();\n }\n }\n\n if (!screenStream.getTracks().some((t) => t.id === track.id)) {\n screenStream.addTrack(track);\n }\n\n this.state.updateParticipantMedia(participantId, {\n screenStream,\n screenTrack: track,\n isScreenSharing: true,\n });\n\n this.events.onScreenShareStarted?.(participantId, screenStream);\n\n return;\n }\n\n let remoteStream = this.remoteStreams.get(participantId);\n\n if (!remoteStream) {\n remoteStream = new MediaStream();\n\n this.remoteStreams.set(participantId, remoteStream);\n }\n\n for (const old of remoteStream.getTracks()) {\n if (old.kind === track.kind && old.id !== track.id) {\n remoteStream.removeTrack(old);\n old.stop();\n }\n }\n\n if (!remoteStream.getTracks().some((t) => t.id === track.id)) {\n remoteStream.addTrack(track);\n }\n\n const current = this.state.getParticipant(participantId);\n\n this.state.updateParticipantMedia(participantId, {\n stream: remoteStream,\n cameraTrack: track.kind === \"video\" ? track : current?.media?.cameraTrack,\n audioTrack: track.kind === \"audio\" ? track : current?.media?.audioTrack,\n });\n\n if (track.kind === \"audio\") {\n this.activeSpeakerDetector.addTrack(participantId, track);\n }\n\n this.events.onTrack?.(remoteStream, participantId);\n\n track.onended = () => {\n if (track.kind === \"video\") {\n this.state.updateParticipantMedia(participantId, {\n camEnabled: false,\n stream: remoteStream,\n });\n\n return;\n }\n\n this.state.updateParticipantMedia(participantId, {\n micEnabled: false,\n stream: remoteStream,\n });\n };\n }\n\n // MEETING\n getMeeting(): {\n id: string | null;\n name: string | null;\n } {\n return this.room;\n }\n\n // ADMISSION CONTROL\n async approveJoinRequest(requestId: string) {\n if (!this.sfuClient) {\n throw new Error(\"SFU client is not connected\");\n }\n\n return this.sfuClient.approveJoinRequest(requestId);\n }\n\n async rejectJoinRequest(requestId: string, reason?: string) {\n if (!this.sfuClient) {\n throw new Error(\"SFU client is not connected\");\n }\n\n return this.sfuClient.rejectJoinRequest(requestId, reason);\n }\n\n async cancelJoinRequest(requestId?: string) {\n return this.sfuClient?.cancelJoinRequest(requestId);\n }\n\n async muteAllAudio() {\n if (!this.sfuClient) throw new Error(\"SFU client is not connected\");\n return this.sfuClient.muteAllAudio();\n }\n\n async muteParticipant(participantId: string) {\n if (!this.sfuClient) throw new Error(\"SFU client is not connected\");\n return this.sfuClient.muteParticipant(participantId);\n }\n\n async removeParticipant(participantId: string) {\n if (!this.sfuClient) throw new Error(\"SFU client is not connected\");\n return this.sfuClient.removeParticipant(participantId);\n }\n\n async getModerators(roomCode: string) {\n return this.sfuClient?.getModerators(roomCode);\n }\n\n async addModerator(roomCode: string, userId: string) {\n return this.sfuClient?.addModerator(roomCode, userId);\n }\n\n async removeModerator(roomCode: string, userId: string) {\n return this.sfuClient?.removeModerator(roomCode, userId);\n }\n\n // MEDIA CONTROL\n toggleMic() {\n const mediaState = this.state.localParticipant?.media;\n\n if (!mediaState || !this.localStream) {\n return;\n }\n\n const nextEnabled = !mediaState.micEnabled;\n\n this.localStream.getAudioTracks().forEach((track) => {\n track.enabled = nextEnabled;\n });\n\n this.state.updateLocalParticipant({\n id: this.myId,\n name: this.participantName,\n media: {\n micEnabled: nextEnabled,\n },\n });\n\n this.sfuClient?.muteAudio(!nextEnabled);\n this.events.onMicToggled?.(this.myId, nextEnabled);\n }\n\n toggleCam() {\n const mediaState = this.state.localParticipant?.media;\n\n if (!mediaState || !this.localStream) {\n return;\n }\n\n const nextEnabled = !mediaState.camEnabled;\n\n this.localStream.getVideoTracks().forEach((track) => {\n track.enabled = nextEnabled;\n });\n\n this.state.updateLocalParticipant({\n id: this.myId,\n name: this.participantName,\n media: {\n camEnabled: nextEnabled,\n },\n });\n\n this.sfuClient?.muteVideo(!nextEnabled);\n\n this.events.onCamToggled?.(this.myId, nextEnabled);\n }\n\n // SCREEN SHARING\n async startScreenShare() {\n try {\n if (!navigator.mediaDevices?.getDisplayMedia) {\n throw new Error(\"Screen sharing not supported on this device\");\n }\n\n if (!this.sfuClient) {\n throw new Error(\"Cannot share screen before joining the meeting\");\n }\n\n this.screenStream = await this.sfuClient.shareScreen();\n\n this.isScreenSharing = true;\n\n this.state.updateLocalParticipant({\n media: {\n isScreenSharing: true,\n screenStream: this.screenStream,\n screenTrack: this.screenStream?.getVideoTracks()[0],\n },\n });\n\n return this.screenStream;\n } catch (err: any) {\n this.emitError(\n \"SCREEN_SHARE_FAILED\",\n err?.message || \"Failed to start screen sharing\",\n err,\n true,\n );\n\n this.isScreenSharing = false;\n this.screenStream = null;\n\n throw err;\n }\n }\n\n async stopScreenShare() {\n if (!this.sfuClient) {\n return;\n }\n\n try {\n await this.sfuClient.stopScreenShare();\n } finally {\n this.screenStream = null;\n this.isScreenSharing = false;\n\n this.state.updateLocalParticipant({\n media: {\n isScreenSharing: false,\n screenStream: null,\n screenTrack: undefined,\n },\n });\n }\n }\n\n // RECORDING\n async startRecording() {\n if (!this.sfuClient) {\n throw new Error(\"SFU client is not connected\");\n }\n\n await this.sfuClient.startRecording();\n }\n\n async stopRecording() {\n if (!this.sfuClient) {\n throw new Error(\"SFU client is not connected\");\n }\n\n await this.sfuClient.stopRecording();\n }\n\n async getRecordingStatus(): Promise<{\n recording: RecordingInfo | null;\n }> {\n if (!this.sfuClient) {\n throw new Error(\"SFU client is not connected\");\n }\n\n return this.sfuClient.getRecordingStatus();\n }\n\n // CHAT\n\n sendChatMessage(payload: ChatInput) {\n if (!this.sfuClient) {\n console.warn(\"SFU Client not connected\");\n return;\n }\n\n const message = payload.message.trim();\n if (!message) return;\n\n this.sfuClient.sendChatMessage({\n message,\n reply_to: payload.reply_to ?? null,\n target: payload.target ?? null,\n });\n }\n\n sendReaction(reaction: string): void {\n if (!this.sfuClient) {\n console.warn(\"SFU Client not connected\");\n return;\n }\n this.sfuClient.sendReaction(reaction);\n }\n\n /**\n * Generic PubSub publishing entry point.\n *\n * The public SDK exposes one PubSub API for all topics. The current SFU\n * protocol still has dedicated wire messages for chat and reactions, so\n * this method is the compatibility bridge. The application does not need\n * to know about those wire-level message types.\n */\n publishPubSub<T extends PubSubTopic>(\n topic: T,\n data: PubSubTopicConfig[T][\"publish\"],\n ): void {\n switch (topic) {\n case \"SECURE_CHAT\":\n this.sendChatMessage(data as ChatInput);\n return;\n\n case \"REACTION\":\n this.sendReaction((data as { emoji: string }).emoji);\n return;\n\n default: {\n const exhaustive: never = topic;\n throw new Error(`Unsupported PubSub topic: ${exhaustive}`);\n }\n }\n }\n\n async startLiveTranscription(): Promise<void> {\n if (!this.sfuClient) {\n throw new Error(\"SFU client is not connected\");\n }\n\n const audioTrack = this.localStream?.getAudioTracks()[0];\n if (!audioTrack || audioTrack.readyState !== \"live\") {\n throw new Error(\"Microphone audio track is not available\");\n }\n\n await this.sfuClient.startLiveTranscription();\n }\n\n stopLiveTranscription(): void {\n this.sfuClient?.stopLiveTranscription();\n }\n\n isLiveTranscriptionActive(): boolean {\n return this.sfuClient?.isLiveTranscriptionActive() ?? false;\n }\n\n getNetworkQuality(): NetworkQuality | null {\n return this.state.networkQuality;\n }\n\n // CLEANUP\n private cleanupRemoteParticipant(participantId: string) {\n this.activeSpeakerDetector.removeParticipant(participantId);\n\n const stream = this.remoteStreams.get(participantId);\n\n stream?.getTracks().forEach((track) => track.stop());\n\n this.remoteStreams.delete(participantId);\n\n const screen = this.remoteScreenStreams.get(participantId);\n\n screen?.getTracks().forEach((track) => track.stop());\n\n this.remoteScreenStreams.delete(participantId);\n }\n\n // DISCONNECT\n async disconnect(): Promise<void> {\n if (this.disconnectPromise) {\n return this.disconnectPromise;\n }\n\n this.disconnectPromise = this.performDisconnect();\n\n try {\n await this.disconnectPromise;\n } finally {\n this.disconnectPromise = null;\n }\n }\n\n private async performDisconnect() {\n this.intentionalDisconnect = true;\n this.joinPromise = null;\n\n if (this.sfuClient) {\n await this.sfuClient.leave();\n }\n\n // LOCAL MEDIA\n if (this.localStream) {\n this.localStream.getTracks().forEach((track) => track.stop());\n\n this.localStream = null;\n }\n\n if (this.screenStream) {\n this.screenStream.getTracks().forEach((track) => track.stop());\n this.screenStream = null;\n }\n\n this.isScreenSharing = false;\n\n // REMOTE MEDIA\n for (const stream of this.remoteStreams.values()) {\n stream.getTracks().forEach((track) => track.stop());\n }\n\n this.remoteStreams.clear();\n for (const stream of this.remoteScreenStreams.values()) {\n stream.getTracks().forEach((track) => track.stop());\n }\n\n this.remoteScreenStreams.clear();\n this.room.id = null;\n this.room.name = null;\n\n this.state.localParticipant = null;\n this.state.clearLiveTranscripts();\n this.state.setNetworkQuality(null);\n\n this.state.notify(\"localParticipant\");\n\n this.state.resetRemoteState();\n this.events.onMeetingLeft?.();\n }\n}\n","import { useEffect, useState } from \"react\";\nimport { StateScope } from \"../types/meeting\";\nimport { MeetingState } from \"../core/MeetingState\";\n\nexport function useMeetingStore<T>(\n stateManager: MeetingState,\n scope: StateScope,\n selector: (state: MeetingState) => T,\n): T {\n const [state, setState] = useState(() => selector(stateManager));\n\n useEffect(() => {\n // Update local react state whenever the SDK notifies this scope\n const unsubscribe = stateManager.subscribe(scope, () => {\n setState(selector(stateManager));\n });\n\n return unsubscribe;\n }, [stateManager, scope, selector]);\n\n return state;\n}\n","import { useEffect } from \"react\";\nimport { useMeetingContext } from \"./MeetingProvider\";\nimport {\n SFUConnectionState,\n LiveTranscript,\n NetworkQuality,\n} from \"../types/meeting\";\n\nexport const useMeeting = (handlers?: {\n onError?: (err: any) => void;\n onEntryRequested?: (req: any) => void;\n onEntryResponded?: (payload: any, decision?: any) => void;\n onJoinRequestCanceled?: (requestId: string) => void;\n onParticipantRemoved?: (participantId: string, removedBy: string) => void;\n onParticipantPermissionsChanged?: (\n participantId: string,\n permissions: any,\n ) => void;\n onMeetingLeft?: () => void;\n onTrackStateChanged?: (track: any) => void;\n onRecordingStarted?: (recording: any) => void;\n onRecordingStopped?: (recording: any) => void;\n onReaction?: (reaction: any) => void;\n onActiveSpeakersChanged?: (participantIds: string[]) => void;\n onConnectionStateChanged?: (state: SFUConnectionState) => void;\n onLiveTranscript?: (transcript: LiveTranscript) => void;\n onNetworkQuality?: (quality: NetworkQuality) => void;\n}) => {\n const ctx = useMeetingContext();\n\n // Error Handler\n useEffect(() => {\n if (!handlers?.onError) return;\n return ctx.onError(handlers.onError);\n }, [handlers?.onError]);\n\n useEffect(() => {\n if (!handlers?.onActiveSpeakersChanged) return;\n\n return ctx.onActiveSpeakersChanged(handlers.onActiveSpeakersChanged);\n }, [handlers?.onActiveSpeakersChanged]);\n\n // Entry Request Handler\n useEffect(() => {\n if (!handlers?.onEntryRequested) return;\n return ctx.onEntryRequested(handlers.onEntryRequested);\n }, [handlers?.onEntryRequested]);\n\n // Entry Response Handler\n useEffect(() => {\n if (!handlers?.onEntryResponded) return;\n return ctx.onEntryResponded(handlers.onEntryResponded);\n }, [handlers?.onEntryResponded]);\n\n useEffect(() => {\n if (!handlers?.onJoinRequestCanceled) return;\n return ctx.onJoinRequestCanceled(handlers.onJoinRequestCanceled);\n }, [handlers?.onJoinRequestCanceled]);\n\n useEffect(() => {\n if (!handlers?.onParticipantRemoved) return;\n return ctx.onParticipantRemoved(handlers.onParticipantRemoved);\n }, [handlers?.onParticipantRemoved]);\n\n useEffect(() => {\n if (!handlers?.onParticipantPermissionsChanged) return;\n return ctx.onParticipantPermissionsChanged(\n handlers.onParticipantPermissionsChanged,\n );\n }, [handlers?.onParticipantPermissionsChanged]);\n\n // Meeting Left Handler\n useEffect(() => {\n if (!handlers?.onMeetingLeft) return;\n return ctx.onMeetingLeft(handlers.onMeetingLeft);\n }, [handlers?.onMeetingLeft]);\n\n useEffect(() => {\n if (!handlers?.onTrackStateChanged) return;\n return ctx.onTrackStateChanged(handlers.onTrackStateChanged);\n }, [handlers?.onTrackStateChanged]);\n\n useEffect(() => {\n if (!handlers?.onRecordingStarted) return;\n return ctx.onRecordingStarted(handlers.onRecordingStarted);\n }, [handlers?.onRecordingStarted]);\n\n useEffect(() => {\n if (!handlers?.onRecordingStopped) return;\n return ctx.onRecordingStopped(handlers.onRecordingStopped);\n }, [handlers?.onRecordingStopped]);\n\n useEffect(() => {\n if (!handlers?.onConnectionStateChanged) return;\n\n return ctx.onConnectionStateChanged(handlers.onConnectionStateChanged);\n }, [handlers?.onConnectionStateChanged]);\n\n useEffect(() => {\n if (!handlers?.onLiveTranscript) return;\n return ctx.onLiveTranscript(handlers.onLiveTranscript);\n }, [handlers?.onLiveTranscript]);\n\n useEffect(() => {\n if (!handlers?.onNetworkQuality) return;\n return ctx.onNetworkQuality(handlers.onNetworkQuality);\n }, [handlers?.onNetworkQuality]);\n\n useEffect(() => {\n if (!handlers?.onReaction) return;\n return ctx.onReaction(handlers.onReaction);\n }, [handlers?.onReaction]);\n\n const { sdk: _, ...publicApi } = ctx;\n return publicApi;\n};\n","import { useEffect, useState } from \"react\";\nimport { useMeetingContext } from \"./MeetingProvider\";\nimport { Participant } from \"../types/meeting\";\n\nexport const useParticipants = () => {\n const { sdk } = useMeetingContext();\n\n const [participants, setParticipants] = useState<Participant[]>(() =>\n sdk.state.getParticipants(),\n );\n\n useEffect(() => {\n const update = () => {\n setParticipants(sdk.state.getParticipants());\n };\n\n update();\n\n const unsub = sdk.state.subscribe(\"participants\", update);\n\n return unsub;\n }, [sdk]);\n\n return participants;\n};\n","import { useEffect, useRef, useState } from \"react\";\nimport { useMeetingContext } from \"./MeetingProvider\";\nimport { Participant } from \"../types/meeting\";\n\nexport const useRemoteMedia = (participantId: string) => {\n const { sdk } = useMeetingContext();\n const videoRef = useRef<HTMLVideoElement | null>(null);\n const audioRef = useRef<HTMLAudioElement | null>(null);\n\n const [participant, setParticipant] = useState<Participant | null>(\n () => sdk.state.getParticipant(participantId) || null,\n );\n\n useEffect(() => {\n const unsub = sdk.state.subscribe(`participant:${participantId}`, () => {\n const p = sdk.state.getParticipant(participantId);\n setParticipant(p ? { ...p } : null);\n });\n\n return unsub;\n }, [participantId, sdk]);\n\n useEffect(() => {\n const stream = participant?.media?.stream;\n if (!stream) return;\n\n // VIDEO\n if (videoRef.current) {\n videoRef.current.srcObject = stream;\n videoRef.current.muted = true;\n videoRef.current.playsInline = true;\n videoRef.current.play().catch(() => {});\n }\n\n // AUDIO\n if (audioRef.current) {\n audioRef.current.srcObject = stream;\n audioRef.current.play().catch(() => {});\n }\n }, [participant?.media?.stream]);\n\n return {\n videoRef,\n audioRef,\n isCamActive: !!participant?.media?.camEnabled,\n isMicEnabled: !!participant?.media?.micEnabled,\n connectionState: participant?.connectionState,\n };\n};\n","import { useEffect, useState } from \"react\";\nimport { SDK_CONFIG } from \"../config/ws\";\n\ntype LiveRoomState = {\n active: boolean;\n count: number;\n canJoin: boolean;\n approved: boolean;\n isHost: boolean;\n hasMoreParticipants: boolean;\n participants: {\n id: string;\n name: string;\n isHost: boolean;\n isPresenter: boolean;\n micEnabled: boolean;\n camEnabled: boolean;\n }[];\n room?: {\n id: string;\n name: string;\n room_code: string;\n capacity: number;\n is_private: boolean;\n };\n};\n\n/**\n * Current SFU does not expose the old `/watch/:room` mesh presence socket.\n * Preview therefore uses the authoritative REST room endpoint and polls it.\n * Live participant/media state begins after JOIN over the SFU WebSocket.\n */\nexport function useMeetingPreview(roomId: string, participantId: string) {\n const [room, setRoom] = useState<LiveRoomState | null>(null);\n const [error, setError] = useState<string | null>(null);\n const [isConnected, setIsConnected] = useState(false);\n const [isLoading, setIsLoading] = useState(true);\n\n useEffect(() => {\n if (!roomId) {\n setIsLoading(false);\n return;\n }\n\n let stopped = false;\n let timer: ReturnType<typeof setTimeout> | null = null;\n\n const load = async () => {\n try {\n const response = await fetch(\n `${SDK_CONFIG.apiBase}/rooms/${encodeURIComponent(roomId)}`,\n );\n\n if (!response.ok) {\n throw new Error(`Room lookup failed (${response.status})`);\n }\n\n const data = await response.json();\n if (stopped) return;\n\n setRoom({\n active: true,\n // The current REST room model intentionally does not expose a live\n // participant count. Do not fabricate one.\n count: 0,\n canJoin: !data.is_private,\n approved: false,\n isHost: false,\n hasMoreParticipants: false,\n participants: [],\n room: {\n id: data.id,\n name: data.name,\n room_code: data.room_code,\n capacity: data.capacity,\n is_private: data.is_private,\n },\n });\n setError(null);\n setIsConnected(true);\n setIsLoading(false);\n } catch (err: any) {\n if (stopped) return;\n setError(err?.message || \"Failed to load room\");\n setIsConnected(false);\n setIsLoading(false);\n } finally {\n if (!stopped) {\n timer = setTimeout(load, 5000);\n }\n }\n };\n\n void load();\n\n return () => {\n stopped = true;\n if (timer) clearTimeout(timer);\n };\n }, [roomId, participantId]);\n\n return {\n room,\n isConnected,\n isLoading,\n error,\n };\n}\n","import { useMeetingStore } from \"./useMeetingStore\";\nimport { useMeetingContext } from \"./MeetingProvider\";\n\nexport const useLiveTranscript = () => {\n const { sdk } = useMeetingContext();\n\n return useMeetingStore(sdk.state, \"transcript\", (state) =>\n state.getLiveTranscripts(),\n );\n};\n","import { useMeetingStore } from \"./useMeetingStore\";\nimport { useMeetingContext } from \"./MeetingProvider\";\n\nexport const useNetworkQuality = () => {\n const { sdk } = useMeetingContext();\n\n return useMeetingStore(\n sdk.state,\n \"networkQuality\",\n (state) => state.networkQuality,\n );\n};\n","import { useEffect } from \"react\";\nimport {\n PubSubMessage,\n PubSubTopic,\n PubSubTopicConfig,\n PubSubHandleForTopic,\n} from \"../types/meeting\";\nimport { useMeetingContext } from \"./MeetingProvider\";\n\nexport function usePubSub<T extends PubSubTopic>(\n topic: T,\n options?: {\n onMessageReceived?: (\n message: PubSubMessage<PubSubTopicConfig[T][\"message\"]>,\n ) => void;\n },\n): PubSubHandleForTopic<T> {\n const ctx = useMeetingContext();\n\n useEffect(() => {\n if (!options?.onMessageReceived) return;\n\n return ctx.onPubSubMessage<T>(\n topic,\n options.onMessageReceived,\n );\n }, [ctx, topic, options?.onMessageReceived]);\n\n return ctx.usePubSub<T>(topic);\n}\n"],"mappings":"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","names":["useEffect","useRef","useState","useState","message","useState","recording","useState","useEffect","useRef","useEffect","useEffect","useEffect","useState","useState","useEffect","useEffect","useRef","useState","useRef","useState","useEffect","useEffect","useState","useState","useEffect","useEffect","useEffect"]}
|