diff --git a/editors/blocknote-react/src/components/BlockNoteViewWrapper.tsx b/editors/blocknote-react/src/components/BlockNoteViewWrapper.tsx index a5268ac50e..b9e9a2f6ce 100644 --- a/editors/blocknote-react/src/components/BlockNoteViewWrapper.tsx +++ b/editors/blocknote-react/src/components/BlockNoteViewWrapper.tsx @@ -28,6 +28,7 @@ import { } from "../blocknote"; import "@blocknote/core/fonts/inter.css"; import { adaptMacroForBlockNote } from "../blocknote/utils"; +import { useTimeoutCheck } from "../hooks"; import { BlockNoteView } from "@blocknote/mantine"; import "@blocknote/mantine/style.css"; import { @@ -188,6 +189,9 @@ const BlockNoteViewWrapper: React.FC = ({ // Prevent changes in the editor until the provider has synced with other clients const [ready, setReady] = useState(!initializer); + // Check if the syncing is happing for too long, in order to display an information message + const longLoading = useTimeoutCheck(1000); + // Creates a new editor instance. const editor = useCreateBlockNote({ ...blockNoteOptions, @@ -291,9 +295,13 @@ const BlockNoteViewWrapper: React.FC = ({ }, []); if (!ready) { + // Only display the loading message after a given amount of time, + // otherwise we end up with a flashing pending message + // + // We still show the

+ structure with an insecable space in order to keep the same height at all times return (

- {t("blocknote.realtime.pendingSync")} + {longLoading ? t("blocknote.realtime.pendingSync") : "\u00A0"}

); } diff --git a/editors/blocknote-react/src/hooks.ts b/editors/blocknote-react/src/hooks.ts index 5c3b583ba0..40223cf135 100644 --- a/editors/blocknote-react/src/hooks.ts +++ b/editors/blocknote-react/src/hooks.ts @@ -18,6 +18,7 @@ * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ import { useBlockNoteEditor } from "@blocknote/react"; +import { useEffect, useState } from "react"; import type { EditorBlockSchema, EditorInlineContentSchema, @@ -33,4 +34,22 @@ function useEditor(): EditorType { >(); } -export { useEditor }; +/** + * Check if a specified number of milliseconds passed since the hook's initial call + * + * @param milliseconds - The number of milliseconds to wait + * + * @returns Whether the delay is expired + */ +function useTimeoutCheck(milliseconds: number): boolean { + const [elapsed, setElapsed] = useState(false); + + useEffect(() => { + const timeout = setTimeout(() => setElapsed(true), milliseconds); + return () => clearTimeout(timeout); + }); + + return elapsed; +} + +export { useEditor, useTimeoutCheck };