refactor MessageComposerInput: bind -> class props
This commit is contained in:
parent
f2ad4bee8b
commit
f4c0baaa2f
2 changed files with 73 additions and 85 deletions
|
@ -48,7 +48,7 @@
|
|||
"browser-request": "^0.3.3",
|
||||
"classnames": "^2.1.2",
|
||||
"commonmark": "^0.27.0",
|
||||
"draft-js": "^0.8.1",
|
||||
"draft-js": "^0.9.1",
|
||||
"draft-js-export-html": "^0.5.0",
|
||||
"draft-js-export-markdown": "^0.2.0",
|
||||
"emojione": "2.2.3",
|
||||
|
|
|
@ -59,6 +59,29 @@ function stateToMarkdown(state) {
|
|||
* The textInput part of the MessageComposer
|
||||
*/
|
||||
export default class MessageComposerInput extends React.Component {
|
||||
static propTypes = {
|
||||
tabComplete: React.PropTypes.any,
|
||||
|
||||
// a callback which is called when the height of the composer is
|
||||
// changed due to a change in content.
|
||||
onResize: React.PropTypes.func,
|
||||
|
||||
// js-sdk Room object
|
||||
room: React.PropTypes.object.isRequired,
|
||||
|
||||
// called with current plaintext content (as a string) whenever it changes
|
||||
onContentChanged: React.PropTypes.func,
|
||||
|
||||
onUpArrow: React.PropTypes.func,
|
||||
|
||||
onDownArrow: React.PropTypes.func,
|
||||
|
||||
// attempts to confirm currently selected completion, returns whether actually confirmed
|
||||
tryComplete: React.PropTypes.func,
|
||||
|
||||
onInputStateChanged: React.PropTypes.func,
|
||||
};
|
||||
|
||||
static getKeyBinding(e: SyntheticKeyboardEvent): string {
|
||||
// C-m => Toggles between rich text and markdown modes
|
||||
if (e.keyCode === KEY_M && KeyBindingUtil.isCtrlKeyCommand(e)) {
|
||||
|
@ -81,17 +104,6 @@ export default class MessageComposerInput extends React.Component {
|
|||
|
||||
constructor(props, context) {
|
||||
super(props, context);
|
||||
this.onAction = this.onAction.bind(this);
|
||||
this.handleReturn = this.handleReturn.bind(this);
|
||||
this.handleKeyCommand = this.handleKeyCommand.bind(this);
|
||||
this.onEditorContentChanged = this.onEditorContentChanged.bind(this);
|
||||
this.setEditorState = this.setEditorState.bind(this);
|
||||
this.onUpArrow = this.onUpArrow.bind(this);
|
||||
this.onDownArrow = this.onDownArrow.bind(this);
|
||||
this.onTab = this.onTab.bind(this);
|
||||
this.onEscape = this.onEscape.bind(this);
|
||||
this.setDisplayedCompletion = this.setDisplayedCompletion.bind(this);
|
||||
this.onMarkdownToggleClicked = this.onMarkdownToggleClicked.bind(this);
|
||||
|
||||
const isRichtextEnabled = UserSettingsStore.getSyncedSetting('MessageComposerInput.isRichTextEnabled', true);
|
||||
|
||||
|
@ -248,7 +260,7 @@ export default class MessageComposerInput extends React.Component {
|
|||
}
|
||||
}
|
||||
|
||||
onAction(payload) {
|
||||
onAction = payload => {
|
||||
let editor = this.refs.editor;
|
||||
let contentState = this.state.editorState.getCurrentContent();
|
||||
|
||||
|
@ -299,7 +311,7 @@ export default class MessageComposerInput extends React.Component {
|
|||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
onTypingActivity() {
|
||||
this.isTyping = true;
|
||||
|
@ -368,7 +380,7 @@ export default class MessageComposerInput extends React.Component {
|
|||
}
|
||||
|
||||
// Called by Draft to change editor contents, and by setEditorState
|
||||
onEditorContentChanged(editorState: EditorState, didRespondToUserInput: boolean = true) {
|
||||
onEditorContentChanged = (editorState: EditorState, didRespondToUserInput: boolean = true) => {
|
||||
editorState = RichText.attachImmutableEntitiesToEmoji(editorState);
|
||||
|
||||
const contentChanged = Q.defer();
|
||||
|
@ -392,11 +404,11 @@ export default class MessageComposerInput extends React.Component {
|
|||
this.props.onContentChanged(textContent, selection);
|
||||
}
|
||||
return contentChanged.promise;
|
||||
}
|
||||
};
|
||||
|
||||
setEditorState(editorState: EditorState) {
|
||||
setEditorState = (editorState: EditorState) => {
|
||||
return this.onEditorContentChanged(editorState, false);
|
||||
}
|
||||
};
|
||||
|
||||
enableRichtext(enabled: boolean) {
|
||||
let contentState = null;
|
||||
|
@ -420,7 +432,7 @@ export default class MessageComposerInput extends React.Component {
|
|||
});
|
||||
}
|
||||
|
||||
handleKeyCommand(command: string): boolean {
|
||||
handleKeyCommand = (command: string): boolean => {
|
||||
if (command === 'toggle-mode') {
|
||||
this.enableRichtext(!this.state.isRichtextEnabled);
|
||||
return true;
|
||||
|
@ -473,9 +485,9 @@ export default class MessageComposerInput extends React.Component {
|
|||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
handleReturn(ev) {
|
||||
handleReturn = ev => {
|
||||
if (ev.shiftKey) {
|
||||
this.onEditorContentChanged(RichUtils.insertSoftNewline(this.state.editorState));
|
||||
return true;
|
||||
|
@ -567,45 +579,44 @@ export default class MessageComposerInput extends React.Component {
|
|||
this.autocomplete.hide();
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
async onUpArrow(e) {
|
||||
onUpArrow = async e => {
|
||||
const completion = this.autocomplete.onUpArrow();
|
||||
if (completion != null) {
|
||||
e.preventDefault();
|
||||
}
|
||||
return await this.setDisplayedCompletion(completion);
|
||||
}
|
||||
};
|
||||
|
||||
async onDownArrow(e) {
|
||||
onDownArrow = async e => {
|
||||
const completion = this.autocomplete.onDownArrow();
|
||||
e.preventDefault();
|
||||
return await this.setDisplayedCompletion(completion);
|
||||
}
|
||||
};
|
||||
|
||||
// tab and shift-tab are mapped to down and up arrow respectively
|
||||
async onTab(e) {
|
||||
onTab = async e => {
|
||||
e.preventDefault(); // we *never* want tab's default to happen, but we do want up/down sometimes
|
||||
const didTab = await (e.shiftKey ? this.onUpArrow : this.onDownArrow)(e);
|
||||
if (!didTab && this.autocomplete) {
|
||||
this.autocomplete.forceComplete().then(() => {
|
||||
await this.autocomplete.forceComplete();
|
||||
this.onDownArrow(e);
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
onEscape(e) {
|
||||
onEscape = e => {
|
||||
e.preventDefault();
|
||||
if (this.autocomplete) {
|
||||
this.autocomplete.onEscape(e);
|
||||
}
|
||||
this.setDisplayedCompletion(null); // restore originalEditorState
|
||||
}
|
||||
};
|
||||
|
||||
/* If passed null, restores the original editor content from state.originalEditorState.
|
||||
* If passed a non-null displayedCompletion, modifies state.originalEditorState to compute new state.editorState.
|
||||
*/
|
||||
async setDisplayedCompletion(displayedCompletion: ?Completion): boolean {
|
||||
setDisplayedCompletion = async (displayedCompletion: ?Completion): boolean => {
|
||||
const activeEditorState = this.state.originalEditorState || this.state.editorState;
|
||||
|
||||
if (displayedCompletion == null) {
|
||||
|
@ -633,7 +644,7 @@ export default class MessageComposerInput extends React.Component {
|
|||
// for some reason, doing this right away does not update the editor :(
|
||||
setTimeout(() => this.refs.editor.focus(), 50);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
onFormatButtonClicked(name: "bold" | "italic" | "strike" | "code" | "underline" | "quote" | "bullet" | "numbullet", e) {
|
||||
e.preventDefault(); // don't steal focus from the editor!
|
||||
|
@ -678,10 +689,10 @@ export default class MessageComposerInput extends React.Component {
|
|||
};
|
||||
}
|
||||
|
||||
onMarkdownToggleClicked(e) {
|
||||
onMarkdownToggleClicked = e => {
|
||||
e.preventDefault(); // don't steal focus from the editor!
|
||||
this.handleKeyCommand('toggle-mode');
|
||||
}
|
||||
};
|
||||
|
||||
render() {
|
||||
const activeEditorState = this.state.originalEditorState || this.state.editorState;
|
||||
|
@ -739,26 +750,3 @@ export default class MessageComposerInput extends React.Component {
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
MessageComposerInput.propTypes = {
|
||||
tabComplete: React.PropTypes.any,
|
||||
|
||||
// a callback which is called when the height of the composer is
|
||||
// changed due to a change in content.
|
||||
onResize: React.PropTypes.func,
|
||||
|
||||
// js-sdk Room object
|
||||
room: React.PropTypes.object.isRequired,
|
||||
|
||||
// called with current plaintext content (as a string) whenever it changes
|
||||
onContentChanged: React.PropTypes.func,
|
||||
|
||||
onUpArrow: React.PropTypes.func,
|
||||
|
||||
onDownArrow: React.PropTypes.func,
|
||||
|
||||
// attempts to confirm currently selected completion, returns whether actually confirmed
|
||||
tryComplete: React.PropTypes.func,
|
||||
|
||||
onInputStateChanged: React.PropTypes.func,
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue