diff --git a/src/RichText.js b/src/RichText.js index c24a510e05..a5bc554b95 100644 --- a/src/RichText.js +++ b/src/RichText.js @@ -1,6 +1,7 @@ import React from 'react'; import { Editor, + EditorState, Modifier, ContentState, ContentBlock, @@ -9,12 +10,13 @@ import { DefaultDraftInlineStyle, CompositeDecorator, SelectionState, + Entity, } from 'draft-js'; import * as sdk from './index'; import * as emojione from 'emojione'; const BLOCK_RENDER_MAP = DefaultDraftBlockRenderMap.set('unstyled', { - element: 'span' + element: 'span', /* draft uses
-function mdownToHtml(mdown) { - var html = marked(mdown) || ""; +function mdownToHtml(mdown: string): string { + let html = marked(mdown) || ""; html = html.trim(); // strip start and end
tags else you get 'orrible spacing if (html.indexOf("
") === 0) { @@ -66,6 +66,17 @@ function mdownToHtml(mdown) { * The textInput part of the MessageComposer */ export default class MessageComposerInput extends React.Component { + static getKeyBinding(e: SyntheticKeyboardEvent): string { + // C-m => Toggles between rich text and markdown modes + if (e.keyCode === KEY_M && KeyBindingUtil.isCtrlKeyCommand(e)) { + return 'toggle-mode'; + } + + return getDefaultKeyBinding(e); + } + + client: MatrixClient; + constructor(props, context) { super(props, context); this.onAction = this.onAction.bind(this); @@ -79,7 +90,7 @@ export default class MessageComposerInput extends React.Component { this.onConfirmAutocompletion = this.onConfirmAutocompletion.bind(this); let isRichtextEnabled = window.localStorage.getItem('mx_editor_rte_enabled'); - if(isRichtextEnabled == null) { + if (isRichtextEnabled == null) { isRichtextEnabled = 'true'; } isRichtextEnabled = isRichtextEnabled === 'true'; @@ -95,15 +106,6 @@ export default class MessageComposerInput extends React.Component { this.client = MatrixClientPeg.get(); } - static getKeyBinding(e: SyntheticKeyboardEvent): string { - // C-m => Toggles between rich text and markdown modes - if (e.keyCode === KEY_M && KeyBindingUtil.isCtrlKeyCommand(e)) { - return 'toggle-mode'; - } - - return getDefaultKeyBinding(e); - } - /** * "Does the right thing" to create an EditorState, based on: * - whether we've got rich text mode enabled @@ -347,15 +349,16 @@ export default class MessageComposerInput extends React.Component { } setEditorState(editorState: EditorState) { + editorState = RichText.attachImmutableEntitiesToEmoji(editorState); this.setState({editorState}); - if(editorState.getCurrentContent().hasText()) { - this.onTypingActivity() + if (editorState.getCurrentContent().hasText()) { + this.onTypingActivity(); } else { this.onFinishedTyping(); } - if(this.props.onContentChanged) { + if (this.props.onContentChanged) { this.props.onContentChanged(editorState.getCurrentContent().getPlainText(), RichText.selectionStateToTextOffsets(editorState.getSelection(), editorState.getCurrentContent().getBlocksAsArray())); @@ -380,7 +383,7 @@ export default class MessageComposerInput extends React.Component { } handleKeyCommand(command: string): boolean { - if(command === 'toggle-mode') { + if (command === 'toggle-mode') { this.enableRichtext(!this.state.isRichtextEnabled); return true; } @@ -388,7 +391,7 @@ export default class MessageComposerInput extends React.Component { let newState: ?EditorState = null; // Draft handles rich text mode commands by default but we need to do it ourselves for Markdown. - if(!this.state.isRichtextEnabled) { + if (!this.state.isRichtextEnabled) { let contentState = this.state.editorState.getCurrentContent(), selection = this.state.editorState.getSelection(); @@ -396,10 +399,10 @@ export default class MessageComposerInput extends React.Component { bold: text => `**${text}**`, italic: text => `*${text}*`, underline: text => `_${text}_`, // there's actually no valid underline in Markdown, but *shrug* - code: text => `\`${text}\`` + code: text => `\`${text}\``, }[command]; - if(modifyFn) { + if (modifyFn) { newState = EditorState.push( this.state.editorState, RichText.modifyText(contentState, selection, modifyFn), @@ -408,7 +411,7 @@ export default class MessageComposerInput extends React.Component { } } - if(newState == null) + if (newState == null) newState = RichUtils.handleKeyCommand(this.state.editorState, command); if (newState != null) { @@ -533,9 +536,11 @@ export default class MessageComposerInput extends React.Component { content ); - this.setState({ - editorState: EditorState.push(this.state.editorState, contentState, 'insert-characters'), - }); + let editorState = EditorState.push(this.state.editorState, contentState, 'insert-characters'); + + editorState = EditorState.forceSelection(editorState, contentState.getSelectionAfter()); + + this.setEditorState(editorState); // for some reason, doing this right away does not update the editor :( setTimeout(() => this.refs.editor.focus(), 50);