Skip to content
This repository was archived by the owner on Feb 6, 2023. It is now read-only.

Conversation

@fabiomcosta
Copy link
Contributor

@fabiomcosta fabiomcosta commented Mar 8, 2019

Summary

This PR attempts to fix long standing issues on Android, mostly related to how it handles composition events.
Currently it's impossible to edit anything on a draft-js Editor field. Even basic operations like "[word][space]" are not possible.
The intent of this PR is not to fix every single Android bug, but to have an editing experience on Android without introducing bugs.

TODO, known issues:

  • Removing empty line breaks with doesn’t remove blocks.

TODO, others:

  • Unit tests

Known issues, that might not be fixed on this PR:

  • Pressing ENTER during a composition doesn’t commit it. Ex: type "hel[enter]", and notice that nothing happens when you click enter, but the expected behavior is to commit that composition and add a line break.
  • [minor] Arrow keys won't work during composition

Test Plan

On Android 9 Pie (API 28)

Type "d[space]"
Renders the letter "d" followed by a space.
letter_space_noautocomplete

Type "da[space]"
Renders the expected highlighted autocomplete option, "day" in this case.
letter_space_autocomplete

Type "day[space][backspace][backspace][backspace][backspace]"
Properly removes the text without re-adding the previous text.
backspace_basic

