{"action":"created","comment":{"url":"https://api.github.com/repos/Automattic/simplenote-electron/pulls/comments/94218314","pull_request_review_id":14748914,"id":94218314,"diff_hunk":"@@ -0,0 +1,138 @@\n+import React, { Component, PropTypes } from 'react';\n+import {\n+\tidentity,\n+\tinvoke,\n+} from 'lodash';\n+\n+const KEY_TAB = 9;\n+const KEY_ENTER = 13;\n+\n+const startsWith = prefix => text =>\n+\ttext\n+\t\t.trim()\n+\t\t.toLowerCase()\n+\t\t.startsWith( prefix.trim().toLowerCase() );\n+\n+export class TagInput extends Component {\n+\tstatic propTypes = {\n+\t\tinputRef: PropTypes.func,\n+\t\tonChange: PropTypes.func,\n+\t\tonSelect: PropTypes.func,\n+\t\ttagNames: PropTypes.arrayOf( PropTypes.string ).isRequired,\n+\t\tvalue: PropTypes.string.isRequired,\n+\t};\n+\n+\tstatic defaultProps = {\n+\t\tinputRef: identity,\n+\t\tonChange: identity,\n+\t\tonSelect: identity,\n+\t};\n+\n+\tcomponentWillUnmount() {\n+\t\tthis.inputField && this.inputField.removeEventListener( 'paste', this.removePastedFormatting, false );\n+\t}\n+\n+\tfocusInput = () => {\n+\t\tif ( ! this.inputField ) {\n+\t\t\treturn;\n+\t\t}\n+\n+\t\tconst input = this.inputField;\n+\n+\t\tinput.focus();\n+\t\tconst range = document.createRange();\n+\t\trange.selectNodeContents( input );\n+\t\trange.collapse( false );\n+\t\tconst selection = window.getSelection();\n+\t\tselection.removeAllRanges();\n+\t\tselection.addRange( range );\n+\t};\n+\n+\tinterceptKeys = event => invoke( {\n+\t\t[ KEY_ENTER ]: this.submitTag,\n+\t\t[ KEY_TAB ]: this.interceptTabPress,\n+\t}, event.keyCode, event );\n+\n+\tinterceptTabPress = event => {\n+\t\tconst { onChange, tagNames, value } = this.props;\n+\n+\t\tif ( ! value.length ) {\n+\t\t\treturn;\n+\t\t}\n+\n+\t\tconst suggestion = tagNames.find( startsWith( value ) );\n+\n+\t\tif ( suggestion ) {\n+\t\t\tonChange( suggestion, this.focusInput );\n+\t\t}\n+\n+\t\tevent.preventDefault();\n+\t\tevent.stopPropagation();\n+\t};\n+\n+\tonChange = ( { target: { textContent: value } } ) =>\n+\t\tvalue.endsWith( ',' ) && value.trim().length // commas should automatically insert non-zero tags\n+\t\t\t? this.props.onSelect( value.slice( 0, -1 ).trim() )\n+\t\t\t: this.props.onChange( value.trim() );\n+\n+\tremovePastedFormatting = event => {\n+\t\tdocument.execCommand(\n+\t\t\t'insertHTML',\n+\t\t\tfalse, // don't show default UI - see execCommand docs for explanation\n+\t\t\tevent.clipboardData.getData( 'text/plain' ),\n+\t\t);\n+\n+\t\tevent.preventDefault();\n+\t\tevent.stopPropagation();\n+\t};\n+\n+\tstoreInput = ref => {\n+\t\tthis.inputField = ref;\n+\t\tthis.props.inputRef( ref );\n+\t\tthis.inputField.addEventListener( 'paste', this.removePastedFormatting, false );\n+\t};\n+\n+\tsubmitTag = event => {\n+\t\tconst { onSelect, value } = this.props;\n+\n+\t\tvalue.trim().length && onSelect( value.trim() );\n+\n+\t\tevent.preventDefault();\n+\t\tevent.stopPropagation();\n+\t};\n+\n+\trender() {\n+\t\tconst {\n+\t\t\tvalue,\n+\t\t\ttagNames,\n+\t\t} = this.props;\n+\n+\t\tconst suggestion = value.length && tagNames.find( startsWith( value ) );\n+\n+\t\treturn (\n+\t\t\t<div className=\"tag-input\"\n+\t\t\t\tonClick={ this.focusInput }\n+\t\t\t>\n+\t\t\t\t<div\n+\t\t\t\t\tref={ this.storeInput }\n+\t\t\t\t\tclassName=\"tag-input__entry\"\n+\t\t\t\t\tcontentEditable=\"true\"","path":"lib/tag-input.jsx","position":119,"original_position":119,"commit_id":"b11197bb3545356f0b298b273568dff2e7ce18c0","original_commit_id":"76ac8f0dbe410ab972db71e50bbc6e9d58fa6396","user":{"login":"dmsnell","id":5431237,"avatar_url":"https://avatars.githubusercontent.com/u/5431237?v=3","gravatar_id":"","url":"https://api.github.com/users/dmsnell","html_url":"https://github.com/dmsnell","followers_url":"https://api.github.com/users/dmsnell/followers","following_url":"https://api.github.com/users/dmsnell/following{/other_user}","gists_url":"https://api.github.com/users/dmsnell/gists{/gist_id}","starred_url":"https://api.github.com/users/dmsnell/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dmsnell/subscriptions","organizations_url":"https://api.github.com/users/dmsnell/orgs","repos_url":"https://api.github.com/users/dmsnell/repos","events_url":"https://api.github.com/users/dmsnell/events{/privacy}","received_events_url":"https://api.github.com/users/dmsnell/received_events","type":"User","site_admin":false},"body":"suppressed in b11197b","created_at":"2016-12-30T10:43:33Z","updated_at":"2016-12-30T10:43:34Z","html_url":"https://github.com/Automattic/simplenote-electron/pull/389#discussion_r94218314","pull_request_url":"https://api.github.com/repos/Automattic/simplenote-electron/pulls/389","_links":{"self":{"href":"https://api.github.com/repos/Automattic/simplenote-electron/pulls/comments/94218314"},"html":{"href":"https://github.com/Automattic/simplenote-electron/pull/389#discussion_r94218314"},"pull_request":{"href":"https://api.github.com/repos/Automattic/simplenote-electron/pulls/389"}}},"pull_request":{"url":"https://api.github.com/repos/Automattic/simplenote-electron/pulls/389","id":86572614,"html_url":"https://github.com/Automattic/simplenote-electron/pull/389","diff_url":"https://github.com/Automattic/simplenote-electron/pull/389.diff","patch_url":"https://github.com/Automattic/simplenote-electron/pull/389.patch","issue_url":"https://api.github.com/repos/Automattic/simplenote-electron/issues/389","number":389,"state":"open","locked":false,"title":"Autocomplete tag names when adding new tags","user":{"login":"dmsnell","id":5431237,"avatar_url":"https://avatars.githubusercontent.com/u/5431237?v=3","gravatar_id":"","url":"https://api.github.com/users/dmsnell","html_url":"https://github.com/dmsnell","followers_url":"https://api.github.com/users/dmsnell/followers","following_url":"https://api.github.com/users/dmsnell/following{/other_user}","gists_url":"https://api.github.com/users/dmsnell/gists{/gist_id}","starred_url":"https://api.github.com/users/dmsnell/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dmsnell/subscriptions","organizations_url":"https://api.github.com/users/dmsnell/orgs","repos_url":"https://api.github.com/users/dmsnell/repos","events_url":"https://api.github.com/users/dmsnell/events{/privacy}","received_events_url":"https://api.github.com/users/dmsnell/received_events","type":"User","site_admin":false},"body":"Resolves #19 \r\nResolves #113 \r\nResolves #340 \r\n\r\nEntering new tags in this app can be a glitchy process.\r\n- Although the app only shows unique tags, it allows storing new tags with identical names. You can see this by adding the same tag twice and opening the note in a native app. That tag will be duplicated (as initially reported in #340)\r\n- Without autocomplete, it's easy to add duplicate tags and it's easy to create new tags that should be identical to an existing tag (adding `ofinterest` when `of-interest` already exists)\r\n\r\nThis PR attempts to resolve these issues and clean up the tagging experience. It provides an autocomplete list and prevents creating tags with the same name as existing tags. It also adds a new behavior: clicking on a selected tag will remove it (a double-click on an unselected tag removes it).\r\n\r\n![tagautocomplete](https://cloud.githubusercontent.com/assets/5431237/21560400/09f9d180-ce1c-11e6-99ad-e3249200afd4.gif)\r\n\r\n**Caveats**\r\n<del>Although the autosuggest component I imported seems to have a well-designed API, it appears to have no way to externally trigger a refocus of the input field. For now, that means that the tag input field _does not_ refocus after selecting and deleting an existing tag. The focus should return to the input after adding new tags, however.</del> Resolved in 17e453f with the help of the component author.\r\n\r\n**Testing**\r\nRun the gamut on tag entry and removal.\r\n- Do the tags added correspond to the tags displayed in the other apps?\r\n- If you have a tag selected and change the tags in another app, does the selection behavior meet your expectations? (try adding new tags, deleting other tags, deleting the tag which is selected in the Electron app)\r\n- Can you create duplicate tags (tags with identical names)?\r\n- Does the autocompleter feel right? look right?\r\n\r\n**Known bugs**\r\n - ~The tag input field sits below the rendered tag items~\r\n - ~The tag input field is hidden and hard to find~\r\n - ~Deleting tags is finicky; works sometimes, others not~\r\n - ~Tag suggestion can get slightly out of alignment with actual input~\r\n\r\ncc: @roundhill @drw158 ","created_at":"2016-09-23T20:03:36Z","updated_at":"2016-12-30T10:43:34Z","closed_at":null,"merged_at":null,"merge_commit_sha":"6cbd3791fd74732cd7bf72f8ba2e52d4ff308beb","assignee":null,"assignees":[],"milestone":null,"commits_url":"https://api.github.com/repos/Automattic/simplenote-electron/pulls/389/commits","review_comments_url":"https://api.github.com/repos/Automattic/simplenote-electron/pulls/389/comments","review_comment_url":"https://api.github.com/repos/Automattic/simplenote-electron/pulls/comments{/number}","comments_url":"https://api.github.com/repos/Automattic/simplenote-electron/issues/389/comments","statuses_url":"https://api.github.com/repos/Automattic/simplenote-electron/statuses/b11197bb3545356f0b298b273568dff2e7ce18c0","head":{"label":"Automattic:issues/19-tag-autocomplete","ref":"issues/19-tag-autocomplete","sha":"b11197bb3545356f0b298b273568dff2e7ce18c0","user":{"login":"Automattic","id":887802,"avatar_url":"https://avatars.githubusercontent.com/u/887802?v=3","gravatar_id":"","url":"https://api.github.com/users/Automattic","html_url":"https://github.com/Automattic","followers_url":"https://api.github.com/users/Automattic/followers","following_url":"https://api.github.com/users/Automattic/following{/other_user}","gists_url":"https://api.github.com/users/Automattic/gists{/gist_id}","starred_url":"https://api.github.com/users/Automattic/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Automattic/subscriptions","organizations_url":"https://api.github.com/users/Automattic/orgs","repos_url":"https://api.github.com/users/Automattic/repos","events_url":"https://api.github.com/users/Automattic/events{/privacy}","received_events_url":"https://api.github.com/users/Automattic/received_events","type":"Organization","site_admin":false},"repo":{"id":41199577,"name":"simplenote-electron","full_name":"Automattic/simplenote-electron","owner":{"login":"Automattic","id":887802,"avatar_url":"https://avatars.githubusercontent.com/u/887802?v=3","gravatar_id":"","url":"https://api.github.com/users/Automattic","html_url":"https://github.com/Automattic","followers_url":"https://api.github.com/users/Automattic/followers","following_url":"https://api.github.com/users/Automattic/following{/other_user}","gists_url":"https://api.github.com/users/Automattic/gists{/gist_id}","starred_url":"https://api.github.com/users/Automattic/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Automattic/subscriptions","organizations_url":"https://api.github.com/users/Automattic/orgs","repos_url":"https://api.github.com/users/Automattic/repos","events_url":"https://api.github.com/users/Automattic/events{/privacy}","received_events_url":"https://api.github.com/users/Automattic/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/Automattic/simplenote-electron","description":"A Simplenote React app packaged in Electron","fork":false,"url":"https://api.github.com/repos/Automattic/simplenote-electron","forks_url":"https://api.github.com/repos/Automattic/simplenote-electron/forks","keys_url":"https://api.github.com/repos/Automattic/simplenote-electron/keys{/key_id}","collaborators_url":"https://api.github.com/repos/Automattic/simplenote-electron/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/Automattic/simplenote-electron/teams","hooks_url":"https://api.github.com/repos/Automattic/simplenote-electron/hooks","issue_events_url":"https://api.github.com/repos/Automattic/simplenote-electron/issues/events{/number}","events_url":"https://api.github.com/repos/Automattic/simplenote-electron/events","assignees_url":"https://api.github.com/repos/Automattic/simplenote-electron/assignees{/user}","branches_url":"https://api.github.com/repos/Automattic/simplenote-electron/branches{/branch}","tags_url":"https://api.github.com/repos/Automattic/simplenote-electron/tags","blobs_url":"https://api.github.com/repos/Automattic/simplenote-electron/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/Automattic/simplenote-electron/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/Automattic/simplenote-electron/git/refs{/sha}","trees_url":"https://api.github.com/repos/Automattic/simplenote-electron/git/trees{/sha}","statuses_url":"https://api.github.com/repos/Automattic/simplenote-electron/statuses/{sha}","languages_url":"https://api.github.com/repos/Automattic/simplenote-electron/languages","stargazers_url":"https://api.github.com/repos/Automattic/simplenote-electron/stargazers","contributors_url":"https://api.github.com/repos/Automattic/simplenote-electron/contributors","subscribers_url":"https://api.github.com/repos/Automattic/simplenote-electron/subscribers","subscription_url":"https://api.github.com/repos/Automattic/simplenote-electron/subscription","commits_url":"https://api.github.com/repos/Automattic/simplenote-electron/commits{/sha}","git_commits_url":"https://api.github.com/repos/Automattic/simplenote-electron/git/commits{/sha}","comments_url":"https://api.github.com/repos/Automattic/simplenote-electron/comments{/number}","issue_comment_url":"https://api.github.com/repos/Automattic/simplenote-electron/issues/comments{/number}","contents_url":"https://api.github.com/repos/Automattic/simplenote-electron/contents/{+path}","compare_url":"https://api.github.com/repos/Automattic/simplenote-electron/compare/{base}...{head}","merges_url":"https://api.github.com/repos/Automattic/simplenote-electron/merges","archive_url":"https://api.github.com/repos/Automattic/simplenote-electron/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/Automattic/simplenote-electron/downloads","issues_url":"https://api.github.com/repos/Automattic/simplenote-electron/issues{/number}","pulls_url":"https://api.github.com/repos/Automattic/simplenote-electron/pulls{/number}","milestones_url":"https://api.github.com/repos/Automattic/simplenote-electron/milestones{/number}","notifications_url":"https://api.github.com/repos/Automattic/simplenote-electron/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/Automattic/simplenote-electron/labels{/name}","releases_url":"https://api.github.com/repos/Automattic/simplenote-electron/releases{/id}","deployments_url":"https://api.github.com/repos/Automattic/simplenote-electron/deployments","created_at":"2015-08-22T09:06:44Z","updated_at":"2016-12-29T23:18:40Z","pushed_at":"2016-12-30T10:43:24Z","git_url":"git://github.com/Automattic/simplenote-electron.git","ssh_url":"git@github.com:Automattic/simplenote-electron.git","clone_url":"https://github.com/Automattic/simplenote-electron.git","svn_url":"https://github.com/Automattic/simplenote-electron","homepage":"","size":10375,"stargazers_count":1025,"watchers_count":1025,"language":"JavaScript","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":145,"mirror_url":null,"open_issues_count":124,"forks":145,"open_issues":124,"watchers":1025,"default_branch":"master"}},"base":{"label":"Automattic:master","ref":"master","sha":"d761694daa326df1f73f63a0d5541464ec489ce5","user":{"login":"Automattic","id":887802,"avatar_url":"https://avatars.githubusercontent.com/u/887802?v=3","gravatar_id":"","url":"https://api.github.com/users/Automattic","html_url":"https://github.com/Automattic","followers_url":"https://api.github.com/users/Automattic/followers","following_url":"https://api.github.com/users/Automattic/following{/other_user}","gists_url":"https://api.github.com/users/Automattic/gists{/gist_id}","starred_url":"https://api.github.com/users/Automattic/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Automattic/subscriptions","organizations_url":"https://api.github.com/users/Automattic/orgs","repos_url":"https://api.github.com/users/Automattic/repos","events_url":"https://api.github.com/users/Automattic/events{/privacy}","received_events_url":"https://api.github.com/users/Automattic/received_events","type":"Organization","site_admin":false},"repo":{"id":41199577,"name":"simplenote-electron","full_name":"Automattic/simplenote-electron","owner":{"login":"Automattic","id":887802,"avatar_url":"https://avatars.githubusercontent.com/u/887802?v=3","gravatar_id":"","url":"https://api.github.com/users/Automattic","html_url":"https://github.com/Automattic","followers_url":"https://api.github.com/users/Automattic/followers","following_url":"https://api.github.com/users/Automattic/following{/other_user}","gists_url":"https://api.github.com/users/Automattic/gists{/gist_id}","starred_url":"https://api.github.com/users/Automattic/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Automattic/subscriptions","organizations_url":"https://api.github.com/users/Automattic/orgs","repos_url":"https://api.github.com/users/Automattic/repos","events_url":"https://api.github.com/users/Automattic/events{/privacy}","received_events_url":"https://api.github.com/users/Automattic/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/Automattic/simplenote-electron","description":"A Simplenote React app packaged in Electron","fork":false,"url":"https://api.github.com/repos/Automattic/simplenote-electron","forks_url":"https://api.github.com/repos/Automattic/simplenote-electron/forks","keys_url":"https://api.github.com/repos/Automattic/simplenote-electron/keys{/key_id}","collaborators_url":"https://api.github.com/repos/Automattic/simplenote-electron/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/Automattic/simplenote-electron/teams","hooks_url":"https://api.github.com/repos/Automattic/simplenote-electron/hooks","issue_events_url":"https://api.github.com/repos/Automattic/simplenote-electron/issues/events{/number}","events_url":"https://api.github.com/repos/Automattic/simplenote-electron/events","assignees_url":"https://api.github.com/repos/Automattic/simplenote-electron/assignees{/user}","branches_url":"https://api.github.com/repos/Automattic/simplenote-electron/branches{/branch}","tags_url":"https://api.github.com/repos/Automattic/simplenote-electron/tags","blobs_url":"https://api.github.com/repos/Automattic/simplenote-electron/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/Automattic/simplenote-electron/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/Automattic/simplenote-electron/git/refs{/sha}","trees_url":"https://api.github.com/repos/Automattic/simplenote-electron/git/trees{/sha}","statuses_url":"https://api.github.com/repos/Automattic/simplenote-electron/statuses/{sha}","languages_url":"https://api.github.com/repos/Automattic/simplenote-electron/languages","stargazers_url":"https://api.github.com/repos/Automattic/simplenote-electron/stargazers","contributors_url":"https://api.github.com/repos/Automattic/simplenote-electron/contributors","subscribers_url":"https://api.github.com/repos/Automattic/simplenote-electron/subscribers","subscription_url":"https://api.github.com/repos/Automattic/simplenote-electron/subscription","commits_url":"https://api.github.com/repos/Automattic/simplenote-electron/commits{/sha}","git_commits_url":"https://api.github.com/repos/Automattic/simplenote-electron/git/commits{/sha}","comments_url":"https://api.github.com/repos/Automattic/simplenote-electron/comments{/number}","issue_comment_url":"https://api.github.com/repos/Automattic/simplenote-electron/issues/comments{/number}","contents_url":"https://api.github.com/repos/Automattic/simplenote-electron/contents/{+path}","compare_url":"https://api.github.com/repos/Automattic/simplenote-electron/compare/{base}...{head}","merges_url":"https://api.github.com/repos/Automattic/simplenote-electron/merges","archive_url":"https://api.github.com/repos/Automattic/simplenote-electron/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/Automattic/simplenote-electron/downloads","issues_url":"https://api.github.com/repos/Automattic/simplenote-electron/issues{/number}","pulls_url":"https://api.github.com/repos/Automattic/simplenote-electron/pulls{/number}","milestones_url":"https://api.github.com/repos/Automattic/simplenote-electron/milestones{/number}","notifications_url":"https://api.github.com/repos/Automattic/simplenote-electron/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/Automattic/simplenote-electron/labels{/name}","releases_url":"https://api.github.com/repos/Automattic/simplenote-electron/releases{/id}","deployments_url":"https://api.github.com/repos/Automattic/simplenote-electron/deployments","created_at":"2015-08-22T09:06:44Z","updated_at":"2016-12-29T23:18:40Z","pushed_at":"2016-12-30T10:43:24Z","git_url":"git://github.com/Automattic/simplenote-electron.git","ssh_url":"git@github.com:Automattic/simplenote-electron.git","clone_url":"https://github.com/Automattic/simplenote-electron.git","svn_url":"https://github.com/Automattic/simplenote-electron","homepage":"","size":10375,"stargazers_count":1025,"watchers_count":1025,"language":"JavaScript","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":145,"mirror_url":null,"open_issues_count":124,"forks":145,"open_issues":124,"watchers":1025,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/Automattic/simplenote-electron/pulls/389"},"html":{"href":"https://github.com/Automattic/simplenote-electron/pull/389"},"issue":{"href":"https://api.github.com/repos/Automattic/simplenote-electron/issues/389"},"comments":{"href":"https://api.github.com/repos/Automattic/simplenote-electron/issues/389/comments"},"review_comments":{"href":"https://api.github.com/repos/Automattic/simplenote-electron/pulls/389/comments"},"review_comment":{"href":"https://api.github.com/repos/Automattic/simplenote-electron/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/Automattic/simplenote-electron/pulls/389/commits"},"statuses":{"href":"https://api.github.com/repos/Automattic/simplenote-electron/statuses/b11197bb3545356f0b298b273568dff2e7ce18c0"}}}}
{"actor":{"display_login":"dmsnell"}}