diff --git a/web/app/components/workflow/note-node/note-editor/context.tsx b/web/app/components/workflow/note-node/note-editor/context.tsx index c9e7eb56c8..4288ec57c0 100644 --- a/web/app/components/workflow/note-node/note-editor/context.tsx +++ b/web/app/components/workflow/note-node/note-editor/context.tsx @@ -3,22 +3,73 @@ import { createContext, memo, + useEffect, useRef, } from 'react' import { LexicalComposer } from '@lexical/react/LexicalComposer' +import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext' import { LinkNode } from '@lexical/link' import { ListItemNode, ListNode, } from '@lexical/list' +import { $getRoot } from 'lexical' import { createNoteEditorStore } from './store' import theme from './theme' +const NoteEditorContentSynchronizer = ({ value }: { value?: string }) => { + const [editor] = useLexicalComposerContext() + const lastSyncedValueRef = useRef(null) + + useEffect(() => { + const normalizedValue = normalizeEditorState(value) + if (normalizedValue === lastSyncedValueRef.current) + return + + const currentSerializedState = JSON.stringify(editor.getEditorState().toJSON()) + if (normalizedValue === currentSerializedState) { + lastSyncedValueRef.current = normalizedValue + return + } + + if (!normalizedValue) { + let hasContent = false + editor.getEditorState().read(() => { + hasContent = !$getRoot().isEmpty() + }) + + if (!hasContent) { + lastSyncedValueRef.current = normalizedValue + return + } + + editor.update(() => { + const root = $getRoot() + root.clear() + root.select() + }) + lastSyncedValueRef.current = normalizedValue + return + } + + try { + const nextState = editor.parseEditorState(normalizedValue) + editor.setEditorState(nextState) + lastSyncedValueRef.current = normalizedValue + } + catch { + lastSyncedValueRef.current = '' + } + }, [editor, value]) + + return null +} + type NoteEditorStore = ReturnType const NoteEditorContext = createContext(null) type NoteEditorContextProviderProps = { - value: string + value?: string children: React.JSX.Element | string | (React.JSX.Element | string)[] editable?: boolean } @@ -34,7 +85,8 @@ export const NoteEditorContextProvider = memo(({ let initialValue = null try { - initialValue = JSON.parse(value) + if (value) + initialValue = JSON.parse(value) } catch { @@ -58,6 +110,7 @@ export const NoteEditorContextProvider = memo(({ return ( + {children} @@ -66,3 +119,19 @@ export const NoteEditorContextProvider = memo(({ NoteEditorContextProvider.displayName = 'NoteEditorContextProvider' export default NoteEditorContext + +function normalizeEditorState(value?: string): string { + if (!value) + return '' + + try { + const parsed = JSON.parse(value) + if (!parsed || typeof parsed !== 'object' || !parsed.root) + return '' + + return JSON.stringify(parsed) + } + catch { + return '' + } +}