From fdfddd550a699480567e1bd651a880c9bc1c9869 Mon Sep 17 00:00:00 2001 From: Fabian Braun Date: Fri, 27 Dec 2024 00:02:00 +0100 Subject: [PATCH] Source tree: Link dialog did not show when creating a new link. --- private/js/cms.tiptap.js | 3 +- private/js/tiptap_plugins/cms.dynlink.js | 44 ++++++++++++------- .../js/tiptap_plugins/cms.formextension.js | 8 ++-- private/js/tiptap_plugins/cms.plugin.js | 1 - .../js/tiptap_plugins/cms.tiptap.toolbar.js | 2 +- private/js/tiptap_plugins/cms.toolbar.js | 8 +++- 6 files changed, 39 insertions(+), 27 deletions(-) diff --git a/private/js/cms.tiptap.js b/private/js/cms.tiptap.js index b76a6a7b..5d9daaf0 100644 --- a/private/js/cms.tiptap.js +++ b/private/js/cms.tiptap.js @@ -75,7 +75,6 @@ class CMSTipTapPlugin { this.debounceTime = props.debounceTime || 200; // the time to wait after the editor loses focus before saving the content // this is to prevent saving when the user is still interacting with the editor - // (e.g. clicking on the toolbar) this.separator_markup = props.separator_markup || ''; this.space_markup = props.space_markup || ''; this.options = props.options || this.defaultOptions(); @@ -215,7 +214,7 @@ class CMSTipTapPlugin { // Blur editor event _blurEditor(editor, event) { - // Let the editor process clicks on the toolbar first + // Let the editor process clicks first // This hopefully prevents race conditions setTimeout(() => { // Allow toolbar and other editor widgets to process the click first diff --git a/private/js/tiptap_plugins/cms.dynlink.js b/private/js/tiptap_plugins/cms.dynlink.js index f946352c..4c957269 100644 --- a/private/js/tiptap_plugins/cms.dynlink.js +++ b/private/js/tiptap_plugins/cms.dynlink.js @@ -4,6 +4,32 @@ 'use strict'; import Link from '@tiptap/extension-link'; +import {Plugin} from '@tiptap/pm/state'; + + +function DynLinkClickHandler(editor) { + return new Plugin({ + props: { + handleDOMEvents: { + click(view, event) { + console.log(view); + const target = event.target.closest('a[href]'); + if (target) { + event.preventDefault(); + setTimeout(() => { + if (editor.isActive('link')) { + editor.commands.extendMarkRange('link'); + editor.commands.openCmsForm('Link'); + } + }, 0); + return true; + } + return false; + } + } + } + }); +} const CmsDynLink = Link.extend({ @@ -22,22 +48,8 @@ const CmsDynLink = Link.extend({ }; }, - onCreate({editor}) { - editor.parent?.(); // Call the parent implementation, if it exists - this.handleEvent = ((event) => { - 'use strict'; - const target = event.target.closest('a[href]'); - if (target) { - event.preventDefault(); - setTimeout(() => { - if (this.editor.isActive('link')) { - this.editor.commands.extendMarkRange('link'); - this.editor.commands.openCmsForm('Link'); - } - }, 0); - } - }).bind(this); // hacky: move the eventHandler to the Mark object (this) to be able to remove it later - editor.view.dom.addEventListener('click', this); + addProseMirrorPlugins() { + return [DynLinkClickHandler(this.editor)]; }, onDestroy() { diff --git a/private/js/tiptap_plugins/cms.formextension.js b/private/js/tiptap_plugins/cms.formextension.js index 0975216b..71b260d7 100644 --- a/private/js/tiptap_plugins/cms.formextension.js +++ b/private/js/tiptap_plugins/cms.formextension.js @@ -66,10 +66,9 @@ function clearFakeSelection(view) { const CmsFormExtension = Extension.create({ name: 'formExtension', addCommands() { - 'use strict'; return { - openCmsForm: (action, target) => ({editor, commands}) => { - if (editor.options.topToolbar.querySelector(`dialog.${action}-form`)) { + openCmsForm: (action, target) => ({editor}) => { + if (editor.options.el.querySelector(`dialog.${action}-form`)) { return false; } let options; @@ -96,9 +95,8 @@ const CmsFormExtension = Extension.create({ }; } - editor.options.topToolbar.focus(); const dialog = new CmsForm( - editor.options.el, + editor.options.element, data => { TiptapToolbar[action].formAction(editor, data); editor.commands.closeCmsForm(); diff --git a/private/js/tiptap_plugins/cms.plugin.js b/private/js/tiptap_plugins/cms.plugin.js index b589f6db..cfca2e87 100644 --- a/private/js/tiptap_plugins/cms.plugin.js +++ b/private/js/tiptap_plugins/cms.plugin.js @@ -201,7 +201,6 @@ const cmsPluginNodes = { // Capture and stop click events dom.addEventListener('click', (event) => { - event.stopPropagation(); event.preventDefault(); }); dom.addEventListener('dblclick', (event) => { diff --git a/private/js/tiptap_plugins/cms.tiptap.toolbar.js b/private/js/tiptap_plugins/cms.tiptap.toolbar.js index 1d7ff32d..669a44c1 100644 --- a/private/js/tiptap_plugins/cms.tiptap.toolbar.js +++ b/private/js/tiptap_plugins/cms.tiptap.toolbar.js @@ -154,7 +154,7 @@ const TiptapToolbar = { // If the user is currently editing a link, update the whole link editor.commands.extendMarkRange('link'); } - editor.commands.openCmsForm('Link'); + setTimeout(() => editor.commands.openCmsForm('Link'), 0); }, formAction: (editor, data) => { if (data) { diff --git a/private/js/tiptap_plugins/cms.toolbar.js b/private/js/tiptap_plugins/cms.toolbar.js index 503a370e..bcb96827 100644 --- a/private/js/tiptap_plugins/cms.toolbar.js +++ b/private/js/tiptap_plugins/cms.toolbar.js @@ -91,7 +91,6 @@ function _createBlockToolbarPlugin(editor) { tr.docChanged || oldState.selection.eq(newState.selection) === false; if (selectionChanged) { - console.log(newState); updateBlockToolbar(editor, newState); } return value; @@ -240,6 +239,7 @@ function _createTopToolbarPlugin(editor, filter) { }, state: { init(_, {doc}) { + this.handleSelectionChange = () => _updateToolbar(editor); return DecorationSet.create(doc, [ Decoration.widget(0, () => { const topToolbar = _createToolbar( @@ -257,6 +257,11 @@ function _createTopToolbarPlugin(editor, filter) { ]); }, apply(tr, value, oldState, newState) { + const selectionChanged = tr.docChanged || oldState.selection.eq(newState.selection) === false; + + if (selectionChanged) { + setTimeout(this.handleSelectionChange, 0); + } return value; } } @@ -301,7 +306,6 @@ function _createToolbar(editor, toolbar, filter) { // Limit its width to the available space toolbarElement.style.maxWidth = (window.innerWidth - toolbarElement.getBoundingClientRect().left - 16) + 'px'; } - editor.on('selectionUpdate', ({editor}) => _updateToolbar(editor)); return toolbarElement; }