import { StrictMode } from 'react' import { createRoot } from 'react-dom/client' import './index.css' import './styles/mobile-gestures.css' import { BrowserRouter } from 'react-router-dom'; import { LocalizationProvider } from '@mui/x-date-pickers'; import { AdapterDateFns } from '@mui/x-date-pickers/AdapterDateFnsV3'; import { initializeAuth } from "./backend/firebase/firebase"; import { initializePolyfills, logBrowserCompatibility } from './utils/browserCompatibility'; import ThemeWrapper from './ThemeWrapper'; import Routes from './routes'; import { AuthProvider } from './contexts/AuthContext'; import { PageLoadingProvider } from './contexts/PageLoadingContext'; import { EnhancedSettingsProvider } from './contexts/EnhancedSettingsContext'; import { PostsProvider } from './contexts/PostsContext'; import { BookmarksProvider } from './contexts/BookmarksContext'; import { ReadLaterProvider } from './contexts/ReadLaterContext'; import { RepostProvider } from './contexts/RepostContext'; import { SnackbarProvider } from './contexts/SnackbarContext'; import { MessagingProvider } from './contexts/MessagingContext'; import { NotificationsProvider } from './contexts/NotificationsContext'; import { QuestionsProvider } from './contexts/QuestionsContext'; // Import test utilities for debugging // import './test-create-post'; import { AdminLoadingProvider } from './contexts/AdminLoadingContext'; import { ScreentimeProvider } from './contexts/ScreentimeContext'; import { PWAProvider } from './contexts/PWAContext'; import { BrowserCompatibilityProvider } from './contexts/BrowserCompatibilityContext'; import { ErrorBoundary } from './frontend/Components/ErrorBoundary'; import SnackbarContainer from './frontend/Components/Snackbar/SnackbarContainer'; import PWAInstallPrompt from './frontend/Components/PWA/PWAInstallPrompt'; import OfflineIndicator from './frontend/Components/PWA/OfflineIndicator'; import { logger } from "./backend/services/loggingService"; // Initialize browser compatibility polyfills initializePolyfills(); // Log browser compatibility information in development if (process.env.NODE_ENV === 'development') { logBrowserCompatibility(); } // Initialize Firebase Auth persistence initializeAuth().then(() => { logger.debug('Firebase Auth initialized successfully', { component: 'main', operation: 'unknown' }); }).catch((error) => { logger.error('Failed to initialize Firebase Auth:', { component: 'main', operation: 'unknown' }, error as Error); }); // Global error handler for unhandled Firebase/Firestore errors window.addEventListener('unhandledrejection', (event) => { const error = event.reason; if (error && typeof error === 'object') { const errorMessage = error.message || error.toString(); if (errorMessage.includes('WebChannelConnection') || errorMessage.includes('transport errored') || errorMessage.includes('RPC') || errorMessage.includes('stream')) { // Parse stream details if available const streamTypeMatch = errorMessage.match(/RPC '(\w+)' stream/); const streamIdMatch = errorMessage.match(/stream (0x[a-f0-9]+)/); const errorDetails = { streamType: streamTypeMatch ? streamTypeMatch[1] : undefined, streamId: streamIdMatch ? streamIdMatch[1] : undefined }; // Only log for admin users - import the connection manager to check admin status import('./backend/services/firestoreConnectionManager').then(({ firestoreConnectionManager }) => { // Check if development mode or admin user before logging if (process.env.NODE_ENV === 'development') { console.warn('๐ŸŒ Unhandled Firestore WebChannel error detected:', error); logger.warn(` Stream Type: ${errorDetails.streamType || 'Unknown'}`, { component: 'main', operation: 'unknown' }); logger.warn(` Stream ID: ${errorDetails.streamId || 'Unknown'}`, { component: 'main', operation: 'unknown' }); } firestoreConnectionManager.handleWebChannelError(errorDetails); }); // Prevent the error from propagating to avoid console spam event.preventDefault(); } } }); // Global console error handler to catch Firebase SDK errors const originalConsoleError = console.error; console.error = (...args) => { const errorMessage = args.join(' '); // Enhanced WebChannel error detection and parsing if (errorMessage.includes('WebChannelConnection') && errorMessage.includes('transport errored')) { // Parse stream type and ID from error message const streamTypeMatch = errorMessage.match(/RPC '(\w+)' stream/); const streamIdMatch = errorMessage.match(/stream (0x[a-f0-9]+)/); const errorDetails = { streamType: streamTypeMatch ? streamTypeMatch[1] : undefined, streamId: streamIdMatch ? streamIdMatch[1] : undefined }; // Only show detailed logs for admin users in production if (process.env.NODE_ENV === 'development') { logger.warn('๐ŸŒ Firebase WebChannelConnection RPC transport error detected', { component: 'main', operation: 'unknown' }); logger.warn(` Stream Type: ${errorDetails.streamType || 'Unknown'}`, { component: 'main', operation: 'unknown' }); logger.warn(` Stream ID: ${errorDetails.streamId || 'Unknown'}`, { component: 'main', operation: 'unknown' }); logger.warn('This is usually temporary and the connection will be restored automatically', { component: 'main', operation: 'unknown' }); } // Import and use the connection manager with enhanced error details import('./backend/services/firestoreConnectionManager').then(({ firestoreConnectionManager }) => { firestoreConnectionManager.handleWebChannelError(errorDetails); }); return; // Don't log the original error to reduce console spam } // Call the original console.error for other errors originalConsoleError.apply(console, args); }; // Real client-side telemetry for the admin System Health panel (issue #211) // -- additive, does not touch the Firestore-specific error handling above. // Errors are always recorded; network timings are sampled (see // clientMetricsService.ts). Deliberately lightweight, dynamically imported // so a telemetry-recording failure can never block app bootstrap. // .catch(() => {}) on every one of these floating promises is deliberate: // without it, a bug in clientMetricsService.ts itself (or its dynamic // import failing) would surface as an unhandled promise rejection, which // would re-trigger the unhandledrejection listener below, which imports // this same module again -- a real recursive-error-loop risk, not just // defensive boilerplate. window.addEventListener('error', (event) => { import('./backend/services/clientMetricsService').then(({ recordClientError }) => { return recordClientError(event.message, { errorType: 'javascript_error', filename: event.filename ?? '', lineno: event.lineno ?? 0, }); }).catch(() => {}); }); window.addEventListener('unhandledrejection', (event) => { const reason = event.reason; const message = reason instanceof Error ? reason.message : String(reason); import('./backend/services/clientMetricsService').then(({ recordClientError }) => { return recordClientError(message, { errorType: 'unhandled_promise_rejection' }); }).catch(() => {}); }); const originalFetch = window.fetch.bind(window); window.fetch = async (...args: Parameters) => { const startTime = performance.now(); try { const response = await originalFetch(...args); const duration = performance.now() - startTime; import('./backend/services/clientMetricsService').then(({ recordNetworkTiming }) => { return recordNetworkTiming(duration, response.ok, response.status); }).catch(() => {}); return response; } catch (error) { const duration = performance.now() - startTime; import('./backend/services/clientMetricsService').then(({ recordNetworkTiming }) => { return recordNetworkTiming(duration, false); }).catch(() => {}); throw error; } }; // Import and expose Firestore test utilities in development if (process.env.NODE_ENV === 'development') { import('./utils/firestoreConnectionTest').then(({ firestoreTest }) => { (window as typeof window & { firestoreTest: typeof firestoreTest }).firestoreTest = firestoreTest; logger.debug('๐Ÿ”ง Firestore test utilities available at window.firestoreTest', { component: 'main', operation: 'unknown' }); logger.debug('๐Ÿ’ก Run "firestoreTest.runAllTests()" in console to diagnose Firestore issues', { component: 'main', operation: 'unknown' }); }); // Also load the WebChannel diagnostics import('./utils/firestoreConnectionDiagnostics').then(() => { logger.debug('๐ŸŒ Firestore connection diagnostics available at window.firestoreConnectionDiagnostics', { component: 'main', operation: 'unknown' }); logger.debug('๐Ÿ’ก Run "firestoreConnectionDiagnostics.getHelp()" for WebChannel error troubleshooting', { component: 'main', operation: 'unknown' }); logger.debug('๐Ÿ’ก Run "firestoreConnectionDiagnostics.runBasicDiagnostics()" to check connection status', { component: 'main', operation: 'unknown' }); logger.debug('โ„น๏ธ Note: Detailed debug logs are only shown for admin users in production', { component: 'main', operation: 'unknown' }); }); // Load WebChannel error testing utilities import('./utils/webChannelErrorTest').then(() => { logger.debug('๐Ÿงช WebChannel error testing utilities loaded', { component: 'main', operation: 'unknown' }); logger.debug('๐Ÿ’ก Run "testWebChannelErrorHandling()" to test error detection', { component: 'main', operation: 'unknown' }); logger.debug('๐Ÿ’ก Run "testWriteRetry()" to test enhanced write operations', { component: 'main', operation: 'unknown' }); }); // Load settings offline handling diagnostic utilities import('./backend/diagnostics/settingsOfflineDiagnostics').then(module => { (window as typeof window & { runSettingsOfflineTests: typeof module.runSettingsOfflineTests; testSettingsOfflineHandling: typeof module.testSettingsOfflineHandling; testCacheManagement: typeof module.testCacheManagement; }).runSettingsOfflineTests = module.runSettingsOfflineTests; (window as typeof window & { testSettingsOfflineHandling: typeof module.testSettingsOfflineHandling }).testSettingsOfflineHandling = module.testSettingsOfflineHandling; (window as typeof window & { testCacheManagement: typeof module.testCacheManagement }).testCacheManagement = module.testCacheManagement; logger.debug('๐Ÿ“ฑ Settings offline test utilities loaded', { component: 'main', operation: 'unknown' }); logger.debug('๐Ÿ’ก Run "runSettingsOfflineTests()" to test offline error handling', { component: 'main', operation: 'unknown' }); logger.debug('๐Ÿ’ก Run "testCacheManagement()" to inspect cache state', { component: 'main', operation: 'unknown' }); logger.debug('๐Ÿ’ก Run "testSettingsOfflineHandling()" to test settings sync offline', { component: 'main', operation: 'unknown' }); }).catch(() => { // Ignore loading errors }); } createRoot(document.getElementById('root')!).render( );