Fix EditorJS read-mode toggle race condition (#1711)
* Fix EditorJS read-mode toggle race condition Fixes rare edge case when toggling read mode is peerformed at the same time. * Make PromiseQueue function
This commit is contained in:
parent
a01a2b5a30
commit
4c53dd0792
4 changed files with 35 additions and 14 deletions
20
package-lock.json
generated
20
package-lock.json
generated
|
@ -1826,12 +1826,13 @@
|
|||
}
|
||||
},
|
||||
"@editorjs/editorjs": {
|
||||
"version": "2.20.0",
|
||||
"resolved": "https://registry.npmjs.org/@editorjs/editorjs/-/editorjs-2.20.0.tgz",
|
||||
"integrity": "sha512-e6DWi8bMypFhovq9R6cefaDWVfrlVU++Q7ABp79+MxZIuC/SKAW5EtxBbKPL22H/Mc3bJIhZCxOqEl70HBh2yw==",
|
||||
"version": "2.22.2",
|
||||
"resolved": "https://registry.npmjs.org/@editorjs/editorjs/-/editorjs-2.22.2.tgz",
|
||||
"integrity": "sha512-rPCv7Z5LZebreQaaL4DZuWzoVGEqwB+P7BF1dsefGQNBmLyeLF412topeW2b6e+g4l1oQ7t75kCOACNTEyYYIA==",
|
||||
"requires": {
|
||||
"codex-notifier": "^1.1.2",
|
||||
"codex-tooltip": "^1.0.1"
|
||||
"codex-tooltip": "^1.0.2",
|
||||
"nanoid": "^3.1.22"
|
||||
}
|
||||
},
|
||||
"@editorjs/embed": {
|
||||
|
@ -11530,9 +11531,9 @@
|
|||
"integrity": "sha512-DCp6xe/LGueJ1N5sXEwcBc3r3PyVkEEDNWCVigfvywAkeXcZMk9K41a31tkEFBW0Ptlwji6/JlAb49E3Yrxbtg=="
|
||||
},
|
||||
"codex-tooltip": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/codex-tooltip/-/codex-tooltip-1.0.2.tgz",
|
||||
"integrity": "sha512-oC+Bu5X/zyhbPydgMSLWKoM/+vkJMqaLWu3Dt/jZgXS3MWK23INwC5DMBrVXZSufAFk0i0SUni38k9rLMyZn/w=="
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/codex-tooltip/-/codex-tooltip-1.0.4.tgz",
|
||||
"integrity": "sha512-Ud+N+y8PMIa9xGyKuo2j3q8QlfTzkMWQ5KeRrbCDerwVn7xq45nqPKQCFBXEMV0YI42/OqSMnsxP8MyVAyVhnA=="
|
||||
},
|
||||
"collapse-white-space": {
|
||||
"version": "1.0.6",
|
||||
|
@ -21820,6 +21821,11 @@
|
|||
"integrity": "sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ==",
|
||||
"optional": true
|
||||
},
|
||||
"nanoid": {
|
||||
"version": "3.1.30",
|
||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.30.tgz",
|
||||
"integrity": "sha512-zJpuPDwOv8D2zq2WRoMe1HsfZthVewpel9CAvTfc/2mBD1uUT/agc5f7GHGWXlYkFvi1mVxe4IjvP2HNrop7nQ=="
|
||||
},
|
||||
"nanomatch": {
|
||||
"version": "1.2.13",
|
||||
"resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz",
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"@apollo/client": "^3.4.15",
|
||||
"@editorjs/editorjs": "^2.19.3",
|
||||
"@editorjs/editorjs": "^2.22.2",
|
||||
"@editorjs/header": "^2.6.1",
|
||||
"@editorjs/image": "^2.6.0",
|
||||
"@editorjs/list": "^1.6.1",
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import EditorJS, { LogLevels, OutputData } from "@editorjs/editorjs";
|
||||
import { FormControl, FormHelperText, InputLabel } from "@material-ui/core";
|
||||
import { PromiseQueue } from "@saleor/misc";
|
||||
import classNames from "classnames";
|
||||
import React from "react";
|
||||
|
||||
|
@ -31,7 +32,7 @@ const RichTextEditor: React.FC<RichTextEditorProps> = ({
|
|||
const [isFocused, setFocus] = React.useState(false);
|
||||
const editor = React.useRef<EditorJS>();
|
||||
const editorContainer = React.useRef<HTMLDivElement>();
|
||||
const prevTogglePromise = React.useRef<Promise<boolean>>(); // used to await subsequent toggle invocations
|
||||
const togglePromiseQueue = React.useRef(PromiseQueue()); // used to await subsequent toggle invocations
|
||||
const initialMount = React.useRef(true);
|
||||
|
||||
React.useEffect(
|
||||
|
@ -75,15 +76,14 @@ const RichTextEditor: React.FC<RichTextEditorProps> = ({
|
|||
if (editor.current?.readOnly) {
|
||||
// readOnly.toggle() by itself does not enqueue the events and will result in a broken output if invocations overlap
|
||||
// Remove this logic when this is fixed in EditorJS
|
||||
if (prevTogglePromise.current instanceof Promise) {
|
||||
await prevTogglePromise.current;
|
||||
}
|
||||
prevTogglePromise.current = editor.current.readOnly.toggle(disabled);
|
||||
togglePromiseQueue.current.add(() =>
|
||||
editor.current.readOnly.toggle(disabled)
|
||||
);
|
||||
|
||||
// Switching to readOnly with empty blocks present causes the editor to freeze
|
||||
// Remove this logic when this is fixed in EditorJS
|
||||
if (!disabled && !data?.blocks?.length) {
|
||||
await prevTogglePromise.current;
|
||||
await togglePromiseQueue.current.queue;
|
||||
editor.current.clear();
|
||||
}
|
||||
}
|
||||
|
|
15
src/misc.ts
15
src/misc.ts
|
@ -460,3 +460,18 @@ export const flatten = (obj: unknown) => {
|
|||
|
||||
return result;
|
||||
};
|
||||
|
||||
export function PromiseQueue() {
|
||||
let queue = Promise.resolve();
|
||||
|
||||
function add<T>(operation: (value: T | void) => PromiseLike<T>) {
|
||||
return new Promise((resolve, reject) => {
|
||||
queue = queue
|
||||
.then(operation)
|
||||
.then(resolve)
|
||||
.catch(reject);
|
||||
});
|
||||
}
|
||||
|
||||
return { queue, add };
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue