{"action":"created","issue":{"url":"https://api.github.com/repos/ianstormtaylor/slate/issues/2062","repository_url":"https://api.github.com/repos/ianstormtaylor/slate","labels_url":"https://api.github.com/repos/ianstormtaylor/slate/issues/2062/labels{/name}","comments_url":"https://api.github.com/repos/ianstormtaylor/slate/issues/2062/comments","events_url":"https://api.github.com/repos/ianstormtaylor/slate/issues/2062/events","html_url":"https://github.com/ianstormtaylor/slate/issues/2062","id":348916624,"node_id":"MDU6SXNzdWUzNDg5MTY2MjQ=","number":2062,"title":"fix editing with \"soft keyboards\" (eg. Android, IMEs)","user":{"login":"ianstormtaylor","id":311752,"node_id":"MDQ6VXNlcjMxMTc1Mg==","avatar_url":"https://avatars0.githubusercontent.com/u/311752?v=4","gravatar_id":"","url":"https://api.github.com/users/ianstormtaylor","html_url":"https://github.com/ianstormtaylor","followers_url":"https://api.github.com/users/ianstormtaylor/followers","following_url":"https://api.github.com/users/ianstormtaylor/following{/other_user}","gists_url":"https://api.github.com/users/ianstormtaylor/gists{/gist_id}","starred_url":"https://api.github.com/users/ianstormtaylor/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ianstormtaylor/subscriptions","organizations_url":"https://api.github.com/users/ianstormtaylor/orgs","repos_url":"https://api.github.com/users/ianstormtaylor/repos","events_url":"https://api.github.com/users/ianstormtaylor/events{/privacy}","received_events_url":"https://api.github.com/users/ianstormtaylor/received_events","type":"User","site_admin":false},"labels":[{"id":404055005,"node_id":"MDU6TGFiZWw0MDQwNTUwMDU=","url":"https://api.github.com/repos/ianstormtaylor/slate/labels/bug","name":"bug","color":"f9d0c4","default":true},{"id":404108549,"node_id":"MDU6TGFiZWw0MDQxMDg1NDk=","url":"https://api.github.com/repos/ianstormtaylor/slate/labels/%E2%9A%91%20cross%20platform","name":"⚑ cross platform","color":"eeeeee","default":false}],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":35,"created_at":"2018-08-08T22:36:02Z","updated_at":"2018-08-21T17:15:23Z","closed_at":null,"author_association":"OWNER","body":"#### Do you want to request a _feature_ or report a _bug_?\r\n\r\nBug.\r\n\r\n#### What's the current behavior?\r\n\r\nThe issue with using Slate on Android is complex, and due to a difference in how its OS keyboard is designed. On mobile devices, keyboards are starting to move away from the \"keys\" concepts in many ways...\r\n\r\n- Autocorrect will make changes without any \"key\" being press.\r\n- Autosuggest will insert words that don't map to keys.\r\n- Swipe-to-type will insert entire words in one go, instead of using keys.\r\n- etc.\r\n\r\nBecause of this, it sounds like the Android team (reasonably from their point of view) decided to not reliably fire key-related events. \r\n\r\n> As soft input methods can use multiple and inventive ways of inputting text, there is no guarantee that any key press on a soft keyboard will generate a key event: this is left to the IME's discretion, and in fact sending such events is discouraged. You should never rely on receiving KeyEvents for any key on a soft input method.\r\n> —[`KeyEvent`, Android Reference](https://developer.android.com/reference/android/view/KeyEvent)\r\n\r\nIt sounds like the behavior is:\r\n\r\n- The `keypress` event is never triggered, which is fine for us.\r\n- Text-based keys like <kbd>a</kbd>, <kbd>b</kbd>, etc. fire a `keydown` event but always with a [key code of `229`](https://stackoverflow.com/questions/36753548/keycode-on-android-is-always-229), indicating that [the key is unidentifiable](https://stackoverflow.com/questions/30743490/capture-keys-typed-on-android-virtual-keyboard-using-javascript) because the keyboard is still busy processing IME input, which may invalidate the actual key pressed.\r\n- Pressing keys like <kbd>enter</kbd> fires a `keydown` event as normal, with an `event.key` that can be recognized? (This is unclear whether this happens or not.)\r\n- Pressing <kbd>backspace</kbd> does not fire a proper `keydown` event.\r\n\r\nA few different resources:\r\n\r\n- Great Android postmortem writeup: https://docs.google.com/document/d/1Hex89Di-r-Wfpo1DLAtxpetoX588ziXVoNyC87Je3Xc/edit#\r\n- Chrome \"bug\": https://bugs.chromium.org/p/chromium/issues/detail?id=118639\r\n- React issues: https://github.com/facebook/react/issues/4079 https://github.com/facebook/react/issues/6176 https://github.com/facebook/react/issues/11231\r\n- VSCode's IME test docs: https://github.com/Microsoft/vscode/wiki/IME-Test\r\n- @danburzo's input methods: https://github.com/danburzo/input-methods\r\n\r\n#### What's the expected behavior?\r\n\r\nThe fix for this is also complicated. There are a handful of different, overlapping pieces of logic that need to change, to accommodate a handful of different input types...\r\n\r\nThe first stage is to handle basic insertions, and auto-suggestions...\r\n\r\n- [ ] Remove the `preventDefault` in `onBeforeInput`, so that the DOM is updated, and the `onInput` logic will trigger, diffing the insertion and then \"fixing\" it.\r\n- [ ] Update the `<Leaf>` (and other?) components to increment their `key` such that React properly unmounts and reconciles the DOM, since it has changed out from under it.\r\n\r\nThis is actually the same starting steps as is required for https://github.com/ianstormtaylor/slate/issues/2060, so I'd recommend we solve that issue in its entirety first, to work from a solid base. \r\n\r\nThis fixes the actual text insertion pieces, and probably deletions as well. Splitting blocks can still be handled by <kbd>enter</kbd> because it still provide proper key codes.\r\n\r\n- [ ] Check that all other behaviors that aren't text insertions (eg. splitting blocks) are handled properly without access to many `keydown` events.\r\n\r\nAnd then there's some selection issues, which apparently can mess up Android's IME (and potentially others) if the selection is manually changed during a composition.\r\n\r\n- [ ] Prevent re-rendering the editor on `compositionstart` and `compositionend`.\r\n- [ ] Prevent updating the selection while a composition is taking place.\r\n\r\nI think this would solve the 90% case for soft keyboard input.\r\n\r\n---\r\n\r\nSeparately, there's still another question of how to properly handle these kinds of behaviors other plugins. For example if a plugin uses <kbd>backspace</kbd> at the start of a block to reset that block, that won't work on Android. So after solving the input issues, we need to step back to an architectural level and solve this plugin handling problem. But that can wait."},"comment":{"url":"https://api.github.com/repos/ianstormtaylor/slate/issues/comments/414751831","html_url":"https://github.com/ianstormtaylor/slate/issues/2062#issuecomment-414751831","issue_url":"https://api.github.com/repos/ianstormtaylor/slate/issues/2062","id":414751831,"node_id":"MDEyOklzc3VlQ29tbWVudDQxNDc1MTgzMQ==","user":{"login":"ianstormtaylor","id":311752,"node_id":"MDQ6VXNlcjMxMTc1Mg==","avatar_url":"https://avatars0.githubusercontent.com/u/311752?v=4","gravatar_id":"","url":"https://api.github.com/users/ianstormtaylor","html_url":"https://github.com/ianstormtaylor","followers_url":"https://api.github.com/users/ianstormtaylor/followers","following_url":"https://api.github.com/users/ianstormtaylor/following{/other_user}","gists_url":"https://api.github.com/users/ianstormtaylor/gists{/gist_id}","starred_url":"https://api.github.com/users/ianstormtaylor/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ianstormtaylor/subscriptions","organizations_url":"https://api.github.com/users/ianstormtaylor/orgs","repos_url":"https://api.github.com/users/ianstormtaylor/repos","events_url":"https://api.github.com/users/ianstormtaylor/events{/privacy}","received_events_url":"https://api.github.com/users/ianstormtaylor/received_events","type":"User","site_admin":false},"created_at":"2018-08-21T17:15:23Z","updated_at":"2018-08-21T17:15:23Z","author_association":"OWNER","body":"@thesunny feel free to make any changes to the selection updating logic. Right now it does update on every render (although I think it checks to see if it needs to, not sure), but there's no reason we have to do that specifically. It just needs to ensure that the selection doesn't get out of date.\r\n\r\nNot sure about the other places for re-renders.\r\n\r\n---\r\n\r\n@thesunny @Slapbox @gaearon I think it's pretty reasonable for React to not include any `contenteditable`-related conveniences. This is the domain of Draft.js and Slate to provide these things, and if they happen to be shareable then they should be separate libraries. Trying to paper over `compositionend` for example is something that would be super complex (if not impossible) for React to manage, and <1% of their users will ever care about it. This definitely doesn't belong in React, and belongs in Slate instead.\r\n\r\n---\r\n\r\n@gaearon as for browser bugs, I'm not sure we have bugs specifically. But one of the big issues right now that we face with React is the discrepancy between real and synthetic events. For example...\r\n\r\nhttps://github.com/facebook/react/issues/11211 - The native `beforeinput` is not accounted for in React right now, which requires us to attach our own listener, which behaves slightly differently. This seems like a fairly easy fix in that it just needs to update the event plugin to check for the real `beforeinput` event in browsers that support it (Safari, Chrome, Opera, iOS Safari, Chrome for Android). This would be awesome to get support in React core.\r\n\r\nhttps://github.com/facebook/react/issues/5785 - Similarly, the `onSelect` handler for React has some limitations, and we're forced to attach our own `selectionchange` listener instead to get around them. It would be nice if React exposed the native `selectionchange` and `selectionstart` event handlers I'd think, since these are supported across most browsers going back a long ways. The only complication here might be the high frequency of them being trigger? I'm not sure what the limitations on the synthetic event pool are, but this might run into them.\r\n\r\nhttps://github.com/facebook/react/issues/13104 - This is another one. If React added the `beforeinput` from above, we'd still need to dip into the `nativeEvent` right now to check the `isComposing` flag I think."}}
{"actor":{"display_login":"ianstormtaylor"}}