// Enhanced polyfill for navigator.mediaDevices
if (typeof navigator !== 'undefined') {
// Ensure mediaDevices exists
if (!navigator.mediaDevices) {
(navigator as any).mediaDevices = {};
}
// Polyfill getUserMedia if not available
if (!navigator.mediaDevices.getUserMedia) {
navigator.mediaDevices.getUserMedia = function(constraints) {
// Try to find any available getUserMedia implementation
const getUserMedia = (navigator as any).getUserMedia ||
(navigator as any).webkitGetUserMedia ||
(navigator as any).mozGetUserMedia ||
(navigator as any).msGetUserMedia;
if (!getUserMedia) {
// If no getUserMedia is available, create a comprehensive mock MediaStream
console.warn('getUserMedia is not supported in this browser. Video/audio features will be disabled.');
// Create a more complete mock MediaStream
const mockTrack = {
id: 'mock-track',
kind: 'video',
label: 'Mock Track',
enabled: true,
muted: false,
readyState: 'live',
addEventListener: function() {},
removeEventListener: function() {},
dispatchEvent: function() { return true; },
stop: function() {},
clone: function() { return this; },
getCapabilities: function() { return {}; },
getConstraints: function() { return {}; },
getSettings: function() { return {}; },
applyConstraints: function() { return Promise.resolve(); }
};
const mockStream = {
id: 'mock-stream',
active: true,
getTracks: () => [mockTrack],
getVideoTracks: () => constraints?.video ? [mockTrack] : [],
getAudioTracks: () => constraints?.audio ? [mockTrack] : [],
addEventListener: function() {},
removeEventListener: function() {},
dispatchEvent: function() { return true; },
addTrack: function() {},
removeTrack: function() {},
clone: function() { return this; },
stop: function() {
this.active = false;
}
};
return Promise.resolve(mockStream as any);
}
// Wrap the legacy getUserMedia with a Promise
return new Promise(function(resolve, reject) {
getUserMedia.call(navigator, constraints, resolve, reject);
});
};
}
// Polyfill enumerateDevices if not available
if (!navigator.mediaDevices.enumerateDevices) {
navigator.mediaDevices.enumerateDevices = function() {
return Promise.resolve([]);
};
}
// Polyfill getDisplayMedia if not available
if (!navigator.mediaDevices.getDisplayMedia) {
navigator.mediaDevices.getDisplayMedia = function(constraints) {
console.warn('getDisplayMedia is not supported in this browser. Screen sharing will be disabled.');
return Promise.reject(new Error('getDisplayMedia is not supported'));
};
}
}
import { StrictMode } from 'react';
import { createRoot } from 'react-dom/client';
import Page from './app/page';
import { PageClientImpl } from './app/rooms/[roomName]/PageClientImpl';
function Router() {
const path = window.location.pathname;
// Check if we're on a room page
const roomMatch = path.match(/^\/rooms\/(.+)$/);
if (roomMatch) {
const roomName = roomMatch[1];
const searchParams = new URLSearchParams(window.location.search);
// Extract query parameters
const region = searchParams.get('region') || undefined;
const hq = searchParams.get('hq') === 'true';
const codec = searchParams.get('codec') || 'vp9';
// Use the client component directly
return (
);
}
// Default to home page
return ;
}
function render(container: HTMLElement) {
const root = createRoot(container);
root.render(
);
}
// Export the LiveKitMeet object
const LiveKitMeet = {
render,
};
// Make it available globally
if (typeof window !== 'undefined') {
(window as any).LiveKitMeet = LiveKitMeet;
}
// Also export for module systems
export default LiveKitMeet;