From 76e1869ebfacd5c491d212ca0c2482c2e10863e6 Mon Sep 17 00:00:00 2001 From: Tom Moor Date: Wed, 16 Mar 2022 15:18:16 -0700 Subject: [PATCH] fix: Catch error when emoji combinations cause document to be unable to persist (#3250) * fix: Catch and warn of rare error when emoji combinations cause document to be unable to persist changes closes #3230 * addEventListener -> removeEventListener --- app/components/Toast.tsx | 9 ++++++-- .../Document/components/MultiplayerEditor.tsx | 22 +++++++++++++++++++ shared/i18n/locales/en_US/translation.json | 7 +++--- 3 files changed, 33 insertions(+), 5 deletions(-) diff --git a/app/components/Toast.tsx b/app/components/Toast.tsx index 50e6dbc34..a859bdf70 100644 --- a/app/components/Toast.tsx +++ b/app/components/Toast.tsx @@ -17,7 +17,12 @@ function Toast({ closeAfterMs = 3000, onRequestClose, toast }: Props) { const { action, type = "info", reoccurring } = toast; React.useEffect(() => { - timeout.current = setTimeout(onRequestClose, toast.timeout || closeAfterMs); + if (toast.timeout) { + timeout.current = setTimeout( + onRequestClose, + toast.timeout || closeAfterMs + ); + } return () => timeout.current && clearTimeout(timeout.current); }, [onRequestClose, toast, closeAfterMs]); @@ -36,7 +41,7 @@ function Toast({ closeAfterMs = 3000, onRequestClose, toast }: Props) { }, []); const handleResume = React.useCallback(() => { - if (timeout.current) { + if (timeout.current && toast.timeout) { timeout.current = setTimeout( onRequestClose, toast.timeout || closeAfterMs diff --git a/app/scenes/Document/components/MultiplayerEditor.tsx b/app/scenes/Document/components/MultiplayerEditor.tsx index 0c0da6d95..20848f0c9 100644 --- a/app/scenes/Document/components/MultiplayerEditor.tsx +++ b/app/scenes/Document/components/MultiplayerEditor.tsx @@ -229,6 +229,28 @@ function MultiplayerEditor({ onSynced, ...props }: Props, ref: any) { } }, [remoteProvider, isIdle, isVisible]); + // Certain emoji combinations trigger this error in YJS, while waiting for a fix + // we must prevent the user from continuing to edit as their changes will not + // be persisted. See: https://github.com/yjs/yjs/issues/303 + React.useEffect(() => { + function onUnhandledError(err: any) { + if (err.message.includes("URIError: URI malformed")) { + showToast( + t( + "Sorry, the last change could not be persisted – please reload the page" + ), + { + type: "error", + timeout: 0, + } + ); + } + } + + window.addEventListener("error", onUnhandledError); + return () => window.removeEventListener("error", onUnhandledError); + }, [showToast, t]); + if (!extensions.length) { return null; } diff --git a/shared/i18n/locales/en_US/translation.json b/shared/i18n/locales/en_US/translation.json index 316733356..f94c70623 100644 --- a/shared/i18n/locales/en_US/translation.json +++ b/shared/i18n/locales/en_US/translation.json @@ -25,8 +25,8 @@ "Import document": "Import document", "Templatize": "Templatize", "Create template": "Create template", - "Home": "Home", "Search documents for \"{{searchQuery}}\"": "Search documents for \"{{searchQuery}}\"", + "Home": "Home", "Drafts": "Drafts", "Templates": "Templates", "Archive": "Archive", @@ -135,6 +135,7 @@ "Change Language": "Change Language", "Dismiss": "Dismiss", "Back": "Back", + "Documents": "Documents", "Document archived": "Document archived", "Move document": "Move document", "Collections": "Collections", @@ -290,7 +291,6 @@ "Suspend account": "Suspend account", "API token created": "API token created", "Name your token something that will help you to remember it's use in the future, for example \"local development\", \"production\", or \"continuous integration\".": "Name your token something that will help you to remember it's use in the future, for example \"local development\", \"production\", or \"continuous integration\".", - "Documents": "Documents", "The document archive is empty at the moment.": "The document archive is empty at the moment.", "This collection is only visible to those given access": "This collection is only visible to those given access", "Private": "Private", @@ -429,6 +429,7 @@ "Offline": "Offline", "We were unable to load the document while offline.": "We were unable to load the document while offline.", "Your account has been suspended": "Your account has been suspended", + "Warning Sign": "Warning Sign", "A team admin ({{ suspendedContactEmail }}) has suspended your account. To re-activate your account, please reach out to them directly.": "A team admin ({{ suspendedContactEmail }}) has suspended your account. To re-activate your account, please reach out to them directly.", "Are you sure about that? Deleting the {{groupName}} group will cause its members to lose access to collections and documents that it is associated with.": "Are you sure about that? Deleting the {{groupName}} group will cause its members to lose access to collections and documents that it is associated with.", "You can edit the name of this group at any time, however doing so too often might confuse your team mates.": "You can edit the name of this group at any time, however doing so too often might confuse your team mates.", @@ -520,6 +521,7 @@ "Author": "Author", "We were unable to find the page you’re looking for.": "We were unable to find the page you’re looking for.", "No documents found for your search filters.": "No documents found for your search filters.", + "Search Results": "Search Results", "Processing": "Processing", "Expired": "Expired", "Failed": "Failed", @@ -617,7 +619,6 @@ "Sharing is currently disabled.": "Sharing is currently disabled.", "You can globally enable and disable public document sharing in the security settings.": "You can globally enable and disable public document sharing in the security settings.", "Documents that have been shared are listed below. Anyone that has the public link can access a read-only version of the document until the link has been revoked.": "Documents that have been shared are listed below. Anyone that has the public link can access a read-only version of the document until the link has been revoked.", - "Shared documents": "Shared documents", "Whoops, you need to accept the permissions in Slack to connect Outline to your team. Try again?": "Whoops, you need to accept the permissions in Slack to connect Outline to your team. Try again?", "Something went wrong while authenticating your request. Please try logging in again?": "Something went wrong while authenticating your request. Please try logging in again?", "Get rich previews of Outline links shared in Slack and use the {{ command }} slash command to search for documents without leaving your chat.": "Get rich previews of Outline links shared in Slack and use the {{ command }} slash command to search for documents without leaving your chat.",