index.tsx 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. import React from "react";
  2. import ReactDOM from "react-dom";
  3. import * as Sentry from "@sentry/browser";
  4. import * as SentryIntegrations from "@sentry/integrations";
  5. import { EVENT } from "./constants";
  6. import { TopErrorBoundary } from "./components/TopErrorBoundary";
  7. import { InitializeApp } from "./components/InitializeApp";
  8. import { IsMobileProvider } from "./is-mobile";
  9. import App from "./components/App";
  10. import { register as registerServiceWorker } from "./serviceWorker";
  11. import "./css/styles.scss";
  12. import { loadFromBlob } from "./data";
  13. // On Apple mobile devices add the proprietary app icon and splashscreen markup.
  14. // No one should have to do this manually, and eventually this annoyance will
  15. // go away once https://bugs.webkit.org/show_bug.cgi?id=183937 is fixed.
  16. if (
  17. /\b(iPad|iPhone|iPod)\b/.test(navigator.userAgent) &&
  18. !matchMedia("(display-mode: standalone)").matches
  19. ) {
  20. import(/* webpackChunkName: "pwacompat" */ "pwacompat");
  21. }
  22. const SentryEnvHostnameMap: { [key: string]: string } = {
  23. "excalidraw.com": "production",
  24. "vercel.app": "staging",
  25. };
  26. const REACT_APP_DISABLE_SENTRY =
  27. process.env.REACT_APP_DISABLE_SENTRY === "true";
  28. const REACT_APP_GIT_SHA = process.env.REACT_APP_GIT_SHA as string;
  29. // Disable Sentry locally or inside the Docker to avoid noise/respect privacy
  30. const onlineEnv =
  31. !REACT_APP_DISABLE_SENTRY &&
  32. Object.keys(SentryEnvHostnameMap).find(
  33. (item) => window.location.hostname.indexOf(item) >= 0,
  34. );
  35. Sentry.init({
  36. dsn: onlineEnv
  37. ? "https://7bfc596a5bf945eda6b660d3015a5460@sentry.io/5179260"
  38. : undefined,
  39. environment: onlineEnv ? SentryEnvHostnameMap[onlineEnv] : undefined,
  40. release: REACT_APP_GIT_SHA,
  41. ignoreErrors: [
  42. "undefined is not an object (evaluating 'window.__pad.performLoop')", // Only happens on Safari, but spams our servers. Doesn't break anything
  43. ],
  44. integrations: [
  45. new SentryIntegrations.CaptureConsole({
  46. levels: ["error"],
  47. }),
  48. ],
  49. });
  50. window.__EXCALIDRAW_SHA__ = REACT_APP_GIT_SHA;
  51. // Block pinch-zooming on iOS outside of the content area
  52. document.addEventListener(
  53. "touchmove",
  54. (event) => {
  55. // @ts-ignore
  56. if (event.scale !== 1) {
  57. event.preventDefault();
  58. }
  59. },
  60. { passive: false },
  61. );
  62. const rootElement = document.getElementById("root");
  63. ReactDOM.render(
  64. <TopErrorBoundary>
  65. <IsMobileProvider>
  66. <InitializeApp>
  67. <App />
  68. </InitializeApp>
  69. </IsMobileProvider>
  70. </TopErrorBoundary>,
  71. rootElement,
  72. );
  73. registerServiceWorker({
  74. onUpdate: (registration) => {
  75. const waitingServiceWorker = registration.waiting;
  76. if (waitingServiceWorker) {
  77. waitingServiceWorker.addEventListener(
  78. EVENT.STATE_CHANGE,
  79. (event: Event) => {
  80. const target = event.target as ServiceWorker;
  81. const state = target.state as ServiceWorkerState;
  82. if (state === "activated") {
  83. window.location.reload();
  84. }
  85. },
  86. );
  87. waitingServiceWorker.postMessage({ type: "SKIP_WAITING" });
  88. }
  89. },
  90. });
  91. if ("launchQueue" in window && "LaunchParams" in window) {
  92. (window as any).launchQueue.setConsumer(
  93. async (launchParams: { files: any[] }) => {
  94. if (!launchParams.files.length) {
  95. return;
  96. }
  97. const fileHandle = launchParams.files[0];
  98. const blob = await fileHandle.getFile();
  99. loadFromBlob(blob);
  100. },
  101. );
  102. }