Push up instantiation of TabComplete to RoomView

RoomView is the parent component which creates MessageComposer AND the status
bar. By making RoomView instantiate TabComplete we can scope instances
correctly rather than relying on singleton behaviour through dispatches. This
also makes communication between status bar and the MessageComposer infinitely
easier since they are now sharing the same TabComplete object.
This commit is contained in:
Kegan Dougal 2015-12-21 10:59:10 +00:00
parent c6d02b2c26
commit 26dc3cc553
3 changed files with 40 additions and 12 deletions

View File

@ -45,6 +45,10 @@ class TabComplete {
this.textArea = textArea;
}
isTabCompleting() {
return this.tabStruct.completing;
}
next() {
this.tabStruct.index++;
this.setCompletionOption();
@ -117,15 +121,27 @@ class TabComplete {
}
}
/**
* @param {DOMEvent} e
* @return {Boolean} True if the tab complete state changed as a result of
* this event.
*/
onKeyDown(ev) {
if (ev.keyCode !== KEY_TAB) {
if (ev.keyCode !== KEY_SHIFT && this.tabStruct.completing) {
// they're resuming typing; reset tab complete state vars.
this.tabStruct.completing = false;
this.tabStruct.index = 0;
return true;
}
return false;
}
if (!this.textArea) {
console.error("onKeyDown called before a <textarea> was set!");
return false;
}
// init struct if necessary
if (!this.tabStruct.completing) {
this.tabStruct.completing = true;

View File

@ -34,6 +34,7 @@ var WhoIsTyping = require("../../WhoIsTyping");
var Modal = require("../../Modal");
var sdk = require('../../index');
var CallHandler = require('../../CallHandler');
var TabComplete = require("../../TabComplete");
var Resend = require("../../Resend");
var dis = require("../../dispatcher");
@ -85,6 +86,12 @@ module.exports = React.createClass({
MatrixClientPeg.get().on("RoomState.members", this.onRoomStateMember);
MatrixClientPeg.get().on("sync", this.onSyncStateChange);
this.savedScrollState = {atBottom: true};
// xchat-style tab complete, add a colon if tab
// completing at the start of the text
this.tabComplete = new TabComplete({
startingWordSuffix: ": ",
wordSuffix: " "
});
},
componentWillUnmount: function() {
@ -1357,7 +1364,9 @@ module.exports = React.createClass({
);
if (canSpeak) {
messageComposer =
<MessageComposer room={this.state.room} roomView={this} uploadFile={this.uploadFile} callState={this.state.callState} />
<MessageComposer
room={this.state.room} roomView={this} uploadFile={this.uploadFile}
callState={this.state.callState} tabComplete={this.tabComplete} />
}
// TODO: Why aren't we storing the term/scope/count in this format

View File

@ -31,7 +31,6 @@ var MatrixClientPeg = require("../../../MatrixClientPeg");
var SlashCommands = require("../../../SlashCommands");
var Modal = require("../../../Modal");
var CallHandler = require('../../../CallHandler');
var TabComplete = require("../../../TabComplete");
var sdk = require('../../../index');
var dis = require("../../../dispatcher");
@ -65,6 +64,10 @@ function mdownToHtml(mdown) {
module.exports = React.createClass({
displayName: 'MessageComposer',
propTypes: {
tabComplete: React.PropTypes.any
},
componentWillMount: function() {
this.oldScrollHeight = 0;
this.markdownEnabled = MARKDOWN_ENABLED;
@ -168,14 +171,9 @@ module.exports = React.createClass({
this.props.room.roomId
);
this.resizeInput();
// xchat-style tab complete, add a colon if tab
// completing at the start of the text
this._tabComplete = new TabComplete({
textArea: this.refs.textarea,
startingWordSuffix: ": ",
wordSuffix: " "
});
if (this.props.tabComplete) {
this.props.tabComplete.setTextArea(this.refs.textarea);
}
},
componentWillUnmount: function() {
@ -233,7 +231,9 @@ module.exports = React.createClass({
return m.name || m.userId;
});
}
this._tabComplete.setCompletionList(memberList);
if (this.props.tabComplete) {
this.props.tabComplete.setCompletionList(memberList);
}
}
else if (ev.keyCode === KeyCode.UP) {
var input = this.refs.textarea.value;
@ -253,7 +253,10 @@ module.exports = React.createClass({
this.resizeInput();
}
}
this._tabComplete.onKeyDown(ev);
if (this.props.tabComplete) {
this.props.tabComplete.onKeyDown(ev);
}
var self = this;
setTimeout(function() {