We’ve been attempting to get our editor working in an Android webview. It’s been a struggle but we’ve gotten it into a usable state. However, the cursorWrapper has been a problem and we are trying out disabling it for Android specifically.
Because the cursorWrapper is inserted on compositionstart due to the markCursor logic, the Android IME is often thrown off. We see text being deleted when hitting enter, the selection ending up one position off, and occasional duplicate characters. Inserting nodes at the start of a composition seems to just be too confusing for Android to handle.
Based off of what was brought up in this thread What does the cursorwrapper solve?, I saw that there were a number of issues with the cursor wrapper and that the approach was migrated from CKEditor. I’m wondering if there are any potential alternatives and if there has been any progress recently.
See also this thread. We recently moved to creating cursor wrappers a lot less often, but during composition, it’s hard to avoid, or the user will see the text in the wrong style.
Right, I recall the changes and the testing yielded decent results in most situations. However, Android simply can’t handle the cursor wrapper. Turning it off by creating a getter for the view object that always returns null for markCursor fixed a ton of problems for us. The mark styles are eventually consistent so you don’t lose data, it just feels a little weird.
It seems like on Android at least, the right long term solution would need to be a persistent cursor wrapper that doesn’t alter the dom on compositionstart. Another alternative is to try to do the cursor wrapper before the composition starts on Android. However, I’m sure this would break other browsers.
Would it be worth coming up with a solution that is different for different environment? I’d be happy to help work on this if there is a rough plan in place.
Given that I’ve tested this quite extensively on Android, I’d be interested in a more specific description of the problem here.
I’ll work to get a few examples. If you don’t fire transactions during inputs, it’s not too bad. The big problem comes in when you have plugin logic that fires during composition and input events. I’ll see if I can get a few problems that occur during unhandled editing actions.
I’m still figuring out how best to set up a bare bones webview with prosemirror, but on mobile Chrome with the demo editor, I am seeing an issue with pending styles. If you hit a few marks in the toolbar to set stored marks and then start typing, the selection resets after the first character.
I can try to get a few more next week as I’ll be on vacation for the rest of the week.
I can reproduce the weirdness when starting a composition with marks enabled. prosemirror-view 1.11.7 should help with that.
Could you file issues on the bug tracker for further problems?
Thanks Marijn, I can file individual bugs for the composition issues. It’s tough to isolate the exact issues on the demo editor at this point but I can keep working on it. We have a lot of Android handling for input events (for mapping backspaces and what not) so it muddies the waters a bit.
Looks like the issues are still there even with the patch. The selection moving is one of the problems, but there is a bigger problem where the IME gets confused. You end up with duplicate characters and random phrases deleted. I’ll work on repro with the demo editor and file bugs on Github.
I know we had discussed this specific issue before, but one of the issues related to the cursor wrapper that is very apparent on Android is that when you set stored marks during a composition, you don’t see the marks until after the compositions ends. To repro
- Type “Test” without completing the composition
- Hit bold, italic, or underline in the toolbar
- Continue typing
You do not see the styles until after you hit enter (which is essentially what happens all of the time if you just completely disable the mark cursor).
Another issue that we had tackled is that if you dispatch a transaction on compositionstart or compositionend in handleDOMEvents, you end up updating the cursor wrapper (even though it is a meta transaction). This would cause infinite composition loops where the keyboard would spaz out. We had to have getters and setters in place to “lock” the cursor wrapper while we were dispatching a transaction. The easiest way to get around that specific issue is to only update the cursor wrapper when the doc or selection has changed when updating the state.
I’d be happy to file Github issues for those two problems, but the other sets of issues are still a bit tough because most of them have to do with custom key handling. We have a way to map input events to synthetic backspace events and Enter keydowns often work. If you have custom handling on enter and the selection ends up in a spot that then triggers a composition start, Android will get confused when it sees the markcursor. The combination of updating the dom programmatically on keydown and having a composition trigger seems to be the underlying culprit. I’m going to investigate a bit more and try suppressing the markcursor temporarily.
I was able to break it a bit by setting stored marks when hitting enter here https://glitch.com/edit/#!/gleaming-hall?path=index.js:65:29. I wasn’t experiencing the same bugs but you do start experience bad behavior. I’ll try to further pinpoint tomorrow to actually file Github issues.