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';