merge develop
This commit is contained in:
commit
f3aeda7af9
9 changed files with 219 additions and 47 deletions
|
@ -34,7 +34,8 @@
|
||||||
"react-dom": "^0.14.2",
|
"react-dom": "^0.14.2",
|
||||||
"react-gemini-scrollbar": "^2.0.1",
|
"react-gemini-scrollbar": "^2.0.1",
|
||||||
"sanitize-html": "^1.11.1",
|
"sanitize-html": "^1.11.1",
|
||||||
"velocity-animate": "^1.2.3"
|
"velocity-animate": "^1.2.3",
|
||||||
|
"velocity-ui-pack": "^1.2.2"
|
||||||
},
|
},
|
||||||
"//deps": "The loader packages are here because webpack in a project that depends on us needs them in this package's node_modules folder",
|
"//deps": "The loader packages are here because webpack in a project that depends on us needs them in this package's node_modules folder",
|
||||||
"//depsbuglink": "https://github.com/webpack/webpack/issues/1472",
|
"//depsbuglink": "https://github.com/webpack/webpack/issues/1472",
|
||||||
|
|
|
@ -152,6 +152,8 @@ class Register extends Signup {
|
||||||
} else {
|
} else {
|
||||||
if (error.errcode === 'M_USER_IN_USE') {
|
if (error.errcode === 'M_USER_IN_USE') {
|
||||||
throw new Error("Username in use");
|
throw new Error("Username in use");
|
||||||
|
} else if (error.errcode == 'M_INVALID_USERNAME') {
|
||||||
|
throw new Error("User names may only contain alphanumeric characters, underscores or dots!");
|
||||||
} else if (error.httpStatus == 401) {
|
} else if (error.httpStatus == 401) {
|
||||||
throw new Error("Authorisation failed!");
|
throw new Error("Authorisation failed!");
|
||||||
} else if (error.httpStatus >= 400 && error.httpStatus < 500) {
|
} else if (error.httpStatus >= 400 && error.httpStatus < 500) {
|
||||||
|
|
|
@ -69,7 +69,7 @@ var commands = {
|
||||||
}),
|
}),
|
||||||
|
|
||||||
// Changes the colorscheme of your current room
|
// Changes the colorscheme of your current room
|
||||||
tint: new Command("tint", "<primaryColor> [<secondaryColor>]", function(room_id, args) {
|
tint: new Command("tint", "<color1> [<color2>]", function(room_id, args) {
|
||||||
if (args) {
|
if (args) {
|
||||||
var matches = args.match(/^(#([0-9a-fA-F]{3}|[0-9a-fA-F]{6}))( +(#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})))?$/);
|
var matches = args.match(/^(#([0-9a-fA-F]{3}|[0-9a-fA-F]{6}))( +(#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})))?$/);
|
||||||
if (matches) {
|
if (matches) {
|
||||||
|
@ -89,7 +89,7 @@ var commands = {
|
||||||
return reject(this.getUsage());
|
return reject(this.getUsage());
|
||||||
}),
|
}),
|
||||||
|
|
||||||
encrypt: new Command("encrypt", "<on/off>", function(room_id, args) {
|
encrypt: new Command("encrypt", "<on|off>", function(room_id, args) {
|
||||||
if (args == "on") {
|
if (args == "on") {
|
||||||
var client = MatrixClientPeg.get();
|
var client = MatrixClientPeg.get();
|
||||||
var members = client.getRoom(room_id).currentState.members;
|
var members = client.getRoom(room_id).currentState.members;
|
||||||
|
@ -316,7 +316,9 @@ var commands = {
|
||||||
};
|
};
|
||||||
|
|
||||||
// helpful aliases
|
// helpful aliases
|
||||||
commands.j = commands.join;
|
var aliases = {
|
||||||
|
j: "join"
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
/**
|
/**
|
||||||
|
@ -336,6 +338,9 @@ module.exports = {
|
||||||
var cmd = bits[1].substring(1).toLowerCase();
|
var cmd = bits[1].substring(1).toLowerCase();
|
||||||
var args = bits[3];
|
var args = bits[3];
|
||||||
if (cmd === "me") return null;
|
if (cmd === "me") return null;
|
||||||
|
if (aliases[cmd]) {
|
||||||
|
cmd = aliases[cmd];
|
||||||
|
}
|
||||||
if (commands[cmd]) {
|
if (commands[cmd]) {
|
||||||
return commands[cmd].run(roomId, args);
|
return commands[cmd].run(roomId, args);
|
||||||
}
|
}
|
||||||
|
@ -347,8 +352,12 @@ module.exports = {
|
||||||
},
|
},
|
||||||
|
|
||||||
getCommandList: function() {
|
getCommandList: function() {
|
||||||
return Object.keys(commands).map(function(cmdKey) {
|
// Return all the commands plus /me which isn't handled like normal commands
|
||||||
|
var cmds = Object.keys(commands).sort().map(function(cmdKey) {
|
||||||
return commands[cmdKey];
|
return commands[cmdKey];
|
||||||
});
|
})
|
||||||
|
cmds.push(new Command("me", "<action>", function(){}));
|
||||||
|
|
||||||
|
return cmds;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -79,7 +79,7 @@ module.exports = React.createClass({
|
||||||
hasUnsentMessages: this._hasUnsentMessages(room),
|
hasUnsentMessages: this._hasUnsentMessages(room),
|
||||||
callState: null,
|
callState: null,
|
||||||
guestsCanJoin: false,
|
guestsCanJoin: false,
|
||||||
readMarkerEventId: room ? room.getEventReadUpTo(MatrixClientPeg.get().credentials.userId) : undefined,
|
readMarkerEventId: room ? room.getEventReadUpTo(MatrixClientPeg.get().credentials.userId) : null,
|
||||||
readMarkerGhostEventId: undefined
|
readMarkerGhostEventId: undefined
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -57,7 +57,7 @@ module.exports = React.createClass({displayName: 'UploadBar',
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!upload) {
|
if (!upload) {
|
||||||
upload = uploads[0];
|
return <div />
|
||||||
}
|
}
|
||||||
|
|
||||||
var innerProgressStyle = {
|
var innerProgressStyle = {
|
||||||
|
|
|
@ -159,6 +159,15 @@ module.exports = React.createClass({
|
||||||
case "RegistrationForm.ERR_PASSWORD_LENGTH":
|
case "RegistrationForm.ERR_PASSWORD_LENGTH":
|
||||||
errMsg = `Password too short (min ${MIN_PASSWORD_LENGTH}).`;
|
errMsg = `Password too short (min ${MIN_PASSWORD_LENGTH}).`;
|
||||||
break;
|
break;
|
||||||
|
case "RegistrationForm.ERR_EMAIL_INVALID":
|
||||||
|
errMsg = "This doesn't look like a valid email address";
|
||||||
|
break;
|
||||||
|
case "RegistrationForm.ERR_USERNAME_INVALID":
|
||||||
|
errMsg = "User names may only contain letters, numbers, dots, hyphens and underscores.";
|
||||||
|
break;
|
||||||
|
case "RegistrationForm.ERR_USERNAME_BLANK":
|
||||||
|
errMsg = "You need to enter a user name";
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
console.error("Unknown error code: %s", errCode);
|
console.error("Unknown error code: %s", errCode);
|
||||||
errMsg = "An unknown error occurred.";
|
errMsg = "An unknown error occurred.";
|
||||||
|
|
|
@ -17,8 +17,15 @@ limitations under the License.
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var React = require('react');
|
var React = require('react');
|
||||||
|
var Velocity = require('velocity-animate');
|
||||||
|
require('velocity-ui-pack');
|
||||||
var sdk = require('../../../index');
|
var sdk = require('../../../index');
|
||||||
|
|
||||||
|
var FIELD_EMAIL = 'field_email';
|
||||||
|
var FIELD_USERNAME = 'field_username';
|
||||||
|
var FIELD_PASSWORD = 'field_password';
|
||||||
|
var FIELD_PASSWORD_CONFIRM = 'field_password_confirm';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A pure UI component which displays a registration form.
|
* A pure UI component which displays a registration form.
|
||||||
*/
|
*/
|
||||||
|
@ -50,52 +57,151 @@ module.exports = React.createClass({
|
||||||
email: this.props.defaultEmail,
|
email: this.props.defaultEmail,
|
||||||
username: this.props.defaultUsername,
|
username: this.props.defaultUsername,
|
||||||
password: null,
|
password: null,
|
||||||
passwordConfirm: null
|
passwordConfirm: null,
|
||||||
|
fieldValid: {}
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
onSubmit: function(ev) {
|
onSubmit: function(ev) {
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
|
|
||||||
var pwd1 = this.refs.password.value.trim();
|
// validate everything, in reverse order so
|
||||||
var pwd2 = this.refs.passwordConfirm.value.trim()
|
// the error that ends up being displayed
|
||||||
|
// is the one from the first invalid field.
|
||||||
|
// It's not super ideal that this just calls
|
||||||
|
// onError once for each invalid field.
|
||||||
|
this.validateField(FIELD_PASSWORD_CONFIRM);
|
||||||
|
this.validateField(FIELD_PASSWORD);
|
||||||
|
this.validateField(FIELD_USERNAME);
|
||||||
|
this.validateField(FIELD_EMAIL);
|
||||||
|
|
||||||
var errCode;
|
if (this.allFieldsValid()) {
|
||||||
if (!pwd1 || !pwd2) {
|
var promise = this.props.onRegisterClick({
|
||||||
errCode = "RegistrationForm.ERR_PASSWORD_MISSING";
|
username: this.refs.username.value.trim(),
|
||||||
}
|
password: this.refs.password.value.trim(),
|
||||||
else if (pwd1 !== pwd2) {
|
email: this.refs.email.value.trim()
|
||||||
errCode = "RegistrationForm.ERR_PASSWORD_MISMATCH";
|
|
||||||
}
|
|
||||||
else if (pwd1.length < this.props.minPasswordLength) {
|
|
||||||
errCode = "RegistrationForm.ERR_PASSWORD_LENGTH";
|
|
||||||
}
|
|
||||||
if (errCode) {
|
|
||||||
this.props.onError(errCode);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var promise = this.props.onRegisterClick({
|
|
||||||
username: this.refs.username.value.trim(),
|
|
||||||
password: pwd1,
|
|
||||||
email: this.refs.email.value.trim()
|
|
||||||
});
|
|
||||||
|
|
||||||
if (promise) {
|
|
||||||
ev.target.disabled = true;
|
|
||||||
promise.finally(function() {
|
|
||||||
ev.target.disabled = false;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (promise) {
|
||||||
|
ev.target.disabled = true;
|
||||||
|
promise.finally(function() {
|
||||||
|
ev.target.disabled = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if all fields were valid last time
|
||||||
|
* they were validated.
|
||||||
|
*/
|
||||||
|
allFieldsValid: function() {
|
||||||
|
var keys = Object.keys(this.state.fieldValid);
|
||||||
|
for (var i = 0; i < keys.length; ++i) {
|
||||||
|
if (this.state.fieldValid[keys[i]] == false) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
|
||||||
|
validateField: function(field_id) {
|
||||||
|
var pwd1 = this.refs.password.value.trim();
|
||||||
|
var pwd2 = this.refs.passwordConfirm.value.trim()
|
||||||
|
|
||||||
|
switch (field_id) {
|
||||||
|
case FIELD_EMAIL:
|
||||||
|
this.markFieldValid(
|
||||||
|
field_id,
|
||||||
|
this.refs.email.value == '' || !!this.refs.email.value.match(/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i),
|
||||||
|
"RegistrationForm.ERR_EMAIL_INVALID"
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case FIELD_USERNAME:
|
||||||
|
// XXX: SPEC-1
|
||||||
|
if (encodeURIComponent(this.refs.username.value) != this.refs.username.value) {
|
||||||
|
this.markFieldValid(
|
||||||
|
field_id,
|
||||||
|
false,
|
||||||
|
"RegistrationForm.ERR_USERNAME_INVALID"
|
||||||
|
);
|
||||||
|
} else if (this.refs.username.value == '') {
|
||||||
|
this.markFieldValid(
|
||||||
|
field_id,
|
||||||
|
false,
|
||||||
|
"RegistrationForm.ERR_USERNAME_BLANK"
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
this.markFieldValid(field_id, true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case FIELD_PASSWORD:
|
||||||
|
if (pwd1 == '') {
|
||||||
|
this.markFieldValid(
|
||||||
|
field_id,
|
||||||
|
false,
|
||||||
|
"RegistrationForm.ERR_PASSWORD_MISSING"
|
||||||
|
);
|
||||||
|
} else if (pwd1.length < this.props.minPasswordLength) {
|
||||||
|
this.markFieldValid(
|
||||||
|
field_id,
|
||||||
|
false,
|
||||||
|
"RegistrationForm.ERR_PASSWORD_LENGTH"
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
this.markFieldValid(field_id, true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case FIELD_PASSWORD_CONFIRM:
|
||||||
|
this.markFieldValid(
|
||||||
|
field_id, pwd1 == pwd2,
|
||||||
|
"RegistrationForm.ERR_PASSWORD_MISMATCH"
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
markFieldValid: function(field_id, val, error_code) {
|
||||||
|
var fieldValid = this.state.fieldValid;
|
||||||
|
fieldValid[field_id] = val;
|
||||||
|
this.setState({fieldValid: fieldValid});
|
||||||
|
if (!val) {
|
||||||
|
Velocity(this.fieldElementById(field_id), "callout.shake", 300);
|
||||||
|
this.props.onError(error_code);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
fieldElementById(field_id) {
|
||||||
|
switch (field_id) {
|
||||||
|
case FIELD_EMAIL:
|
||||||
|
return this.refs.email;
|
||||||
|
case FIELD_USERNAME:
|
||||||
|
return this.refs.username;
|
||||||
|
case FIELD_PASSWORD:
|
||||||
|
return this.refs.password;
|
||||||
|
case FIELD_PASSWORD_CONFIRM:
|
||||||
|
return this.refs.passwordConfirm;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_styleField: function(field_id, baseStyle) {
|
||||||
|
var style = baseStyle || {};
|
||||||
|
if (this.state.fieldValid[field_id] === false) {
|
||||||
|
style['borderColor'] = 'red';
|
||||||
|
}
|
||||||
|
return style;
|
||||||
|
},
|
||||||
|
|
||||||
render: function() {
|
render: function() {
|
||||||
|
var self = this;
|
||||||
var emailSection, registerButton;
|
var emailSection, registerButton;
|
||||||
if (this.props.showEmail) {
|
if (this.props.showEmail) {
|
||||||
emailSection = (
|
emailSection = (
|
||||||
<input className="mx_Login_field" type="text" ref="email"
|
<input className="mx_Login_field" type="text" ref="email"
|
||||||
autoFocus={true} placeholder="Email address"
|
autoFocus={true} placeholder="Email address"
|
||||||
defaultValue={this.state.email} />
|
defaultValue={this.state.email}
|
||||||
|
style={this._styleField(FIELD_EMAIL)}
|
||||||
|
onBlur={function() {self.validateField(FIELD_EMAIL)}} />
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (this.props.onRegisterClick) {
|
if (this.props.onRegisterClick) {
|
||||||
|
@ -111,13 +217,19 @@ module.exports = React.createClass({
|
||||||
<br />
|
<br />
|
||||||
<input className="mx_Login_field" type="text" ref="username"
|
<input className="mx_Login_field" type="text" ref="username"
|
||||||
placeholder="User name" defaultValue={this.state.username}
|
placeholder="User name" defaultValue={this.state.username}
|
||||||
|
style={this._styleField(FIELD_USERNAME)}
|
||||||
|
onBlur={function() {self.validateField(FIELD_USERNAME)}}
|
||||||
disabled={this.props.disableUsernameChanges} />
|
disabled={this.props.disableUsernameChanges} />
|
||||||
<br />
|
<br />
|
||||||
<input className="mx_Login_field" type="password" ref="password"
|
<input className="mx_Login_field" type="password" ref="password"
|
||||||
|
style={this._styleField(FIELD_PASSWORD)}
|
||||||
|
onBlur={function() {self.validateField(FIELD_PASSWORD)}}
|
||||||
placeholder="Password" defaultValue={this.state.password} />
|
placeholder="Password" defaultValue={this.state.password} />
|
||||||
<br />
|
<br />
|
||||||
<input className="mx_Login_field" type="password" ref="passwordConfirm"
|
<input className="mx_Login_field" type="password" ref="passwordConfirm"
|
||||||
placeholder="Confirm password"
|
placeholder="Confirm password"
|
||||||
|
style={this._styleField(FIELD_PASSWORD_CONFIRM)}
|
||||||
|
onBlur={function() {self.validateField(FIELD_PASSWORD_CONFIRM)}}
|
||||||
defaultValue={this.state.passwordConfirm} />
|
defaultValue={this.state.passwordConfirm} />
|
||||||
<br />
|
<br />
|
||||||
{registerButton}
|
{registerButton}
|
||||||
|
|
|
@ -16,12 +16,18 @@ limitations under the License.
|
||||||
var React = require('react');
|
var React = require('react');
|
||||||
var classNames = require('classnames');
|
var classNames = require('classnames');
|
||||||
var Matrix = require("matrix-js-sdk");
|
var Matrix = require("matrix-js-sdk");
|
||||||
|
var q = require('q');
|
||||||
var MatrixClientPeg = require("../../../MatrixClientPeg");
|
var MatrixClientPeg = require("../../../MatrixClientPeg");
|
||||||
var Modal = require("../../../Modal");
|
var Modal = require("../../../Modal");
|
||||||
var sdk = require('../../../index');
|
var sdk = require('../../../index');
|
||||||
var GeminiScrollbar = require('react-gemini-scrollbar');
|
var GeminiScrollbar = require('react-gemini-scrollbar');
|
||||||
|
|
||||||
var INITIAL_LOAD_NUM_MEMBERS = 50;
|
var INITIAL_LOAD_NUM_MEMBERS = 50;
|
||||||
|
var SHARE_HISTORY_WARNING = "Newly invited users will see the history of this room. "+
|
||||||
|
"If you'd prefer invited users not to see messages that were sent before they joined, "+
|
||||||
|
"turn off, 'Share message history with new users' in the settings for this room.";
|
||||||
|
|
||||||
|
var shown_invite_warning_this_session = false;
|
||||||
|
|
||||||
module.exports = React.createClass({
|
module.exports = React.createClass({
|
||||||
displayName: 'MemberList',
|
displayName: 'MemberList',
|
||||||
|
@ -132,12 +138,41 @@ module.exports = React.createClass({
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var promise;
|
var invite_defer = q.defer();
|
||||||
|
|
||||||
|
var room = MatrixClientPeg.get().getRoom(this.props.roomId);
|
||||||
|
var history_visibility = room.currentState.getStateEvents('m.room.history_visibility', '');
|
||||||
|
if (history_visibility) history_visibility = history_visibility.getContent().history_visibility;
|
||||||
|
|
||||||
|
if (history_visibility == 'shared' && !shown_invite_warning_this_session) {
|
||||||
|
var QuestionDialog = sdk.getComponent("dialogs.QuestionDialog");
|
||||||
|
Modal.createDialog(QuestionDialog, {
|
||||||
|
title: "Warning",
|
||||||
|
description: SHARE_HISTORY_WARNING,
|
||||||
|
button: "Invite",
|
||||||
|
onFinished: function(should_invite) {
|
||||||
|
if (should_invite) {
|
||||||
|
shown_invite_warning_this_session = true;
|
||||||
|
invite_defer.resolve();
|
||||||
|
} else {
|
||||||
|
invite_defer.reject(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
invite_defer.resolve();
|
||||||
|
}
|
||||||
|
|
||||||
|
var promise = invite_defer.promise;;
|
||||||
if (isEmailAddress) {
|
if (isEmailAddress) {
|
||||||
promise = MatrixClientPeg.get().inviteByEmail(this.props.roomId, inputText);
|
promise = promise.then(function() {
|
||||||
|
MatrixClientPeg.get().inviteByEmail(self.props.roomId, inputText);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
promise = MatrixClientPeg.get().invite(this.props.roomId, inputText);
|
promise = promise.then(function() {
|
||||||
|
MatrixClientPeg.get().invite(self.props.roomId, inputText);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
self.setState({
|
self.setState({
|
||||||
|
@ -152,11 +187,13 @@ module.exports = React.createClass({
|
||||||
inviting: false
|
inviting: false
|
||||||
});
|
});
|
||||||
}, function(err) {
|
}, function(err) {
|
||||||
console.error("Failed to invite: %s", JSON.stringify(err));
|
if (err !== null) {
|
||||||
Modal.createDialog(ErrorDialog, {
|
console.error("Failed to invite: %s", JSON.stringify(err));
|
||||||
title: "Server error whilst inviting",
|
Modal.createDialog(ErrorDialog, {
|
||||||
description: err.message
|
title: "Server error whilst inviting",
|
||||||
});
|
description: err.message
|
||||||
|
});
|
||||||
|
}
|
||||||
self.setState({
|
self.setState({
|
||||||
inviting: false
|
inviting: false
|
||||||
});
|
});
|
||||||
|
|
|
@ -18,6 +18,7 @@ limitations under the License.
|
||||||
|
|
||||||
var React = require('react');
|
var React = require('react');
|
||||||
var MatrixClientPeg = require("../../../MatrixClientPeg");
|
var MatrixClientPeg = require("../../../MatrixClientPeg");
|
||||||
|
var CommandEntry = require("../../../TabCompleteEntries").CommandEntry;
|
||||||
|
|
||||||
module.exports = React.createClass({
|
module.exports = React.createClass({
|
||||||
displayName: 'TabCompleteBar',
|
displayName: 'TabCompleteBar',
|
||||||
|
@ -31,8 +32,9 @@ module.exports = React.createClass({
|
||||||
<div className="mx_TabCompleteBar">
|
<div className="mx_TabCompleteBar">
|
||||||
{this.props.entries.map(function(entry, i) {
|
{this.props.entries.map(function(entry, i) {
|
||||||
return (
|
return (
|
||||||
<div key={entry.getKey() || i + ""} className="mx_TabCompleteBar_item"
|
<div key={entry.getKey() || i + ""}
|
||||||
onClick={entry.onClick.bind(entry)} >
|
className={ "mx_TabCompleteBar_item " + (entry instanceof CommandEntry ? "mx_TabCompleteBar_command" : "") }
|
||||||
|
onClick={entry.onClick.bind(entry)} >
|
||||||
{entry.getImageJsx()}
|
{entry.getImageJsx()}
|
||||||
<span className="mx_TabCompleteBar_text">
|
<span className="mx_TabCompleteBar_text">
|
||||||
{entry.getText()}
|
{entry.getText()}
|
||||||
|
|
Loading…
Reference in a new issue