Refactor composition handling to support prosemirror-view behavior#219
Refactor composition handling to support prosemirror-view behavior#219smoores-dev wants to merge 7 commits into
Conversation
| // When we insert the text that corresponds to an ongoing composition, | ||
| // the relevant TextNodeView will pause re-rendering so that React doesn't | ||
| // clobber the composition in the DOM. This means that we have to wait for | ||
| // the browser to update the DOM itself before attempting to reconcile | ||
| // the selection, so we specifically defer pending effects to the next | ||
| // macro task | ||
| if (view instanceof ReactEditorView) { | ||
| view.deferPendingEffects = true; | ||
| } |
There was a problem hiding this comment.
Another option I'm considering, but haven't tested yet, is doing like view.dom.once('input', () => {...}) in the beforeinput handler, and running the view.dispatch from there. That feels like it should allow us to drop the setTimeout in commitPendingEffects. I tried using an input handler yesterday and there was some other timing issue that I now can't remember, so it's possible that won't be an option.
There was a problem hiding this comment.
I was unable to get this working :/ but I do think that the current setTimeout implementation is working quite well. It does seem like maybe the selection management isn't quite right yet (only an issue during the composition, before and after the selection is set correctly and works as expected).
|
Ok, fixed up a few more things. Two known limitations/issues:
|
64e36b9 to
03ff218
Compare
3521f75 to
4a64892
Compare
e1b4bf2 to
073ef98
Compare
ProseMirror View's composition handling does not match my initial read of the code from years ago. Here's the actual behavior:
This doesn't yet handle the second case, but just handling the first case was very challenging with our setup.
Just as a refresher, here's our flow for a normal input:
I have updated compositions to follow a similar-ish flow, but it is more complicated:
this.renderRef. This is strictly necessary — updating the rendered content will cause React to overwrite the composition node, and the browser will cancel the composition.This means that we now have a path that runs
view.commitPendingEffectsin a setTimeout, which I have not convinced myself is safe (but is, I think, no less safe than pm-view's approach?). In addition, for the same reason, the code inuseNodeViewDescriptionthat finds the newly-created composition node and assigns it to the CompositionNodeView has to run in a setTimeout (it will still run before the commitPendingEffects call, which is what matters).I still have to update this to fix the second behavior from above, and I'll probably have to update the composition tests as well.