Merge remote-tracking branch 'origin/develop' into dbkr/user_search_feedback
This commit is contained in:
@@ -41,7 +41,7 @@ module.exports = React.createClass({
|
||||
height: 40,
|
||||
resizeMethod: 'crop',
|
||||
defaultToInitialLetter: true
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
getInitialState: function() {
|
||||
|
||||
@@ -42,7 +42,7 @@ module.exports = React.createClass({
|
||||
height: 40,
|
||||
resizeMethod: 'crop',
|
||||
viewUserOnClick: false,
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
getInitialState: function() {
|
||||
@@ -64,7 +64,7 @@ module.exports = React.createClass({
|
||||
props.width,
|
||||
props.height,
|
||||
props.resizeMethod)
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
render: function() {
|
||||
@@ -78,7 +78,7 @@ module.exports = React.createClass({
|
||||
action: 'view_user',
|
||||
member: this.props.member,
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
@@ -39,7 +39,7 @@ module.exports = React.createClass({
|
||||
height: 36,
|
||||
resizeMethod: 'crop',
|
||||
oobData: {},
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
getInitialState: function() {
|
||||
@@ -51,7 +51,7 @@ module.exports = React.createClass({
|
||||
componentWillReceiveProps: function(newProps) {
|
||||
this.setState({
|
||||
urls: this.getImageUrls(newProps)
|
||||
})
|
||||
});
|
||||
},
|
||||
|
||||
getImageUrls: function(props) {
|
||||
|
||||
@@ -40,7 +40,7 @@ module.exports = React.createClass({
|
||||
},
|
||||
|
||||
onValueChanged: function(ev) {
|
||||
this.props.onChange(ev.target.value)
|
||||
this.props.onChange(ev.target.value);
|
||||
},
|
||||
|
||||
render: function() {
|
||||
|
||||
@@ -27,6 +27,15 @@ var Modal = require('../../../Modal');
|
||||
|
||||
const TRUNCATE_QUERY_LIST = 40;
|
||||
|
||||
/*
|
||||
* Escapes a string so it can be used in a RegExp
|
||||
* Basically just replaces: \ ^ $ * + ? . ( ) | { } [ ]
|
||||
* From http://stackoverflow.com/a/6969486
|
||||
*/
|
||||
function escapeRegExp(str) {
|
||||
return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
|
||||
}
|
||||
|
||||
module.exports = React.createClass({
|
||||
displayName: "ChatInviteDialog",
|
||||
propTypes: {
|
||||
@@ -71,15 +80,12 @@ module.exports = React.createClass({
|
||||
},
|
||||
|
||||
onButtonClick: function() {
|
||||
var inviteList = this.state.inviteList.slice();
|
||||
let inviteList = this.state.inviteList.slice();
|
||||
// Check the text input field to see if user has an unconverted address
|
||||
// If there is and it's valid add it to the local inviteList
|
||||
var check = Invite.isValidAddress(this.refs.textinput.value);
|
||||
if (check === true || check === null) {
|
||||
inviteList.push(this.refs.textinput.value);
|
||||
} else if (this.refs.textinput.value.length > 0) {
|
||||
this.setState({ error: true });
|
||||
return;
|
||||
if (this.refs.textinput.value !== '') {
|
||||
inviteList = this._addInputToList();
|
||||
if (inviteList === null) return;
|
||||
}
|
||||
|
||||
if (inviteList.length > 0) {
|
||||
@@ -119,15 +125,15 @@ module.exports = React.createClass({
|
||||
} else if (e.keyCode === 38) { // up arrow
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
this.addressSelector.onKeyUp();
|
||||
this.addressSelector.moveSelectionUp();
|
||||
} else if (e.keyCode === 40) { // down arrow
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
this.addressSelector.onKeyDown();
|
||||
} else if (this.state.queryList.length > 0 && (e.keyCode === 188, e.keyCode === 13 || e.keyCode === 9)) { // comma or enter or tab
|
||||
this.addressSelector.moveSelectionDown();
|
||||
} else if (this.state.queryList.length > 0 && (e.keyCode === 188 || e.keyCode === 13 || e.keyCode === 9)) { // comma or enter or tab
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
this.addressSelector.onKeySelect();
|
||||
this.addressSelector.chooseSelection();
|
||||
} else if (this.refs.textinput.value.length === 0 && this.state.inviteList.length && e.keyCode === 8) { // backspace
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
@@ -135,21 +141,16 @@ module.exports = React.createClass({
|
||||
} else if (e.keyCode === 13) { // enter
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
this.onButtonClick();
|
||||
if (this.refs.textinput.value == '') {
|
||||
// if there's nothing in the input box, submit the form
|
||||
this.onButtonClick();
|
||||
} else {
|
||||
this._addInputToList();
|
||||
}
|
||||
} else if (e.keyCode === 188 || e.keyCode === 9) { // comma or tab
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
var check = Invite.isValidAddress(this.refs.textinput.value);
|
||||
if (check === true || check === null) {
|
||||
var inviteList = this.state.inviteList.slice();
|
||||
inviteList.push(this.refs.textinput.value.trim());
|
||||
this.setState({
|
||||
inviteList: inviteList,
|
||||
queryList: [],
|
||||
});
|
||||
} else {
|
||||
this.setState({ error: true });
|
||||
}
|
||||
this._addInputToList();
|
||||
}
|
||||
},
|
||||
|
||||
@@ -191,7 +192,7 @@ module.exports = React.createClass({
|
||||
inviteList: inviteList,
|
||||
queryList: [],
|
||||
});
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
onClick: function(index) {
|
||||
@@ -327,13 +328,18 @@ module.exports = React.createClass({
|
||||
return true;
|
||||
}
|
||||
|
||||
// split spaces in name and try matching constituent parts
|
||||
var parts = name.split(" ");
|
||||
for (var i = 0; i < parts.length; i++) {
|
||||
if (parts[i].indexOf(query) === 0) {
|
||||
return true;
|
||||
}
|
||||
// Try to find the query following a "word boundary", except that
|
||||
// this does avoids using \b because it only considers letters from
|
||||
// the roman alphabet to be word characters.
|
||||
// Instead, we look for the query following either:
|
||||
// * The start of the string
|
||||
// * Whitespace, or
|
||||
// * A fixed number of punctuation characters
|
||||
const expr = new RegExp("(?:^|[\\s\\(\)'\",\.-_@\?;:{}\\[\\]\\#~`\\*\\&\\$])" + escapeRegExp(query));
|
||||
if (expr.test(name)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
|
||||
@@ -373,6 +379,22 @@ module.exports = React.createClass({
|
||||
return addrs;
|
||||
},
|
||||
|
||||
_addInputToList: function() {
|
||||
const addrType = Invite.getAddressType(this.refs.textinput.value);
|
||||
if (addrType !== null) {
|
||||
const inviteList = this.state.inviteList.slice();
|
||||
inviteList.push(this.refs.textinput.value.trim());
|
||||
this.setState({
|
||||
inviteList: inviteList,
|
||||
queryList: [],
|
||||
});
|
||||
return inviteList;
|
||||
} else {
|
||||
this.setState({ error: true });
|
||||
return null;
|
||||
}
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var TintableSvg = sdk.getComponent("elements.TintableSvg");
|
||||
var AddressSelector = sdk.getComponent("elements.AddressSelector");
|
||||
@@ -406,13 +428,18 @@ module.exports = React.createClass({
|
||||
var error;
|
||||
var addressSelector;
|
||||
if (this.state.error) {
|
||||
error = <div className="mx_ChatInviteDialog_error">You have entered an invalid contact. Try using their Matrix ID or email address.</div>
|
||||
error = <div className="mx_ChatInviteDialog_error">You have entered an invalid contact. Try using their Matrix ID or email address.</div>;
|
||||
} else {
|
||||
const addressSelectorHeader = <div className="mx_ChatInviteDialog_addressSelectHeader">
|
||||
Searching known users
|
||||
</div>;
|
||||
addressSelector = (
|
||||
<AddressSelector ref={(ref) => {this.addressSelector = ref}}
|
||||
<AddressSelector ref={(ref) => {this.addressSelector = ref;}}
|
||||
addressList={ this.state.queryList }
|
||||
onSelected={ this.onSelected }
|
||||
truncateAt={ TRUNCATE_QUERY_LIST } />
|
||||
truncateAt={ TRUNCATE_QUERY_LIST }
|
||||
header={ addressSelectorHeader }
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -80,8 +80,8 @@ export default class DeactivateAccountDialog extends React.Component {
|
||||
let error = null;
|
||||
if (this.state.errStr) {
|
||||
error = <div className="error">
|
||||
{this.state.err_str}
|
||||
</div>
|
||||
{this.state.errStr}
|
||||
</div>;
|
||||
passwordBoxClass = 'error';
|
||||
}
|
||||
|
||||
@@ -92,7 +92,7 @@ export default class DeactivateAccountDialog extends React.Component {
|
||||
if (!this.state.busy) {
|
||||
cancelButton = <button onClick={this._onCancel} autoFocus={true}>
|
||||
Cancel
|
||||
</button>
|
||||
</button>;
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
@@ -1,187 +0,0 @@
|
||||
/*
|
||||
Copyright 2015, 2016 OpenMarket Ltd
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
var React = require("react");
|
||||
var sdk = require('../../../index');
|
||||
var MatrixClientPeg = require("../../../MatrixClientPeg");
|
||||
|
||||
module.exports = React.createClass({
|
||||
displayName: 'EncryptedEventDialog',
|
||||
|
||||
propTypes: {
|
||||
event: React.PropTypes.object.isRequired,
|
||||
onFinished: React.PropTypes.func.isRequired,
|
||||
},
|
||||
|
||||
getInitialState: function() {
|
||||
return { device: this.refreshDevice() };
|
||||
},
|
||||
|
||||
componentWillMount: function() {
|
||||
this._unmounted = false;
|
||||
var client = MatrixClientPeg.get();
|
||||
client.on("deviceVerificationChanged", this.onDeviceVerificationChanged);
|
||||
|
||||
// no need to redownload keys if we already have the device
|
||||
if (this.state.device) {
|
||||
return;
|
||||
}
|
||||
client.downloadKeys([this.props.event.getSender()], true).done(()=>{
|
||||
if (this._unmounted) {
|
||||
return;
|
||||
}
|
||||
this.setState({ device: this.refreshDevice() });
|
||||
}, (err)=>{
|
||||
console.log("Error downloading devices", err);
|
||||
});
|
||||
},
|
||||
|
||||
componentWillUnmount: function() {
|
||||
this._unmounted = true;
|
||||
var client = MatrixClientPeg.get();
|
||||
if (client) {
|
||||
client.removeListener("deviceVerificationChanged", this.onDeviceVerificationChanged);
|
||||
}
|
||||
},
|
||||
|
||||
refreshDevice: function() {
|
||||
return MatrixClientPeg.get().getEventSenderDeviceInfo(this.props.event);
|
||||
},
|
||||
|
||||
onDeviceVerificationChanged: function(userId, device) {
|
||||
if (userId == this.props.event.getSender()) {
|
||||
this.setState({ device: this.refreshDevice() });
|
||||
}
|
||||
},
|
||||
|
||||
onKeyDown: function(e) {
|
||||
if (e.keyCode === 27) { // escape
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
this.props.onFinished(false);
|
||||
}
|
||||
},
|
||||
|
||||
_renderDeviceInfo: function() {
|
||||
var device = this.state.device;
|
||||
if (!device) {
|
||||
return (<i>unknown device</i>);
|
||||
}
|
||||
|
||||
var verificationStatus = (<b>NOT verified</b>);
|
||||
if (device.isBlocked()) {
|
||||
verificationStatus = (<b>Blacklisted</b>);
|
||||
} else if (device.isVerified()) {
|
||||
verificationStatus = "verified";
|
||||
}
|
||||
|
||||
return (
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Name</td>
|
||||
<td>{ device.getDisplayName() }</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Device ID</td>
|
||||
<td><code>{ device.deviceId }</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Verification</td>
|
||||
<td>{ verificationStatus }</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Ed25519 fingerprint</td>
|
||||
<td><code>{device.getFingerprint()}</code></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
);
|
||||
},
|
||||
|
||||
_renderEventInfo: function() {
|
||||
var event = this.props.event;
|
||||
|
||||
return (
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>User ID</td>
|
||||
<td>{ event.getSender() }</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Curve25519 identity key</td>
|
||||
<td><code>{ event.getSenderKey() || <i>none</i> }</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Claimed Ed25519 fingerprint key</td>
|
||||
<td><code>{ event.getKeysClaimed().ed25519 || <i>none</i> }</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Algorithm</td>
|
||||
<td>{ event.getWireContent().algorithm || <i>unencrypted</i> }</td>
|
||||
</tr>
|
||||
{
|
||||
event.getContent().msgtype === 'm.bad.encrypted' ? (
|
||||
<tr>
|
||||
<td>Decryption error</td>
|
||||
<td>{ event.getContent().body }</td>
|
||||
</tr>
|
||||
) : null
|
||||
}
|
||||
<tr>
|
||||
<td>Session ID</td>
|
||||
<td><code>{ event.getWireContent().session_id || <i>none</i> }</code></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
);
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var DeviceVerifyButtons = sdk.getComponent('elements.DeviceVerifyButtons');
|
||||
|
||||
var buttons = null;
|
||||
if (this.state.device) {
|
||||
buttons = (
|
||||
<DeviceVerifyButtons device={ this.state.device }
|
||||
userId={ this.props.event.getSender() }
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="mx_EncryptedEventDialog" onKeyDown={ this.onKeyDown }>
|
||||
<div className="mx_Dialog_title">
|
||||
End-to-end encryption information
|
||||
</div>
|
||||
<div className="mx_Dialog_content">
|
||||
<h4>Event information</h4>
|
||||
{this._renderEventInfo()}
|
||||
|
||||
<h4>Sender device information</h4>
|
||||
{this._renderDeviceInfo()}
|
||||
</div>
|
||||
<div className="mx_Dialog_buttons">
|
||||
<button className="mx_Dialog_primary" onClick={ this.props.onFinished } autoFocus={ true }>
|
||||
OK
|
||||
</button>
|
||||
{buttons}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
@@ -30,6 +30,9 @@ module.exports = React.createClass({
|
||||
addressList: React.PropTypes.array.isRequired,
|
||||
truncateAt: React.PropTypes.number.isRequired,
|
||||
selected: React.PropTypes.number,
|
||||
|
||||
// Element to put as a header on top of the list
|
||||
header: React.PropTypes.node,
|
||||
},
|
||||
|
||||
getInitialState: function() {
|
||||
@@ -57,7 +60,7 @@ module.exports = React.createClass({
|
||||
}
|
||||
},
|
||||
|
||||
onKeyUp: function() {
|
||||
moveSelectionUp: function() {
|
||||
if (this.state.selected > 0) {
|
||||
this.setState({
|
||||
selected: this.state.selected - 1,
|
||||
@@ -66,7 +69,7 @@ module.exports = React.createClass({
|
||||
}
|
||||
},
|
||||
|
||||
onKeyDown: function() {
|
||||
moveSelectionDown: function() {
|
||||
if (this.state.selected < this._maxSelected(this.props.addressList)) {
|
||||
this.setState({
|
||||
selected: this.state.selected + 1,
|
||||
@@ -75,25 +78,19 @@ module.exports = React.createClass({
|
||||
}
|
||||
},
|
||||
|
||||
onKeySelect: function() {
|
||||
chooseSelection: function() {
|
||||
this.selectAddress(this.state.selected);
|
||||
},
|
||||
|
||||
onClick: function(index) {
|
||||
var self = this;
|
||||
return function() {
|
||||
self.selectAddress(index);
|
||||
};
|
||||
this.selectAddress(index);
|
||||
},
|
||||
|
||||
onMouseEnter: function(index) {
|
||||
var self = this;
|
||||
return function() {
|
||||
self.setState({
|
||||
selected: index,
|
||||
hover: true,
|
||||
});
|
||||
};
|
||||
this.setState({
|
||||
selected: index,
|
||||
hover: true,
|
||||
});
|
||||
},
|
||||
|
||||
onMouseLeave: function() {
|
||||
@@ -127,7 +124,7 @@ module.exports = React.createClass({
|
||||
// method, how far to scroll when using the arrow keys
|
||||
addressList.push(
|
||||
<div className={classes} onClick={this.onClick(i)} onMouseEnter={this.onMouseEnter(i)} onMouseLeave={this.onMouseLeave} key={i} ref={(ref) => { this.addressListElement = ref; }} >
|
||||
<AddressTile address={this.props.addressList[i]} justified={true} networkName="vector" networkUrl="img/search-icon-vector.svg" />
|
||||
<AddressTile address={this.props.addressList[i].userId} justified={true} networkName="vector" networkUrl="img/search-icon-vector.svg" />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -137,7 +134,7 @@ module.exports = React.createClass({
|
||||
|
||||
_maxSelected: function(list) {
|
||||
var listSize = list.length === 0 ? 0 : list.length - 1;
|
||||
var maxSelected = listSize > (this.props.truncateAt - 1) ? (this.props.truncateAt - 1) : listSize
|
||||
var maxSelected = listSize > (this.props.truncateAt - 1) ? (this.props.truncateAt - 1) : listSize;
|
||||
return maxSelected;
|
||||
},
|
||||
|
||||
@@ -148,7 +145,8 @@ module.exports = React.createClass({
|
||||
});
|
||||
|
||||
return (
|
||||
<div className={classes} ref={(ref) => {this.scrollElement = ref}}>
|
||||
<div className={classes} ref={(ref) => {this.scrollElement = ref;}}>
|
||||
{ this.props.header }
|
||||
{ this.createAddressListTiles() }
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -111,7 +111,7 @@ module.exports = React.createClass({
|
||||
info = (
|
||||
<div className={unknownMxClasses}>{ this.props.address }</div>
|
||||
);
|
||||
} else if (email) {
|
||||
} else if (email) {
|
||||
var emailClasses = classNames({
|
||||
"mx_AddressTile_email": true,
|
||||
"mx_AddressTile_justified": this.props.justified,
|
||||
|
||||
@@ -42,8 +42,8 @@ export default React.createClass({
|
||||
<div className="mx_UserSettings_cryptoSection">
|
||||
<ul>
|
||||
<li><label>Device name:</label> <span>{ this.props.device.getDisplayName() }</span></li>
|
||||
<li><label>Device ID:</label> <span><code>{ this.props.device.deviceId}</code></span></li>
|
||||
<li><label>Device key:</label> <span><code><b>{ this.props.device.getFingerprint() }</b></code></span></li>
|
||||
<li><label>Device ID:</label> <span><code>{ this.props.device.deviceId}</code></span></li>
|
||||
<li><label>Device key:</label> <span><code><b>{ this.props.device.getFingerprint() }</b></code></span></li>
|
||||
</ul>
|
||||
</div>
|
||||
<p>
|
||||
|
||||
@@ -57,7 +57,7 @@ module.exports = React.createClass({
|
||||
getInitialState: function() {
|
||||
return {
|
||||
phase: this.Phases.Display,
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
componentWillReceiveProps: function(nextProps) {
|
||||
@@ -164,7 +164,7 @@ module.exports = React.createClass({
|
||||
|
||||
this.setState({
|
||||
phase: this.Phases.Edit,
|
||||
})
|
||||
});
|
||||
},
|
||||
|
||||
onFocus: function(ev) {
|
||||
@@ -197,9 +197,9 @@ module.exports = React.createClass({
|
||||
sel.removeAllRanges();
|
||||
|
||||
if (this.props.blurToCancel)
|
||||
this.cancelEdit();
|
||||
{this.cancelEdit();}
|
||||
else
|
||||
this.onFinish(ev);
|
||||
{this.onFinish(ev);}
|
||||
|
||||
this.showPlaceholder(!this.value);
|
||||
},
|
||||
|
||||
@@ -73,7 +73,7 @@ module.exports = React.createClass({
|
||||
getValue: function() {
|
||||
var value;
|
||||
if (this.refs.select) {
|
||||
value = reverseRoles[ this.refs.select.value ];
|
||||
value = reverseRoles[this.refs.select.value];
|
||||
if (this.refs.custom) {
|
||||
if (value === undefined) value = parseInt( this.refs.custom.value );
|
||||
}
|
||||
@@ -86,10 +86,10 @@ module.exports = React.createClass({
|
||||
if (this.state.custom) {
|
||||
var input;
|
||||
if (this.props.disabled) {
|
||||
input = <span>{ this.props.value }</span>
|
||||
input = <span>{ this.props.value }</span>;
|
||||
}
|
||||
else {
|
||||
input = <input ref="custom" type="text" size="3" defaultValue={ this.props.value } onBlur={ this.onCustomBlur } onKeyDown={ this.onCustomKeyDown }/>
|
||||
input = <input ref="custom" type="text" size="3" defaultValue={ this.props.value } onBlur={ this.onCustomBlur } onKeyDown={ this.onCustomKeyDown }/>;
|
||||
}
|
||||
customPicker = <span> of { input }</span>;
|
||||
}
|
||||
@@ -115,7 +115,7 @@ module.exports = React.createClass({
|
||||
<option value="Moderator">Moderator (50)</option>
|
||||
<option value="Admin">Admin (100)</option>
|
||||
<option value="Custom">Custom level</option>
|
||||
</select>
|
||||
</select>;
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
@@ -35,4 +35,4 @@ module.exports = React.createClass({
|
||||
<div className="mx_ProgressBar"><div className="mx_ProgressBar_fill" style={progressStyle}></div></div>
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -55,7 +55,7 @@ module.exports = React.createClass({
|
||||
overflowJsx = this.props.createOverflowElement(
|
||||
overflowCount, childCount
|
||||
);
|
||||
|
||||
|
||||
// cut out the overflow elements
|
||||
childArray.splice(childCount - overflowCount, overflowCount);
|
||||
childsJsx = childArray; // use what is left
|
||||
|
||||
@@ -56,7 +56,7 @@ module.exports = React.createClass({
|
||||
<div>
|
||||
<ul className="mx_UserSelector_UserIdList" ref="list">
|
||||
{this.props.selected_users.map(function(user_id, i) {
|
||||
return <li key={user_id}>{user_id} - <span onClick={function() {self.removeUser(user_id);}}>X</span></li>
|
||||
return <li key={user_id}>{user_id} - <span onClick={function() {self.removeUser(user_id);}}>X</span></li>;
|
||||
})}
|
||||
</ul>
|
||||
<input type="text" ref="user_id_input" defaultValue="" className="mx_UserSelector_userIdInput" placeholder="ex. @bob:example.com"/>
|
||||
|
||||
@@ -52,7 +52,7 @@ module.exports = React.createClass({
|
||||
this._onCaptchaLoaded();
|
||||
} else {
|
||||
console.log("Loading recaptcha script...");
|
||||
window.mx_on_recaptcha_loaded = () => {this._onCaptchaLoaded()};
|
||||
window.mx_on_recaptcha_loaded = () => {this._onCaptchaLoaded();};
|
||||
var protocol = global.location.protocol;
|
||||
if (protocol === "file:") {
|
||||
var warning = document.createElement('div');
|
||||
@@ -101,7 +101,7 @@ module.exports = React.createClass({
|
||||
} catch (e) {
|
||||
this.setState({
|
||||
errorText: e.toString(),
|
||||
})
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@@ -70,7 +70,7 @@ export const PasswordAuthEntry = React.createClass({
|
||||
});
|
||||
},
|
||||
|
||||
_onPasswordFieldChange: function (ev) {
|
||||
_onPasswordFieldChange: function(ev) {
|
||||
// enable the submit button iff the password is non-empty
|
||||
this.props.setSubmitButtonEnabled(Boolean(ev.target.value));
|
||||
},
|
||||
@@ -209,4 +209,4 @@ export function getEntryComponentForLoginType(loginType) {
|
||||
}
|
||||
}
|
||||
return FallbackAuthEntry;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -38,6 +38,16 @@ module.exports = React.createClass({
|
||||
defaultEmail: React.PropTypes.string,
|
||||
defaultUsername: React.PropTypes.string,
|
||||
defaultPassword: React.PropTypes.string,
|
||||
teamsConfig: React.PropTypes.shape({
|
||||
// Email address to request new teams
|
||||
supportEmail: React.PropTypes.string,
|
||||
teams: React.PropTypes.arrayOf(React.PropTypes.shape({
|
||||
// The displayed name of the team
|
||||
"name": React.PropTypes.string,
|
||||
// The suffix with which every team email address ends
|
||||
"emailSuffix": React.PropTypes.string,
|
||||
})).required,
|
||||
}),
|
||||
|
||||
// A username that will be used if no username is entered.
|
||||
// Specifying this param will also warn the user that entering
|
||||
@@ -62,7 +72,8 @@ module.exports = React.createClass({
|
||||
|
||||
getInitialState: function() {
|
||||
return {
|
||||
fieldValid: {}
|
||||
fieldValid: {},
|
||||
selectedTeam: null,
|
||||
};
|
||||
},
|
||||
|
||||
@@ -105,10 +116,14 @@ module.exports = React.createClass({
|
||||
},
|
||||
|
||||
_doSubmit: function() {
|
||||
let email = this.refs.email.value.trim();
|
||||
if (this.state.selectedTeam) {
|
||||
email += "@" + this.state.selectedTeam.emailSuffix;
|
||||
}
|
||||
var promise = this.props.onRegisterClick({
|
||||
username: this.refs.username.value.trim() || this.props.guestUsername,
|
||||
password: this.refs.password.value.trim(),
|
||||
email: this.refs.email.value.trim()
|
||||
email: email,
|
||||
});
|
||||
|
||||
if (promise) {
|
||||
@@ -119,6 +134,25 @@ module.exports = React.createClass({
|
||||
}
|
||||
},
|
||||
|
||||
onSelectTeam: function(teamIndex) {
|
||||
let team = this._getSelectedTeam(teamIndex);
|
||||
if (team) {
|
||||
this.refs.email.value = this.refs.email.value.split("@")[0];
|
||||
}
|
||||
this.setState({
|
||||
selectedTeam: team,
|
||||
showSupportEmail: teamIndex === "other",
|
||||
});
|
||||
},
|
||||
|
||||
_getSelectedTeam: function(teamIndex) {
|
||||
if (this.props.teamsConfig &&
|
||||
this.props.teamsConfig.teams[teamIndex]) {
|
||||
return this.props.teamsConfig.teams[teamIndex];
|
||||
}
|
||||
return null;
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns true if all fields were valid last time
|
||||
* they were validated.
|
||||
@@ -135,15 +169,19 @@ module.exports = React.createClass({
|
||||
|
||||
validateField: function(field_id) {
|
||||
var pwd1 = this.refs.password.value.trim();
|
||||
var pwd2 = this.refs.passwordConfirm.value.trim()
|
||||
var pwd2 = this.refs.passwordConfirm.value.trim();
|
||||
|
||||
switch (field_id) {
|
||||
case FIELD_EMAIL:
|
||||
this.markFieldValid(
|
||||
field_id,
|
||||
this.refs.email.value == '' || Email.looksValid(this.refs.email.value),
|
||||
"RegistrationForm.ERR_EMAIL_INVALID"
|
||||
);
|
||||
let email = this.refs.email.value;
|
||||
if (this.props.teamsConfig) {
|
||||
let team = this.state.selectedTeam;
|
||||
if (team) {
|
||||
email = email + "@" + team.emailSuffix;
|
||||
}
|
||||
}
|
||||
let valid = email === '' || Email.looksValid(email);
|
||||
this.markFieldValid(field_id, valid, "RegistrationForm.ERR_EMAIL_INVALID");
|
||||
break;
|
||||
case FIELD_USERNAME:
|
||||
// XXX: SPEC-1
|
||||
@@ -222,17 +260,64 @@ module.exports = React.createClass({
|
||||
return cls;
|
||||
},
|
||||
|
||||
_renderEmailInputSuffix: function() {
|
||||
let suffix = null;
|
||||
if (!this.state.selectedTeam) {
|
||||
return suffix;
|
||||
}
|
||||
let team = this.state.selectedTeam;
|
||||
if (team) {
|
||||
suffix = "@" + team.emailSuffix;
|
||||
}
|
||||
return suffix;
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var self = this;
|
||||
var emailSection, registerButton;
|
||||
var emailSection, teamSection, teamAdditionSupport, registerButton;
|
||||
if (this.props.showEmail) {
|
||||
let emailSuffix = this._renderEmailInputSuffix();
|
||||
emailSection = (
|
||||
<input type="text" ref="email"
|
||||
autoFocus={true} placeholder="Email address (optional)"
|
||||
defaultValue={this.props.defaultEmail}
|
||||
className={this._classForField(FIELD_EMAIL, 'mx_Login_field')}
|
||||
onBlur={function() {self.validateField(FIELD_EMAIL)}} />
|
||||
<div>
|
||||
<input type="text" ref="email"
|
||||
autoFocus={true} placeholder="Email address (optional)"
|
||||
defaultValue={this.props.defaultEmail}
|
||||
className={this._classForField(FIELD_EMAIL, 'mx_Login_field')}
|
||||
onBlur={function() {self.validateField(FIELD_EMAIL);}}
|
||||
value={self.state.email}/>
|
||||
{emailSuffix ? <input className="mx_Login_field" value={emailSuffix} disabled/> : null }
|
||||
</div>
|
||||
);
|
||||
if (this.props.teamsConfig) {
|
||||
teamSection = (
|
||||
<select
|
||||
defaultValue="-1"
|
||||
className="mx_Login_field"
|
||||
onBlur={function() {self.validateField(FIELD_EMAIL);}}
|
||||
onChange={function(ev) {self.onSelectTeam(ev.target.value);}}
|
||||
>
|
||||
<option key="-1" value="-1">No team</option>
|
||||
{this.props.teamsConfig.teams.map((t, index) => {
|
||||
return (
|
||||
<option key={index} value={index}>
|
||||
{t.name}
|
||||
</option>
|
||||
);
|
||||
})}
|
||||
<option key="-2" value="other">Other</option>
|
||||
</select>
|
||||
);
|
||||
if (this.props.teamsConfig.supportEmail && this.state.showSupportEmail) {
|
||||
teamAdditionSupport = (
|
||||
<span>
|
||||
If your team is not listed, email
|
||||
<a href={"mailto:" + this.props.teamsConfig.supportEmail}>
|
||||
{this.props.teamsConfig.supportEmail}
|
||||
</a>
|
||||
</span>
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (this.props.onRegisterClick) {
|
||||
registerButton = (
|
||||
@@ -242,31 +327,34 @@ module.exports = React.createClass({
|
||||
|
||||
var placeholderUserName = "User name";
|
||||
if (this.props.guestUsername) {
|
||||
placeholderUserName += " (default: " + this.props.guestUsername + ")"
|
||||
placeholderUserName += " (default: " + this.props.guestUsername + ")";
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<form onSubmit={this.onSubmit}>
|
||||
{teamSection}
|
||||
{teamAdditionSupport}
|
||||
<br />
|
||||
{emailSection}
|
||||
<br />
|
||||
<input type="text" ref="username"
|
||||
placeholder={ placeholderUserName } defaultValue={this.props.defaultUsername}
|
||||
className={this._classForField(FIELD_USERNAME, 'mx_Login_field')}
|
||||
onBlur={function() {self.validateField(FIELD_USERNAME)}} />
|
||||
onBlur={function() {self.validateField(FIELD_USERNAME);}} />
|
||||
<br />
|
||||
{ this.props.guestUsername ?
|
||||
<div className="mx_Login_fieldLabel">Setting a user name will create a fresh account</div> : null
|
||||
}
|
||||
<input type="password" ref="password"
|
||||
className={this._classForField(FIELD_PASSWORD, 'mx_Login_field')}
|
||||
onBlur={function() {self.validateField(FIELD_PASSWORD)}}
|
||||
onBlur={function() {self.validateField(FIELD_PASSWORD);}}
|
||||
placeholder="Password" defaultValue={this.props.defaultPassword} />
|
||||
<br />
|
||||
<input type="password" ref="passwordConfirm"
|
||||
placeholder="Confirm password"
|
||||
className={this._classForField(FIELD_PASSWORD_CONFIRM, 'mx_Login_field')}
|
||||
onBlur={function() {self.validateField(FIELD_PASSWORD_CONFIRM)}}
|
||||
onBlur={function() {self.validateField(FIELD_PASSWORD_CONFIRM);}}
|
||||
defaultValue={this.props.defaultPassword} />
|
||||
<br />
|
||||
{registerButton}
|
||||
|
||||
@@ -64,10 +64,10 @@ module.exports = React.createClass({
|
||||
hs_url: this.props.customHsUrl,
|
||||
is_url: this.props.customIsUrl,
|
||||
// if withToggleButton is false, then show the config all the time given we have no way otherwise of making it visible
|
||||
configVisible: !this.props.withToggleButton ||
|
||||
configVisible: !this.props.withToggleButton ||
|
||||
(this.props.customHsUrl !== this.props.defaultHsUrl) ||
|
||||
(this.props.customIsUrl !== this.props.defaultIsUrl)
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
onHomeserverChanged: function(ev) {
|
||||
|
||||
@@ -31,7 +31,7 @@ export default class MAudioBody extends React.Component {
|
||||
decryptedUrl: null,
|
||||
decryptedBlob: null,
|
||||
error: null,
|
||||
}
|
||||
};
|
||||
}
|
||||
onPlayToggle() {
|
||||
this.setState({
|
||||
|
||||
@@ -281,7 +281,7 @@ module.exports = React.createClass({
|
||||
decryptedBlob: blob,
|
||||
});
|
||||
}).catch((err) => {
|
||||
console.warn("Unable to decrypt attachment: ", err)
|
||||
console.warn("Unable to decrypt attachment: ", err);
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
description: "Error decrypting attachment"
|
||||
});
|
||||
@@ -372,7 +372,7 @@ module.exports = React.createClass({
|
||||
var extra = text ? (': ' + text) : '';
|
||||
return <span className="mx_MFileBody">
|
||||
Invalid file{extra}
|
||||
</span>
|
||||
</span>;
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
@@ -119,7 +119,7 @@ module.exports = React.createClass({
|
||||
if (content.info.thumbnail_file) {
|
||||
thumbnailPromise = decryptFile(
|
||||
content.info.thumbnail_file
|
||||
).then(function (blob) {
|
||||
).then(function(blob) {
|
||||
return readBlobAsDataUri(blob);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -111,7 +111,7 @@ module.exports = React.createClass({
|
||||
this.props.onWidgetLoad();
|
||||
});
|
||||
}).catch((err) => {
|
||||
console.warn("Unable to decrypt attachment: ", err)
|
||||
console.warn("Unable to decrypt attachment: ", err);
|
||||
// Set a placeholder image when we can't decrypt the image.
|
||||
this.setState({
|
||||
error: err,
|
||||
|
||||
@@ -200,7 +200,7 @@ module.exports = React.createClass({
|
||||
global.localStorage.removeItem("hide_preview_" + self.props.mxEvent.getId());
|
||||
}
|
||||
},
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
onStarterLinkClick: function(starterLink, ev) {
|
||||
@@ -230,8 +230,8 @@ module.exports = React.createClass({
|
||||
if (!confirmed) {
|
||||
return;
|
||||
}
|
||||
let width = window.screen.width > 1024 ? 1024 : window.screen.width;
|
||||
let height = window.screen.height > 800 ? 800 : window.screen.height;
|
||||
let width = window.screen.width > 1024 ? 1024 : window.screen.width;
|
||||
let height = window.screen.height > 800 ? 800 : window.screen.height;
|
||||
let left = (window.screen.width - width) / 2;
|
||||
let top = (window.screen.height - height) / 2;
|
||||
window.open(completeUrl, '_blank', `height=${height}, width=${width}, top=${top}, left=${left},`);
|
||||
|
||||
@@ -103,13 +103,13 @@ module.exports = React.createClass({
|
||||
}
|
||||
if (oldCanonicalAlias !== this.state.canonicalAlias) {
|
||||
console.log("AliasSettings: Updating canonical alias");
|
||||
promises = [ q.all(promises).then(
|
||||
promises = [q.all(promises).then(
|
||||
MatrixClientPeg.get().sendStateEvent(
|
||||
this.props.roomId, "m.room.canonical_alias", {
|
||||
alias: this.state.canonicalAlias
|
||||
}, ""
|
||||
)
|
||||
) ];
|
||||
)];
|
||||
}
|
||||
|
||||
return promises;
|
||||
@@ -144,7 +144,7 @@ module.exports = React.createClass({
|
||||
// XXX: do we need to deep copy aliases before editing it?
|
||||
this.state.domainToAliases[domain] = this.state.domainToAliases[domain] || [];
|
||||
this.state.domainToAliases[domain].push(alias);
|
||||
this.setState({
|
||||
this.setState({
|
||||
domainToAliases: this.state.domainToAliases
|
||||
});
|
||||
|
||||
@@ -152,9 +152,9 @@ module.exports = React.createClass({
|
||||
this.refs.add_alias.setValue(''); // FIXME
|
||||
}
|
||||
else {
|
||||
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: "Invalid alias format",
|
||||
title: "Invalid alias format",
|
||||
description: "'" + alias + "' is not a valid format for an alias",
|
||||
});
|
||||
}
|
||||
@@ -168,9 +168,9 @@ module.exports = React.createClass({
|
||||
this.state.domainToAliases[domain][index] = alias;
|
||||
}
|
||||
else {
|
||||
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
title: "Invalid address format",
|
||||
title: "Invalid address format",
|
||||
description: "'" + alias + "' is not a valid format for an address",
|
||||
});
|
||||
}
|
||||
@@ -183,7 +183,7 @@ module.exports = React.createClass({
|
||||
// would be to arbitrarily deepcopy to a temp variable and then setState
|
||||
// that, but why bother when we can cut this corner.
|
||||
var alias = this.state.domainToAliases[domain].splice(index, 1);
|
||||
this.setState({
|
||||
this.setState({
|
||||
domainToAliases: this.state.domainToAliases
|
||||
});
|
||||
},
|
||||
@@ -281,7 +281,7 @@ module.exports = React.createClass({
|
||||
onValueChanged={ self.onAliasChanged.bind(self, localDomain, i) }
|
||||
editable={ self.props.canSetAliases }
|
||||
initialValue={ alias } />
|
||||
<div className="mx_RoomSettings_deleteAlias">
|
||||
<div className="mx_RoomSettings_deleteAlias mx_filterFlipColor">
|
||||
{ deleteButton }
|
||||
</div>
|
||||
</div>
|
||||
@@ -297,7 +297,7 @@ module.exports = React.createClass({
|
||||
placeholder={ "New address (e.g. #foo:" + localDomain + ")" }
|
||||
blurToCancel={ false }
|
||||
onValueChanged={ self.onAliasAdded } />
|
||||
<div className="mx_RoomSettings_addAlias">
|
||||
<div className="mx_RoomSettings_addAlias mx_filterFlipColor">
|
||||
<img src="img/plus.svg" width="14" height="14" alt="Add"
|
||||
onClick={ self.onAliasAdded.bind(self, undefined) }/>
|
||||
</div>
|
||||
@@ -310,4 +310,4 @@ module.exports = React.createClass({
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -135,7 +135,7 @@ module.exports = React.createClass({
|
||||
</div>
|
||||
);
|
||||
}
|
||||
var boundClick = this._onColorSchemeChanged.bind(this, i)
|
||||
var boundClick = this._onColorSchemeChanged.bind(this, i);
|
||||
return (
|
||||
<div className="mx_RoomSettings_roomColor"
|
||||
key={ "room_color_" + i }
|
||||
|
||||
@@ -121,13 +121,13 @@ module.exports = React.createClass({
|
||||
onChange={ this.onGlobalDisableUrlPreviewChange }
|
||||
checked={ this.state.globalDisableUrlPreview } />
|
||||
Disable URL previews by default for participants in this room
|
||||
</label>
|
||||
</label>;
|
||||
}
|
||||
else {
|
||||
disableRoomPreviewUrls =
|
||||
<label>
|
||||
URL previews are { this.state.globalDisableUrlPreview ? "disabled" : "enabled" } by default for participants in this room.
|
||||
</label>
|
||||
</label>;
|
||||
}
|
||||
|
||||
return (
|
||||
@@ -154,4 +154,4 @@ module.exports = React.createClass({
|
||||
);
|
||||
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -93,8 +93,8 @@ module.exports = React.createClass({
|
||||
}
|
||||
else {
|
||||
joinText = (<span>
|
||||
Join as <a onClick={(event)=>{ this.onConferenceNotificationClick(event, 'voice')}}
|
||||
href="#">voice</a> or <a onClick={(event)=>{ this.onConferenceNotificationClick(event, 'video') }}
|
||||
Join as <a onClick={(event)=>{ this.onConferenceNotificationClick(event, 'voice');}}
|
||||
href="#">voice</a> or <a onClick={(event)=>{ this.onConferenceNotificationClick(event, 'video'); }}
|
||||
href="#">video</a>.
|
||||
</span>);
|
||||
|
||||
|
||||
@@ -149,13 +149,13 @@ module.exports = WithMatrixClient(React.createClass({
|
||||
this.props.mxEvent.on("Event.decrypted", this._onDecrypted);
|
||||
},
|
||||
|
||||
componentWillReceiveProps: function (nextProps) {
|
||||
componentWillReceiveProps: function(nextProps) {
|
||||
if (nextProps.mxEvent !== this.props.mxEvent) {
|
||||
this._verifyEvent(nextProps.mxEvent);
|
||||
}
|
||||
},
|
||||
|
||||
shouldComponentUpdate: function (nextProps, nextState) {
|
||||
shouldComponentUpdate: function(nextProps, nextState) {
|
||||
if (!ObjectUtils.shallowEqual(this.state, nextState)) {
|
||||
return true;
|
||||
}
|
||||
@@ -259,11 +259,11 @@ module.exports = WithMatrixClient(React.createClass({
|
||||
|
||||
onEditClicked: function(e) {
|
||||
var MessageContextMenu = sdk.getComponent('context_menus.MessageContextMenu');
|
||||
var buttonRect = e.target.getBoundingClientRect()
|
||||
var buttonRect = e.target.getBoundingClientRect();
|
||||
|
||||
// The window X and Y offsets are to adjust position when zoomed in to page
|
||||
var x = buttonRect.right + window.pageXOffset;
|
||||
var y = (buttonRect.top + (e.target.height / 2) + window.pageYOffset) - 19;
|
||||
var y = (buttonRect.top + (buttonRect.height / 2) + window.pageYOffset) - 19;
|
||||
var self = this;
|
||||
ContextualMenu.createMenu(MessageContextMenu, {
|
||||
chevronOffset: 10,
|
||||
@@ -293,7 +293,7 @@ module.exports = WithMatrixClient(React.createClass({
|
||||
// If it is, we want to display the complete date along with the HH:MM:SS,
|
||||
// rather than just HH:MM:SS.
|
||||
let dayAfterEvent = new Date(this.props.mxEvent.getTs());
|
||||
dayAfterEvent.setDate(dayAfterEvent.getDate() + 1)
|
||||
dayAfterEvent.setDate(dayAfterEvent.getDate() + 1);
|
||||
dayAfterEvent.setHours(0);
|
||||
dayAfterEvent.setMinutes(0);
|
||||
dayAfterEvent.setSeconds(0);
|
||||
@@ -366,10 +366,11 @@ module.exports = WithMatrixClient(React.createClass({
|
||||
},
|
||||
|
||||
onCryptoClicked: function(e) {
|
||||
var EncryptedEventDialog = sdk.getComponent("dialogs.EncryptedEventDialog");
|
||||
var event = this.props.mxEvent;
|
||||
|
||||
Modal.createDialog(EncryptedEventDialog, {
|
||||
Modal.createDialogAsync((cb) => {
|
||||
require(['../../../async-components/views/dialogs/EncryptedEventDialog'], cb);
|
||||
}, {
|
||||
event: event,
|
||||
});
|
||||
},
|
||||
@@ -465,7 +466,7 @@ module.exports = WithMatrixClient(React.createClass({
|
||||
}
|
||||
|
||||
var editButton = (
|
||||
<img className="mx_EventTile_editButton" src="img/icon_context_message.svg" width="19" height="19" alt="Options" title="Options" onClick={this.onEditClicked} />
|
||||
<span className="mx_EventTile_editButton" title="Options" onClick={this.onEditClicked} />
|
||||
);
|
||||
|
||||
var e2e;
|
||||
|
||||
@@ -60,13 +60,15 @@ module.exports = React.createClass({
|
||||
},
|
||||
|
||||
componentDidMount: function() {
|
||||
if (this.refs.description)
|
||||
if (this.refs.description) {
|
||||
linkifyElement(this.refs.description, linkifyMatrix.options);
|
||||
}
|
||||
},
|
||||
|
||||
componentDidUpdate: function() {
|
||||
if (this.refs.description)
|
||||
if (this.refs.description) {
|
||||
linkifyElement(this.refs.description, linkifyMatrix.options);
|
||||
}
|
||||
},
|
||||
|
||||
componentWillUnmount: function() {
|
||||
@@ -116,7 +118,7 @@ module.exports = React.createClass({
|
||||
if (image) {
|
||||
img = <div className="mx_LinkPreviewWidget_image" style={{ height: thumbHeight }}>
|
||||
<img style={{ maxWidth: imageMaxWidth, maxHeight: imageMaxHeight }} src={ image } onClick={ this.onImageClick }/>
|
||||
</div>
|
||||
</div>;
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
@@ -60,7 +60,7 @@ export default class MemberDeviceInfo extends React.Component {
|
||||
</div>
|
||||
);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
MemberDeviceInfo.displayName = 'MemberDeviceInfo';
|
||||
MemberDeviceInfo.propTypes = {
|
||||
|
||||
@@ -64,7 +64,7 @@ module.exports = WithMatrixClient(React.createClass({
|
||||
updating: 0,
|
||||
devicesLoading: true,
|
||||
devices: null,
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
componentWillMount: function() {
|
||||
@@ -202,7 +202,7 @@ module.exports = WithMatrixClient(React.createClass({
|
||||
}
|
||||
|
||||
var cancelled = false;
|
||||
this._cancelDeviceList = function() { cancelled = true; }
|
||||
this._cancelDeviceList = function() { cancelled = true; };
|
||||
|
||||
var client = this.props.matrixClient;
|
||||
var self = this;
|
||||
@@ -529,7 +529,7 @@ module.exports = WithMatrixClient(React.createClass({
|
||||
});
|
||||
},
|
||||
|
||||
onMemberAvatarClick: function () {
|
||||
onMemberAvatarClick: function() {
|
||||
var avatarUrl = this.props.member.user ? this.props.member.user.avatarUrl : this.props.member.events.member.getContent().avatar_url;
|
||||
if(!avatarUrl) return;
|
||||
|
||||
@@ -620,7 +620,7 @@ module.exports = WithMatrixClient(React.createClass({
|
||||
<img src="img/create-big.svg" width="26" height="26" />
|
||||
</div>
|
||||
<div className={labelClasses}><i>Start new chat</i></div>
|
||||
</div>
|
||||
</div>;
|
||||
|
||||
startChat = <div>
|
||||
<h3>Direct chats</h3>
|
||||
@@ -654,7 +654,7 @@ module.exports = WithMatrixClient(React.createClass({
|
||||
var giveOpLabel = this.state.isTargetMod ? "Revoke Moderator" : "Make Moderator";
|
||||
giveModButton = <div className="mx_MemberInfo_field" onClick={this.onModToggle}>
|
||||
{giveOpLabel}
|
||||
</div>
|
||||
</div>;
|
||||
}
|
||||
|
||||
// TODO: we should have an invite button if this MemberInfo is showing a user who isn't actually in the current room yet
|
||||
@@ -672,7 +672,7 @@ module.exports = WithMatrixClient(React.createClass({
|
||||
{banButton}
|
||||
{giveModButton}
|
||||
</div>
|
||||
</div>
|
||||
</div>;
|
||||
}
|
||||
|
||||
const memberName = this.props.member.name;
|
||||
|
||||
@@ -32,7 +32,7 @@ var SHARE_HISTORY_WARNING =
|
||||
Newly invited users will see the history of this room. <br/>
|
||||
If you'd prefer invited users not to see messages that were sent before they joined, <br/>
|
||||
turn off, 'Share message history with new users' in the settings for this room.
|
||||
</span>
|
||||
</span>;
|
||||
|
||||
module.exports = React.createClass({
|
||||
displayName: 'MemberList',
|
||||
@@ -207,7 +207,7 @@ module.exports = React.createClass({
|
||||
// For now we'll pretend this is any entity. It should probably be a separate tile.
|
||||
var EntityTile = sdk.getComponent("rooms.EntityTile");
|
||||
var BaseAvatar = sdk.getComponent("avatars.BaseAvatar");
|
||||
var text = "and " + overflowCount + " other" + (overflowCount > 1 ? "s" : "") + "...";
|
||||
var text = "and " + overflowCount + " other" + (overflowCount > 1 ? "s" : "") + "...";
|
||||
return (
|
||||
<EntityTile className="mx_EntityTile_ellipsis" avatarJsx={
|
||||
<BaseAvatar url="img/ellipsis.svg" name="..." width={36} height={36} />
|
||||
@@ -338,8 +338,8 @@ module.exports = React.createClass({
|
||||
}
|
||||
memberList.push(
|
||||
<EntityTile key={e.getStateKey()} name={e.getContent().display_name} />
|
||||
)
|
||||
})
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ module.exports = React.createClass({
|
||||
(this.user_last_modified_time === undefined ||
|
||||
this.user_last_modified_time < nextProps.member.user.getLastModifiedTime())
|
||||
) {
|
||||
return true
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
@@ -222,20 +222,22 @@ export default class MessageComposer extends React.Component {
|
||||
</div>
|
||||
);
|
||||
|
||||
let e2eimg, e2etitle;
|
||||
let e2eImg, e2eTitle, e2eClass;
|
||||
|
||||
if (MatrixClientPeg.get().isRoomEncrypted(this.props.room.roomId)) {
|
||||
// FIXME: show a /!\ if there are untrusted devices in the room...
|
||||
e2eimg = 'img/e2e-verified.svg';
|
||||
e2etitle = 'Encrypted room';
|
||||
e2eImg = 'img/e2e-verified.svg';
|
||||
e2eTitle = 'Encrypted room';
|
||||
e2eClass = 'mx_MessageComposer_e2eIcon';
|
||||
} else {
|
||||
e2eimg = 'img/e2e-unencrypted.svg';
|
||||
e2etitle = 'Unencrypted room';
|
||||
e2eImg = 'img/e2e-unencrypted.svg';
|
||||
e2eTitle = 'Unencrypted room';
|
||||
e2eClass = 'mx_MessageComposer_e2eIcon mx_filterFlipColor';
|
||||
}
|
||||
|
||||
controls.push(
|
||||
<img key="e2eIcon" className="mx_MessageComposer_e2eIcon" src={e2eimg} width="12" height="12"
|
||||
alt={e2etitle} title={e2etitle}
|
||||
<img key="e2eIcon" className={e2eClass} src={e2eImg} width="12" height="12"
|
||||
alt={e2eTitle} title={e2eTitle}
|
||||
/>
|
||||
);
|
||||
var callButton, videoCallButton, hangupButton;
|
||||
@@ -331,6 +333,7 @@ export default class MessageComposer extends React.Component {
|
||||
const disabled = !this.state.inputState.isRichtextEnabled && 'underline' === name;
|
||||
const className = classNames("mx_MessageComposer_format_button", {
|
||||
mx_MessageComposer_format_button_disabled: disabled,
|
||||
mx_filterFlipColor: true,
|
||||
});
|
||||
return <img className={className}
|
||||
title={name}
|
||||
@@ -355,11 +358,11 @@ export default class MessageComposer extends React.Component {
|
||||
<div style={{flex: 1}}></div>
|
||||
<img title={`Turn Markdown ${this.state.inputState.isRichtextEnabled ? 'on' : 'off'}`}
|
||||
onMouseDown={this.onToggleMarkdownClicked}
|
||||
className="mx_MessageComposer_formatbar_markdown"
|
||||
className="mx_MessageComposer_formatbar_markdown mx_filterFlipColor"
|
||||
src={`img/button-md-${!this.state.inputState.isRichtextEnabled}.png`} />
|
||||
<img title="Hide Text Formatting Toolbar"
|
||||
onClick={this.onToggleFormattingClicked}
|
||||
className="mx_MessageComposer_formatbar_cancel"
|
||||
className="mx_MessageComposer_formatbar_cancel mx_filterFlipColor"
|
||||
src="img/icon-text-cancel.svg" />
|
||||
</div>
|
||||
</div>: null
|
||||
@@ -367,7 +370,7 @@ export default class MessageComposer extends React.Component {
|
||||
</div>
|
||||
);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
MessageComposer.propTypes = {
|
||||
tabComplete: React.PropTypes.any,
|
||||
|
||||
@@ -443,12 +443,12 @@ export default class MessageComposerInput extends React.Component {
|
||||
selection = this.state.editorState.getSelection();
|
||||
|
||||
let modifyFn = {
|
||||
bold: text => `**${text}**`,
|
||||
italic: text => `*${text}*`,
|
||||
underline: text => `_${text}_`, // there's actually no valid underline in Markdown, but *shrug*
|
||||
strike: text => `~~${text}~~`,
|
||||
code: text => `\`${text}\``,
|
||||
blockquote: text => text.split('\n').map(line => `> ${line}\n`).join(''),
|
||||
'bold': text => `**${text}**`,
|
||||
'italic': text => `*${text}*`,
|
||||
'underline': text => `_${text}_`, // there's actually no valid underline in Markdown, but *shrug*
|
||||
'strike': text => `~~${text}~~`,
|
||||
'code': text => `\`${text}\``,
|
||||
'blockquote': text => text.split('\n').map(line => `> ${line}\n`).join(''),
|
||||
'unordered-list-item': text => text.split('\n').map(line => `- ${line}\n`).join(''),
|
||||
'ordered-list-item': text => text.split('\n').map((line, i) => `${i+1}. ${line}\n`).join(''),
|
||||
}[command];
|
||||
@@ -462,8 +462,9 @@ export default class MessageComposerInput extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
if (newState == null)
|
||||
if (newState == null) {
|
||||
newState = RichUtils.handleKeyCommand(this.state.editorState, command);
|
||||
}
|
||||
|
||||
if (newState != null) {
|
||||
this.setEditorState(newState);
|
||||
@@ -523,7 +524,9 @@ export default class MessageComposerInput extends React.Component {
|
||||
);
|
||||
} else {
|
||||
const md = new Markdown(contentText);
|
||||
if (!md.isPlainText()) {
|
||||
if (md.isPlainText()) {
|
||||
contentText = md.toPlaintext();
|
||||
} else {
|
||||
contentHTML = md.toHTML();
|
||||
}
|
||||
}
|
||||
@@ -663,7 +666,7 @@ export default class MessageComposerInput extends React.Component {
|
||||
|
||||
const blockName = {
|
||||
'code-block': 'code',
|
||||
blockquote: 'quote',
|
||||
'blockquote': 'quote',
|
||||
'unordered-list-item': 'bullet',
|
||||
'ordered-list-item': 'numbullet',
|
||||
};
|
||||
@@ -716,7 +719,7 @@ export default class MessageComposerInput extends React.Component {
|
||||
selection={selection} />
|
||||
</div>
|
||||
<div className={className}>
|
||||
<img className="mx_MessageComposer_input_markdownIndicator"
|
||||
<img className="mx_MessageComposer_input_markdownIndicator mx_filterFlipColor"
|
||||
onMouseDown={this.onMarkdownToggleClicked}
|
||||
title={`Markdown is ${this.state.isRichtextEnabled ? 'disabled' : 'enabled'}`}
|
||||
src={`img/button-md-${!this.state.isRichtextEnabled}.png`} />
|
||||
@@ -738,7 +741,7 @@ export default class MessageComposerInput extends React.Component {
|
||||
</div>
|
||||
);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
MessageComposerInput.propTypes = {
|
||||
tabComplete: React.PropTypes.any,
|
||||
|
||||
@@ -192,7 +192,7 @@ module.exports = React.createClass({
|
||||
}
|
||||
},
|
||||
|
||||
onKeyDown: function (ev) {
|
||||
onKeyDown: function(ev) {
|
||||
if (ev.keyCode === KeyCode.ENTER && !ev.shiftKey) {
|
||||
var input = this.refs.textarea.value;
|
||||
if (input.length === 0) {
|
||||
@@ -331,6 +331,7 @@ module.exports = React.createClass({
|
||||
MatrixClientPeg.get().sendHtmlMessage(this.props.room.roomId, contentText, htmlText);
|
||||
}
|
||||
else {
|
||||
const contentText = mdown.toPlaintext();
|
||||
sendMessagePromise = isEmote ?
|
||||
MatrixClientPeg.get().sendEmoteMessage(this.props.room.roomId, contentText) :
|
||||
MatrixClientPeg.get().sendTextMessage(this.props.room.roomId, contentText);
|
||||
|
||||
@@ -71,7 +71,7 @@ module.exports = React.createClass({
|
||||
getDefaultProps: function() {
|
||||
return {
|
||||
leftOffset: 0,
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
getInitialState: function() {
|
||||
@@ -81,7 +81,7 @@ module.exports = React.createClass({
|
||||
// position.
|
||||
return {
|
||||
suppressDisplay: !this.props.suppressAnimation,
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
componentWillUnmount: function() {
|
||||
|
||||
@@ -182,8 +182,8 @@ module.exports = React.createClass({
|
||||
'm.room.name', user_id
|
||||
);
|
||||
|
||||
save_button = <div className="mx_RoomHeader_textButton" onClick={this.props.onSaveClick}>Save</div>
|
||||
cancel_button = <div className="mx_RoomHeader_cancelButton" onClick={this.props.onCancelClick}><img src="img/cancel.svg" width="18" height="18" alt="Cancel"/> </div>
|
||||
save_button = <div className="mx_RoomHeader_textButton" onClick={this.props.onSaveClick}>Save</div>;
|
||||
cancel_button = <div className="mx_RoomHeader_cancelButton mx_filterFlipColor" onClick={this.props.onCancelClick}><img src="img/cancel.svg" width="18" height="18" alt="Cancel"/> </div>;
|
||||
}
|
||||
|
||||
if (this.props.saving) {
|
||||
@@ -193,7 +193,7 @@ module.exports = React.createClass({
|
||||
|
||||
if (can_set_room_name) {
|
||||
var RoomNameEditor = sdk.getComponent("rooms.RoomNameEditor");
|
||||
name = <RoomNameEditor ref="nameEditor" room={this.props.room} />
|
||||
name = <RoomNameEditor ref="nameEditor" room={this.props.room} />;
|
||||
}
|
||||
else {
|
||||
var searchStatus;
|
||||
@@ -232,7 +232,7 @@ module.exports = React.createClass({
|
||||
|
||||
if (can_set_room_topic) {
|
||||
var RoomTopicEditor = sdk.getComponent("rooms.RoomTopicEditor");
|
||||
topic_el = <RoomTopicEditor ref="topicEditor" room={this.props.room} />
|
||||
topic_el = <RoomTopicEditor ref="topicEditor" room={this.props.room} />;
|
||||
} else {
|
||||
var topic;
|
||||
if (this.props.room) {
|
||||
@@ -301,7 +301,7 @@ module.exports = React.createClass({
|
||||
rightPanel_buttons =
|
||||
<div className="mx_RoomHeader_button" onClick={this.onShowRhsClick} title="<">
|
||||
<TintableSvg src="img/minimise.svg" width="10" height="16"/>
|
||||
</div>
|
||||
</div>;
|
||||
}
|
||||
|
||||
var right_row;
|
||||
|
||||
@@ -46,7 +46,7 @@ module.exports = React.createClass({
|
||||
isLoadingLeftRooms: false,
|
||||
lists: {},
|
||||
incomingCall: null,
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
componentWillMount: function() {
|
||||
@@ -338,7 +338,7 @@ module.exports = React.createClass({
|
||||
// as this is used to calculate the CSS fixed top position for the stickies
|
||||
var scrollAreaHeight = ReactDOM.findDOMNode(this).getBoundingClientRect().height;
|
||||
|
||||
var top = (incomingCallBox.parentElement.getBoundingClientRect().top + window.pageYOffset)
|
||||
var top = (incomingCallBox.parentElement.getBoundingClientRect().top + window.pageYOffset);
|
||||
// Make sure we don't go too far up, if the headers aren't sticky
|
||||
top = (top < scrollAreaOffset) ? scrollAreaOffset : top;
|
||||
// make sure we don't go too far down, if the headers aren't sticky
|
||||
@@ -401,7 +401,7 @@ module.exports = React.createClass({
|
||||
var stickyHeight = sticky.dataset.originalHeight;
|
||||
var stickyHeader = sticky.childNodes[0];
|
||||
var topStuckHeight = stickyHeight * i;
|
||||
var bottomStuckHeight = stickyHeight * (stickyWrappers.length - i)
|
||||
var bottomStuckHeight = stickyHeight * (stickyWrappers.length - i);
|
||||
|
||||
if (self.scrollAreaSufficient && stickyPosition < (scrollArea.scrollTop + topStuckHeight)) {
|
||||
// Top stickies
|
||||
@@ -520,7 +520,7 @@ module.exports = React.createClass({
|
||||
collapsed={ self.props.collapsed }
|
||||
searchFilter={ self.props.searchFilter }
|
||||
onHeaderClick={ self.onSubListHeaderClick }
|
||||
onShowMoreRooms={ self.onShowMoreRooms } />
|
||||
onShowMoreRooms={ self.onShowMoreRooms } />;
|
||||
|
||||
}
|
||||
}) }
|
||||
|
||||
@@ -58,7 +58,7 @@ module.exports = React.createClass({
|
||||
getInitialState: function() {
|
||||
return {
|
||||
busy: false
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
componentWillMount: function() {
|
||||
@@ -96,7 +96,7 @@ module.exports = React.createClass({
|
||||
emailMatchBlock = <div className="error">
|
||||
Unable to ascertain that the address this invite was
|
||||
sent to matches one associated with your account.
|
||||
</div>
|
||||
</div>;
|
||||
} else if (this.state.invitedEmailMxid != MatrixClientPeg.get().credentials.userId) {
|
||||
emailMatchBlock =
|
||||
<div className="mx_RoomPreviewBar_warning">
|
||||
@@ -107,7 +107,7 @@ module.exports = React.createClass({
|
||||
This invitation was sent to <b><span className="email">{this.props.invitedEmail}</span></b>, which is not associated with this account.<br/>
|
||||
You may wish to login with a different account, or add this email to this account.
|
||||
</div>
|
||||
</div>
|
||||
</div>;
|
||||
}
|
||||
}
|
||||
joinBlock = (
|
||||
|
||||
@@ -252,7 +252,7 @@ module.exports = React.createClass({
|
||||
return this.refs.url_preview_settings.saveSettings();
|
||||
},
|
||||
|
||||
saveEncryption: function () {
|
||||
saveEncryption: function() {
|
||||
if (!this.refs.encrypt) { return q(); }
|
||||
|
||||
var encrypt = this.refs.encrypt.checked;
|
||||
@@ -404,7 +404,7 @@ module.exports = React.createClass({
|
||||
var cli = MatrixClientPeg.get();
|
||||
var roomState = this.props.room.currentState;
|
||||
return (roomState.mayClientSendStateEvent("m.room.join_rules", cli) &&
|
||||
roomState.mayClientSendStateEvent("m.room.guest_access", cli))
|
||||
roomState.mayClientSendStateEvent("m.room.guest_access", cli));
|
||||
},
|
||||
|
||||
onManageIntegrations(ev) {
|
||||
@@ -510,7 +510,7 @@ module.exports = React.createClass({
|
||||
var UrlPreviewSettings = sdk.getComponent("room_settings.UrlPreviewSettings");
|
||||
var EditableText = sdk.getComponent('elements.EditableText');
|
||||
var PowerSelector = sdk.getComponent('elements.PowerSelector');
|
||||
var Loader = sdk.getComponent("elements.Spinner")
|
||||
var Loader = sdk.getComponent("elements.Spinner");
|
||||
|
||||
var cli = MatrixClientPeg.get();
|
||||
var roomState = this.props.room.currentState;
|
||||
@@ -557,7 +557,7 @@ module.exports = React.createClass({
|
||||
</div>;
|
||||
}
|
||||
else {
|
||||
userLevelsSection = <div>No users have specific privileges in this room.</div>
|
||||
userLevelsSection = <div>No users have specific privileges in this room.</div>;
|
||||
}
|
||||
|
||||
var banned = this.props.room.getMembersWithMembership("ban");
|
||||
@@ -635,7 +635,7 @@ module.exports = React.createClass({
|
||||
</label>);
|
||||
})) : (self.state.tags && self.state.tags.join) ? self.state.tags.join(", ") : ""
|
||||
}
|
||||
</div>
|
||||
</div>;
|
||||
}
|
||||
|
||||
// If there is no history_visibility, it is assumed to be 'shared'.
|
||||
@@ -653,7 +653,7 @@ module.exports = React.createClass({
|
||||
addressWarning =
|
||||
<div className="mx_RoomSettings_warning">
|
||||
To link to a room it must have <a href="#addresses">an address</a>.
|
||||
</div>
|
||||
</div>;
|
||||
}
|
||||
|
||||
var inviteGuestWarning;
|
||||
@@ -664,7 +664,7 @@ module.exports = React.createClass({
|
||||
this.setState({ join_rule: "invite", guest_access: "can_join" });
|
||||
e.preventDefault();
|
||||
}}>Click here to fix</a>.
|
||||
</div>
|
||||
</div>;
|
||||
}
|
||||
|
||||
var integrationsButton;
|
||||
|
||||
@@ -26,6 +26,7 @@ var sdk = require('../../../index');
|
||||
var ContextualMenu = require('../../structures/ContextualMenu');
|
||||
var RoomNotifs = require('../../../RoomNotifs');
|
||||
var FormattingUtils = require('../../../utils/FormattingUtils');
|
||||
var UserSettingsStore = require('../../../UserSettingsStore');
|
||||
|
||||
module.exports = React.createClass({
|
||||
displayName: 'RoomTile',
|
||||
@@ -176,7 +177,8 @@ module.exports = React.createClass({
|
||||
var self = this;
|
||||
ContextualMenu.createMenu(RoomTagMenu, {
|
||||
chevronOffset: 10,
|
||||
menuColour: "#FFFFFF",
|
||||
// XXX: fix horrid hardcoding
|
||||
menuColour: UserSettingsStore.getSyncedSettings().theme === 'dark' ? "#2d2d2d" : "#FFFFFF",
|
||||
left: x,
|
||||
top: y,
|
||||
room: this.props.room,
|
||||
@@ -219,7 +221,7 @@ module.exports = React.createClass({
|
||||
var avatarContainerClasses = classNames({
|
||||
'mx_RoomTile_avatar_container': true,
|
||||
'mx_RoomTile_avatar_roomTagMenu': this.state.roomTagMenu,
|
||||
})
|
||||
});
|
||||
|
||||
var badgeClasses = classNames({
|
||||
'mx_RoomTile_badge': true,
|
||||
|
||||
@@ -118,7 +118,7 @@ var SearchableEntityList = React.createClass({
|
||||
_createOverflowEntity: function(overflowCount, totalCount) {
|
||||
var EntityTile = sdk.getComponent("rooms.EntityTile");
|
||||
var BaseAvatar = sdk.getComponent("avatars.BaseAvatar");
|
||||
var text = "and " + overflowCount + " other" + (overflowCount > 1 ? "s" : "") + "...";
|
||||
var text = "and " + overflowCount + " other" + (overflowCount > 1 ? "s" : "") + "...";
|
||||
return (
|
||||
<EntityTile className="mx_EntityTile_ellipsis" avatarJsx={
|
||||
<BaseAvatar url="img/ellipsis.svg" name="..." width={36} height={36} />
|
||||
@@ -135,8 +135,8 @@ var SearchableEntityList = React.createClass({
|
||||
<form onSubmit={this.onQuerySubmit} autoComplete="off">
|
||||
<input className="mx_SearchableEntityList_query" id="mx_SearchableEntityList_query" type="text"
|
||||
onChange={this.onQueryChanged} value={this.state.query}
|
||||
onFocus= {() => { this.setState({ focused: true }) }}
|
||||
onBlur= {() => { this.setState({ focused: false }) }}
|
||||
onFocus= {() => { this.setState({ focused: true }); }}
|
||||
onBlur= {() => { this.setState({ focused: false }); }}
|
||||
placeholder={this.props.searchPlaceholderText} />
|
||||
</form>
|
||||
);
|
||||
|
||||
@@ -44,7 +44,7 @@ module.exports = React.createClass({
|
||||
|
||||
var cancelButton;
|
||||
if (this.props.onCancelClick) {
|
||||
cancelButton = <div className="mx_RoomHeader_cancelButton" onClick={this.props.onCancelClick}><img src="img/cancel.svg" width="18" height="18" alt="Cancel"/> </div>
|
||||
cancelButton = <div className="mx_RoomHeader_cancelButton" onClick={this.props.onCancelClick}><img src="img/cancel.svg" width="18" height="18" alt="Cancel"/> </div>;
|
||||
}
|
||||
|
||||
var showRhsButton;
|
||||
|
||||
@@ -38,7 +38,7 @@ module.exports = React.createClass({
|
||||
var active = -1;
|
||||
|
||||
// FIXME: make presence data update whenever User.presence changes...
|
||||
active = user.lastActiveAgo ?
|
||||
active = user.lastActiveAgo ?
|
||||
(Date.now() - (user.lastPresenceTs - user.lastActiveAgo)) : -1;
|
||||
|
||||
var BaseAvatar = sdk.getComponent('avatars.BaseAvatar');
|
||||
|
||||
@@ -49,7 +49,7 @@ module.exports = React.createClass({
|
||||
return {
|
||||
avatarUrl: this.props.initialAvatarUrl,
|
||||
phase: this.Phases.Display,
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
componentWillReceiveProps: function(newProps) {
|
||||
@@ -120,7 +120,7 @@ module.exports = React.createClass({
|
||||
var BaseAvatar = sdk.getComponent("avatars.BaseAvatar");
|
||||
// XXX: FIXME: once we track in the JS what our own displayname is(!) then use it here rather than ?
|
||||
avatarImg = <BaseAvatar width={this.props.width} height={this.props.height} resizeMethod='crop'
|
||||
name='?' idName={ MatrixClientPeg.get().getUserIdLocalpart() } url={this.state.avatarUrl} />
|
||||
name='?' idName={ MatrixClientPeg.get().getUserIdLocalpart() } url={this.state.avatarUrl} />;
|
||||
}
|
||||
|
||||
var uploadSection;
|
||||
@@ -130,7 +130,7 @@ module.exports = React.createClass({
|
||||
Upload new:
|
||||
<input type="file" onChange={this.onFileSelected}/>
|
||||
{this.state.errorText}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -59,7 +59,7 @@ module.exports = React.createClass({
|
||||
getInitialState: function() {
|
||||
return {
|
||||
phase: this.Phases.Edit
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
changePassword: function(old_password, new_password) {
|
||||
@@ -105,7 +105,7 @@ module.exports = React.createClass({
|
||||
render: function() {
|
||||
var rowClassName = this.props.rowClassName;
|
||||
var rowLabelClassName = this.props.rowLabelClassName;
|
||||
var rowInputClassName = this.props.rowInputClassName
|
||||
var rowInputClassName = this.props.rowInputClassName;
|
||||
var buttonClassName = this.props.buttonClassName;
|
||||
|
||||
switch (this.state.phase) {
|
||||
|
||||
@@ -88,7 +88,7 @@ export default class DevicesPanel extends React.Component {
|
||||
const removed_id = device.device_id;
|
||||
this.setState((state, props) => {
|
||||
const newDevices = state.devices.filter(
|
||||
d => { return d.device_id != removed_id }
|
||||
d => { return d.device_id != removed_id; }
|
||||
);
|
||||
return { devices: newDevices };
|
||||
});
|
||||
@@ -98,7 +98,7 @@ export default class DevicesPanel extends React.Component {
|
||||
var DevicesPanelEntry = sdk.getComponent('settings.DevicesPanelEntry');
|
||||
return (
|
||||
<DevicesPanelEntry key={device.device_id} device={device}
|
||||
onDeleted={()=>{this._onDeviceDeleted(device)}} />
|
||||
onDeleted={()=>{this._onDeviceDeleted(device);}} />
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -15,12 +15,9 @@ limitations under the License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import classNames from 'classnames';
|
||||
import q from 'q';
|
||||
|
||||
import sdk from '../../../index';
|
||||
import MatrixClientPeg from '../../../MatrixClientPeg';
|
||||
import DateUtils from '../../../DateUtils';
|
||||
import Modal from '../../../Modal';
|
||||
|
||||
export default class DevicesPanelEntry extends React.Component {
|
||||
@@ -61,7 +58,7 @@ export default class DevicesPanelEntry extends React.Component {
|
||||
if (this._unmounted) { return; }
|
||||
if (error.httpStatus !== 401 || !error.data || !error.data.flows) {
|
||||
// doesn't look like an interactive-auth failure
|
||||
throw e;
|
||||
throw error;
|
||||
}
|
||||
|
||||
// pop up an interactive auth dialog
|
||||
@@ -121,7 +118,7 @@ export default class DevicesPanelEntry extends React.Component {
|
||||
|
||||
let deleteButton;
|
||||
if (this.state.deleteError) {
|
||||
deleteButton = <div className="error">{this.state.deleteError}</div>
|
||||
deleteButton = <div className="error">{this.state.deleteError}</div>;
|
||||
} else {
|
||||
deleteButton = (
|
||||
<div className="mx_textButton"
|
||||
|
||||
@@ -17,7 +17,6 @@ limitations under the License.
|
||||
'use strict';
|
||||
var React = require("react");
|
||||
var Notifier = require("../../../Notifier");
|
||||
var sdk = require('../../../index');
|
||||
var dis = require("../../../dispatcher");
|
||||
|
||||
module.exports = React.createClass({
|
||||
|
||||
@@ -124,7 +124,7 @@ module.exports = React.createClass({
|
||||
return this.refs.video;
|
||||
},
|
||||
|
||||
render: function(){
|
||||
render: function() {
|
||||
var VideoView = sdk.getComponent('voip.VideoView');
|
||||
|
||||
var voice;
|
||||
|
||||
@@ -114,7 +114,7 @@ module.exports = React.createClass({
|
||||
<VideoFeed ref="remote" onResize={this.props.onResize}
|
||||
maxHeight={maxVideoHeight} />
|
||||
</div>
|
||||
<div className="mx_VideoView_localVideoFeed">
|
||||
<div className="mx_VideoView_localVideoFeed">
|
||||
<VideoFeed ref="local"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user