636565d552
- lib/crashRecovery.ts: window.onerror + unhandledrejection handlers, dedupe identical messages within 10s, burst-reload after 8 distinct errors in 30s - components/CrashToast.tsx: portal stack in bottom-right, max 3 visible, auto-dismiss after 7s, per-entry close button - Wired in main.tsx before bootstrap so crypto/i18n errors are captured, rendered from App.tsx alongside UpdateToast Covers the async layer ErrorBoundary misses (realtime handlers, stray Promises, setTimeout callbacks, LiveKit listeners).
35 lines
1.1 KiB
TypeScript
35 lines
1.1 KiB
TypeScript
import { setCryptoBackend } from '@chat-app/shared/crypto';
|
|
import React from 'react';
|
|
import ReactDOM from 'react-dom/client';
|
|
|
|
import { App } from './App';
|
|
import { createLibsodiumBackend } from './lib/cryptoBackend';
|
|
import { installCrashHandlers } from './lib/crashRecovery';
|
|
import { bootstrapI18n } from './lib/i18n';
|
|
import './styles/globals.css';
|
|
|
|
async function boot(): Promise<void> {
|
|
// Install first so bootstrap errors (crypto backend, i18n) are captured.
|
|
installCrashHandlers();
|
|
bootstrapI18n();
|
|
setCryptoBackend(await createLibsodiumBackend());
|
|
|
|
const rootEl = document.getElementById('root');
|
|
if (!rootEl) throw new Error('Root element #root not found');
|
|
|
|
ReactDOM.createRoot(rootEl).render(
|
|
<React.StrictMode>
|
|
<App />
|
|
</React.StrictMode>,
|
|
);
|
|
}
|
|
|
|
void boot().catch((err: unknown) => {
|
|
console.error('boot failed', err);
|
|
const rootEl = document.getElementById('root');
|
|
if (rootEl) {
|
|
rootEl.innerHTML =
|
|
'<pre style="padding:2rem;color:#f88;font-family:monospace">Boot failed. Check the browser console.</pre>';
|
|
}
|
|
});
|