diff --git a/contentcuration/contentcuration/frontend/shared/views/TipTapEditor/TipTapEditor/TipTapEditor.vue b/contentcuration/contentcuration/frontend/shared/views/TipTapEditor/TipTapEditor/TipTapEditor.vue index f59e183e86..feb6e348f7 100644 --- a/contentcuration/contentcuration/frontend/shared/views/TipTapEditor/TipTapEditor/TipTapEditor.vue +++ b/contentcuration/contentcuration/frontend/shared/views/TipTapEditor/TipTapEditor/TipTapEditor.vue @@ -197,7 +197,10 @@ return editor.value.storage.markdown.getMarkdown(); }; - let isUpdatingFromOutside = false; // A flag to prevent infinite update loops + // Cache of the latest markdown value emitted by this component. Used to + // detect when an incoming prop.value is just our own emitted value echoed + // back, so we can skip unnecessary re-rendering of the editor content. + let lastEmittedMarkdown = null; watch( () => props.mode, @@ -217,6 +220,13 @@ watch( () => props.value, newValue => { + // If the incoming value matches what we last emitted, the editor + // already reflects this content, so skip re-rendering to avoid + // unnecessary work and resetting the editor state. + if (newValue === lastEmittedMarkdown) { + return; + } + const processedContent = preprocessMarkdown(newValue); if (!editor.value) { @@ -228,36 +238,31 @@ const editorContent = getMarkdownContent(); if (editorContent !== newValue) { - isUpdatingFromOutside = true; editor.value.commands.setContent(processedContent, false); - nextTick(() => { - isUpdatingFromOutside = false; - }); } }, { immediate: true }, ); - // sync changes from the editor to the parent component - watch( - () => editor.value?.state, - () => { - if ( - !editor.value || - !isReady.value || - isUpdatingFromOutside || - !editor.value.storage?.markdown - ) { - return; - } + // sync changes from the editor to the parent component, only on blur + const emitMarkdownUpdate = () => { + if (!editor.value || !isReady.value || !editor.value.storage?.markdown) { + return; + } - const markdown = getMarkdownContent(); - if (markdown !== props.value) { - emit('update', markdown); - } - }, - { deep: true }, - ); + const markdown = getMarkdownContent(); + if (markdown !== props.value) { + lastEmittedMarkdown = markdown; + emit('update', markdown); + } + }; + + // Emit the markdown update only when the editor loses focus (blur). + watch(isFocused, (focused, wasFocused) => { + if (wasFocused && !focused) { + emitMarkdownUpdate(); + } + }); const handleContainerKeydown = event => { if (event.key === 'Enter') {