From 0419eff230a75620bf1d1287f4abc99bcc71400d Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Thu, 20 Jul 2017 15:46:36 +0100 Subject: [PATCH 1/5] Insert pill onClick of timeline profile When clicking someone in the timeline, insert a user pill instead of the plaintext "displayname:" --- src/components/views/messages/TextualBody.js | 3 +-- src/components/views/rooms/EventTile.js | 4 ++-- .../views/rooms/MessageComposerInput.js | 18 +++++++++++++----- 3 files changed, 16 insertions(+), 9 deletions(-) diff --git a/src/components/views/messages/TextualBody.js b/src/components/views/messages/TextualBody.js index 85cc85be49..d45813cb17 100644 --- a/src/components/views/messages/TextualBody.js +++ b/src/components/views/messages/TextualBody.js @@ -297,10 +297,9 @@ module.exports = React.createClass({ onEmoteSenderClick: function(event) { const mxEvent = this.props.mxEvent; - const name = mxEvent.sender ? mxEvent.sender.name : mxEvent.getSender(); dis.dispatch({ action: 'insert_displayname', - displayname: name.replace(' (IRC)', ''), + user_id: mxEvent.getSender(), }); }, diff --git a/src/components/views/rooms/EventTile.js b/src/components/views/rooms/EventTile.js index 68ef3a1f44..32f0739795 100644 --- a/src/components/views/rooms/EventTile.js +++ b/src/components/views/rooms/EventTile.js @@ -357,10 +357,10 @@ module.exports = withMatrixClient(React.createClass({ }, onSenderProfileClick: function(event) { - var mxEvent = this.props.mxEvent; + const mxEvent = this.props.mxEvent; dis.dispatch({ action: 'insert_displayname', - displayname: (mxEvent.sender ? mxEvent.sender.name : mxEvent.getSender()).replace(' (IRC)', ''), + user_id: mxEvent.getSender(), }); }, diff --git a/src/components/views/rooms/MessageComposerInput.js b/src/components/views/rooms/MessageComposerInput.js index d5a486bb39..29f627180b 100644 --- a/src/components/views/rooms/MessageComposerInput.js +++ b/src/components/views/rooms/MessageComposerInput.js @@ -275,15 +275,23 @@ export default class MessageComposerInput extends React.Component { case 'focus_composer': editor.focus(); break; - - // TODO change this so we insert a complete user alias - case 'insert_displayname': { + const entityKey = Entity.create( + 'LINK', 'IMMUTABLE', + { url: `https://matrix.to/#/${payload.user_id}`}, + ); + const selection = this.state.editorState.getSelection(); contentState = Modifier.replaceText( contentState, - this.state.editorState.getSelection(), - `${payload.displayname}: `, + selection, + `${payload.user_id}`, + null, + entityKey, ); + + const suffix = selection.getStartOffset() === 0 ? ': ' : ' '; + contentState = Modifier.replaceText(contentState, contentState.getSelectionAfter(), suffix); + let editorState = EditorState.push(this.state.editorState, contentState, 'insert-characters'); editorState = EditorState.forceSelection(editorState, contentState.getSelectionAfter()); this.onEditorContentChanged(editorState); From 0600c5b049cb282c38f4c7e720664756033c7692 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Thu, 20 Jul 2017 16:46:53 +0100 Subject: [PATCH 2/5] Pretend that insert_displayname is a completion on that user This has the advantage of us not reimplementing things and fixing the same bugs twice. --- .../views/rooms/MessageComposerInput.js | 44 +++++++++---------- 1 file changed, 21 insertions(+), 23 deletions(-) diff --git a/src/components/views/rooms/MessageComposerInput.js b/src/components/views/rooms/MessageComposerInput.js index 3ff93d7b24..cf934c09fd 100644 --- a/src/components/views/rooms/MessageComposerInput.js +++ b/src/components/views/rooms/MessageComposerInput.js @@ -286,29 +286,19 @@ export default class MessageComposerInput extends React.Component { editor.focus(); break; case 'insert_displayname': { - const entityKey = Entity.create( - 'LINK', 'IMMUTABLE', - { url: `https://matrix.to/#/${payload.user_id}`}, - ); + // Pretend that we've autocompleted this user because keeping two code + // paths for inserting a user pill is not fun const selection = this.state.editorState.getSelection(); - contentState = Modifier.replaceText( - contentState, + const member = this.props.room.getMember(payload.user_id); + const completion = member ? member.name : payload.user_id; + this.setDisplayedCompletion({ + completion, selection, - `${payload.user_id}`, - null, - entityKey, - ); - - const suffix = selection.getStartOffset() === 0 ? ': ' : ' '; - contentState = Modifier.replaceText(contentState, contentState.getSelectionAfter(), suffix); - - let editorState = EditorState.push(this.state.editorState, contentState, 'insert-characters'); - editorState = EditorState.forceSelection(editorState, contentState.getSelectionAfter()); - this.onEditorContentChanged(editorState); - editor.focus(); + href: `https://matrix.to/#/${payload.user_id}`, + suffix: selection.getStartOffset() === 0 ? ': ' : ' ', + }); } break; - case 'quote': { let {body, formatted_body} = payload.event.getContent(); formatted_body = formatted_body || escape(body); @@ -946,7 +936,8 @@ export default class MessageComposerInput extends React.Component { return false; } - const {range = {}, completion = '', href = null, suffix = ''} = displayedCompletion; + const {range = null, completion = '', href = null, suffix = ''} = displayedCompletion; + let entityKey; let mdCompletion; if (href) { @@ -956,11 +947,18 @@ export default class MessageComposerInput extends React.Component { } } + let selection; + if (range) { + selection = RichText.textOffsetsToSelectionState( + range, activeEditorState.getCurrentContent().getBlocksAsArray(), + ); + } else { + selection = activeEditorState.getSelection(); + } + let contentState = Modifier.replaceText( activeEditorState.getCurrentContent(), - RichText.textOffsetsToSelectionState( - range, activeEditorState.getCurrentContent().getBlocksAsArray(), - ), + selection, mdCompletion || completion, null, entityKey, From 6d7bff83ca18734843c8698ce2c57f150cd4a13a Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Thu, 20 Jul 2017 16:49:23 +0100 Subject: [PATCH 3/5] Update type Completion --- src/autocomplete/Autocompleter.js | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/autocomplete/Autocompleter.js b/src/autocomplete/Autocompleter.js index 6fadf53a61..7a64fb154c 100644 --- a/src/autocomplete/Autocompleter.js +++ b/src/autocomplete/Autocompleter.js @@ -34,12 +34,9 @@ export type Completion = { component: ?Component, range: SelectionRange, command: ?string, - // An entity applied during the replacement (using draftjs@0.8.1 Entity.create) - entity: ? { - type: string, - mutability: string, - data: ?Object, - }, + // If provided, apply a LINK entity to the completion with the + // data = { url: href }. + href: ?string, }; const PROVIDERS = [ From 08cc0c421d44f6e59fca89471ea6c5a3a883e18a Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Thu, 20 Jul 2017 18:02:54 +0100 Subject: [PATCH 4/5] insert_displayname -> insert_mention --- src/components/views/messages/TextualBody.js | 2 +- src/components/views/rooms/EventTile.js | 2 +- src/components/views/rooms/MessageComposerInput.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/components/views/messages/TextualBody.js b/src/components/views/messages/TextualBody.js index d45813cb17..b901f98f19 100644 --- a/src/components/views/messages/TextualBody.js +++ b/src/components/views/messages/TextualBody.js @@ -298,7 +298,7 @@ module.exports = React.createClass({ onEmoteSenderClick: function(event) { const mxEvent = this.props.mxEvent; dis.dispatch({ - action: 'insert_displayname', + action: 'insert_mention', user_id: mxEvent.getSender(), }); }, diff --git a/src/components/views/rooms/EventTile.js b/src/components/views/rooms/EventTile.js index 32f0739795..b3831a7d0d 100644 --- a/src/components/views/rooms/EventTile.js +++ b/src/components/views/rooms/EventTile.js @@ -359,7 +359,7 @@ module.exports = withMatrixClient(React.createClass({ onSenderProfileClick: function(event) { const mxEvent = this.props.mxEvent; dis.dispatch({ - action: 'insert_displayname', + action: 'insert_mention', user_id: mxEvent.getSender(), }); }, diff --git a/src/components/views/rooms/MessageComposerInput.js b/src/components/views/rooms/MessageComposerInput.js index cf934c09fd..ddb205d08e 100644 --- a/src/components/views/rooms/MessageComposerInput.js +++ b/src/components/views/rooms/MessageComposerInput.js @@ -285,7 +285,7 @@ export default class MessageComposerInput extends React.Component { case 'focus_composer': editor.focus(); break; - case 'insert_displayname': { + case 'insert_mention': { // Pretend that we've autocompleted this user because keeping two code // paths for inserting a user pill is not fun const selection = this.state.editorState.getSelection(); From bac22cfb7cdf5f1c78b2ef5d63e92fcd291c7129 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Thu, 20 Jul 2017 18:04:12 +0100 Subject: [PATCH 5/5] Re-add removal of (IRC) suffix --- src/components/views/rooms/MessageComposerInput.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/views/rooms/MessageComposerInput.js b/src/components/views/rooms/MessageComposerInput.js index ddb205d08e..2c011f3770 100644 --- a/src/components/views/rooms/MessageComposerInput.js +++ b/src/components/views/rooms/MessageComposerInput.js @@ -290,7 +290,7 @@ export default class MessageComposerInput extends React.Component { // paths for inserting a user pill is not fun const selection = this.state.editorState.getSelection(); const member = this.props.room.getMember(payload.user_id); - const completion = member ? member.name : payload.user_id; + const completion = member ? member.name.replace(' (IRC)', '') : payload.user_id; this.setDisplayedCompletion({ completion, selection,