Переглянути джерело

feat: Add toast (#2772)

Co-authored-by: Lipis <lipiridis@gmail.com>
Co-authored-by: dwelle <luzar.david@gmail.com>
Arun 4 роки тому
батько
коміт
543c624405

+ 5 - 0
src/actions/actionStyles.ts

@@ -4,6 +4,7 @@ import {
   redrawTextBoundingBox,
 } from "../element";
 import { CODES, KEYS } from "../keys";
+import { t } from "../i18n";
 import { register } from "./register";
 import { mutateElement, newElementWith } from "../element/mutateElement";
 import {
@@ -23,6 +24,10 @@ export const actionCopyStyles = register({
       copiedStyles = JSON.stringify(element);
     }
     return {
+      appState: {
+        ...appState,
+        toastMessage: t("toast.copyStyles"),
+      },
       commitToHistory: false,
     };
   },

+ 2 - 0
src/appState.ts

@@ -67,6 +67,7 @@ export const getDefaultAppState = (): Omit<
     showStats: false,
     startBoundElement: null,
     suggestedBindings: [],
+    toastMessage: null,
     viewBackgroundColor: oc.white,
     width: window.innerWidth,
     zenModeEnabled: false,
@@ -145,6 +146,7 @@ const APP_STATE_STORAGE_CONF = (<
   showStats: { browser: true, export: false },
   startBoundElement: { browser: false, export: false },
   suggestedBindings: { browser: false, export: false },
+  toastMessage: { browser: false, export: false },
   viewBackgroundColor: { browser: true, export: true },
   width: { browser: false, export: false },
   zenModeEnabled: { browser: true, export: false },

+ 12 - 0
src/components/App.tsx

@@ -158,6 +158,7 @@ import {
 import ContextMenu from "./ContextMenu";
 import LayerUI from "./LayerUI";
 import { Stats } from "./Stats";
+import { Toast } from "./Toast";
 
 const { history } = createHistory();
 
@@ -376,6 +377,12 @@ class App extends React.Component<ExcalidrawProps, AppState> {
             onClose={this.toggleStats}
           />
         )}
+        {this.state.toastMessage !== null && (
+          <Toast
+            message={this.state.toastMessage}
+            clearToast={this.clearToast}
+          />
+        )}
         <main>
           <canvas
             id="canvas"
@@ -911,6 +918,7 @@ class App extends React.Component<ExcalidrawProps, AppState> {
         this.canvas!,
         this.state,
       );
+      this.setState({ toastMessage: t("toast.copyToClipboardAsPng") });
     } catch (error) {
       console.error(error);
       this.setState({ errorMessage: error.message });
@@ -1168,6 +1176,10 @@ class App extends React.Component<ExcalidrawProps, AppState> {
     });
   };
 
+  clearToast = () => {
+    this.setState({ toastMessage: null });
+  };
+
   public updateScene = withBatchedUpdates((sceneData: SceneData) => {
     if (sceneData.commitToHistory) {
       history.resumeRecording();

+ 32 - 0
src/components/Toast.scss

@@ -0,0 +1,32 @@
+@import "../css/_variables";
+
+.excalidraw {
+  .Toast {
+    animation: fade-in 0.5s;
+    background-color: var(--button-gray-1);
+    border-radius: 4px;
+    bottom: 10px;
+    box-sizing: border-box;
+    cursor: default;
+    left: 50%;
+    margin-left: -150px;
+    padding: 4px 0;
+    position: fixed;
+    text-align: center;
+    width: 300px;
+    z-index: 999999;
+  }
+
+  .Toast__message {
+    color: var(--popup-text-color);
+  }
+
+  @keyframes fade-in {
+    from {
+      opacity: 0;
+    }
+    to {
+      opacity: 1;
+    }
+  }
+}

+ 34 - 0
src/components/Toast.tsx

@@ -0,0 +1,34 @@
+import React, { useCallback, useEffect, useRef } from "react";
+import { TOAST_TIMEOUT } from "../constants";
+import "./Toast.scss";
+
+export const Toast = ({
+  message,
+  clearToast,
+}: {
+  message: string;
+  clearToast: () => void;
+}) => {
+  const timerRef = useRef<number>(0);
+
+  const scheduleTimeout = useCallback(
+    () =>
+      (timerRef.current = window.setTimeout(() => clearToast(), TOAST_TIMEOUT)),
+    [clearToast],
+  );
+
+  useEffect(() => {
+    scheduleTimeout();
+    return () => clearTimeout(timerRef.current);
+  }, [scheduleTimeout, message]);
+
+  return (
+    <div
+      className="Toast"
+      onMouseEnter={() => clearTimeout(timerRef?.current)}
+      onMouseLeave={scheduleTimeout}
+    >
+      <p className="Toast__message">{message}</p>
+    </div>
+  );
+};

+ 1 - 0
src/constants.ts

@@ -89,3 +89,4 @@ export const STORAGE_KEYS = {
 export const TAP_TWICE_TIMEOUT = 300;
 export const TOUCH_CTX_MENU_TIMEOUT = 500;
 export const TITLE_TIMEOUT = 10000;
+export const TOAST_TIMEOUT = 5000;

+ 1 - 1
src/data/index.ts

@@ -36,7 +36,7 @@ export const exportCanvas = async (
   },
 ) => {
   if (elements.length === 0) {
-    return window.alert(t("alerts.cannotExportEmptyCanvas"));
+    throw new Error(t("alerts.cannotExportEmptyCanvas"));
   }
   if (type === "svg" || type === "clipboard-svg") {
     const tempSvg = exportToSvg(elements, {

+ 4 - 0
src/locales/en.json

@@ -232,5 +232,9 @@
     "title": "Stats for nerds",
     "total": "Total",
     "width": "Width"
+  },
+  "toast": {
+    "copyStyles": "Copied styles.",
+    "copyToClipboardAsPng": "Copied to clipboard as PNG."
   }
 }

+ 69 - 2
src/tests/__snapshots__/regressionTests.test.tsx.snap

@@ -74,6 +74,7 @@ Object {
   "showStats": false,
   "startBoundElement": null,
   "suggestedBindings": Array [],
+  "toastMessage": null,
   "viewBackgroundColor": "#ffffff",
   "width": 1024,
   "zenModeEnabled": false,
@@ -539,6 +540,7 @@ Object {
   "showStats": false,
   "startBoundElement": null,
   "suggestedBindings": Array [],
+  "toastMessage": null,
   "viewBackgroundColor": "#ffffff",
   "width": 1024,
   "zenModeEnabled": false,
@@ -986,6 +988,7 @@ Object {
   "showStats": false,
   "startBoundElement": null,
   "suggestedBindings": Array [],
+  "toastMessage": null,
   "viewBackgroundColor": "#ffffff",
   "width": 1024,
   "zenModeEnabled": false,
@@ -1761,6 +1764,7 @@ Object {
   "showStats": false,
   "startBoundElement": null,
   "suggestedBindings": Array [],
+  "toastMessage": null,
   "viewBackgroundColor": "#ffffff",
   "width": 1024,
   "zenModeEnabled": false,
@@ -1967,6 +1971,7 @@ Object {
   "showStats": false,
   "startBoundElement": null,
   "suggestedBindings": Array [],
+  "toastMessage": null,
   "viewBackgroundColor": "#ffffff",
   "width": 1024,
   "zenModeEnabled": false,
@@ -2417,6 +2422,7 @@ Object {
   "showStats": false,
   "startBoundElement": null,
   "suggestedBindings": Array [],
+  "toastMessage": null,
   "viewBackgroundColor": "#ffffff",
   "width": 1024,
   "zenModeEnabled": false,
@@ -2664,6 +2670,7 @@ Object {
   "showStats": false,
   "startBoundElement": null,
   "suggestedBindings": Array [],
+  "toastMessage": null,
   "viewBackgroundColor": "#ffffff",
   "width": 1024,
   "zenModeEnabled": false,
@@ -2828,6 +2835,7 @@ Object {
   "showStats": false,
   "startBoundElement": null,
   "suggestedBindings": Array [],
+  "toastMessage": null,
   "viewBackgroundColor": "#ffffff",
   "width": 1024,
   "zenModeEnabled": false,
@@ -3299,6 +3307,7 @@ Object {
   "showStats": false,
   "startBoundElement": null,
   "suggestedBindings": Array [],
+  "toastMessage": null,
   "viewBackgroundColor": "#ffffff",
   "width": 1024,
   "zenModeEnabled": false,
@@ -3607,6 +3616,7 @@ Object {
   "showStats": false,
   "startBoundElement": null,
   "suggestedBindings": Array [],
+  "toastMessage": null,
   "viewBackgroundColor": "#ffffff",
   "width": 1024,
   "zenModeEnabled": false,
@@ -3810,6 +3820,7 @@ Object {
   "showStats": false,
   "startBoundElement": null,
   "suggestedBindings": Array [],
+  "toastMessage": null,
   "viewBackgroundColor": "#ffffff",
   "width": 1024,
   "zenModeEnabled": false,
@@ -4049,6 +4060,7 @@ Object {
   "showStats": false,
   "startBoundElement": null,
   "suggestedBindings": Array [],
+  "toastMessage": null,
   "viewBackgroundColor": "#ffffff",
   "width": 1024,
   "zenModeEnabled": false,
@@ -4299,6 +4311,7 @@ Object {
   "showStats": false,
   "startBoundElement": null,
   "suggestedBindings": Array [],
+  "toastMessage": null,
   "viewBackgroundColor": "#ffffff",
   "width": 1024,
   "zenModeEnabled": false,
@@ -4699,6 +4712,7 @@ Object {
   "showStats": false,
   "startBoundElement": null,
   "suggestedBindings": Array [],
+  "toastMessage": null,
   "viewBackgroundColor": "#ffffff",
   "width": 1024,
   "zenModeEnabled": false,
@@ -4969,6 +4983,7 @@ Object {
   "showStats": false,
   "startBoundElement": null,
   "suggestedBindings": Array [],
+  "toastMessage": null,
   "viewBackgroundColor": "#ffffff",
   "width": 1024,
   "zenModeEnabled": false,
@@ -5293,6 +5308,7 @@ Object {
   "showStats": false,
   "startBoundElement": null,
   "suggestedBindings": Array [],
+  "toastMessage": null,
   "viewBackgroundColor": "#ffffff",
   "width": 1024,
   "zenModeEnabled": false,
@@ -5476,6 +5492,7 @@ Object {
   "showStats": false,
   "startBoundElement": null,
   "suggestedBindings": Array [],
+  "toastMessage": null,
   "viewBackgroundColor": "#ffffff",
   "width": 1024,
   "zenModeEnabled": false,
@@ -5637,6 +5654,7 @@ Object {
   "showStats": false,
   "startBoundElement": null,
   "suggestedBindings": Array [],
+  "toastMessage": null,
   "viewBackgroundColor": "#ffffff",
   "width": 1024,
   "zenModeEnabled": false,
@@ -6094,6 +6112,7 @@ Object {
   "showStats": false,
   "startBoundElement": null,
   "suggestedBindings": Array [],
+  "toastMessage": null,
   "viewBackgroundColor": "#ffffff",
   "width": 1024,
   "zenModeEnabled": false,
@@ -6402,6 +6421,7 @@ Object {
   "showStats": false,
   "startBoundElement": null,
   "suggestedBindings": Array [],
+  "toastMessage": null,
   "viewBackgroundColor": "#ffffff",
   "width": 1024,
   "zenModeEnabled": false,
@@ -8438,6 +8458,7 @@ Object {
   "showStats": false,
   "startBoundElement": null,
   "suggestedBindings": Array [],
+  "toastMessage": null,
   "viewBackgroundColor": "#ffffff",
   "width": 1024,
   "zenModeEnabled": false,
@@ -8798,6 +8819,7 @@ Object {
   "showStats": false,
   "startBoundElement": null,
   "suggestedBindings": Array [],
+  "toastMessage": null,
   "viewBackgroundColor": "#ffffff",
   "width": 1024,
   "zenModeEnabled": false,
@@ -9048,6 +9070,7 @@ Object {
   "showStats": false,
   "startBoundElement": null,
   "suggestedBindings": Array [],
+  "toastMessage": null,
   "viewBackgroundColor": "#ffffff",
   "width": 1024,
   "zenModeEnabled": false,
@@ -9299,6 +9322,7 @@ Object {
   "showStats": false,
   "startBoundElement": null,
   "suggestedBindings": Array [],
+  "toastMessage": null,
   "viewBackgroundColor": "#ffffff",
   "width": 1024,
   "zenModeEnabled": false,
@@ -9606,6 +9630,7 @@ Object {
   "showStats": false,
   "startBoundElement": null,
   "suggestedBindings": Array [],
+  "toastMessage": null,
   "viewBackgroundColor": "#ffffff",
   "width": 1024,
   "zenModeEnabled": false,
@@ -9767,6 +9792,7 @@ Object {
   "showStats": false,
   "startBoundElement": null,
   "suggestedBindings": Array [],
+  "toastMessage": null,
   "viewBackgroundColor": "#ffffff",
   "width": 1024,
   "zenModeEnabled": false,
@@ -9928,6 +9954,7 @@ Object {
   "showStats": false,
   "startBoundElement": null,
   "suggestedBindings": Array [],
+  "toastMessage": null,
   "viewBackgroundColor": "#ffffff",
   "width": 1024,
   "zenModeEnabled": false,
@@ -10089,6 +10116,7 @@ Object {
   "showStats": false,
   "startBoundElement": null,
   "suggestedBindings": Array [],
+  "toastMessage": null,
   "viewBackgroundColor": "#ffffff",
   "width": 1024,
   "zenModeEnabled": false,
@@ -10280,6 +10308,7 @@ Object {
   "showStats": false,
   "startBoundElement": null,
   "suggestedBindings": Array [],
+  "toastMessage": null,
   "viewBackgroundColor": "#ffffff",
   "width": 1024,
   "zenModeEnabled": false,
@@ -10471,6 +10500,7 @@ Object {
   "showStats": false,
   "startBoundElement": null,
   "suggestedBindings": Array [],
+  "toastMessage": null,
   "viewBackgroundColor": "#ffffff",
   "width": 1024,
   "zenModeEnabled": false,
@@ -10662,6 +10692,7 @@ Object {
   "showStats": false,
   "startBoundElement": null,
   "suggestedBindings": Array [],
+  "toastMessage": null,
   "viewBackgroundColor": "#ffffff",
   "width": 1024,
   "zenModeEnabled": false,
@@ -10853,6 +10884,7 @@ Object {
   "showStats": false,
   "startBoundElement": null,
   "suggestedBindings": Array [],
+  "toastMessage": null,
   "viewBackgroundColor": "#ffffff",
   "width": 1024,
   "zenModeEnabled": false,
@@ -11014,6 +11046,7 @@ Object {
   "showStats": false,
   "startBoundElement": null,
   "suggestedBindings": Array [],
+  "toastMessage": null,
   "viewBackgroundColor": "#ffffff",
   "width": 1024,
   "zenModeEnabled": false,
@@ -11175,6 +11208,7 @@ Object {
   "showStats": false,
   "startBoundElement": null,
   "suggestedBindings": Array [],
+  "toastMessage": null,
   "viewBackgroundColor": "#ffffff",
   "width": 1024,
   "zenModeEnabled": false,
@@ -11366,6 +11400,7 @@ Object {
   "showStats": false,
   "startBoundElement": null,
   "suggestedBindings": Array [],
+  "toastMessage": null,
   "viewBackgroundColor": "#ffffff",
   "width": 1024,
   "zenModeEnabled": false,
@@ -11527,6 +11562,7 @@ Object {
   "showStats": false,
   "startBoundElement": null,
   "suggestedBindings": Array [],
+  "toastMessage": null,
   "viewBackgroundColor": "#ffffff",
   "width": 1024,
   "zenModeEnabled": false,
@@ -11729,6 +11765,7 @@ Object {
   "showStats": false,
   "startBoundElement": null,
   "suggestedBindings": Array [],
+  "toastMessage": null,
   "viewBackgroundColor": "#ffffff",
   "width": 1024,
   "zenModeEnabled": false,
@@ -12435,6 +12472,7 @@ Object {
   "showStats": false,
   "startBoundElement": null,
   "suggestedBindings": Array [],
+  "toastMessage": null,
   "viewBackgroundColor": "#ffffff",
   "width": 1024,
   "zenModeEnabled": false,
@@ -12681,6 +12719,7 @@ Object {
   "showStats": false,
   "startBoundElement": null,
   "suggestedBindings": Array [],
+  "toastMessage": null,
   "viewBackgroundColor": "#ffffff",
   "width": 1024,
   "zenModeEnabled": false,
@@ -12778,6 +12817,7 @@ Object {
   "showStats": false,
   "startBoundElement": null,
   "suggestedBindings": Array [],
+  "toastMessage": null,
   "viewBackgroundColor": "#ffffff",
   "width": 1024,
   "zenModeEnabled": false,
@@ -12877,6 +12917,7 @@ Object {
   "showStats": false,
   "startBoundElement": null,
   "suggestedBindings": Array [],
+  "toastMessage": null,
   "viewBackgroundColor": "#ffffff",
   "width": 1024,
   "zenModeEnabled": false,
@@ -13038,6 +13079,7 @@ Object {
   "showStats": false,
   "startBoundElement": null,
   "suggestedBindings": Array [],
+  "toastMessage": null,
   "viewBackgroundColor": "#ffffff",
   "width": 1024,
   "zenModeEnabled": false,
@@ -13343,6 +13385,7 @@ Object {
   "showStats": false,
   "startBoundElement": null,
   "suggestedBindings": Array [],
+  "toastMessage": null,
   "viewBackgroundColor": "#ffffff",
   "width": 1024,
   "zenModeEnabled": false,
@@ -13648,6 +13691,7 @@ Object {
   "showStats": false,
   "startBoundElement": null,
   "suggestedBindings": Array [],
+  "toastMessage": "Copied styles.",
   "viewBackgroundColor": "#ffffff",
   "width": 1024,
   "zenModeEnabled": false,
@@ -13744,7 +13788,7 @@ Object {
 
 exports[`regression tests selecting 'Copy styles' in context menu copies styles: [end of test] number of elements 1`] = `1`;
 
-exports[`regression tests selecting 'Copy styles' in context menu copies styles: [end of test] number of renders 1`] = `6`;
+exports[`regression tests selecting 'Copy styles' in context menu copies styles: [end of test] number of renders 1`] = `7`;
 
 exports[`regression tests selecting 'Delete' in context menu deletes element: [end of test] appState 1`] = `
 Object {
@@ -13807,6 +13851,7 @@ Object {
   "showStats": false,
   "startBoundElement": null,
   "suggestedBindings": Array [],
+  "toastMessage": null,
   "viewBackgroundColor": "#ffffff",
   "width": 1024,
   "zenModeEnabled": false,
@@ -14002,6 +14047,7 @@ Object {
   "showStats": false,
   "startBoundElement": null,
   "suggestedBindings": Array [],
+  "toastMessage": null,
   "viewBackgroundColor": "#ffffff",
   "width": 1024,
   "zenModeEnabled": false,
@@ -14254,6 +14300,7 @@ Object {
   "showStats": false,
   "startBoundElement": null,
   "suggestedBindings": Array [],
+  "toastMessage": null,
   "viewBackgroundColor": "#ffffff",
   "width": 1024,
   "zenModeEnabled": false,
@@ -14569,6 +14616,7 @@ Object {
   "showStats": false,
   "startBoundElement": null,
   "suggestedBindings": Array [],
+  "toastMessage": "Copied styles.",
   "viewBackgroundColor": "#ffffff",
   "width": 1024,
   "zenModeEnabled": false,
@@ -15340,7 +15388,7 @@ Object {
 
 exports[`regression tests selecting 'Paste styles' in context menu pastes styles: [end of test] number of elements 1`] = `2`;
 
-exports[`regression tests selecting 'Paste styles' in context menu pastes styles: [end of test] number of renders 1`] = `21`;
+exports[`regression tests selecting 'Paste styles' in context menu pastes styles: [end of test] number of renders 1`] = `22`;
 
 exports[`regression tests selecting 'Send backward' in context menu sends element backward: [end of test] appState 1`] = `
 Object {
@@ -15405,6 +15453,7 @@ Object {
   "showStats": false,
   "startBoundElement": null,
   "suggestedBindings": Array [],
+  "toastMessage": null,
   "viewBackgroundColor": "#ffffff",
   "width": 1024,
   "zenModeEnabled": false,
@@ -15710,6 +15759,7 @@ Object {
   "showStats": false,
   "startBoundElement": null,
   "suggestedBindings": Array [],
+  "toastMessage": null,
   "viewBackgroundColor": "#ffffff",
   "width": 1024,
   "zenModeEnabled": false,
@@ -16019,6 +16069,7 @@ Object {
   "showStats": false,
   "startBoundElement": null,
   "suggestedBindings": Array [],
+  "toastMessage": null,
   "viewBackgroundColor": "#ffffff",
   "width": 1024,
   "zenModeEnabled": false,
@@ -16394,6 +16445,7 @@ Object {
   "showStats": false,
   "startBoundElement": null,
   "suggestedBindings": Array [],
+  "toastMessage": null,
   "viewBackgroundColor": "#ffffff",
   "width": 1024,
   "zenModeEnabled": false,
@@ -16564,6 +16616,7 @@ Object {
   "showStats": false,
   "startBoundElement": null,
   "suggestedBindings": Array [],
+  "toastMessage": null,
   "viewBackgroundColor": "#ffffff",
   "width": 1024,
   "zenModeEnabled": false,
@@ -16876,6 +16929,7 @@ Object {
   "showStats": false,
   "startBoundElement": null,
   "suggestedBindings": Array [],
+  "toastMessage": null,
   "viewBackgroundColor": "#ffffff",
   "width": 1024,
   "zenModeEnabled": false,
@@ -17115,6 +17169,7 @@ Object {
   "showStats": false,
   "startBoundElement": null,
   "suggestedBindings": Array [],
+  "toastMessage": null,
   "viewBackgroundColor": "#ffffff",
   "width": 1024,
   "zenModeEnabled": false,
@@ -17369,6 +17424,7 @@ Object {
   "showStats": false,
   "startBoundElement": null,
   "suggestedBindings": Array [],
+  "toastMessage": null,
   "viewBackgroundColor": "#ffffff",
   "width": 1024,
   "zenModeEnabled": false,
@@ -17683,6 +17739,7 @@ Object {
   "showStats": false,
   "startBoundElement": null,
   "suggestedBindings": Array [],
+  "toastMessage": null,
   "viewBackgroundColor": "#ffffff",
   "width": 1024,
   "zenModeEnabled": false,
@@ -17782,6 +17839,7 @@ Object {
   "showStats": false,
   "startBoundElement": null,
   "suggestedBindings": Array [],
+  "toastMessage": null,
   "viewBackgroundColor": "#ffffff",
   "width": 1024,
   "zenModeEnabled": false,
@@ -17954,6 +18012,7 @@ Object {
   "showStats": false,
   "startBoundElement": null,
   "suggestedBindings": Array [],
+  "toastMessage": null,
   "viewBackgroundColor": "#ffffff",
   "width": 1024,
   "zenModeEnabled": false,
@@ -18759,6 +18818,7 @@ Object {
   "showStats": false,
   "startBoundElement": null,
   "suggestedBindings": Array [],
+  "toastMessage": null,
   "viewBackgroundColor": "#ffffff",
   "width": 1024,
   "zenModeEnabled": false,
@@ -18860,6 +18920,7 @@ Object {
   "showStats": false,
   "startBoundElement": null,
   "suggestedBindings": Array [],
+  "toastMessage": null,
   "viewBackgroundColor": "#ffffff",
   "width": 1024,
   "zenModeEnabled": false,
@@ -19635,6 +19696,7 @@ Object {
   "showStats": false,
   "startBoundElement": null,
   "suggestedBindings": Array [],
+  "toastMessage": null,
   "viewBackgroundColor": "#ffffff",
   "width": 1024,
   "zenModeEnabled": false,
@@ -20035,6 +20097,7 @@ Object {
   "showStats": false,
   "startBoundElement": null,
   "suggestedBindings": Array [],
+  "toastMessage": null,
   "viewBackgroundColor": "#ffffff",
   "width": 1024,
   "zenModeEnabled": false,
@@ -20281,6 +20344,7 @@ Object {
   "showStats": false,
   "startBoundElement": null,
   "suggestedBindings": Array [],
+  "toastMessage": null,
   "viewBackgroundColor": "#ffffff",
   "width": 1024,
   "zenModeEnabled": false,
@@ -20380,6 +20444,7 @@ Object {
   "showStats": false,
   "startBoundElement": null,
   "suggestedBindings": Array [],
+  "toastMessage": null,
   "viewBackgroundColor": "#ffffff",
   "width": 1024,
   "zenModeEnabled": false,
@@ -20873,6 +20938,7 @@ Object {
   "showStats": false,
   "startBoundElement": null,
   "suggestedBindings": Array [],
+  "toastMessage": null,
   "viewBackgroundColor": "#ffffff",
   "width": 1024,
   "zenModeEnabled": false,
@@ -20970,6 +21036,7 @@ Object {
   "showStats": false,
   "startBoundElement": null,
   "suggestedBindings": Array [],
+  "toastMessage": null,
   "viewBackgroundColor": "#ffffff",
   "width": 1024,
   "zenModeEnabled": false,

+ 1 - 0
src/types.ts

@@ -82,6 +82,7 @@ export type AppState = {
   previousSelectedElementIds: { [id: string]: boolean };
   shouldCacheIgnoreZoom: boolean;
   showShortcutsDialog: boolean;
+  toastMessage: string | null;
   zenModeEnabled: boolean;
   appearance: "light" | "dark";
   gridSize: number | null;