[doesn't work yet] Type "d[space][enter][backspace][enter]"
Shouldn't cause an error and should render "d[space][enter]".

Acknowledgments

Based on ideas from:
#1672
#1774
ianstormtaylor/slate#2565

Useful links:

draft-js 0.10.5 sandbox: https://codesandbox.io/s/ko4zmx633v
plain contenteditable sandbox: https://codesandbox.io/s/q77yqk1nww

@fabiomcosta fabiomcosta changed the title Attempt on fixing known Android issues [WIP] Attempt on fixing known Android issues Mar 8, 2019
gulpfile.js Outdated
'dev',
gulp.series(function() {
gulp.watch(paths.src, ['modules', 'dist']);
gulp.watch(paths.src, gulp.parallel('modules', 'dist'));
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These changes are introduced separately by #2030

@claudiopro
Copy link
Contributor

Hi @fabiomcosta, thanks for taking the time to submit improvements for the Android editing experience. I'll set some time aside to review them in the coming days as I'm not familiar with the quirks of this platform. In the meantime, I'll look for someone internal to Facebook who can give you a code review faster.

@fabiomcosta
Copy link
Contributor Author

fabiomcosta commented Mar 10, 2019 via email

@claudiopro
Copy link
Contributor

Sounds good @fabiomcosta, thank you so much for this!

@fabiomcosta
Copy link
Contributor Author

@claudiopro this is a quick one though: #2030

@claudiopro
Copy link
Contributor

Sure, see my comments on #2030 😄

…will never work with the data that comes from the event and will be working on a new approach next
@fabiomcosta
Copy link
Contributor Author

I noticed this approach won't work when doing multiple compositions, which can happen on Android.
I'm working on a new experiment that uses Prosemirror's DOMObserver: https://github.com/ProseMirror/prosemirror-view/blob/409f267d6f4dc534637acc708fcac582274da6ce/src/domobserver.js

Prosemirror, for the ones that don't know, is a very solid project that works flawlessly on Android and other devices.

I might create a new PR for that, we'll see.

@fabiomcosta
Copy link
Contributor Author

@claudiopro I'm closing this in favor of #2035, which is handling composition events in a much more consistent way.
I'm pretty pumped!

facebook-github-bot pushed a commit that referenced this pull request May 9, 2019
Summary:
This PR is a new attempt to address #1895

On #2031 I was trying to make compositions work using the data provided by that event, and even though that works well for most operational system, that doesn't work well for Android, where you can make composition updates in multiple places on the same composition transaction.

This PR is an improvement over that PR, in that it uses a DOM mutation observer during the `compositionStart` -> `compositionEnd` interval to detect the changes the user made, and then re-apply those to the ContentState on `compositionEnd`.

This approach is the one used by [Prosemirror](http://prosemirror.net/) (see https://github.com/ProseMirror/prosemirror-view/blob/master/src/domobserver.js), which is the only Rich Text Editor I've tried that works well on Android.
Like previously mentioned, it allows multiple mutations on multiple places in the same composition transaction, which was impossible with the previous approach, and would cause DOM<->state inconsistencies in multiple use cases.

The intent of this PR is not to fix every single Android bug, but to have a consistent editing experience on Android without introducing bugs (ideally).

**TODO, known issues:**
- [x] Removing empty line breaks with <backspace> doesn’t remove blocks.
- [x] Mutations on the same block (different leaf nodes) are not being properly applied.
- [x] Selection is not properly updated during composition events
- [ ] Keep `inlineStyleOverride` working with a consistent behavior

**TODO, others:**
- [x] Test on Android Pie v9 API 28
- [x] Test on Android Oreo v8.1 API 27
- [x] Test on Android Oreo v8.0 API 26
- [x] Test on iPhone 12.1 (with Japanese Kana keyboard)
- [x] Test composition events on Chrome Desktop v73
- [x] Test composition on IE11 (I didn't know how to test composition events though)
- [x] Unit tests

There are 3 ways to try out this PR.

Codesandbox: https://3ymzzlj9n5.codesandbox.io/ (uses `draft-js-android-fix-beta.3`)

Use the published [draft-js-android-fix](https://www.npmjs.com/package/draft-js-android-fix) package: `yarn install draft-js-android-fix`

Note that this package might not be up-to-date, it's hard for me to guarantee I'll always remember to update the package, but I'll do my best.

The other way is guaranteed to be up-to-date, but has a longer setup:
* run `git clone https://github.com/facebook/draft-js.git`
* run `git remote add fabiomcosta https://github.com/fabiomcosta/draft-js.git`
* run `git fetch fabiomcosta`
* run `git checkout -b attempt_android_fix_with_dom_diff fabiomcosta/attempt_android_fix_with_dom_diff`
* run `yarn install` (or use `npm`)
* run `open examples/draft-0-10-0/rich/rich.html`, or any other example you'd like to test
Pull Request resolved: #2035

Reviewed By: kedromelon

Differential Revision: D14568528

Pulled By: claudiopro

fbshipit-source-id: 16861de52eca41cd98f884b0aecf034213fc1bd0
jdecked pushed a commit to twitter-forks/draft-js that referenced this pull request Oct 9, 2019
Summary:
This PR is a new attempt to address facebookarchive#1895

On facebookarchive#2031 I was trying to make compositions work using the data provided by that event, and even though that works well for most operational system, that doesn't work well for Android, where you can make composition updates in multiple places on the same composition transaction.

This PR is an improvement over that PR, in that it uses a DOM mutation observer during the `compositionStart` -> `compositionEnd` interval to detect the changes the user made, and then re-apply those to the ContentState on `compositionEnd`.

This approach is the one used by [Prosemirror](http://prosemirror.net/) (see https://github.com/ProseMirror/prosemirror-view/blob/master/src/domobserver.js), which is the only Rich Text Editor I've tried that works well on Android.
Like previously mentioned, it allows multiple mutations on multiple places in the same composition transaction, which was impossible with the previous approach, and would cause DOM<->state inconsistencies in multiple use cases.

The intent of this PR is not to fix every single Android bug, but to have a consistent editing experience on Android without introducing bugs (ideally).

**TODO, known issues:**
- [x] Removing empty line breaks with <backspace> doesn’t remove blocks.
- [x] Mutations on the same block (different leaf nodes) are not being properly applied.
- [x] Selection is not properly updated during composition events
- [ ] Keep `inlineStyleOverride` working with a consistent behavior

**TODO, others:**
- [x] Test on Android Pie v9 API 28
- [x] Test on Android Oreo v8.1 API 27
- [x] Test on Android Oreo v8.0 API 26
- [x] Test on iPhone 12.1 (with Japanese Kana keyboard)
- [x] Test composition events on Chrome Desktop v73
- [x] Test composition on IE11 (I didn't know how to test composition events though)
- [x] Unit tests

There are 3 ways to try out this PR.

Codesandbox: https://3ymzzlj9n5.codesandbox.io/ (uses `draft-js-android-fix-beta.3`)

Use the published [draft-js-android-fix](https://www.npmjs.com/package/draft-js-android-fix) package: `yarn install draft-js-android-fix`

Note that this package might not be up-to-date, it's hard for me to guarantee I'll always remember to update the package, but I'll do my best.

The other way is guaranteed to be up-to-date, but has a longer setup:
* run `git clone https://github.com/facebook/draft-js.git`
* run `git remote add fabiomcosta https://github.com/fabiomcosta/draft-js.git`
* run `git fetch fabiomcosta`
* run `git checkout -b attempt_android_fix_with_dom_diff fabiomcosta/attempt_android_fix_with_dom_diff`
* run `yarn install` (or use `npm`)
* run `open examples/draft-0-10-0/rich/rich.html`, or any other example you'd like to test
Pull Request resolved: facebookarchive#2035

Reviewed By: kedromelon

Differential Revision: D14568528

Pulled By: claudiopro

fbshipit-source-id: 16861de52eca41cd98f884b0aecf034213fc1bd0
mmissey pushed a commit to mmissey/draft-js that referenced this pull request Mar 24, 2020
Summary:
This PR is a new attempt to address facebookarchive#1895

On facebookarchive#2031 I was trying to make compositions work using the data provided by that event, and even though that works well for most operational system, that doesn't work well for Android, where you can make composition updates in multiple places on the same composition transaction.

This PR is an improvement over that PR, in that it uses a DOM mutation observer during the `compositionStart` -> `compositionEnd` interval to detect the changes the user made, and then re-apply those to the ContentState on `compositionEnd`.

This approach is the one used by [Prosemirror](http://prosemirror.net/) (see https://github.com/ProseMirror/prosemirror-view/blob/master/src/domobserver.js), which is the only Rich Text Editor I've tried that works well on Android.
Like previously mentioned, it allows multiple mutations on multiple places in the same composition transaction, which was impossible with the previous approach, and would cause DOM<->state inconsistencies in multiple use cases.

The intent of this PR is not to fix every single Android bug, but to have a consistent editing experience on Android without introducing bugs (ideally).

**TODO, known issues:**
- [x] Removing empty line breaks with <backspace> doesn’t remove blocks.
- [x] Mutations on the same block (different leaf nodes) are not being properly applied.
- [x] Selection is not properly updated during composition events
- [ ] Keep `inlineStyleOverride` working with a consistent behavior

**TODO, others:**
- [x] Test on Android Pie v9 API 28
- [x] Test on Android Oreo v8.1 API 27
- [x] Test on Android Oreo v8.0 API 26
- [x] Test on iPhone 12.1 (with Japanese Kana keyboard)
- [x] Test composition events on Chrome Desktop v73
- [x] Test composition on IE11 (I didn't know how to test composition events though)
- [x] Unit tests

There are 3 ways to try out this PR.

Codesandbox: https://3ymzzlj9n5.codesandbox.io/ (uses `draft-js-android-fix-beta.3`)

Use the published [draft-js-android-fix](https://www.npmjs.com/package/draft-js-android-fix) package: `yarn install draft-js-android-fix`

Note that this package might not be up-to-date, it's hard for me to guarantee I'll always remember to update the package, but I'll do my best.

The other way is guaranteed to be up-to-date, but has a longer setup:
* run `git clone https://github.com/facebook/draft-js.git`
* run `git remote add fabiomcosta https://github.com/fabiomcosta/draft-js.git`
* run `git fetch fabiomcosta`
* run `git checkout -b attempt_android_fix_with_dom_diff fabiomcosta/attempt_android_fix_with_dom_diff`
* run `yarn install` (or use `npm`)
* run `open examples/draft-0-10-0/rich/rich.html`, or any other example you'd like to test
Pull Request resolved: facebookarchive#2035

Reviewed By: kedromelon

Differential Revision: D14568528

Pulled By: claudiopro

fbshipit-source-id: 16861de52eca41cd98f884b0aecf034213fc1bd0
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants