@afosecure/meetingsdk 1.4.2 → 1.4.3

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 CHANGED
@@ -1353,7 +1353,7 @@ var useRemoteMedia = (participantId) => {
1353
1353
  };
1354
1354
  };
1355
1355
 
1356
- // src/react/useMeetingPreview.tsx
1356
+ // src/react/useMeetingPreview.ts
1357
1357
  var import_react7 = require("react");
1358
1358
  function useMeetingPreview(roomId, userId) {
1359
1359
  const [room, setRoom] = (0, import_react7.useState)(null);
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/react/useLocalParticipant.tsx","../src/react/MeetingProvider.tsx","../src/config/ws.ts","../src/core/MeetingState.ts","../src/core/VideoCore.ts","../src/react/useMeetingStore.ts","../src/react/useMeeting.ts","../src/react/useParticipants.ts","../src/react/useRemoteMedia.ts","../src/react/useMeetingPreview.tsx"],"sourcesContent":["export { useLocalParticipant } from \"./react/useLocalParticipant\";\n\n// Core exports\nexport { VideoSDKCore } from \"./core/VideoCore\";\nexport { MeetingState } from \"./core/MeetingState\";\nexport type { Participant, ChatInput } from \"./types/meeting\";\n\n// React hooks and components\nexport { MeetingProvider, useMeetingContext } from \"./react/MeetingProvider\";\nexport { useMeeting } from \"./react/useMeeting\";\nexport { useParticipants } from \"./react/useParticipants\";\nexport { useRemoteMedia } from \"./react/useRemoteMedia\";\nexport { useMeetingPreview } from \"./react/useMeetingPreview\";\n","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, { createContext, useContext, useMemo, useRef } from \"react\";\nimport { VideoSDKCore } from \"../core/VideoCore\";\nimport {\n ChatInput,\n ChatMessage,\n MeetingConfig,\n Participant,\n PubSubTopic,\n} from \"../types/meeting\";\nimport { useMeetingStore } from \"./useMeetingStore\";\n\ntype PubSubHandle = {\n messages: ChatMessage[];\n publish: (input: ChatInput) => void;\n};\n\ntype MeetingContextValue = {\n sdk: VideoSDKCore;\n join: (config?: MeetingConfig) => Promise<void>;\n leave: () => void;\n\n toggleMic: () => void;\n toggleCam: () => void;\n\n startScreenShare: () => Promise<MediaStream>;\n stopScreenShare: () => void;\n\n sendMessage: (input: ChatInput) => void;\n\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 usePubSub: (topic: PubSubTopic) => PubSubHandle;\n approveJoinRequest: (requestId: string) => void;\n rejectJoinRequest: (requestId: string) => void;\n onError: (cb: (err: any) => void) => () => void;\n onEntryRequested: (cb: (req: any) => void) => () => void;\n onEntryResponded: (cb: (payload: any, decision?: any) => void) => () => void;\n onMeetingLeft: (cb: () => 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 meetingLeftListeners = useRef(new Set<() => void>());\n\n if (!sdkRef.current) {\n sdkRef.current = new VideoSDKCore({\n onError: (err) => errorListeners.current.forEach((fn) => fn(err)),\n onEntryRequested: (req) =>\n entryRequestListeners.current.forEach((fn) => fn(req)),\n onEntryResponded: (p, d) =>\n entryResponseListeners.current.forEach((fn) => fn(p, d)),\n onMeetingLeft: () => meetingLeftListeners.current.forEach((fn) => fn()),\n });\n }\n\n const sdk = sdkRef.current;\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\n const value = useMemo<MeetingContextValue>(() => {\n if (!sdkRef.current) {\n sdkRef.current = new VideoSDKCore({\n onError: (err) => {\n errorListeners.current.forEach((fn) => fn(err));\n },\n });\n }\n\n return {\n sdk,\n\n join: (joinConfig?: MeetingConfig) =>\n sdk.joinMeeting({\n ...config,\n ...joinConfig,\n }),\n leave: () => sdk.disconnect(),\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\n room: sdk.getMeeting(),\n localParticipant,\n participants,\n messages,\n presenterId,\n usePubSub: (topic: PubSubTopic) => {\n if (topic !== \"SECURE_CHAT\") {\n throw new Error(`Unsupported PubSub argument: \"${topic}\"`);\n }\n return {\n messages: sdk.state.getChatMessages(),\n publish: sdk.sendChatMessage.bind(sdk),\n };\n },\n approveJoinRequest: sdk.approveJoinRequest.bind(sdk),\n rejectJoinRequest: sdk.rejectJoinRequest.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 onMeetingLeft: (cb: () => void) => {\n meetingLeftListeners.current.add(cb);\n return () => {\n meetingLeftListeners.current.delete(cb);\n };\n },\n };\n }, [config, sdk, localParticipant, participants, messages, presenterId]);\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","export const SDK_CONFIG = {\n wsUrl: \"wss://rust-video-server-sfyf.onrender.com/ws\",\n baseUrl: \"https://rust-video-server-sfyf.onrender.com\",\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 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\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 // ---- 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: true,\n camEnabled: true,\n 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 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 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.notify(\"participants\");\n this.notify(\"chat\");\n this.notify(\"presenter\");\n }\n}\n","import { SDK_CONFIG } from \"../config/ws\";\nimport {\n ChatInput,\n ChatMessage,\n Events,\n MeetingConfig,\n Participant,\n SDKError,\n} from \"../types/meeting\";\nimport { MeetingState } from \"./MeetingState\";\n\nexport class VideoSDKCore {\n private ws: WebSocket | null = null;\n private peers: Record<string, RTCPeerConnection> = {};\n private initiators = new Set<string>();\n private lastPong = Date.now();\n private iceServers: RTCIceServer[] = [];\n private intentionalDisconnect = false;\n\n private myId: string;\n private room: { id: string | null; name: string | null } = {\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 screenSenders: Record<string, RTCRtpSender[]> = {};\n\n private pingInterval: any = null;\n private pendingIceCandidates: Record<string, RTCIceCandidateInit[]> = {};\n private pendingOffers: Record<string, string> = {};\n private reconnectAttempts = 0;\n private reconnectTimer?: number;\n private participantName = \"\";\n public readonly state: MeetingState;\n private joinResolver?: () => void;\n private joinRejecter?: (e: any) => void;\n\n // Track if we're in the waiting room (pending approval)\n private isWaitingForApproval = false;\n private pendingRequestId: string | null = null;\n private iceTransportPolicy: RTCIceTransportPolicy = \"all\";\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 userId: this.myId,\n recoverable,\n };\n\n this.events.onError?.(err);\n\n this.joinRejecter?.(err);\n this.joinRejecter = undefined;\n\n console.error(\"[MeetingSDK Error]\", err);\n }\n\n constructor(\n private events: Events = {},\n private url: string = SDK_CONFIG.wsUrl,\n ) {\n this.state = new MeetingState();\n this.events = events;\n this.url = url;\n\n this.myId = localStorage.getItem(\"vsdk_id\") || crypto.randomUUID();\n\n localStorage.setItem(\"vsdk_id\", this.myId);\n }\n\n // ---------------- STREAM ----------------\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 // Verify tracks are actually live BEFORE connecting\n const hasVideo = this.localStream\n .getVideoTracks()\n .some((t) => t.readyState === \"live\");\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 this.state.updateLocalParticipant({\n id: this.myId,\n name: this.participantName,\n media: {\n stream: this.localStream,\n micEnabled: true,\n camEnabled: true,\n isScreenSharing: false,\n },\n });\n\n this.state.localStream = this.localStream;\n } catch (err: any) {\n this.emitError(\"GET_USER_MEDIA_FAILED\", err?.message, err, false);\n throw err;\n }\n }\n\n // ---------------- CONNECT ----------------\n async connect(roomId: string, name: string) {\n this.room.id = roomId;\n\n this.reset();\n\n return new Promise<void>((resolve, reject) => {\n this.joinResolver = resolve;\n this.joinRejecter = reject;\n this.ws = new WebSocket(this.url);\n\n this.ws.onopen = () => {\n console.log(\"WebSocket connected, sending JOIN...\");\n this.send({\n type: \"JOIN\",\n room_id: roomId,\n user_id: this.myId,\n sender_name: name,\n camera_stream_id: this.localStream?.id.replace(/[{}]/g, \"\"),\n audio_muted: this.state.localParticipant?.media?.micEnabled,\n video_muted: this.state.localParticipant?.media?.camEnabled,\n });\n };\n\n this.ws.onerror = (err) => {\n this.emitError(\"WS_ERROR\", \"WebSocket encountered an error\", err, true);\n };\n\n this.ws.onclose = (e) => {\n this.joinRejecter?.({\n code: \"WS_CLOSED\",\n message: \"Connection closed before join completed\",\n raw: e,\n });\n\n this.joinRejecter = undefined;\n\n if (this.intentionalDisconnect) {\n return; // do NOT reconnect\n }\n\n if (e.code === 1000 || e.code === 1001) {\n return;\n }\n\n // Don't auto-reconnect if waiting for approval (user must reconnect after approval)\n if (this.isWaitingForApproval) {\n return;\n }\n\n this.scheduleReconnect();\n };\n\n this.ws.onmessage = async (e) => {\n await this.handle(JSON.parse(e.data));\n };\n });\n }\n\n async joinMeeting(config: MeetingConfig) {\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 this.participantName = name;\n\n // Reuse existing stream if initLocal already configured it\n if (!this.localStream) {\n this.localStream = await navigator.mediaDevices.getUserMedia({\n video: true,\n audio: true,\n });\n }\n\n this.localStream.getAudioTracks().forEach((t) => {\n t.enabled = !audioMuted;\n });\n this.localStream.getVideoTracks().forEach((t) => {\n t.enabled = !videoMuted;\n });\n\n this.state.updateLocalParticipant({\n id: this.myId,\n name: this.participantName,\n media: {\n stream: this.localStream,\n micEnabled: !audioMuted,\n camEnabled: !videoMuted,\n isScreenSharing: false,\n },\n });\n\n this.state.localStream = this.localStream;\n\n await this.connect(roomId, name);\n }\n\n getMeeting(): { id: string | null; name: string | null } {\n return this.room;\n }\n\n toggleMic() {\n const mediaState = this.state.localParticipant?.media;\n if (!mediaState) return;\n\n const nextEnabled = !mediaState.micEnabled;\n\n this.localStream\n ?.getAudioTracks()\n .forEach((t) => (t.enabled = nextEnabled));\n\n // Update state layer\n this.state.updateLocalParticipant({\n id: this.myId,\n name: this.participantName,\n media: {\n ...mediaState,\n micEnabled: nextEnabled,\n },\n });\n\n // Notify peers\n this.send({\n type: \"MEDIA_STATE\",\n kind: \"audio\",\n enabled: nextEnabled,\n });\n }\n\n toggleCam() {\n const mediaState = this.state.localParticipant?.media;\n if (!mediaState) return;\n\n const nextEnabled = !mediaState.camEnabled;\n\n this.localStream\n ?.getVideoTracks()\n .forEach((t) => (t.enabled = nextEnabled));\n\n // Update state layer\n this.state.updateLocalParticipant({\n id: this.myId,\n name: this.participantName,\n media: {\n ...mediaState,\n camEnabled: nextEnabled,\n },\n });\n\n // Notify peers\n this.send({\n type: \"MEDIA_STATE\",\n kind: \"video\",\n enabled: nextEnabled,\n });\n }\n\n private scheduleReconnect() {\n if (!this.room.id) return;\n\n const delay = Math.min(1000 * Math.pow(2, this.reconnectAttempts), 30000);\n\n clearTimeout(this.reconnectTimer);\n\n this.reconnectTimer = window.setTimeout(async () => {\n try {\n await this.connect(this.room.id!, this.participantName);\n\n this.reconnectAttempts = 0;\n } catch {\n this.reconnectAttempts++;\n this.scheduleReconnect();\n }\n }, delay);\n }\n\n private startHeartbeat() {\n this.stopHeartbeat();\n\n this.pingInterval = setInterval(() => {\n if (!this.ws || this.ws.readyState !== WebSocket.OPEN) return;\n\n this.send({\n type: \"PING\",\n client_ts: Date.now(),\n });\n }, 20000); // every 20s\n }\n private stopHeartbeat() {\n if (this.pingInterval) {\n clearInterval(this.pingInterval);\n this.pingInterval = null;\n }\n }\n\n // ---------------- RESET ----------------\n private reset() {\n Object.values(this.peers).forEach((pc) => pc.close());\n\n this.peers = {};\n this.initiators.clear();\n this.pendingIceCandidates = {};\n\n this.state.resetRemoteState();\n }\n\n private async handleJoinApproved(msg: any) {\n console.log(\"JOIN_APPROVED received, sending new JOIN...\");\n\n this.events.onEntryResponded?.({\n participantId: msg.user_id,\n decision: \"approved\",\n });\n\n this.isWaitingForApproval = false;\n this.pendingRequestId = null;\n\n // Send JOIN again on SAME socket\n if (this.ws && this.ws.readyState === WebSocket.OPEN) {\n this.send({\n type: \"JOIN\",\n room_id: this.room.id,\n user_id: this.myId,\n sender_name: this.participantName,\n });\n console.log(\"Sent new JOIN after approval\");\n }\n }\n\n private async handle(msg: any) {\n if (msg.sender === this.myId) return;\n\n switch (msg.type) {\n case \"PONG\":\n this.lastPong = Date.now();\n break;\n case \"OFFER\":\n console.log(\"[Offer] Received from\", msg.sender, {\n sdp: msg.payload.substring(0, 200),\n });\n await this.handleOffer(msg.payload, msg.sender);\n break;\n\n case \"ANSWER\": {\n const pc = this.peers[msg.sender];\n console.log(\"[Answer] Received from\", msg.sender, {\n signalingState: pc?.signalingState,\n iceConnectionState: pc?.iceConnectionState,\n connectionState: pc?.connectionState,\n });\n\n if (!pc) return;\n\n if (pc.signalingState !== \"have-local-offer\") {\n console.warn(\n `[Signaling] Unexpected ANSWER in state \"${pc.signalingState}\", ignoring`,\n );\n return;\n }\n\n try {\n await pc.setRemoteDescription({\n type: \"answer\",\n sdp: msg.payload,\n });\n\n await this.flushIce(msg.sender, pc);\n } catch (err) {\n console.error(\"[Signaling] Failed to apply answer:\", err);\n this.emitError(\n \"ANSWER_FAILED\",\n `Failed to apply answer from ${msg.sender}`,\n err,\n true,\n );\n }\n break;\n }\n case \"ICE\": {\n const candidate = JSON.parse(msg.payload);\n\n let pc = this.peers[msg.sender];\n\n if (!pc) {\n this.pendingIceCandidates[msg.sender] ??= [];\n this.pendingIceCandidates[msg.sender].push(candidate);\n break;\n }\n\n if (!pc.remoteDescription) {\n this.pendingIceCandidates[msg.sender] ??= [];\n this.pendingIceCandidates[msg.sender].push(candidate);\n break;\n }\n\n try {\n await pc.addIceCandidate(candidate);\n } catch (err) {\n console.warn(\"ICE error:\", err);\n }\n\n break;\n }\n case \"EXISTING_USERS\":\n if (msg.presenterId) {\n this.state.setPresenterId(msg.presenterId);\n\n this.events.onScreenShareStarted?.(msg.presenterId, null!);\n this.state.setPresenterId(msg.presenterId);\n }\n\n for (const p of msg.participants || []) {\n if (!p?.id || p.id === this.myId) continue;\n const structuredParticipant: Participant = {\n id: p.id,\n name: p.name,\n isHost: p.isHost,\n isPresenter: p.isPresenter,\n media: {\n stream: null,\n screenStream: undefined,\n cameraTrack: undefined,\n screenTrack: undefined,\n audioTrack: undefined,\n micEnabled: p.micEnabled ?? true,\n camEnabled: p.camEnabled ?? true,\n isScreenSharing: p.isScreenSharing ?? false,\n remoteScreenStreamId: p.remoteScreenStreamId || undefined,\n cameraStreamId: p.cameraId || undefined,\n },\n };\n this.state.addParticipant(structuredParticipant);\n this.events.onUserJoined?.(structuredParticipant);\n\n if (p.isScreenSharing && p.remoteScreenStreamId) {\n this.state.setPresenterId(p.id);\n this.state.updateParticipantMedia(p.id, {\n isScreenSharing: true,\n remoteScreenStreamId: p.remoteScreenStreamId,\n cameraStreamId: p.cameraId || null,\n });\n }\n if (this.shouldInitiate(p.id)) {\n await this.createOffer(p.id);\n }\n }\n break;\n\n case \"JOINED\": {\n if (msg.iceServers) {\n this.iceServers = msg.iceServers;\n }\n this.room.name = msg.room_name;\n\n this.isWaitingForApproval = false;\n this.pendingRequestId = null;\n this.intentionalDisconnect = false;\n this.reconnectAttempts = 0;\n\n // Process any OFFERs that arrived before JOINED\n if (Object.keys(this.pendingOffers).length > 0) {\n console.log(\n \"Processing\",\n Object.keys(this.pendingOffers).length,\n \"pending offers\",\n );\n for (const [peerId, sdp] of Object.entries(this.pendingOffers)) {\n await this.handleOffer(sdp, peerId);\n }\n this.pendingOffers = {};\n }\n\n const media = this.state.localParticipant?.media;\n\n if (media) {\n this.send({\n type: \"MEDIA_STATE\",\n kind: \"audio\",\n enabled: !!media.micEnabled,\n });\n\n this.send({\n type: \"MEDIA_STATE\",\n kind: \"video\",\n enabled: !!media.camEnabled,\n });\n }\n this.startHeartbeat();\n this.joinResolver?.();\n this.joinResolver = undefined;\n this.joinRejecter = undefined;\n break;\n }\n case \"USER_JOINED\": {\n const p = msg.participant;\n\n if (!p?.id || p.id === this.myId) return;\n\n this.state.addParticipant(p);\n\n this.events.onUserJoined?.(p);\n if (this.shouldInitiate(p.id)) {\n await this.createOffer(p.id);\n }\n\n break;\n }\n\n case \"JOIN_PENDING\": {\n const req = msg.request;\n\n this.isWaitingForApproval = true;\n this.pendingRequestId = req.request_id;\n\n this.events.onEntryRequested?.({\n requestId: req.request_id,\n userId: req.user_id,\n name: req.name,\n });\n\n break;\n }\n\n case \"JOIN_REQUEST\": {\n const req = msg.request;\n this.events.onEntryRequested?.({\n requestId: req.id,\n userId: req.user_id,\n name: req.name,\n });\n\n break;\n }\n\n case \"JOIN_APPROVED\": {\n await this.handleJoinApproved(msg);\n break;\n }\n\n case \"JOIN_REJECTED\": {\n const decision = \"rejected\";\n\n this.isWaitingForApproval = false;\n this.pendingRequestId = null;\n\n this.events.onEntryResponded?.({\n participantId: msg.user_id,\n decision,\n });\n\n break;\n }\n\n case \"USER_LEFT\":\n const peerId = msg.participant.id;\n this.closePeer(peerId);\n\n this.state.removeParticipant(peerId);\n\n this.events.onUserLeft?.(peerId);\n\n break;\n\n case \"MEDIA_STATE_CHANGE\": {\n const peerId = msg.peerId;\n const { kind, enabled } = msg;\n\n if (kind === \"audio\") {\n this.state.updateParticipantMedia(peerId, { micEnabled: enabled });\n this.events.onMicToggled?.(peerId, enabled);\n } else if (kind === \"video\") {\n this.state.updateParticipantMedia(peerId, { camEnabled: enabled });\n this.events.onCamToggled?.(peerId, enabled);\n }\n\n break;\n }\n\n case \"CHAT_MESSAGE\": {\n const newMsg = msg.data;\n\n if (newMsg.sender_id === this.myId) break; // already added optimistically\n this.state.addChatMessage({\n id: newMsg.id,\n text: newMsg.message,\n sender_id: newMsg.sender_id,\n sender_name: newMsg.sender_name,\n timestamp: new Date(newMsg.timestamp).getTime(),\n target: newMsg.target,\n });\n\n this.events.onChatMessage?.(msg);\n break;\n }\n case \"SCREEN_SHARE_START\": {\n const peerId = msg.peerId;\n\n this.state.updateParticipantMedia(peerId, {\n isScreenSharing: true,\n remoteScreenStreamId: msg.stream_id,\n cameraStreamId: msg?.camera_stream_id,\n });\n\n if (!this.state.presenterId) {\n this.state.setPresenterId(peerId);\n }\n\n const screenStream =\n this.state.getParticipant(peerId)?.media?.screenStream;\n\n this.events.onScreenShareStarted?.(peerId, screenStream || null!);\n break;\n }\n\n case \"SCREEN_SHARE_STOP\": {\n const peerId = msg.peerId;\n this.state.updateParticipantMedia(peerId, { isScreenSharing: false });\n if (this.state.presenterId === peerId) {\n this.state.setPresenterId(null);\n }\n this.events.onScreenShareStopped?.(peerId);\n break;\n }\n case \"ERROR\": {\n const fatal = msg?.fatal === true;\n\n this.emitError(\n \"WS_ERROR\",\n msg?.message || \"Unknown error\",\n msg,\n !fatal,\n );\n\n if (fatal) {\n this.disconnect();\n }\n\n return;\n }\n }\n }\n\n // ---------------- PEER ----------------\n private createPeer(id: string) {\n if (!this.localStream) throw new Error(\"No local stream\");\n if (!this.iceServers || this.iceServers.length === 0) {\n throw new Error(\n \"ICE Servers not configured. Backend must provide iceServers on JOIN.\",\n );\n }\n\n const pc = new RTCPeerConnection({\n iceServers: this.iceServers,\n iceTransportPolicy: this.iceTransportPolicy,\n });\n\n pc.ontrack = (event) => {\n const incomingStream =\n event.streams?.[0] || new MediaStream([event.track]);\n const streamId = incomingStream?.id?.replace(/[{}]/g, \"\");\n\n const participant = this.state.getParticipant(id);\n\n const isCameraStream =\n streamId &&\n participant?.media?.cameraStreamId &&\n streamId === participant?.media?.cameraStreamId;\n\n const isScreenStream =\n streamId &&\n participant?.media?.remoteScreenStreamId &&\n streamId === participant?.media?.remoteScreenStreamId;\n\n if (event.track.muted) {\n event.track.onunmute = () => {\n console.log(`${event.track.kind} track unmuted for ${id}`);\n };\n }\n\n if (isScreenStream) {\n const videoTrack =\n event.track.kind === \"video\"\n ? event.track\n : incomingStream.getVideoTracks()[0] ||\n participant?.media?.screenTrack;\n\n this.state.updateParticipantMedia(id, {\n screenStream: incomingStream,\n screenTrack: videoTrack,\n remoteScreenStreamId: incomingStream.id,\n isScreenSharing: true,\n });\n\n if (!this.state.presenterId) {\n this.state.setPresenterId(id);\n }\n\n this.events.onScreenShareStarted?.(id, incomingStream);\n console.log(`Screen share stream detected for ${id}`);\n } else if (isCameraStream) {\n this.state.updateParticipantMedia(id, {\n stream: incomingStream,\n cameraTrack: incomingStream.getVideoTracks()[0],\n audioTrack: incomingStream.getAudioTracks()[0],\n });\n this.events.onTrack?.(incomingStream, id);\n } else {\n this.state.updateParticipantMedia(id, {\n stream: incomingStream,\n cameraTrack: incomingStream.getVideoTracks()[0],\n audioTrack: incomingStream.getAudioTracks()[0],\n });\n this.events.onTrack?.(incomingStream, id);\n }\n };\n\n pc.onicecandidate = (e) => {\n if (!e.candidate) return;\n\n console.log(\"LOCAL ICE:\", e.candidate.candidate);\n this.send({\n type: \"ICE\",\n payload: JSON.stringify(e.candidate),\n sender: this.myId,\n target: id,\n });\n };\n\n pc.oniceconnectionstatechange = async () => {\n console.log(\"================================\");\n console.log(`Peer: ${id}`);\n console.log(`ICE: ${pc.iceConnectionState}`);\n console.log(`Connection: ${pc.connectionState}`);\n console.log(`Signaling: ${pc.signalingState}`);\n\n if (pc.iceConnectionState === \"disconnected\") {\n const stats = await pc.getStats();\n\n stats.forEach((report) => {\n if (report.type === \"transport\") {\n console.log(JSON.stringify(report, null, 2));\n }\n });\n }\n };\n\n pc.onconnectionstatechange = () => {\n if (pc.connectionState === \"failed\") {\n try {\n pc.restartIce();\n } catch {}\n }\n };\n\n this.localStream.getTracks().forEach((track) => {\n pc.addTrack(track, this.localStream!);\n });\n\n if (this.isScreenSharing && this.screenStream) {\n this.screenSenders[id] = [];\n this.screenStream.getTracks().forEach((track) => {\n const sender = pc.addTrack(track, this.screenStream!);\n this.screenSenders[id].push(sender);\n });\n }\n\n return pc;\n }\n\n // ---------------- OFFER ----------------\n private async createOffer(id: string, isRenegotiation = false) {\n if (!isRenegotiation && !this.shouldInitiate(id)) {\n console.debug(\n `[Offer] ${id} should initiate (${id} > ${this.myId}), skipping`,\n );\n return;\n }\n\n if (!isRenegotiation && this.initiators.has(id)) {\n console.debug(\n `[Offer] Already initiating with ${id}, skipping duplicate`,\n );\n return; // ← This was missing!\n }\n\n if (!isRenegotiation) {\n this.initiators.add(id);\n }\n if (!this.peers[id]) {\n this.peers[id] = this.createPeer(id);\n }\n\n const pc = this.peers[id];\n\n try {\n const offer = await pc.createOffer();\n await pc.setLocalDescription(offer);\n\n this.send({\n type: \"OFFER\",\n payload: offer.sdp,\n sender: this.myId,\n target: id,\n });\n\n console.debug(`[Offer] Sent to ${id}`);\n } catch (err) {\n console.error(`[Offer] Failed for ${id}:`, err);\n }\n }\n\n private shouldInitiate(peerId: string): boolean {\n // Lexicographic comparison: lower ID initiates\n return this.myId < peerId;\n }\n\n // ---------------- ANSWER ----------------\n private async handleOffer(sdp: string, id: string) {\n if (!this.iceServers || this.iceServers.length === 0) {\n console.warn(\"[Offer] Waiting for iceServers, queuing offer from\", id);\n this.pendingOffers[id] = sdp;\n return;\n }\n\n if (!this.peers[id]) {\n this.peers[id] = this.createPeer(id);\n }\n\n const pc = this.peers[id];\n\n try {\n // GLARE RECOVERY: Both peers sent OFFERs simultaneously\n if (pc.signalingState === \"have-local-offer\") {\n if (this.shouldInitiate(id)) {\n // WE WIN: Keep our offer, reject theirs\n console.warn(\n `[Glare] Both sent OFFERs, we win (${this.myId} < ${id}), keeping our OFFER`,\n );\n return; // Ignore their offer, wait for their ANSWER\n } else {\n // THEY WIN: Roll back and accept their offer\n console.warn(\n `[Glare] Both sent OFFERs, they win (${id} < ${this.myId}), rolling back`,\n );\n pc.close();\n delete this.peers[id];\n this.initiators.delete(id);\n\n // Create fresh peer connection to answer their offer\n this.peers[id] = this.createPeer(id);\n }\n }\n\n // Only set remote description if we're not already in negotiation\n if (\n this.peers[id].signalingState !== \"stable\" &&\n this.peers[id].signalingState !== \"have-local-offer\"\n ) {\n console.warn(\n `[Signaling] Cannot accept OFFER in state \"${this.peers[id].signalingState}\"`,\n );\n return;\n }\n\n await this.peers[id].setRemoteDescription({\n type: \"offer\",\n sdp,\n });\n\n const pending = this.pendingIceCandidates[id] || [];\n\n for (const candidate of pending) {\n try {\n await this.peers[id].addIceCandidate(candidate);\n } catch (err) {\n console.warn(\"[ICE] Failed to add candidate:\", err);\n }\n }\n\n delete this.pendingIceCandidates[id];\n\n const answer = await this.peers[id].createAnswer();\n\n await this.peers[id].setLocalDescription(answer);\n await this.flushIce(id, this.peers[id]);\n\n this.send({\n type: \"ANSWER\",\n payload: answer.sdp,\n sender: this.myId,\n target: id,\n });\n\n console.debug(`[Answer] Sent to ${id}`);\n } catch (err) {\n console.error(`[Signaling] Failed to handle OFFER from ${id}:`, err);\n this.emitError(\n \"OFFER_HANDLING_FAILED\",\n `Failed to handle offer from ${id}`,\n err,\n true,\n );\n }\n }\n\n // ---------------- CLEANUP ----------------\n private closePeer(id: string) {\n const pc = this.peers[id];\n\n if (!pc) return;\n\n pc.ontrack = null;\n pc.onicecandidate = null;\n pc.onconnectionstatechange = null;\n\n pc.close();\n\n delete this.peers[id];\n\n this.initiators.delete(id);\n\n this.state.removeParticipant(id);\n }\n\n async startScreenShare() {\n try {\n if (this.state.presenterId && this.state.presenterId !== this.myId) {\n throw new Error(\"Another user is already sharing their screen.\");\n }\n if (!navigator.mediaDevices?.getDisplayMedia) {\n throw new Error(\"Screen sharing not supported on this device\");\n }\n\n this.screenStream = await navigator.mediaDevices.getDisplayMedia({\n video: true,\n // audio: true,\n });\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 this.state.setPresenterId(this.myId);\n // Handle the user clicking browser's built-in \"Stop Sharing\" button\n this.screenStream.getVideoTracks()[0].onended = () => {\n this.stopScreenShare();\n };\n\n Object.entries(this.peers).forEach(([peerId, pc]) => {\n this.screenSenders[peerId] = [];\n this.screenStream!.getTracks().forEach((track) => {\n const sender = pc.addTrack(track, this.screenStream!);\n this.screenSenders[peerId].push(sender);\n });\n\n // Renegotiate peer connection descriptors to notify remote side of new track footprint\n this.createOffer(peerId, true);\n });\n\n this.send({\n type: \"SCREEN_SHARE_START\",\n sender: this.myId,\n room_id: this.room.id,\n camera_id: this.localStream?.id.replace(/[{}]/g, \"\"),\n stream_id: this.screenStream.id.replace(/[{}]/g, \"\"),\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 throw err;\n }\n }\n\n stopScreenShare() {\n if (!this.screenStream) return;\n\n this.screenStream.getTracks().forEach((t) => t.stop());\n\n // Remove tracks cleanly from WebRTC channel pathways across your peers\n Object.entries(this.peers).forEach(([peerId, pc]) => {\n const senders = this.screenSenders[peerId] || [];\n senders.forEach((sender) => {\n try {\n pc.removeTrack(sender);\n } catch (err) {\n console.warn(err);\n }\n });\n delete this.screenSenders[peerId];\n\n // Renegotiate layout expectations to scale down stream bounds\n this.createOffer(peerId, true);\n });\n\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 if (this.state.presenterId === this.myId) {\n this.state.setPresenterId(null);\n }\n\n this.send({\n type: \"SCREEN_SHARE_STOP\",\n sender: this.myId,\n room_id: this.room.id,\n });\n }\n\n sendChatMessage(payload: ChatInput) {\n if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {\n console.warn(\"WS not connected\");\n return;\n }\n\n if (!this.room.id) {\n console.warn(\"No roomId set\");\n return;\n }\n\n const isPrivate = !!payload?.target;\n\n const senderName = this.state.localParticipant?.name || \"Anonymous\";\n\n const msg: ChatMessage = {\n id: crypto.randomUUID(),\n sender_id: this.myId,\n sender_name: senderName,\n text: payload.message.trim(),\n timestamp: Date.now(),\n reply_to: payload.reply_to ?? null,\n target: payload.target ?? null,\n };\n\n // optimistic UI update\n this.state.addChatMessage(msg);\n\n // send protocol payload (clean + consistent)\n this.send({\n type: \"CHAT_MESSAGE\",\n message: payload.message.trim(),\n user_id: this.myId,\n sender_name: senderName,\n room_id: this.room.id,\n target: isPrivate ? (payload.target ?? null) : null,\n reply_to: payload.reply_to ?? null,\n\n client_ts: Date.now(),\n });\n }\n\n disconnect() {\n this.intentionalDisconnect = true;\n\n this.stopScreenShare();\n\n Object.values(this.peers).forEach((pc) => pc.close());\n this.peers = {};\n this.initiators.clear();\n\n this.stopHeartbeat();\n\n if (this.ws?.readyState === WebSocket.OPEN) {\n this.send({\n type: \"LEAVE\",\n room_id: this.room.id,\n user_id: this.myId,\n sender_name: this.state.localParticipant?.name,\n });\n\n // Allow the LEAVE frame to be flushed.\n setTimeout(() => {\n this.ws?.close(1000, \"Leaving meeting\");\n this.ws = null;\n }, 50);\n }\n\n if (this.localStream) {\n this.localStream.getTracks().forEach((track) => track.stop());\n this.localStream = null;\n }\n\n this.room.id = null;\n\n this.state.localParticipant = null;\n this.state.notify(\"localParticipant\");\n\n this.state.participants.clear();\n this.state.notify(\"participants\");\n\n this.events.onMeetingLeft?.();\n\n this.state.clearChat();\n this.state.setPresenterId(null);\n }\n\n private async flushIce(id: string, pc: RTCPeerConnection) {\n const pending = this.pendingIceCandidates[id];\n if (!pending?.length) return;\n\n for (const candidate of pending) {\n try {\n await pc.addIceCandidate(candidate);\n } catch (e) {\n console.warn(\"ICE flush error\", e);\n }\n }\n\n delete this.pendingIceCandidates[id];\n }\n\n private send(msg: any) {\n this.ws?.send(JSON.stringify(msg));\n }\n\n approveJoinRequest(requestId: string) {\n this.send({\n type: \"JOIN_APPROVE\",\n request_id: requestId,\n });\n }\n\n rejectJoinRequest(requestId: string) {\n this.send({\n type: \"JOIN_REJECT\",\n request_id: requestId,\n });\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\";\n\nexport const useMeeting = (handlers?: {\n onError?: (err: any) => void;\n onEntryRequested?: (req: any) => void;\n onEntryResponded?: (payload: any, decision?: any) => void;\n onMeetingLeft?: () => 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 // 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 // Meeting Left Handler\n useEffect(() => {\n if (!handlers?.onMeetingLeft) return;\n return ctx.onMeetingLeft(handlers.onMeetingLeft);\n }, [handlers?.onMeetingLeft]);\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 };\n};\n","import { useCallback, 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 participants: {\n id: string;\n name: string;\n isHost: boolean;\n isPresenter: boolean;\n micEnabled: boolean;\n camEnabled: boolean;\n }[];\n};\n\nexport function useMeetingPreview(roomId: string, userId: string) {\n const [room, setRoom] = useState<LiveRoomState | null>(null);\n const [isLoading, setIsLoading] = useState(true);\n const [error, setError] = useState<Error | null>(null);\n\n const load = useCallback(async () => {\n if (!roomId || !userId) return;\n\n try {\n setIsLoading(true);\n setError(null);\n\n const res = await fetch(\n `${SDK_CONFIG.baseUrl}/api/rooms/${roomId}/live?user_id=${userId}`,\n );\n\n if (!res.ok) {\n throw new Error(\"Failed to fetch meeting preview\");\n }\n\n const data = await res.json();\n\n setRoom(data);\n } catch (err) {\n setError(err instanceof Error ? err : new Error(\"Unknown error\"));\n } finally {\n setIsLoading(false);\n }\n }, [roomId, userId]);\n\n useEffect(() => {\n load();\n\n const interval = setInterval(load, 5000);\n\n return () => clearInterval(interval);\n }, [load]);\n\n return {\n room,\n isLoading,\n error,\n refetch: load,\n };\n}\n"],"mappings":"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","names":["import_react","import_react","peerId","import_react","import_react","import_react","import_react"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/react/useLocalParticipant.tsx","../src/react/MeetingProvider.tsx","../src/config/ws.ts","../src/core/MeetingState.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"],"sourcesContent":["export { useLocalParticipant } from \"./react/useLocalParticipant\";\n\n// Core exports\nexport { VideoSDKCore } from \"./core/VideoCore\";\nexport { MeetingState } from \"./core/MeetingState\";\nexport type { Participant, ChatInput } from \"./types/meeting\";\n\n// React hooks and components\nexport { MeetingProvider, useMeetingContext } from \"./react/MeetingProvider\";\nexport { useMeeting } from \"./react/useMeeting\";\nexport { useParticipants } from \"./react/useParticipants\";\nexport { useRemoteMedia } from \"./react/useRemoteMedia\";\nexport { useMeetingPreview } from \"./react/useMeetingPreview\";\n","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, { createContext, useContext, useMemo, useRef } from \"react\";\nimport { VideoSDKCore } from \"../core/VideoCore\";\nimport {\n ChatInput,\n ChatMessage,\n MeetingConfig,\n Participant,\n PubSubTopic,\n} from \"../types/meeting\";\nimport { useMeetingStore } from \"./useMeetingStore\";\n\ntype PubSubHandle = {\n messages: ChatMessage[];\n publish: (input: ChatInput) => void;\n};\n\ntype MeetingContextValue = {\n sdk: VideoSDKCore;\n join: (config?: MeetingConfig) => Promise<void>;\n leave: () => void;\n\n toggleMic: () => void;\n toggleCam: () => void;\n\n startScreenShare: () => Promise<MediaStream>;\n stopScreenShare: () => void;\n\n sendMessage: (input: ChatInput) => void;\n\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 usePubSub: (topic: PubSubTopic) => PubSubHandle;\n approveJoinRequest: (requestId: string) => void;\n rejectJoinRequest: (requestId: string) => void;\n onError: (cb: (err: any) => void) => () => void;\n onEntryRequested: (cb: (req: any) => void) => () => void;\n onEntryResponded: (cb: (payload: any, decision?: any) => void) => () => void;\n onMeetingLeft: (cb: () => 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 meetingLeftListeners = useRef(new Set<() => void>());\n\n if (!sdkRef.current) {\n sdkRef.current = new VideoSDKCore({\n onError: (err) => errorListeners.current.forEach((fn) => fn(err)),\n onEntryRequested: (req) =>\n entryRequestListeners.current.forEach((fn) => fn(req)),\n onEntryResponded: (p, d) =>\n entryResponseListeners.current.forEach((fn) => fn(p, d)),\n onMeetingLeft: () => meetingLeftListeners.current.forEach((fn) => fn()),\n });\n }\n\n const sdk = sdkRef.current;\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\n const value = useMemo<MeetingContextValue>(() => {\n if (!sdkRef.current) {\n sdkRef.current = new VideoSDKCore({\n onError: (err) => {\n errorListeners.current.forEach((fn) => fn(err));\n },\n });\n }\n\n return {\n sdk,\n\n join: (joinConfig?: MeetingConfig) =>\n sdk.joinMeeting({\n ...config,\n ...joinConfig,\n }),\n leave: () => sdk.disconnect(),\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\n room: sdk.getMeeting(),\n localParticipant,\n participants,\n messages,\n presenterId,\n usePubSub: (topic: PubSubTopic) => {\n if (topic !== \"SECURE_CHAT\") {\n throw new Error(`Unsupported PubSub argument: \"${topic}\"`);\n }\n return {\n messages: sdk.state.getChatMessages(),\n publish: sdk.sendChatMessage.bind(sdk),\n };\n },\n approveJoinRequest: sdk.approveJoinRequest.bind(sdk),\n rejectJoinRequest: sdk.rejectJoinRequest.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 onMeetingLeft: (cb: () => void) => {\n meetingLeftListeners.current.add(cb);\n return () => {\n meetingLeftListeners.current.delete(cb);\n };\n },\n };\n }, [config, sdk, localParticipant, participants, messages, presenterId]);\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","export const SDK_CONFIG = {\n wsUrl: \"wss://rust-video-server-sfyf.onrender.com/ws\",\n baseUrl: \"https://rust-video-server-sfyf.onrender.com\",\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 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\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 // ---- 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: true,\n camEnabled: true,\n 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 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 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.notify(\"participants\");\n this.notify(\"chat\");\n this.notify(\"presenter\");\n }\n}\n","import { SDK_CONFIG } from \"../config/ws\";\nimport {\n ChatInput,\n ChatMessage,\n Events,\n MeetingConfig,\n Participant,\n SDKError,\n} from \"../types/meeting\";\nimport { MeetingState } from \"./MeetingState\";\n\nexport class VideoSDKCore {\n private ws: WebSocket | null = null;\n private peers: Record<string, RTCPeerConnection> = {};\n private initiators = new Set<string>();\n private lastPong = Date.now();\n private iceServers: RTCIceServer[] = [];\n private intentionalDisconnect = false;\n\n private myId: string;\n private room: { id: string | null; name: string | null } = {\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 screenSenders: Record<string, RTCRtpSender[]> = {};\n\n private pingInterval: any = null;\n private pendingIceCandidates: Record<string, RTCIceCandidateInit[]> = {};\n private pendingOffers: Record<string, string> = {};\n private reconnectAttempts = 0;\n private reconnectTimer?: number;\n private participantName = \"\";\n public readonly state: MeetingState;\n private joinResolver?: () => void;\n private joinRejecter?: (e: any) => void;\n\n // Track if we're in the waiting room (pending approval)\n private isWaitingForApproval = false;\n private pendingRequestId: string | null = null;\n private iceTransportPolicy: RTCIceTransportPolicy = \"all\";\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 userId: this.myId,\n recoverable,\n };\n\n this.events.onError?.(err);\n\n this.joinRejecter?.(err);\n this.joinRejecter = undefined;\n\n console.error(\"[MeetingSDK Error]\", err);\n }\n\n constructor(\n private events: Events = {},\n private url: string = SDK_CONFIG.wsUrl,\n ) {\n this.state = new MeetingState();\n this.events = events;\n this.url = url;\n\n this.myId = localStorage.getItem(\"vsdk_id\") || crypto.randomUUID();\n\n localStorage.setItem(\"vsdk_id\", this.myId);\n }\n\n // ---------------- STREAM ----------------\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 // Verify tracks are actually live BEFORE connecting\n const hasVideo = this.localStream\n .getVideoTracks()\n .some((t) => t.readyState === \"live\");\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 this.state.updateLocalParticipant({\n id: this.myId,\n name: this.participantName,\n media: {\n stream: this.localStream,\n micEnabled: true,\n camEnabled: true,\n isScreenSharing: false,\n },\n });\n\n this.state.localStream = this.localStream;\n } catch (err: any) {\n this.emitError(\"GET_USER_MEDIA_FAILED\", err?.message, err, false);\n throw err;\n }\n }\n\n // ---------------- CONNECT ----------------\n async connect(roomId: string, name: string) {\n this.room.id = roomId;\n\n this.reset();\n\n return new Promise<void>((resolve, reject) => {\n this.joinResolver = resolve;\n this.joinRejecter = reject;\n this.ws = new WebSocket(this.url);\n\n this.ws.onopen = () => {\n console.log(\"WebSocket connected, sending JOIN...\");\n this.send({\n type: \"JOIN\",\n room_id: roomId,\n user_id: this.myId,\n sender_name: name,\n camera_stream_id: this.localStream?.id.replace(/[{}]/g, \"\"),\n audio_muted: this.state.localParticipant?.media?.micEnabled,\n video_muted: this.state.localParticipant?.media?.camEnabled,\n });\n };\n\n this.ws.onerror = (err) => {\n this.emitError(\"WS_ERROR\", \"WebSocket encountered an error\", err, true);\n };\n\n this.ws.onclose = (e) => {\n this.joinRejecter?.({\n code: \"WS_CLOSED\",\n message: \"Connection closed before join completed\",\n raw: e,\n });\n\n this.joinRejecter = undefined;\n\n if (this.intentionalDisconnect) {\n return; // do NOT reconnect\n }\n\n if (e.code === 1000 || e.code === 1001) {\n return;\n }\n\n // Don't auto-reconnect if waiting for approval (user must reconnect after approval)\n if (this.isWaitingForApproval) {\n return;\n }\n\n this.scheduleReconnect();\n };\n\n this.ws.onmessage = async (e) => {\n await this.handle(JSON.parse(e.data));\n };\n });\n }\n\n async joinMeeting(config: MeetingConfig) {\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 this.participantName = name;\n\n // Reuse existing stream if initLocal already configured it\n if (!this.localStream) {\n this.localStream = await navigator.mediaDevices.getUserMedia({\n video: true,\n audio: true,\n });\n }\n\n this.localStream.getAudioTracks().forEach((t) => {\n t.enabled = !audioMuted;\n });\n this.localStream.getVideoTracks().forEach((t) => {\n t.enabled = !videoMuted;\n });\n\n this.state.updateLocalParticipant({\n id: this.myId,\n name: this.participantName,\n media: {\n stream: this.localStream,\n micEnabled: !audioMuted,\n camEnabled: !videoMuted,\n isScreenSharing: false,\n },\n });\n\n this.state.localStream = this.localStream;\n\n await this.connect(roomId, name);\n }\n\n getMeeting(): { id: string | null; name: string | null } {\n return this.room;\n }\n\n toggleMic() {\n const mediaState = this.state.localParticipant?.media;\n if (!mediaState) return;\n\n const nextEnabled = !mediaState.micEnabled;\n\n this.localStream\n ?.getAudioTracks()\n .forEach((t) => (t.enabled = nextEnabled));\n\n // Update state layer\n this.state.updateLocalParticipant({\n id: this.myId,\n name: this.participantName,\n media: {\n ...mediaState,\n micEnabled: nextEnabled,\n },\n });\n\n // Notify peers\n this.send({\n type: \"MEDIA_STATE\",\n kind: \"audio\",\n enabled: nextEnabled,\n });\n }\n\n toggleCam() {\n const mediaState = this.state.localParticipant?.media;\n if (!mediaState) return;\n\n const nextEnabled = !mediaState.camEnabled;\n\n this.localStream\n ?.getVideoTracks()\n .forEach((t) => (t.enabled = nextEnabled));\n\n // Update state layer\n this.state.updateLocalParticipant({\n id: this.myId,\n name: this.participantName,\n media: {\n ...mediaState,\n camEnabled: nextEnabled,\n },\n });\n\n // Notify peers\n this.send({\n type: \"MEDIA_STATE\",\n kind: \"video\",\n enabled: nextEnabled,\n });\n }\n\n private scheduleReconnect() {\n if (!this.room.id) return;\n\n const delay = Math.min(1000 * Math.pow(2, this.reconnectAttempts), 30000);\n\n clearTimeout(this.reconnectTimer);\n\n this.reconnectTimer = window.setTimeout(async () => {\n try {\n await this.connect(this.room.id!, this.participantName);\n\n this.reconnectAttempts = 0;\n } catch {\n this.reconnectAttempts++;\n this.scheduleReconnect();\n }\n }, delay);\n }\n\n private startHeartbeat() {\n this.stopHeartbeat();\n\n this.pingInterval = setInterval(() => {\n if (!this.ws || this.ws.readyState !== WebSocket.OPEN) return;\n\n this.send({\n type: \"PING\",\n client_ts: Date.now(),\n });\n }, 20000); // every 20s\n }\n private stopHeartbeat() {\n if (this.pingInterval) {\n clearInterval(this.pingInterval);\n this.pingInterval = null;\n }\n }\n\n // ---------------- RESET ----------------\n private reset() {\n Object.values(this.peers).forEach((pc) => pc.close());\n\n this.peers = {};\n this.initiators.clear();\n this.pendingIceCandidates = {};\n\n this.state.resetRemoteState();\n }\n\n private async handleJoinApproved(msg: any) {\n console.log(\"JOIN_APPROVED received, sending new JOIN...\");\n\n this.events.onEntryResponded?.({\n participantId: msg.user_id,\n decision: \"approved\",\n });\n\n this.isWaitingForApproval = false;\n this.pendingRequestId = null;\n\n // Send JOIN again on SAME socket\n if (this.ws && this.ws.readyState === WebSocket.OPEN) {\n this.send({\n type: \"JOIN\",\n room_id: this.room.id,\n user_id: this.myId,\n sender_name: this.participantName,\n });\n console.log(\"Sent new JOIN after approval\");\n }\n }\n\n private async handle(msg: any) {\n if (msg.sender === this.myId) return;\n\n switch (msg.type) {\n case \"PONG\":\n this.lastPong = Date.now();\n break;\n case \"OFFER\":\n console.log(\"[Offer] Received from\", msg.sender, {\n sdp: msg.payload.substring(0, 200),\n });\n await this.handleOffer(msg.payload, msg.sender);\n break;\n\n case \"ANSWER\": {\n const pc = this.peers[msg.sender];\n console.log(\"[Answer] Received from\", msg.sender, {\n signalingState: pc?.signalingState,\n iceConnectionState: pc?.iceConnectionState,\n connectionState: pc?.connectionState,\n });\n\n if (!pc) return;\n\n if (pc.signalingState !== \"have-local-offer\") {\n console.warn(\n `[Signaling] Unexpected ANSWER in state \"${pc.signalingState}\", ignoring`,\n );\n return;\n }\n\n try {\n await pc.setRemoteDescription({\n type: \"answer\",\n sdp: msg.payload,\n });\n\n await this.flushIce(msg.sender, pc);\n } catch (err) {\n console.error(\"[Signaling] Failed to apply answer:\", err);\n this.emitError(\n \"ANSWER_FAILED\",\n `Failed to apply answer from ${msg.sender}`,\n err,\n true,\n );\n }\n break;\n }\n case \"ICE\": {\n const candidate = JSON.parse(msg.payload);\n\n let pc = this.peers[msg.sender];\n\n if (!pc) {\n this.pendingIceCandidates[msg.sender] ??= [];\n this.pendingIceCandidates[msg.sender].push(candidate);\n break;\n }\n\n if (!pc.remoteDescription) {\n this.pendingIceCandidates[msg.sender] ??= [];\n this.pendingIceCandidates[msg.sender].push(candidate);\n break;\n }\n\n try {\n await pc.addIceCandidate(candidate);\n } catch (err) {\n console.warn(\"ICE error:\", err);\n }\n\n break;\n }\n case \"EXISTING_USERS\":\n if (msg.presenterId) {\n this.state.setPresenterId(msg.presenterId);\n\n this.events.onScreenShareStarted?.(msg.presenterId, null!);\n this.state.setPresenterId(msg.presenterId);\n }\n\n for (const p of msg.participants || []) {\n if (!p?.id || p.id === this.myId) continue;\n const structuredParticipant: Participant = {\n id: p.id,\n name: p.name,\n isHost: p.isHost,\n isPresenter: p.isPresenter,\n media: {\n stream: null,\n screenStream: undefined,\n cameraTrack: undefined,\n screenTrack: undefined,\n audioTrack: undefined,\n micEnabled: p.micEnabled ?? true,\n camEnabled: p.camEnabled ?? true,\n isScreenSharing: p.isScreenSharing ?? false,\n remoteScreenStreamId: p.remoteScreenStreamId || undefined,\n cameraStreamId: p.cameraId || undefined,\n },\n };\n this.state.addParticipant(structuredParticipant);\n this.events.onUserJoined?.(structuredParticipant);\n\n if (p.isScreenSharing && p.remoteScreenStreamId) {\n this.state.setPresenterId(p.id);\n this.state.updateParticipantMedia(p.id, {\n isScreenSharing: true,\n remoteScreenStreamId: p.remoteScreenStreamId,\n cameraStreamId: p.cameraId || null,\n });\n }\n if (this.shouldInitiate(p.id)) {\n await this.createOffer(p.id);\n }\n }\n break;\n\n case \"JOINED\": {\n if (msg.iceServers) {\n this.iceServers = msg.iceServers;\n }\n this.room.name = msg.room_name;\n\n this.isWaitingForApproval = false;\n this.pendingRequestId = null;\n this.intentionalDisconnect = false;\n this.reconnectAttempts = 0;\n\n // Process any OFFERs that arrived before JOINED\n if (Object.keys(this.pendingOffers).length > 0) {\n console.log(\n \"Processing\",\n Object.keys(this.pendingOffers).length,\n \"pending offers\",\n );\n for (const [peerId, sdp] of Object.entries(this.pendingOffers)) {\n await this.handleOffer(sdp, peerId);\n }\n this.pendingOffers = {};\n }\n\n const media = this.state.localParticipant?.media;\n\n if (media) {\n this.send({\n type: \"MEDIA_STATE\",\n kind: \"audio\",\n enabled: !!media.micEnabled,\n });\n\n this.send({\n type: \"MEDIA_STATE\",\n kind: \"video\",\n enabled: !!media.camEnabled,\n });\n }\n this.startHeartbeat();\n this.joinResolver?.();\n this.joinResolver = undefined;\n this.joinRejecter = undefined;\n break;\n }\n case \"USER_JOINED\": {\n const p = msg.participant;\n\n if (!p?.id || p.id === this.myId) return;\n\n this.state.addParticipant(p);\n\n this.events.onUserJoined?.(p);\n if (this.shouldInitiate(p.id)) {\n await this.createOffer(p.id);\n }\n\n break;\n }\n\n case \"JOIN_PENDING\": {\n const req = msg.request;\n\n this.isWaitingForApproval = true;\n this.pendingRequestId = req.request_id;\n\n this.events.onEntryRequested?.({\n requestId: req.request_id,\n userId: req.user_id,\n name: req.name,\n });\n\n break;\n }\n\n case \"JOIN_REQUEST\": {\n const req = msg.request;\n this.events.onEntryRequested?.({\n requestId: req.id,\n userId: req.user_id,\n name: req.name,\n });\n\n break;\n }\n\n case \"JOIN_APPROVED\": {\n await this.handleJoinApproved(msg);\n break;\n }\n\n case \"JOIN_REJECTED\": {\n const decision = \"rejected\";\n\n this.isWaitingForApproval = false;\n this.pendingRequestId = null;\n\n this.events.onEntryResponded?.({\n participantId: msg.user_id,\n decision,\n });\n\n break;\n }\n\n case \"USER_LEFT\":\n const peerId = msg.participant.id;\n this.closePeer(peerId);\n\n this.state.removeParticipant(peerId);\n\n this.events.onUserLeft?.(peerId);\n\n break;\n\n case \"MEDIA_STATE_CHANGE\": {\n const peerId = msg.peerId;\n const { kind, enabled } = msg;\n\n if (kind === \"audio\") {\n this.state.updateParticipantMedia(peerId, { micEnabled: enabled });\n this.events.onMicToggled?.(peerId, enabled);\n } else if (kind === \"video\") {\n this.state.updateParticipantMedia(peerId, { camEnabled: enabled });\n this.events.onCamToggled?.(peerId, enabled);\n }\n\n break;\n }\n\n case \"CHAT_MESSAGE\": {\n const newMsg = msg.data;\n\n if (newMsg.sender_id === this.myId) break; // already added optimistically\n this.state.addChatMessage({\n id: newMsg.id,\n text: newMsg.message,\n sender_id: newMsg.sender_id,\n sender_name: newMsg.sender_name,\n timestamp: new Date(newMsg.timestamp).getTime(),\n target: newMsg.target,\n });\n\n this.events.onChatMessage?.(msg);\n break;\n }\n case \"SCREEN_SHARE_START\": {\n const peerId = msg.peerId;\n\n this.state.updateParticipantMedia(peerId, {\n isScreenSharing: true,\n remoteScreenStreamId: msg.stream_id,\n cameraStreamId: msg?.camera_stream_id,\n });\n\n if (!this.state.presenterId) {\n this.state.setPresenterId(peerId);\n }\n\n const screenStream =\n this.state.getParticipant(peerId)?.media?.screenStream;\n\n this.events.onScreenShareStarted?.(peerId, screenStream || null!);\n break;\n }\n\n case \"SCREEN_SHARE_STOP\": {\n const peerId = msg.peerId;\n this.state.updateParticipantMedia(peerId, { isScreenSharing: false });\n if (this.state.presenterId === peerId) {\n this.state.setPresenterId(null);\n }\n this.events.onScreenShareStopped?.(peerId);\n break;\n }\n case \"ERROR\": {\n const fatal = msg?.fatal === true;\n\n this.emitError(\n \"WS_ERROR\",\n msg?.message || \"Unknown error\",\n msg,\n !fatal,\n );\n\n if (fatal) {\n this.disconnect();\n }\n\n return;\n }\n }\n }\n\n // ---------------- PEER ----------------\n private createPeer(id: string) {\n if (!this.localStream) throw new Error(\"No local stream\");\n if (!this.iceServers || this.iceServers.length === 0) {\n throw new Error(\n \"ICE Servers not configured. Backend must provide iceServers on JOIN.\",\n );\n }\n\n const pc = new RTCPeerConnection({\n iceServers: this.iceServers,\n iceTransportPolicy: this.iceTransportPolicy,\n });\n\n pc.ontrack = (event) => {\n const incomingStream =\n event.streams?.[0] || new MediaStream([event.track]);\n const streamId = incomingStream?.id?.replace(/[{}]/g, \"\");\n\n const participant = this.state.getParticipant(id);\n\n const isCameraStream =\n streamId &&\n participant?.media?.cameraStreamId &&\n streamId === participant?.media?.cameraStreamId;\n\n const isScreenStream =\n streamId &&\n participant?.media?.remoteScreenStreamId &&\n streamId === participant?.media?.remoteScreenStreamId;\n\n if (event.track.muted) {\n event.track.onunmute = () => {\n console.log(`${event.track.kind} track unmuted for ${id}`);\n };\n }\n\n if (isScreenStream) {\n const videoTrack =\n event.track.kind === \"video\"\n ? event.track\n : incomingStream.getVideoTracks()[0] ||\n participant?.media?.screenTrack;\n\n this.state.updateParticipantMedia(id, {\n screenStream: incomingStream,\n screenTrack: videoTrack,\n remoteScreenStreamId: incomingStream.id,\n isScreenSharing: true,\n });\n\n if (!this.state.presenterId) {\n this.state.setPresenterId(id);\n }\n\n this.events.onScreenShareStarted?.(id, incomingStream);\n console.log(`Screen share stream detected for ${id}`);\n } else if (isCameraStream) {\n this.state.updateParticipantMedia(id, {\n stream: incomingStream,\n cameraTrack: incomingStream.getVideoTracks()[0],\n audioTrack: incomingStream.getAudioTracks()[0],\n });\n this.events.onTrack?.(incomingStream, id);\n } else {\n this.state.updateParticipantMedia(id, {\n stream: incomingStream,\n cameraTrack: incomingStream.getVideoTracks()[0],\n audioTrack: incomingStream.getAudioTracks()[0],\n });\n this.events.onTrack?.(incomingStream, id);\n }\n };\n\n pc.onicecandidate = (e) => {\n if (!e.candidate) return;\n\n console.log(\"LOCAL ICE:\", e.candidate.candidate);\n this.send({\n type: \"ICE\",\n payload: JSON.stringify(e.candidate),\n sender: this.myId,\n target: id,\n });\n };\n\n pc.oniceconnectionstatechange = async () => {\n console.log(\"================================\");\n console.log(`Peer: ${id}`);\n console.log(`ICE: ${pc.iceConnectionState}`);\n console.log(`Connection: ${pc.connectionState}`);\n console.log(`Signaling: ${pc.signalingState}`);\n\n if (pc.iceConnectionState === \"disconnected\") {\n const stats = await pc.getStats();\n\n stats.forEach((report) => {\n if (report.type === \"transport\") {\n console.log(JSON.stringify(report, null, 2));\n }\n });\n }\n };\n\n pc.onconnectionstatechange = () => {\n if (pc.connectionState === \"failed\") {\n try {\n pc.restartIce();\n } catch {}\n }\n };\n\n this.localStream.getTracks().forEach((track) => {\n pc.addTrack(track, this.localStream!);\n });\n\n if (this.isScreenSharing && this.screenStream) {\n this.screenSenders[id] = [];\n this.screenStream.getTracks().forEach((track) => {\n const sender = pc.addTrack(track, this.screenStream!);\n this.screenSenders[id].push(sender);\n });\n }\n\n return pc;\n }\n\n // ---------------- OFFER ----------------\n private async createOffer(id: string, isRenegotiation = false) {\n if (!isRenegotiation && !this.shouldInitiate(id)) {\n console.debug(\n `[Offer] ${id} should initiate (${id} > ${this.myId}), skipping`,\n );\n return;\n }\n\n if (!isRenegotiation && this.initiators.has(id)) {\n console.debug(\n `[Offer] Already initiating with ${id}, skipping duplicate`,\n );\n return; // ← This was missing!\n }\n\n if (!isRenegotiation) {\n this.initiators.add(id);\n }\n if (!this.peers[id]) {\n this.peers[id] = this.createPeer(id);\n }\n\n const pc = this.peers[id];\n\n try {\n const offer = await pc.createOffer();\n await pc.setLocalDescription(offer);\n\n this.send({\n type: \"OFFER\",\n payload: offer.sdp,\n sender: this.myId,\n target: id,\n });\n\n console.debug(`[Offer] Sent to ${id}`);\n } catch (err) {\n console.error(`[Offer] Failed for ${id}:`, err);\n }\n }\n\n private shouldInitiate(peerId: string): boolean {\n // Lexicographic comparison: lower ID initiates\n return this.myId < peerId;\n }\n\n // ---------------- ANSWER ----------------\n private async handleOffer(sdp: string, id: string) {\n if (!this.iceServers || this.iceServers.length === 0) {\n console.warn(\"[Offer] Waiting for iceServers, queuing offer from\", id);\n this.pendingOffers[id] = sdp;\n return;\n }\n\n if (!this.peers[id]) {\n this.peers[id] = this.createPeer(id);\n }\n\n const pc = this.peers[id];\n\n try {\n // GLARE RECOVERY: Both peers sent OFFERs simultaneously\n if (pc.signalingState === \"have-local-offer\") {\n if (this.shouldInitiate(id)) {\n // WE WIN: Keep our offer, reject theirs\n console.warn(\n `[Glare] Both sent OFFERs, we win (${this.myId} < ${id}), keeping our OFFER`,\n );\n return; // Ignore their offer, wait for their ANSWER\n } else {\n // THEY WIN: Roll back and accept their offer\n console.warn(\n `[Glare] Both sent OFFERs, they win (${id} < ${this.myId}), rolling back`,\n );\n pc.close();\n delete this.peers[id];\n this.initiators.delete(id);\n\n // Create fresh peer connection to answer their offer\n this.peers[id] = this.createPeer(id);\n }\n }\n\n // Only set remote description if we're not already in negotiation\n if (\n this.peers[id].signalingState !== \"stable\" &&\n this.peers[id].signalingState !== \"have-local-offer\"\n ) {\n console.warn(\n `[Signaling] Cannot accept OFFER in state \"${this.peers[id].signalingState}\"`,\n );\n return;\n }\n\n await this.peers[id].setRemoteDescription({\n type: \"offer\",\n sdp,\n });\n\n const pending = this.pendingIceCandidates[id] || [];\n\n for (const candidate of pending) {\n try {\n await this.peers[id].addIceCandidate(candidate);\n } catch (err) {\n console.warn(\"[ICE] Failed to add candidate:\", err);\n }\n }\n\n delete this.pendingIceCandidates[id];\n\n const answer = await this.peers[id].createAnswer();\n\n await this.peers[id].setLocalDescription(answer);\n await this.flushIce(id, this.peers[id]);\n\n this.send({\n type: \"ANSWER\",\n payload: answer.sdp,\n sender: this.myId,\n target: id,\n });\n\n console.debug(`[Answer] Sent to ${id}`);\n } catch (err) {\n console.error(`[Signaling] Failed to handle OFFER from ${id}:`, err);\n this.emitError(\n \"OFFER_HANDLING_FAILED\",\n `Failed to handle offer from ${id}`,\n err,\n true,\n );\n }\n }\n\n // ---------------- CLEANUP ----------------\n private closePeer(id: string) {\n const pc = this.peers[id];\n\n if (!pc) return;\n\n pc.ontrack = null;\n pc.onicecandidate = null;\n pc.onconnectionstatechange = null;\n\n pc.close();\n\n delete this.peers[id];\n\n this.initiators.delete(id);\n\n this.state.removeParticipant(id);\n }\n\n async startScreenShare() {\n try {\n if (this.state.presenterId && this.state.presenterId !== this.myId) {\n throw new Error(\"Another user is already sharing their screen.\");\n }\n if (!navigator.mediaDevices?.getDisplayMedia) {\n throw new Error(\"Screen sharing not supported on this device\");\n }\n\n this.screenStream = await navigator.mediaDevices.getDisplayMedia({\n video: true,\n // audio: true,\n });\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 this.state.setPresenterId(this.myId);\n // Handle the user clicking browser's built-in \"Stop Sharing\" button\n this.screenStream.getVideoTracks()[0].onended = () => {\n this.stopScreenShare();\n };\n\n Object.entries(this.peers).forEach(([peerId, pc]) => {\n this.screenSenders[peerId] = [];\n this.screenStream!.getTracks().forEach((track) => {\n const sender = pc.addTrack(track, this.screenStream!);\n this.screenSenders[peerId].push(sender);\n });\n\n // Renegotiate peer connection descriptors to notify remote side of new track footprint\n this.createOffer(peerId, true);\n });\n\n this.send({\n type: \"SCREEN_SHARE_START\",\n sender: this.myId,\n room_id: this.room.id,\n camera_id: this.localStream?.id.replace(/[{}]/g, \"\"),\n stream_id: this.screenStream.id.replace(/[{}]/g, \"\"),\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 throw err;\n }\n }\n\n stopScreenShare() {\n if (!this.screenStream) return;\n\n this.screenStream.getTracks().forEach((t) => t.stop());\n\n // Remove tracks cleanly from WebRTC channel pathways across your peers\n Object.entries(this.peers).forEach(([peerId, pc]) => {\n const senders = this.screenSenders[peerId] || [];\n senders.forEach((sender) => {\n try {\n pc.removeTrack(sender);\n } catch (err) {\n console.warn(err);\n }\n });\n delete this.screenSenders[peerId];\n\n // Renegotiate layout expectations to scale down stream bounds\n this.createOffer(peerId, true);\n });\n\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 if (this.state.presenterId === this.myId) {\n this.state.setPresenterId(null);\n }\n\n this.send({\n type: \"SCREEN_SHARE_STOP\",\n sender: this.myId,\n room_id: this.room.id,\n });\n }\n\n sendChatMessage(payload: ChatInput) {\n if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {\n console.warn(\"WS not connected\");\n return;\n }\n\n if (!this.room.id) {\n console.warn(\"No roomId set\");\n return;\n }\n\n const isPrivate = !!payload?.target;\n\n const senderName = this.state.localParticipant?.name || \"Anonymous\";\n\n const msg: ChatMessage = {\n id: crypto.randomUUID(),\n sender_id: this.myId,\n sender_name: senderName,\n text: payload.message.trim(),\n timestamp: Date.now(),\n reply_to: payload.reply_to ?? null,\n target: payload.target ?? null,\n };\n\n // optimistic UI update\n this.state.addChatMessage(msg);\n\n // send protocol payload (clean + consistent)\n this.send({\n type: \"CHAT_MESSAGE\",\n message: payload.message.trim(),\n user_id: this.myId,\n sender_name: senderName,\n room_id: this.room.id,\n target: isPrivate ? (payload.target ?? null) : null,\n reply_to: payload.reply_to ?? null,\n\n client_ts: Date.now(),\n });\n }\n\n disconnect() {\n this.intentionalDisconnect = true;\n\n this.stopScreenShare();\n\n Object.values(this.peers).forEach((pc) => pc.close());\n this.peers = {};\n this.initiators.clear();\n\n this.stopHeartbeat();\n\n if (this.ws?.readyState === WebSocket.OPEN) {\n this.send({\n type: \"LEAVE\",\n room_id: this.room.id,\n user_id: this.myId,\n sender_name: this.state.localParticipant?.name,\n });\n\n // Allow the LEAVE frame to be flushed.\n setTimeout(() => {\n this.ws?.close(1000, \"Leaving meeting\");\n this.ws = null;\n }, 50);\n }\n\n if (this.localStream) {\n this.localStream.getTracks().forEach((track) => track.stop());\n this.localStream = null;\n }\n\n this.room.id = null;\n\n this.state.localParticipant = null;\n this.state.notify(\"localParticipant\");\n\n this.state.participants.clear();\n this.state.notify(\"participants\");\n\n this.events.onMeetingLeft?.();\n\n this.state.clearChat();\n this.state.setPresenterId(null);\n }\n\n private async flushIce(id: string, pc: RTCPeerConnection) {\n const pending = this.pendingIceCandidates[id];\n if (!pending?.length) return;\n\n for (const candidate of pending) {\n try {\n await pc.addIceCandidate(candidate);\n } catch (e) {\n console.warn(\"ICE flush error\", e);\n }\n }\n\n delete this.pendingIceCandidates[id];\n }\n\n private send(msg: any) {\n this.ws?.send(JSON.stringify(msg));\n }\n\n approveJoinRequest(requestId: string) {\n this.send({\n type: \"JOIN_APPROVE\",\n request_id: requestId,\n });\n }\n\n rejectJoinRequest(requestId: string) {\n this.send({\n type: \"JOIN_REJECT\",\n request_id: requestId,\n });\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\";\n\nexport const useMeeting = (handlers?: {\n onError?: (err: any) => void;\n onEntryRequested?: (req: any) => void;\n onEntryResponded?: (payload: any, decision?: any) => void;\n onMeetingLeft?: () => 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 // 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 // Meeting Left Handler\n useEffect(() => {\n if (!handlers?.onMeetingLeft) return;\n return ctx.onMeetingLeft(handlers.onMeetingLeft);\n }, [handlers?.onMeetingLeft]);\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 };\n};\n","import { useCallback, 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 participants: {\n id: string;\n name: string;\n isHost: boolean;\n isPresenter: boolean;\n micEnabled: boolean;\n camEnabled: boolean;\n }[];\n};\n\nexport function useMeetingPreview(roomId: string, userId: string) {\n const [room, setRoom] = useState<LiveRoomState | null>(null);\n const [isLoading, setIsLoading] = useState(true);\n const [error, setError] = useState<Error | null>(null);\n\n const load = useCallback(async () => {\n if (!roomId || !userId) return;\n\n try {\n setIsLoading(true);\n setError(null);\n\n const res = await fetch(\n `${SDK_CONFIG.baseUrl}/api/rooms/${roomId}/live?user_id=${userId}`,\n );\n\n if (!res.ok) {\n throw new Error(\"Failed to fetch meeting preview\");\n }\n\n const data = await res.json();\n\n setRoom(data);\n } catch (err) {\n setError(err instanceof Error ? err : new Error(\"Unknown error\"));\n } finally {\n setIsLoading(false);\n }\n }, [roomId, userId]);\n\n useEffect(() => {\n load();\n\n const interval = setInterval(load, 5000);\n\n return () => clearInterval(interval);\n }, [load]);\n\n return {\n room,\n isLoading,\n error,\n refetch: load,\n };\n}\n"],"mappings":"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","names":["import_react","import_react","peerId","import_react","import_react","import_react","import_react"]}
package/dist/index.mjs CHANGED
@@ -1319,7 +1319,7 @@ var useRemoteMedia = (participantId) => {
1319
1319
  };
