Skip to content
This repository has been archived by the owner on Sep 11, 2024. It is now read-only.

Fix /join #alias command in markdown mode #1254

Merged
merged 2 commits into from
Jul 27, 2017
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 53 additions & 33 deletions src/components/views/rooms/MessageComposerInput.js
Original file line number Diff line number Diff line change
Expand Up @@ -644,7 +644,17 @@ export default class MessageComposerInput extends React.Component {

let contentText = contentState.getPlainText(), contentHTML;

const cmd = SlashCommands.processInput(this.props.room.roomId, contentText);
// Strip MD user (tab-completed) mentions to preserve plaintext mention behaviour.
// We have to do this now as opposed to after calculating the contentText for MD
// mode because entity positions may not be maintained when using
// md.toPlaintext().
// Unfortunately this means we lose mentions in history when in MD mode. This
// would be fixed if history was stored as contentState.
contentText = this.removeMDLinks(contentState, ['@']);

// Some commands (/join) require pills to be replaced with their text content
const commandText = this.removeMDLinks(contentState, ['#']);
const cmd = SlashCommands.processInput(this.props.room.roomId, commandText);
if (cmd) {
if (!cmd.error) {
this.setState({
Expand Down Expand Up @@ -708,7 +718,9 @@ export default class MessageComposerInput extends React.Component {
);
}
} else {
const md = new Markdown(contentText);
// Use the original plaintext because `contextText` has had mentions stripped
// and these need to end up in contentHTML
const md = new Markdown(contentState.getPlainText());
if (md.isPlainText()) {
contentText = md.toPlaintext();
} else {
Expand Down Expand Up @@ -737,35 +749,6 @@ export default class MessageComposerInput extends React.Component {
sendTextFn = this.client.sendEmoteMessage;
}

// Strip MD user (tab-completed) mentions to preserve plaintext mention behaviour
contentText = contentText.replace(REGEX_MATRIXTO_MARKDOWN_GLOBAL,
(markdownLink, text, resource, prefix, offset) => {
// Calculate the offset relative to the current block that the offset is in
let sum = 0;
const blocks = contentState.getBlocksAsArray();
let block;
for (let i = 0; i < blocks.length; i++) {
block = blocks[i];
sum += block.getLength();
if (sum > offset) {
sum -= block.getLength();
break;
}
}
offset -= sum;

const entityKey = block.getEntityAt(offset);
const entity = entityKey ? Entity.get(entityKey) : null;
if (entity && entity.getData().isCompletion && prefix === '@') {
// This is a completed mention, so do not insert MD link, just text
return text;
} else {
// This is either a MD link that was typed into the composer or another
// type of pill (e.g. room pill)
return markdownLink;
}
});

let sendMessagePromise;
if (contentHTML) {
sendMessagePromise = sendHtmlFn.call(
Expand Down Expand Up @@ -1013,6 +996,44 @@ export default class MessageComposerInput extends React.Component {
};
}

getAutocompleteQuery(contentState: ContentState) {
// Don't send markdown links to the autocompleter
return this.removeMDLinks(contentState, ['@', '#']);
}

removeMDLinks(contentState: ContentState, prefixes: string[]) {
const plaintext = contentState.getPlainText();
if (!plaintext) return '';
return plaintext.replace(REGEX_MATRIXTO_MARKDOWN_GLOBAL,
(markdownLink, text, resource, prefix, offset) => {
if (!prefixes.includes(prefix)) return markdownLink;
// Calculate the offset relative to the current block that the offset is in
let sum = 0;
const blocks = contentState.getBlocksAsArray();
let block;
for (let i = 0; i < blocks.length; i++) {
block = blocks[i];
sum += block.getLength();
if (sum > offset) {
sum -= block.getLength();
break;
}
}
offset -= sum;

const entityKey = block.getEntityAt(offset);
const entity = entityKey ? Entity.get(entityKey) : null;
if (entity && entity.getData().isCompletion) {
// This is a completed mention, so do not insert MD link, just text
return text;
} else {
// This is either a MD link that was typed into the composer or another
// type of pill (e.g. room pill)
return markdownLink;
}
});
}

onMarkdownToggleClicked = (e) => {
e.preventDefault(); // don't steal focus from the editor!
this.handleKeyCommand('toggle-mode');
Expand All @@ -1038,7 +1059,6 @@ export default class MessageComposerInput extends React.Component {
});

const content = activeEditorState.getCurrentContent();
const contentText = content.getPlainText();
const selection = RichText.selectionStateToTextOffsets(activeEditorState.getSelection(),
activeEditorState.getCurrentContent().getBlocksAsArray());

Expand All @@ -1048,7 +1068,7 @@ export default class MessageComposerInput extends React.Component {
<Autocomplete
ref={(e) => this.autocomplete = e}
onConfirm={this.setDisplayedCompletion}
query={contentText}
query={this.getAutocompleteQuery(content)}
selection={selection}/>
</div>
<div className={className}>
Expand Down