Fix focus and toggling issues in formatting bar

This commit is contained in:
Aviral Dasgupta 2016-09-08 02:46:56 +05:30
parent 8974442084
commit c11232742b
3 changed files with 23 additions and 24 deletions

View File

@ -22,6 +22,7 @@ const MARKDOWN_REGEX = {
BOLD: /([\*_])\1([\w\s]+?)\1\1/g, BOLD: /([\*_])\1([\w\s]+?)\1\1/g,
HR: /(\n|^)((-|\*|_) *){3,}(\n|$)/g, HR: /(\n|^)((-|\*|_) *){3,}(\n|$)/g,
CODE: /`[^`]*`/g, CODE: /`[^`]*`/g,
STRIKETHROUGH: /~{2}[^~]*~{2}/g,
}; };
const USERNAME_REGEX = /@\S+:\S+/g; const USERNAME_REGEX = /@\S+:\S+/g;
@ -121,7 +122,7 @@ export function getScopedRTDecorators(scope: any): CompositeDecorator {
} }
export function getScopedMDDecorators(scope: any): CompositeDecorator { export function getScopedMDDecorators(scope: any): CompositeDecorator {
let markdownDecorators = ['HR', 'BOLD', 'ITALIC', 'CODE'].map( let markdownDecorators = ['HR', 'BOLD', 'ITALIC', 'CODE', 'STRIKETHROUGH'].map(
(style) => ({ (style) => ({
strategy: (contentBlock, callback) => { strategy: (contentBlock, callback) => {
return findWithRegex(MARKDOWN_REGEX[style], contentBlock, callback); return findWithRegex(MARKDOWN_REGEX[style], contentBlock, callback);

View File

@ -178,12 +178,11 @@ export default class MessageComposer extends React.Component {
onToggleFormattingClicked() { onToggleFormattingClicked() {
UserSettingsStore.setSyncedSetting('MessageComposer.showFormatting', !this.state.showFormatting); UserSettingsStore.setSyncedSetting('MessageComposer.showFormatting', !this.state.showFormatting);
this.setState({showFormatting: !this.state.showFormatting}); this.setState({showFormatting: !this.state.showFormatting});
this.messageComposerInput.focus();
} }
onToggleMarkdownClicked() { onToggleMarkdownClicked(e) {
e.preventDefault(); // don't steal focus from the editor!
this.messageComposerInput.enableRichtext(!this.state.inputState.isRichtextEnabled); this.messageComposerInput.enableRichtext(!this.state.inputState.isRichtextEnabled);
this.messageComposerInput.focus();
} }
render() { render() {
@ -292,13 +291,13 @@ export default class MessageComposer extends React.Component {
const active = style.includes(name) || blockType === name; const active = style.includes(name) || blockType === name;
const suffix = active ? '-o-n' : ''; const suffix = active ? '-o-n' : '';
const onFormatButtonClicked = this.onFormatButtonClicked.bind(this, name); const onFormatButtonClicked = this.onFormatButtonClicked.bind(this, name);
const disabled = !this.state.inputState.isRichtextEnabled && ['strike', 'underline'].includes(name); const disabled = !this.state.inputState.isRichtextEnabled && 'underline' === name;
const className = classNames("mx_MessageComposer_format_button", { const className = classNames("mx_MessageComposer_format_button", {
mx_MessageComposer_format_button_disabled: disabled, mx_MessageComposer_format_button_disabled: disabled,
}); });
return <img className={className} return <img className={className}
title={name} title={name}
onClick={disabled ? null : onFormatButtonClicked} onMouseDown={disabled ? null : onFormatButtonClicked}
key={name} key={name}
src={`img/button-text-${name}${suffix}.svg`} src={`img/button-text-${name}${suffix}.svg`}
height="17" />; height="17" />;
@ -319,7 +318,7 @@ export default class MessageComposer extends React.Component {
{formatButtons} {formatButtons}
<div style={{flex: 1}}></div> <div style={{flex: 1}}></div>
<img title={`Turn Markdown ${this.state.inputState.isRichtextEnabled ? 'on' : 'off'}`} <img title={`Turn Markdown ${this.state.inputState.isRichtextEnabled ? 'on' : 'off'}`}
onClick={this.onToggleMarkdownClicked} onMouseDown={this.onToggleMarkdownClicked}
className="mx_MessageComposer_formatbar_markdown" className="mx_MessageComposer_formatbar_markdown"
src={`img/button-md-${!this.state.inputState.isRichtextEnabled}.png`} /> src={`img/button-md-${!this.state.inputState.isRichtextEnabled}.png`} />
<img title="Hide Text Formatting Toolbar" <img title="Hide Text Formatting Toolbar"

View File

@ -83,7 +83,6 @@ export default class MessageComposerInput extends React.Component {
constructor(props, context) { constructor(props, context) {
super(props, context); super(props, context);
this.onAction = this.onAction.bind(this); this.onAction = this.onAction.bind(this);
this.focus = this.focus.bind(this);
this.handleReturn = this.handleReturn.bind(this); this.handleReturn = this.handleReturn.bind(this);
this.handleKeyCommand = this.handleKeyCommand.bind(this); this.handleKeyCommand = this.handleKeyCommand.bind(this);
this.setEditorState = this.setEditorState.bind(this); this.setEditorState = this.setEditorState.bind(this);
@ -378,13 +377,10 @@ export default class MessageComposerInput extends React.Component {
} }
} }
focus(ev) {
this.refs.editor.focus();
}
setEditorState(editorState: EditorState) { setEditorState(editorState: EditorState, cb = () => null) {
editorState = RichText.attachImmutableEntitiesToEmoji(editorState); editorState = RichText.attachImmutableEntitiesToEmoji(editorState);
this.setState({editorState}); this.setState({editorState}, cb);
if (editorState.getCurrentContent().hasText()) { if (editorState.getCurrentContent().hasText()) {
this.onTypingActivity(); this.onTypingActivity();
@ -402,19 +398,20 @@ export default class MessageComposerInput extends React.Component {
} }
enableRichtext(enabled: boolean) { enableRichtext(enabled: boolean) {
let contentState = null;
if (enabled) { if (enabled) {
const html = mdownToHtml(this.state.editorState.getCurrentContent().getPlainText()); const html = mdownToHtml(this.state.editorState.getCurrentContent().getPlainText());
const contentState = RichText.HTMLtoContentState(html); contentState = RichText.HTMLtoContentState(html);
this.setEditorState(this.createEditorState(enabled, contentState));
} else { } else {
let markdown = stateToMarkdown(this.state.editorState.getCurrentContent()); let markdown = stateToMarkdown(this.state.editorState.getCurrentContent());
markdown = markdown.substring(0, markdown.length - 1); // stateToMarkdown tacks on an extra newline (?!?) markdown = markdown.substring(0, markdown.length - 1); // stateToMarkdown tacks on an extra newline (?!?)
const contentState = ContentState.createFromText(markdown); contentState = ContentState.createFromText(markdown);
this.setEditorState(this.createEditorState(enabled, contentState));
} }
this.setState({ this.setEditorState(this.createEditorState(enabled, contentState), () => {
isRichtextEnabled: enabled, this.setState({
isRichtextEnabled: enabled,
});
}); });
UserSettingsStore.setSyncedSetting('MessageComposerInput.isRichTextEnabled', enabled); UserSettingsStore.setSyncedSetting('MessageComposerInput.isRichTextEnabled', enabled);
@ -447,6 +444,7 @@ export default class MessageComposerInput extends React.Component {
bold: text => `**${text}**`, bold: text => `**${text}**`,
italic: text => `*${text}*`, italic: text => `*${text}*`,
underline: text => `_${text}_`, // there's actually no valid underline in Markdown, but *shrug* underline: text => `_${text}_`, // there's actually no valid underline in Markdown, but *shrug*
strike: text => `~~${text}~~`,
code: text => `\`${text}\``, code: text => `\`${text}\``,
blockquote: text => text.split('\n').map(line => `> ${line}\n`).join(''), blockquote: text => text.split('\n').map(line => `> ${line}\n`).join(''),
'unordered-list-item': text => text.split('\n').map(line => `- ${line}\n`).join(''), 'unordered-list-item': text => text.split('\n').map(line => `- ${line}\n`).join(''),
@ -590,6 +588,7 @@ export default class MessageComposerInput extends React.Component {
} }
onFormatButtonClicked(name: "bold" | "italic" | "strike" | "code" | "underline" | "quote" | "bullet" | "numbullet", e) { onFormatButtonClicked(name: "bold" | "italic" | "strike" | "code" | "underline" | "quote" | "bullet" | "numbullet", e) {
e.preventDefault(); // don't steal focus from the editor!
const command = { const command = {
code: 'code-block', code: 'code-block',
quote: 'blockquote', quote: 'blockquote',
@ -631,8 +630,9 @@ export default class MessageComposerInput extends React.Component {
}; };
} }
onMarkdownToggleClicked() { onMarkdownToggleClicked(e) {
this.enableRichtext(!this.state.isRichtextEnabled); e.preventDefault(); // don't steal focus from the editor!
this.handleKeyCommand('toggle-mode');
} }
render() { render() {
@ -654,10 +654,9 @@ export default class MessageComposerInput extends React.Component {
}); });
return ( return (
<div className={className} <div className={className}>
onClick={ this.focus }>
<img className="mx_MessageComposer_input_markdownIndicator" <img className="mx_MessageComposer_input_markdownIndicator"
onClick={this.onMarkdownToggleClicked} onMouseDown={this.onMarkdownToggleClicked}
title={`Markdown is ${this.state.isRichtextEnabled ? 'disabled' : 'enabled'}`} title={`Markdown is ${this.state.isRichtextEnabled ? 'disabled' : 'enabled'}`}
src={`img/button-md-${!this.state.isRichtextEnabled}.png`} /> src={`img/button-md-${!this.state.isRichtextEnabled}.png`} />
<Editor ref="editor" <Editor ref="editor"