@dialtribe/react-sdk 0.1.0-alpha.8 → 0.1.4
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/LICENSE +20 -20
- package/README.md +535 -535
- package/dist/{broadcast-player.d.mts → dialtribe-player-CNriUtNi.d.mts} +97 -85
- package/dist/{broadcast-player.d.ts → dialtribe-player-CNriUtNi.d.ts} +97 -85
- package/dist/dialtribe-player.d.mts +3 -0
- package/dist/dialtribe-player.d.ts +3 -0
- package/dist/{broadcast-player.js → dialtribe-player.js} +1103 -548
- package/dist/dialtribe-player.js.map +1 -0
- package/dist/{broadcast-player.mjs → dialtribe-player.mjs} +1099 -544
- package/dist/dialtribe-player.mjs.map +1 -0
- package/dist/dialtribe-streamer-C16mRqha.d.ts +567 -0
- package/dist/dialtribe-streamer-FjMRCQfA.d.mts +567 -0
- package/dist/dialtribe-streamer.d.mts +4 -0
- package/dist/dialtribe-streamer.d.ts +4 -0
- package/dist/dialtribe-streamer.js +4836 -0
- package/dist/dialtribe-streamer.js.map +1 -0
- package/dist/dialtribe-streamer.mjs +4799 -0
- package/dist/dialtribe-streamer.mjs.map +1 -0
- package/dist/hello-world.js.map +1 -1
- package/dist/hello-world.mjs.map +1 -1
- package/dist/index.d.mts +2 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +3306 -609
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +3222 -541
- package/dist/index.mjs.map +1 -1
- package/dist/styles.css +3 -3
- package/package.json +91 -86
- package/dist/broadcast-player.js.map +0 -1
- package/dist/broadcast-player.mjs.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/context/DialtribeProvider.tsx","../src/client/DialtribeClient.ts","../src/utils/media-constraints.ts","../src/utils/websocket-streamer.ts","../src/components/AudioWaveform.tsx","../src/components/StreamingPreview.tsx","../src/components/StreamKeyDisplay.tsx","../src/components/StreamingControls.tsx","../src/components/StreamKeyInput.tsx","../src/components/DialtribeStreamer.tsx","../src/components/LoadingSpinner.tsx","../src/utils/cdn.ts","../src/utils/format.ts","../src/utils/http-status.ts","../src/utils/debug.ts","../src/components/DialtribePlayer.tsx","../src/components/DialtribePlayerErrorBoundary.tsx","../src/components/DialtribeOverlay.tsx","../src/utils/dialtribe-popup.ts","../src/hooks/useDialtribeStreamerPopup.ts","../src/hooks/useDialtribeStreamerLauncher.ts"],"names":["createContext","useState","useCallback","useEffect","jsx","useContext","ctx","canvas","videoElement","useRef","animationId","jsxs","sizeClasses","Fragment","useMemo","handleTimeUpdate","ReactPlayer","Component","React","createPortal"],"mappings":"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","file":"dialtribe-streamer.js","sourcesContent":["import React, { createContext, useContext, useState, useCallback, useEffect } from 'react';\r\n\r\n/**\r\n * Dialtribe SDK Context\r\n * Manages session token and auto-refresh across all SDK components\r\n */\r\n\r\nexport interface DialtribeContextValue {\r\n /** Current session token */\r\n sessionToken: string | null;\r\n /** Update the session token (called automatically on refresh) */\r\n setSessionToken: (token: string, expiresAt?: string) => void;\r\n /** Whether the session token is expired/invalid */\r\n isExpired: boolean;\r\n /** Mark token as expired */\r\n markExpired: () => void;\r\n /** Optional API base URL override */\r\n apiBaseUrl?: string;\r\n}\r\n\r\nconst DialtribeContext = createContext<DialtribeContextValue | null>(null);\r\n\r\nexport interface DialtribeProviderProps {\r\n /** Session token from your backend (required) */\r\n sessionToken: string;\r\n /** Called when the API returns a refreshed token via X-Session-Token header */\r\n onTokenRefresh?: (newToken: string, expiresAt: string) => void;\r\n /** Called when the session token expires or becomes invalid */\r\n onTokenExpired?: () => void;\r\n /**\r\n * Optional: Override API base URL (for local development)\r\n * If not provided, uses NEXT_PUBLIC_DIALTRIBE_API_URL environment variable or production default\r\n * @example \"http://localhost:3001/api/public/v1\"\r\n */\r\n apiBaseUrl?: string;\r\n /** Your React app */\r\n children: React.ReactNode;\r\n}\r\n\r\n/**\r\n * Dialtribe Provider\r\n *\r\n * Wraps your app to provide session token authentication to all SDK components.\r\n *\r\n * @example\r\n * ```tsx\r\n * // Production (default)\r\n * <DialtribeProvider\r\n * sessionToken=\"sess_xxx...\"\r\n * onTokenRefresh={(newToken) => setToken(newToken)}\r\n * onTokenExpired={() => router.push('/login')}\r\n * >\r\n * <App />\r\n * </DialtribeProvider>\r\n *\r\n * // Local development (explicit)\r\n * <DialtribeProvider\r\n * sessionToken=\"sess_xxx...\"\r\n * apiBaseUrl=\"http://localhost:3001/api/public/v1\"\r\n * onTokenRefresh={(newToken) => setToken(newToken)}\r\n * >\r\n * <App />\r\n * </DialtribeProvider>\r\n *\r\n * // Local development (via env var - recommended)\r\n * // Set NEXT_PUBLIC_DIALTRIBE_API_URL=http://localhost:3001/api/public/v1 in .env\r\n * <DialtribeProvider sessionToken=\"sess_xxx...\">\r\n * <App />\r\n * </DialtribeProvider>\r\n * ```\r\n */\r\nexport function DialtribeProvider({\r\n sessionToken: initialToken,\r\n onTokenRefresh,\r\n onTokenExpired,\r\n apiBaseUrl,\r\n children,\r\n}: DialtribeProviderProps) {\r\n const [sessionToken, setSessionTokenState] = useState<string>(initialToken);\r\n const [isExpired, setIsExpired] = useState(false);\r\n\r\n // Update token and notify parent\r\n const setSessionToken = useCallback(\r\n (newToken: string, expiresAt?: string) => {\r\n setSessionTokenState(newToken);\r\n setIsExpired(false);\r\n // Notify parent component of token refresh\r\n if (expiresAt) {\r\n onTokenRefresh?.(newToken, expiresAt);\r\n }\r\n },\r\n [onTokenRefresh]\r\n );\r\n\r\n // Mark token as expired\r\n const markExpired = useCallback(() => {\r\n setIsExpired(true);\r\n onTokenExpired?.();\r\n }, [onTokenExpired]);\r\n\r\n // Sync with prop changes (in case parent updates the token)\r\n useEffect(() => {\r\n if (initialToken !== sessionToken) {\r\n setSessionTokenState(initialToken);\r\n setIsExpired(false);\r\n }\r\n }, [initialToken, sessionToken]);\r\n\r\n const value: DialtribeContextValue = {\r\n sessionToken,\r\n setSessionToken,\r\n isExpired,\r\n markExpired,\r\n apiBaseUrl,\r\n };\r\n\r\n return (\r\n <DialtribeContext.Provider value={value}>\r\n {children}\r\n </DialtribeContext.Provider>\r\n );\r\n}\r\n\r\n/**\r\n * Hook to access Dialtribe context\r\n *\r\n * @throws Error if used outside DialtribeProvider\r\n *\r\n * @example\r\n * ```tsx\r\n * const { sessionToken, setSessionToken } = useDialtribe();\r\n * ```\r\n */\r\nexport function useDialtribe(): DialtribeContextValue {\r\n const context = useContext(DialtribeContext);\r\n\r\n if (!context) {\r\n throw new Error(\r\n 'useDialtribe must be used within a DialtribeProvider. ' +\r\n 'Wrap your app with <DialtribeProvider sessionToken=\"sess_xxx\">...</DialtribeProvider>'\r\n );\r\n }\r\n\r\n return context;\r\n}\r\n\r\n/**\r\n * Hook to optionally access Dialtribe context\r\n * Returns null if not within a DialtribeProvider (doesn't throw)\r\n *\r\n * @example\r\n * ```tsx\r\n * const context = useDialtribeOptional();\r\n * const sessionToken = context?.sessionToken ?? propSessionToken;\r\n * ```\r\n */\r\nexport function useDialtribeOptional(): DialtribeContextValue | null {\r\n return useContext(DialtribeContext);\r\n}\r\n","/**\r\n * Dialtribe API Client\r\n *\r\n * Handles all API communication with Dialtribe endpoints.\r\n * Automatically manages session token refresh via X-Session-Token headers.\r\n *\r\n * Supports configurable API base URL for development:\r\n * 1. Via environment variable: NEXT_PUBLIC_DIALTRIBE_API_URL\r\n * 2. Via apiBaseUrl prop on DialtribeProvider (takes precedence)\r\n *\r\n * Defaults to production URL if neither is specified.\r\n */\r\n\r\n/**\r\n * Get the default API base URL\r\n * Checks environment variable, falls back to production\r\n */\r\nfunction getDefaultApiBaseUrl(): string {\r\n // Check for environment variable (Next.js, Create React App, Vite all support this pattern)\r\n if (typeof process !== 'undefined' && process.env?.NEXT_PUBLIC_DIALTRIBE_API_URL) {\r\n return process.env.NEXT_PUBLIC_DIALTRIBE_API_URL;\r\n }\r\n\r\n // Production default\r\n return 'https://dialtribe.com/api/public/v1';\r\n}\r\n\r\n/** Default API base URL (production or from environment) */\r\nexport const DIALTRIBE_API_BASE = getDefaultApiBaseUrl();\r\n\r\n/**\r\n * Generate API endpoints for a given base URL\r\n * This allows runtime configuration while maintaining type safety\r\n */\r\nexport function getEndpoints(baseUrl: string = DIALTRIBE_API_BASE) {\r\n return {\r\n broadcasts: `${baseUrl}/broadcasts`,\r\n broadcast: (id: number) => `${baseUrl}/broadcasts/${id}`,\r\n contentPlay: `${baseUrl}/content/play`,\r\n presignedUrl: `${baseUrl}/media/presigned-url`,\r\n audienceStart: `${baseUrl}/audiences/start`,\r\n audiencePing: `${baseUrl}/audiences/ping`,\r\n sessionPing: `${baseUrl}/sessions/ping`,\r\n } as const;\r\n}\r\n\r\n/** Default API endpoints (uses default base URL) */\r\nexport const ENDPOINTS = getEndpoints();\r\n\r\nexport interface ApiClientConfig {\r\n /** Session token for authentication */\r\n sessionToken: string;\r\n /** Called when API returns a refreshed token */\r\n onTokenRefresh?: (newToken: string, expiresAt: string) => void;\r\n /** Called when token expires or becomes invalid */\r\n onTokenExpired?: () => void;\r\n /**\r\n * Optional: Override API base URL (e.g., for local development)\r\n * If not provided, uses environment variable or production default\r\n * @example \"http://localhost:3001/api/public/v1\"\r\n */\r\n apiBaseUrl?: string;\r\n}\r\n\r\n/**\r\n * Dialtribe API Client\r\n *\r\n * Low-level client for making authenticated requests to Dialtribe API.\r\n * Handles session token auto-refresh automatically.\r\n */\r\nexport class DialtribeClient {\r\n private config: ApiClientConfig;\r\n private endpoints: ReturnType<typeof getEndpoints>;\r\n\r\n constructor(config: ApiClientConfig) {\r\n this.config = config;\r\n // Generate endpoints with custom base URL if provided\r\n this.endpoints = config.apiBaseUrl ? getEndpoints(config.apiBaseUrl) : ENDPOINTS;\r\n }\r\n\r\n /**\r\n * Make an authenticated request to Dialtribe API\r\n *\r\n * Automatically:\r\n * - Adds Authorization header with session token\r\n * - Checks for X-Session-Token header in response (token refresh)\r\n * - Calls onTokenRefresh if new token is provided\r\n * - Calls onTokenExpired on 401 errors\r\n */\r\n async fetch(url: string, options: RequestInit = {}): Promise<Response> {\r\n const headers = new Headers(options.headers);\r\n\r\n // Add session token to Authorization header\r\n headers.set('Authorization', `Bearer ${this.config.sessionToken}`);\r\n headers.set('Content-Type', 'application/json');\r\n\r\n const response = await fetch(url, {\r\n ...options,\r\n headers,\r\n });\r\n\r\n // Check for refreshed session token in response headers\r\n const newToken = response.headers.get('X-Session-Token');\r\n const expiresAt = response.headers.get('X-Session-Expires');\r\n\r\n if (newToken && expiresAt) {\r\n // API returned a refreshed token\r\n this.config.onTokenRefresh?.(newToken, expiresAt);\r\n }\r\n\r\n // Handle expired/invalid token\r\n if (response.status === 401) {\r\n this.config.onTokenExpired?.();\r\n throw new Error('Session token expired or invalid');\r\n }\r\n\r\n return response;\r\n }\r\n\r\n /**\r\n * Update the session token\r\n * Called automatically when token is refreshed, or manually by user\r\n */\r\n setSessionToken(token: string) {\r\n this.config.sessionToken = token;\r\n }\r\n\r\n /**\r\n * Get list of broadcasts for the authenticated app\r\n */\r\n async getBroadcasts(params?: {\r\n page?: number;\r\n limit?: number;\r\n broadcastStatus?: 1 | 2;\r\n search?: string;\r\n includeDeleted?: boolean;\r\n }) {\r\n const searchParams = new URLSearchParams();\r\n\r\n if (params?.page) searchParams.set('page', params.page.toString());\r\n if (params?.limit) searchParams.set('limit', params.limit.toString());\r\n if (params?.broadcastStatus) searchParams.set('broadcastStatus', params.broadcastStatus.toString());\r\n if (params?.search) searchParams.set('search', params.search);\r\n if (params?.includeDeleted) searchParams.set('includeDeleted', 'true');\r\n\r\n const url = `${this.endpoints.broadcasts}${searchParams.toString() ? `?${searchParams}` : ''}`;\r\n const response = await this.fetch(url);\r\n\r\n if (!response.ok) {\r\n throw new Error(`Failed to fetch broadcasts: ${response.status} ${response.statusText}`);\r\n }\r\n\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Get a single broadcast by ID\r\n */\r\n async getBroadcast(id: number) {\r\n const response = await this.fetch(this.endpoints.broadcast(id));\r\n\r\n if (!response.ok) {\r\n if (response.status === 404) {\r\n throw new Error('Broadcast not found');\r\n }\r\n throw new Error(`Failed to fetch broadcast: ${response.status} ${response.statusText}`);\r\n }\r\n\r\n return response.json();\r\n }\r\n\r\n /**\r\n * Get presigned URL for media playback\r\n *\r\n * @param broadcastId - Broadcast ID\r\n * @param hash - Broadcast hash (optional if using session token)\r\n * @param action - 'download' to force download, otherwise streams\r\n */\r\n async getPlaybackUrl(params: {\r\n broadcastId: number;\r\n hash?: string;\r\n action?: 'download';\r\n }): Promise<string> {\r\n const searchParams = new URLSearchParams({\r\n broadcastId: params.broadcastId.toString(),\r\n });\r\n\r\n if (params.hash) searchParams.set('hash', params.hash);\r\n if (params.action) searchParams.set('action', params.action);\r\n\r\n const url = `${this.endpoints.contentPlay}?${searchParams}`;\r\n const response = await this.fetch(url, {\r\n redirect: 'manual', // Don't follow redirect, we want the URL\r\n });\r\n\r\n // The endpoint returns a 307 redirect to the signed URL\r\n const location = response.headers.get('Location');\r\n if (!location) {\r\n throw new Error('No playback URL returned from API');\r\n }\r\n\r\n return location;\r\n }\r\n\r\n /**\r\n * Refresh a presigned URL before it expires\r\n *\r\n * @param broadcastId - Broadcast ID\r\n * @param hash - Broadcast hash\r\n * @param fileType - Type of media file\r\n */\r\n async refreshPresignedUrl(params: {\r\n broadcastId: number;\r\n hash: string;\r\n fileType: 'mp4' | 'mp3' | 'hls';\r\n }) {\r\n const searchParams = new URLSearchParams({\r\n broadcastId: params.broadcastId.toString(),\r\n hash: params.hash,\r\n fileType: params.fileType,\r\n });\r\n\r\n const url = `${this.endpoints.presignedUrl}?${searchParams}`;\r\n const response = await this.fetch(url);\r\n\r\n if (!response.ok) {\r\n throw new Error(`Failed to refresh URL: ${response.status} ${response.statusText}`);\r\n }\r\n\r\n return response.json() as Promise<{\r\n url: string;\r\n expiresAt: string;\r\n expiresIn: number;\r\n }>;\r\n }\r\n\r\n /**\r\n * Start a new audience tracking session\r\n *\r\n * @returns audienceId and optional resumePosition\r\n */\r\n async startSession(params: {\r\n contentId: number;\r\n broadcastId: number;\r\n appId: string;\r\n foreignId?: string | null;\r\n foreignTier?: string;\r\n sessionId: string;\r\n fileType: string;\r\n platform: string;\r\n userAgent: string | null;\r\n origin: string | null;\r\n country?: string | null;\r\n region?: string | null;\r\n }) {\r\n const response = await this.fetch(this.endpoints.audienceStart, {\r\n method: 'POST',\r\n body: JSON.stringify(params),\r\n });\r\n\r\n if (!response.ok) {\r\n throw new Error(`Failed to start session: ${response.status} ${response.statusText}`);\r\n }\r\n\r\n return response.json() as Promise<{\r\n audienceId: string;\r\n resumePosition?: number;\r\n }>;\r\n }\r\n\r\n /**\r\n * Send a session ping event\r\n *\r\n * Event types:\r\n * - 0: PAUSE/STOP\r\n * - 1: PLAY/START\r\n * - 2: HEARTBEAT\r\n * - 3: UNMOUNT\r\n */\r\n async sendSessionPing(params: {\r\n audienceId: string;\r\n sessionId: string;\r\n eventType: 0 | 1 | 2 | 3;\r\n currentTime: number;\r\n duration: number;\r\n }) {\r\n const response = await this.fetch(this.endpoints.audiencePing, {\r\n method: 'POST',\r\n body: JSON.stringify(params),\r\n });\r\n\r\n if (!response.ok) {\r\n throw new Error(`Failed to send session ping: ${response.status} ${response.statusText}`);\r\n }\r\n\r\n // Session ping may return no body\r\n if (response.status === 204) {\r\n return;\r\n }\r\n\r\n return response.json();\r\n }\r\n}\r\n","/**\r\n * Media constraints for browser streaming\r\n * Based on prankcast reference implementation\r\n */\r\n\r\nexport interface MediaConstraintsOptions {\r\n isVideo: boolean;\r\n facingMode?: \"user\" | \"environment\"; // front or back camera\r\n}\r\n\r\nexport function getMediaConstraints(options: MediaConstraintsOptions): MediaStreamConstraints {\r\n const { isVideo, facingMode = \"user\" } = options;\r\n\r\n // Audio constraints (always included)\r\n const audioConstraints: MediaTrackConstraints = {\r\n autoGainControl: true,\r\n channelCount: 2, // Stereo\r\n echoCancellation: false,\r\n noiseSuppression: false,\r\n sampleRate: 48_000, // 48kHz\r\n };\r\n\r\n // Video constraints (720p, 16:9, 30fps)\r\n const videoConstraints: MediaTrackConstraints | false = isVideo\r\n ? {\r\n aspectRatio: 16 / 9,\r\n width: { ideal: 1280 },\r\n height: { ideal: 720 },\r\n frameRate: { ideal: 30 },\r\n facingMode, // \"user\" (front) or \"environment\" (back)\r\n }\r\n : false;\r\n\r\n return {\r\n audio: audioConstraints,\r\n video: videoConstraints,\r\n };\r\n}\r\n\r\n/**\r\n * MediaRecorder options for encoding\r\n */\r\nexport function getMediaRecorderOptions(isVideo: boolean): MediaRecorderOptions {\r\n // Try H.264/AAC first for MP4 compatibility (enables recording)\r\n // Fall back to VP8/Opus if not supported\r\n let mimeType: string | undefined;\r\n\r\n if (isVideo) {\r\n // Try H.264 + AAC (best for MP4 recording)\r\n if (MediaRecorder.isTypeSupported('video/mp4;codecs=avc1,mp4a')) {\r\n mimeType = 'video/mp4;codecs=avc1,mp4a';\r\n }\r\n // Try H.264 in WebM container\r\n else if (MediaRecorder.isTypeSupported('video/webm;codecs=h264,opus')) {\r\n mimeType = 'video/webm;codecs=h264,opus';\r\n }\r\n // Fall back to VP8 + Opus (won't work with MP4 recording)\r\n else if (MediaRecorder.isTypeSupported('video/webm;codecs=vp8,opus')) {\r\n mimeType = 'video/webm;codecs=vp8,opus';\r\n console.warn('⚠️ Browser only supports VP8/Opus - recordings will be disabled');\r\n }\r\n } else {\r\n // Audio only - try AAC first, then Opus\r\n if (MediaRecorder.isTypeSupported('audio/mp4;codecs=mp4a')) {\r\n mimeType = 'audio/mp4;codecs=mp4a';\r\n } else if (MediaRecorder.isTypeSupported('audio/webm;codecs=opus')) {\r\n mimeType = 'audio/webm;codecs=opus';\r\n console.warn('⚠️ Browser only supports Opus - recordings may be disabled');\r\n }\r\n }\r\n\r\n return {\r\n mimeType,\r\n audioBitsPerSecond: 128_000, // 128 kbps audio\r\n videoBitsPerSecond: isVideo ? 2_500_000 : undefined, // 2.5 Mbps for 720p video\r\n };\r\n}\r\n\r\n/**\r\n * Check browser compatibility\r\n */\r\nexport function checkBrowserCompatibility(): { compatible: boolean; error?: string } {\r\n if (typeof window === 'undefined') {\r\n return {\r\n compatible: false,\r\n error: \"This component requires a browser environment\",\r\n };\r\n }\r\n\r\n if (!window.MediaRecorder) {\r\n return {\r\n compatible: false,\r\n error: \"MediaRecorder API not supported in this browser\",\r\n };\r\n }\r\n\r\n if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) {\r\n return {\r\n compatible: false,\r\n error: \"getUserMedia API not supported in this browser\",\r\n };\r\n }\r\n\r\n return { compatible: true };\r\n}\r\n","/**\r\n * WebSocket streaming client for sending media chunks to encoder server\r\n * Based on prankcast reference implementation\r\n */\r\n\r\nimport { getMediaRecorderOptions } from \"./media-constraints\";\r\n\r\n/** Default encoder server URL */\r\nexport const DEFAULT_ENCODER_SERVER_URL = \"https://broadcastapi.dialtribe.com\";\r\n\r\nexport interface StreamDiagnostics {\r\n mimeType: string | undefined;\r\n chunksSent: number;\r\n bytesSent: number;\r\n elapsedMs: number;\r\n closeCode?: number;\r\n closeReason?: string;\r\n lastError?: string;\r\n}\r\n\r\nexport interface WebSocketStreamerOptions {\r\n streamKey: string;\r\n mediaStream: MediaStream;\r\n isVideo: boolean;\r\n /** Optional custom encoder server URL (defaults to DEFAULT_ENCODER_SERVER_URL) */\r\n encoderServerUrl?: string;\r\n /** Disable canvas rendering (for debugging HLS issues). Disables seamless camera flips. */\r\n disableCanvasRendering?: boolean;\r\n onBytesUpdate?: (bytes: number) => void;\r\n onStateChange?: (state: \"connecting\" | \"live\" | \"stopped\" | \"terminated\" | \"error\") => void;\r\n onError?: (error: string, diagnostics?: StreamDiagnostics) => void;\r\n}\r\n\r\n/** Canvas rendering state for seamless camera flips */\r\ninterface CanvasRenderingState {\r\n canvas: HTMLCanvasElement;\r\n ctx: CanvasRenderingContext2D;\r\n videoElement: HTMLVideoElement;\r\n stream: MediaStream;\r\n renderLoopId: number;\r\n // Adaptive performance\r\n useBlurBackground: boolean;\r\n slowFrameCount: number;\r\n // Cached scaling dimensions\r\n cachedContain: { x: number; y: number; width: number; height: number } | null;\r\n cachedCover: { x: number; y: number; width: number; height: number } | null;\r\n cachedNeedsBackground: boolean;\r\n lastVideoWidth: number;\r\n lastVideoHeight: number;\r\n}\r\n\r\nexport class WebSocketStreamer {\r\n private streamKey: string;\r\n private mediaStream: MediaStream;\r\n private isVideo: boolean;\r\n private encoderServerUrl: string;\r\n private disableCanvasRendering: boolean;\r\n private websocket: WebSocket | null = null;\r\n private mediaRecorder: MediaRecorder | null = null;\r\n private bytesSent: number = 0;\r\n private chunksSent: number = 0;\r\n private userStopped: boolean = false; // Track if user initiated the stop\r\n private isHotSwapping: boolean = false; // Track if we're swapping media streams\r\n private startTime: number = 0;\r\n private mimeType: string | undefined;\r\n private onBytesUpdate?: (bytes: number) => void;\r\n private onStateChange?: (state: \"connecting\" | \"live\" | \"stopped\" | \"terminated\" | \"error\") => void;\r\n private onError?: (error: string, diagnostics?: StreamDiagnostics) => void;\r\n\r\n // Canvas-based rendering for seamless camera flips\r\n // MediaRecorder records from canvas stream, so track changes don't affect it\r\n private canvasState: CanvasRenderingState | null = null;\r\n\r\n constructor(options: WebSocketStreamerOptions) {\r\n this.streamKey = options.streamKey;\r\n this.mediaStream = options.mediaStream;\r\n this.isVideo = options.isVideo;\r\n this.encoderServerUrl = options.encoderServerUrl || DEFAULT_ENCODER_SERVER_URL;\r\n this.disableCanvasRendering = options.disableCanvasRendering || false;\r\n this.onBytesUpdate = options.onBytesUpdate;\r\n this.onStateChange = options.onStateChange;\r\n this.onError = options.onError;\r\n }\r\n\r\n /**\r\n * Calculate scaled dimensions for fitting video into canvas.\r\n * @param mode - \"contain\" fits video inside canvas, \"cover\" fills canvas (cropping)\r\n */\r\n private calculateScaledDimensions(\r\n videoWidth: number,\r\n videoHeight: number,\r\n canvasWidth: number,\r\n canvasHeight: number,\r\n mode: \"contain\" | \"cover\"\r\n ): { x: number; y: number; width: number; height: number } {\r\n const videoAspect = videoWidth / videoHeight;\r\n const canvasAspect = canvasWidth / canvasHeight;\r\n\r\n // For \"contain\": use width-based scaling when video is wider\r\n // For \"cover\": use width-based scaling when video is taller (inverted)\r\n const useWidthBased = mode === \"contain\"\r\n ? videoAspect > canvasAspect\r\n : videoAspect <= canvasAspect;\r\n\r\n if (useWidthBased) {\r\n const width = canvasWidth;\r\n const height = canvasWidth / videoAspect;\r\n return { x: 0, y: (canvasHeight - height) / 2, width, height };\r\n } else {\r\n const height = canvasHeight;\r\n const width = canvasHeight * videoAspect;\r\n return { x: (canvasWidth - width) / 2, y: 0, width, height };\r\n }\r\n }\r\n\r\n /**\r\n * Invalidate cached scaling dimensions (call when video source changes)\r\n */\r\n private invalidateScalingCache(): void {\r\n if (this.canvasState) {\r\n this.canvasState.cachedContain = null;\r\n this.canvasState.cachedCover = null;\r\n this.canvasState.cachedNeedsBackground = false;\r\n this.canvasState.lastVideoWidth = 0;\r\n this.canvasState.lastVideoHeight = 0;\r\n }\r\n }\r\n\r\n /**\r\n * Validate stream key format\r\n * Stream keys must follow format: {tierCode}{foreignId}_{randomKey}\r\n * Tier codes: a (audio shared), b (audio VIP), v (video shared), w (video VIP)\r\n */\r\n private validateStreamKeyFormat(): void {\r\n if (!this.streamKey || this.streamKey.length < 10) {\r\n throw new Error(\"Invalid stream key: too short\");\r\n }\r\n\r\n const tierCode = this.streamKey[0];\r\n if (!['a', 'b', 'v', 'w'].includes(tierCode)) {\r\n throw new Error(\r\n `Invalid stream key format: must start with 'a', 'b', 'v', or 'w' (got '${tierCode}')`\r\n );\r\n }\r\n\r\n if (!this.streamKey.includes('_')) {\r\n throw new Error(\r\n \"Invalid stream key format: must contain underscore separator (format: {tier}{id}_{key})\"\r\n );\r\n }\r\n\r\n console.log(\"✅ Stream key format validated:\", {\r\n tierCode,\r\n isVideo: tierCode === 'v' || tierCode === 'w',\r\n isVIP: tierCode === 'b' || tierCode === 'w'\r\n });\r\n }\r\n\r\n /**\r\n * Set up canvas-based rendering pipeline for video streams.\r\n * This allows seamless camera flips by changing the video source\r\n * without affecting MediaRecorder (which records from the canvas).\r\n *\r\n * This is async to ensure the video is producing frames before returning,\r\n * which prevents black initial thumbnails.\r\n */\r\n private async setupCanvasRendering(): Promise<MediaStream> {\r\n console.log(\"🎨 Setting up canvas-based rendering for seamless camera flips\");\r\n\r\n // Get video track dimensions\r\n const videoTrack = this.mediaStream.getVideoTracks()[0];\r\n const settings = videoTrack?.getSettings() || {};\r\n const width = settings.width || 1280;\r\n const height = settings.height || 720;\r\n\r\n console.log(`📐 Video dimensions: ${width}x${height}`);\r\n\r\n // Create offscreen canvas\r\n const canvas = document.createElement(\"canvas\");\r\n canvas.width = width;\r\n canvas.height = height;\r\n const ctx = canvas.getContext(\"2d\");\r\n\r\n if (!ctx) {\r\n throw new Error(\"Failed to get 2D canvas context - canvas rendering unavailable\");\r\n }\r\n\r\n // Create hidden video element to play camera stream\r\n const videoElement = document.createElement(\"video\");\r\n videoElement.srcObject = this.mediaStream;\r\n videoElement.muted = true; // Mute to prevent echo\r\n videoElement.playsInline = true;\r\n\r\n // Wait for video to be ready before continuing\r\n await new Promise<void>((resolve) => {\r\n const checkReady = () => {\r\n if (videoElement.videoWidth > 0 && videoElement.videoHeight > 0) {\r\n console.log(`📹 Video ready: ${videoElement.videoWidth}x${videoElement.videoHeight}`);\r\n resolve();\r\n } else {\r\n // Check again on next frame\r\n requestAnimationFrame(checkReady);\r\n }\r\n };\r\n\r\n videoElement.addEventListener(\"loadeddata\", () => {\r\n checkReady();\r\n }, { once: true });\r\n\r\n // Start playback\r\n videoElement.play().catch((e: unknown) => {\r\n console.warn(\"Video autoplay warning:\", e);\r\n resolve(); // Continue anyway\r\n });\r\n\r\n // Timeout fallback\r\n setTimeout(() => {\r\n console.warn(\"⚠️ Video ready timeout - continuing anyway\");\r\n resolve();\r\n }, 2000);\r\n });\r\n\r\n // Capture canvas at the same frame rate as source (or 30fps default)\r\n const frameRate = settings.frameRate || 30;\r\n const stream = canvas.captureStream(frameRate);\r\n\r\n // Add audio track from original stream to canvas stream\r\n // (Canvas only captures video, so we need to manually add audio)\r\n const audioTracks = this.mediaStream.getAudioTracks();\r\n audioTracks.forEach((track) => {\r\n stream.addTrack(track);\r\n });\r\n\r\n console.log(`🎬 Canvas stream created with ${frameRate}fps video + ${audioTracks.length} audio track(s)`);\r\n\r\n // Initialize canvas state\r\n this.canvasState = {\r\n canvas,\r\n ctx,\r\n videoElement,\r\n stream,\r\n renderLoopId: 0, // Will be set below\r\n useBlurBackground: true,\r\n slowFrameCount: 0,\r\n cachedContain: null,\r\n cachedCover: null,\r\n cachedNeedsBackground: false,\r\n lastVideoWidth: 0,\r\n lastVideoHeight: 0,\r\n };\r\n\r\n // Draw the FIRST frame synchronously to prevent black initial thumbnails\r\n // This ensures the canvas has content before MediaRecorder starts capturing\r\n if (videoElement.videoWidth > 0 && videoElement.videoHeight > 0) {\r\n const vw = videoElement.videoWidth;\r\n const vh = videoElement.videoHeight;\r\n const cw = canvas.width;\r\n const ch = canvas.height;\r\n // Simple contain scaling for first frame\r\n const scale = Math.min(cw / vw, ch / vh);\r\n const sw = vw * scale;\r\n const sh = vh * scale;\r\n const sx = (cw - sw) / 2;\r\n const sy = (ch - sh) / 2;\r\n // Clear and draw\r\n ctx.fillStyle = \"#000\";\r\n ctx.fillRect(0, 0, cw, ch);\r\n ctx.drawImage(videoElement, sx, sy, sw, sh);\r\n console.log(\"🖼️ Drew first frame synchronously to prevent black thumbnail\");\r\n }\r\n\r\n // Start render loop - draw video frames to canvas with contain scaling\r\n // and optional blurred background fill for letterboxing\r\n const state = this.canvasState; // Capture reference for closure\r\n const renderFrame = () => {\r\n if (!this.canvasState || state !== this.canvasState) return; // State was cleaned up\r\n\r\n const { ctx, canvas, videoElement } = state;\r\n if (videoElement.paused) {\r\n // Try to resume playback - this can happen after camera flip on iOS\r\n videoElement.play().catch(() => {});\r\n // Still draw the current frame (even if paused, we can draw the last frame)\r\n // Don't skip - skipping causes the canvas to freeze\r\n }\r\n\r\n const canvasWidth = canvas.width;\r\n const canvasHeight = canvas.height;\r\n const videoWidth = videoElement.videoWidth;\r\n const videoHeight = videoElement.videoHeight;\r\n\r\n // Skip frame if video dimensions not yet available\r\n if (videoWidth === 0 || videoHeight === 0) {\r\n state.renderLoopId = requestAnimationFrame(renderFrame);\r\n return;\r\n }\r\n\r\n // Recalculate cached dimensions only when video size changes\r\n if (videoWidth !== state.lastVideoWidth || videoHeight !== state.lastVideoHeight) {\r\n state.lastVideoWidth = videoWidth;\r\n state.lastVideoHeight = videoHeight;\r\n state.cachedContain = this.calculateScaledDimensions(\r\n videoWidth, videoHeight, canvasWidth, canvasHeight, \"contain\"\r\n );\r\n state.cachedCover = this.calculateScaledDimensions(\r\n videoWidth, videoHeight, canvasWidth, canvasHeight, \"cover\"\r\n );\r\n state.cachedNeedsBackground =\r\n Math.abs(state.cachedContain.width - canvasWidth) > 1 ||\r\n Math.abs(state.cachedContain.height - canvasHeight) > 1;\r\n\r\n console.log(`📐 Video dimensions changed: ${videoWidth}x${videoHeight}, needsBackground: ${state.cachedNeedsBackground}`);\r\n }\r\n\r\n const contain = state.cachedContain!;\r\n const cover = state.cachedCover!;\r\n\r\n // Start timing after cache check (only time actual drawing)\r\n const frameStart = performance.now();\r\n\r\n if (state.cachedNeedsBackground && state.useBlurBackground) {\r\n // Draw blurred, darkened background (video scaled to cover/fill)\r\n ctx.save();\r\n ctx.filter = \"blur(20px)\";\r\n ctx.drawImage(videoElement, cover.x, cover.y, cover.width, cover.height);\r\n ctx.restore();\r\n\r\n // Darken the blurred background\r\n ctx.fillStyle = \"rgba(0, 0, 0, 0.5)\";\r\n ctx.fillRect(0, 0, canvasWidth, canvasHeight);\r\n } else if (state.cachedNeedsBackground) {\r\n // Performance mode: just use black background\r\n ctx.fillStyle = \"#000\";\r\n ctx.fillRect(0, 0, canvasWidth, canvasHeight);\r\n }\r\n\r\n // Draw the main video (contain scaling, centered)\r\n ctx.drawImage(videoElement, contain.x, contain.y, contain.width, contain.height);\r\n\r\n // Adaptive performance: disable blur if frames are too slow\r\n const frameDuration = performance.now() - frameStart;\r\n if (frameDuration > 16 && state.useBlurBackground) {\r\n state.slowFrameCount++;\r\n if (state.slowFrameCount > 5) {\r\n console.log(\"⚡ Disabling blur background for performance\");\r\n state.useBlurBackground = false;\r\n }\r\n } else if (frameDuration <= 16) {\r\n state.slowFrameCount = 0;\r\n }\r\n\r\n state.renderLoopId = requestAnimationFrame(renderFrame);\r\n };\r\n state.renderLoopId = requestAnimationFrame(renderFrame);\r\n\r\n console.log(\"✅ Canvas rendering pipeline ready (with adaptive blur background)\");\r\n return stream;\r\n }\r\n\r\n /**\r\n * Clean up canvas rendering resources\r\n */\r\n private cleanupCanvasRendering(): void {\r\n if (!this.canvasState) return;\r\n\r\n cancelAnimationFrame(this.canvasState.renderLoopId);\r\n this.canvasState.videoElement.pause();\r\n this.canvasState.videoElement.srcObject = null;\r\n this.canvasState.stream.getTracks().forEach((track) => track.stop());\r\n this.canvasState = null;\r\n }\r\n\r\n /**\r\n * Build WebSocket URL from stream key\r\n */\r\n private buildWebSocketUrl(): string {\r\n const url = new URL(this.encoderServerUrl);\r\n\r\n // Convert HTTP(S) to WebSocket protocol\r\n if (url.protocol === \"http:\") {\r\n url.protocol = \"ws:\";\r\n } else if (url.protocol === \"https:\") {\r\n url.protocol = \"wss:\";\r\n }\r\n\r\n // Build path: /targets/dialtribe?key={streamKey}\r\n url.pathname = \"/targets/dialtribe\";\r\n url.searchParams.set(\"key\", this.streamKey);\r\n\r\n return url.toString();\r\n }\r\n\r\n /**\r\n * Start streaming\r\n */\r\n async start(): Promise<void> {\r\n try {\r\n // Reset state from any previous session\r\n this.userStopped = false;\r\n this.chunksSent = 0;\r\n this.bytesSent = 0;\r\n this.startTime = 0;\r\n\r\n // Validate stream key format before attempting connection\r\n this.validateStreamKeyFormat();\r\n\r\n this.onStateChange?.(\"connecting\");\r\n\r\n // Build WebSocket URL\r\n const wsUrl = this.buildWebSocketUrl();\r\n console.log(\"📡 Connecting to WebSocket:\", wsUrl.replace(this.streamKey, \"***\"));\r\n\r\n // Create WebSocket connection\r\n this.websocket = new WebSocket(wsUrl);\r\n\r\n // Wait for WebSocket to open\r\n await new Promise<void>((resolve, reject) => {\r\n if (!this.websocket) {\r\n reject(new Error(\"WebSocket not initialized\"));\r\n return;\r\n }\r\n\r\n // Set up timeout that we can clear on success/failure\r\n const timeoutId = setTimeout(() => {\r\n reject(new Error(`WebSocket connection timeout. URL: ${wsUrl}`));\r\n }, 10000);\r\n\r\n this.websocket.addEventListener(\"open\", () => {\r\n clearTimeout(timeoutId);\r\n resolve();\r\n }, { once: true });\r\n\r\n this.websocket.addEventListener(\"error\", (event) => {\r\n clearTimeout(timeoutId);\r\n console.error(\"❌ WebSocket error event:\", event);\r\n console.error(\"🔍 Connection diagnostics:\", {\r\n url: wsUrl.replace(this.streamKey, \"***\"),\r\n streamKeyFormat: this.streamKey.substring(0, 5) + \"***\",\r\n readyState: this.websocket?.readyState,\r\n readyStateText: [\"CONNECTING\", \"OPEN\", \"CLOSING\", \"CLOSED\"][this.websocket?.readyState || 0]\r\n });\r\n reject(new Error(\r\n `WebSocket connection failed (likely 403 Forbidden).\\n\\n` +\r\n `Common causes:\\n` +\r\n `1. Encoder server cannot connect to the database\\n` +\r\n `2. Encoder server is using a different database\\n` +\r\n `3. Stream key validation failed on encoder server\\n\\n` +\r\n `Please check encoder server logs and DATABASE_URL configuration.`\r\n ));\r\n }, { once: true });\r\n });\r\n\r\n console.log(\"✅ WebSocket connected\");\r\n\r\n // Set up WebSocket event handlers\r\n this.setupWebSocketHandlers();\r\n\r\n // For video streams, use canvas-based rendering to enable seamless camera flips\r\n // For audio-only streams, record directly from the media stream\r\n // Canvas can be disabled for debugging HLS issues\r\n const useCanvas = this.isVideo && !this.disableCanvasRendering;\r\n const streamToRecord = useCanvas\r\n ? await this.setupCanvasRendering()\r\n : this.mediaStream;\r\n\r\n // Create MediaRecorder\r\n const recorderOptions = getMediaRecorderOptions(this.isVideo);\r\n this.mimeType = recorderOptions.mimeType;\r\n this.mediaRecorder = new MediaRecorder(streamToRecord, recorderOptions);\r\n\r\n console.log(\"🎙️ MediaRecorder created with options:\", recorderOptions);\r\n if (useCanvas) {\r\n console.log(\"🎨 Recording from canvas stream (enables seamless camera flips)\");\r\n } else if (this.isVideo) {\r\n console.log(\"📹 Recording directly from camera (canvas disabled)\");\r\n }\r\n\r\n // Set up MediaRecorder event handlers\r\n this.setupMediaRecorderHandlers();\r\n\r\n // Start recording - send chunks every 300ms\r\n this.mediaRecorder.start(300);\r\n this.startTime = Date.now();\r\n\r\n console.log(\"🔴 Recording started\");\r\n this.onStateChange?.(\"live\");\r\n } catch (error) {\r\n console.error(\"❌ Error starting stream:\", error);\r\n this.onError?.(error instanceof Error ? error.message : \"Failed to start stream\");\r\n this.onStateChange?.(\"error\");\r\n this.stop();\r\n throw error;\r\n }\r\n }\r\n\r\n /**\r\n * Stop streaming\r\n */\r\n stop(): void {\r\n console.log(\"⏹️ Stopping stream\");\r\n this.userStopped = true; // Mark as user-initiated stop\r\n\r\n // Stop MediaRecorder\r\n if (this.mediaRecorder && this.mediaRecorder.state !== \"inactive\") {\r\n this.mediaRecorder.stop();\r\n console.log(\"⏹️ MediaRecorder stopped\");\r\n }\r\n\r\n // Close WebSocket\r\n if (this.websocket) {\r\n const readyStateNames = [\"CONNECTING\", \"OPEN\", \"CLOSING\", \"CLOSED\"];\r\n const stateName = readyStateNames[this.websocket.readyState] || \"UNKNOWN\";\r\n console.log(`🔌 WebSocket state: ${stateName} (${this.websocket.readyState})`);\r\n\r\n // Close regardless of state - safe to call on any state\r\n if (this.websocket.readyState !== WebSocket.CLOSED) {\r\n this.websocket.close();\r\n console.log(\"🔌 WebSocket close() called\");\r\n } else {\r\n console.log(\"🔌 WebSocket already closed\");\r\n }\r\n } else {\r\n console.log(\"⚠️ No WebSocket to close\");\r\n }\r\n\r\n // Clean up canvas rendering\r\n this.cleanupCanvasRendering();\r\n\r\n // Clean up references\r\n this.mediaRecorder = null;\r\n this.websocket = null;\r\n\r\n this.onStateChange?.(\"stopped\");\r\n }\r\n\r\n /**\r\n * Get total bytes sent\r\n */\r\n getBytesSent(): number {\r\n return this.bytesSent;\r\n }\r\n\r\n /**\r\n * Get the current source media stream.\r\n * This may change after replaceVideoTrack() is called.\r\n */\r\n getMediaStream(): MediaStream {\r\n return this.mediaStream;\r\n }\r\n\r\n /**\r\n * Get current diagnostics\r\n */\r\n private getDiagnostics(closeCode?: number, closeReason?: string): StreamDiagnostics {\r\n return {\r\n mimeType: this.mimeType,\r\n chunksSent: this.chunksSent,\r\n bytesSent: this.bytesSent,\r\n elapsedMs: this.startTime ? Date.now() - this.startTime : 0,\r\n closeCode,\r\n closeReason,\r\n };\r\n }\r\n\r\n /**\r\n * Replace the video track for camera flips.\r\n *\r\n * When using canvas-based rendering (video streams), this preloads the new\r\n * camera in a temporary video element, waits for it to be ready, then swaps\r\n * it in. This ensures continuous frame output with no gaps.\r\n *\r\n * @param newVideoTrack - The new video track from the flipped camera\r\n * @returns Promise that resolves when the swap is complete\r\n */\r\n async replaceVideoTrack(newVideoTrack: MediaStreamTrack): Promise<void> {\r\n console.log(\"🔄 Replacing video track\");\r\n\r\n if (this.canvasState) {\r\n // Canvas-based rendering: Preload new camera before switching\r\n console.log(\"🎨 Using canvas-based swap with preloading (no frame gaps)\");\r\n\r\n // Create a new MediaStream with the new video track and existing audio\r\n const audioTracks = this.mediaStream.getAudioTracks();\r\n const newStream = new MediaStream([newVideoTrack, ...audioTracks]);\r\n\r\n // Create temporary video element to preload new camera\r\n const preloadVideo = document.createElement(\"video\");\r\n preloadVideo.srcObject = newStream;\r\n preloadVideo.muted = true;\r\n preloadVideo.playsInline = true;\r\n\r\n // Wait for new video to be ready AND PLAYING\r\n // On iOS Safari, orphan video elements may not autoplay - we MUST verify\r\n await new Promise<void>((resolve, reject) => {\r\n const timeout = setTimeout(() => {\r\n console.warn(\"⚠️ Video preload timeout - switching anyway\");\r\n // Last-ditch attempt to play\r\n if (preloadVideo.paused) {\r\n preloadVideo.play().catch(() => {});\r\n }\r\n resolve();\r\n }, 3000);\r\n\r\n // Check if video is ready: has dimensions AND is playing (not paused)\r\n const checkFullyReady = () => {\r\n if (preloadVideo.videoWidth > 0 && preloadVideo.videoHeight > 0 && !preloadVideo.paused) {\r\n clearTimeout(timeout);\r\n console.log(`📹 New camera ready and playing: ${preloadVideo.videoWidth}x${preloadVideo.videoHeight}`);\r\n resolve();\r\n return true;\r\n }\r\n return false;\r\n };\r\n\r\n preloadVideo.addEventListener(\"loadeddata\", () => {\r\n // Has metadata, now try to play\r\n preloadVideo.play().then(() => {\r\n // Wait a frame for play to take effect, then check\r\n requestAnimationFrame(() => {\r\n if (!checkFullyReady()) {\r\n // Keep checking until playing\r\n const pollPlaying = setInterval(() => {\r\n if (checkFullyReady()) {\r\n clearInterval(pollPlaying);\r\n }\r\n }, 50);\r\n // Stop polling after 2s\r\n setTimeout(() => clearInterval(pollPlaying), 2000);\r\n }\r\n });\r\n }).catch((e: unknown) => {\r\n console.warn(\"Video preload play warning:\", e);\r\n // On iOS, try user interaction workaround - but we're async so this might not help\r\n // Still resolve to not block forever, but video might be paused\r\n checkFullyReady();\r\n });\r\n }, { once: true });\r\n\r\n preloadVideo.addEventListener(\"error\", (e) => {\r\n clearTimeout(timeout);\r\n reject(new Error(`Video preload failed: ${e}`));\r\n }, { once: true });\r\n\r\n // Initial play attempt (might fail on iOS, loadeddata handler will retry)\r\n preloadVideo.play().catch(() => {});\r\n });\r\n\r\n // IMPORTANT: Swap FIRST, then cleanup old - this prevents frame gaps\r\n // If we stop old tracks before swapping, the render loop draws black frames\r\n const oldVideoElement = this.canvasState.videoElement;\r\n this.canvasState.videoElement = preloadVideo;\r\n\r\n // NOW stop old tracks and cleanup (after render loop has switched to new source)\r\n this.mediaStream.getVideoTracks().forEach((track) => track.stop());\r\n oldVideoElement.pause();\r\n oldVideoElement.srcObject = null;\r\n\r\n // Update our reference to the source media stream\r\n this.mediaStream = newStream;\r\n\r\n // Invalidate cached scaling dimensions - new camera may have different resolution\r\n this.invalidateScalingCache();\r\n\r\n const settings = newVideoTrack.getSettings();\r\n if (settings.width && settings.height) {\r\n console.log(`📐 New camera resolution: ${settings.width}x${settings.height}`);\r\n }\r\n\r\n console.log(\"✅ Video source swapped - canvas continues seamlessly\");\r\n } else {\r\n // Fallback for non-canvas mode (shouldn't happen for video streams)\r\n console.warn(\"⚠️ Canvas not available - attempting direct track replacement\");\r\n\r\n // Get current video tracks\r\n const oldVideoTracks = this.mediaStream.getVideoTracks();\r\n\r\n // Add new track first (MediaRecorder will pick it up)\r\n this.mediaStream.addTrack(newVideoTrack);\r\n console.log(\"➕ New video track added\");\r\n\r\n // Remove and stop old tracks\r\n oldVideoTracks.forEach((track) => {\r\n this.mediaStream.removeTrack(track);\r\n track.stop();\r\n });\r\n console.log(\"➖ Old video track(s) removed\");\r\n\r\n console.log(\"✅ Video track replaced\");\r\n }\r\n }\r\n\r\n /**\r\n * Replace the audio track in the current MediaStream without stopping MediaRecorder.\r\n *\r\n * @param newAudioTrack - The new audio track\r\n */\r\n replaceAudioTrack(newAudioTrack: MediaStreamTrack): void {\r\n console.log(\"🔄 Replacing audio track (no MediaRecorder restart)\");\r\n\r\n const oldAudioTracks = this.mediaStream.getAudioTracks();\r\n\r\n // Update the source media stream\r\n this.mediaStream.addTrack(newAudioTrack);\r\n console.log(\"➕ New audio track added to source stream\");\r\n\r\n oldAudioTracks.forEach((track) => {\r\n this.mediaStream.removeTrack(track);\r\n track.stop();\r\n });\r\n console.log(\"➖ Old audio track(s) removed from source stream\");\r\n\r\n // Also update the canvas stream if we're using canvas-based rendering\r\n // (MediaRecorder records from canvasStream, so it needs the new audio track)\r\n if (this.canvasState) {\r\n // Remove old audio tracks from canvas stream\r\n this.canvasState.stream.getAudioTracks().forEach((track) => {\r\n this.canvasState!.stream.removeTrack(track);\r\n });\r\n // Add new audio track to canvas stream\r\n this.canvasState.stream.addTrack(newAudioTrack);\r\n console.log(\"🎨 Audio track synced to canvas stream\");\r\n }\r\n\r\n console.log(\"✅ Audio track replaced - streaming continues seamlessly\");\r\n }\r\n\r\n /**\r\n * Update the media stream (e.g., when switching devices from settings)\r\n * This keeps the WebSocket connection alive while swapping the media source.\r\n * Restarts the MediaRecorder with the new stream.\r\n *\r\n * Note: For camera flips, prefer replaceVideoTrack() which doesn't restart MediaRecorder.\r\n * Note: Errors are thrown to the caller, not sent to onError callback.\r\n */\r\n async updateMediaStream(newMediaStream: MediaStream): Promise<void> {\r\n console.log(\"🔄 Updating media stream (hot-swap)\");\r\n\r\n // Set flag to prevent WebSocket from closing when MediaRecorder stops\r\n this.isHotSwapping = true;\r\n\r\n // Stop current MediaRecorder\r\n if (this.mediaRecorder && this.mediaRecorder.state !== \"inactive\") {\r\n this.mediaRecorder.stop();\r\n console.log(\"⏹️ Old MediaRecorder stopped\");\r\n }\r\n\r\n // Update the media stream\r\n this.mediaStream = newMediaStream;\r\n\r\n // For video streams, recreate canvas rendering pipeline with new stream\r\n // For audio-only streams, record directly from the media stream\r\n const useCanvas = this.isVideo && !this.disableCanvasRendering;\r\n let streamToRecord = this.mediaStream;\r\n if (useCanvas) {\r\n this.cleanupCanvasRendering();\r\n streamToRecord = await this.setupCanvasRendering();\r\n console.log(\"🎨 Canvas rendering recreated for new stream\");\r\n }\r\n\r\n // Create new MediaRecorder with the appropriate stream\r\n const recorderOptions = getMediaRecorderOptions(this.isVideo);\r\n this.mediaRecorder = new MediaRecorder(streamToRecord, recorderOptions);\r\n\r\n console.log(\"🎙️ New MediaRecorder created\");\r\n\r\n // Set up MediaRecorder event handlers\r\n this.setupMediaRecorderHandlers();\r\n\r\n // Start recording again\r\n this.mediaRecorder.start(300);\r\n\r\n // Clear the hot-swap flag\r\n this.isHotSwapping = false;\r\n\r\n console.log(\"✅ Media stream updated - streaming continues\");\r\n }\r\n\r\n /**\r\n * Set up WebSocket event handlers\r\n */\r\n private setupWebSocketHandlers(): void {\r\n if (!this.websocket) return;\r\n\r\n this.websocket.addEventListener(\"close\", (event) => {\r\n console.log(\"🔌 WebSocket closed\", { code: event.code, reason: event.reason });\r\n\r\n // If WebSocket closes and user didn't stop it, determine the cause\r\n if (!this.userStopped) {\r\n const diagnostics = this.getDiagnostics(event.code, event.reason);\r\n console.warn(\"⚠️ Stream ended unexpectedly\", diagnostics);\r\n\r\n // Determine error message based on close code\r\n let errorMessage: string;\r\n if (event.code === 1000) {\r\n // Normal closure - server decided to close\r\n errorMessage = event.reason || \"Stream ended by server\";\r\n } else if (event.code === 1001) {\r\n // Going away - server shutting down or client navigating\r\n errorMessage = \"Connection closed - server going away\";\r\n } else if (event.code === 1006) {\r\n // Abnormal closure - network issue\r\n errorMessage = \"Connection lost unexpectedly\";\r\n } else if (event.code >= 4000 && event.code < 5000) {\r\n // Application-specific codes\r\n errorMessage = event.reason || \"Stream terminated by server\";\r\n } else {\r\n errorMessage = `Connection closed (code: ${event.code})`;\r\n }\r\n\r\n this.onStateChange?.(\"terminated\");\r\n this.onError?.(errorMessage, diagnostics);\r\n }\r\n\r\n // Stop MediaRecorder if still running\r\n if (this.mediaRecorder && this.mediaRecorder.state !== \"inactive\") {\r\n this.mediaRecorder.stop();\r\n }\r\n });\r\n\r\n this.websocket.addEventListener(\"error\", (event) => {\r\n console.error(\"❌ WebSocket error:\", event);\r\n this.onError?.(\"WebSocket connection error\");\r\n this.onStateChange?.(\"error\");\r\n });\r\n }\r\n\r\n /**\r\n * Set up MediaRecorder event handlers\r\n */\r\n private setupMediaRecorderHandlers(): void {\r\n if (!this.mediaRecorder) return;\r\n\r\n // Handle data available - send chunks to WebSocket\r\n this.mediaRecorder.addEventListener(\"dataavailable\", (event) => {\r\n if (event.data.size > 0 && this.websocket?.readyState === WebSocket.OPEN) {\r\n this.websocket.send(event.data);\r\n this.bytesSent += event.data.size;\r\n this.chunksSent += 1;\r\n this.onBytesUpdate?.(this.bytesSent);\r\n\r\n // Log every 10th chunk to reduce console noise (roughly every 3 seconds)\r\n if (this.chunksSent % 10 === 0) {\r\n console.log(`📤 Sent ${this.chunksSent} chunks (${(this.bytesSent / 1024 / 1024).toFixed(2)} MB total)`);\r\n }\r\n }\r\n });\r\n\r\n // Handle errors\r\n this.mediaRecorder.addEventListener(\"error\", (event: Event) => {\r\n const errorEvent = event as ErrorEvent;\r\n console.error(\"❌ MediaRecorder error:\", errorEvent.error);\r\n this.onError?.(`Encoding error: ${errorEvent.error?.toString() || \"Unknown error\"}`);\r\n this.onStateChange?.(\"error\");\r\n this.stop();\r\n });\r\n\r\n // Handle stop\r\n this.mediaRecorder.addEventListener(\"stop\", () => {\r\n console.log(\"⏹️ MediaRecorder stopped\");\r\n // Only close WebSocket if this is a real stop, not a hot-swap\r\n if (!this.isHotSwapping && this.websocket?.readyState === WebSocket.OPEN) {\r\n this.websocket.close();\r\n }\r\n });\r\n }\r\n}\r\n","import { useEffect, useRef, useState } from \"react\";\r\n\r\ninterface AudioWaveformProps {\r\n /** Audio/video element for playback visualization */\r\n audioElement?: HTMLMediaElement | null;\r\n /** Media stream for live streaming visualization */\r\n mediaStream?: MediaStream | null;\r\n /** Whether the audio is currently playing (for playback mode) */\r\n isPlaying?: boolean;\r\n /** Whether this is currently a live stream (for HLS streams) */\r\n isLive?: boolean;\r\n}\r\n\r\n/**\r\n * Shared audio waveform visualization component\r\n * Can be used for both live streaming (MediaStream) and playback (HTMLVideoElement)\r\n */\r\nexport function AudioWaveform({\r\n audioElement,\r\n mediaStream,\r\n isPlaying = false,\r\n isLive = false,\r\n}: AudioWaveformProps) {\r\n const canvasRef = useRef<HTMLCanvasElement>(null);\r\n const animationFrameRef = useRef<number | undefined>(undefined);\r\n const [setupError, setSetupError] = useState(false);\r\n const isPlayingRef = useRef(isPlaying);\r\n const isLiveRef = useRef(isLive);\r\n\r\n // Sync playing state ref\r\n useEffect(() => {\r\n isPlayingRef.current = isPlaying;\r\n }, [isPlaying]);\r\n\r\n // Sync live state ref\r\n useEffect(() => {\r\n isLiveRef.current = isLive;\r\n }, [isLive]);\r\n\r\n useEffect(() => {\r\n const canvas = canvasRef.current;\r\n if (!canvas) return;\r\n\r\n const ctx = canvas.getContext(\"2d\");\r\n if (!ctx) return;\r\n\r\n // Validate audio element before using it\r\n // Accept both native HTMLMediaElement and custom elements with video/audio API (like HLS-VIDEO)\r\n if (audioElement) {\r\n const hasMediaAPI =\r\n \"play\" in audioElement &&\r\n \"pause\" in audioElement &&\r\n \"currentTime\" in audioElement;\r\n const isMediaElement = audioElement instanceof HTMLMediaElement;\r\n\r\n if (!hasMediaAPI && !isMediaElement) {\r\n console.warn(\r\n \"[AudioWaveform] Invalid audio element - missing media API\"\r\n );\r\n return;\r\n }\r\n\r\n console.log(\"[AudioWaveform] Audio element validation:\", {\r\n tagName: audioElement.tagName,\r\n isHTMLMediaElement: isMediaElement,\r\n hasMediaAPI: hasMediaAPI,\r\n willAttemptVisualization: true,\r\n });\r\n }\r\n\r\n // Check if we can use the audio element for visualization\r\n const canUseAudioElement =\r\n audioElement && audioElement instanceof HTMLMediaElement;\r\n\r\n // Check if this is specifically an HLS live stream (custom element)\r\n const isHLSLiveStream = audioElement && !canUseAudioElement;\r\n\r\n // If we don't have a valid source, or have a custom element, show static waveform\r\n if (\r\n (!audioElement && !mediaStream) ||\r\n (audioElement && !canUseAudioElement)\r\n ) {\r\n // Enhanced dynamic waveform for HLS live streams\r\n if (isHLSLiveStream) {\r\n let time = 0;\r\n let frozenTime = 0; // Store time when stream ends\r\n let wasFrozen = false; // Track if we've frozen\r\n let frameCount = 0;\r\n // Create unique phase offsets for each bar to desynchronize them\r\n const barPhases = Array.from(\r\n { length: 128 },\r\n () => Math.random() * Math.PI * 2\r\n );\r\n const barSpeeds = Array.from(\r\n { length: 128 },\r\n () => 0.8 + Math.random() * 0.4\r\n ); // Speed variance 0.8-1.2x\r\n const glowPhases = Array.from(\r\n { length: 128 },\r\n () => Math.random() * Math.PI * 2\r\n ); // Unique glow phase per bar\r\n const glowSpeeds = Array.from(\r\n { length: 128 },\r\n () => 0.7 + Math.random() * 0.6\r\n ); // Glow speed variance 0.7-1.3x\r\n\r\n const drawEnhancedWaveform = () => {\r\n frameCount++;\r\n ctx.fillStyle = \"#000\";\r\n ctx.fillRect(0, 0, canvas.width, canvas.height);\r\n\r\n const gradient = ctx.createLinearGradient(0, 0, canvas.width, 0);\r\n gradient.addColorStop(0, \"#06b6d4\");\r\n gradient.addColorStop(0.3, \"#3b82f6\");\r\n gradient.addColorStop(0.6, \"#8b5cf6\");\r\n gradient.addColorStop(1, \"#ec4899\");\r\n\r\n // Check current live state from ref (always up-to-date)\r\n const currentlyLive = isLiveRef.current;\r\n\r\n // Only increment time if stream is live\r\n if (currentlyLive) {\r\n time += 0.02;\r\n wasFrozen = false; // Reset frozen state if we go live again\r\n } else if (!wasFrozen) {\r\n // Stream just ended, freeze at current time\r\n frozenTime = time;\r\n wasFrozen = true;\r\n }\r\n\r\n // Use frozen time when paused\r\n const currentTime = wasFrozen ? frozenTime : time;\r\n\r\n const barCount = 128;\r\n const barWidth = canvas.width / barCount;\r\n const gap = 2;\r\n const maxHeight = canvas.height * 0.9; // Allow bars to reach 90% of container height\r\n\r\n for (let i = 0; i < barCount; i++) {\r\n // Layer multiple sine waves with different frequencies for organic movement\r\n const primaryWave =\r\n Math.sin(\r\n (i / barCount) * Math.PI * 2 * 2.5 -\r\n currentTime * barSpeeds[i] +\r\n barPhases[i]\r\n ) *\r\n (maxHeight * 0.35);\r\n const secondaryWave =\r\n Math.sin(\r\n (i / barCount) * Math.PI * 2 * 4 -\r\n currentTime * barSpeeds[i] * 1.3 +\r\n barPhases[i] * 0.7\r\n ) *\r\n (maxHeight * 0.15);\r\n const tertiaryWave =\r\n Math.sin(\r\n (i / barCount) * Math.PI * 2 * 7 -\r\n currentTime * barSpeeds[i] * 0.8 +\r\n barPhases[i] * 1.5\r\n ) *\r\n (maxHeight * 0.1);\r\n\r\n // Combine waves for complex, organic height variation\r\n const baseHeight = maxHeight * 0.15;\r\n const combinedWave = primaryWave + secondaryWave + tertiaryWave;\r\n const barHeight = Math.max(\r\n 10,\r\n Math.min(maxHeight, baseHeight + combinedWave)\r\n ); // Min 10px, max 90% container\r\n\r\n // Multi-layered opacity variation for depth\r\n const opacityWave1 = Math.sin(\r\n (i / barCount) * Math.PI * 2 * 1.5 - currentTime * 1.2\r\n );\r\n const opacityWave2 = Math.sin(\r\n (i / barCount) * Math.PI * 2 * 3.5 - currentTime * 0.7\r\n );\r\n const opacity =\r\n 0.3 + opacityWave1 * 0.25 + opacityWave2 * 0.15; // Range: 0.3-0.7\r\n\r\n // Variable glow intensity - each bar has unique glow animation\r\n const glowWave = Math.sin(\r\n currentTime * glowSpeeds[i] + glowPhases[i]\r\n );\r\n const glowIntensity = 8 + glowWave * 12; // Range: 0-20 (varies per bar)\r\n\r\n const x = i * barWidth;\r\n const y = canvas.height / 2 - barHeight / 2;\r\n\r\n ctx.shadowBlur = glowIntensity;\r\n ctx.shadowColor = \"#3b82f6\";\r\n ctx.fillStyle = gradient;\r\n ctx.globalAlpha = Math.max(0.15, Math.min(0.9, opacity)); // Clamp between 0.15-0.9\r\n ctx.fillRect(x + gap / 2, y, barWidth - gap, barHeight);\r\n }\r\n ctx.globalAlpha = 1.0;\r\n ctx.shadowBlur = 0;\r\n };\r\n\r\n const animationId = setInterval(drawEnhancedWaveform, 1000 / 60);\r\n return () => clearInterval(animationId);\r\n }\r\n\r\n // Simple static waveform for other cases (loading state, etc.)\r\n let waveOffset = 0;\r\n const drawPlaceholder = () => {\r\n ctx.fillStyle = \"#000\";\r\n ctx.fillRect(0, 0, canvas.width, canvas.height);\r\n\r\n const gradient = ctx.createLinearGradient(0, 0, canvas.width, 0);\r\n gradient.addColorStop(0, \"#06b6d4\");\r\n gradient.addColorStop(0.3, \"#3b82f6\");\r\n gradient.addColorStop(0.6, \"#8b5cf6\");\r\n gradient.addColorStop(1, \"#ec4899\");\r\n\r\n waveOffset += 0.0083;\r\n\r\n const barCount = 128;\r\n const barWidth = canvas.width / barCount;\r\n const gap = 2;\r\n const baseHeight = 15;\r\n const waveAmplitude = 10;\r\n\r\n for (let i = 0; i < barCount; i++) {\r\n const wave =\r\n Math.sin((i / barCount) * Math.PI * 2 * 3 - waveOffset) *\r\n waveAmplitude;\r\n const barHeight = baseHeight + wave;\r\n const opacityWave = Math.sin(\r\n (i / barCount) * Math.PI * 2 * 2 - waveOffset * 1.5\r\n );\r\n const opacity = 0.5 + opacityWave * 0.3;\r\n\r\n const x = i * barWidth;\r\n const y = canvas.height / 2 - barHeight / 2;\r\n\r\n ctx.shadowBlur = 15;\r\n ctx.shadowColor = \"#3b82f6\";\r\n ctx.fillStyle = gradient;\r\n ctx.globalAlpha = opacity;\r\n ctx.fillRect(x + gap / 2, y, barWidth - gap, barHeight);\r\n }\r\n ctx.globalAlpha = 1.0;\r\n ctx.shadowBlur = 0;\r\n };\r\n\r\n const animationId = setInterval(drawPlaceholder, 1000 / 60);\r\n return () => clearInterval(animationId);\r\n }\r\n\r\n let audioContext: AudioContext | null = null;\r\n let analyser: AnalyserNode | null = null;\r\n let source:\r\n | MediaElementAudioSourceNode\r\n | MediaStreamAudioSourceNode\r\n | null = null;\r\n\r\n // Set up audio analyser\r\n try {\r\n audioContext = new AudioContext();\r\n analyser = audioContext.createAnalyser();\r\n analyser.fftSize = 2048;\r\n\r\n // Create source from either audio element or media stream\r\n if (audioElement) {\r\n // Playback mode: use HTMLVideoElement\r\n // Note: Custom elements like HLS-VIDEO are NOT supported by Web Audio API\r\n console.log(\"[AudioWaveform] Creating audio source from element:\", {\r\n tagName: audioElement.tagName,\r\n src: audioElement.src?.substring(0, 80),\r\n readyState: audioElement.readyState,\r\n paused: audioElement.paused,\r\n currentTime: audioElement.currentTime,\r\n hasSourceNode: !!(audioElement as any).audioSourceNode,\r\n isNativeElement: audioElement instanceof HTMLMediaElement,\r\n });\r\n\r\n // Web Audio API only works with native HTMLMediaElement (VIDEO, AUDIO tags)\r\n // Custom elements like HLS-VIDEO are not supported\r\n if (!(audioElement instanceof HTMLMediaElement)) {\r\n console.warn(\r\n \"[AudioWaveform] Cannot visualize custom element (HLS-VIDEO), falling back to static waveform\"\r\n );\r\n setSetupError(true);\r\n return; // Let the placeholder waveform handle it\r\n }\r\n\r\n // Check if source was already created (can only call createMediaElementSource once per element)\r\n if ((audioElement as any).audioSourceNode) {\r\n console.log(\r\n \"[AudioWaveform] Audio source already exists, reusing it\"\r\n );\r\n source = (audioElement as any).audioSourceNode;\r\n source?.connect(analyser);\r\n analyser.connect(audioContext.destination);\r\n } else {\r\n try {\r\n source = audioContext.createMediaElementSource(audioElement);\r\n source.connect(analyser);\r\n analyser.connect(audioContext.destination);\r\n // Store reference so we don't try to create it again\r\n (audioElement as any).audioSourceNode = source;\r\n console.log(\r\n \"[AudioWaveform] Audio source created and connected successfully\"\r\n );\r\n } catch (error) {\r\n console.error(\r\n \"[AudioWaveform] Failed to create media element source:\",\r\n error\r\n );\r\n setSetupError(true);\r\n return; // Let the placeholder waveform handle it\r\n }\r\n }\r\n\r\n // Track if audio is actually playing\r\n audioElement.addEventListener(\"play\", () => {\r\n console.log(\"[AudioWaveform] Play event - setting isPlaying to true\");\r\n isPlayingRef.current = true;\r\n });\r\n audioElement.addEventListener(\"pause\", () => {\r\n console.log(\r\n \"[AudioWaveform] Pause event - setting isPlaying to false\"\r\n );\r\n isPlayingRef.current = false;\r\n });\r\n audioElement.addEventListener(\"ended\", () => {\r\n console.log(\r\n \"[AudioWaveform] Ended event - setting isPlaying to false\"\r\n );\r\n isPlayingRef.current = false;\r\n });\r\n\r\n // Log initial state\r\n console.log(\"[AudioWaveform] Initial audio state:\", {\r\n paused: audioElement.paused,\r\n currentTime: audioElement.currentTime,\r\n readyState: audioElement.readyState,\r\n });\r\n\r\n // Set initial playing state based on audio element\r\n if (!audioElement.paused) {\r\n isPlayingRef.current = true;\r\n }\r\n } else if (mediaStream) {\r\n // Live streaming mode: use MediaStream\r\n source = audioContext.createMediaStreamSource(mediaStream);\r\n source.connect(analyser);\r\n // Note: Don't connect to destination for live streams - we don't want to echo the audio\r\n isPlayingRef.current = true; // Always \"playing\" for live streams\r\n } else {\r\n // No audio source provided\r\n return;\r\n }\r\n\r\n const bufferLength = analyser.frequencyBinCount;\r\n const dataArray = new Uint8Array(bufferLength);\r\n\r\n let waveOffset = 0;\r\n\r\n const drawStaticWaveform = () => {\r\n // Clear canvas\r\n ctx.fillStyle = \"#000\";\r\n ctx.fillRect(0, 0, canvas.width, canvas.height);\r\n\r\n // Create gradient\r\n const gradient = ctx.createLinearGradient(0, 0, canvas.width, 0);\r\n gradient.addColorStop(0, \"#06b6d4\");\r\n gradient.addColorStop(0.3, \"#3b82f6\");\r\n gradient.addColorStop(0.6, \"#8b5cf6\");\r\n gradient.addColorStop(1, \"#ec4899\");\r\n\r\n // Animate wave (super subtle speed)\r\n waveOffset += 0.0083;\r\n\r\n // Draw animated wave\r\n const barCount = 128;\r\n const barWidth = canvas.width / barCount;\r\n const gap = 2;\r\n const baseHeight = 15; // Half the previous height\r\n const waveAmplitude = 10; // How much the bars grow/shrink (more subtle)\r\n\r\n for (let i = 0; i < barCount; i++) {\r\n // Create smooth wave using sine function (subtract to flow right)\r\n const wave =\r\n Math.sin((i / barCount) * Math.PI * 2 * 3 - waveOffset) *\r\n waveAmplitude;\r\n const barHeight = baseHeight + wave;\r\n\r\n // Create opacity wave (dims and brightens as it flows)\r\n const opacityWave = Math.sin(\r\n (i / barCount) * Math.PI * 2 * 2 - waveOffset * 1.5\r\n );\r\n const opacity = 0.5 + opacityWave * 0.3; // Increased from 0.3 + 0.2 for better visibility\r\n\r\n const x = i * barWidth;\r\n const y = canvas.height / 2 - barHeight / 2;\r\n\r\n // Add subtle glow\r\n ctx.shadowBlur = 15; // Increased glow\r\n ctx.shadowColor = \"#3b82f6\";\r\n\r\n ctx.fillStyle = gradient;\r\n ctx.globalAlpha = opacity;\r\n ctx.fillRect(x + gap / 2, y, barWidth - gap, barHeight);\r\n }\r\n ctx.globalAlpha = 1.0;\r\n ctx.shadowBlur = 0;\r\n };\r\n\r\n let frameCount = 0;\r\n const draw = () => {\r\n if (!analyser) return;\r\n animationFrameRef.current = requestAnimationFrame(draw);\r\n\r\n analyser.getByteFrequencyData(dataArray);\r\n\r\n // Check if there's actual audio activity\r\n const hasActivity = dataArray.some((value) => value > 0);\r\n const maxValue = Math.max(...dataArray);\r\n\r\n // Debug logging - log first 5 frames and then every 60 frames (once per second at 60fps)\r\n frameCount++;\r\n if (frameCount < 5 || frameCount % 60 === 0) {\r\n console.log(\"[AudioWaveform] Frame\", frameCount, \"Audio activity:\", {\r\n hasActivity,\r\n maxValue,\r\n isPlaying: isPlayingRef.current,\r\n sampleValues: [\r\n dataArray[0],\r\n dataArray[10],\r\n dataArray[50],\r\n dataArray[100],\r\n ],\r\n avgValue:\r\n dataArray.reduce((a, b) => a + b, 0) / dataArray.length,\r\n });\r\n }\r\n\r\n if (!hasActivity || !isPlayingRef.current) {\r\n // Show static waveform when paused/stopped\r\n if (frameCount < 5) {\r\n console.log(\r\n \"[AudioWaveform] No activity or not playing, showing static waveform\"\r\n );\r\n }\r\n drawStaticWaveform();\r\n return;\r\n }\r\n\r\n // Clear canvas with dark background for trail effect\r\n ctx.fillStyle = \"rgba(0, 0, 0, 0.1)\";\r\n ctx.fillRect(0, 0, canvas.width, canvas.height);\r\n\r\n // Create gradient from cyan/blue to purple/pink\r\n const gradient = ctx.createLinearGradient(0, 0, canvas.width, 0);\r\n gradient.addColorStop(0, \"#06b6d4\"); // cyan\r\n gradient.addColorStop(0.3, \"#3b82f6\"); // blue\r\n gradient.addColorStop(0.6, \"#8b5cf6\"); // purple\r\n gradient.addColorStop(1, \"#ec4899\"); // pink\r\n\r\n // Draw frequency bars\r\n const barCount = 128;\r\n const barWidth = canvas.width / barCount;\r\n const gap = 2;\r\n\r\n for (let i = 0; i < barCount; i++) {\r\n const barHeight = (dataArray[i] / 255) * canvas.height * 0.8;\r\n const x = i * barWidth;\r\n const y = canvas.height / 2 - barHeight / 2;\r\n\r\n // Add glow effect\r\n ctx.shadowBlur = 20;\r\n ctx.shadowColor = \"#3b82f6\";\r\n\r\n // Draw bar\r\n ctx.fillStyle = gradient;\r\n ctx.fillRect(x + gap / 2, y, barWidth - gap, barHeight);\r\n }\r\n\r\n // Reset shadow for next frame\r\n ctx.shadowBlur = 0;\r\n };\r\n\r\n draw();\r\n } catch (error) {\r\n console.error(\"Error setting up audio visualization:\", error);\r\n setSetupError(true);\r\n\r\n // Draw a static flat line if visualization fails\r\n if (ctx) {\r\n ctx.fillStyle = \"#000\";\r\n ctx.fillRect(0, 0, canvas.width, canvas.height);\r\n ctx.strokeStyle = \"#3b82f6\";\r\n ctx.lineWidth = 2;\r\n ctx.beginPath();\r\n ctx.moveTo(0, canvas.height / 2);\r\n ctx.lineTo(canvas.width, canvas.height / 2);\r\n ctx.stroke();\r\n }\r\n }\r\n\r\n return () => {\r\n // Cleanup animation frame\r\n if (animationFrameRef.current) {\r\n cancelAnimationFrame(animationFrameRef.current);\r\n }\r\n // Close audio context\r\n if (audioContext) {\r\n audioContext.close();\r\n }\r\n };\r\n }, [audioElement, mediaStream, isLive]);\r\n\r\n return (\r\n <div className=\"w-full h-full\">\r\n <canvas\r\n ref={canvasRef}\r\n width={1600}\r\n height={400}\r\n className=\"w-full h-full\"\r\n style={{ display: \"block\" }}\r\n />\r\n {setupError && (\r\n <p className=\"text-gray-400 text-xs text-center mt-2 absolute bottom-4\">\r\n Audio visualization unavailable\r\n </p>\r\n )}\r\n </div>\r\n );\r\n}\r\n","import type { RefObject } from 'react';\r\nimport { AudioWaveform } from \"./AudioWaveform\";\r\n\r\nexport interface StreamingPreviewProps {\r\n videoRef: RefObject<HTMLVideoElement>;\r\n isVideoKey: boolean;\r\n isVideoEnabled: boolean;\r\n mediaStream: MediaStream | null;\r\n facingMode: \"user\" | \"environment\";\r\n}\r\n\r\nexport function StreamingPreview({\r\n videoRef,\r\n isVideoKey,\r\n isVideoEnabled,\r\n mediaStream,\r\n facingMode,\r\n}: StreamingPreviewProps) {\r\n\r\n return (\r\n <div className=\"dialtribe-streaming-preview flex-1 relative bg-black overflow-hidden\">\r\n {/* Video Preview (for video streams) */}\r\n {isVideoKey && isVideoEnabled && (\r\n <video\r\n ref={videoRef}\r\n autoPlay\r\n muted\r\n playsInline\r\n className={`w-full h-full object-cover ${\r\n facingMode === \"user\" ? \"scale-x-[-1]\" : \"\"\r\n }`}\r\n style={{ maxHeight: \"100vh\" }}\r\n />\r\n )}\r\n\r\n {/* Audio Waveform (for audio-only streams) */}\r\n {!isVideoKey && (\r\n <div className=\"w-full h-full flex items-center justify-center p-8\">\r\n <div className=\"w-full max-w-4xl\">\r\n <div className=\"w-full h-auto border border-gray-800 rounded-lg overflow-hidden\">\r\n <AudioWaveform mediaStream={mediaStream} isPlaying={true} />\r\n </div>\r\n <div className=\"text-center mt-4\">\r\n <div className=\"w-16 h-16 bg-blue-600 rounded-full flex items-center justify-center mx-auto mb-3\">\r\n <svg\r\n className=\"w-8 h-8 text-white\"\r\n fill=\"none\"\r\n stroke=\"currentColor\"\r\n viewBox=\"0 0 24 24\"\r\n >\r\n <path\r\n strokeLinecap=\"round\"\r\n strokeLinejoin=\"round\"\r\n strokeWidth={2}\r\n d=\"M19 11a7 7 0 01-7 7m0 0a7 7 0 01-7-7m7 7v4m0 0H8m4 0h4m-4-8a3 3 0 01-3-3V5a3 3 0 116 0v6a3 3 0 01-3 3z\"\r\n />\r\n </svg>\r\n </div>\r\n <p className=\"text-white text-xl font-medium\">Audio-Only Stream</p>\r\n <p className=\"text-gray-400 text-sm mt-1\">Your audio is being captured</p>\r\n </div>\r\n </div>\r\n </div>\r\n )}\r\n\r\n {/* Video Disabled Overlay - shows audio waveform when camera is off */}\r\n {isVideoKey && !isVideoEnabled && (\r\n <div className=\"w-full h-full flex items-center justify-center p-8 bg-gray-900\">\r\n <div className=\"w-full max-w-4xl\">\r\n {/* Audio Waveform */}\r\n <div className=\"w-full h-auto border border-gray-800 rounded-lg overflow-hidden mb-6\">\r\n <AudioWaveform mediaStream={mediaStream} isPlaying={true} />\r\n </div>\r\n {/* Camera off indicator */}\r\n <div className=\"text-center\">\r\n <div className=\"w-16 h-16 bg-gray-800 rounded-full flex items-center justify-center mx-auto mb-3\">\r\n <svg\r\n className=\"w-8 h-8 text-gray-400\"\r\n fill=\"none\"\r\n stroke=\"currentColor\"\r\n viewBox=\"0 0 24 24\"\r\n aria-hidden=\"true\"\r\n >\r\n <path\r\n strokeLinecap=\"round\"\r\n strokeLinejoin=\"round\"\r\n strokeWidth={2}\r\n d=\"M15 10l4.553-2.276A1 1 0 0121 8.618v6.764a1 1 0 01-1.447.894L15 14M5 18h8a2 2 0 002-2V8a2 2 0 00-2-2H5a2 2 0 00-2 2v8a2 2 0 002 2z M3 3l18 18\"\r\n />\r\n </svg>\r\n </div>\r\n <p className=\"text-white text-xl font-medium\">Camera Off</p>\r\n <p className=\"text-gray-400 text-sm mt-1\">Your audio is still being broadcast</p>\r\n </div>\r\n </div>\r\n </div>\r\n )}\r\n </div>\r\n );\r\n}\r\n","import { useState } from 'react';\r\n\r\nexport interface StreamKeyDisplayProps {\r\n streamKey: string;\r\n className?: string;\r\n showLabel?: boolean;\r\n showCopy?: boolean;\r\n editable?: boolean;\r\n onChange?: (newKey: string) => void;\r\n size?: 'sm' | 'md' | 'lg';\r\n layout?: 'vertical' | 'horizontal';\r\n darkMode?: boolean;\r\n}\r\n\r\n/**\r\n * Shared component for displaying stream keys with reveal/copy functionality\r\n * Obscures the stream key by default, showing only first 6 and last 6 characters\r\n * When revealed and editable, becomes an input field for editing\r\n */\r\nexport function StreamKeyDisplay({\r\n streamKey,\r\n className = '',\r\n showLabel = true,\r\n showCopy = true,\r\n editable = false,\r\n onChange,\r\n size = 'md',\r\n layout = 'vertical',\r\n darkMode = false,\r\n}: StreamKeyDisplayProps) {\r\n const [isRevealed, setIsRevealed] = useState(false);\r\n const [copySuccess, setCopySuccess] = useState(false);\r\n\r\n const obscureStreamKey = (key: string): string => {\r\n if (key.length <= 12) {\r\n return '•'.repeat(key.length);\r\n }\r\n return `${key.substring(0, 6)}${'•'.repeat(key.length - 12)}${key.substring(key.length - 6)}`;\r\n };\r\n\r\n const handleCopy = async () => {\r\n try {\r\n await navigator.clipboard.writeText(streamKey);\r\n setCopySuccess(true);\r\n setTimeout(() => setCopySuccess(false), 2000);\r\n } catch (err) {\r\n console.error('Failed to copy stream key:', err);\r\n }\r\n };\r\n\r\n const handleReveal = () => {\r\n setIsRevealed(!isRevealed);\r\n };\r\n\r\n // Size-based styling\r\n const sizeClasses = {\r\n sm: {\r\n label: 'text-xs',\r\n code: 'text-xs px-2 py-1',\r\n button: 'text-xs px-2 py-1',\r\n },\r\n md: {\r\n label: 'text-sm',\r\n code: 'text-sm px-2 py-1',\r\n button: 'text-sm px-3 py-1.5',\r\n },\r\n lg: {\r\n label: 'text-base',\r\n code: 'text-base px-3 py-2',\r\n button: 'text-base px-4 py-2',\r\n },\r\n };\r\n\r\n const styles = sizeClasses[size];\r\n\r\n // Layout classes\r\n const isHorizontal = layout === 'horizontal';\r\n const containerClass = isHorizontal\r\n ? 'flex items-center gap-3'\r\n : 'flex flex-col gap-2';\r\n\r\n // Dark mode styling for non-editable display\r\n // Use truncate instead of break-all to prevent wrapping\r\n const codeClass = darkMode && !isRevealed\r\n ? `${styles.code} font-mono text-white bg-transparent rounded truncate`\r\n : `${styles.code} font-mono text-black dark:text-white bg-gray-100 dark:bg-zinc-800 rounded truncate flex-1 min-w-0`;\r\n\r\n const labelClass = darkMode\r\n ? `${styles.label} text-white/80 font-medium whitespace-nowrap`\r\n : `${styles.label} text-gray-600 dark:text-gray-400 font-medium`;\r\n\r\n const revealButtonClass = darkMode\r\n ? `${styles.button} text-blue-400 hover:text-blue-300 hover:bg-white/10 rounded transition-colors whitespace-nowrap`\r\n : `${styles.button} text-blue-600 hover:text-blue-700 dark:text-blue-400 dark:hover:text-blue-300 hover:bg-blue-50 dark:hover:bg-blue-900/20 rounded transition-colors whitespace-nowrap`;\r\n\r\n return (\r\n <div className={`dialtribe-stream-key-display ${containerClass} ${className}`}>\r\n {showLabel && (\r\n <span className={labelClass}>\r\n Stream Key:\r\n </span>\r\n )}\r\n <div className=\"flex items-center gap-2 min-w-0 overflow-hidden\">\r\n {isRevealed && editable ? (\r\n <input\r\n type=\"text\"\r\n value={streamKey}\r\n onChange={(e) => onChange?.(e.target.value)}\r\n className={`${styles.code} font-mono text-black dark:text-white bg-white dark:bg-zinc-900 border border-gray-300 dark:border-zinc-700 rounded focus:outline-none focus:ring-2 focus:ring-blue-500 flex-1 min-w-0`}\r\n placeholder=\"Enter stream key\"\r\n />\r\n ) : (\r\n <code className={codeClass}>\r\n {isRevealed ? streamKey : obscureStreamKey(streamKey)}\r\n </code>\r\n )}\r\n <button\r\n onClick={handleReveal}\r\n className={`${revealButtonClass} shrink-0`}\r\n >\r\n {isRevealed ? 'Hide' : 'Reveal'}\r\n </button>\r\n {showCopy && (\r\n <button\r\n onClick={handleCopy}\r\n className={`${styles.button} text-gray-600 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-300 hover:bg-gray-100 dark:hover:bg-zinc-800 rounded transition-colors whitespace-nowrap shrink-0`}\r\n title=\"Copy to clipboard\"\r\n >\r\n {copySuccess ? 'Copied!' : 'Copy'}\r\n </button>\r\n )}\r\n </div>\r\n </div>\r\n );\r\n}\r\n","import { useEffect, useState } from \"react\";\r\nimport { StreamKeyDisplay } from \"./StreamKeyDisplay\";\r\nimport { AudioWaveform } from \"./AudioWaveform\";\r\n\r\nexport type StreamingControlState = \"previewing\" | \"connecting\" | \"live\" | \"stopping\";\r\n\r\nexport interface MediaDeviceInfo {\r\n deviceId: string;\r\n label: string;\r\n}\r\n\r\nexport interface StreamingControlsProps {\r\n state: StreamingControlState;\r\n isVideoKey: boolean;\r\n isMuted: boolean;\r\n isVideoEnabled: boolean;\r\n facingMode: \"user\" | \"environment\";\r\n hasMultipleCameras: boolean;\r\n startTime: Date | null;\r\n bytesSent: number;\r\n showStopConfirm: boolean;\r\n streamKey: string;\r\n onStreamKeyChange?: (newKey: string) => void;\r\n onStart: () => void;\r\n onStop: () => void;\r\n onConfirmStop: () => void;\r\n onCancelStop: () => void;\r\n onToggleMute: () => void;\r\n onToggleVideo: () => void;\r\n onFlipCamera: () => void;\r\n onClose?: () => void;\r\n showCloseConfirm?: boolean;\r\n onConfirmClose?: () => void;\r\n onCancelClose?: () => void;\r\n // Device selection props\r\n videoDevices?: MediaDeviceInfo[];\r\n audioDevices?: MediaDeviceInfo[];\r\n selectedVideoDeviceId?: string;\r\n selectedAudioDeviceId?: string;\r\n onVideoDeviceChange?: (deviceId: string) => void;\r\n onAudioDeviceChange?: (deviceId: string) => void;\r\n // Media stream for audio preview\r\n mediaStream?: MediaStream | null;\r\n}\r\n\r\nexport function StreamingControls({\r\n state,\r\n isVideoKey,\r\n isMuted,\r\n isVideoEnabled,\r\n facingMode: _facingMode, // Reserved for future use (e.g., showing camera direction)\r\n hasMultipleCameras,\r\n startTime,\r\n bytesSent,\r\n showStopConfirm,\r\n streamKey,\r\n onStreamKeyChange,\r\n onStart,\r\n onStop,\r\n onConfirmStop,\r\n onCancelStop,\r\n onToggleMute,\r\n onToggleVideo,\r\n onFlipCamera,\r\n onClose,\r\n showCloseConfirm,\r\n onConfirmClose,\r\n onCancelClose,\r\n // Device selection props\r\n videoDevices = [],\r\n audioDevices = [],\r\n selectedVideoDeviceId,\r\n selectedAudioDeviceId,\r\n onVideoDeviceChange,\r\n onAudioDeviceChange,\r\n mediaStream,\r\n}: StreamingControlsProps) {\r\n const [duration, setDuration] = useState(0);\r\n const [showSettings, setShowSettings] = useState(false);\r\n\r\n // Update duration every second when live\r\n useEffect(() => {\r\n if (state !== \"live\" || !startTime) return;\r\n\r\n const interval = setInterval(() => {\r\n const elapsed = Math.floor((Date.now() - startTime.getTime()) / 1000);\r\n setDuration(elapsed);\r\n }, 1000);\r\n\r\n return () => clearInterval(interval);\r\n }, [state, startTime]);\r\n\r\n const formatDuration = (seconds: number): string => {\r\n const hours = Math.floor(seconds / 3600);\r\n const minutes = Math.floor((seconds % 3600) / 60);\r\n const secs = seconds % 60;\r\n\r\n if (hours > 0) {\r\n return `${hours}:${minutes.toString().padStart(2, \"0\")}:${secs.toString().padStart(2, \"0\")}`;\r\n }\r\n return `${minutes}:${secs.toString().padStart(2, \"0\")}`;\r\n };\r\n\r\n const formatBytes = (bytes: number): string => {\r\n if (bytes === 0) return \"0 B\";\r\n const k = 1024;\r\n const sizes = [\"B\", \"KB\", \"MB\", \"GB\"];\r\n const i = Math.floor(Math.log(bytes) / Math.log(k));\r\n return `${(bytes / Math.pow(k, i)).toFixed(2)} ${sizes[i]}`;\r\n };\r\n\r\n return (\r\n <>\r\n {/* Top Overlay - Close button (Preview) or Timer/Status (Live) */}\r\n {state === \"previewing\" && onClose && (\r\n <div className=\"absolute top-0 left-0 right-0 p-4 bg-gradient-to-b from-black/60 to-transparent z-10 flex items-start justify-end\">\r\n {/* Close button */}\r\n <button\r\n onClick={onClose}\r\n className=\"w-10 h-10 shrink-0 bg-black/50 hover:bg-black/70 backdrop-blur rounded-full flex items-center justify-center transition-colors\"\r\n title=\"Close broadcast preview\"\r\n aria-label=\"Close broadcast preview\"\r\n >\r\n <svg className=\"w-5 h-5 text-white\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\" aria-hidden=\"true\">\r\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M6 18L18 6M6 6l12 12\" />\r\n </svg>\r\n </button>\r\n </div>\r\n )}\r\n {state === \"live\" && (\r\n <div className=\"absolute top-0 left-0 right-0 p-4 bg-gradient-to-b from-black/60 to-transparent z-10\">\r\n <div className=\"flex items-center justify-between\">\r\n <div className=\"flex items-center gap-2\">\r\n <div className=\"w-3 h-3 bg-red-600 rounded-full animate-pulse\" />\r\n <span className=\"text-white font-semibold text-lg\">LIVE</span>\r\n </div>\r\n <div className=\"flex items-center gap-4\">\r\n <div className=\"text-right\">\r\n <div className=\"text-white font-mono text-lg font-semibold\">\r\n {formatDuration(duration)}\r\n </div>\r\n <div className=\"text-white/80 text-sm\">\r\n {formatBytes(bytesSent)} sent\r\n </div>\r\n </div>\r\n {/* Close button */}\r\n {onClose && (\r\n <button\r\n onClick={onClose}\r\n className=\"w-10 h-10 bg-black/50 hover:bg-black/70 backdrop-blur rounded-full flex items-center justify-center transition-colors\"\r\n title=\"Close and end broadcast\"\r\n aria-label=\"Close and end broadcast\"\r\n >\r\n <svg className=\"w-5 h-5 text-white\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\" aria-hidden=\"true\">\r\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M6 18L18 6M6 6l12 12\" />\r\n </svg>\r\n </button>\r\n )}\r\n </div>\r\n </div>\r\n </div>\r\n )}\r\n\r\n {/* Bottom Overlay - Controls */}\r\n <div className=\"absolute bottom-0 left-0 right-0 p-6 bg-gradient-to-t from-black/80 to-transparent z-10\">\r\n {/* Start Button with Settings (Preview State) */}\r\n {state === \"previewing\" && (\r\n <div className=\"relative flex justify-center items-center\">\r\n {/* Flip Camera Button - positioned in bottom left (video streams with multiple cameras) */}\r\n {isVideoKey && hasMultipleCameras && (\r\n <button\r\n onClick={onFlipCamera}\r\n className=\"absolute left-0 w-10 h-10 bg-black/50 hover:bg-black/70 backdrop-blur rounded-full flex items-center justify-center transition-colors\"\r\n title=\"Switch camera\"\r\n aria-label=\"Switch between front and back camera\"\r\n >\r\n <svg className=\"w-5 h-5 text-white\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\" aria-hidden=\"true\">\r\n <path\r\n strokeLinecap=\"round\"\r\n strokeLinejoin=\"round\"\r\n strokeWidth={2}\r\n d=\"M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15\"\r\n />\r\n </svg>\r\n </button>\r\n )}\r\n <button\r\n onClick={onStart}\r\n className=\"px-12 py-4 bg-blue-600 hover:bg-blue-700 text-white text-xl font-bold rounded-full transition-all transform hover:scale-105 active:scale-95 shadow-lg\"\r\n aria-label=\"Start live streaming\"\r\n >\r\n Start Streaming\r\n </button>\r\n {/* Settings Gear Button - positioned in bottom right */}\r\n <button\r\n onClick={() => setShowSettings(true)}\r\n className=\"absolute right-0 w-10 h-10 bg-black/50 hover:bg-black/70 backdrop-blur rounded-full flex items-center justify-center transition-colors\"\r\n title=\"Stream settings\"\r\n aria-label=\"Open stream settings\"\r\n >\r\n <svg className=\"w-5 h-5 text-white\" fill=\"currentColor\" viewBox=\"0 0 20 20\" aria-hidden=\"true\">\r\n <path fillRule=\"evenodd\" d=\"M11.49 3.17c-.38-1.56-2.6-1.56-2.98 0a1.532 1.532 0 01-2.286.948c-1.372-.836-2.942.734-2.106 2.106.54.886.061 2.042-.947 2.287-1.561.379-1.561 2.6 0 2.978a1.532 1.532 0 01.947 2.287c-.836 1.372.734 2.942 2.106 2.106a1.532 1.532 0 012.287.947c.379 1.561 2.6 1.561 2.978 0a1.533 1.533 0 012.287-.947c1.372.836 2.942-.734 2.106-2.106a1.533 1.533 0 01.947-2.287c1.561-.379 1.561-2.6 0-2.978a1.532 1.532 0 01-.947-2.287c.836-1.372-.734-2.942-2.106-2.106a1.532 1.532 0 01-2.287-.947zM10 13a3 3 0 100-6 3 3 0 000 6z\" clipRule=\"evenodd\" />\r\n </svg>\r\n </button>\r\n </div>\r\n )}\r\n\r\n {/* Connecting State */}\r\n {state === \"connecting\" && (\r\n <div className=\"flex justify-center\">\r\n <div className=\"px-12 py-4 bg-blue-600 text-white text-xl font-bold rounded-full flex items-center gap-3\">\r\n <div className=\"w-5 h-5 border-2 border-white border-t-transparent rounded-full animate-spin\" />\r\n Connecting...\r\n </div>\r\n </div>\r\n )}\r\n\r\n {/* Live Controls */}\r\n {state === \"live\" && !showStopConfirm && !showCloseConfirm && (\r\n <div className=\"space-y-4\">\r\n {/* Main Controls Row */}\r\n <div className=\"flex items-center justify-center gap-4\">\r\n {/* Mute Button */}\r\n <button\r\n onClick={onToggleMute}\r\n className={`w-14 h-14 rounded-full flex items-center justify-center transition-all shadow-lg ${\r\n isMuted\r\n ? \"bg-red-600 hover:bg-red-700\"\r\n : \"bg-white/20 hover:bg-white/30 backdrop-blur\"\r\n }`}\r\n title={isMuted ? \"Unmute microphone\" : \"Mute microphone\"}\r\n aria-label={isMuted ? \"Unmute microphone\" : \"Mute microphone\"}\r\n aria-pressed={isMuted}\r\n >\r\n {isMuted ? (\r\n <svg className=\"w-6 h-6 text-white\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\" aria-hidden=\"true\">\r\n <path\r\n strokeLinecap=\"round\"\r\n strokeLinejoin=\"round\"\r\n strokeWidth={2}\r\n d=\"M5.586 15H4a1 1 0 01-1-1v-4a1 1 0 011-1h1.586l4.707-4.707C10.923 3.663 12 4.109 12 5v14c0 .891-1.077 1.337-1.707.707L5.586 15z M17 14l2-2m0 0l2-2m-2 2l-2-2m2 2l2 2\"\r\n />\r\n </svg>\r\n ) : (\r\n <svg className=\"w-6 h-6 text-white\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\" aria-hidden=\"true\">\r\n <path\r\n strokeLinecap=\"round\"\r\n strokeLinejoin=\"round\"\r\n strokeWidth={2}\r\n d=\"M15.536 8.464a5 5 0 010 7.072m2.828-9.9a9 9 0 010 12.728M5.586 15H4a1 1 0 01-1-1v-4a1 1 0 011-1h1.586l4.707-4.707C10.923 3.663 12 4.109 12 5v14c0 .891-1.077 1.337-1.707.707L5.586 15z\"\r\n />\r\n </svg>\r\n )}\r\n </button>\r\n\r\n {/* Stop Button */}\r\n <button\r\n onClick={onStop}\r\n className=\"w-16 h-16 bg-red-600 hover:bg-red-700 rounded-full flex items-center justify-center transition-all shadow-lg\"\r\n title=\"Stop streaming\"\r\n aria-label=\"Stop streaming\"\r\n >\r\n <div className=\"w-6 h-6 bg-white rounded-sm\" aria-hidden=\"true\" />\r\n </button>\r\n\r\n {/* Video Toggle (Video Streams Only) */}\r\n {isVideoKey && (\r\n <button\r\n onClick={onToggleVideo}\r\n className={`w-14 h-14 rounded-full flex items-center justify-center transition-all shadow-lg ${\r\n !isVideoEnabled\r\n ? \"bg-red-600 hover:bg-red-700\"\r\n : \"bg-white/20 hover:bg-white/30 backdrop-blur\"\r\n }`}\r\n title={isVideoEnabled ? \"Turn camera off\" : \"Turn camera on\"}\r\n aria-label={isVideoEnabled ? \"Turn camera off\" : \"Turn camera on\"}\r\n aria-pressed={!isVideoEnabled}\r\n >\r\n {isVideoEnabled ? (\r\n <svg className=\"w-6 h-6 text-white\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\" aria-hidden=\"true\">\r\n <path\r\n strokeLinecap=\"round\"\r\n strokeLinejoin=\"round\"\r\n strokeWidth={2}\r\n d=\"M15 10l4.553-2.276A1 1 0 0121 8.618v6.764a1 1 0 01-1.447.894L15 14M5 18h8a2 2 0 002-2V8a2 2 0 00-2-2H5a2 2 0 00-2 2v8a2 2 0 002 2z\"\r\n />\r\n </svg>\r\n ) : (\r\n <svg className=\"w-6 h-6 text-white\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\" aria-hidden=\"true\">\r\n <path\r\n strokeLinecap=\"round\"\r\n strokeLinejoin=\"round\"\r\n strokeWidth={2}\r\n d=\"M15 10l4.553-2.276A1 1 0 0121 8.618v6.764a1 1 0 01-1.447.894L15 14M5 18h8a2 2 0 002-2V8a2 2 0 00-2-2H5a2 2 0 00-2 2v8a2 2 0 002 2z M3 3l18 18\"\r\n />\r\n </svg>\r\n )}\r\n </button>\r\n )}\r\n\r\n {/* Flip Camera (Video Streams Only, when multiple cameras detected) */}\r\n {isVideoKey && hasMultipleCameras && (\r\n <button\r\n onClick={onFlipCamera}\r\n className=\"w-14 h-14 bg-white/20 hover:bg-white/30 backdrop-blur rounded-full flex items-center justify-center transition-all shadow-lg\"\r\n title=\"Switch camera\"\r\n aria-label=\"Switch between front and back camera\"\r\n >\r\n <svg className=\"w-6 h-6 text-white\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\" aria-hidden=\"true\">\r\n <path\r\n strokeLinecap=\"round\"\r\n strokeLinejoin=\"round\"\r\n strokeWidth={2}\r\n d=\"M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15\"\r\n />\r\n </svg>\r\n </button>\r\n )}\r\n\r\n {/* Clip Button (Placeholder for future) */}\r\n <button\r\n disabled\r\n className=\"w-14 h-14 bg-white/10 rounded-full flex items-center justify-center opacity-50 cursor-not-allowed shadow-lg\"\r\n title=\"Create clip (Coming soon)\"\r\n aria-label=\"Create clip (Coming soon)\"\r\n aria-disabled=\"true\"\r\n >\r\n <svg className=\"w-6 h-6 text-white\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\" aria-hidden=\"true\">\r\n <path\r\n strokeLinecap=\"round\"\r\n strokeLinejoin=\"round\"\r\n strokeWidth={2}\r\n d=\"M14.752 11.168l-3.197-2.132A1 1 0 0010 9.87v4.263a1 1 0 001.555.832l3.197-2.132a1 1 0 000-1.664z M21 12a9 9 0 11-18 0 9 9 0 0118 0z\"\r\n />\r\n </svg>\r\n </button>\r\n </div>\r\n </div>\r\n )}\r\n\r\n </div>\r\n\r\n {/* Stop Confirmation Modal Overlay */}\r\n {showStopConfirm && (\r\n <div className=\"absolute inset-0 z-20 flex items-center justify-center p-4 bg-black/70\">\r\n <div className=\"bg-black/95 rounded-2xl p-6 backdrop-blur border border-white/20 max-w-sm w-full\" role=\"dialog\" aria-labelledby=\"stop-dialog-title\">\r\n <p id=\"stop-dialog-title\" className=\"text-white text-center text-lg font-medium mb-4\">\r\n Stop streaming?\r\n </p>\r\n <div className=\"flex gap-3\">\r\n <button\r\n onClick={onCancelStop}\r\n className=\"flex-1 px-6 py-3 bg-white/20 hover:bg-white/30 text-white font-medium rounded-lg transition-colors\"\r\n aria-label=\"Cancel and continue streaming\"\r\n >\r\n Cancel\r\n </button>\r\n <button\r\n onClick={onConfirmStop}\r\n className=\"flex-1 px-6 py-3 bg-red-600 hover:bg-red-700 text-white font-medium rounded-lg transition-colors\"\r\n aria-label=\"Confirm stop streaming\"\r\n >\r\n Stop\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n )}\r\n\r\n {/* Close Confirmation Modal Overlay */}\r\n {showCloseConfirm && (\r\n <div className=\"absolute inset-0 z-20 flex items-center justify-center p-4 bg-black/70\">\r\n <div className=\"bg-black/95 rounded-2xl p-6 backdrop-blur border border-white/20 max-w-sm w-full\" role=\"dialog\" aria-labelledby=\"close-dialog-title\" aria-describedby=\"close-dialog-description\">\r\n <p id=\"close-dialog-title\" className=\"text-white text-center text-lg font-medium mb-2\">\r\n Close and end stream?\r\n </p>\r\n <p id=\"close-dialog-description\" className=\"text-white/70 text-center text-sm mb-4\">\r\n Closing will stop your live broadcast.\r\n </p>\r\n <div className=\"flex gap-3\">\r\n <button\r\n onClick={onCancelClose}\r\n className=\"flex-1 px-6 py-3 bg-white/20 hover:bg-white/30 text-white font-medium rounded-lg transition-colors\"\r\n aria-label=\"Cancel and continue streaming\"\r\n >\r\n Cancel\r\n </button>\r\n <button\r\n onClick={onConfirmClose}\r\n className=\"flex-1 px-6 py-3 bg-red-600 hover:bg-red-700 text-white font-medium rounded-lg transition-colors\"\r\n aria-label=\"Confirm end broadcast and close\"\r\n >\r\n End & Close\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n )}\r\n\r\n {/* Settings Panel Overlay */}\r\n {showSettings && (\r\n <div className=\"absolute inset-0 z-20 flex items-center justify-center p-4 bg-black/80\">\r\n <div\r\n className=\"bg-black/95 rounded-2xl backdrop-blur border border-white/20 max-w-md w-full max-h-[90%] overflow-hidden flex flex-col\"\r\n role=\"dialog\"\r\n aria-labelledby=\"settings-dialog-title\"\r\n >\r\n {/* Header */}\r\n <div className=\"flex items-center justify-between p-4 border-b border-white/10\">\r\n <h2 id=\"settings-dialog-title\" className=\"text-white text-lg font-semibold\">\r\n Stream Settings\r\n </h2>\r\n <button\r\n onClick={() => setShowSettings(false)}\r\n className=\"w-8 h-8 bg-white/10 hover:bg-white/20 rounded-full flex items-center justify-center transition-colors\"\r\n title=\"Close settings\"\r\n aria-label=\"Close settings\"\r\n >\r\n <svg className=\"w-4 h-4 text-white\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\" aria-hidden=\"true\">\r\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M6 18L18 6M6 6l12 12\" />\r\n </svg>\r\n </button>\r\n </div>\r\n\r\n {/* Scrollable Content */}\r\n <div className=\"flex-1 overflow-y-auto p-4 space-y-6\">\r\n {/* Stream Key Section */}\r\n <div>\r\n <label className=\"block text-sm font-medium text-white/80 mb-2\">\r\n Stream Key\r\n </label>\r\n <div className=\"bg-white/5 border border-white/10 rounded-lg p-3\">\r\n <StreamKeyDisplay\r\n streamKey={streamKey}\r\n editable={!!onStreamKeyChange}\r\n onChange={onStreamKeyChange}\r\n showCopy={true}\r\n size=\"sm\"\r\n layout=\"vertical\"\r\n darkMode={true}\r\n />\r\n </div>\r\n </div>\r\n\r\n {/* Video Source Section */}\r\n {isVideoKey && videoDevices.length > 0 && (\r\n <div>\r\n <label className=\"block text-sm font-medium text-white/80 mb-2\">\r\n Camera\r\n </label>\r\n <select\r\n value={selectedVideoDeviceId || \"\"}\r\n onChange={(e) => onVideoDeviceChange?.(e.target.value)}\r\n className=\"w-full px-3 py-2 bg-white/5 border border-white/10 rounded-lg text-white text-sm focus:outline-none focus:ring-2 focus:ring-blue-500\"\r\n aria-label=\"Select camera\"\r\n >\r\n {videoDevices.map((device) => (\r\n <option key={device.deviceId} value={device.deviceId} className=\"bg-zinc-900\">\r\n {device.label || `Camera ${device.deviceId.slice(0, 8)}`}\r\n </option>\r\n ))}\r\n </select>\r\n {/* Video Preview */}\r\n <div className=\"mt-3 aspect-video bg-black rounded-lg overflow-hidden border border-white/10\">\r\n {mediaStream && isVideoEnabled ? (\r\n <video\r\n autoPlay\r\n muted\r\n playsInline\r\n className=\"w-full h-full object-cover scale-x-[-1]\"\r\n ref={(el) => {\r\n if (el && mediaStream) {\r\n el.srcObject = mediaStream;\r\n }\r\n }}\r\n />\r\n ) : (\r\n <div className=\"w-full h-full flex items-center justify-center\">\r\n <div className=\"text-center\">\r\n <svg className=\"w-8 h-8 text-gray-500 mx-auto mb-2\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\" aria-hidden=\"true\">\r\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M15 10l4.553-2.276A1 1 0 0121 8.618v6.764a1 1 0 01-1.447.894L15 14M5 18h8a2 2 0 002-2V8a2 2 0 00-2-2H5a2 2 0 00-2 2v8a2 2 0 002 2z M3 3l18 18\" />\r\n </svg>\r\n <p className=\"text-gray-500 text-xs\">Camera off</p>\r\n </div>\r\n </div>\r\n )}\r\n </div>\r\n </div>\r\n )}\r\n\r\n {/* Audio Source Section */}\r\n {audioDevices.length > 0 && (\r\n <div>\r\n <label className=\"block text-sm font-medium text-white/80 mb-2\">\r\n Microphone\r\n </label>\r\n <select\r\n value={selectedAudioDeviceId || \"\"}\r\n onChange={(e) => onAudioDeviceChange?.(e.target.value)}\r\n className=\"w-full px-3 py-2 bg-white/5 border border-white/10 rounded-lg text-white text-sm focus:outline-none focus:ring-2 focus:ring-blue-500\"\r\n aria-label=\"Select microphone\"\r\n >\r\n {audioDevices.map((device) => (\r\n <option key={device.deviceId} value={device.deviceId} className=\"bg-zinc-900\">\r\n {device.label || `Microphone ${device.deviceId.slice(0, 8)}`}\r\n </option>\r\n ))}\r\n </select>\r\n {/* Audio Waveform Preview */}\r\n <div className=\"mt-3 h-16 bg-black rounded-lg overflow-hidden border border-white/10\">\r\n {mediaStream && !isMuted ? (\r\n <AudioWaveform mediaStream={mediaStream} isPlaying={true} />\r\n ) : (\r\n <div className=\"w-full h-full flex items-center justify-center\">\r\n <p className=\"text-gray-500 text-xs\">\r\n {isMuted ? \"Microphone muted\" : \"No audio\"}\r\n </p>\r\n </div>\r\n )}\r\n </div>\r\n </div>\r\n )}\r\n </div>\r\n\r\n {/* Footer */}\r\n <div className=\"p-4 border-t border-white/10\">\r\n <button\r\n onClick={() => setShowSettings(false)}\r\n className=\"w-full px-6 py-3 bg-blue-600 hover:bg-blue-700 text-white font-medium rounded-lg transition-colors\"\r\n aria-label=\"Save and close settings\"\r\n >\r\n Done\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n )}\r\n </>\r\n );\r\n}\r\n","import { useState } from \"react\";\r\n\r\nexport interface StreamKeyInputProps {\r\n onSubmit: (key: string) => void;\r\n /**\r\n * When true, the input fills its parent container instead of the viewport.\r\n * Use this when embedding inline within a page.\r\n */\r\n inline?: boolean;\r\n}\r\n\r\n/**\r\n * Stream key input form for manual entry\r\n * Validates stream key format before submission\r\n */\r\nexport function StreamKeyInput({ onSubmit, inline = false }: StreamKeyInputProps) {\r\n const [streamKey, setStreamKey] = useState(\"\");\r\n const [error, setError] = useState(\"\");\r\n\r\n // Container class based on inline mode\r\n const containerClass = inline\r\n ? \"dialtribe-stream-key-input flex items-center justify-center h-full w-full p-4 overflow-auto\"\r\n : \"dialtribe-stream-key-input flex items-center justify-center min-h-screen p-4\";\r\n\r\n const validateStreamKey = (key: string): boolean => {\r\n // Stream key format: {mediaType}{foreignId}_{key}\r\n // Media types: a=audio_shared, b=audio_dedicated, v=video_shared, w=video_dedicated\r\n // Example: w1_3cb32a86191e918b07f9c4bda3e6b596 OR wdefault_1cfe70eb191e918b07f9c4bda3e6b596\r\n // ForeignId can be alphanumeric (digits or strings like \"default\")\r\n const pattern = /^[abvw][a-zA-Z0-9]+_.+$/;\r\n return pattern.test(key);\r\n };\r\n\r\n const handleSubmit = (e: React.FormEvent) => {\r\n e.preventDefault();\r\n setError(\"\");\r\n\r\n const trimmedKey = streamKey.trim();\r\n\r\n if (!trimmedKey) {\r\n setError(\"Please enter a stream key\");\r\n return;\r\n }\r\n\r\n if (!validateStreamKey(trimmedKey)) {\r\n setError(\r\n \"Invalid stream key format. Expected format: {mediaType}{foreignId}_{key} (e.g., w1_abc123...)\"\r\n );\r\n return;\r\n }\r\n\r\n onSubmit(trimmedKey);\r\n };\r\n\r\n return (\r\n <div className={containerClass}>\r\n <div className=\"bg-white dark:bg-zinc-900 rounded-lg border border-gray-200 dark:border-zinc-800 p-8 max-w-md w-full\">\r\n <div className=\"text-center mb-8\">\r\n <h1 className=\"text-3xl font-bold text-black dark:text-white mb-2\">\r\n Start Broadcasting\r\n </h1>\r\n <p className=\"text-gray-600 dark:text-gray-400\">\r\n Enter your stream key to get started\r\n </p>\r\n </div>\r\n\r\n <form onSubmit={handleSubmit} className=\"space-y-6\">\r\n <div>\r\n <label className=\"block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2\">\r\n Stream Key\r\n </label>\r\n <input\r\n type=\"text\"\r\n value={streamKey}\r\n onChange={(e) => {\r\n setStreamKey(e.target.value);\r\n setError(\"\");\r\n }}\r\n className=\"w-full px-4 py-3 bg-white dark:bg-zinc-800 border border-gray-300 dark:border-zinc-700 rounded-lg text-black dark:text-white font-mono text-sm placeholder:text-gray-400 dark:placeholder:text-gray-500 focus:ring-2 focus:ring-blue-500 focus:border-transparent\"\r\n placeholder=\"w1_abc123...\"\r\n autoFocus\r\n />\r\n {error && (\r\n <p className=\"mt-2 text-sm text-red-600 dark:text-red-400\">\r\n {error}\r\n </p>\r\n )}\r\n <p className=\"mt-2 text-xs text-gray-500 dark:text-gray-400\">\r\n Paste the stream key provided by your administrator\r\n </p>\r\n </div>\r\n\r\n <button\r\n type=\"submit\"\r\n className=\"w-full px-6 py-3 bg-blue-600 hover:bg-blue-700 text-white font-medium rounded-lg transition-colors\"\r\n >\r\n Continue\r\n </button>\r\n </form>\r\n\r\n <div className=\"mt-8 pt-6 border-t border-gray-200 dark:border-zinc-800\">\r\n <p className=\"text-sm text-gray-600 dark:text-gray-400 mb-2\">\r\n Where do I find my stream key?\r\n </p>\r\n <p className=\"text-xs text-gray-500 dark:text-gray-400\">\r\n If you have access to the DialTribe dashboard, navigate to your app's <strong>Stream Keys</strong> page and click the \"Broadcast\" button next to any active stream key.\r\n </p>\r\n </div>\r\n </div>\r\n </div>\r\n );\r\n}\r\n","import { useEffect, useRef, useState } from \"react\";\r\nimport {\r\n checkBrowserCompatibility,\r\n getMediaConstraints,\r\n} from \"../utils/media-constraints\";\r\nimport { WebSocketStreamer, DEFAULT_ENCODER_SERVER_URL, StreamDiagnostics } from \"../utils/websocket-streamer\";\r\nimport { StreamingPreview } from \"./StreamingPreview\";\r\nimport { StreamingControls, StreamingControlState } from \"./StreamingControls\";\r\nimport { StreamKeyInput } from \"./StreamKeyInput\";\r\nimport { DIALTRIBE_API_BASE } from \"../client/DialtribeClient\";\r\nimport { useDialtribeOptional } from \"../context/DialtribeProvider\";\r\n\r\ntype StreamingState = \"idle\" | \"requesting\" | \"previewing\" | \"connecting\" | \"live\" | \"stopping\" | \"stopped\" | \"terminated\" | \"error\";\r\n\r\n/**\r\n * Props for the DialtribeStreamer component.\r\n *\r\n * @example\r\n * ```tsx\r\n * // Inside DialtribeProvider (recommended)\r\n * <DialtribeProvider sessionToken={token}>\r\n * <DialtribeStreamer\r\n * streamKey={keyFromBackend}\r\n * onDone={() => window.close()}\r\n * />\r\n * </DialtribeProvider>\r\n *\r\n * // Standalone (e.g., popup window)\r\n * <DialtribeStreamer\r\n * sessionToken={token}\r\n * streamKey={keyFromBackend}\r\n * onDone={() => window.close()}\r\n * />\r\n * ```\r\n */\r\nexport interface DialtribeStreamerProps {\r\n /**\r\n * Session token for API authentication.\r\n *\r\n * Required for permission checks. Can be provided via:\r\n * 1. DialtribeProvider context (recommended for main app)\r\n * 2. This prop (required for popup windows)\r\n *\r\n * Must include `broadcasts:stream` permission.\r\n */\r\n sessionToken?: string;\r\n\r\n /**\r\n * Stream key for broadcasting.\r\n *\r\n * **Production apps should always provide this from their backend.**\r\n * The stream key authenticates the broadcaster with the encoder server.\r\n *\r\n * If omitted, a manual input form is shown. This is intended for\r\n * development/testing only - end users should never see or handle stream keys.\r\n *\r\n * @example \"w1_abc123def456...\"\r\n */\r\n streamKey?: string;\r\n\r\n /**\r\n * Called when streaming ends (user stops, terminates, or clicks Done).\r\n * Use this to close the popup or navigate away.\r\n *\r\n * @example () => window.close()\r\n */\r\n onDone?: () => void;\r\n\r\n /**\r\n * Called when the stream key changes (e.g., user edits it in preview mode).\r\n * Useful for persisting the key or updating parent state.\r\n */\r\n onStreamKeyChange?: (key: string) => void;\r\n\r\n /**\r\n * Custom encoder server URL. Defaults to Dialtribe's production encoder.\r\n * Only change this for self-hosted encoder deployments.\r\n *\r\n * @default \"https://broadcastapi.dialtribe.com\"\r\n */\r\n encoderServerUrl?: string;\r\n\r\n /**\r\n * Custom API base URL for broadcast availability checks.\r\n * Only change this for self-hosted API deployments.\r\n *\r\n * @default \"https://dialtribe.com/api/public/v1\"\r\n */\r\n apiBaseUrl?: string;\r\n\r\n /**\r\n * When true, the streamer fills its parent container instead of the viewport.\r\n * Use this when embedding the streamer inline within a page.\r\n *\r\n * @default false\r\n */\r\n inline?: boolean;\r\n}\r\n\r\nexport function DialtribeStreamer({\r\n sessionToken: propSessionToken,\r\n streamKey: initialStreamKey,\r\n onDone,\r\n onStreamKeyChange,\r\n encoderServerUrl = DEFAULT_ENCODER_SERVER_URL,\r\n apiBaseUrl = DIALTRIBE_API_BASE,\r\n inline = false,\r\n}: DialtribeStreamerProps) {\r\n // Container class based on inline mode\r\n // For inline mode, we need `relative` so absolute-positioned children (controls) stay within the container\r\n const containerClass = inline\r\n ? \"dialtribe-dialtribe-streamer h-full w-full bg-black relative\"\r\n : \"dialtribe-dialtribe-streamer min-h-screen bg-black\";\r\n const centeredContainerClass = inline\r\n ? \"dialtribe-dialtribe-streamer flex items-center justify-center h-full w-full p-4 bg-black relative\"\r\n : \"dialtribe-dialtribe-streamer flex items-center justify-center min-h-screen p-4 bg-black\";\r\n // Get session token from context or prop (prop takes precedence for popup windows)\r\n const dialTribeContext = useDialtribeOptional();\r\n const sessionToken = propSessionToken ?? dialTribeContext?.sessionToken ?? null;\r\n\r\n const [streamKey, setStreamKey] = useState<string | null>(initialStreamKey || null);\r\n const [state, setState] = useState<StreamingState>(\"idle\");\r\n\r\n // Sync internal streamKey state when prop changes (for popup postMessage scenario)\r\n useEffect(() => {\r\n if (initialStreamKey && initialStreamKey !== streamKey) {\r\n setStreamKey(initialStreamKey);\r\n }\r\n }, [initialStreamKey]);\r\n const [error, setError] = useState<string | null>(null);\r\n const [diagnostics, setDiagnostics] = useState<StreamDiagnostics | null>(null);\r\n const [mediaStream, setMediaStream] = useState<MediaStream | null>(null);\r\n const [streamer, setStreamer] = useState<WebSocketStreamer | null>(null);\r\n const [bytesSent, setBytesSent] = useState(0);\r\n const [startTime, setStartTime] = useState<Date | null>(null);\r\n const [isMuted, setIsMuted] = useState(false);\r\n const [isVideoEnabled, setIsVideoEnabled] = useState(true);\r\n const [facingMode, setFacingMode] = useState<\"user\" | \"environment\">(\"user\");\r\n const [showStopConfirm, setShowStopConfirm] = useState(false);\r\n const [showCloseConfirm, setShowCloseConfirm] = useState(false);\r\n const [hasMultipleCameras, setHasMultipleCameras] = useState(false);\r\n\r\n // Device selection state\r\n const [videoDevices, setVideoDevices] = useState<{ deviceId: string; label: string }[]>([]);\r\n const [audioDevices, setAudioDevices] = useState<{ deviceId: string; label: string }[]>([]);\r\n const [selectedVideoDeviceId, setSelectedVideoDeviceId] = useState<string | undefined>();\r\n const [selectedAudioDeviceId, setSelectedAudioDeviceId] = useState<string | undefined>();\r\n\r\n const videoRef = useRef<HTMLVideoElement>(null);\r\n const streamerRef = useRef<WebSocketStreamer | null>(null);\r\n const mediaStreamRef = useRef<MediaStream | null>(null);\r\n\r\n // Determine if this is a video or audio-only stream key\r\n const isVideoKey = streamKey ? (streamKey.startsWith(\"v\") || streamKey.startsWith(\"w\")) : false;\r\n\r\n // Handle stream key submission from input form\r\n const handleStreamKeySubmit = (key: string) => {\r\n setStreamKey(key);\r\n onStreamKeyChange?.(key);\r\n };\r\n\r\n // Handle internal stream key changes\r\n const handleStreamKeyChange = (key: string) => {\r\n setStreamKey(key);\r\n onStreamKeyChange?.(key);\r\n };\r\n\r\n // Check browser compatibility and detect cameras on mount\r\n useEffect(() => {\r\n if (!streamKey) return; // Wait for stream key\r\n\r\n const compat = checkBrowserCompatibility();\r\n if (!compat.compatible) {\r\n setError(compat.error || \"Browser not compatible\");\r\n setState(\"error\");\r\n return;\r\n }\r\n\r\n // Detect number of available cameras\r\n detectCameras();\r\n\r\n // Request media permissions\r\n requestMediaPermissions();\r\n }, [streamKey]);\r\n\r\n const detectCameras = async () => {\r\n try {\r\n const devices = await navigator.mediaDevices.enumerateDevices();\r\n const videoInputs = devices.filter(device => device.kind === \"videoinput\");\r\n const audioInputs = devices.filter(device => device.kind === \"audioinput\");\r\n\r\n console.log(`📷 Found ${videoInputs.length} video input device(s)`);\r\n console.log(`🎤 Found ${audioInputs.length} audio input device(s)`);\r\n\r\n // Detect iOS/iPadOS - these devices always have front + back cameras\r\n // but enumerateDevices() may not accurately report them\r\n const isIOS = /iPad|iPhone|iPod/.test(navigator.userAgent) ||\r\n (navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1);\r\n\r\n // On iOS, assume multiple cameras are available for video streams\r\n // since all modern iOS devices have front and back cameras\r\n const hasMultiple = videoInputs.length > 1 || (isIOS && isVideoKey);\r\n setHasMultipleCameras(hasMultiple);\r\n\r\n if (isIOS && videoInputs.length <= 1) {\r\n console.log(\"📱 iOS device detected - assuming multiple cameras available\");\r\n }\r\n\r\n // Map to simplified device info\r\n setVideoDevices(videoInputs.map(d => ({\r\n deviceId: d.deviceId,\r\n label: d.label || `Camera ${d.deviceId.slice(0, 8)}`,\r\n })));\r\n setAudioDevices(audioInputs.map(d => ({\r\n deviceId: d.deviceId,\r\n label: d.label || `Microphone ${d.deviceId.slice(0, 8)}`,\r\n })));\r\n\r\n // Set initial selected devices (first in list or from current stream)\r\n if (videoInputs.length > 0 && !selectedVideoDeviceId) {\r\n setSelectedVideoDeviceId(videoInputs[0].deviceId);\r\n }\r\n if (audioInputs.length > 0 && !selectedAudioDeviceId) {\r\n setSelectedAudioDeviceId(audioInputs[0].deviceId);\r\n }\r\n } catch (err) {\r\n console.error(\"❌ Failed to enumerate devices:\", err);\r\n // On iOS, still assume multiple cameras even if enumeration fails\r\n const isIOS = /iPad|iPhone|iPod/.test(navigator.userAgent) ||\r\n (navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1);\r\n setHasMultipleCameras(isIOS && isVideoKey);\r\n }\r\n };\r\n\r\n // Sync refs with state\r\n useEffect(() => {\r\n streamerRef.current = streamer;\r\n }, [streamer]);\r\n\r\n useEffect(() => {\r\n mediaStreamRef.current = mediaStream;\r\n }, [mediaStream]);\r\n\r\n // Clean up on unmount ONLY\r\n useEffect(() => {\r\n return () => {\r\n if (streamerRef.current) {\r\n streamerRef.current.stop();\r\n }\r\n if (mediaStreamRef.current) {\r\n mediaStreamRef.current.getTracks().forEach((track) => track.stop());\r\n }\r\n };\r\n }, []);\r\n\r\n // Prevent accidental navigation\r\n useEffect(() => {\r\n if (state === \"live\") {\r\n const handleBeforeUnload = (e: BeforeUnloadEvent) => {\r\n e.preventDefault();\r\n e.returnValue = \"You are currently streaming. Are you sure you want to leave?\";\r\n return e.returnValue;\r\n };\r\n\r\n window.addEventListener(\"beforeunload\", handleBeforeUnload);\r\n return () => window.removeEventListener(\"beforeunload\", handleBeforeUnload);\r\n }\r\n }, [state]);\r\n\r\n // Update video element when media stream changes or video is re-enabled\r\n // Note: When isVideoEnabled toggles, the video element is conditionally rendered,\r\n // so we need to re-attach the stream when the element comes back into the DOM\r\n useEffect(() => {\r\n if (videoRef.current && mediaStream) {\r\n videoRef.current.srcObject = mediaStream;\r\n }\r\n }, [mediaStream, isVideoEnabled]);\r\n\r\n const requestMediaPermissions = async () => {\r\n if (!streamKey) return;\r\n\r\n try {\r\n setState(\"requesting\");\r\n setError(null);\r\n\r\n const constraints = getMediaConstraints({\r\n isVideo: isVideoKey && isVideoEnabled,\r\n facingMode,\r\n });\r\n\r\n console.log(\"📸 Requesting media permissions:\", constraints);\r\n\r\n const stream = await navigator.mediaDevices.getUserMedia(constraints);\r\n\r\n console.log(\"✅ Media permissions granted\");\r\n setMediaStream(stream);\r\n setState(\"previewing\");\r\n } catch (err) {\r\n console.error(\"❌ Media permission error:\", err);\r\n\r\n if (err instanceof Error) {\r\n if (err.name === \"NotAllowedError\" || err.name === \"PermissionDeniedError\") {\r\n setError(\"Camera/microphone access denied. Please enable permissions in your browser settings.\");\r\n } else if (err.name === \"NotFoundError\") {\r\n setError(isVideoKey ? \"No camera or microphone found.\" : \"No microphone found.\");\r\n } else {\r\n setError(err.message || \"Failed to access media devices\");\r\n }\r\n } else {\r\n setError(\"Failed to access media devices\");\r\n }\r\n\r\n setState(\"error\");\r\n }\r\n };\r\n\r\n const handleStartStreaming = async () => {\r\n if (!mediaStream || !streamKey) {\r\n setError(\"No media stream available\");\r\n return;\r\n }\r\n\r\n try {\r\n setState(\"connecting\");\r\n setError(null);\r\n\r\n // STEP 1: Check if broadcast can be started\r\n // This validates session token permissions and checks for active broadcasts\r\n console.log(\"🔍 Checking broadcast availability...\");\r\n const checkResponse = await fetch(`${apiBaseUrl}/broadcasts/check`, {\r\n method: \"POST\",\r\n headers: {\r\n \"Content-Type\": \"application/json\",\r\n \"Authorization\": `Bearer ${sessionToken}`,\r\n },\r\n body: JSON.stringify({\r\n streamKey: streamKey,\r\n }),\r\n });\r\n\r\n if (!checkResponse.ok) {\r\n // Handle 401 Unauthorized - invalid/expired session token\r\n if (checkResponse.status === 401) {\r\n console.error(\"❌ Session token invalid or expired\");\r\n setError(\"Session expired. Please refresh the page and try again.\");\r\n setState(\"error\");\r\n // Notify context of token expiration\r\n dialTribeContext?.markExpired();\r\n return;\r\n }\r\n\r\n // Handle 403 Forbidden - missing broadcasts:stream permission\r\n if (checkResponse.status === 403) {\r\n const data = await checkResponse.json().catch(() => ({}));\r\n console.error(\"❌ Permission denied:\", data);\r\n setError(\r\n data.error ||\r\n \"Streaming is not enabled for this app. Please upgrade your plan or contact support.\"\r\n );\r\n setState(\"error\");\r\n return;\r\n }\r\n\r\n // Handle 409 Conflict - already active broadcast\r\n if (checkResponse.status === 409) {\r\n const data = await checkResponse.json();\r\n console.log(\"❌ Broadcast conflict:\", data);\r\n setError(\r\n data.error ||\r\n \"A broadcast is already active for this stream key. Please terminate it before starting a new one.\"\r\n );\r\n setState(\"error\");\r\n return;\r\n }\r\n\r\n // Handle other errors\r\n const errorData = await checkResponse.json().catch(() => ({ error: checkResponse.statusText }));\r\n console.error(\"❌ Check failed:\", checkResponse.status, errorData);\r\n setError(errorData.error || `Failed to check broadcast availability: ${checkResponse.statusText}`);\r\n setState(\"error\");\r\n return;\r\n }\r\n\r\n const checkData = await checkResponse.json();\r\n console.log(\"✅ Broadcast check passed:\", checkData);\r\n\r\n // STEP 2: Now connect to WebSocket and start streaming\r\n const newStreamer = new WebSocketStreamer({\r\n streamKey,\r\n mediaStream,\r\n isVideo: isVideoKey && isVideoEnabled,\r\n encoderServerUrl,\r\n disableCanvasRendering: true, // <-- ADD THIS LINE\r\n onBytesUpdate: setBytesSent,\r\n onStateChange: (streamerState) => {\r\n if (streamerState === \"live\") {\r\n setState(\"live\");\r\n setStartTime(new Date());\r\n } else if (streamerState === \"terminated\") {\r\n setState(\"terminated\");\r\n setStartTime(null);\r\n } else if (streamerState === \"error\") {\r\n setState(\"error\");\r\n }\r\n },\r\n onError: (errorMsg, diag) => {\r\n setError(errorMsg);\r\n if (diag) {\r\n setDiagnostics(diag);\r\n }\r\n },\r\n });\r\n\r\n await newStreamer.start();\r\n setStreamer(newStreamer);\r\n } catch (err) {\r\n console.error(\"❌ Failed to start streaming:\", err);\r\n setError(err instanceof Error ? err.message : \"Failed to start streaming\");\r\n setState(\"previewing\");\r\n }\r\n };\r\n\r\n const handleStopStreaming = () => {\r\n setShowStopConfirm(true);\r\n };\r\n\r\n const confirmStopStreaming = () => {\r\n setState(\"stopping\");\r\n setShowStopConfirm(false);\r\n\r\n if (streamer) {\r\n streamer.stop();\r\n }\r\n\r\n if (mediaStream) {\r\n mediaStream.getTracks().forEach((track) => track.stop());\r\n }\r\n\r\n setState(\"stopped\");\r\n setStartTime(null);\r\n };\r\n\r\n const handleToggleMute = () => {\r\n if (mediaStream) {\r\n const audioTracks = mediaStream.getAudioTracks();\r\n audioTracks.forEach((track) => {\r\n track.enabled = !track.enabled;\r\n });\r\n setIsMuted(!isMuted);\r\n }\r\n };\r\n\r\n const handleToggleVideo = () => {\r\n if (!isVideoKey) return; // Audio-only keys can't toggle video\r\n\r\n if (mediaStream) {\r\n const videoTracks = mediaStream.getVideoTracks();\r\n videoTracks.forEach((track) => {\r\n track.enabled = !track.enabled;\r\n });\r\n setIsVideoEnabled(!isVideoEnabled);\r\n }\r\n };\r\n\r\n const handleFlipCamera = async () => {\r\n if (!isVideoKey || !hasMultipleCameras) return;\r\n\r\n // Toggle facing mode\r\n const newFacingMode = facingMode === \"user\" ? \"environment\" : \"user\";\r\n\r\n // If we're currently streaming, use canvas-based track replacement\r\n // The canvas acts as an intermediary - MediaRecorder records from canvas, not camera\r\n // When we swap the camera, we just change what's being drawn to the canvas\r\n if (state === \"live\" && streamer) {\r\n console.log(\"🔄 Flipping camera during live broadcast (canvas-based swap)\");\r\n\r\n try {\r\n // Get new camera stream\r\n const constraints = getMediaConstraints({\r\n isVideo: true,\r\n facingMode: newFacingMode,\r\n });\r\n\r\n const newStream = await navigator.mediaDevices.getUserMedia(constraints);\r\n console.log(\"📷 Got new camera stream:\", newFacingMode);\r\n\r\n // Replace the video track in the streamer\r\n // With canvas-based rendering, this preloads the new camera then swaps\r\n // MediaRecorder continues recording from the unchanged canvas stream\r\n const newVideoTrack = newStream.getVideoTracks()[0];\r\n if (newVideoTrack) {\r\n await streamer.replaceVideoTrack(newVideoTrack);\r\n }\r\n\r\n // Update state with the streamer's current media stream\r\n const updatedStream = streamer.getMediaStream();\r\n setMediaStream(updatedStream);\r\n setFacingMode(newFacingMode);\r\n\r\n // Update the video preview to show the new camera\r\n if (videoRef.current) {\r\n videoRef.current.srcObject = updatedStream;\r\n }\r\n\r\n console.log(\"✅ Camera flipped successfully - broadcast continues seamlessly\");\r\n } catch (err) {\r\n console.error(\"❌ Failed to flip camera:\", err);\r\n console.warn(\"⚠️ Camera flip failed - continuing with current camera\");\r\n // Don't change facingMode since we failed\r\n }\r\n } else {\r\n // Not streaming yet, just update the preview (can stop/start freely)\r\n setFacingMode(newFacingMode);\r\n\r\n try {\r\n const constraints = getMediaConstraints({\r\n isVideo: true,\r\n facingMode: newFacingMode,\r\n });\r\n\r\n const newStream = await navigator.mediaDevices.getUserMedia(constraints);\r\n console.log(\"📷 Camera flipped to:\", newFacingMode);\r\n\r\n if (mediaStream) {\r\n mediaStream.getTracks().forEach((track) => track.stop());\r\n }\r\n setMediaStream(newStream);\r\n } catch (err) {\r\n console.error(\"❌ Failed to get new camera stream:\", err);\r\n // Revert facing mode\r\n setFacingMode(facingMode);\r\n console.warn(\"⚠️ Camera flip not available - this device may only have one camera\");\r\n }\r\n }\r\n };\r\n\r\n const handleRetry = () => {\r\n setError(null);\r\n setState(\"idle\");\r\n requestMediaPermissions();\r\n };\r\n\r\n const handleDone = () => {\r\n onDone?.();\r\n };\r\n\r\n // Handle close button - shows confirmation if live, otherwise closes immediately\r\n const handleClose = () => {\r\n if (state === \"live\") {\r\n setShowCloseConfirm(true);\r\n } else {\r\n // Not streaming, can close immediately\r\n if (mediaStream) {\r\n mediaStream.getTracks().forEach((track) => track.stop());\r\n }\r\n onDone?.();\r\n }\r\n };\r\n\r\n // Confirm close during live - stops stream and closes\r\n const confirmClose = () => {\r\n setShowCloseConfirm(false);\r\n\r\n if (streamer) {\r\n streamer.stop();\r\n }\r\n if (mediaStream) {\r\n mediaStream.getTracks().forEach((track) => track.stop());\r\n }\r\n\r\n // Close immediately without showing the \"stopped\" state\r\n onDone?.();\r\n };\r\n\r\n // Handle video device change from settings\r\n const handleVideoDeviceChange = async (deviceId: string) => {\r\n if (deviceId === selectedVideoDeviceId) return;\r\n\r\n setSelectedVideoDeviceId(deviceId);\r\n\r\n // Only update stream if we're in preview or live state\r\n if (state !== \"previewing\" && state !== \"live\") return;\r\n\r\n try {\r\n const constraints: MediaStreamConstraints = {\r\n video: { deviceId: { exact: deviceId } },\r\n audio: selectedAudioDeviceId ? { deviceId: { exact: selectedAudioDeviceId } } : true,\r\n };\r\n\r\n const newStream = await navigator.mediaDevices.getUserMedia(constraints);\r\n console.log(`📷 Switched to camera: ${deviceId}`);\r\n\r\n if (state === \"live\" && streamer) {\r\n // Hot-swap during live stream\r\n try {\r\n await streamer.updateMediaStream(newStream);\r\n if (mediaStream) {\r\n mediaStream.getTracks().forEach((track) => track.stop());\r\n }\r\n setMediaStream(newStream);\r\n } catch (swapErr) {\r\n console.error(\"❌ Failed to hot-swap video device:\", swapErr);\r\n newStream.getTracks().forEach((track) => track.stop());\r\n }\r\n } else {\r\n // Preview mode - just update the stream\r\n if (mediaStream) {\r\n mediaStream.getTracks().forEach((track) => track.stop());\r\n }\r\n setMediaStream(newStream);\r\n }\r\n } catch (err) {\r\n console.error(\"❌ Failed to switch video device:\", err);\r\n }\r\n };\r\n\r\n // Handle audio device change from settings\r\n const handleAudioDeviceChange = async (deviceId: string) => {\r\n if (deviceId === selectedAudioDeviceId) return;\r\n\r\n setSelectedAudioDeviceId(deviceId);\r\n\r\n // Only update stream if we're in preview or live state\r\n if (state !== \"previewing\" && state !== \"live\") return;\r\n\r\n try {\r\n const constraints: MediaStreamConstraints = {\r\n video: isVideoKey && isVideoEnabled && selectedVideoDeviceId\r\n ? { deviceId: { exact: selectedVideoDeviceId } }\r\n : isVideoKey && isVideoEnabled,\r\n audio: { deviceId: { exact: deviceId } },\r\n };\r\n\r\n const newStream = await navigator.mediaDevices.getUserMedia(constraints);\r\n console.log(`🎤 Switched to microphone: ${deviceId}`);\r\n\r\n if (state === \"live\" && streamer) {\r\n // Hot-swap during live stream\r\n try {\r\n await streamer.updateMediaStream(newStream);\r\n if (mediaStream) {\r\n mediaStream.getTracks().forEach((track) => track.stop());\r\n }\r\n setMediaStream(newStream);\r\n } catch (swapErr) {\r\n console.error(\"❌ Failed to hot-swap audio device:\", swapErr);\r\n newStream.getTracks().forEach((track) => track.stop());\r\n }\r\n } else {\r\n // Preview mode - just update the stream\r\n if (mediaStream) {\r\n mediaStream.getTracks().forEach((track) => track.stop());\r\n }\r\n setMediaStream(newStream);\r\n }\r\n } catch (err) {\r\n console.error(\"❌ Failed to switch audio device:\", err);\r\n }\r\n };\r\n\r\n // Show connecting state if no session token (waiting for credentials via postMessage)\r\n if (!sessionToken) {\r\n return (\r\n <div className={centeredContainerClass}>\r\n <div className=\"text-center\">\r\n <div className=\"w-16 h-16 border-4 border-gray-700 border-t-blue-600 rounded-full animate-spin mx-auto mb-4\" />\r\n <p className=\"text-white text-lg\">Connecting...</p>\r\n </div>\r\n </div>\r\n );\r\n }\r\n\r\n // Show stream key input if no stream key provided\r\n if (!streamKey) {\r\n return <StreamKeyInput onSubmit={handleStreamKeySubmit} inline={inline} />;\r\n }\r\n\r\n // Render error state\r\n if (state === \"error\") {\r\n // Check if this is a broadcast conflict error (409)\r\n const isBroadcastConflict =\r\n error?.includes(\"already active\") || error?.includes(\"terminate it before\");\r\n\r\n return (\r\n <div className={centeredContainerClass}>\r\n <div className=\"bg-white dark:bg-zinc-900 rounded-lg border border-gray-200 dark:border-zinc-800 p-8 max-w-md w-full text-center\">\r\n <div className=\"w-16 h-16 bg-red-100 dark:bg-red-900/20 rounded-full flex items-center justify-center mx-auto mb-4\">\r\n <svg\r\n className=\"w-8 h-8 text-red-600 dark:text-red-400\"\r\n fill=\"none\"\r\n stroke=\"currentColor\"\r\n viewBox=\"0 0 24 24\"\r\n >\r\n <path\r\n strokeLinecap=\"round\"\r\n strokeLinejoin=\"round\"\r\n strokeWidth={2}\r\n d=\"M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z\"\r\n />\r\n </svg>\r\n </div>\r\n <h2 className=\"text-xl font-bold text-black dark:text-white mb-2\">\r\n {isBroadcastConflict ? \"Broadcast Already Active\" : \"Error\"}\r\n </h2>\r\n <p className=\"text-gray-600 dark:text-gray-400 mb-6\">{error}</p>\r\n\r\n {isBroadcastConflict && (\r\n <p className=\"text-sm text-gray-500 dark:text-gray-400 mb-6\">\r\n You need to terminate the existing broadcast before starting a new one.\r\n </p>\r\n )}\r\n\r\n <div className=\"flex flex-col gap-2\">\r\n {!isBroadcastConflict && (\r\n <button\r\n onClick={handleRetry}\r\n className=\"w-full px-6 py-2 bg-blue-600 hover:bg-blue-700 text-white font-medium rounded-lg transition-colors\"\r\n >\r\n Retry\r\n </button>\r\n )}\r\n <button\r\n onClick={handleDone}\r\n className=\"w-full px-6 py-2 bg-gray-100 dark:bg-zinc-800 hover:bg-gray-200 dark:hover:bg-zinc-700 text-black dark:text-white font-medium rounded-lg transition-colors\"\r\n >\r\n Close\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n );\r\n }\r\n\r\n // Render stopped state\r\n if (state === \"stopped\") {\r\n return (\r\n <div className={centeredContainerClass}>\r\n <div className=\"bg-white dark:bg-zinc-900 rounded-lg border border-gray-200 dark:border-zinc-800 p-8 max-w-md w-full text-center\">\r\n <div className=\"w-16 h-16 bg-green-100 dark:bg-green-900/20 rounded-full flex items-center justify-center mx-auto mb-4\">\r\n <svg\r\n className=\"w-8 h-8 text-green-600 dark:text-green-400\"\r\n fill=\"none\"\r\n stroke=\"currentColor\"\r\n viewBox=\"0 0 24 24\"\r\n >\r\n <path\r\n strokeLinecap=\"round\"\r\n strokeLinejoin=\"round\"\r\n strokeWidth={2}\r\n d=\"M5 13l4 4L19 7\"\r\n />\r\n </svg>\r\n </div>\r\n <h2 className=\"text-xl font-bold text-black dark:text-white mb-2\">Stream Ended</h2>\r\n <p className=\"text-gray-600 dark:text-gray-400 mb-2\">Your broadcast has ended successfully.</p>\r\n <p className=\"text-sm text-gray-500 dark:text-gray-400 mb-6\">\r\n Total sent: {(bytesSent / 1024 / 1024).toFixed(2)} MB\r\n </p>\r\n <button\r\n onClick={handleDone}\r\n className=\"w-full px-6 py-2 bg-blue-600 hover:bg-blue-700 text-white font-medium rounded-lg transition-colors\"\r\n >\r\n Done\r\n </button>\r\n </div>\r\n </div>\r\n );\r\n }\r\n\r\n // Render terminated state\r\n if (state === \"terminated\") {\r\n return (\r\n <div className={centeredContainerClass}>\r\n <div className=\"bg-white dark:bg-zinc-900 rounded-lg border border-gray-200 dark:border-zinc-800 p-8 max-w-md w-full text-center\">\r\n <div className=\"w-16 h-16 bg-orange-100 dark:bg-orange-900/20 rounded-full flex items-center justify-center mx-auto mb-4\">\r\n <svg\r\n className=\"w-8 h-8 text-orange-600 dark:text-orange-400\"\r\n fill=\"none\"\r\n stroke=\"currentColor\"\r\n viewBox=\"0 0 24 24\"\r\n >\r\n <path\r\n strokeLinecap=\"round\"\r\n strokeLinejoin=\"round\"\r\n strokeWidth={2}\r\n d=\"M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z\"\r\n />\r\n </svg>\r\n </div>\r\n <h2 className=\"text-xl font-bold text-black dark:text-white mb-2\">Stream Ended</h2>\r\n <p className=\"text-gray-600 dark:text-gray-400 mb-2\">{error || \"Connection closed unexpectedly\"}</p>\r\n <p className=\"text-sm text-gray-500 dark:text-gray-400 mb-2\">\r\n Total sent: {(bytesSent / 1024 / 1024).toFixed(2)} MB\r\n </p>\r\n {diagnostics && (\r\n <div className=\"text-xs text-gray-400 dark:text-gray-500 mb-6 font-mono bg-gray-100 dark:bg-zinc-800 rounded p-2 text-left\">\r\n <div>Codec: {diagnostics.mimeType || \"unknown\"}</div>\r\n <div>Chunks: {diagnostics.chunksSent} ({(diagnostics.bytesSent / 1024).toFixed(1)} KB)</div>\r\n <div>Duration: {(diagnostics.elapsedMs / 1000).toFixed(1)}s</div>\r\n <div>Close code: {diagnostics.closeCode ?? \"N/A\"}{diagnostics.closeReason ? ` (${diagnostics.closeReason})` : \"\"}</div>\r\n </div>\r\n )}\r\n {!diagnostics && <div className=\"mb-6\" />}\r\n <button\r\n onClick={handleDone}\r\n className=\"w-full px-6 py-2 bg-blue-600 hover:bg-blue-700 text-white font-medium rounded-lg transition-colors\"\r\n >\r\n Done\r\n </button>\r\n </div>\r\n </div>\r\n );\r\n }\r\n\r\n // Render loading state\r\n if (state === \"idle\" || state === \"requesting\") {\r\n return (\r\n <div className={centeredContainerClass}>\r\n <div className=\"text-center\">\r\n <div className=\"w-16 h-16 border-4 border-gray-700 border-t-blue-600 rounded-full animate-spin mx-auto mb-4\" />\r\n <p className=\"text-white text-lg\">\r\n {state === \"idle\" ? \"Initializing...\" : \"Requesting permissions...\"}\r\n </p>\r\n </div>\r\n </div>\r\n );\r\n }\r\n\r\n // Map state to control state (only preview/connecting/live states)\r\n const controlState: StreamingControlState = state as StreamingControlState;\r\n\r\n // Render preview or live streaming state\r\n return (\r\n <div className={`${containerClass} flex flex-col`}>\r\n <StreamingPreview\r\n videoRef={videoRef}\r\n isVideoKey={isVideoKey}\r\n isVideoEnabled={isVideoEnabled}\r\n mediaStream={mediaStream}\r\n facingMode={facingMode}\r\n />\r\n\r\n <StreamingControls\r\n state={controlState}\r\n isVideoKey={isVideoKey}\r\n isMuted={isMuted}\r\n isVideoEnabled={isVideoEnabled}\r\n facingMode={facingMode}\r\n hasMultipleCameras={hasMultipleCameras}\r\n startTime={startTime}\r\n bytesSent={bytesSent}\r\n showStopConfirm={showStopConfirm}\r\n streamKey={streamKey}\r\n onStreamKeyChange={handleStreamKeyChange}\r\n onStart={handleStartStreaming}\r\n onStop={handleStopStreaming}\r\n onConfirmStop={confirmStopStreaming}\r\n onCancelStop={() => setShowStopConfirm(false)}\r\n onToggleMute={handleToggleMute}\r\n onToggleVideo={handleToggleVideo}\r\n onFlipCamera={handleFlipCamera}\r\n // Only show close button in non-inline mode (popup/fullscreen)\r\n onClose={inline ? undefined : handleClose}\r\n showCloseConfirm={showCloseConfirm}\r\n onConfirmClose={confirmClose}\r\n onCancelClose={() => setShowCloseConfirm(false)}\r\n // Device selection props\r\n videoDevices={videoDevices}\r\n audioDevices={audioDevices}\r\n selectedVideoDeviceId={selectedVideoDeviceId}\r\n selectedAudioDeviceId={selectedAudioDeviceId}\r\n onVideoDeviceChange={handleVideoDeviceChange}\r\n onAudioDeviceChange={handleAudioDeviceChange}\r\n mediaStream={mediaStream}\r\n />\r\n </div>\r\n );\r\n}\r\n","\r\n/**\r\n * Shared Loading Spinner Component\r\n */\r\n\r\ninterface LoadingSpinnerProps {\r\n /**\r\n * Optional text to display below the spinner\r\n */\r\n text?: string;\r\n /**\r\n * Size variant of the spinner\r\n * @default \"md\"\r\n */\r\n size?: \"sm\" | \"md\" | \"lg\";\r\n /**\r\n * Color scheme\r\n * @default \"default\"\r\n */\r\n variant?: \"default\" | \"primary\" | \"white\";\r\n}\r\n\r\nconst sizeClasses = {\r\n sm: \"h-4 w-4 border-2\",\r\n md: \"h-8 w-8 border-4\",\r\n lg: \"h-12 w-12 border-4\",\r\n};\r\n\r\nconst variantClasses = {\r\n default:\r\n \"border-gray-200 dark:border-gray-800 border-t-black dark:border-t-white\",\r\n primary:\r\n \"border-gray-300 dark:border-gray-700 border-t-blue-600 dark:border-t-blue-400\",\r\n white: \"border-gray-600 border-t-white\",\r\n};\r\n\r\n/**\r\n * Loading spinner component with optional text\r\n *\r\n * @example\r\n * <LoadingSpinner />\r\n * <LoadingSpinner text=\"Loading broadcasts...\" size=\"lg\" />\r\n * <LoadingSpinner variant=\"white\" />\r\n */\r\nexport function LoadingSpinner({\r\n text,\r\n size = \"md\",\r\n variant = \"default\",\r\n}: LoadingSpinnerProps) {\r\n return (\r\n <div className=\"flex flex-col items-center justify-center gap-3\">\r\n <div\r\n className={`${sizeClasses[size]} ${variantClasses[variant]} rounded-full animate-spin`}\r\n role=\"status\"\r\n aria-label=\"Loading\"\r\n />\r\n {text && <p className=\"text-sm text-gray-500 dark:text-gray-400\">{text}</p>}\r\n </div>\r\n );\r\n}\r\n","/**\r\n * CDN domain for broadcast content\r\n * Can be overridden via environment variable CONTENT_CDN_DOMAIN\r\n */\r\nexport const CDN_DOMAIN =\r\n typeof process !== \"undefined\" && process.env?.CONTENT_CDN_DOMAIN\r\n ? process.env.CONTENT_CDN_DOMAIN\r\n : \"cdn.dialtribe.com\";\r\n\r\n/**\r\n * Shard a hash by inserting slashes between characters\r\n * Example: \"abc123\" → \"a/b/c/1/2/3\"\r\n */\r\nfunction shardHash(hash: string): string {\r\n return hash.toLowerCase().split(\"\").join(\"/\");\r\n}\r\n\r\n/**\r\n * Build S3 key prefix for broadcast files\r\n *\r\n * @param appHash - App S3 hash\r\n * @param broadcastHash - Broadcast hash\r\n * @returns S3 key prefix with trailing slash\r\n */\r\nexport function buildBroadcastS3KeyPrefix(\r\n appHash: string,\r\n broadcastHash: string\r\n): string {\r\n return `a/${shardHash(appHash)}/b/${shardHash(broadcastHash)}/`;\r\n}\r\n\r\n/**\r\n * Build CDN URL for a broadcast file (HLS)\r\n *\r\n * @param appHash - App S3 hash\r\n * @param broadcastHash - Broadcast hash\r\n * @param filename - File name (e.g., \"index.m3u8\", \"seg-0-000001.ts\")\r\n * @returns CDN URL\r\n */\r\nexport function buildBroadcastCdnUrl(\r\n appHash: string,\r\n broadcastHash: string,\r\n filename: string\r\n): string {\r\n const keyPrefix = buildBroadcastS3KeyPrefix(appHash, broadcastHash);\r\n return `https://${CDN_DOMAIN}/${keyPrefix}${filename}`;\r\n}\r\n","/**\r\n * Format seconds to time string (HH:MM:SS or MM:SS)\r\n *\r\n * @param seconds - Number of seconds\r\n * @param includeHours - Whether to always include hours (default: auto-detect)\r\n * @returns Formatted time string\r\n *\r\n * Examples:\r\n * - formatTime(45) → \"0:45\"\r\n * - formatTime(125) → \"2:05\"\r\n * - formatTime(3665) → \"1:01:05\"\r\n */\r\nexport function formatTime(seconds: number, includeHours?: boolean): string {\r\n if (isNaN(seconds) || !isFinite(seconds) || seconds < 0) {\r\n return \"0:00\";\r\n }\r\n\r\n const hrs = Math.floor(seconds / 3600);\r\n const mins = Math.floor((seconds % 3600) / 60);\r\n const secs = Math.floor(seconds % 60);\r\n\r\n const secStr = secs.toString().padStart(2, \"0\");\r\n const minStr = mins.toString().padStart(2, \"0\");\r\n\r\n if (hrs > 0 || includeHours) {\r\n return `${hrs}:${minStr}:${secStr}`;\r\n }\r\n\r\n return `${mins}:${secStr}`;\r\n}\r\n","export const HTTP_STATUS = {\r\n // 2xx Success\r\n OK: 200,\r\n CREATED: 201,\r\n ACCEPTED: 202,\r\n NO_CONTENT: 204,\r\n\r\n // 3xx Redirection\r\n MOVED_PERMANENTLY: 301,\r\n FOUND: 302,\r\n SEE_OTHER: 303,\r\n NOT_MODIFIED: 304,\r\n TEMPORARY_REDIRECT: 307,\r\n PERMANENT_REDIRECT: 308,\r\n\r\n // 4xx Client Errors\r\n BAD_REQUEST: 400,\r\n UNAUTHORIZED: 401,\r\n PAYMENT_REQUIRED: 402,\r\n FORBIDDEN: 403,\r\n NOT_FOUND: 404,\r\n METHOD_NOT_ALLOWED: 405,\r\n NOT_ACCEPTABLE: 406,\r\n CONFLICT: 409,\r\n GONE: 410,\r\n PAYLOAD_TOO_LARGE: 413,\r\n UNSUPPORTED_MEDIA_TYPE: 415,\r\n UNPROCESSABLE_ENTITY: 422,\r\n TOO_MANY_REQUESTS: 429,\r\n\r\n // 5xx Server Errors\r\n INTERNAL_SERVER_ERROR: 500,\r\n NOT_IMPLEMENTED: 501,\r\n BAD_GATEWAY: 502,\r\n SERVICE_UNAVAILABLE: 503,\r\n GATEWAY_TIMEOUT: 504,\r\n} as const;\r\n\r\n// Type-safe status code type\r\nexport type HttpStatusCode = typeof HTTP_STATUS[keyof typeof HTTP_STATUS];\r\n","/**\r\n * Debug logging utility\r\n * Only logs in development mode to avoid exposing internals in production\r\n */\r\n\r\nconst DEBUG = process.env.NODE_ENV === 'development';\r\n\r\nexport const debug = {\r\n log: (...args: unknown[]) => {\r\n if (DEBUG) console.log(...args);\r\n },\r\n\r\n warn: (...args: unknown[]) => {\r\n if (DEBUG) console.warn(...args);\r\n },\r\n\r\n error: (...args: unknown[]) => {\r\n if (DEBUG) console.error(...args);\r\n },\r\n};\r\n","import { useEffect, useRef, useState, useCallback, useMemo } from \"react\";\r\nimport ReactPlayer from \"react-player\";\r\n\r\nimport { AudioWaveform } from \"./AudioWaveform\";\r\nimport { LoadingSpinner } from \"./LoadingSpinner\";\r\nimport { buildBroadcastCdnUrl } from \"../utils/cdn\";\r\nimport { formatTime } from \"../utils/format\";\r\nimport { HTTP_STATUS } from \"../utils/http-status\";\r\nimport { debug } from \"../utils/debug\";\r\nimport { useDialtribe } from \"../context/DialtribeProvider\";\r\nimport { DialtribeClient, ENDPOINTS } from \"../client/DialtribeClient\";\r\nimport type { Broadcast, TranscriptData } from \"../types/broadcast\";\r\n\r\n// Constants for URL refresh behavior\r\nconst URL_EXPIRATION_MS = 6 * 60 * 60 * 1000; // 6 hours\r\nconst REFRESH_THRESHOLD_MS = 5 * 60 * 1000; // 5 minutes before expiration\r\nconst REFRESH_CHECK_INTERVAL_MS = 60000; // Check every 1 minute\r\nconst PLAYBACK_RESUME_DELAY_MS = 500; // Wait for player to load new URL\r\nconst TRAILING_WORDS = 3; // Number of trailing words to highlight in transcript\r\n\r\n/**\r\n * Build a playback URL for the content/play endpoint\r\n */\r\nfunction buildPlaybackUrl(\r\n broadcastId: number,\r\n hash: string,\r\n action?: \"download\"\r\n): string {\r\n const searchParams = new URLSearchParams({\r\n broadcastId: broadcastId.toString(),\r\n hash,\r\n });\r\n if (action) {\r\n searchParams.set(\"action\", action);\r\n }\r\n return `${ENDPOINTS.contentPlay}?${searchParams}`;\r\n}\r\n\r\n/**\r\n * Get a user-friendly error message based on the error type\r\n */\r\nfunction getErrorMessage(error: unknown): string {\r\n if (!error) return \"Unable to play media. Please try again.\";\r\n\r\n const errorMsg = error instanceof Error ? error.message : String(error);\r\n const errorCode = (error as any)?.code;\r\n const errorStatus = (error as any)?.status || (error as any)?.statusCode;\r\n\r\n // Network errors\r\n if (\r\n errorMsg.toLowerCase().includes(\"network\") ||\r\n errorMsg.includes(\"NetworkError\")\r\n ) {\r\n return \"No internet connection detected. Please check your network and try again.\";\r\n }\r\n\r\n // Session/Auth errors\r\n if (\r\n errorStatus === 401 ||\r\n errorMsg.includes(\"401\") ||\r\n errorMsg.includes(\"Unauthorized\")\r\n ) {\r\n return \"Session expired. Please refresh the page and log in again.\";\r\n }\r\n\r\n if (\r\n errorStatus === 403 ||\r\n errorMsg.includes(\"403\") ||\r\n errorMsg.includes(\"Forbidden\")\r\n ) {\r\n return \"Access denied. You may not have permission to view this content.\";\r\n }\r\n\r\n // Not found errors\r\n if (\r\n errorStatus === 404 ||\r\n errorMsg.includes(\"404\") ||\r\n errorMsg.includes(\"not found\")\r\n ) {\r\n return \"Media file not found. It may have been deleted or is still processing.\";\r\n }\r\n\r\n // Media errors\r\n if (\r\n errorMsg.includes(\"no supported sources\") ||\r\n errorMsg.includes(\"NotSupportedError\")\r\n ) {\r\n return \"This media format is not supported by your browser. Try using Chrome, Firefox, or Safari.\";\r\n }\r\n\r\n if (errorMsg.includes(\"MEDIA_ERR_SRC_NOT_SUPPORTED\") || errorCode === 4) {\r\n return \"Media file is not available or the format is unsupported.\";\r\n }\r\n\r\n if (errorMsg.includes(\"MEDIA_ERR_NETWORK\") || errorCode === 2) {\r\n return \"Network error while loading media. Please check your connection.\";\r\n }\r\n\r\n if (errorMsg.includes(\"MEDIA_ERR_DECODE\") || errorCode === 3) {\r\n return \"Media file is corrupted or cannot be decoded. Please contact support.\";\r\n }\r\n\r\n if (errorMsg.includes(\"AbortError\")) {\r\n return \"Media loading was interrupted. Please try again.\";\r\n }\r\n\r\n // Generic fallback\r\n return \"Unable to play media. Please try refreshing the page or contact support if the problem persists.\";\r\n}\r\n\r\nexport interface DialtribePlayerProps {\r\n /** Broadcast data from Dialtribe API */\r\n broadcast: Broadcast;\r\n\r\n /** Optional: App ID for tracking */\r\n appId?: string;\r\n\r\n /** Optional: Content ID for tracking */\r\n contentId?: number;\r\n\r\n /** Foreign user ID from partner system (any tier) */\r\n foreignId?: string;\r\n\r\n /** Tier name from partner system (e.g., 'guest', 'member', 'subscriber_gold') */\r\n foreignTier?: string;\r\n\r\n /**\r\n * Optional render prop for clip creator\r\n * If provided, the \"Create Clip\" button will be shown and this will be called when clicked\r\n */\r\n renderClipCreator?: (props: {\r\n isOpen: boolean;\r\n onClose: () => void;\r\n sourceVideoUrl?: string;\r\n sourceAudioUrl?: string;\r\n sourceDuration: number;\r\n onPauseParent: () => void;\r\n }) => React.ReactNode;\r\n\r\n /** Optional: Called when player encounters error */\r\n onError?: (error: Error) => void;\r\n\r\n /** Optional: Custom CSS classes */\r\n className?: string;\r\n\r\n /** Optional: Enable keyboard shortcuts (Space, arrows, M, F, etc.). Default: false */\r\n enableKeyboardShortcuts?: boolean;\r\n}\r\n\r\n/**\r\n * DialtribePlayer - Media player component for Dialtribe broadcasts\r\n *\r\n * Plays video/audio broadcasts with transcript, waveform visualization, and clip creation.\r\n * For modal or fullscreen display, wrap with the Overlay component.\r\n *\r\n * @example\r\n * ```tsx\r\n * // Inline (embedded in page)\r\n * <DialtribePlayer broadcast={broadcast} />\r\n *\r\n * // Modal (wrap with Overlay)\r\n * <DialtribeOverlay mode=\"modal\" isOpen={show} onClose={() => setShow(false)}>\r\n * <DialtribePlayer broadcast={broadcast} />\r\n * </DialtribeOverlay>\r\n *\r\n * // Fullscreen (wrap with Overlay)\r\n * <DialtribeOverlay mode=\"fullscreen\" isOpen={show} onClose={() => setShow(false)}>\r\n * <DialtribePlayer broadcast={broadcast} />\r\n * </DialtribeOverlay>\r\n * ```\r\n */\r\nexport function DialtribePlayer({\r\n broadcast,\r\n appId,\r\n contentId,\r\n foreignId,\r\n foreignTier = \"guest\",\r\n renderClipCreator,\r\n onError,\r\n className = \"\",\r\n enableKeyboardShortcuts = false,\r\n}: DialtribePlayerProps) {\r\n // Get session token and API base URL from context\r\n const { sessionToken, setSessionToken, markExpired, apiBaseUrl } =\r\n useDialtribe();\r\n\r\n // Create API client with token refresh handlers (stable reference)\r\n const clientRef = useRef<DialtribeClient | null>(null);\r\n\r\n // Initialize or update client when token changes\r\n if (!clientRef.current && sessionToken) {\r\n clientRef.current = new DialtribeClient({\r\n sessionToken,\r\n apiBaseUrl,\r\n onTokenRefresh: (newToken, expiresAt) => {\r\n debug.log(`[DialtribeClient] Token refreshed, expires at ${expiresAt}`);\r\n setSessionToken(newToken, expiresAt);\r\n },\r\n onTokenExpired: () => {\r\n debug.error(\"[DialtribeClient] Token expired\");\r\n markExpired();\r\n },\r\n });\r\n } else if (clientRef.current && sessionToken) {\r\n // Update token in existing client\r\n clientRef.current.setSessionToken(sessionToken);\r\n }\r\n\r\n const client = clientRef.current;\r\n\r\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n const playerRef = useRef<any>(null); // ReactPlayer doesn't export proper types\r\n const transcriptContainerRef = useRef<HTMLDivElement>(null);\r\n const activeWordRef = useRef<HTMLSpanElement>(null);\r\n const [audioElement, setAudioElement] = useState<HTMLMediaElement | null>(\r\n null\r\n );\r\n const [playing, setPlaying] = useState(false);\r\n const [played, setPlayed] = useState(0);\r\n const [duration, setDuration] = useState(0);\r\n const [volume, setVolume] = useState(1);\r\n const [muted, setMuted] = useState(false);\r\n const [seeking, setSeeking] = useState(false);\r\n const [hasError, setHasError] = useState(false);\r\n const [errorMessage, setErrorMessage] = useState(\"\");\r\n const [hasEnded, setHasEnded] = useState(false);\r\n const [hasStreamEnded, setHasStreamEnded] = useState(false);\r\n const [showTranscript, setShowTranscript] = useState(false);\r\n const [transcriptData, setTranscriptData] = useState<TranscriptData | null>(\r\n null\r\n );\r\n const [currentTime, setCurrentTime] = useState(0);\r\n const [isLoadingTranscript, setIsLoadingTranscript] = useState(false);\r\n const [isLoadingVideo, setIsLoadingVideo] = useState(true);\r\n const [autoScrollEnabled, setAutoScrollEnabled] = useState(true);\r\n const isScrollingProgrammatically = useRef(false);\r\n const lastActiveWordIndex = useRef<number>(-1);\r\n const [showClipCreator, setShowClipCreator] = useState(false);\r\n\r\n // Track initial playback type\r\n const initialPlaybackTypeRef = useRef<string | null>(null);\r\n const [currentPlaybackInfo, setCurrentPlaybackInfo] = useState<{\r\n url: string;\r\n type: string;\r\n } | null>(null);\r\n const [urlExpiresAt, setUrlExpiresAt] = useState<Date | null>(null);\r\n const isRefreshingUrl = useRef(false);\r\n\r\n // Audience tracking state\r\n const [audienceId, setAudienceId] = useState<string | null>(null);\r\n const [sessionId] = useState<string>(() => {\r\n if (typeof crypto !== \"undefined\" && crypto.randomUUID) {\r\n return crypto.randomUUID();\r\n }\r\n return \"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx\".replace(/[xy]/g, (c) => {\r\n const r = (Math.random() * 16) | 0;\r\n const v = c === \"x\" ? r : (r & 0x3) | 0x8;\r\n return v.toString(16);\r\n });\r\n });\r\n const heartbeatIntervalRef = useRef<NodeJS.Timeout | null>(null);\r\n const hasInitializedSession = useRef(false);\r\n\r\n /**\r\n * Refresh presigned URL when it expires\r\n */\r\n const refreshPresignedUrl = useCallback(\r\n async (fileType: \"mp4\" | \"mp3\" | \"hls\"): Promise<boolean> => {\r\n if (!broadcast.hash || isRefreshingUrl.current || !client) {\r\n debug.log(\r\n \"[URL Refresh] Skipping refresh - no hash, already refreshing, or no client\"\r\n );\r\n return false;\r\n }\r\n\r\n // HLS doesn't need refresh (direct CloudFront URLs)\r\n if (fileType === \"hls\") {\r\n debug.log(\"[URL Refresh] HLS does not need URL refresh\");\r\n return false;\r\n }\r\n\r\n isRefreshingUrl.current = true;\r\n debug.log(\r\n `[URL Refresh] Refreshing ${fileType} URL for broadcast ${broadcast.id}`\r\n );\r\n\r\n try {\r\n const data = await client.refreshPresignedUrl({\r\n broadcastId: broadcast.id,\r\n hash: broadcast.hash,\r\n fileType,\r\n });\r\n\r\n debug.log(\r\n `[URL Refresh] Successfully refreshed URL, expires at ${data.expiresAt}`\r\n );\r\n\r\n // Update playback info with new URL\r\n setCurrentPlaybackInfo({ url: data.url, type: fileType });\r\n setUrlExpiresAt(new Date(data.expiresAt));\r\n\r\n // Clear error state\r\n if (\r\n errorMessage.includes(\"URL\") ||\r\n errorMessage.includes(\"session\") ||\r\n errorMessage.includes(\"refresh\")\r\n ) {\r\n setHasError(false);\r\n setErrorMessage(\"\");\r\n }\r\n\r\n return true;\r\n } catch (error) {\r\n if (error instanceof Error && error.name === \"AbortError\") {\r\n debug.log(\"[URL Refresh] Request aborted\");\r\n return false;\r\n }\r\n\r\n debug.error(\"[URL Refresh] Failed to refresh presigned URL:\", error);\r\n setHasError(true);\r\n setErrorMessage(\r\n \"Unable to refresh media URL. The session may have expired.\"\r\n );\r\n if (onError && error instanceof Error) {\r\n onError(error);\r\n }\r\n return false;\r\n } finally {\r\n isRefreshingUrl.current = false;\r\n }\r\n },\r\n [broadcast.hash, broadcast.id, errorMessage, client, onError]\r\n );\r\n\r\n /**\r\n * Detect screen size category\r\n */\r\n const getScreenSize = () => {\r\n if (typeof window === \"undefined\") return \"unknown\";\r\n const width = window.innerWidth;\r\n if (width < 768) return \"mobile\";\r\n if (width < 1024) return \"tablet\";\r\n return \"desktop\";\r\n };\r\n\r\n /**\r\n * Initialize audience tracking session\r\n */\r\n const initializeTrackingSession = useCallback(async () => {\r\n // Only track recorded content (not live HLS)\r\n if (!contentId || !appId || !client) return;\r\n if (currentPlaybackInfo?.type === \"hls\" && broadcast.broadcastStatus === 1)\r\n return;\r\n\r\n // Prevent duplicate initialization\r\n if (hasInitializedSession.current) return;\r\n hasInitializedSession.current = true;\r\n\r\n try {\r\n const screenSize = getScreenSize();\r\n const platformInfo = `${navigator.platform || \"Unknown\"} (${screenSize})`;\r\n\r\n const data = await client.startSession({\r\n contentId,\r\n broadcastId: broadcast.id,\r\n appId,\r\n foreignId: foreignId || null,\r\n foreignTier: foreignTier || \"guest\",\r\n sessionId,\r\n fileType: currentPlaybackInfo?.type || \"mp3\",\r\n platform: platformInfo,\r\n userAgent: navigator.userAgent || null,\r\n origin: window.location.origin || null,\r\n country: null,\r\n region: null,\r\n });\r\n\r\n setAudienceId(data.audienceId);\r\n\r\n if (data.resumePosition && data.resumePosition > 0 && audioElement) {\r\n audioElement.currentTime = data.resumePosition;\r\n debug.log(\r\n `[Audience Tracking] Resumed playback at ${data.resumePosition}s`\r\n );\r\n }\r\n\r\n debug.log(\"[Audience Tracking] Session initialized:\", data.audienceId);\r\n } catch (error) {\r\n debug.error(\"[Audience Tracking] Error initializing session:\", error);\r\n if (onError && error instanceof Error) {\r\n onError(error);\r\n }\r\n }\r\n }, [\r\n contentId,\r\n appId,\r\n broadcast.id,\r\n broadcast.broadcastStatus,\r\n foreignId,\r\n foreignTier,\r\n sessionId,\r\n currentPlaybackInfo?.type,\r\n audioElement,\r\n client,\r\n onError,\r\n ]);\r\n\r\n /**\r\n * Send audience tracking ping event\r\n */\r\n const sendTrackingPing = useCallback(\r\n async (eventType: 0 | 1 | 2 | 3) => {\r\n if (!audienceId || !sessionId || !client) return;\r\n\r\n try {\r\n await client.sendSessionPing({\r\n audienceId,\r\n sessionId,\r\n eventType,\r\n currentTime: Math.floor(audioElement?.currentTime || 0),\r\n duration: Math.floor(duration || 0),\r\n });\r\n } catch (error) {\r\n debug.error(\"[Audience Tracking] Error sending ping:\", error);\r\n }\r\n },\r\n [audienceId, sessionId, audioElement, duration, client]\r\n );\r\n\r\n /**\r\n * Determine which URL and type to use for playback\r\n */\r\n const getPlaybackInfo = () => {\r\n // Live HLS streams - use direct CloudFront URL\r\n if (broadcast.broadcastStatus === 1) {\r\n if (broadcast.hlsPlaylistUrl) {\r\n return { url: broadcast.hlsPlaylistUrl, type: \"hls\" };\r\n }\r\n if (broadcast.hash && broadcast.app?.s3Hash) {\r\n const hlsUrl = buildBroadcastCdnUrl(\r\n broadcast.app.s3Hash,\r\n broadcast.hash,\r\n \"index.m3u8\"\r\n );\r\n return { url: hlsUrl, type: \"hls\" };\r\n }\r\n }\r\n\r\n // MP4 recordings - use secure playback endpoint\r\n // ReactPlayer will follow the 307 redirect to the presigned S3 URL\r\n if (broadcast.recordingMp4Url && broadcast.isVideo && broadcast.hash) {\r\n return {\r\n url: buildPlaybackUrl(broadcast.id, broadcast.hash),\r\n type: \"mp4\",\r\n };\r\n }\r\n\r\n // MP3 recordings - use secure playback endpoint\r\n // ReactPlayer will follow the 307 redirect to the presigned S3 URL\r\n if (broadcast.recordingMp3Url && broadcast.hash) {\r\n return {\r\n url: buildPlaybackUrl(broadcast.id, broadcast.hash),\r\n type: \"mp3\",\r\n };\r\n }\r\n\r\n // Offline HLS - use direct CloudFront URL\r\n if (broadcast.hlsPlaylistUrl) {\r\n return { url: broadcast.hlsPlaylistUrl, type: \"hls\" };\r\n }\r\n\r\n return null;\r\n };\r\n\r\n // Initialize playback info on first render\r\n useEffect(() => {\r\n if (!currentPlaybackInfo) {\r\n const info = getPlaybackInfo();\r\n setCurrentPlaybackInfo(info);\r\n initialPlaybackTypeRef.current = info?.type || null;\r\n\r\n // Set expiration time for presigned URLs\r\n if (info && (info.type === \"mp4\" || info.type === \"mp3\")) {\r\n const expiresAt = new Date(Date.now() + URL_EXPIRATION_MS);\r\n setUrlExpiresAt(expiresAt);\r\n debug.log(\r\n `[URL Refresh] Initial ${\r\n info.type\r\n } URL expires at ${expiresAt.toISOString()}`\r\n );\r\n }\r\n\r\n // Auto-play when component mounts\r\n if (info) {\r\n setPlaying(true);\r\n setIsLoadingVideo(true);\r\n }\r\n }\r\n }, [currentPlaybackInfo]);\r\n\r\n // Reset loading state when playback URL changes\r\n useEffect(() => {\r\n if (currentPlaybackInfo?.url) {\r\n setIsLoadingVideo(true);\r\n }\r\n }, [currentPlaybackInfo?.url]);\r\n\r\n // Proactively refresh presigned URLs before they expire\r\n useEffect(() => {\r\n if (!urlExpiresAt || !currentPlaybackInfo?.type) return;\r\n\r\n const checkExpiration = () => {\r\n const now = new Date();\r\n const timeUntilExpiration = urlExpiresAt.getTime() - now.getTime();\r\n\r\n if (\r\n timeUntilExpiration <= REFRESH_THRESHOLD_MS &&\r\n timeUntilExpiration > 0\r\n ) {\r\n debug.log(\"[URL Refresh] Proactively refreshing URL before expiration\");\r\n\r\n const fileType = currentPlaybackInfo.type;\r\n if (fileType === \"mp4\" || fileType === \"mp3\" || fileType === \"hls\") {\r\n refreshPresignedUrl(fileType);\r\n }\r\n }\r\n };\r\n\r\n const interval = setInterval(checkExpiration, REFRESH_CHECK_INTERVAL_MS);\r\n checkExpiration();\r\n\r\n return () => {\r\n clearInterval(interval);\r\n };\r\n }, [urlExpiresAt, currentPlaybackInfo?.type, refreshPresignedUrl]);\r\n\r\n // When live HLS stream ends and MP3 is available, switch to MP3\r\n useEffect(() => {\r\n if (\r\n initialPlaybackTypeRef.current === \"hls\" &&\r\n currentPlaybackInfo?.type === \"hls\" &&\r\n broadcast.broadcastStatus !== 1 &&\r\n broadcast.recordingMp3Url &&\r\n broadcast.hash &&\r\n parseInt(broadcast.mp3Size || \"0\") > 0\r\n ) {\r\n const secureUrl = buildPlaybackUrl(broadcast.id, broadcast.hash);\r\n setCurrentPlaybackInfo({ url: secureUrl, type: \"mp3\" });\r\n setAudioElement(null);\r\n setPlaying(true);\r\n }\r\n }, [\r\n broadcast.broadcastStatus,\r\n broadcast.recordingMp3Url,\r\n broadcast.mp3Size,\r\n broadcast.hash,\r\n broadcast.id,\r\n currentPlaybackInfo,\r\n ]);\r\n\r\n const playbackUrl = currentPlaybackInfo?.url || null;\r\n const playbackType = currentPlaybackInfo?.type || null;\r\n const isAudioOnly =\r\n playbackType === \"mp3\" || (!broadcast.isVideo && playbackType !== \"mp4\");\r\n const isLiveStream =\r\n broadcast.broadcastStatus === 1 &&\r\n playbackType === \"hls\" &&\r\n !hasStreamEnded;\r\n const wasLiveStream = initialPlaybackTypeRef.current === \"hls\";\r\n\r\n // ReactPlayer config - enables HLS live streaming with low latency mode\r\n // Type assertion needed as react-player types are incomplete for HLS options\r\n const playerConfig = useMemo(\r\n () =>\r\n ({\r\n file: {\r\n forceHLS: playbackType === \"hls\",\r\n hlsOptions: isLiveStream\r\n ? {\r\n maxLoadingDelay: 10,\r\n minAutoBitrate: 0,\r\n lowLatencyMode: true,\r\n enableWorker: true,\r\n }\r\n : {},\r\n },\r\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n } as any),\r\n [playbackType, isLiveStream]\r\n );\r\n\r\n /**\r\n * Format time as HH:MM:SS for transcript timestamps\r\n */\r\n const formatTimestamp = (seconds: number) => {\r\n if (!seconds || isNaN(seconds) || !isFinite(seconds)) return \"00:00:00\";\r\n const hrs = Math.floor(seconds / 3600);\r\n const mins = Math.floor((seconds % 3600) / 60);\r\n const secs = Math.floor(seconds % 60);\r\n return `${hrs.toString().padStart(2, \"0\")}:${mins\r\n .toString()\r\n .padStart(2, \"0\")}:${secs.toString().padStart(2, \"0\")}`;\r\n };\r\n\r\n const handlePlay = () => {\r\n setPlaying(true);\r\n setIsLoadingVideo(false);\r\n };\r\n\r\n const handlePause = () => {\r\n setPlaying(false);\r\n };\r\n\r\n const handleEnded = () => {\r\n setPlaying(false);\r\n if (playbackType === \"hls\") {\r\n setHasStreamEnded(true);\r\n }\r\n if (!wasLiveStream) {\r\n setHasEnded(true);\r\n }\r\n };\r\n\r\n // Initialize duration from broadcast data\r\n useEffect(() => {\r\n if (broadcast.durationSeconds && broadcast.durationSeconds > 0) {\r\n setDuration(broadcast.durationSeconds);\r\n }\r\n }, [broadcast.durationSeconds]);\r\n\r\n // Auto-play live streams\r\n useEffect(() => {\r\n if (isLiveStream && !playing) {\r\n setPlaying(true);\r\n }\r\n }, [isLiveStream, playing]);\r\n\r\n // Initialize audience tracking session\r\n useEffect(() => {\r\n if (currentPlaybackInfo && audioElement && !hasInitializedSession.current) {\r\n initializeTrackingSession();\r\n }\r\n }, [currentPlaybackInfo, audioElement, initializeTrackingSession]);\r\n\r\n // Set up heartbeat interval when playing\r\n useEffect(() => {\r\n if (playing && audienceId) {\r\n sendTrackingPing(1); // PLAY_START\r\n\r\n heartbeatIntervalRef.current = setInterval(() => {\r\n sendTrackingPing(2); // HEARTBEAT\r\n }, 15000);\r\n\r\n return () => {\r\n if (heartbeatIntervalRef.current) {\r\n clearInterval(heartbeatIntervalRef.current);\r\n heartbeatIntervalRef.current = null;\r\n }\r\n };\r\n } else if (!playing && audienceId) {\r\n sendTrackingPing(0); // PAUSE_STOP\r\n\r\n if (heartbeatIntervalRef.current) {\r\n clearInterval(heartbeatIntervalRef.current);\r\n heartbeatIntervalRef.current = null;\r\n }\r\n }\r\n }, [playing, audienceId, sendTrackingPing]);\r\n\r\n // Send unmount event\r\n useEffect(() => {\r\n return () => {\r\n if (audienceId && sessionId && sessionToken) {\r\n const payload = {\r\n audienceId,\r\n sessionId,\r\n eventType: 3, // UNMOUNT\r\n currentTime: Math.floor(audioElement?.currentTime || 0),\r\n duration: Math.floor(duration || 0),\r\n };\r\n\r\n const headers = {\r\n Authorization: `Bearer ${sessionToken}`,\r\n \"Content-Type\": \"application/json\",\r\n };\r\n // Note: sendBeacon doesn't support custom headers, so we use fetch with keepalive\r\n fetch(ENDPOINTS.sessionPing, {\r\n method: \"POST\",\r\n headers,\r\n body: JSON.stringify(payload),\r\n keepalive: true,\r\n }).catch(() => {\r\n // Silently fail - component is unmounting\r\n });\r\n }\r\n };\r\n }, [audienceId, sessionId, sessionToken, audioElement, duration]);\r\n\r\n // Fetch transcript\r\n useEffect(() => {\r\n if (\r\n broadcast.transcriptUrl &&\r\n broadcast.transcriptStatus === 2 &&\r\n !transcriptData\r\n ) {\r\n setIsLoadingTranscript(true);\r\n fetch(broadcast.transcriptUrl)\r\n .then((res) => {\r\n if (!res.ok) {\r\n throw new Error(\r\n `Failed to fetch transcript: ${res.status} ${res.statusText}`\r\n );\r\n }\r\n return res.json();\r\n })\r\n .then((data) => {\r\n // Assign words to segments if needed\r\n if (data.segments && data.words && !data.segments[0]?.words) {\r\n data.segments = data.segments.map((segment: any, index: number) => {\r\n const segmentWords = data.words!.filter((word: any) => {\r\n if (index === data.segments!.length - 1) {\r\n return word.start >= segment.start;\r\n }\r\n return word.start >= segment.start && word.start < segment.end;\r\n });\r\n return {\r\n ...segment,\r\n words: segmentWords,\r\n };\r\n });\r\n }\r\n\r\n setTranscriptData(data);\r\n setIsLoadingTranscript(false);\r\n })\r\n .catch((error) => {\r\n debug.error(\"[Transcript] Failed to load transcript:\", error);\r\n setIsLoadingTranscript(false);\r\n });\r\n }\r\n }, [broadcast.transcriptUrl, broadcast.transcriptStatus, transcriptData]);\r\n\r\n // Update current time\r\n useEffect(() => {\r\n if (!audioElement) return;\r\n\r\n const handleTimeUpdate = () => {\r\n setCurrentTime(audioElement.currentTime);\r\n };\r\n\r\n audioElement.addEventListener(\"timeupdate\", handleTimeUpdate);\r\n return () =>\r\n audioElement.removeEventListener(\"timeupdate\", handleTimeUpdate);\r\n }, [audioElement]);\r\n\r\n // Auto-scroll to active word\r\n useEffect(() => {\r\n if (\r\n showTranscript &&\r\n autoScrollEnabled &&\r\n activeWordRef.current &&\r\n transcriptContainerRef.current\r\n ) {\r\n const container = transcriptContainerRef.current;\r\n const activeWord = activeWordRef.current;\r\n const containerRect = container.getBoundingClientRect();\r\n const wordRect = activeWord.getBoundingClientRect();\r\n\r\n if (\r\n wordRect.top < containerRect.top ||\r\n wordRect.bottom > containerRect.bottom\r\n ) {\r\n isScrollingProgrammatically.current = true;\r\n activeWord.scrollIntoView({ behavior: \"smooth\", block: \"center\" });\r\n\r\n setTimeout(() => {\r\n isScrollingProgrammatically.current = false;\r\n }, 500);\r\n }\r\n }\r\n }, [currentTime, showTranscript, autoScrollEnabled]);\r\n\r\n // Detect manual scrolling\r\n useEffect(() => {\r\n if (!showTranscript || !transcriptContainerRef.current) return;\r\n\r\n const container = transcriptContainerRef.current;\r\n\r\n const handleScroll = () => {\r\n if (!isScrollingProgrammatically.current && autoScrollEnabled) {\r\n setAutoScrollEnabled(false);\r\n }\r\n };\r\n\r\n container.addEventListener(\"scroll\", handleScroll, { passive: true });\r\n return () => container.removeEventListener(\"scroll\", handleScroll);\r\n }, [showTranscript, autoScrollEnabled]);\r\n\r\n const handlePlayPause = () => {\r\n if (hasEnded) {\r\n if (audioElement) {\r\n audioElement.currentTime = 0;\r\n }\r\n setHasEnded(false);\r\n }\r\n setPlaying(!playing);\r\n };\r\n\r\n const handleRestart = () => {\r\n if (audioElement) {\r\n audioElement.currentTime = 0;\r\n }\r\n setHasEnded(false);\r\n setPlaying(true);\r\n };\r\n\r\n const handleVideoClick = () => {\r\n if (!isLiveStream) {\r\n handlePlayPause();\r\n }\r\n };\r\n\r\n const handleSeekChange = (e: React.ChangeEvent<HTMLInputElement>) => {\r\n const newValue = parseFloat(e.target.value);\r\n setPlayed(newValue);\r\n };\r\n\r\n const handleSeekMouseDown = () => {\r\n setSeeking(true);\r\n };\r\n\r\n const handleSeekMouseUp = (e: React.MouseEvent<HTMLInputElement>) => {\r\n const seekValue = parseFloat((e.target as HTMLInputElement).value);\r\n setSeeking(false);\r\n\r\n if (audioElement && duration > 0) {\r\n const seekTime = seekValue * duration;\r\n audioElement.currentTime = seekTime;\r\n setHasEnded(false);\r\n }\r\n };\r\n\r\n const handleSeekTouchStart = () => {\r\n setSeeking(true);\r\n };\r\n\r\n const handleSeekTouchEnd = (e: React.TouchEvent<HTMLInputElement>) => {\r\n const seekValue = parseFloat((e.target as HTMLInputElement).value);\r\n setSeeking(false);\r\n\r\n if (audioElement && duration > 0) {\r\n const seekTime = seekValue * duration;\r\n audioElement.currentTime = seekTime;\r\n setHasEnded(false);\r\n }\r\n };\r\n\r\n const handleTimeUpdate = (e: React.SyntheticEvent<HTMLVideoElement>) => {\r\n if (!seeking) {\r\n const video = e.currentTarget;\r\n const playedFraction =\r\n video.duration > 0 ? video.currentTime / video.duration : 0;\r\n setPlayed(playedFraction);\r\n }\r\n };\r\n\r\n const handleLoadedMetadata = (e: React.SyntheticEvent<HTMLVideoElement>) => {\r\n const video = e.currentTarget;\r\n setAudioElement(video);\r\n\r\n if (video.duration && !isNaN(video.duration) && video.duration > 0) {\r\n setDuration(video.duration);\r\n } else if (broadcast.durationSeconds && broadcast.durationSeconds > 0) {\r\n setDuration(broadcast.durationSeconds);\r\n }\r\n };\r\n\r\n const handlePlayerReady = (player?: any) => {\r\n try {\r\n const internalPlayer = player?.getInternalPlayer?.();\r\n\r\n if (internalPlayer && internalPlayer instanceof HTMLMediaElement) {\r\n setAudioElement(internalPlayer);\r\n }\r\n } catch (error) {\r\n debug.error(\"[DialtribePlayer] Error getting internal player:\", error);\r\n }\r\n };\r\n\r\n // Audio element detection\r\n useEffect(() => {\r\n const findAudioElement = () => {\r\n const videoElements = document.querySelectorAll(\"video, audio\");\r\n\r\n if (videoElements.length > 0) {\r\n const element = videoElements[0] as HTMLVideoElement;\r\n setAudioElement(element);\r\n return true;\r\n }\r\n return false;\r\n };\r\n\r\n if (!findAudioElement()) {\r\n const retryIntervals = [\r\n 100, 300, 500, 1000, 1500, 2000, 3000, 4000, 5000,\r\n ];\r\n const timeouts = retryIntervals.map((delay) =>\r\n setTimeout(() => {\r\n findAudioElement();\r\n }, delay)\r\n );\r\n\r\n return () => timeouts.forEach(clearTimeout);\r\n }\r\n }, [playbackUrl]);\r\n\r\n useEffect(() => {\r\n if (playing && !audioElement) {\r\n const videoElements = document.querySelectorAll(\"video, audio\");\r\n if (videoElements.length > 0) {\r\n const element = videoElements[0] as HTMLVideoElement;\r\n setAudioElement(element);\r\n }\r\n }\r\n }, [playing, audioElement]);\r\n\r\n const handleVolumeChange = (e: React.ChangeEvent<HTMLInputElement>) => {\r\n setVolume(parseFloat(e.target.value));\r\n };\r\n\r\n const toggleMute = () => {\r\n setMuted(!muted);\r\n };\r\n\r\n const toggleFullscreen = async () => {\r\n try {\r\n if (document.fullscreenElement) {\r\n await document.exitFullscreen();\r\n return;\r\n }\r\n\r\n let videoElement = null;\r\n\r\n if (\r\n playerRef.current &&\r\n typeof playerRef.current.getInternalPlayer === \"function\"\r\n ) {\r\n videoElement = playerRef.current.getInternalPlayer();\r\n }\r\n\r\n if (\r\n !videoElement ||\r\n typeof videoElement.requestFullscreen !== \"function\"\r\n ) {\r\n const videoElements = document.querySelectorAll(\"video\");\r\n if (videoElements.length > 0) {\r\n videoElement = videoElements[0];\r\n }\r\n }\r\n\r\n if (\r\n !videoElement ||\r\n typeof videoElement.requestFullscreen !== \"function\"\r\n ) {\r\n const modalElement = document.querySelector(\".aspect-video\");\r\n if (\r\n modalElement &&\r\n typeof (modalElement as HTMLElement).requestFullscreen === \"function\"\r\n ) {\r\n await (modalElement as HTMLElement).requestFullscreen();\r\n return;\r\n }\r\n }\r\n\r\n if (\r\n videoElement &&\r\n typeof videoElement.requestFullscreen === \"function\"\r\n ) {\r\n await videoElement.requestFullscreen();\r\n }\r\n } catch (error) {\r\n debug.error(\"Error toggling fullscreen:\", error);\r\n }\r\n };\r\n\r\n const handleError = async (error: any) => {\r\n debug.error(\"Media playback error:\", error);\r\n\r\n const isPotentialExpiration =\r\n error?.code === HTTP_STATUS.FORBIDDEN ||\r\n error?.status === HTTP_STATUS.FORBIDDEN ||\r\n error?.statusCode === HTTP_STATUS.FORBIDDEN ||\r\n error?.code === HTTP_STATUS.NOT_FOUND ||\r\n error?.status === HTTP_STATUS.NOT_FOUND ||\r\n error?.statusCode === HTTP_STATUS.NOT_FOUND ||\r\n error?.message?.includes(\"403\") ||\r\n error?.message?.includes(\"404\") ||\r\n error?.message?.includes(\"Forbidden\") ||\r\n error?.message?.toLowerCase().includes(\"network\") ||\r\n error?.type === \"network\" ||\r\n error?.message?.includes(\"MEDIA_ERR_SRC_NOT_SUPPORTED\");\r\n\r\n if (\r\n isPotentialExpiration &&\r\n currentPlaybackInfo?.type &&\r\n !isRefreshingUrl.current\r\n ) {\r\n debug.log(\r\n \"[Player Error] Detected potential URL expiration, attempting refresh...\"\r\n );\r\n\r\n const currentPosition = audioElement?.currentTime || 0;\r\n const wasPlaying = playing;\r\n\r\n const fileType = currentPlaybackInfo.type;\r\n if (fileType !== \"mp4\" && fileType !== \"mp3\" && fileType !== \"hls\") {\r\n debug.error(\r\n \"[Player Error] Invalid file type, cannot refresh:\",\r\n fileType\r\n );\r\n } else {\r\n const refreshed = await refreshPresignedUrl(fileType);\r\n\r\n if (refreshed) {\r\n debug.log(\r\n \"[Player Error] URL refreshed successfully, resuming playback\"\r\n );\r\n setTimeout(() => {\r\n if (audioElement && currentPosition > 0) {\r\n audioElement.currentTime = currentPosition;\r\n }\r\n if (wasPlaying) {\r\n setPlaying(true);\r\n }\r\n }, PLAYBACK_RESUME_DELAY_MS);\r\n return;\r\n }\r\n }\r\n }\r\n\r\n setHasError(true);\r\n setPlaying(false);\r\n setIsLoadingVideo(false);\r\n\r\n // Use the improved error message helper\r\n setErrorMessage(getErrorMessage(error));\r\n\r\n if (onError && error instanceof Error) {\r\n onError(error);\r\n }\r\n };\r\n\r\n const handleRetry = useCallback(() => {\r\n setHasError(false);\r\n setErrorMessage(\"\");\r\n setIsLoadingVideo(true);\r\n\r\n // Force reinitialize playback\r\n const info = getPlaybackInfo();\r\n if (info) {\r\n setCurrentPlaybackInfo(null); // Force re-render\r\n setTimeout(() => {\r\n setCurrentPlaybackInfo(info);\r\n setPlaying(true);\r\n }, 100);\r\n }\r\n }, [broadcast]);\r\n\r\n const handleWordClick = (startTime: number) => {\r\n if (audioElement) {\r\n audioElement.currentTime = startTime;\r\n setPlayed(startTime / duration);\r\n setHasEnded(false);\r\n if (!playing) {\r\n setPlaying(true);\r\n }\r\n }\r\n };\r\n\r\n /**\r\n * Keyboard shortcuts effect\r\n *\r\n * Listens for keyboard events when enableKeyboardShortcuts is true.\r\n * Prevents interference with form inputs, contenteditable elements, and modifier key combinations.\r\n *\r\n * Supported shortcuts:\r\n * - Space/K: Play/Pause\r\n * - Arrow Left/Right: Seek backward/forward 5 seconds\r\n * - Arrow Up/Down: Volume up/down 10%\r\n * - M: Mute toggle\r\n * - F: Fullscreen (video only)\r\n * - 0/Home: Jump to start\r\n * - End: Jump to end\r\n */\r\n useEffect(() => {\r\n // Skip if keyboard shortcuts are disabled\r\n if (!enableKeyboardShortcuts) return;\r\n\r\n /**\r\n * Seek by a relative number of seconds\r\n * @param seconds - Number of seconds to seek (negative for backward, positive for forward)\r\n */\r\n const seekBy = (seconds: number) => {\r\n if (!audioElement || duration <= 0) return;\r\n const newTime = Math.max(\r\n 0,\r\n Math.min(duration, audioElement.currentTime + seconds)\r\n );\r\n audioElement.currentTime = newTime;\r\n setPlayed(newTime / duration);\r\n };\r\n\r\n const handleKeyDown = (e: KeyboardEvent) => {\r\n const target = e.target as HTMLElement;\r\n\r\n // Don't interfere with typing in inputs, textareas, or contenteditable elements\r\n if (\r\n target instanceof HTMLInputElement ||\r\n target instanceof HTMLTextAreaElement ||\r\n target.contentEditable === \"true\" ||\r\n target.getAttribute(\"role\") === \"textbox\"\r\n ) {\r\n return;\r\n }\r\n\r\n // Don't handle if a modifier key is pressed\r\n if (e.ctrlKey || e.metaKey || e.altKey) {\r\n return;\r\n }\r\n\r\n switch (e.key) {\r\n case \" \":\r\n case \"k\":\r\n case \"K\":\r\n e.preventDefault();\r\n handlePlayPause();\r\n break;\r\n\r\n case \"ArrowLeft\":\r\n e.preventDefault();\r\n seekBy(-5);\r\n break;\r\n\r\n case \"ArrowRight\":\r\n e.preventDefault();\r\n seekBy(5);\r\n break;\r\n\r\n case \"ArrowUp\":\r\n e.preventDefault();\r\n setVolume((prev) => Math.min(1, prev + 0.1));\r\n if (muted) setMuted(false);\r\n break;\r\n\r\n case \"ArrowDown\":\r\n e.preventDefault();\r\n setVolume((prev) => Math.max(0, prev - 0.1));\r\n break;\r\n\r\n case \"m\":\r\n case \"M\":\r\n e.preventDefault();\r\n toggleMute();\r\n break;\r\n\r\n case \"f\":\r\n case \"F\":\r\n if (!isAudioOnly) {\r\n e.preventDefault();\r\n toggleFullscreen();\r\n }\r\n break;\r\n\r\n case \"0\":\r\n case \"Home\":\r\n e.preventDefault();\r\n if (audioElement && duration > 0) {\r\n audioElement.currentTime = 0;\r\n setPlayed(0);\r\n setHasEnded(false);\r\n }\r\n break;\r\n\r\n case \"End\":\r\n e.preventDefault();\r\n if (audioElement && duration > 0) {\r\n audioElement.currentTime = duration - 1;\r\n setPlayed((duration - 1) / duration);\r\n }\r\n break;\r\n\r\n default:\r\n break;\r\n }\r\n };\r\n\r\n window.addEventListener(\"keydown\", handleKeyDown);\r\n return () => window.removeEventListener(\"keydown\", handleKeyDown);\r\n }, [\r\n enableKeyboardShortcuts,\r\n audioElement,\r\n duration,\r\n playing,\r\n muted,\r\n isAudioOnly,\r\n handlePlayPause,\r\n toggleMute,\r\n toggleFullscreen,\r\n ]);\r\n\r\n // Show error if no playback URL after initialization\r\n if (currentPlaybackInfo !== null && !playbackUrl) {\r\n return (\r\n <div className=\"bg-white dark:bg-zinc-900 rounded-lg p-6 max-w-md w-full mx-4 border border-gray-200 dark:border-zinc-800\">\r\n <h3 className=\"text-lg font-bold text-black dark:text-white mb-4\">\r\n Broadcast Unavailable\r\n </h3>\r\n <p className=\"text-gray-600 dark:text-gray-400\">\r\n No playback URL available for this broadcast. The recording may still\r\n be processing.\r\n </p>\r\n </div>\r\n );\r\n }\r\n\r\n // Show loading state\r\n if (!playbackUrl) {\r\n return (\r\n <div className=\"flex items-center justify-center p-8\">\r\n <LoadingSpinner variant=\"white\" text=\"Loading...\" />\r\n </div>\r\n );\r\n }\r\n\r\n const hasTranscript =\r\n broadcast.transcriptStatus === 2 &&\r\n transcriptData &&\r\n ((transcriptData.segments &&\r\n transcriptData.segments.some((s) => s.words && s.words.length > 0)) ||\r\n (transcriptData.words && transcriptData.words.length > 0));\r\n\r\n // The core player content\r\n const playerContent = (\r\n <div\r\n className={`bg-black rounded-lg shadow-2xl w-full max-h-full flex flex-col overflow-hidden ${className}`}\r\n >\r\n {/* Header */}\r\n <div className=\"bg-zinc-900/50 backdrop-blur-sm border-b border-zinc-800 px-3 sm:px-4 md:px-6 py-2 sm:py-3 md:py-4 flex justify-between items-center rounded-t-lg shrink-0\">\r\n <div>\r\n <h3 className=\"text-lg font-semibold text-white\">\r\n {broadcast.streamKeyRecord?.foreignName || \"Broadcast\"}\r\n </h3>\r\n <p className=\"text-sm text-gray-400\">\r\n {broadcast.isVideo ? \"Video\" : \"Audio\"} •{\" \"}\r\n {broadcast.broadcastStatus === 1 ? (\r\n <span className=\"text-red-500 font-semibold\">🔴 LIVE</span>\r\n ) : playbackType === \"hls\" ? (\r\n <span className=\"text-gray-500 font-semibold\">OFFLINE</span>\r\n ) : (\r\n formatTime(duration)\r\n )}\r\n </p>\r\n </div>\r\n <div className=\"flex items-center gap-3\">\r\n {renderClipCreator &&\r\n playbackType !== \"hls\" &&\r\n appId &&\r\n contentId &&\r\n duration > 0 && (\r\n <button\r\n onClick={() => setShowClipCreator(true)}\r\n className=\"px-3 md:px-4 py-1.5 md:py-2 bg-blue-600 hover:bg-blue-700 text-white text-xs md:text-sm font-medium rounded-lg transition-colors flex items-center gap-1 md:gap-2\"\r\n title=\"Create a clip from this broadcast\"\r\n aria-label=\"Create clip from broadcast\"\r\n >\r\n <svg\r\n className=\"w-3 h-3 md:w-4 md:h-4\"\r\n fill=\"none\"\r\n stroke=\"currentColor\"\r\n viewBox=\"0 0 24 24\"\r\n >\r\n <path\r\n strokeLinecap=\"round\"\r\n strokeLinejoin=\"round\"\r\n strokeWidth={2}\r\n d=\"M14.752 11.168l-3.197-2.132A1 1 0 0010 9.87v4.263a1 1 0 001.555.832l3.197-2.132a1 1 0 000-1.664z\"\r\n />\r\n <path\r\n strokeLinecap=\"round\"\r\n strokeLinejoin=\"round\"\r\n strokeWidth={2}\r\n d=\"M21 12a9 9 0 11-18 0 9 9 0 0118 0z\"\r\n />\r\n </svg>\r\n <span className=\"hidden sm:inline\">Create Clip</span>\r\n <span className=\"sm:hidden\">Clip</span>\r\n </button>\r\n )}\r\n </div>\r\n </div>\r\n\r\n {/* Main Content Area - Player + Transcript */}\r\n <div className=\"flex flex-col md:flex-row flex-1 min-h-0 overflow-hidden\">\r\n {/* Player Container */}\r\n <div className=\"shrink-0 md:shrink md:flex-1 flex flex-col overflow-hidden\">\r\n {/* Player Area */}\r\n <div\r\n className={`relative ${\r\n isAudioOnly\r\n ? \"bg-linear-to-br from-zinc-900 via-zinc-800 to-zinc-900 flex items-stretch\"\r\n : \"bg-black\"\r\n }`}\r\n >\r\n {isAudioOnly ? (\r\n <div\r\n className=\"relative cursor-pointer w-full flex flex-col\"\r\n onClick={handleVideoClick}\r\n >\r\n {!hasError ? (\r\n <>\r\n <div className=\"w-full h-full relative\">\r\n <AudioWaveform\r\n audioElement={audioElement}\r\n isPlaying={isLiveStream ? true : playing}\r\n isLive={isLiveStream}\r\n />\r\n {isLoadingVideo && !hasError && (\r\n <div className=\"absolute inset-0 bg-black/90 flex items-center justify-center z-20\">\r\n <LoadingSpinner variant=\"white\" />\r\n </div>\r\n )}\r\n {hasEnded && !wasLiveStream && (\r\n <div className=\"absolute inset-0 bg-black/50 flex items-center justify-center z-20 pointer-events-auto\">\r\n <button\r\n onClick={(e) => {\r\n e.stopPropagation();\r\n handleRestart();\r\n }}\r\n className=\"bg-white hover:bg-blue-500 text-black hover:text-white font-semibold py-4 px-8 rounded-full transition-all transform hover:scale-105 flex items-center gap-3\"\r\n aria-label=\"Restart playback from beginning\"\r\n >\r\n <svg\r\n className=\"w-6 h-6\"\r\n fill=\"currentColor\"\r\n viewBox=\"0 0 20 20\"\r\n >\r\n <path\r\n fillRule=\"evenodd\"\r\n d=\"M4 2a1 1 0 011 1v2.101a7.002 7.002 0 0111.601 2.566 1 1 0 11-1.885.666A5.002 5.002 0 005.999 7H9a1 1 0 010 2H4a1 1 0 01-1-1V3a1 1 0 011-1zm.008 9.057a1 1 0 011.276.61A5.002 5.002 0 0014.001 13H11a1 1 0 110-2h5a1 1 0 011 1v5a1 1 0 11-2 0v-2.101a7.002 7.002 0 01-11.601-2.566 1 1 0 01.61-1.276z\"\r\n clipRule=\"evenodd\"\r\n />\r\n </svg>\r\n Restart\r\n </button>\r\n </div>\r\n )}\r\n </div>\r\n </>\r\n ) : (\r\n <div className=\"w-full h-full flex items-center justify-center\">\r\n <div className=\"text-center max-w-md px-4\">\r\n <div className=\"text-6xl mb-4\">⚠️</div>\r\n <h3 className=\"text-xl font-semibold text-white mb-3\">\r\n Playback Error\r\n </h3>\r\n <p className=\"text-gray-300 text-sm mb-6\">\r\n {errorMessage}\r\n </p>\r\n <button\r\n onClick={handleRetry}\r\n className=\"px-6 py-3 bg-blue-600 hover:bg-blue-700 text-white font-medium rounded-lg transition-colors inline-flex items-center gap-2\"\r\n aria-label=\"Retry playback\"\r\n >\r\n <svg\r\n className=\"w-5 h-5\"\r\n fill=\"none\"\r\n stroke=\"currentColor\"\r\n viewBox=\"0 0 24 24\"\r\n >\r\n <path\r\n strokeLinecap=\"round\"\r\n strokeLinejoin=\"round\"\r\n strokeWidth={2}\r\n d=\"M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15\"\r\n />\r\n </svg>\r\n Retry\r\n </button>\r\n </div>\r\n </div>\r\n )}\r\n </div>\r\n ) : (\r\n <div className=\"aspect-video relative\">\r\n <div onClick={handleVideoClick} className=\"cursor-pointer\">\r\n <ReactPlayer\r\n key={playbackUrl || \"no-url\"}\r\n ref={playerRef}\r\n src={playbackUrl || undefined}\r\n playing={playing}\r\n volume={volume}\r\n muted={muted}\r\n width=\"100%\"\r\n height=\"100%\"\r\n crossOrigin=\"anonymous\"\r\n config={playerConfig}\r\n onReady={handlePlayerReady}\r\n onTimeUpdate={handleTimeUpdate}\r\n onLoadedMetadata={handleLoadedMetadata}\r\n onPlay={handlePlay}\r\n onPause={handlePause}\r\n onEnded={handleEnded}\r\n onError={handleError}\r\n style={{ backgroundColor: \"#000\" }}\r\n />\r\n </div>\r\n {isLoadingVideo && !hasError && (\r\n <div className=\"absolute inset-0 bg-black/90 flex items-center justify-center\">\r\n <LoadingSpinner variant=\"white\" />\r\n </div>\r\n )}\r\n {hasEnded && !hasError && (\r\n <div className=\"absolute inset-0 bg-black/50 flex items-center justify-center\">\r\n <button\r\n onClick={(e) => {\r\n e.stopPropagation();\r\n handleRestart();\r\n }}\r\n className=\"bg-white hover:bg-blue-500 text-black hover:text-white font-semibold py-4 px-8 rounded-full transition-all transform hover:scale-105 flex items-center gap-3\"\r\n aria-label=\"Restart playback from beginning\"\r\n >\r\n <svg\r\n className=\"w-6 h-6\"\r\n fill=\"currentColor\"\r\n viewBox=\"0 0 20 20\"\r\n aria-hidden=\"true\"\r\n >\r\n <path\r\n fillRule=\"evenodd\"\r\n d=\"M4 2a1 1 0 011 1v2.101a7.002 7.002 0 0111.601 2.566 1 1 0 11-1.885.666A5.002 5.002 0 005.999 7H9a1 1 0 010 2H4a1 1 0 01-1-1V3a1 1 0 011-1zm.008 9.057a1 1 0 011.276.61A5.002 5.002 0 0014.001 13H11a1 1 0 110-2h5a1 1 0 011 1v5a1 1 0 11-2 0v-2.101a7.002 7.002 0 01-11.601-2.566 1 1 0 01.61-1.276z\"\r\n clipRule=\"evenodd\"\r\n />\r\n </svg>\r\n Restart\r\n </button>\r\n </div>\r\n )}\r\n {hasError && (\r\n <div className=\"absolute inset-0 bg-black/90 flex items-center justify-center p-8\">\r\n <div className=\"text-center max-w-md\">\r\n <div className=\"text-6xl mb-4\">⚠️</div>\r\n <h3 className=\"text-xl font-semibold text-white mb-3\">\r\n Playback Error\r\n </h3>\r\n <p className=\"text-gray-300 text-sm mb-6\">\r\n {errorMessage}\r\n </p>\r\n <button\r\n onClick={handleRetry}\r\n className=\"px-6 py-3 bg-blue-600 hover:bg-blue-700 text-white font-medium rounded-lg transition-colors inline-flex items-center gap-2\"\r\n aria-label=\"Retry playback\"\r\n >\r\n <svg\r\n className=\"w-5 h-5\"\r\n fill=\"none\"\r\n stroke=\"currentColor\"\r\n viewBox=\"0 0 24 24\"\r\n >\r\n <path\r\n strokeLinecap=\"round\"\r\n strokeLinejoin=\"round\"\r\n strokeWidth={2}\r\n d=\"M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15\"\r\n />\r\n </svg>\r\n Retry\r\n </button>\r\n </div>\r\n </div>\r\n )}\r\n </div>\r\n )}\r\n\r\n {/* Hidden audio player for audio-only */}\r\n {isAudioOnly && (\r\n <div className=\"hidden\">\r\n <ReactPlayer\r\n key={playbackUrl || \"no-url\"}\r\n ref={playerRef}\r\n src={playbackUrl || undefined}\r\n playing={playing}\r\n volume={volume}\r\n muted={muted}\r\n width=\"0\"\r\n height=\"0\"\r\n crossOrigin=\"anonymous\"\r\n config={playerConfig}\r\n onReady={handlePlayerReady}\r\n onTimeUpdate={handleTimeUpdate}\r\n onLoadedMetadata={handleLoadedMetadata}\r\n onPlay={handlePlay}\r\n onPause={handlePause}\r\n onEnded={handleEnded}\r\n onError={handleError}\r\n />\r\n </div>\r\n )}\r\n </div>\r\n\r\n {/* Custom Controls */}\r\n {!hasError &&\r\n !isLiveStream &&\r\n (wasLiveStream ? (\r\n parseInt(broadcast.mp3Size || \"0\") > 0 ||\r\n parseInt(broadcast.mp4Size || \"0\") > 0 ? (\r\n <div className=\"bg-zinc-900/50 backdrop-blur-sm px-4 md:px-6 py-3 md:py-4 rounded-b-lg\">\r\n {/* Progress Bar */}\r\n <div className=\"mb-4\">\r\n <input\r\n type=\"range\"\r\n min={0}\r\n max={0.999999}\r\n step=\"any\"\r\n value={played || 0}\r\n onMouseDown={handleSeekMouseDown}\r\n onMouseUp={handleSeekMouseUp}\r\n onTouchStart={handleSeekTouchStart}\r\n onTouchEnd={handleSeekTouchEnd}\r\n onChange={handleSeekChange}\r\n className=\"w-full h-1 bg-zinc-700 rounded-lg appearance-none cursor-pointer slider\"\r\n aria-label=\"Seek position\"\r\n aria-valuemin={0}\r\n aria-valuemax={duration}\r\n aria-valuenow={played * duration}\r\n aria-valuetext={`${formatTime(\r\n played * duration\r\n )} of ${formatTime(duration)}`}\r\n role=\"slider\"\r\n />\r\n <div className=\"flex justify-between text-xs text-gray-400 mt-1\">\r\n <span>{formatTime((played || 0) * duration)}</span>\r\n <span>{formatTime(duration)}</span>\r\n </div>\r\n </div>\r\n\r\n {/* Control Buttons */}\r\n <div className=\"flex items-center justify-between\">\r\n <div className=\"flex items-center gap-4\">\r\n {/* Play/Pause */}\r\n <button\r\n onClick={handlePlayPause}\r\n className=\"text-white hover:text-blue-400 transition-colors\"\r\n title={playing ? \"Pause\" : \"Play\"}\r\n aria-label={playing ? \"Pause\" : \"Play\"}\r\n aria-pressed={playing}\r\n >\r\n {playing ? (\r\n <svg\r\n className=\"w-8 h-8\"\r\n fill=\"currentColor\"\r\n viewBox=\"0 0 20 20\"\r\n aria-hidden=\"true\"\r\n >\r\n <path\r\n fillRule=\"evenodd\"\r\n d=\"M18 10a8 8 0 11-16 0 8 8 0 0116 0zM7 8a1 1 0 012 0v4a1 1 0 11-2 0V8zm5-1a1 1 0 00-1 1v4a1 1 0 102 0V8a1 1 0 00-1-1z\"\r\n clipRule=\"evenodd\"\r\n />\r\n </svg>\r\n ) : (\r\n <svg\r\n className=\"w-8 h-8\"\r\n fill=\"currentColor\"\r\n viewBox=\"0 0 20 20\"\r\n aria-hidden=\"true\"\r\n >\r\n <path\r\n fillRule=\"evenodd\"\r\n d=\"M10 18a8 8 0 100-16 8 8 0 000 16zM9.555 7.168A1 1 0 008 8v4a1 1 0 001.555.832l3-2a1 1 0 000-1.664l-3-2z\"\r\n clipRule=\"evenodd\"\r\n />\r\n </svg>\r\n )}\r\n </button>\r\n\r\n {/* Volume */}\r\n <div className=\"flex items-center gap-2\">\r\n <button\r\n onClick={toggleMute}\r\n className=\"text-white hover:text-blue-400 transition-colors\"\r\n title={muted ? \"Unmute\" : \"Mute\"}\r\n aria-label={muted ? \"Unmute\" : \"Mute\"}\r\n aria-pressed={muted}\r\n >\r\n {muted || volume === 0 ? (\r\n <svg\r\n className=\"w-5 h-5\"\r\n fill=\"currentColor\"\r\n viewBox=\"0 0 20 20\"\r\n >\r\n <path\r\n fillRule=\"evenodd\"\r\n d=\"M9.383 3.076A1 1 0 0110 4v12a1 1 0 01-1.707.707L4.586 13H2a1 1 0 01-1-1V8a1 1 0 011-1h2.586l3.707-3.707a1 1 0 011.09-.217zM12.293 7.293a1 1 0 011.414 0L15 8.586l1.293-1.293a1 1 0 111.414 1.414L16.414 10l1.293 1.293a1 1 0 01-1.414 1.414L15 11.414l-1.293 1.293a1 1 0 01-1.414-1.414L13.586 10l-1.293-1.293a1 1 0 010-1.414z\"\r\n clipRule=\"evenodd\"\r\n />\r\n </svg>\r\n ) : (\r\n <svg\r\n className=\"w-5 h-5\"\r\n fill=\"currentColor\"\r\n viewBox=\"0 0 20 20\"\r\n >\r\n <path\r\n fillRule=\"evenodd\"\r\n d=\"M9.383 3.076A1 1 0 0110 4v12a1 1 0 01-1.707.707L4.586 13H2a1 1 0 01-1-1V8a1 1 0 011-1h2.586l3.707-3.707a1 1 0 011.09-.217zM14.657 2.929a1 1 0 011.414 0A9.972 9.972 0 0119 10a9.972 9.972 0 01-2.929 7.071 1 1 0 01-1.414-1.414A7.971 7.971 0 0017 10c0-2.21-.894-4.208-2.343-5.657a1 1 0 010-1.414zm-2.829 2.828a1 1 0 011.415 0A5.983 5.983 0 0115 10a5.984 5.984 0 01-1.757 4.243 1 1 0 01-1.415-1.415A3.984 3.984 0 0013 10a3.983 3.983 0 00-1.172-2.828 1 1 0 010-1.415z\"\r\n clipRule=\"evenodd\"\r\n />\r\n </svg>\r\n )}\r\n </button>\r\n <input\r\n type=\"range\"\r\n min={0}\r\n max={1}\r\n step={0.01}\r\n value={muted ? 0 : volume || 1}\r\n onChange={handleVolumeChange}\r\n className=\"w-20 h-1 bg-zinc-700 rounded-lg appearance-none cursor-pointer slider\"\r\n aria-label=\"Volume\"\r\n aria-valuemin={0}\r\n aria-valuemax={100}\r\n aria-valuenow={muted ? 0 : Math.round(volume * 100)}\r\n aria-valuetext={\r\n muted ? \"Muted\" : `${Math.round(volume * 100)}%`\r\n }\r\n role=\"slider\"\r\n />\r\n </div>\r\n </div>\r\n\r\n {/* Fullscreen, Download, and Transcript buttons */}\r\n <div className=\"flex items-center gap-3\">\r\n {/* Download */}\r\n {!isLiveStream &&\r\n broadcast.hash &&\r\n (broadcast.recordingMp4Url ||\r\n broadcast.recordingMp3Url) && (\r\n <button\r\n onClick={() => {\r\n const downloadUrl = buildPlaybackUrl(\r\n broadcast.id,\r\n broadcast.hash!,\r\n \"download\"\r\n );\r\n window.open(downloadUrl, \"_blank\");\r\n }}\r\n className=\"text-white hover:text-blue-400 transition-colors\"\r\n title=\"Download Recording\"\r\n aria-label=\"Download recording\"\r\n >\r\n <svg\r\n className=\"w-5 h-5\"\r\n fill=\"none\"\r\n stroke=\"currentColor\"\r\n viewBox=\"0 0 24 24\"\r\n >\r\n <path\r\n strokeLinecap=\"round\"\r\n strokeLinejoin=\"round\"\r\n strokeWidth={2}\r\n d=\"M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4\"\r\n />\r\n </svg>\r\n </button>\r\n )}\r\n\r\n {/* Fullscreen */}\r\n {!isAudioOnly && (\r\n <button\r\n onClick={toggleFullscreen}\r\n className=\"text-white hover:text-blue-400 transition-colors\"\r\n title=\"Fullscreen\"\r\n aria-label=\"Toggle fullscreen\"\r\n >\r\n <svg\r\n className=\"w-5 h-5\"\r\n fill=\"currentColor\"\r\n viewBox=\"0 0 20 20\"\r\n >\r\n <path\r\n fillRule=\"evenodd\"\r\n d=\"M3 4a1 1 0 011-1h4a1 1 0 010 2H6.414l2.293 2.293a1 1 0 11-1.414 1.414L5 6.414V8a1 1 0 01-2 0V4zm9 1a1 1 0 010-2h4a1 1 0 011 1v4a1 1 0 01-2 0V6.414l-2.293 2.293a1 1 0 11-1.414-1.414L13.586 5H12zm-9 7a1 1 0 012 0v1.586l2.293-2.293a1 1 0 111.414 1.414L6.414 15H8a1 1 0 010 2H4a1 1 0 01-1-1v-4zm13-1a1 1 0 011 1v4a1 1 0 01-1 1h-4a1 1 0 010-2h1.586l-2.293-2.293a1 1 0 111.414-1.414L15 13.586V12a1 1 0 011-1z\"\r\n clipRule=\"evenodd\"\r\n />\r\n </svg>\r\n </button>\r\n )}\r\n\r\n {/* Transcript toggle */}\r\n {hasTranscript && (\r\n <button\r\n onClick={() => setShowTranscript(!showTranscript)}\r\n className={`transition-colors ${\r\n showTranscript\r\n ? \"text-blue-400\"\r\n : \"text-white hover:text-blue-400\"\r\n }`}\r\n title={\r\n showTranscript\r\n ? \"Hide Transcript\"\r\n : \"Show Transcript\"\r\n }\r\n aria-label={\r\n showTranscript\r\n ? \"Hide transcript\"\r\n : \"Show transcript\"\r\n }\r\n aria-pressed={showTranscript}\r\n >\r\n <svg\r\n className=\"w-5 h-5\"\r\n fill=\"none\"\r\n stroke=\"currentColor\"\r\n viewBox=\"0 0 24 24\"\r\n >\r\n <path\r\n strokeLinecap=\"round\"\r\n strokeLinejoin=\"round\"\r\n strokeWidth={2}\r\n d=\"M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z\"\r\n />\r\n </svg>\r\n </button>\r\n )}\r\n </div>\r\n </div>\r\n </div>\r\n ) : null\r\n ) : (\r\n <div className=\"bg-zinc-900/50 backdrop-blur-sm px-4 md:px-6 py-3 md:py-4 rounded-b-lg\">\r\n {/* Progress Bar */}\r\n <div className=\"mb-4\">\r\n <input\r\n type=\"range\"\r\n min={0}\r\n max={0.999999}\r\n step=\"any\"\r\n value={played || 0}\r\n onMouseDown={handleSeekMouseDown}\r\n onMouseUp={handleSeekMouseUp}\r\n onTouchStart={handleSeekTouchStart}\r\n onTouchEnd={handleSeekTouchEnd}\r\n onChange={handleSeekChange}\r\n className=\"w-full h-1 bg-zinc-700 rounded-lg appearance-none cursor-pointer slider\"\r\n aria-label=\"Seek position\"\r\n aria-valuemin={0}\r\n aria-valuemax={duration}\r\n aria-valuenow={played * duration}\r\n aria-valuetext={`${formatTime(\r\n played * duration\r\n )} of ${formatTime(duration)}`}\r\n role=\"slider\"\r\n />\r\n <div className=\"flex justify-between text-xs text-gray-400 mt-1\">\r\n <span>{formatTime((played || 0) * duration)}</span>\r\n <span>{formatTime(duration)}</span>\r\n </div>\r\n </div>\r\n\r\n {/* Control Buttons */}\r\n <div className=\"flex items-center justify-between\">\r\n <div className=\"flex items-center gap-4\">\r\n {/* Play/Pause */}\r\n <button\r\n onClick={handlePlayPause}\r\n className=\"text-white hover:text-blue-400 transition-colors\"\r\n title={playing ? \"Pause\" : \"Play\"}\r\n aria-label={playing ? \"Pause\" : \"Play\"}\r\n aria-pressed={playing}\r\n >\r\n {playing ? (\r\n <svg\r\n className=\"w-8 h-8\"\r\n fill=\"currentColor\"\r\n viewBox=\"0 0 20 20\"\r\n aria-hidden=\"true\"\r\n >\r\n <path\r\n fillRule=\"evenodd\"\r\n d=\"M18 10a8 8 0 11-16 0 8 8 0 0116 0zM7 8a1 1 0 012 0v4a1 1 0 11-2 0V8zm5-1a1 1 0 00-1 1v4a1 1 0 102 0V8a1 1 0 00-1-1z\"\r\n clipRule=\"evenodd\"\r\n />\r\n </svg>\r\n ) : (\r\n <svg\r\n className=\"w-8 h-8\"\r\n fill=\"currentColor\"\r\n viewBox=\"0 0 20 20\"\r\n aria-hidden=\"true\"\r\n >\r\n <path\r\n fillRule=\"evenodd\"\r\n d=\"M10 18a8 8 0 100-16 8 8 0 000 16zM9.555 7.168A1 1 0 008 8v4a1 1 0 001.555.832l3-2a1 1 0 000-1.664l-3-2z\"\r\n clipRule=\"evenodd\"\r\n />\r\n </svg>\r\n )}\r\n </button>\r\n\r\n {/* Volume */}\r\n <div className=\"flex items-center gap-2\">\r\n <button\r\n onClick={toggleMute}\r\n className=\"text-white hover:text-blue-400 transition-colors\"\r\n title={muted ? \"Unmute\" : \"Mute\"}\r\n aria-label={muted ? \"Unmute\" : \"Mute\"}\r\n aria-pressed={muted}\r\n >\r\n {muted || volume === 0 ? (\r\n <svg\r\n className=\"w-5 h-5\"\r\n fill=\"currentColor\"\r\n viewBox=\"0 0 20 20\"\r\n aria-hidden=\"true\"\r\n >\r\n <path\r\n fillRule=\"evenodd\"\r\n d=\"M9.383 3.076A1 1 0 0110 4v12a1 1 0 01-1.707.707L4.586 13H2a1 1 0 01-1-1V8a1 1 0 011-1h2.586l3.707-3.707a1 1 0 011.09-.217zM12.293 7.293a1 1 0 011.414 0L15 8.586l1.293-1.293a1 1 0 111.414 1.414L16.414 10l1.293 1.293a1 1 0 01-1.414 1.414L15 11.414l-1.293 1.293a1 1 0 01-1.414-1.414L13.586 10l-1.293-1.293a1 1 0 010-1.414z\"\r\n clipRule=\"evenodd\"\r\n />\r\n </svg>\r\n ) : (\r\n <svg\r\n className=\"w-5 h-5\"\r\n fill=\"currentColor\"\r\n viewBox=\"0 0 20 20\"\r\n aria-hidden=\"true\"\r\n >\r\n <path\r\n fillRule=\"evenodd\"\r\n d=\"M9.383 3.076A1 1 0 0110 4v12a1 1 0 01-1.707.707L4.586 13H2a1 1 0 01-1-1V8a1 1 0 011-1h2.586l3.707-3.707a1 1 0 011.09-.217zM14.657 2.929a1 1 0 011.414 0A9.972 9.972 0 0119 10a9.972 9.972 0 01-2.929 7.071 1 1 0 01-1.414-1.414A7.971 7.971 0 0017 10c0-2.21-.894-4.208-2.343-5.657a1 1 0 010-1.414zm-2.829 2.828a1 1 0 011.415 0A5.983 5.983 0 0115 10a5.984 5.984 0 01-1.757 4.243 1 1 0 01-1.415-1.415A3.984 3.984 0 0013 10a3.983 3.983 0 00-1.172-2.828 1 1 0 010-1.415z\"\r\n clipRule=\"evenodd\"\r\n />\r\n </svg>\r\n )}\r\n </button>\r\n <input\r\n type=\"range\"\r\n min={0}\r\n max={1}\r\n step={0.01}\r\n value={muted ? 0 : volume || 1}\r\n onChange={handleVolumeChange}\r\n className=\"w-20 h-1 bg-zinc-700 rounded-lg appearance-none cursor-pointer slider\"\r\n aria-label=\"Volume\"\r\n aria-valuemin={0}\r\n aria-valuemax={100}\r\n aria-valuenow={muted ? 0 : Math.round(volume * 100)}\r\n aria-valuetext={\r\n muted ? \"Muted\" : `${Math.round(volume * 100)}%`\r\n }\r\n role=\"slider\"\r\n />\r\n </div>\r\n </div>\r\n\r\n {/* Fullscreen and Transcript buttons */}\r\n <div className=\"flex items-center gap-3\">\r\n {/* Fullscreen */}\r\n {!isAudioOnly && (\r\n <button\r\n onClick={toggleFullscreen}\r\n className=\"text-white hover:text-blue-400 transition-colors\"\r\n title=\"Toggle fullscreen\"\r\n aria-label=\"Toggle fullscreen\"\r\n >\r\n <svg\r\n className=\"w-5 h-5\"\r\n fill=\"currentColor\"\r\n viewBox=\"0 0 20 20\"\r\n aria-hidden=\"true\"\r\n >\r\n <path\r\n fillRule=\"evenodd\"\r\n d=\"M3 4a1 1 0 011-1h4a1 1 0 010 2H6.414l2.293 2.293a1 1 0 11-1.414 1.414L5 6.414V8a1 1 0 01-2 0V4zm9 1a1 1 0 010-2h4a1 1 0 011 1v4a1 1 0 01-2 0V6.414l-2.293 2.293a1 1 0 11-1.414-1.414L13.586 5H12zm-9 7a1 1 0 012 0v1.586l2.293-2.293a1 1 0 111.414 1.414L6.414 15H8a1 1 0 010 2H4a1 1 0 01-1-1v-4zm13-1a1 1 0 011 1v4a1 1 0 01-1 1h-4a1 1 0 010-2h1.586l-2.293-2.293a1 1 0 111.414-1.414L15 13.586V12a1 1 0 011-1z\"\r\n clipRule=\"evenodd\"\r\n />\r\n </svg>\r\n </button>\r\n )}\r\n\r\n {/* Transcript toggle */}\r\n {hasTranscript && (\r\n <button\r\n onClick={() => setShowTranscript(!showTranscript)}\r\n className={`transition-colors ${\r\n showTranscript\r\n ? \"text-blue-400\"\r\n : \"text-white hover:text-blue-400\"\r\n }`}\r\n title={\r\n showTranscript ? \"Hide transcript\" : \"Show transcript\"\r\n }\r\n aria-label={\r\n showTranscript ? \"Hide transcript\" : \"Show transcript\"\r\n }\r\n aria-pressed={showTranscript}\r\n >\r\n <svg\r\n className=\"w-5 h-5\"\r\n fill=\"none\"\r\n stroke=\"currentColor\"\r\n viewBox=\"0 0 24 24\"\r\n aria-hidden=\"true\"\r\n >\r\n <path\r\n strokeLinecap=\"round\"\r\n strokeLinejoin=\"round\"\r\n strokeWidth={2}\r\n d=\"M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z\"\r\n />\r\n </svg>\r\n </button>\r\n )}\r\n </div>\r\n </div>\r\n </div>\r\n ))}\r\n </div>\r\n\r\n {/* Transcript Side Panel */}\r\n {showTranscript && hasTranscript && (\r\n <div className=\"flex-1 md:flex-none min-h-0 w-full md:w-96 bg-zinc-900 border-t md:border-t-0 border-l border-zinc-800 flex flex-col overflow-hidden\">\r\n {/* Transcript Header */}\r\n <div className=\"px-4 py-3 border-b border-zinc-800 bg-zinc-900/50 shrink-0\">\r\n <div className=\"flex items-center justify-between\">\r\n <div className=\"flex items-center gap-2\">\r\n <svg\r\n className=\"w-5 h-5 text-green-400\"\r\n fill=\"none\"\r\n stroke=\"currentColor\"\r\n viewBox=\"0 0 24 24\"\r\n >\r\n <path\r\n strokeLinecap=\"round\"\r\n strokeLinejoin=\"round\"\r\n strokeWidth={2}\r\n d=\"M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z\"\r\n />\r\n </svg>\r\n <span className=\"font-medium text-white\">Transcript</span>\r\n {broadcast.transcriptLanguage && (\r\n <span className=\"text-xs text-gray-400 px-2 py-0.5 bg-zinc-800 rounded\">\r\n {broadcast.transcriptLanguage.toUpperCase()}\r\n </span>\r\n )}\r\n </div>\r\n {broadcast.transcriptUrl && (\r\n <a\r\n href={broadcast.transcriptUrl}\r\n download={`${\r\n broadcast.hash || broadcast.id\r\n }-transcript.json`}\r\n className=\"text-gray-400 hover:text-white transition-colors\"\r\n title=\"Download transcript\"\r\n aria-label=\"Download transcript as JSON file\"\r\n >\r\n <svg\r\n className=\"w-5 h-5\"\r\n fill=\"none\"\r\n stroke=\"currentColor\"\r\n viewBox=\"0 0 24 24\"\r\n aria-hidden=\"true\"\r\n >\r\n <path\r\n strokeLinecap=\"round\"\r\n strokeLinejoin=\"round\"\r\n strokeWidth={2}\r\n d=\"M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4\"\r\n />\r\n </svg>\r\n </a>\r\n )}\r\n </div>\r\n </div>\r\n\r\n {/* Resume Auto-Scroll Button */}\r\n {!autoScrollEnabled && (\r\n <div className=\"px-4 py-2 bg-zinc-800/50 border-b border-zinc-700 shrink-0\">\r\n <button\r\n onClick={() => setAutoScrollEnabled(true)}\r\n className=\"w-full px-3 py-2 bg-blue-600 hover:bg-blue-700 text-white rounded transition-colors flex items-center justify-center gap-2 text-sm font-medium\"\r\n aria-label=\"Resume automatic scrolling of transcript\"\r\n >\r\n <svg\r\n className=\"w-4 h-4\"\r\n fill=\"none\"\r\n stroke=\"currentColor\"\r\n viewBox=\"0 0 24 24\"\r\n aria-hidden=\"true\"\r\n >\r\n <path\r\n strokeLinecap=\"round\"\r\n strokeLinejoin=\"round\"\r\n strokeWidth={2}\r\n d=\"M19 14l-7 7m0 0l-7-7m7 7V3\"\r\n />\r\n </svg>\r\n Resume Auto-Scroll\r\n </button>\r\n </div>\r\n )}\r\n\r\n {/* Transcript Content - Scrollable */}\r\n <div\r\n ref={transcriptContainerRef}\r\n className=\"flex-1 min-h-0 overflow-y-auto px-4 py-4 text-gray-300 leading-relaxed\"\r\n >\r\n {isLoadingTranscript ? (\r\n <div className=\"flex items-center justify-center py-8\">\r\n <div className=\"h-6 w-6 border-2 border-gray-600 border-t-blue-500 rounded-full animate-spin\" />\r\n </div>\r\n ) : transcriptData?.segments &&\r\n transcriptData.segments.length > 0 ? (\r\n <div className=\"space-y-4\">\r\n {(() => {\r\n const filteredSegments = transcriptData.segments.filter(\r\n (s) => s.words && s.words.length > 0\r\n );\r\n let globalWordIndex = 0;\r\n const wordMap = new Map();\r\n\r\n filteredSegments.forEach((segment) => {\r\n segment.words.forEach((_word, wordIndex) => {\r\n wordMap.set(\r\n `${segment.id}-${wordIndex}`,\r\n globalWordIndex++\r\n );\r\n });\r\n });\r\n\r\n let currentWordIndex = -1;\r\n\r\n filteredSegments.forEach((segment) => {\r\n segment.words.forEach((word, wordIndex) => {\r\n const globalIdx =\r\n wordMap.get(`${segment.id}-${wordIndex}`) || -1;\r\n if (\r\n currentTime >= word.start &&\r\n globalIdx > currentWordIndex\r\n ) {\r\n currentWordIndex = globalIdx;\r\n }\r\n });\r\n });\r\n\r\n const previousWordIndex = lastActiveWordIndex.current;\r\n let minHighlightIndex = -1;\r\n let maxHighlightIndex = -1;\r\n\r\n if (currentWordIndex >= 0) {\r\n minHighlightIndex = Math.max(\r\n 0,\r\n currentWordIndex - TRAILING_WORDS\r\n );\r\n maxHighlightIndex = currentWordIndex;\r\n\r\n if (currentWordIndex <= TRAILING_WORDS) {\r\n minHighlightIndex = 0;\r\n }\r\n\r\n lastActiveWordIndex.current = currentWordIndex;\r\n } else if (currentWordIndex === -1) {\r\n minHighlightIndex = 0;\r\n maxHighlightIndex = 0;\r\n } else if (previousWordIndex >= 0) {\r\n minHighlightIndex = Math.max(\r\n 0,\r\n previousWordIndex - TRAILING_WORDS\r\n );\r\n maxHighlightIndex = previousWordIndex;\r\n }\r\n\r\n return filteredSegments.map((segment, _segmentIndex) => {\r\n const isSegmentActive =\r\n currentTime >= segment.start &&\r\n currentTime < segment.end;\r\n return (\r\n <div\r\n key={segment.id}\r\n ref={isSegmentActive ? transcriptContainerRef : null}\r\n className=\"flex gap-3 items-start leading-relaxed\"\r\n >\r\n <button\r\n onClick={() => handleWordClick(segment.start)}\r\n className=\"text-xs text-gray-500 hover:text-gray-300 transition-colors shrink-0 pt-0.5 font-mono\"\r\n title={`Jump to ${formatTimestamp(segment.start)}`}\r\n >\r\n {formatTimestamp(segment.start)}\r\n </button>\r\n\r\n <div className=\"flex-1\">\r\n {segment.words.map((word, wordIndex) => {\r\n const thisGlobalIndex =\r\n wordMap.get(`${segment.id}-${wordIndex}`) ?? -1;\r\n const isTimestampActive =\r\n currentTime >= word.start &&\r\n currentTime < word.end;\r\n const isInGapFill =\r\n minHighlightIndex >= 0 &&\r\n thisGlobalIndex >= minHighlightIndex &&\r\n thisGlobalIndex <= maxHighlightIndex;\r\n const isWordActive = isInGapFill;\r\n\r\n return (\r\n <span\r\n key={`${segment.id}-${wordIndex}`}\r\n ref={isTimestampActive ? activeWordRef : null}\r\n onClick={() => handleWordClick(word.start)}\r\n className={`cursor-pointer ${\r\n isWordActive\r\n ? \"text-blue-400 font-medium active-word\"\r\n : isSegmentActive\r\n ? \"text-gray-200 segment-word\"\r\n : \"text-gray-400 hover:text-gray-200 inactive-word\"\r\n }`}\r\n title={`${formatTime(\r\n word.start\r\n )} - ${formatTime(word.end)}`}\r\n >\r\n {word.word}{\" \"}\r\n </span>\r\n );\r\n })}\r\n </div>\r\n </div>\r\n );\r\n });\r\n })()}\r\n </div>\r\n ) : transcriptData?.words && transcriptData.words.length > 0 ? (\r\n <div className=\"space-y-1\">\r\n {transcriptData.words.map((word, index) => {\r\n const isActive =\r\n currentTime >= word.start && currentTime < word.end;\r\n return (\r\n <span\r\n key={index}\r\n ref={isActive ? activeWordRef : null}\r\n onClick={() => handleWordClick(word.start)}\r\n className={`inline-block cursor-pointer transition-all ${\r\n isActive\r\n ? \"text-blue-400 underline decoration-blue-400 decoration-2 font-medium\"\r\n : \"text-gray-400 hover:text-gray-200\"\r\n }`}\r\n title={`${formatTime(word.start)} - ${formatTime(\r\n word.end\r\n )}`}\r\n >\r\n {word.word}{\" \"}\r\n </span>\r\n );\r\n })}\r\n </div>\r\n ) : (\r\n <div className=\"text-center text-gray-500 py-8\">\r\n <p className=\"mb-2\">Transcript data not available</p>\r\n {transcriptData && (\r\n <p className=\"text-xs text-gray-600\">\r\n Debug: segments=\r\n {transcriptData.segments\r\n ? transcriptData.segments.length\r\n : 0}\r\n , words=\r\n {transcriptData.words ? transcriptData.words.length : 0}\r\n </p>\r\n )}\r\n </div>\r\n )}\r\n </div>\r\n </div>\r\n )}\r\n </div>\r\n\r\n {/* Clip Creator */}\r\n {renderClipCreator &&\r\n renderClipCreator({\r\n isOpen: showClipCreator,\r\n onClose: () => setShowClipCreator(false),\r\n sourceVideoUrl:\r\n playbackType === \"mp4\" ? playbackUrl || undefined : undefined,\r\n sourceAudioUrl:\r\n playbackType === \"mp3\" ? playbackUrl || undefined : undefined,\r\n sourceDuration: duration,\r\n onPauseParent: () => setPlaying(false),\r\n })}\r\n\r\n <style>{`\r\n .slider::-webkit-slider-thumb {\r\n appearance: none;\r\n width: 14px;\r\n height: 14px;\r\n border-radius: 50%;\r\n background: white;\r\n cursor: pointer;\r\n box-shadow: 0 2px 4px rgba(0,0,0,0.3);\r\n }\r\n .slider::-webkit-slider-thumb:hover {\r\n background: #60a5fa;\r\n }\r\n .slider::-moz-range-thumb {\r\n width: 14px;\r\n height: 14px;\r\n border-radius: 50%;\r\n background: white;\r\n cursor: pointer;\r\n border: none;\r\n box-shadow: 0 2px 4px rgba(0,0,0,0.3);\r\n }\r\n .slider::-moz-range-thumb:hover {\r\n background: #60a5fa;\r\n }\r\n\r\n .active-word {\r\n transition: color 0s, text-shadow 0s;\r\n text-shadow: 0 0 8px rgba(96, 165, 250, 0.6), 0 0 12px rgba(96, 165, 250, 0.4);\r\n }\r\n .segment-word,\r\n .inactive-word {\r\n transition: color 0.4s ease-out, text-shadow 0.4s ease-out;\r\n text-shadow: none;\r\n }\r\n .segment-word:hover,\r\n .inactive-word:hover {\r\n transition: color 0.15s ease-in;\r\n }\r\n `}</style>\r\n </div>\r\n );\r\n\r\n return playerContent;\r\n}\r\n","import { Component, ErrorInfo, ReactNode } from \"react\";\r\n\r\ninterface Props {\r\n children: ReactNode;\r\n /** Callback when modal needs to be closed */\r\n onClose?: () => void;\r\n /** Broadcast ID for logging purposes */\r\n broadcastId?: number;\r\n}\r\n\r\ninterface State {\r\n hasError: boolean;\r\n error: Error | null;\r\n errorInfo: ErrorInfo | null;\r\n}\r\n\r\n/**\r\n * Error Boundary for Broadcast Player Modal\r\n *\r\n * Catches and handles React errors that occur during:\r\n * - Rendering\r\n * - Lifecycle methods\r\n * - Constructors of the whole tree below them\r\n *\r\n * Does NOT catch errors in:\r\n * - Event handlers (use try-catch)\r\n * - Asynchronous code (use try-catch)\r\n * - Server-side rendering\r\n * - Errors thrown in the error boundary itself\r\n *\r\n * Benefits:\r\n * - Prevents white screen of death\r\n * - Provides user-friendly error UI\r\n * - Logs errors for debugging\r\n * - Allows graceful recovery\r\n */\r\nexport class DialtribePlayerErrorBoundary extends Component<Props, State> {\r\n constructor(props: Props) {\r\n super(props);\r\n this.state = {\r\n hasError: false,\r\n error: null,\r\n errorInfo: null,\r\n };\r\n }\r\n\r\n static getDerivedStateFromError(error: Error): Partial<State> {\r\n // Update state so the next render will show the fallback UI\r\n return { hasError: true, error };\r\n }\r\n\r\n componentDidCatch(error: Error, errorInfo: ErrorInfo) {\r\n // Log error details for debugging\r\n console.error(\"[Player Error Boundary] Caught error:\", {\r\n error: error.message,\r\n stack: error.stack,\r\n componentStack: errorInfo.componentStack,\r\n broadcastId: this.props.broadcastId,\r\n timestamp: new Date().toISOString(),\r\n });\r\n\r\n // Update state with error info\r\n this.setState({\r\n error,\r\n errorInfo,\r\n });\r\n\r\n // TODO: Send error to logging service (e.g., Sentry, LogRocket)\r\n // Example:\r\n // logErrorToService({\r\n // error,\r\n // errorInfo,\r\n // broadcastId: this.props.broadcastId,\r\n // });\r\n }\r\n\r\n handleReset = () => {\r\n // Reset error state and try again\r\n this.setState({\r\n hasError: false,\r\n error: null,\r\n errorInfo: null,\r\n });\r\n };\r\n\r\n handleClose = () => {\r\n // Close modal and reset error state\r\n this.setState({\r\n hasError: false,\r\n error: null,\r\n errorInfo: null,\r\n });\r\n this.props.onClose?.();\r\n };\r\n\r\n render() {\r\n if (this.state.hasError) {\r\n // Render fallback UI\r\n return (\r\n <div className=\"fixed inset-0 z-50 flex items-center justify-center bg-black/80\">\r\n <div className=\"bg-white dark:bg-gray-800 rounded-lg shadow-xl max-w-2xl w-full mx-4 p-6\">\r\n {/* Header */}\r\n <div className=\"flex items-center justify-between mb-4\">\r\n <h2 className=\"text-2xl font-bold text-gray-900 dark:text-white\">\r\n Player Error\r\n </h2>\r\n <button\r\n onClick={this.handleClose}\r\n className=\"text-gray-400 hover:text-gray-600 dark:hover:text-gray-300\"\r\n aria-label=\"Close\"\r\n >\r\n <svg\r\n className=\"w-6 h-6\"\r\n fill=\"none\"\r\n stroke=\"currentColor\"\r\n viewBox=\"0 0 24 24\"\r\n >\r\n <path\r\n strokeLinecap=\"round\"\r\n strokeLinejoin=\"round\"\r\n strokeWidth={2}\r\n d=\"M6 18L18 6M6 6l12 12\"\r\n />\r\n </svg>\r\n </button>\r\n </div>\r\n\r\n {/* Error icon */}\r\n <div className=\"flex justify-center mb-4\">\r\n <div className=\"rounded-full bg-red-100 dark:bg-red-900/30 p-3\">\r\n <svg\r\n className=\"w-12 h-12 text-red-600 dark:text-red-400\"\r\n fill=\"none\"\r\n stroke=\"currentColor\"\r\n viewBox=\"0 0 24 24\"\r\n >\r\n <path\r\n strokeLinecap=\"round\"\r\n strokeLinejoin=\"round\"\r\n strokeWidth={2}\r\n d=\"M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z\"\r\n />\r\n </svg>\r\n </div>\r\n </div>\r\n\r\n {/* Error message */}\r\n <div className=\"text-center mb-6\">\r\n <p className=\"text-lg text-gray-900 dark:text-white mb-2\">\r\n Something went wrong with the media player\r\n </p>\r\n <p className=\"text-sm text-gray-600 dark:text-gray-400\">\r\n {this.state.error?.message || \"An unexpected error occurred\"}\r\n </p>\r\n </div>\r\n\r\n {/* Error details (collapsible, for debugging) */}\r\n {process.env.NODE_ENV === \"development\" && this.state.errorInfo && (\r\n <details className=\"mb-6 p-4 bg-gray-100 dark:bg-gray-900 rounded text-xs\">\r\n <summary className=\"cursor-pointer font-semibold text-gray-700 dark:text-gray-300 mb-2\">\r\n Error Details (Development Only)\r\n </summary>\r\n <pre className=\"overflow-auto text-gray-600 dark:text-gray-400 whitespace-pre-wrap\">\r\n {this.state.error?.stack}\r\n {\"\\n\\nComponent Stack:\"}\r\n {this.state.errorInfo.componentStack}\r\n </pre>\r\n </details>\r\n )}\r\n\r\n {/* Action buttons */}\r\n <div className=\"flex gap-3 justify-center\">\r\n <button\r\n onClick={this.handleReset}\r\n className=\"px-6 py-2 bg-blue-600 hover:bg-blue-700 text-white rounded-lg font-medium transition-colors\"\r\n >\r\n Try Again\r\n </button>\r\n <button\r\n onClick={this.handleClose}\r\n className=\"px-6 py-2 bg-gray-200 hover:bg-gray-300 dark:bg-gray-700 dark:hover:bg-gray-600 text-gray-900 dark:text-white rounded-lg font-medium transition-colors\"\r\n >\r\n Close Player\r\n </button>\r\n </div>\r\n\r\n {/* Help text */}\r\n <p className=\"text-center text-sm text-gray-500 dark:text-gray-400 mt-6\">\r\n If this problem persists, try refreshing the page or contact\r\n support.\r\n </p>\r\n </div>\r\n </div>\r\n );\r\n }\r\n\r\n return this.props.children;\r\n }\r\n}\r\n","import { useEffect, useRef } from \"react\";\r\n\r\n/** Display mode for the overlay */\r\nexport type DialtribeOverlayMode = \"modal\" | \"fullscreen\";\r\n\r\nexport interface DialtribeOverlayProps {\r\n /** Whether the overlay is open */\r\n isOpen: boolean;\r\n\r\n /** Called when the overlay should close */\r\n onClose: () => void;\r\n\r\n /** Display mode: \"modal\" (centered with backdrop) or \"fullscreen\" (fills viewport) */\r\n mode?: DialtribeOverlayMode;\r\n\r\n /** Content to display inside the overlay */\r\n children: React.ReactNode;\r\n\r\n /** Optional: aria-label for accessibility */\r\n ariaLabel?: string;\r\n\r\n /** Optional: Show close button. Default: true */\r\n showCloseButton?: boolean;\r\n\r\n /** Optional: Close on backdrop click. Default: true */\r\n closeOnBackdropClick?: boolean;\r\n\r\n /** Optional: Close on ESC key. Default: true */\r\n closeOnEsc?: boolean;\r\n}\r\n\r\n// Overlay styles for each mode\r\nconst overlayStyles = {\r\n modal: {\r\n backdrop: \"bg-black/70 backdrop-blur-xl p-2 sm:p-4\",\r\n container: \"max-w-7xl max-h-[95vh] sm:max-h-[90vh]\",\r\n },\r\n fullscreen: {\r\n backdrop: \"bg-black\",\r\n container: \"h-full\",\r\n },\r\n};\r\n\r\n/**\r\n * DialtribeOverlay - Reusable modal/fullscreen overlay component\r\n *\r\n * Provides a consistent overlay experience with:\r\n * - Focus management (traps focus, restores on close)\r\n * - ESC key to close\r\n * - Backdrop click to close\r\n * - Accessible with proper ARIA attributes\r\n *\r\n * @example\r\n * ```tsx\r\n * // Modal mode (centered with backdrop blur)\r\n * <DialtribeOverlay isOpen={show} onClose={() => setShow(false)} mode=\"modal\">\r\n * <MyContent />\r\n * </DialtribeOverlay>\r\n *\r\n * // Fullscreen mode (fills entire viewport)\r\n * <DialtribeOverlay isOpen={show} onClose={() => setShow(false)} mode=\"fullscreen\">\r\n * <MyContent />\r\n * </DialtribeOverlay>\r\n * ```\r\n */\r\nexport function DialtribeOverlay({\r\n isOpen,\r\n onClose,\r\n mode = \"modal\",\r\n children,\r\n ariaLabel = \"Dialog\",\r\n showCloseButton = true,\r\n closeOnBackdropClick = true,\r\n closeOnEsc = true,\r\n}: DialtribeOverlayProps) {\r\n const closeButtonRef = useRef<HTMLButtonElement>(null);\r\n const previousActiveElement = useRef<HTMLElement | null>(null);\r\n\r\n // Focus management\r\n useEffect(() => {\r\n if (!isOpen) return;\r\n\r\n // Save current focus\r\n previousActiveElement.current = document.activeElement as HTMLElement;\r\n\r\n // Focus close button after render\r\n setTimeout(() => {\r\n closeButtonRef.current?.focus();\r\n }, 100);\r\n\r\n return () => {\r\n // Restore focus when overlay closes\r\n if (previousActiveElement.current) {\r\n previousActiveElement.current.focus();\r\n }\r\n };\r\n }, [isOpen]);\r\n\r\n // ESC key handler\r\n useEffect(() => {\r\n if (!isOpen || !closeOnEsc) return;\r\n\r\n const handleKeyDown = (e: KeyboardEvent) => {\r\n if (e.key === \"Escape\") {\r\n onClose();\r\n }\r\n };\r\n\r\n document.addEventListener(\"keydown\", handleKeyDown);\r\n return () => document.removeEventListener(\"keydown\", handleKeyDown);\r\n }, [isOpen, onClose, closeOnEsc]);\r\n\r\n // Don't render if not open\r\n if (!isOpen) {\r\n return null;\r\n }\r\n\r\n // Backdrop click handler\r\n const handleBackdropClick = (e: React.MouseEvent) => {\r\n if (closeOnBackdropClick && e.target === e.currentTarget) {\r\n onClose();\r\n }\r\n };\r\n\r\n const styles = overlayStyles[mode];\r\n\r\n return (\r\n <div\r\n className={`fixed inset-0 flex items-center justify-center z-50 ${styles.backdrop}`}\r\n onClick={handleBackdropClick}\r\n role=\"dialog\"\r\n aria-modal=\"true\"\r\n aria-label={ariaLabel}\r\n >\r\n <div className={`relative w-full overflow-hidden ${styles.container}`}>\r\n {/* Close Button */}\r\n {showCloseButton && (\r\n <button\r\n ref={closeButtonRef}\r\n onClick={onClose}\r\n className=\"absolute top-2 right-2 sm:top-4 sm:right-4 z-10 text-gray-400 hover:text-white text-2xl leading-none transition-colors w-8 h-8 flex items-center justify-center bg-black/50 rounded-full\"\r\n title=\"Close (ESC)\"\r\n aria-label=\"Close\"\r\n >\r\n ×\r\n </button>\r\n )}\r\n {children}\r\n </div>\r\n </div>\r\n );\r\n}\r\n","/**\r\n * Utility functions for opening broadcast streamer popup windows\r\n */\r\n\r\nexport interface PopupDimensions {\r\n width: number;\r\n height: number;\r\n left: number;\r\n top: number;\r\n}\r\n\r\n/**\r\n * Calculate optimal popup dimensions based on screen size\r\n * - Desktop/wider screens: 16:9 landscape ratio (e.g., 1280x720) to match modern webcams\r\n * - Mobile/narrower screens: 9:16 portrait ratio (e.g., 720x1280) for vertical video\r\n */\r\nexport function calculatePopupDimensions(): PopupDimensions {\r\n const screenWidth = window.screen.width;\r\n const screenHeight = window.screen.height;\r\n const screenAspectRatio = screenWidth / screenHeight;\r\n\r\n let width: number;\r\n let height: number;\r\n\r\n // Detect if screen is more landscape (desktop) or portrait (mobile)\r\n if (screenAspectRatio > 1.2) {\r\n // Landscape/desktop screen - use 16:9 LANDSCAPE ratio to match modern webcams\r\n // This minimizes black space below the video\r\n // Target: 1280x720 (scaled to fit screen)\r\n height = Math.min(720, Math.floor(screenHeight * 0.85));\r\n width = Math.floor(height * (16 / 9)); // 16:9 landscape ratio (width > height)\r\n } else {\r\n // Portrait/mobile screen - use 9:16 PORTRAIT ratio for vertical video\r\n // Target: 720x1280 (scaled to fit screen)\r\n width = Math.min(720, Math.floor(screenWidth * 0.9));\r\n height = Math.floor(width * (16 / 9)); // 9:16 portrait ratio (height > width)\r\n }\r\n\r\n // Center the popup\r\n const left = Math.floor((screenWidth - width) / 2);\r\n const top = Math.floor((screenHeight - height) / 2);\r\n\r\n return { width, height, left, top };\r\n}\r\n\r\n/**\r\n * Options for opening a broadcast streamer popup window.\r\n */\r\nexport interface OpenDialtribeStreamerPopupOptions {\r\n /**\r\n * Session token for API authentication. **Required.**\r\n * The token must include `broadcasts:stream` permission.\r\n * Sent securely via postMessage (not in the URL).\r\n */\r\n sessionToken: string;\r\n\r\n /**\r\n * Stream key for broadcasting. **Required for production use.**\r\n * Fetch this from your backend and pass it here.\r\n * The key is sent securely via postMessage (not in the URL).\r\n *\r\n * @example \"w1_abc123def456...\"\r\n */\r\n streamKey: string;\r\n\r\n /**\r\n * URL path for the streamer page. **Required.**\r\n * This is the route in your app where the popup page is hosted.\r\n *\r\n * @example \"/broadcasts/new\"\r\n * @example \"/stream/live\"\r\n */\r\n streamerUrl: string;\r\n\r\n /** Optional app ID to include in the postMessage payload */\r\n appId?: number;\r\n\r\n /** Additional URL parameters to pass to the popup page */\r\n additionalParams?: Record<string, string>;\r\n}\r\n\r\n/**\r\n * Open broadcast streamer popup window with credentials sent via postMessage\r\n * This is more secure than passing sensitive data in the URL\r\n *\r\n * @example\r\n * ```tsx\r\n * import { openDialtribeStreamerPopup } from '@dialtribe/react-sdk/dialtribe-streamer';\r\n *\r\n * // Open popup for live streaming\r\n * openDialtribeStreamerPopup({\r\n * sessionToken: 'sess_xxx...',\r\n * streamKey: 'w1_abc123...',\r\n * streamerUrl: '/broadcasts/new',\r\n * });\r\n * ```\r\n *\r\n * @returns The popup window reference, or null if popup was blocked\r\n */\r\nexport function openDialtribeStreamerPopup(\r\n options: OpenDialtribeStreamerPopupOptions\r\n): Window | null {\r\n const {\r\n sessionToken,\r\n streamKey,\r\n streamerUrl,\r\n appId,\r\n additionalParams,\r\n } = options;\r\n\r\n const { width, height, left, top } = calculatePopupDimensions();\r\n\r\n // Build URL with additional params (but NOT sensitive data like stream key)\r\n const params = new URLSearchParams();\r\n if (additionalParams) {\r\n Object.entries(additionalParams).forEach(([key, value]) => {\r\n params.append(key, value);\r\n });\r\n }\r\n\r\n const url = `${streamerUrl}${params.toString() ? `?${params.toString()}` : ''}`;\r\n\r\n // Open popup window\r\n const popup = window.open(\r\n url,\r\n \"_blank\",\r\n `width=${width},height=${height},left=${left},top=${top},resizable=yes,scrollbars=yes`\r\n );\r\n\r\n if (!popup) {\r\n console.error('Failed to open popup window - popup may be blocked');\r\n return null;\r\n }\r\n\r\n // Send credentials via postMessage after popup loads\r\n // Use a short delay to ensure the popup window is ready to receive messages\r\n const sendMessage = () => {\r\n try {\r\n popup.postMessage(\r\n {\r\n type: 'STREAM_KEY',\r\n sessionToken,\r\n streamKey,\r\n appId,\r\n },\r\n window.location.origin\r\n );\r\n } catch (error) {\r\n console.error('Failed to send credentials to popup:', error);\r\n }\r\n };\r\n\r\n // Try sending immediately and also after a short delay to ensure delivery\r\n sendMessage();\r\n setTimeout(sendMessage, 100);\r\n setTimeout(sendMessage, 500);\r\n\r\n return popup;\r\n}\r\n\r\n/**\r\n * Legacy function name for backwards compatibility\r\n * @deprecated Use openDialtribeStreamerPopup instead\r\n */\r\nexport const openBroadcastPopup = openDialtribeStreamerPopup;\r\n","import { useState, useEffect, useRef } from 'react';\r\n\r\n/**\r\n * Return value from useDialtribeStreamerPopup hook.\r\n */\r\nexport interface UseDialtribeStreamerPopupReturn {\r\n /**\r\n * Session token received from parent window.\r\n * Will be null until credentials are received via postMessage.\r\n */\r\n sessionToken: string | null;\r\n\r\n /**\r\n * Stream key received from parent window.\r\n * Will be null until credentials are received via postMessage.\r\n */\r\n streamKey: string | null;\r\n\r\n /**\r\n * API base URL received from parent window.\r\n * Defaults to empty string (uses SDK default).\r\n */\r\n apiBaseUrl: string;\r\n\r\n /**\r\n * Function to update the stream key.\r\n * Pass this to DialtribeStreamer's onStreamKeyChange prop.\r\n */\r\n setStreamKey: React.Dispatch<React.SetStateAction<string | null>>;\r\n\r\n /**\r\n * True if credentials have been received from the parent window.\r\n */\r\n isReady: boolean;\r\n}\r\n\r\n/**\r\n * Hook for popup pages that receive streaming credentials via postMessage.\r\n *\r\n * Use this in your popup page component to handle the postMessage communication\r\n * with the parent window that opened the popup via `openDialtribeStreamerPopup()`.\r\n *\r\n * @example\r\n * ```tsx\r\n * import { DialtribeStreamer, useDialtribeStreamerPopup } from '@dialtribe/react-sdk/dialtribe-streamer';\r\n *\r\n * export default function BroadcastPopupPage() {\r\n * const { sessionToken, streamKey, apiBaseUrl, setStreamKey } = useDialtribeStreamerPopup();\r\n *\r\n * return (\r\n * <DialtribeStreamer\r\n * sessionToken={sessionToken}\r\n * streamKey={streamKey}\r\n * apiBaseUrl={apiBaseUrl}\r\n * onDone={() => window.close()}\r\n * onStreamKeyChange={setStreamKey}\r\n * />\r\n * );\r\n * }\r\n * ```\r\n */\r\nexport function useDialtribeStreamerPopup(): UseDialtribeStreamerPopupReturn {\r\n const [sessionToken, setSessionToken] = useState<string | null>(null);\r\n const [streamKey, setStreamKey] = useState<string | null>(null);\r\n const [apiBaseUrl, setApiBaseUrl] = useState<string>('');\r\n const receivedDataRef = useRef(false);\r\n\r\n useEffect(() => {\r\n // Listen for postMessage from parent window\r\n const handleMessage = (event: MessageEvent) => {\r\n // Only accept STREAM_KEY messages\r\n if (event.data?.type !== 'STREAM_KEY') return;\r\n\r\n const { sessionToken: token, streamKey: key, apiBaseUrl: url } = event.data;\r\n\r\n if (token && key) {\r\n receivedDataRef.current = true;\r\n setSessionToken(token);\r\n setStreamKey(key);\r\n if (url) {\r\n setApiBaseUrl(url);\r\n }\r\n } else if (key) {\r\n // Backwards compatibility: just stream key (no session token)\r\n receivedDataRef.current = true;\r\n setStreamKey(key);\r\n }\r\n };\r\n\r\n window.addEventListener('message', handleMessage);\r\n\r\n // Request credentials from parent - keep trying until we get them\r\n const requestCredentials = () => {\r\n if (window.opener && !receivedDataRef.current) {\r\n window.opener.postMessage({ type: 'POPUP_READY' }, '*');\r\n }\r\n };\r\n\r\n // Send immediately and poll every 200ms until we get a response\r\n requestCredentials();\r\n const pollInterval = setInterval(() => {\r\n if (!receivedDataRef.current) {\r\n requestCredentials();\r\n } else {\r\n clearInterval(pollInterval);\r\n }\r\n }, 200);\r\n\r\n // Stop polling after 10 seconds\r\n const timeout = setTimeout(() => {\r\n clearInterval(pollInterval);\r\n }, 10000);\r\n\r\n return () => {\r\n window.removeEventListener('message', handleMessage);\r\n clearInterval(pollInterval);\r\n clearTimeout(timeout);\r\n };\r\n }, []);\r\n\r\n return {\r\n sessionToken,\r\n streamKey,\r\n apiBaseUrl,\r\n setStreamKey,\r\n isReady: receivedDataRef.current,\r\n };\r\n}\r\n","import React, { useState, useCallback, useRef, useEffect, type ReactNode } from 'react';\r\nimport { createPortal } from 'react-dom';\r\nimport { openDialtribeStreamerPopup } from '../utils/dialtribe-popup';\r\nimport { DialtribeOverlay } from '../components/DialtribeOverlay';\r\nimport { DialtribeStreamer } from '../components/DialtribeStreamer';\r\n\r\n/**\r\n * Fallback behavior when popup is blocked by the browser.\r\n */\r\nexport type PopupFallbackMode = 'fullscreen' | 'newTab' | 'none';\r\n\r\n/**\r\n * Options for the useDialtribeStreamerLauncher hook.\r\n */\r\nexport interface UseDialtribeStreamerLauncherOptions {\r\n /**\r\n * Session token for API authentication.\r\n */\r\n sessionToken: string | null;\r\n\r\n /**\r\n * Stream key for broadcasting.\r\n */\r\n streamKey: string;\r\n\r\n /**\r\n * URL path for the streamer page (e.g., '/broadcasts/new').\r\n */\r\n streamerUrl: string;\r\n\r\n /**\r\n * API base URL for the streamer.\r\n */\r\n apiBaseUrl?: string;\r\n\r\n /**\r\n * What to do if the popup is blocked by the browser.\r\n * - 'fullscreen': Show a fullscreen overlay in the current page\r\n * - 'newTab': Open in a new browser tab (less likely to be blocked)\r\n * - 'none': Do nothing, let the caller handle it\r\n *\r\n * @default 'fullscreen'\r\n */\r\n fallback?: PopupFallbackMode;\r\n\r\n /**\r\n * Callback when popup is blocked (called regardless of fallback mode).\r\n */\r\n onPopupBlocked?: () => void;\r\n\r\n /**\r\n * Callback when streaming ends (from fullscreen fallback mode).\r\n */\r\n onDone?: () => void;\r\n\r\n /**\r\n * Callback when stream key changes (from fallback streamer).\r\n */\r\n onStreamKeyChange?: (key: string) => void;\r\n}\r\n\r\n/**\r\n * Return value from useDialtribeStreamerLauncher hook.\r\n */\r\nexport interface UseDialtribeStreamerLauncherReturn {\r\n /**\r\n * Launch the streamer. Tries popup first, falls back if blocked.\r\n */\r\n launch: () => void;\r\n\r\n /**\r\n * Portal component that renders the fallback overlay.\r\n * Include this once in your JSX - it renders via portal to document.body.\r\n *\r\n * @example\r\n * ```tsx\r\n * const { launch, Fallback } = useDialtribeStreamerLauncher({...});\r\n * return (\r\n * <>\r\n * <button onClick={launch}>Start</button>\r\n * <Fallback />\r\n * </>\r\n * );\r\n * ```\r\n */\r\n Fallback: React.FC;\r\n\r\n /**\r\n * Whether the fallback fullscreen overlay is currently shown.\r\n * Use this for custom fallback rendering.\r\n */\r\n showFallback: boolean;\r\n\r\n /**\r\n * Close the fallback overlay.\r\n * Use this for custom fallback rendering.\r\n */\r\n closeFallback: () => void;\r\n\r\n /**\r\n * Reference to the popup window (if successfully opened).\r\n */\r\n popupRef: Window | null;\r\n\r\n /**\r\n * Whether the last launch attempt was blocked.\r\n */\r\n wasBlocked: boolean;\r\n}\r\n\r\n/**\r\n * Hook for launching the DialtribeStreamer with automatic popup fallback.\r\n *\r\n * This hook tries to open the streamer in a popup window first. If the popup\r\n * is blocked by the browser, it automatically falls back to a fullscreen\r\n * overlay or new tab (configurable).\r\n *\r\n * @example\r\n * ```tsx\r\n * import { useDialtribeStreamerLauncher } from '@dialtribe/react-sdk/dialtribe-streamer';\r\n *\r\n * function StreamButton({ sessionToken, streamKey }: Props) {\r\n * const { launch, Fallback } = useDialtribeStreamerLauncher({\r\n * sessionToken,\r\n * streamKey,\r\n * streamerUrl: '/broadcasts/new',\r\n * fallback: 'fullscreen',\r\n * });\r\n *\r\n * return (\r\n * <>\r\n * <button onClick={launch}>Start Streaming</button>\r\n * <Fallback />\r\n * </>\r\n * );\r\n * }\r\n * ```\r\n */\r\nexport function useDialtribeStreamerLauncher(\r\n options: UseDialtribeStreamerLauncherOptions\r\n): UseDialtribeStreamerLauncherReturn {\r\n const {\r\n sessionToken,\r\n streamKey,\r\n streamerUrl,\r\n apiBaseUrl,\r\n fallback = 'fullscreen',\r\n onPopupBlocked,\r\n onDone,\r\n onStreamKeyChange,\r\n } = options;\r\n\r\n const [showFallback, setShowFallback] = useState(false);\r\n const [wasBlocked, setWasBlocked] = useState(false);\r\n const popupRef = useRef<Window | null>(null);\r\n\r\n // Store latest values in refs for the message handler\r\n const sessionTokenRef = useRef(sessionToken);\r\n const streamKeyRef = useRef(streamKey);\r\n const apiBaseUrlRef = useRef(apiBaseUrl);\r\n\r\n useEffect(() => {\r\n sessionTokenRef.current = sessionToken;\r\n }, [sessionToken]);\r\n\r\n useEffect(() => {\r\n streamKeyRef.current = streamKey;\r\n }, [streamKey]);\r\n\r\n useEffect(() => {\r\n apiBaseUrlRef.current = apiBaseUrl;\r\n }, [apiBaseUrl]);\r\n\r\n // Listen for POPUP_READY messages from the popup\r\n useEffect(() => {\r\n const handleMessage = (event: MessageEvent) => {\r\n if (event.data?.type === 'POPUP_READY' && popupRef.current) {\r\n popupRef.current.postMessage(\r\n {\r\n type: 'STREAM_KEY',\r\n sessionToken: sessionTokenRef.current,\r\n streamKey: streamKeyRef.current,\r\n apiBaseUrl: apiBaseUrlRef.current,\r\n },\r\n '*'\r\n );\r\n }\r\n };\r\n\r\n window.addEventListener('message', handleMessage);\r\n return () => window.removeEventListener('message', handleMessage);\r\n }, []);\r\n\r\n const launch = useCallback(() => {\r\n if (!sessionToken) {\r\n console.warn('Cannot launch streamer: no session token');\r\n return;\r\n }\r\n\r\n setWasBlocked(false);\r\n\r\n // Try to open popup\r\n const popup = openDialtribeStreamerPopup({\r\n sessionToken,\r\n streamKey,\r\n streamerUrl,\r\n });\r\n\r\n if (popup) {\r\n // Popup opened successfully\r\n popupRef.current = popup;\r\n return;\r\n }\r\n\r\n // Popup was blocked\r\n setWasBlocked(true);\r\n onPopupBlocked?.();\r\n\r\n // Handle fallback\r\n switch (fallback) {\r\n case 'fullscreen':\r\n setShowFallback(true);\r\n break;\r\n\r\n case 'newTab':\r\n // Open in new tab (less likely to be blocked)\r\n window.open(streamerUrl, '_blank');\r\n break;\r\n\r\n case 'none':\r\n // Do nothing, caller handles it\r\n break;\r\n }\r\n }, [sessionToken, streamKey, streamerUrl, fallback, onPopupBlocked]);\r\n\r\n const closeFallback = useCallback(() => {\r\n setShowFallback(false);\r\n onDone?.();\r\n }, [onDone]);\r\n\r\n // Fallback component that renders via portal to document.body\r\n const Fallback = useCallback((): ReactNode => {\r\n // Don't render anything if not using fullscreen fallback or not showing\r\n if (fallback !== 'fullscreen' || !showFallback) {\r\n return null;\r\n }\r\n\r\n // Only render portal on client side\r\n if (typeof document === 'undefined') {\r\n return null;\r\n }\r\n\r\n const streamerElement = React.createElement(DialtribeStreamer, {\r\n sessionToken: sessionToken || undefined,\r\n streamKey: streamKey || undefined,\r\n apiBaseUrl,\r\n onDone: closeFallback,\r\n onStreamKeyChange,\r\n });\r\n\r\n const overlayElement = React.createElement(\r\n DialtribeOverlay,\r\n {\r\n mode: 'fullscreen' as const,\r\n isOpen: true,\r\n onClose: closeFallback,\r\n children: streamerElement,\r\n }\r\n );\r\n\r\n return createPortal(overlayElement, document.body);\r\n }, [fallback, showFallback, closeFallback, sessionToken, streamKey, apiBaseUrl, onStreamKeyChange]);\r\n\r\n return {\r\n launch,\r\n Fallback: Fallback as React.FC,\r\n showFallback,\r\n closeFallback,\r\n popupRef: popupRef.current,\r\n wasBlocked,\r\n };\r\n}\r\n"]}
|