1320
1320
  };
1321
1321
 
1322
- // src/react/useMeetingPreview.tsx
1322
+ // src/react/useMeetingPreview.ts
1323
1323
  import { useCallback as useCallback2, useEffect as useEffect6, useState as useState5 } from "react";
1324
1324
  function useMeetingPreview(roomId, userId) {
1325
1325
  const [room, setRoom] = useState5(null);
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/react/useLocalParticipant.tsx","../src/react/MeetingProvider.tsx","../src/config/ws.ts","../src/core/MeetingState.ts","../src/core/VideoCore.ts","../src/react/useMeetingStore.ts","../src/react/useMeeting.ts","../src/react/useParticipants.ts","../src/react/useRemoteMedia.ts","../src/react/useMeetingPreview.tsx"],"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, { createContext, useContext, useMemo, useRef } from \"react\";\nimport { VideoSDKCore } from \"../core/VideoCore\";\nimport {\n ChatInput,\n ChatMessage,\n MeetingConfig,\n Participant,\n PubSubTopic,\n} from \"../types/meeting\";\nimport { useMeetingStore } from \"./useMeetingStore\";\n\ntype PubSubHandle = {\n messages: ChatMessage[];\n publish: (input: ChatInput) => void;\n};\n\ntype MeetingContextValue = {\n sdk: VideoSDKCore;\n join: (config?: MeetingConfig) => Promise<void>;\n leave: () => void;\n\n toggleMic: () => void;\n toggleCam: () => void;\n\n startScreenShare: () => Promise<MediaStream>;\n stopScreenShare: () => void;\n\n sendMessage: (input: ChatInput) => void;\n\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 usePubSub: (topic: PubSubTopic) => PubSubHandle;\n approveJoinRequest: (requestId: string) => void;\n rejectJoinRequest: (requestId: string) => void;\n onError: (cb: (err: any) => void) => () => void;\n onEntryRequested: (cb: (req: any) => void) => () => void;\n onEntryResponded: (cb: (payload: any, decision?: any) => void) => () => void;\n onMeetingLeft: (cb: () => 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 meetingLeftListeners = useRef(new Set<() => void>());\n\n if (!sdkRef.current) {\n sdkRef.current = new VideoSDKCore({\n onError: (err) => errorListeners.current.forEach((fn) => fn(err)),\n onEntryRequested: (req) =>\n entryRequestListeners.current.forEach((fn) => fn(req)),\n onEntryResponded: (p, d) =>\n entryResponseListeners.current.forEach((fn) => fn(p, d)),\n onMeetingLeft: () => meetingLeftListeners.current.forEach((fn) => fn()),\n });\n }\n\n const sdk = sdkRef.current;\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\n const value = useMemo<MeetingContextValue>(() => {\n if (!sdkRef.current) {\n sdkRef.current = new VideoSDKCore({\n onError: (err) => {\n errorListeners.current.forEach((fn) => fn(err));\n },\n });\n }\n\n return {\n sdk,\n\n join: (joinConfig?: MeetingConfig) =>\n sdk.joinMeeting({\n ...config,\n ...joinConfig,\n }),\n leave: () => sdk.disconnect(),\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\n room: sdk.getMeeting(),\n localParticipant,\n participants,\n messages,\n presenterId,\n usePubSub: (topic: PubSubTopic) => {\n if (topic !== \"SECURE_CHAT\") {\n throw new Error(`Unsupported PubSub argument: \"${topic}\"`);\n }\n return {\n messages: sdk.state.getChatMessages(),\n publish: sdk.sendChatMessage.bind(sdk),\n };\n },\n approveJoinRequest: sdk.approveJoinRequest.bind(sdk),\n rejectJoinRequest: sdk.rejectJoinRequest.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 onMeetingLeft: (cb: () => void) => {\n meetingLeftListeners.current.add(cb);\n return () => {\n meetingLeftListeners.current.delete(cb);\n };\n },\n };\n }, [config, sdk, localParticipant, participants, messages, presenterId]);\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","export const SDK_CONFIG = {\n wsUrl: \"wss://rust-video-server-sfyf.onrender.com/ws\",\n baseUrl: \"https://rust-video-server-sfyf.onrender.com\",\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 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\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 // ---- 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: true,\n camEnabled: true,\n 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 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 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.notify(\"participants\");\n this.notify(\"chat\");\n this.notify(\"presenter\");\n }\n}\n","import { SDK_CONFIG } from \"../config/ws\";\nimport {\n ChatInput,\n ChatMessage,\n Events,\n MeetingConfig,\n Participant,\n SDKError,\n} from \"../types/meeting\";\nimport { MeetingState } from \"./MeetingState\";\n\nexport class VideoSDKCore {\n private ws: WebSocket | null = null;\n private peers: Record<string, RTCPeerConnection> = {};\n private initiators = new Set<string>();\n private lastPong = Date.now();\n private iceServers: RTCIceServer[] = [];\n private intentionalDisconnect = false;\n\n private myId: string;\n private room: { id: string | null; name: string | null } = {\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 screenSenders: Record<string, RTCRtpSender[]> = {};\n\n private pingInterval: any = null;\n private pendingIceCandidates: Record<string, RTCIceCandidateInit[]> = {};\n private pendingOffers: Record<string, string> = {};\n private reconnectAttempts = 0;\n private reconnectTimer?: number;\n private participantName = \"\";\n public readonly state: MeetingState;\n private joinResolver?: () => void;\n private joinRejecter?: (e: any) => void;\n\n // Track if we're in the waiting room (pending approval)\n private isWaitingForApproval = false;\n private pendingRequestId: string | null = null;\n private iceTransportPolicy: RTCIceTransportPolicy = \"all\";\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 userId: this.myId,\n recoverable,\n };\n\n this.events.onError?.(err);\n\n this.joinRejecter?.(err);\n this.joinRejecter = undefined;\n\n console.error(\"[MeetingSDK Error]\", err);\n }\n\n constructor(\n private events: Events = {},\n private url: string = SDK_CONFIG.wsUrl,\n ) {\n this.state = new MeetingState();\n this.events = events;\n this.url = url;\n\n this.myId = localStorage.getItem(\"vsdk_id\") || crypto.randomUUID();\n\n localStorage.setItem(\"vsdk_id\", this.myId);\n }\n\n // ---------------- STREAM ----------------\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 // Verify tracks are actually live BEFORE connecting\n const hasVideo = this.localStream\n .getVideoTracks()\n .some((t) => t.readyState === \"live\");\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 this.state.updateLocalParticipant({\n id: this.myId,\n name: this.participantName,\n media: {\n stream: this.localStream,\n micEnabled: true,\n camEnabled: true,\n isScreenSharing: false,\n },\n });\n\n this.state.localStream = this.localStream;\n } catch (err: any) {\n this.emitError(\"GET_USER_MEDIA_FAILED\", err?.message, err, false);\n throw err;\n }\n }\n\n // ---------------- CONNECT ----------------\n async connect(roomId: string, name: string) {\n this.room.id = roomId;\n\n this.reset();\n\n return new Promise<void>((resolve, reject) => {\n this.joinResolver = resolve;\n this.joinRejecter = reject;\n this.ws = new WebSocket(this.url);\n\n this.ws.onopen = () => {\n console.log(\"WebSocket connected, sending JOIN...\");\n this.send({\n type: \"JOIN\",\n room_id: roomId,\n user_id: this.myId,\n sender_name: name,\n camera_stream_id: this.localStream?.id.replace(/[{}]/g, \"\"),\n audio_muted: this.state.localParticipant?.media?.micEnabled,\n video_muted: this.state.localParticipant?.media?.camEnabled,\n });\n };\n\n this.ws.onerror = (err) => {\n this.emitError(\"WS_ERROR\", \"WebSocket encountered an error\", err, true);\n };\n\n this.ws.onclose = (e) => {\n this.joinRejecter?.({\n code: \"WS_CLOSED\",\n message: \"Connection closed before join completed\",\n raw: e,\n });\n\n this.joinRejecter = undefined;\n\n if (this.intentionalDisconnect) {\n return; // do NOT reconnect\n }\n\n if (e.code === 1000 || e.code === 1001) {\n return;\n }\n\n // Don't auto-reconnect if waiting for approval (user must reconnect after approval)\n if (this.isWaitingForApproval) {\n return;\n }\n\n this.scheduleReconnect();\n };\n\n this.ws.onmessage = async (e) => {\n await this.handle(JSON.parse(e.data));\n };\n });\n }\n\n async joinMeeting(config: MeetingConfig) {\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 this.participantName = name;\n\n // Reuse existing stream if initLocal already configured it\n if (!this.localStream) {\n this.localStream = await navigator.mediaDevices.getUserMedia({\n video: true,\n audio: true,\n });\n }\n\n this.localStream.getAudioTracks().forEach((t) => {\n t.enabled = !audioMuted;\n });\n this.localStream.getVideoTracks().forEach((t) => {\n t.enabled = !videoMuted;\n });\n\n this.state.updateLocalParticipant({\n id: this.myId,\n name: this.participantName,\n media: {\n stream: this.localStream,\n micEnabled: !audioMuted,\n camEnabled: !videoMuted,\n isScreenSharing: false,\n },\n });\n\n this.state.localStream = this.localStream;\n\n await this.connect(roomId, name);\n }\n\n getMeeting(): { id: string | null; name: string | null } {\n return this.room;\n }\n\n toggleMic() {\n const mediaState = this.state.localParticipant?.media;\n if (!mediaState) return;\n\n const nextEnabled = !mediaState.micEnabled;\n\n this.localStream\n ?.getAudioTracks()\n .forEach((t) => (t.enabled = nextEnabled));\n\n // Update state layer\n this.state.updateLocalParticipant({\n id: this.myId,\n name: this.participantName,\n media: {\n ...mediaState,\n micEnabled: nextEnabled,\n },\n });\n\n // Notify peers\n this.send({\n type: \"MEDIA_STATE\",\n kind: \"audio\",\n enabled: nextEnabled,\n });\n }\n\n toggleCam() {\n const mediaState = this.state.localParticipant?.media;\n if (!mediaState) return;\n\n const nextEnabled = !mediaState.camEnabled;\n\n this.localStream\n ?.getVideoTracks()\n .forEach((t) => (t.enabled = nextEnabled));\n\n // Update state layer\n this.state.updateLocalParticipant({\n id: this.myId,\n name: this.participantName,\n media: {\n ...mediaState,\n camEnabled: nextEnabled,\n },\n });\n\n // Notify peers\n this.send({\n type: \"MEDIA_STATE\",\n kind: \"video\",\n enabled: nextEnabled,\n });\n }\n\n private scheduleReconnect() {\n if (!this.room.id) return;\n\n const delay = Math.min(1000 * Math.pow(2, this.reconnectAttempts), 30000);\n\n clearTimeout(this.reconnectTimer);\n\n this.reconnectTimer = window.setTimeout(async () => {\n try {\n await this.connect(this.room.id!, this.participantName);\n\n this.reconnectAttempts = 0;\n } catch {\n this.reconnectAttempts++;\n this.scheduleReconnect();\n }\n }, delay);\n }\n\n private startHeartbeat() {\n this.stopHeartbeat();\n\n this.pingInterval = setInterval(() => {\n if (!this.ws || this.ws.readyState !== WebSocket.OPEN) return;\n\n this.send({\n type: \"PING\",\n client_ts: Date.now(),\n });\n }, 20000); // every 20s\n }\n private stopHeartbeat() {\n if (this.pingInterval) {\n clearInterval(this.pingInterval);\n this.pingInterval = null;\n }\n }\n\n // ---------------- RESET ----------------\n private reset() {\n Object.values(this.peers).forEach((pc) => pc.close());\n\n this.peers = {};\n this.initiators.clear();\n this.pendingIceCandidates = {};\n\n this.state.resetRemoteState();\n }\n\n private async handleJoinApproved(msg: any) {\n console.log(\"JOIN_APPROVED received, sending new JOIN...\");\n\n this.events.onEntryResponded?.({\n participantId: msg.user_id,\n decision: \"approved\",\n });\n\n this.isWaitingForApproval = false;\n this.pendingRequestId = null;\n\n // Send JOIN again on SAME socket\n if (this.ws && this.ws.readyState === WebSocket.OPEN) {\n this.send({\n type: \"JOIN\",\n room_id: this.room.id,\n user_id: this.myId,\n sender_name: this.participantName,\n });\n console.log(\"Sent new JOIN after approval\");\n }\n }\n\n private async handle(msg: any) {\n if (msg.sender === this.myId) return;\n\n switch (msg.type) {\n case \"PONG\":\n this.lastPong = Date.now();\n break;\n case \"OFFER\":\n console.log(\"[Offer] Received from\", msg.sender, {\n sdp: msg.payload.substring(0, 200),\n });\n await this.handleOffer(msg.payload, msg.sender);\n break;\n\n case \"ANSWER\": {\n const pc = this.peers[msg.sender];\n console.log(\"[Answer] Received from\", msg.sender, {\n signalingState: pc?.signalingState,\n iceConnectionState: pc?.iceConnectionState,\n connectionState: pc?.connectionState,\n });\n\n if (!pc) return;\n\n if (pc.signalingState !== \"have-local-offer\") {\n console.warn(\n `[Signaling] Unexpected ANSWER in state \"${pc.signalingState}\", ignoring`,\n );\n return;\n }\n\n try {\n await pc.setRemoteDescription({\n type: \"answer\",\n sdp: msg.payload,\n });\n\n await this.flushIce(msg.sender, pc);\n } catch (err) {\n console.error(\"[Signaling] Failed to apply answer:\", err);\n this.emitError(\n \"ANSWER_FAILED\",\n `Failed to apply answer from ${msg.sender}`,\n err,\n true,\n );\n }\n break;\n }\n case \"ICE\": {\n const candidate = JSON.parse(msg.payload);\n\n let pc = this.peers[msg.sender];\n\n if (!pc) {\n this.pendingIceCandidates[msg.sender] ??= [];\n this.pendingIceCandidates[msg.sender].push(candidate);\n break;\n }\n\n if (!pc.remoteDescription) {\n this.pendingIceCandidates[msg.sender] ??= [];\n this.pendingIceCandidates[msg.sender].push(candidate);\n break;\n }\n\n try {\n await pc.addIceCandidate(candidate);\n } catch (err) {\n console.warn(\"ICE error:\", err);\n }\n\n break;\n }\n case \"EXISTING_USERS\":\n if (msg.presenterId) {\n this.state.setPresenterId(msg.presenterId);\n\n this.events.onScreenShareStarted?.(msg.presenterId, null!);\n this.state.setPresenterId(msg.presenterId);\n }\n\n for (const p of msg.participants || []) {\n if (!p?.id || p.id === this.myId) continue;\n const structuredParticipant: Participant = {\n id: p.id,\n name: p.name,\n isHost: p.isHost,\n isPresenter: p.isPresenter,\n media: {\n stream: null,\n screenStream: undefined,\n cameraTrack: undefined,\n screenTrack: undefined,\n audioTrack: undefined,\n micEnabled: p.micEnabled ?? true,\n camEnabled: p.camEnabled ?? true,\n isScreenSharing: p.isScreenSharing ?? false,\n remoteScreenStreamId: p.remoteScreenStreamId || undefined,\n cameraStreamId: p.cameraId || undefined,\n },\n };\n this.state.addParticipant(structuredParticipant);\n this.events.onUserJoined?.(structuredParticipant);\n\n if (p.isScreenSharing && p.remoteScreenStreamId) {\n this.state.setPresenterId(p.id);\n this.state.updateParticipantMedia(p.id, {\n isScreenSharing: true,\n remoteScreenStreamId: p.remoteScreenStreamId,\n cameraStreamId: p.cameraId || null,\n });\n }\n if (this.shouldInitiate(p.id)) {\n await this.createOffer(p.id);\n }\n }\n break;\n\n case \"JOINED\": {\n if (msg.iceServers) {\n this.iceServers = msg.iceServers;\n }\n this.room.name = msg.room_name;\n\n this.isWaitingForApproval = false;\n this.pendingRequestId = null;\n this.intentionalDisconnect = false;\n this.reconnectAttempts = 0;\n\n // Process any OFFERs that arrived before JOINED\n if (Object.keys(this.pendingOffers).length > 0) {\n console.log(\n \"Processing\",\n Object.keys(this.pendingOffers).length,\n \"pending offers\",\n );\n for (const [peerId, sdp] of Object.entries(this.pendingOffers)) {\n await this.handleOffer(sdp, peerId);\n }\n this.pendingOffers = {};\n }\n\n const media = this.state.localParticipant?.media;\n\n if (media) {\n this.send({\n type: \"MEDIA_STATE\",\n kind: \"audio\",\n enabled: !!media.micEnabled,\n });\n\n this.send({\n type: \"MEDIA_STATE\",\n kind: \"video\",\n enabled: !!media.camEnabled,\n });\n }\n this.startHeartbeat();\n this.joinResolver?.();\n this.joinResolver = undefined;\n this.joinRejecter = undefined;\n break;\n }\n case \"USER_JOINED\": {\n const p = msg.participant;\n\n if (!p?.id || p.id === this.myId) return;\n\n this.state.addParticipant(p);\n\n this.events.onUserJoined?.(p);\n if (this.shouldInitiate(p.id)) {\n await this.createOffer(p.id);\n }\n\n break;\n }\n\n case \"JOIN_PENDING\": {\n const req = msg.request;\n\n this.isWaitingForApproval = true;\n this.pendingRequestId = req.request_id;\n\n this.events.onEntryRequested?.({\n requestId: req.request_id,\n userId: req.user_id,\n name: req.name,\n });\n\n break;\n }\n\n case \"JOIN_REQUEST\": {\n const req = msg.request;\n this.events.onEntryRequested?.({\n requestId: req.id,\n userId: req.user_id,\n name: req.name,\n });\n\n break;\n }\n\n case \"JOIN_APPROVED\": {\n await this.handleJoinApproved(msg);\n break;\n }\n\n case \"JOIN_REJECTED\": {\n const decision = \"rejected\";\n\n this.isWaitingForApproval = false;\n this.pendingRequestId = null;\n\n this.events.onEntryResponded?.({\n participantId: msg.user_id,\n decision,\n });\n\n break;\n }\n\n case \"USER_LEFT\":\n const peerId = msg.participant.id;\n this.closePeer(peerId);\n\n this.state.removeParticipant(peerId);\n\n this.events.onUserLeft?.(peerId);\n\n break;\n\n case \"MEDIA_STATE_CHANGE\": {\n const peerId = msg.peerId;\n const { kind, enabled } = msg;\n\n if (kind === \"audio\") {\n this.state.updateParticipantMedia(peerId, { micEnabled: enabled });\n this.events.onMicToggled?.(peerId, enabled);\n } else if (kind === \"video\") {\n this.state.updateParticipantMedia(peerId, { camEnabled: enabled });\n this.events.onCamToggled?.(peerId, enabled);\n }\n\n break;\n }\n\n case \"CHAT_MESSAGE\": {\n const newMsg = msg.data;\n\n if (newMsg.sender_id === this.myId) break; // already added optimistically\n this.state.addChatMessage({\n id: newMsg.id,\n text: newMsg.message,\n sender_id: newMsg.sender_id,\n sender_name: newMsg.sender_name,\n timestamp: new Date(newMsg.timestamp).getTime(),\n target: newMsg.target,\n });\n\n this.events.onChatMessage?.(msg);\n break;\n }\n case \"SCREEN_SHARE_START\": {\n const peerId = msg.peerId;\n\n this.state.updateParticipantMedia(peerId, {\n isScreenSharing: true,\n remoteScreenStreamId: msg.stream_id,\n cameraStreamId: msg?.camera_stream_id,\n });\n\n if (!this.state.presenterId) {\n this.state.setPresenterId(peerId);\n }\n\n const screenStream =\n this.state.getParticipant(peerId)?.media?.screenStream;\n\n this.events.onScreenShareStarted?.(peerId, screenStream || null!);\n break;\n }\n\n case \"SCREEN_SHARE_STOP\": {\n const peerId = msg.peerId;\n this.state.updateParticipantMedia(peerId, { isScreenSharing: false });\n if (this.state.presenterId === peerId) {\n this.state.setPresenterId(null);\n }\n this.events.onScreenShareStopped?.(peerId);\n break;\n }\n case \"ERROR\": {\n const fatal = msg?.fatal === true;\n\n this.emitError(\n \"WS_ERROR\",\n msg?.message || \"Unknown error\",\n msg,\n !fatal,\n );\n\n if (fatal) {\n this.disconnect();\n }\n\n return;\n }\n }\n }\n\n // ---------------- PEER ----------------\n private createPeer(id: string) {\n if (!this.localStream) throw new Error(\"No local stream\");\n if (!this.iceServers || this.iceServers.length === 0) {\n throw new Error(\n \"ICE Servers not configured. Backend must provide iceServers on JOIN.\",\n );\n }\n\n const pc = new RTCPeerConnection({\n iceServers: this.iceServers,\n iceTransportPolicy: this.iceTransportPolicy,\n });\n\n pc.ontrack = (event) => {\n const incomingStream =\n event.streams?.[0] || new MediaStream([event.track]);\n const streamId = incomingStream?.id?.replace(/[{}]/g, \"\");\n\n const participant = this.state.getParticipant(id);\n\n const isCameraStream =\n streamId &&\n participant?.media?.cameraStreamId &&\n streamId === participant?.media?.cameraStreamId;\n\n const isScreenStream =\n streamId &&\n participant?.media?.remoteScreenStreamId &&\n streamId === participant?.media?.remoteScreenStreamId;\n\n if (event.track.muted) {\n event.track.onunmute = () => {\n console.log(`${event.track.kind} track unmuted for ${id}`);\n };\n }\n\n if (isScreenStream) {\n const videoTrack =\n event.track.kind === \"video\"\n ? event.track\n : incomingStream.getVideoTracks()[0] ||\n participant?.media?.screenTrack;\n\n this.state.updateParticipantMedia(id, {\n screenStream: incomingStream,\n screenTrack: videoTrack,\n remoteScreenStreamId: incomingStream.id,\n isScreenSharing: true,\n });\n\n if (!this.state.presenterId) {\n this.state.setPresenterId(id);\n }\n\n this.events.onScreenShareStarted?.(id, incomingStream);\n console.log(`Screen share stream detected for ${id}`);\n } else if (isCameraStream) {\n this.state.updateParticipantMedia(id, {\n stream: incomingStream,\n cameraTrack: incomingStream.getVideoTracks()[0],\n audioTrack: incomingStream.getAudioTracks()[0],\n });\n this.events.onTrack?.(incomingStream, id);\n } else {\n this.state.updateParticipantMedia(id, {\n stream: incomingStream,\n cameraTrack: incomingStream.getVideoTracks()[0],\n audioTrack: incomingStream.getAudioTracks()[0],\n });\n this.events.onTrack?.(incomingStream, id);\n }\n };\n\n pc.onicecandidate = (e) => {\n if (!e.candidate) return;\n\n console.log(\"LOCAL ICE:\", e.candidate.candidate);\n this.send({\n type: \"ICE\",\n payload: JSON.stringify(e.candidate),\n sender: this.myId,\n target: id,\n });\n };\n\n pc.oniceconnectionstatechange = async () => {\n console.log(\"================================\");\n console.log(`Peer: ${id}`);\n console.log(`ICE: ${pc.iceConnectionState}`);\n console.log(`Connection: ${pc.connectionState}`);\n console.log(`Signaling: ${pc.signalingState}`);\n\n if (pc.iceConnectionState === \"disconnected\") {\n const stats = await pc.getStats();\n\n stats.forEach((report) => {\n if (report.type === \"transport\") {\n console.log(JSON.stringify(report, null, 2));\n }\n });\n }\n };\n\n pc.onconnectionstatechange = () => {\n if (pc.connectionState === \"failed\") {\n try {\n pc.restartIce();\n } catch {}\n }\n };\n\n this.localStream.getTracks().forEach((track) => {\n pc.addTrack(track, this.localStream!);\n });\n\n if (this.isScreenSharing && this.screenStream) {\n this.screenSenders[id] = [];\n this.screenStream.getTracks().forEach((track) => {\n const sender = pc.addTrack(track, this.screenStream!);\n this.screenSenders[id].push(sender);\n });\n }\n\n return pc;\n }\n\n // ---------------- OFFER ----------------\n private async createOffer(id: string, isRenegotiation = false) {\n if (!isRenegotiation && !this.shouldInitiate(id)) {\n console.debug(\n `[Offer] ${id} should initiate (${id} > ${this.myId}), skipping`,\n );\n return;\n }\n\n if (!isRenegotiation && this.initiators.has(id)) {\n console.debug(\n `[Offer] Already initiating with ${id}, skipping duplicate`,\n );\n return; // ← This was missing!\n }\n\n if (!isRenegotiation) {\n this.initiators.add(id);\n }\n if (!this.peers[id]) {\n this.peers[id] = this.createPeer(id);\n }\n\n const pc = this.peers[id];\n\n try {\n const offer = await pc.createOffer();\n await pc.setLocalDescription(offer);\n\n this.send({\n type: \"OFFER\",\n payload: offer.sdp,\n sender: this.myId,\n target: id,\n });\n\n console.debug(`[Offer] Sent to ${id}`);\n } catch (err) {\n console.error(`[Offer] Failed for ${id}:`, err);\n }\n }\n\n private shouldInitiate(peerId: string): boolean {\n // Lexicographic comparison: lower ID initiates\n return this.myId < peerId;\n }\n\n // ---------------- ANSWER ----------------\n private async handleOffer(sdp: string, id: string) {\n if (!this.iceServers || this.iceServers.length === 0) {\n console.warn(\"[Offer] Waiting for iceServers, queuing offer from\", id);\n this.pendingOffers[id] = sdp;\n return;\n }\n\n if (!this.peers[id]) {\n this.peers[id] = this.createPeer(id);\n }\n\n const pc = this.peers[id];\n\n try {\n // GLARE RECOVERY: Both peers sent OFFERs simultaneously\n if (pc.signalingState === \"have-local-offer\") {\n if (this.shouldInitiate(id)) {\n // WE WIN: Keep our offer, reject theirs\n console.warn(\n `[Glare] Both sent OFFERs, we win (${this.myId} < ${id}), keeping our OFFER`,\n );\n return; // Ignore their offer, wait for their ANSWER\n } else {\n // THEY WIN: Roll back and accept their offer\n console.warn(\n `[Glare] Both sent OFFERs, they win (${id} < ${this.myId}), rolling back`,\n );\n pc.close();\n delete this.peers[id];\n this.initiators.delete(id);\n\n // Create fresh peer connection to answer their offer\n this.peers[id] = this.createPeer(id);\n }\n }\n\n // Only set remote description if we're not already in negotiation\n if (\n this.peers[id].signalingState !== \"stable\" &&\n this.peers[id].signalingState !== \"have-local-offer\"\n ) {\n console.warn(\n `[Signaling] Cannot accept OFFER in state \"${this.peers[id].signalingState}\"`,\n );\n return;\n }\n\n await this.peers[id].setRemoteDescription({\n type: \"offer\",\n sdp,\n });\n\n const pending = this.pendingIceCandidates[id] || [];\n\n for (const candidate of pending) {\n try {\n await this.peers[id].addIceCandidate(candidate);\n } catch (err) {\n console.warn(\"[ICE] Failed to add candidate:\", err);\n }\n }\n\n delete this.pendingIceCandidates[id];\n\n const answer = await this.peers[id].createAnswer();\n\n await this.peers[id].setLocalDescription(answer);\n await this.flushIce(id, this.peers[id]);\n\n this.send({\n type: \"ANSWER\",\n payload: answer.sdp,\n sender: this.myId,\n target: id,\n });\n\n console.debug(`[Answer] Sent to ${id}`);\n } catch (err) {\n console.error(`[Signaling] Failed to handle OFFER from ${id}:`, err);\n this.emitError(\n \"OFFER_HANDLING_FAILED\",\n `Failed to handle offer from ${id}`,\n err,\n true,\n );\n }\n }\n\n // ---------------- CLEANUP ----------------\n private closePeer(id: string) {\n const pc = this.peers[id];\n\n if (!pc) return;\n\n pc.ontrack = null;\n pc.onicecandidate = null;\n pc.onconnectionstatechange = null;\n\n pc.close();\n\n delete this.peers[id];\n\n this.initiators.delete(id);\n\n this.state.removeParticipant(id);\n }\n\n async startScreenShare() {\n try {\n if (this.state.presenterId && this.state.presenterId !== this.myId) {\n throw new Error(\"Another user is already sharing their screen.\");\n }\n if (!navigator.mediaDevices?.getDisplayMedia) {\n throw new Error(\"Screen sharing not supported on this device\");\n }\n\n this.screenStream = await navigator.mediaDevices.getDisplayMedia({\n video: true,\n // audio: true,\n });\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 this.state.setPresenterId(this.myId);\n // Handle the user clicking browser's built-in \"Stop Sharing\" button\n this.screenStream.getVideoTracks()[0].onended = () => {\n this.stopScreenShare();\n };\n\n Object.entries(this.peers).forEach(([peerId, pc]) => {\n this.screenSenders[peerId] = [];\n this.screenStream!.getTracks().forEach((track) => {\n const sender = pc.addTrack(track, this.screenStream!);\n this.screenSenders[peerId].push(sender);\n });\n\n // Renegotiate peer connection descriptors to notify remote side of new track footprint\n this.createOffer(peerId, true);\n });\n\n this.send({\n type: \"SCREEN_SHARE_START\",\n sender: this.myId,\n room_id: this.room.id,\n camera_id: this.localStream?.id.replace(/[{}]/g, \"\"),\n stream_id: this.screenStream.id.replace(/[{}]/g, \"\"),\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 throw err;\n }\n }\n\n stopScreenShare() {\n if (!this.screenStream) return;\n\n this.screenStream.getTracks().forEach((t) => t.stop());\n\n // Remove tracks cleanly from WebRTC channel pathways across your peers\n Object.entries(this.peers).forEach(([peerId, pc]) => {\n const senders = this.screenSenders[peerId] || [];\n senders.forEach((sender) => {\n try {\n pc.removeTrack(sender);\n } catch (err) {\n console.warn(err);\n }\n });\n delete this.screenSenders[peerId];\n\n // Renegotiate layout expectations to scale down stream bounds\n this.createOffer(peerId, true);\n });\n\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 if (this.state.presenterId === this.myId) {\n this.state.setPresenterId(null);\n }\n\n this.send({\n type: \"SCREEN_SHARE_STOP\",\n sender: this.myId,\n room_id: this.room.id,\n });\n }\n\n sendChatMessage(payload: ChatInput) {\n if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {\n console.warn(\"WS not connected\");\n return;\n }\n\n if (!this.room.id) {\n console.warn(\"No roomId set\");\n return;\n }\n\n const isPrivate = !!payload?.target;\n\n const senderName = this.state.localParticipant?.name || \"Anonymous\";\n\n const msg: ChatMessage = {\n id: crypto.randomUUID(),\n sender_id: this.myId,\n sender_name: senderName,\n text: payload.message.trim(),\n timestamp: Date.now(),\n reply_to: payload.reply_to ?? null,\n target: payload.target ?? null,\n };\n\n // optimistic UI update\n this.state.addChatMessage(msg);\n\n // send protocol payload (clean + consistent)\n this.send({\n type: \"CHAT_MESSAGE\",\n message: payload.message.trim(),\n user_id: this.myId,\n sender_name: senderName,\n room_id: this.room.id,\n target: isPrivate ? (payload.target ?? null) : null,\n reply_to: payload.reply_to ?? null,\n\n client_ts: Date.now(),\n });\n }\n\n disconnect() {\n this.intentionalDisconnect = true;\n\n this.stopScreenShare();\n\n Object.values(this.peers).forEach((pc) => pc.close());\n this.peers = {};\n this.initiators.clear();\n\n this.stopHeartbeat();\n\n if (this.ws?.readyState === WebSocket.OPEN) {\n this.send({\n type: \"LEAVE\",\n room_id: this.room.id,\n user_id: this.myId,\n sender_name: this.state.localParticipant?.name,\n });\n\n // Allow the LEAVE frame to be flushed.\n setTimeout(() => {\n this.ws?.close(1000, \"Leaving meeting\");\n this.ws = null;\n }, 50);\n }\n\n if (this.localStream) {\n this.localStream.getTracks().forEach((track) => track.stop());\n this.localStream = null;\n }\n\n this.room.id = null;\n\n this.state.localParticipant = null;\n this.state.notify(\"localParticipant\");\n\n this.state.participants.clear();\n this.state.notify(\"participants\");\n\n this.events.onMeetingLeft?.();\n\n this.state.clearChat();\n this.state.setPresenterId(null);\n }\n\n private async flushIce(id: string, pc: RTCPeerConnection) {\n const pending = this.pendingIceCandidates[id];\n if (!pending?.length) return;\n\n for (const candidate of pending) {\n try {\n await pc.addIceCandidate(candidate);\n } catch (e) {\n console.warn(\"ICE flush error\", e);\n }\n }\n\n delete this.pendingIceCandidates[id];\n }\n\n private send(msg: any) {\n this.ws?.send(JSON.stringify(msg));\n }\n\n approveJoinRequest(requestId: string) {\n this.send({\n type: \"JOIN_APPROVE\",\n request_id: requestId,\n });\n }\n\n rejectJoinRequest(requestId: string) {\n this.send({\n type: \"JOIN_REJECT\",\n request_id: requestId,\n });\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\";\n\nexport const useMeeting = (handlers?: {\n onError?: (err: any) => void;\n onEntryRequested?: (req: any) => void;\n onEntryResponded?: (payload: any, decision?: any) => void;\n onMeetingLeft?: () => 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 // 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 // Meeting Left Handler\n useEffect(() => {\n if (!handlers?.onMeetingLeft) return;\n return ctx.onMeetingLeft(handlers.onMeetingLeft);\n }, [handlers?.onMeetingLeft]);\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 };\n};\n","import { useCallback, 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 participants: {\n id: string;\n name: string;\n isHost: boolean;\n isPresenter: boolean;\n micEnabled: boolean;\n camEnabled: boolean;\n }[];\n};\n\nexport function useMeetingPreview(roomId: string, userId: string) {\n const [room, setRoom] = useState<LiveRoomState | null>(null);\n const [isLoading, setIsLoading] = useState(true);\n const [error, setError] = useState<Error | null>(null);\n\n const load = useCallback(async () => {\n if (!roomId || !userId) return;\n\n try {\n setIsLoading(true);\n setError(null);\n\n const res = await fetch(\n `${SDK_CONFIG.baseUrl}/api/rooms/${roomId}/live?user_id=${userId}`,\n );\n\n if (!res.ok) {\n throw new Error(\"Failed to fetch meeting preview\");\n }\n\n const data = await res.json();\n\n setRoom(data);\n } catch (err) {\n setError(err instanceof Error ? err : new Error(\"Unknown error\"));\n } finally {\n setIsLoading(false);\n }\n }, [roomId, userId]);\n\n useEffect(() => {\n load();\n\n const interval = setInterval(load, 5000);\n\n return () => clearInterval(interval);\n }, [load]);\n\n return {\n room,\n isLoading,\n error,\n refetch: load,\n };\n}\n"],"mappings":"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","names":["useEffect","useRef","useState","peerId","useState","useEffect","useRef","useEffect","useEffect","useEffect","useState","useState","useEffect","useEffect","useRef","useState","useRef","useState","useEffect","useCallback","useEffect","useState","useState","useCallback","useEffect"]}
1
+ {"version":3,"sources":["../src/react/useLocalParticipant.tsx","../src/react/MeetingProvider.tsx","../src/config/ws.ts","../src/core/MeetingState.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"],"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, { createContext, useContext, useMemo, useRef } from \"react\";\nimport { VideoSDKCore } from \"../core/VideoCore\";\nimport {\n ChatInput,\n ChatMessage,\n MeetingConfig,\n Participant,\n PubSubTopic,\n} from \"../types/meeting\";\nimport { useMeetingStore } from \"./useMeetingStore\";\n\ntype PubSubHandle = {\n messages: ChatMessage[];\n publish: (input: ChatInput) => void;\n};\n\ntype MeetingContextValue = {\n sdk: VideoSDKCore;\n join: (config?: MeetingConfig) => Promise<void>;\n leave: () => void;\n\n toggleMic: () => void;\n toggleCam: () => void;\n\n startScreenShare: () => Promise<MediaStream>;\n stopScreenShare: () => void;\n\n sendMessage: (input: ChatInput) => void;\n\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 usePubSub: (topic: PubSubTopic) => PubSubHandle;\n approveJoinRequest: (requestId: string) => void;\n rejectJoinRequest: (requestId: string) => void;\n onError: (cb: (err: any) => void) => () => void;\n onEntryRequested: (cb: (req: any) => void) => () => void;\n onEntryResponded: (cb: (payload: any, decision?: any) => void) => () => void;\n onMeetingLeft: (cb: () => 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 meetingLeftListeners = useRef(new Set<() => void>());\n\n if (!sdkRef.current) {\n sdkRef.current = new VideoSDKCore({\n onError: (err) => errorListeners.current.forEach((fn) => fn(err)),\n onEntryRequested: (req) =>\n entryRequestListeners.current.forEach((fn) => fn(req)),\n onEntryResponded: (p, d) =>\n entryResponseListeners.current.forEach((fn) => fn(p, d)),\n onMeetingLeft: () => meetingLeftListeners.current.forEach((fn) => fn()),\n });\n }\n\n const sdk = sdkRef.current;\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\n const value = useMemo<MeetingContextValue>(() => {\n if (!sdkRef.current) {\n sdkRef.current = new VideoSDKCore({\n onError: (err) => {\n errorListeners.current.forEach((fn) => fn(err));\n },\n });\n }\n\n return {\n sdk,\n\n join: (joinConfig?: MeetingConfig) =>\n sdk.joinMeeting({\n ...config,\n ...joinConfig,\n }),\n leave: () => sdk.disconnect(),\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\n room: sdk.getMeeting(),\n localParticipant,\n participants,\n messages,\n presenterId,\n usePubSub: (topic: PubSubTopic) => {\n if (topic !== \"SECURE_CHAT\") {\n throw new Error(`Unsupported PubSub argument: \"${topic}\"`);\n }\n return {\n messages: sdk.state.getChatMessages(),\n publish: sdk.sendChatMessage.bind(sdk),\n };\n },\n approveJoinRequest: sdk.approveJoinRequest.bind(sdk),\n rejectJoinRequest: sdk.rejectJoinRequest.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 onMeetingLeft: (cb: () => void) => {\n meetingLeftListeners.current.add(cb);\n return () => {\n meetingLeftListeners.current.delete(cb);\n };\n },\n };\n }, [config, sdk, localParticipant, participants, messages, presenterId]);\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","export const SDK_CONFIG = {\n wsUrl: \"wss://rust-video-server-sfyf.onrender.com/ws\",\n baseUrl: \"https://rust-video-server-sfyf.onrender.com\",\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 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\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 // ---- 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: true,\n camEnabled: true,\n 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 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 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.notify(\"participants\");\n this.notify(\"chat\");\n this.notify(\"presenter\");\n }\n}\n","import { SDK_CONFIG } from \"../config/ws\";\nimport {\n ChatInput,\n ChatMessage,\n Events,\n MeetingConfig,\n Participant,\n SDKError,\n} from \"../types/meeting\";\nimport { MeetingState } from \"./MeetingState\";\n\nexport class VideoSDKCore {\n private ws: WebSocket | null = null;\n private peers: Record<string, RTCPeerConnection> = {};\n private initiators = new Set<string>();\n private lastPong = Date.now();\n private iceServers: RTCIceServer[] = [];\n private intentionalDisconnect = false;\n\n private myId: string;\n private room: { id: string | null; name: string | null } = {\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 screenSenders: Record<string, RTCRtpSender[]> = {};\n\n private pingInterval: any = null;\n private pendingIceCandidates: Record<string, RTCIceCandidateInit[]> = {};\n private pendingOffers: Record<string, string> = {};\n private reconnectAttempts = 0;\n private reconnectTimer?: number;\n private participantName = \"\";\n public readonly state: MeetingState;\n private joinResolver?: () => void;\n private joinRejecter?: (e: any) => void;\n\n // Track if we're in the waiting room (pending approval)\n private isWaitingForApproval = false;\n private pendingRequestId: string | null = null;\n private iceTransportPolicy: RTCIceTransportPolicy = \"all\";\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 userId: this.myId,\n recoverable,\n };\n\n this.events.onError?.(err);\n\n this.joinRejecter?.(err);\n this.joinRejecter = undefined;\n\n console.error(\"[MeetingSDK Error]\", err);\n }\n\n constructor(\n private events: Events = {},\n private url: string = SDK_CONFIG.wsUrl,\n ) {\n this.state = new MeetingState();\n this.events = events;\n this.url = url;\n\n this.myId = localStorage.getItem(\"vsdk_id\") || crypto.randomUUID();\n\n localStorage.setItem(\"vsdk_id\", this.myId);\n }\n\n // ---------------- STREAM ----------------\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 // Verify tracks are actually live BEFORE connecting\n const hasVideo = this.localStream\n .getVideoTracks()\n .some((t) => t.readyState === \"live\");\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 this.state.updateLocalParticipant({\n id: this.myId,\n name: this.participantName,\n media: {\n stream: this.localStream,\n micEnabled: true,\n camEnabled: true,\n isScreenSharing: false,\n },\n });\n\n this.state.localStream = this.localStream;\n } catch (err: any) {\n this.emitError(\"GET_USER_MEDIA_FAILED\", err?.message, err, false);\n throw err;\n }\n }\n\n // ---------------- CONNECT ----------------\n async connect(roomId: string, name: string) {\n this.room.id = roomId;\n\n this.reset();\n\n return new Promise<void>((resolve, reject) => {\n this.joinResolver = resolve;\n this.joinRejecter = reject;\n this.ws = new WebSocket(this.url);\n\n this.ws.onopen = () => {\n console.log(\"WebSocket connected, sending JOIN...\");\n this.send({\n type: \"JOIN\",\n room_id: roomId,\n user_id: this.myId,\n sender_name: name,\n camera_stream_id: this.localStream?.id.replace(/[{}]/g, \"\"),\n audio_muted: this.state.localParticipant?.media?.micEnabled,\n video_muted: this.state.localParticipant?.media?.camEnabled,\n });\n };\n\n this.ws.onerror = (err) => {\n this.emitError(\"WS_ERROR\", \"WebSocket encountered an error\", err, true);\n };\n\n this.ws.onclose = (e) => {\n this.joinRejecter?.({\n code: \"WS_CLOSED\",\n message: \"Connection closed before join completed\",\n raw: e,\n });\n\n this.joinRejecter = undefined;\n\n if (this.intentionalDisconnect) {\n return; // do NOT reconnect\n }\n\n if (e.code === 1000 || e.code === 1001) {\n return;\n }\n\n // Don't auto-reconnect if waiting for approval (user must reconnect after approval)\n if (this.isWaitingForApproval) {\n return;\n }\n\n this.scheduleReconnect();\n };\n\n this.ws.onmessage = async (e) => {\n await this.handle(JSON.parse(e.data));\n };\n });\n }\n\n async joinMeeting(config: MeetingConfig) {\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 this.participantName = name;\n\n // Reuse existing stream if initLocal already configured it\n if (!this.localStream) {\n this.localStream = await navigator.mediaDevices.getUserMedia({\n video: true,\n audio: true,\n });\n }\n\n this.localStream.getAudioTracks().forEach((t) => {\n t.enabled = !audioMuted;\n });\n this.localStream.getVideoTracks().forEach((t) => {\n t.enabled = !videoMuted;\n });\n\n this.state.updateLocalParticipant({\n id: this.myId,\n name: this.participantName,\n media: {\n stream: this.localStream,\n micEnabled: !audioMuted,\n camEnabled: !videoMuted,\n isScreenSharing: false,\n },\n });\n\n this.state.localStream = this.localStream;\n\n await this.connect(roomId, name);\n }\n\n getMeeting(): { id: string | null; name: string | null } {\n return this.room;\n }\n\n toggleMic() {\n const mediaState = this.state.localParticipant?.media;\n if (!mediaState) return;\n\n const nextEnabled = !mediaState.micEnabled;\n\n this.localStream\n ?.getAudioTracks()\n .forEach((t) => (t.enabled = nextEnabled));\n\n // Update state layer\n this.state.updateLocalParticipant({\n id: this.myId,\n name: this.participantName,\n media: {\n ...mediaState,\n micEnabled: nextEnabled,\n },\n });\n\n // Notify peers\n this.send({\n type: \"MEDIA_STATE\",\n kind: \"audio\",\n enabled: nextEnabled,\n });\n }\n\n toggleCam() {\n const mediaState = this.state.localParticipant?.media;\n if (!mediaState) return;\n\n const nextEnabled = !mediaState.camEnabled;\n\n this.localStream\n ?.getVideoTracks()\n .forEach((t) => (t.enabled = nextEnabled));\n\n // Update state layer\n this.state.updateLocalParticipant({\n id: this.myId,\n name: this.participantName,\n media: {\n ...mediaState,\n camEnabled: nextEnabled,\n },\n });\n\n // Notify peers\n this.send({\n type: \"MEDIA_STATE\",\n kind: \"video\",\n enabled: nextEnabled,\n });\n }\n\n private scheduleReconnect() {\n if (!this.room.id) return;\n\n const delay = Math.min(1000 * Math.pow(2, this.reconnectAttempts), 30000);\n\n clearTimeout(this.reconnectTimer);\n\n this.reconnectTimer = window.setTimeout(async () => {\n try {\n await this.connect(this.room.id!, this.participantName);\n\n this.reconnectAttempts = 0;\n } catch {\n this.reconnectAttempts++;\n this.scheduleReconnect();\n }\n }, delay);\n }\n\n private startHeartbeat() {\n this.stopHeartbeat();\n\n this.pingInterval = setInterval(() => {\n if (!this.ws || this.ws.readyState !== WebSocket.OPEN) return;\n\n this.send({\n type: \"PING\",\n client_ts: Date.now(),\n });\n }, 20000); // every 20s\n }\n private stopHeartbeat() {\n if (this.pingInterval) {\n clearInterval(this.pingInterval);\n this.pingInterval = null;\n }\n }\n\n // ---------------- RESET ----------------\n private reset() {\n Object.values(this.peers).forEach((pc) => pc.close());\n\n this.peers = {};\n this.initiators.clear();\n this.pendingIceCandidates = {};\n\n this.state.resetRemoteState();\n }\n\n private async handleJoinApproved(msg: any) {\n console.log(\"JOIN_APPROVED received, sending new JOIN...\");\n\n this.events.onEntryResponded?.({\n participantId: msg.user_id,\n decision: \"approved\",\n });\n\n this.isWaitingForApproval = false;\n this.pendingRequestId = null;\n\n // Send JOIN again on SAME socket\n if (this.ws && this.ws.readyState === WebSocket.OPEN) {\n this.send({\n type: \"JOIN\",\n room_id: this.room.id,\n user_id: this.myId,\n sender_name: this.participantName,\n });\n console.log(\"Sent new JOIN after approval\");\n }\n }\n\n private async handle(msg: any) {\n if (msg.sender === this.myId) return;\n\n switch (msg.type) {\n case \"PONG\":\n this.lastPong = Date.now();\n break;\n case \"OFFER\":\n console.log(\"[Offer] Received from\", msg.sender, {\n sdp: msg.payload.substring(0, 200),\n });\n await this.handleOffer(msg.payload, msg.sender);\n break;\n\n case \"ANSWER\": {\n const pc = this.peers[msg.sender];\n console.log(\"[Answer] Received from\", msg.sender, {\n signalingState: pc?.signalingState,\n iceConnectionState: pc?.iceConnectionState,\n connectionState: pc?.connectionState,\n });\n\n if (!pc) return;\n\n if (pc.signalingState !== \"have-local-offer\") {\n console.warn(\n `[Signaling] Unexpected ANSWER in state \"${pc.signalingState}\", ignoring`,\n );\n return;\n }\n\n try {\n await pc.setRemoteDescription({\n type: \"answer\",\n sdp: msg.payload,\n });\n\n await this.flushIce(msg.sender, pc);\n } catch (err) {\n console.error(\"[Signaling] Failed to apply answer:\", err);\n this.emitError(\n \"ANSWER_FAILED\",\n `Failed to apply answer from ${msg.sender}`,\n err,\n true,\n );\n }\n break;\n }\n case \"ICE\": {\n const candidate = JSON.parse(msg.payload);\n\n let pc = this.peers[msg.sender];\n\n if (!pc) {\n this.pendingIceCandidates[msg.sender] ??= [];\n this.pendingIceCandidates[msg.sender].push(candidate);\n break;\n }\n\n if (!pc.remoteDescription) {\n this.pendingIceCandidates[msg.sender] ??= [];\n this.pendingIceCandidates[msg.sender].push(candidate);\n break;\n }\n\n try {\n await pc.addIceCandidate(candidate);\n } catch (err) {\n console.warn(\"ICE error:\", err);\n }\n\n break;\n }\n case \"EXISTING_USERS\":\n if (msg.presenterId) {\n this.state.setPresenterId(msg.presenterId);\n\n this.events.onScreenShareStarted?.(msg.presenterId, null!);\n this.state.setPresenterId(msg.presenterId);\n }\n\n for (const p of msg.participants || []) {\n if (!p?.id || p.id === this.myId) continue;\n const structuredParticipant: Participant = {\n id: p.id,\n name: p.name,\n isHost: p.isHost,\n isPresenter: p.isPresenter,\n media: {\n stream: null,\n screenStream: undefined,\n cameraTrack: undefined,\n screenTrack: undefined,\n audioTrack: undefined,\n micEnabled: p.micEnabled ?? true,\n camEnabled: p.camEnabled ?? true,\n isScreenSharing: p.isScreenSharing ?? false,\n remoteScreenStreamId: p.remoteScreenStreamId || undefined,\n cameraStreamId: p.cameraId || undefined,\n },\n };\n this.state.addParticipant(structuredParticipant);\n this.events.onUserJoined?.(structuredParticipant);\n\n if (p.isScreenSharing && p.remoteScreenStreamId) {\n this.state.setPresenterId(p.id);\n this.state.updateParticipantMedia(p.id, {\n isScreenSharing: true,\n remoteScreenStreamId: p.remoteScreenStreamId,\n cameraStreamId: p.cameraId || null,\n });\n }\n if (this.shouldInitiate(p.id)) {\n await this.createOffer(p.id);\n }\n }\n break;\n\n case \"JOINED\": {\n if (msg.iceServers) {\n this.iceServers = msg.iceServers;\n }\n this.room.name = msg.room_name;\n\n this.isWaitingForApproval = false;\n this.pendingRequestId = null;\n this.intentionalDisconnect = false;\n this.reconnectAttempts = 0;\n\n // Process any OFFERs that arrived before JOINED\n if (Object.keys(this.pendingOffers).length > 0) {\n console.log(\n \"Processing\",\n Object.keys(this.pendingOffers).length,\n \"pending offers\",\n );\n for (const [peerId, sdp] of Object.entries(this.pendingOffers)) {\n await this.handleOffer(sdp, peerId);\n }\n this.pendingOffers = {};\n }\n\n const media = this.state.localParticipant?.media;\n\n if (media) {\n this.send({\n type: \"MEDIA_STATE\",\n kind: \"audio\",\n enabled: !!media.micEnabled,\n });\n\n this.send({\n type: \"MEDIA_STATE\",\n kind: \"video\",\n enabled: !!media.camEnabled,\n });\n }\n this.startHeartbeat();\n this.joinResolver?.();\n this.joinResolver = undefined;\n this.joinRejecter = undefined;\n break;\n }\n case \"USER_JOINED\": {\n const p = msg.participant;\n\n if (!p?.id || p.id === this.myId) return;\n\n this.state.addParticipant(p);\n\n this.events.onUserJoined?.(p);\n if (this.shouldInitiate(p.id)) {\n await this.createOffer(p.id);\n }\n\n break;\n }\n\n case \"JOIN_PENDING\": {\n const req = msg.request;\n\n this.isWaitingForApproval = true;\n this.pendingRequestId = req.request_id;\n\n this.events.onEntryRequested?.({\n requestId: req.request_id,\n userId: req.user_id,\n name: req.name,\n });\n\n break;\n }\n\n case \"JOIN_REQUEST\": {\n const req = msg.request;\n this.events.onEntryRequested?.({\n requestId: req.id,\n userId: req.user_id,\n name: req.name,\n });\n\n break;\n }\n\n case \"JOIN_APPROVED\": {\n await this.handleJoinApproved(msg);\n break;\n }\n\n case \"JOIN_REJECTED\": {\n const decision = \"rejected\";\n\n this.isWaitingForApproval = false;\n this.pendingRequestId = null;\n\n this.events.onEntryResponded?.({\n participantId: msg.user_id,\n decision,\n });\n\n break;\n }\n\n case \"USER_LEFT\":\n const peerId = msg.participant.id;\n this.closePeer(peerId);\n\n this.state.removeParticipant(peerId);\n\n this.events.onUserLeft?.(peerId);\n\n break;\n\n case \"MEDIA_STATE_CHANGE\": {\n const peerId = msg.peerId;\n const { kind, enabled } = msg;\n\n if (kind === \"audio\") {\n this.state.updateParticipantMedia(peerId, { micEnabled: enabled });\n this.events.onMicToggled?.(peerId, enabled);\n } else if (kind === \"video\") {\n this.state.updateParticipantMedia(peerId, { camEnabled: enabled });\n this.events.onCamToggled?.(peerId, enabled);\n }\n\n break;\n }\n\n case \"CHAT_MESSAGE\": {\n const newMsg = msg.data;\n\n if (newMsg.sender_id === this.myId) break; // already added optimistically\n this.state.addChatMessage({\n id: newMsg.id,\n text: newMsg.message,\n sender_id: newMsg.sender_id,\n sender_name: newMsg.sender_name,\n timestamp: new Date(newMsg.timestamp).getTime(),\n target: newMsg.target,\n });\n\n this.events.onChatMessage?.(msg);\n break;\n }\n case \"SCREEN_SHARE_START\": {\n const peerId = msg.peerId;\n\n this.state.updateParticipantMedia(peerId, {\n isScreenSharing: true,\n remoteScreenStreamId: msg.stream_id,\n cameraStreamId: msg?.camera_stream_id,\n });\n\n if (!this.state.presenterId) {\n this.state.setPresenterId(peerId);\n }\n\n const screenStream =\n this.state.getParticipant(peerId)?.media?.screenStream;\n\n this.events.onScreenShareStarted?.(peerId, screenStream || null!);\n break;\n }\n\n case \"SCREEN_SHARE_STOP\": {\n const peerId = msg.peerId;\n this.state.updateParticipantMedia(peerId, { isScreenSharing: false });\n if (this.state.presenterId === peerId) {\n this.state.setPresenterId(null);\n }\n this.events.onScreenShareStopped?.(peerId);\n break;\n }\n case \"ERROR\": {\n const fatal = msg?.fatal === true;\n\n this.emitError(\n \"WS_ERROR\",\n msg?.message || \"Unknown error\",\n msg,\n !fatal,\n );\n\n if (fatal) {\n this.disconnect();\n }\n\n return;\n }\n }\n }\n\n // ---------------- PEER ----------------\n private createPeer(id: string) {\n if (!this.localStream) throw new Error(\"No local stream\");\n if (!this.iceServers || this.iceServers.length === 0) {\n throw new Error(\n \"ICE Servers not configured. Backend must provide iceServers on JOIN.\",\n );\n }\n\n const pc = new RTCPeerConnection({\n iceServers: this.iceServers,\n iceTransportPolicy: this.iceTransportPolicy,\n });\n\n pc.ontrack = (event) => {\n const incomingStream =\n event.streams?.[0] || new MediaStream([event.track]);\n const streamId = incomingStream?.id?.replace(/[{}]/g, \"\");\n\n const participant = this.state.getParticipant(id);\n\n const isCameraStream =\n streamId &&\n participant?.media?.cameraStreamId &&\n streamId === participant?.media?.cameraStreamId;\n\n const isScreenStream =\n streamId &&\n participant?.media?.remoteScreenStreamId &&\n streamId === participant?.media?.remoteScreenStreamId;\n\n if (event.track.muted) {\n event.track.onunmute = () => {\n console.log(`${event.track.kind} track unmuted for ${id}`);\n };\n }\n\n if (isScreenStream) {\n const videoTrack =\n event.track.kind === \"video\"\n ? event.track\n : incomingStream.getVideoTracks()[0] ||\n participant?.media?.screenTrack;\n\n this.state.updateParticipantMedia(id, {\n screenStream: incomingStream,\n screenTrack: videoTrack,\n remoteScreenStreamId: incomingStream.id,\n isScreenSharing: true,\n });\n\n if (!this.state.presenterId) {\n this.state.setPresenterId(id);\n }\n\n this.events.onScreenShareStarted?.(id, incomingStream);\n console.log(`Screen share stream detected for ${id}`);\n } else if (isCameraStream) {\n this.state.updateParticipantMedia(id, {\n stream: incomingStream,\n cameraTrack: incomingStream.getVideoTracks()[0],\n audioTrack: incomingStream.getAudioTracks()[0],\n });\n this.events.onTrack?.(incomingStream, id);\n } else {\n this.state.updateParticipantMedia(id, {\n stream: incomingStream,\n cameraTrack: incomingStream.getVideoTracks()[0],\n audioTrack: incomingStream.getAudioTracks()[0],\n });\n this.events.onTrack?.(incomingStream, id);\n }\n };\n\n pc.onicecandidate = (e) => {\n if (!e.candidate) return;\n\n console.log(\"LOCAL ICE:\", e.candidate.candidate);\n this.send({\n type: \"ICE\",\n payload: JSON.stringify(e.candidate),\n sender: this.myId,\n target: id,\n });\n };\n\n pc.oniceconnectionstatechange = async () => {\n console.log(\"================================\");\n console.log(`Peer: ${id}`);\n console.log(`ICE: ${pc.iceConnectionState}`);\n console.log(`Connection: ${pc.connectionState}`);\n console.log(`Signaling: ${pc.signalingState}`);\n\n if (pc.iceConnectionState === \"disconnected\") {\n const stats = await pc.getStats();\n\n stats.forEach((report) => {\n if (report.type === \"transport\") {\n console.log(JSON.stringify(report, null, 2));\n }\n });\n }\n };\n\n pc.onconnectionstatechange = () => {\n if (pc.connectionState === \"failed\") {\n try {\n pc.restartIce();\n } catch {}\n }\n };\n\n this.localStream.getTracks().forEach((track) => {\n pc.addTrack(track, this.localStream!);\n });\n\n if (this.isScreenSharing && this.screenStream) {\n this.screenSenders[id] = [];\n this.screenStream.getTracks().forEach((track) => {\n const sender = pc.addTrack(track, this.screenStream!);\n this.screenSenders[id].push(sender);\n });\n }\n\n return pc;\n }\n\n // ---------------- OFFER ----------------\n private async createOffer(id: string, isRenegotiation = false) {\n if (!isRenegotiation && !this.shouldInitiate(id)) {\n console.debug(\n `[Offer] ${id} should initiate (${id} > ${this.myId}), skipping`,\n );\n return;\n }\n\n if (!isRenegotiation && this.initiators.has(id)) {\n console.debug(\n `[Offer] Already initiating with ${id}, skipping duplicate`,\n );\n return; // ← This was missing!\n }\n\n if (!isRenegotiation) {\n this.initiators.add(id);\n }\n if (!this.peers[id]) {\n this.peers[id] = this.createPeer(id);\n }\n\n const pc = this.peers[id];\n\n try {\n const offer = await pc.createOffer();\n await pc.setLocalDescription(offer);\n\n this.send({\n type: \"OFFER\",\n payload: offer.sdp,\n sender: this.myId,\n target: id,\n });\n\n console.debug(`[Offer] Sent to ${id}`);\n } catch (err) {\n console.error(`[Offer] Failed for ${id}:`, err);\n }\n }\n\n private shouldInitiate(peerId: string): boolean {\n // Lexicographic comparison: lower ID initiates\n return this.myId < peerId;\n }\n\n // ---------------- ANSWER ----------------\n private async handleOffer(sdp: string, id: string) {\n if (!this.iceServers || this.iceServers.length === 0) {\n console.warn(\"[Offer] Waiting for iceServers, queuing offer from\", id);\n this.pendingOffers[id] = sdp;\n return;\n }\n\n if (!this.peers[id]) {\n this.peers[id] = this.createPeer(id);\n }\n\n const pc = this.peers[id];\n\n try {\n // GLARE RECOVERY: Both peers sent OFFERs simultaneously\n if (pc.signalingState === \"have-local-offer\") {\n if (this.shouldInitiate(id)) {\n // WE WIN: Keep our offer, reject theirs\n console.warn(\n `[Glare] Both sent OFFERs, we win (${this.myId} < ${id}), keeping our OFFER`,\n );\n return; // Ignore their offer, wait for their ANSWER\n } else {\n // THEY WIN: Roll back and accept their offer\n console.warn(\n `[Glare] Both sent OFFERs, they win (${id} < ${this.myId}), rolling back`,\n );\n pc.close();\n delete this.peers[id];\n this.initiators.delete(id);\n\n // Create fresh peer connection to answer their offer\n this.peers[id] = this.createPeer(id);\n }\n }\n\n // Only set remote description if we're not already in negotiation\n if (\n this.peers[id].signalingState !== \"stable\" &&\n this.peers[id].signalingState !== \"have-local-offer\"\n ) {\n console.warn(\n `[Signaling] Cannot accept OFFER in state \"${this.peers[id].signalingState}\"`,\n );\n return;\n }\n\n await this.peers[id].setRemoteDescription({\n type: \"offer\",\n sdp,\n });\n\n const pending = this.pendingIceCandidates[id] || [];\n\n for (const candidate of pending) {\n try {\n await this.peers[id].addIceCandidate(candidate);\n } catch (err) {\n console.warn(\"[ICE] Failed to add candidate:\", err);\n }\n }\n\n delete this.pendingIceCandidates[id];\n\n const answer = await this.peers[id].createAnswer();\n\n await this.peers[id].setLocalDescription(answer);\n await this.flushIce(id, this.peers[id]);\n\n this.send({\n type: \"ANSWER\",\n payload: answer.sdp,\n sender: this.myId,\n target: id,\n });\n\n console.debug(`[Answer] Sent to ${id}`);\n } catch (err) {\n console.error(`[Signaling] Failed to handle OFFER from ${id}:`, err);\n this.emitError(\n \"OFFER_HANDLING_FAILED\",\n `Failed to handle offer from ${id}`,\n err,\n true,\n );\n }\n }\n\n // ---------------- CLEANUP ----------------\n private closePeer(id: string) {\n const pc = this.peers[id];\n\n if (!pc) return;\n\n pc.ontrack = null;\n pc.onicecandidate = null;\n pc.onconnectionstatechange = null;\n\n pc.close();\n\n delete this.peers[id];\n\n this.initiators.delete(id);\n\n this.state.removeParticipant(id);\n }\n\n async startScreenShare() {\n try {\n if (this.state.presenterId && this.state.presenterId !== this.myId) {\n throw new Error(\"Another user is already sharing their screen.\");\n }\n if (!navigator.mediaDevices?.getDisplayMedia) {\n throw new Error(\"Screen sharing not supported on this device\");\n }\n\n this.screenStream = await navigator.mediaDevices.getDisplayMedia({\n video: true,\n // audio: true,\n });\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 this.state.setPresenterId(this.myId);\n // Handle the user clicking browser's built-in \"Stop Sharing\" button\n this.screenStream.getVideoTracks()[0].onended = () => {\n this.stopScreenShare();\n };\n\n Object.entries(this.peers).forEach(([peerId, pc]) => {\n this.screenSenders[peerId] = [];\n this.screenStream!.getTracks().forEach((track) => {\n const sender = pc.addTrack(track, this.screenStream!);\n this.screenSenders[peerId].push(sender);\n });\n\n // Renegotiate peer connection descriptors to notify remote side of new track footprint\n this.createOffer(peerId, true);\n });\n\n this.send({\n type: \"SCREEN_SHARE_START\",\n sender: this.myId,\n room_id: this.room.id,\n camera_id: this.localStream?.id.replace(/[{}]/g, \"\"),\n stream_id: this.screenStream.id.replace(/[{}]/g, \"\"),\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 throw err;\n }\n }\n\n stopScreenShare() {\n if (!this.screenStream) return;\n\n this.screenStream.getTracks().forEach((t) => t.stop());\n\n // Remove tracks cleanly from WebRTC channel pathways across your peers\n Object.entries(this.peers).forEach(([peerId, pc]) => {\n const senders = this.screenSenders[peerId] || [];\n senders.forEach((sender) => {\n try {\n pc.removeTrack(sender);\n } catch (err) {\n console.warn(err);\n }\n });\n delete this.screenSenders[peerId];\n\n // Renegotiate layout expectations to scale down stream bounds\n this.createOffer(peerId, true);\n });\n\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 if (this.state.presenterId === this.myId) {\n this.state.setPresenterId(null);\n }\n\n this.send({\n type: \"SCREEN_SHARE_STOP\",\n sender: this.myId,\n room_id: this.room.id,\n });\n }\n\n sendChatMessage(payload: ChatInput) {\n if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {\n console.warn(\"WS not connected\");\n return;\n }\n\n if (!this.room.id) {\n console.warn(\"No roomId set\");\n return;\n }\n\n const isPrivate = !!payload?.target;\n\n const senderName = this.state.localParticipant?.name || \"Anonymous\";\n\n const msg: ChatMessage = {\n id: crypto.randomUUID(),\n sender_id: this.myId,\n sender_name: senderName,\n text: payload.message.trim(),\n timestamp: Date.now(),\n reply_to: payload.reply_to ?? null,\n target: payload.target ?? null,\n };\n\n // optimistic UI update\n this.state.addChatMessage(msg);\n\n // send protocol payload (clean + consistent)\n this.send({\n type: \"CHAT_MESSAGE\",\n message: payload.message.trim(),\n user_id: this.myId,\n sender_name: senderName,\n room_id: this.room.id,\n target: isPrivate ? (payload.target ?? null) : null,\n reply_to: payload.reply_to ?? null,\n\n client_ts: Date.now(),\n });\n }\n\n disconnect() {\n this.intentionalDisconnect = true;\n\n this.stopScreenShare();\n\n Object.values(this.peers).forEach((pc) => pc.close());\n this.peers = {};\n this.initiators.clear();\n\n this.stopHeartbeat();\n\n if (this.ws?.readyState === WebSocket.OPEN) {\n this.send({\n type: \"LEAVE\",\n room_id: this.room.id,\n user_id: this.myId,\n sender_name: this.state.localParticipant?.name,\n });\n\n // Allow the LEAVE frame to be flushed.\n setTimeout(() => {\n this.ws?.close(1000, \"Leaving meeting\");\n this.ws = null;\n }, 50);\n }\n\n if (this.localStream) {\n this.localStream.getTracks().forEach((track) => track.stop());\n this.localStream = null;\n }\n\n this.room.id = null;\n\n this.state.localParticipant = null;\n this.state.notify(\"localParticipant\");\n\n this.state.participants.clear();\n this.state.notify(\"participants\");\n\n this.events.onMeetingLeft?.();\n\n this.state.clearChat();\n this.state.setPresenterId(null);\n }\n\n private async flushIce(id: string, pc: RTCPeerConnection) {\n const pending = this.pendingIceCandidates[id];\n if (!pending?.length) return;\n\n for (const candidate of pending) {\n try {\n await pc.addIceCandidate(candidate);\n } catch (e) {\n console.warn(\"ICE flush error\", e);\n }\n }\n\n delete this.pendingIceCandidates[id];\n }\n\n private send(msg: any) {\n this.ws?.send(JSON.stringify(msg));\n }\n\n approveJoinRequest(requestId: string) {\n this.send({\n type: \"JOIN_APPROVE\",\n request_id: requestId,\n });\n }\n\n rejectJoinRequest(requestId: string) {\n this.send({\n type: \"JOIN_REJECT\",\n request_id: requestId,\n });\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\";\n\nexport const useMeeting = (handlers?: {\n onError?: (err: any) => void;\n onEntryRequested?: (req: any) => void;\n onEntryResponded?: (payload: any, decision?: any) => void;\n onMeetingLeft?: () => 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 // 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 // Meeting Left Handler\n useEffect(() => {\n if (!handlers?.onMeetingLeft) return;\n return ctx.onMeetingLeft(handlers.onMeetingLeft);\n }, [handlers?.onMeetingLeft]);\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 };\n};\n","import { useCallback, 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 participants: {\n id: string;\n name: string;\n isHost: boolean;\n isPresenter: boolean;\n micEnabled: boolean;\n camEnabled: boolean;\n }[];\n};\n\nexport function useMeetingPreview(roomId: string, userId: string) {\n const [room, setRoom] = useState<LiveRoomState | null>(null);\n const [isLoading, setIsLoading] = useState(true);\n const [error, setError] = useState<Error | null>(null);\n\n const load = useCallback(async () => {\n if (!roomId || !userId) return;\n\n try {\n setIsLoading(true);\n setError(null);\n\n const res = await fetch(\n `${SDK_CONFIG.baseUrl}/api/rooms/${roomId}/live?user_id=${userId}`,\n );\n\n if (!res.ok) {\n throw new Error(\"Failed to fetch meeting preview\");\n }\n\n const data = await res.json();\n\n setRoom(data);\n } catch (err) {\n setError(err instanceof Error ? err : new Error(\"Unknown error\"));\n } finally {\n setIsLoading(false);\n }\n }, [roomId, userId]);\n\n useEffect(() => {\n load();\n\n const interval = setInterval(load, 5000);\n\n return () => clearInterval(interval);\n }, [load]);\n\n return {\n room,\n isLoading,\n error,\n refetch: load,\n };\n}\n"],"mappings":"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","names":["useEffect","useRef","useState","peerId","useState","useEffect","useRef","useEffect","useEffect","useEffect","useState","useState","useEffect","useEffect","useRef","useState","useRef","useState","useEffect","useCallback","useEffect","useState","useState","useCallback","useEffect"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@afosecure/meetingsdk",
3
- "version": "1.4.2",
3
+ "version": "1.4.3",
4
4
  "description": "A modern, lightweight React SDK for building peer-to-peer video communication applications. Built on WebRTC with a clean, composable rust API.",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",
@@ -38,7 +38,8 @@
38
38
  "sdk",
39
39
  "rust",
40
40
  "sdk",
41
- "typescript"
41
+ "typescript",
42
+ "videosdk"
42
43
  ],
43
44
  "author": "Afolabi Mubarak",
44
45
  "license": "MIT",