diff --git a/apps/client/src/AppRouter.tsx b/apps/client/src/AppRouter.tsx
index ba146279a3..3aeb83209a 100644
--- a/apps/client/src/AppRouter.tsx
+++ b/apps/client/src/AppRouter.tsx
@@ -1,24 +1,35 @@
-import { lazy, Suspense } from 'react';
-import { Navigate, Route, Routes } from 'react-router-dom';
+import React from 'react';
+import {
+ createRoutesFromChildren,
+ matchRoutes,
+ Navigate,
+ Route,
+ Routes,
+ useLocation,
+ useNavigationType,
+} from 'react-router-dom';
+import * as Sentry from '@sentry/react';
import { useClientPath } from './common/hooks/useClientPath';
import Log from './features/log/Log';
import withPreset from './features/PresetWrapper';
import withData from './features/viewers/ViewWrapper';
+import { ONTIME_VERSION } from './ONTIME_VERSION';
+import { sentryDsn, sentryRecommendedIgnore } from './sentry.config';
-const Editor = lazy(() => import('./features/editors/ProtectedEditor'));
-const Cuesheet = lazy(() => import('./features/cuesheet/ProtectedCuesheet'));
-const Operator = lazy(() => import('./features/operator/OperatorExport'));
+const Editor = React.lazy(() => import('./features/editors/ProtectedEditor'));
+const Cuesheet = React.lazy(() => import('./features/cuesheet/ProtectedCuesheet'));
+const Operator = React.lazy(() => import('./features/operator/OperatorExport'));
-const TimerView = lazy(() => import('./features/viewers/timer/Timer'));
-const MinimalTimerView = lazy(() => import('./features/viewers/minimal-timer/MinimalTimer'));
-const ClockView = lazy(() => import('./features/viewers/clock/Clock'));
-const Countdown = lazy(() => import('./features/viewers/countdown/Countdown'));
+const TimerView = React.lazy(() => import('./features/viewers/timer/Timer'));
+const MinimalTimerView = React.lazy(() => import('./features/viewers/minimal-timer/MinimalTimer'));
+const ClockView = React.lazy(() => import('./features/viewers/clock/Clock'));
+const Countdown = React.lazy(() => import('./features/viewers/countdown/Countdown'));
-const Backstage = lazy(() => import('./features/viewers/backstage/Backstage'));
-const Public = lazy(() => import('./features/viewers/public/Public'));
-const Lower = lazy(() => import('./features/viewers/lower-thirds/LowerThird'));
-const StudioClock = lazy(() => import('./features/viewers/studio/StudioClock'));
+const Backstage = React.lazy(() => import('./features/viewers/backstage/Backstage'));
+const Public = React.lazy(() => import('./features/viewers/public/Public'));
+const Lower = React.lazy(() => import('./features/viewers/lower-thirds/LowerThird'));
+const StudioClock = React.lazy(() => import('./features/viewers/studio/StudioClock'));
const STimer = withPreset(withData(TimerView));
const SMinimalTimer = withPreset(withData(MinimalTimerView));
@@ -29,18 +40,38 @@ const SPublic = withPreset(withData(Public));
const SLowerThird = withPreset(withData(Lower));
const SStudio = withPreset(withData(StudioClock));
-const EditorFeatureWrapper = lazy(() => import('./features/EditorFeatureWrapper'));
-const RundownPanel = lazy(() => import('./features/rundown/RundownExport'));
-const TimerControl = lazy(() => import('./features/control/playback/TimerControlExport'));
-const MessageControl = lazy(() => import('./features/control/message/MessageControlExport'));
+const EditorFeatureWrapper = React.lazy(() => import('./features/EditorFeatureWrapper'));
+const RundownPanel = React.lazy(() => import('./features/rundown/RundownExport'));
+const TimerControl = React.lazy(() => import('./features/control/playback/TimerControlExport'));
+const MessageControl = React.lazy(() => import('./features/control/message/MessageControlExport'));
+
+Sentry.init({
+ dsn: sentryDsn,
+ integrations: [
+ Sentry.reactRouterV6BrowserTracingIntegration({
+ useEffect: React.useEffect,
+ useLocation,
+ useNavigationType,
+ createRoutesFromChildren,
+ matchRoutes,
+ }),
+ ],
+ tracesSampleRate: 0.3,
+ release: ONTIME_VERSION,
+ enabled: import.meta.env.PROD,
+ ignoreErrors: [...sentryRecommendedIgnore, /Unable to preload CSS/i, /dynamically imported module/i],
+ denyUrls: [/extensions\//i, /^chrome:\/\//i, /^chrome-extension:\/\//i],
+});
+
+const SentryRoutes = Sentry.withSentryReactRouterV6Routing(Routes);
export default function AppRouter() {
// handle client path changes
useClientPath();
return (
-
-
+
+
} />
} />
@@ -99,7 +130,7 @@ export default function AppRouter() {
/>
{/*/!* Send to default if nothing found *!/*/}
} />
-
-
+
+
);
}
diff --git a/apps/client/src/index.tsx b/apps/client/src/index.tsx
index 39397ccc3a..47720389d4 100644
--- a/apps/client/src/index.tsx
+++ b/apps/client/src/index.tsx
@@ -1,51 +1,13 @@
import { StrictMode } from 'react';
import { createRoot } from 'react-dom/client';
-// skipcq: JS-C1003 - sentry does not expose itself as an ES Module.
-import * as Sentry from '@sentry/react';
import App from './App';
-import { ONTIME_VERSION } from './ONTIME_VERSION';
import './index.scss';
const container = document.getElementById('root');
const root = createRoot(container as Element);
-// https://docs.sentry.io/platforms/javascript/configuration/filtering/#decluttering-sentry
-const sentryRecommendedIgnore = [
- // Random plugins/extensions
- 'top.GLOBALS',
- // See: http://blog.errorception.com/2012/03/tale-of-unfindable-js-error.html
- 'originalCreateNotification',
- 'canvas.contentDocument',
- 'MyApp_RemoveAllHighlights',
- 'http://tt.epicplay.com',
- "Can't find variable: ZiteReader",
- 'jigsaw is not defined',
- 'ComboSearch is not defined',
- 'http://loading.retry.widdit.com/',
- 'atomicFindClose',
- // Facebook borked
- 'fb_xd_fragment',
- // ISP "optimizing" proxy - `Cache-Control: no-transform` seems to
- // reduce this. (thanks @acdha)
- // See http://stackoverflow.com/questions/4113268
- 'bmi_SafeAddOnload',
- 'EBCallBackMessageReceived',
- // See http://toolbar.conduit.com/Developer/HtmlAndGadget/Methods/JSInjection.aspx
- 'conduitPage',
-];
-
-Sentry.init({
- dsn: 'https://5e4d2c4b57ab409cb98d4c08b2014755@o4504288369836032.ingest.sentry.io/4504288371343360',
- integrations: [Sentry.browserTracingIntegration()],
- tracesSampleRate: 0.3,
- release: ONTIME_VERSION,
- enabled: import.meta.env.PROD,
- ignoreErrors: [...sentryRecommendedIgnore, /Unable to preload CSS/i, /dynamically imported module/i],
- denyUrls: [/extensions\//i, /^chrome:\/\//i, /^chrome-extension:\/\//i],
-});
-
root.render(
diff --git a/apps/client/src/sentry.config.ts b/apps/client/src/sentry.config.ts
new file mode 100644
index 0000000000..f7af7d1ef6
--- /dev/null
+++ b/apps/client/src/sentry.config.ts
@@ -0,0 +1,25 @@
+// https://docs.sentry.io/platforms/javascript/configuration/filtering/#decluttering-sentry
+export const sentryRecommendedIgnore = [
+ // Random plugins/extensions
+ 'top.GLOBALS',
+ // See: http://blog.errorception.com/2012/03/tale-of-unfindable-js-error.html
+ 'originalCreateNotification',
+ 'canvas.contentDocument',
+ 'MyApp_RemoveAllHighlights',
+ 'http://tt.epicplay.com',
+ "Can't find variable: ZiteReader",
+ 'jigsaw is not defined',
+ 'ComboSearch is not defined',
+ 'http://loading.retry.widdit.com/',
+ 'atomicFindClose',
+ // Facebook borked
+ 'fb_xd_fragment',
+ // ISP "optimizing" proxy - `Cache-Control: no-transform` seems to
+ // reduce this. (thanks @acdha)
+ // See http://stackoverflow.com/questions/4113268
+ 'bmi_SafeAddOnload',
+ 'EBCallBackMessageReceived',
+ // See http://toolbar.conduit.com/Developer/HtmlAndGadget/Methods/JSInjection.aspx
+ 'conduitPage',
+];
+export const sentryDsn = 'https://5e4d2c4b57ab409cb98d4c08b2014755@o4504288369836032.ingest.sentry.io/4504288371343360';