fix: prevent a bug for node views when pressing enter on iOS, fix #1214
This commit is contained in:
@@ -3,6 +3,7 @@ import { NodeSelection } from 'prosemirror-state'
|
|||||||
import { Node as ProseMirrorNode } from 'prosemirror-model'
|
import { Node as ProseMirrorNode } from 'prosemirror-model'
|
||||||
import { Editor as CoreEditor } from './Editor'
|
import { Editor as CoreEditor } from './Editor'
|
||||||
import { Node } from './Node'
|
import { Node } from './Node'
|
||||||
|
import isiOS from './utilities/isiOS'
|
||||||
import { NodeViewRendererProps } from './types'
|
import { NodeViewRendererProps } from './types'
|
||||||
|
|
||||||
interface NodeViewRendererOptions {
|
interface NodeViewRendererOptions {
|
||||||
@@ -176,22 +177,50 @@ export class NodeView<Component, Editor extends CoreEditor = CoreEditor> impleme
|
|||||||
}
|
}
|
||||||
|
|
||||||
ignoreMutation(mutation: MutationRecord | { type: 'selection', target: Element }) {
|
ignoreMutation(mutation: MutationRecord | { type: 'selection', target: Element }) {
|
||||||
if (mutation.type === 'selection') {
|
if (!this.dom || !this.contentDOM) {
|
||||||
if (this.node.isLeaf) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!this.contentDOM) {
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
const contentDOMHasChanged = !this.contentDOM.contains(mutation.target)
|
// a leaf/atom node is like a black box for ProseMirror
|
||||||
|| (this.contentDOM === mutation.target && mutation.type === 'attributes')
|
// and should be fully handled by the node view
|
||||||
|
if (this.node.isLeaf) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
return contentDOMHasChanged
|
// ProseMirror should handle any selections
|
||||||
|
if (mutation.type === 'selection') {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// try to prevent a bug on iOS that will break node views on enter
|
||||||
|
// this is because ProseMirror can’t preventDispatch on enter
|
||||||
|
// this will lead to a re-render of the node view on enter
|
||||||
|
// see: https://github.com/ueberdosis/tiptap/issues/1214
|
||||||
|
if (this.dom.contains(mutation.target) && mutation.type === 'childList' && isiOS()) {
|
||||||
|
const changedNodes = [
|
||||||
|
...Array.from(mutation.addedNodes),
|
||||||
|
...Array.from(mutation.removedNodes),
|
||||||
|
] as HTMLElement[]
|
||||||
|
|
||||||
|
// we’ll check if every changed node is contentEditable
|
||||||
|
// to make sure it’s probably mutated by ProseMirror
|
||||||
|
if (changedNodes.every(node => node.isContentEditable)) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// we will allow mutation contentDOM with attributes
|
||||||
|
// so we can for example adding classes within our node view
|
||||||
|
if (this.contentDOM === mutation.target && mutation.type === 'attributes') {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// ProseMirror should handle any changes within contentDOM
|
||||||
|
if (this.contentDOM.contains(mutation.target)) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
updateAttributes(attributes: {}) {
|
updateAttributes(attributes: {}) {
|
||||||
|
|||||||
12
packages/core/src/utilities/isiOS.ts
Normal file
12
packages/core/src/utilities/isiOS.ts
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
export default function isiOS(): boolean {
|
||||||
|
return [
|
||||||
|
'iPad Simulator',
|
||||||
|
'iPhone Simulator',
|
||||||
|
'iPod Simulator',
|
||||||
|
'iPad',
|
||||||
|
'iPhone',
|
||||||
|
'iPod',
|
||||||
|
].includes(navigator.platform)
|
||||||
|
// iPad on iOS 13 detection
|
||||||
|
|| (navigator.userAgent.includes('Mac') && 'ontouchend' in document)
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user