Merge branch 'develop' into t3chguy/jump_to_rr
This commit is contained in:
commit
e57d9e686b
177 changed files with 4458 additions and 3386 deletions
|
@ -32,7 +32,7 @@ module.exports = React.createClass({
|
|||
height: React.PropTypes.number,
|
||||
// XXX resizeMethod not actually used.
|
||||
resizeMethod: React.PropTypes.string,
|
||||
defaultToInitialLetter: React.PropTypes.bool // true to add default url
|
||||
defaultToInitialLetter: React.PropTypes.bool, // true to add default url
|
||||
},
|
||||
|
||||
getDefaultProps: function() {
|
||||
|
@ -40,7 +40,7 @@ module.exports = React.createClass({
|
|||
width: 40,
|
||||
height: 40,
|
||||
resizeMethod: 'crop',
|
||||
defaultToInitialLetter: true
|
||||
defaultToInitialLetter: true,
|
||||
};
|
||||
},
|
||||
|
||||
|
@ -50,15 +50,14 @@ module.exports = React.createClass({
|
|||
|
||||
componentWillReceiveProps: function(nextProps) {
|
||||
// work out if we need to call setState (if the image URLs array has changed)
|
||||
var newState = this._getState(nextProps);
|
||||
var newImageUrls = newState.imageUrls;
|
||||
var oldImageUrls = this.state.imageUrls;
|
||||
const newState = this._getState(nextProps);
|
||||
const newImageUrls = newState.imageUrls;
|
||||
const oldImageUrls = this.state.imageUrls;
|
||||
if (newImageUrls.length !== oldImageUrls.length) {
|
||||
this.setState(newState); // detected a new entry
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
// check each one to see if they are the same
|
||||
for (var i = 0; i < newImageUrls.length; i++) {
|
||||
for (let i = 0; i < newImageUrls.length; i++) {
|
||||
if (oldImageUrls[i] !== newImageUrls[i]) {
|
||||
this.setState(newState); // detected a diff
|
||||
break;
|
||||
|
@ -71,31 +70,31 @@ module.exports = React.createClass({
|
|||
// work out the full set of urls to try to load. This is formed like so:
|
||||
// imageUrls: [ props.url, props.urls, default image ]
|
||||
|
||||
var urls = props.urls || [];
|
||||
const urls = props.urls || [];
|
||||
if (props.url) {
|
||||
urls.unshift(props.url); // put in urls[0]
|
||||
}
|
||||
|
||||
var defaultImageUrl = null;
|
||||
let defaultImageUrl = null;
|
||||
if (props.defaultToInitialLetter) {
|
||||
defaultImageUrl = AvatarLogic.defaultAvatarUrlForString(
|
||||
props.idName || props.name
|
||||
props.idName || props.name,
|
||||
);
|
||||
urls.push(defaultImageUrl); // lowest priority
|
||||
}
|
||||
return {
|
||||
imageUrls: urls,
|
||||
defaultImageUrl: defaultImageUrl,
|
||||
urlsIndex: 0
|
||||
urlsIndex: 0,
|
||||
};
|
||||
},
|
||||
|
||||
onError: function(ev) {
|
||||
var nextIndex = this.state.urlsIndex + 1;
|
||||
const nextIndex = this.state.urlsIndex + 1;
|
||||
if (nextIndex < this.state.imageUrls.length) {
|
||||
// try the next one
|
||||
this.setState({
|
||||
urlsIndex: nextIndex
|
||||
urlsIndex: nextIndex,
|
||||
});
|
||||
}
|
||||
},
|
||||
|
@ -109,32 +108,32 @@ module.exports = React.createClass({
|
|||
return undefined;
|
||||
}
|
||||
|
||||
var idx = 0;
|
||||
var initial = name[0];
|
||||
let idx = 0;
|
||||
const initial = name[0];
|
||||
if ((initial === '@' || initial === '#') && name[1]) {
|
||||
idx++;
|
||||
}
|
||||
|
||||
// string.codePointAt(0) would do this, but that isn't supported by
|
||||
// some browsers (notably PhantomJS).
|
||||
var chars = 1;
|
||||
var first = name.charCodeAt(idx);
|
||||
let chars = 1;
|
||||
const first = name.charCodeAt(idx);
|
||||
|
||||
// check if it’s the start of a surrogate pair
|
||||
if (first >= 0xD800 && first <= 0xDBFF && name[idx+1]) {
|
||||
var second = name.charCodeAt(idx+1);
|
||||
const second = name.charCodeAt(idx+1);
|
||||
if (second >= 0xDC00 && second <= 0xDFFF) {
|
||||
chars++;
|
||||
}
|
||||
}
|
||||
|
||||
var firstChar = name.substring(idx, idx+chars);
|
||||
const firstChar = name.substring(idx, idx+chars);
|
||||
return firstChar.toUpperCase();
|
||||
},
|
||||
|
||||
render: function() {
|
||||
const EmojiText = sdk.getComponent('elements.EmojiText');
|
||||
var imageUrl = this.state.imageUrls[this.state.urlsIndex];
|
||||
const imageUrl = this.state.imageUrls[this.state.urlsIndex];
|
||||
|
||||
const {
|
||||
name, idName, title, url, urls, width, height, resizeMethod,
|
||||
|
@ -150,7 +149,7 @@ module.exports = React.createClass({
|
|||
width: width + "px",
|
||||
lineHeight: height + "px" }}
|
||||
>
|
||||
{initialLetter}
|
||||
{ initialLetter }
|
||||
</EmojiText>
|
||||
);
|
||||
const imgNode = (
|
||||
|
@ -163,15 +162,15 @@ module.exports = React.createClass({
|
|||
<AccessibleButton element='span' className="mx_BaseAvatar"
|
||||
onClick={onClick} {...otherProps}
|
||||
>
|
||||
{textNode}
|
||||
{imgNode}
|
||||
{ textNode }
|
||||
{ imgNode }
|
||||
</AccessibleButton>
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<span className="mx_BaseAvatar" {...otherProps}>
|
||||
{textNode}
|
||||
{imgNode}
|
||||
{ textNode }
|
||||
{ imgNode }
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
@ -196,5 +195,5 @@ module.exports = React.createClass({
|
|||
{...otherProps} />
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
|
|
|
@ -16,9 +16,9 @@ limitations under the License.
|
|||
|
||||
'use strict';
|
||||
|
||||
var React = require('react');
|
||||
var Avatar = require('../../../Avatar');
|
||||
var sdk = require("../../../index");
|
||||
const React = require('react');
|
||||
const Avatar = require('../../../Avatar');
|
||||
const sdk = require("../../../index");
|
||||
const dispatcher = require("../../../dispatcher");
|
||||
|
||||
module.exports = React.createClass({
|
||||
|
@ -63,14 +63,14 @@ module.exports = React.createClass({
|
|||
imageUrl: Avatar.avatarUrlForMember(props.member,
|
||||
props.width,
|
||||
props.height,
|
||||
props.resizeMethod)
|
||||
props.resizeMethod),
|
||||
};
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var BaseAvatar = sdk.getComponent("avatars.BaseAvatar");
|
||||
const BaseAvatar = sdk.getComponent("avatars.BaseAvatar");
|
||||
|
||||
var {member, onClick, viewUserOnClick, ...otherProps} = this.props;
|
||||
let {member, onClick, viewUserOnClick, ...otherProps} = this.props;
|
||||
|
||||
if (viewUserOnClick) {
|
||||
onClick = () => {
|
||||
|
@ -83,7 +83,7 @@ module.exports = React.createClass({
|
|||
|
||||
return (
|
||||
<BaseAvatar {...otherProps} name={this.state.name} title={this.state.title}
|
||||
idName={member.userId} url={this.state.imageUrl} onClick={onClick}/>
|
||||
idName={member.userId} url={this.state.imageUrl} onClick={onClick} />
|
||||
);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
|
|
@ -36,7 +36,7 @@ module.exports = React.createClass({
|
|||
|
||||
render: function() {
|
||||
return (
|
||||
<button className="mx_CreateRoomButton" onClick={this.onClick}>{_t("Create Room")}</button>
|
||||
<button className="mx_CreateRoomButton" onClick={this.onClick}>{ _t("Create Room") }</button>
|
||||
);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
|
|
@ -16,10 +16,10 @@ limitations under the License.
|
|||
|
||||
'use strict';
|
||||
|
||||
var React = require('react');
|
||||
const React = require('react');
|
||||
import { _t } from '../../../languageHandler';
|
||||
|
||||
var Presets = {
|
||||
const Presets = {
|
||||
PrivateChat: "private_chat",
|
||||
PublicChat: "public_chat",
|
||||
Custom: "custom",
|
||||
|
@ -29,7 +29,7 @@ module.exports = React.createClass({
|
|||
displayName: 'CreateRoomPresets',
|
||||
propTypes: {
|
||||
onChange: React.PropTypes.func,
|
||||
preset: React.PropTypes.string
|
||||
preset: React.PropTypes.string,
|
||||
},
|
||||
|
||||
Presets: Presets,
|
||||
|
@ -47,10 +47,10 @@ module.exports = React.createClass({
|
|||
render: function() {
|
||||
return (
|
||||
<select className="mx_Presets" onChange={this.onValueChanged} value={this.props.preset}>
|
||||
<option value={this.Presets.PrivateChat}>{_t("Private Chat")}</option>
|
||||
<option value={this.Presets.PublicChat}>{_t("Public Chat")}</option>
|
||||
<option value={this.Presets.Custom}>{_t("Custom")}</option>
|
||||
<option value={this.Presets.PrivateChat}>{ _t("Private Chat") }</option>
|
||||
<option value={this.Presets.PublicChat}>{ _t("Public Chat") }</option>
|
||||
<option value={this.Presets.Custom}>{ _t("Custom") }</option>
|
||||
</select>
|
||||
);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
|
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
var React = require('react');
|
||||
const React = require('react');
|
||||
import { _t } from '../../../languageHandler';
|
||||
|
||||
module.exports = React.createClass({
|
||||
|
@ -35,10 +35,10 @@ module.exports = React.createClass({
|
|||
},
|
||||
|
||||
getAliasLocalpart: function() {
|
||||
var room_alias = this.props.alias;
|
||||
let room_alias = this.props.alias;
|
||||
|
||||
if (room_alias && this.props.homeserver) {
|
||||
var suffix = ":" + this.props.homeserver;
|
||||
const suffix = ":" + this.props.homeserver;
|
||||
if (room_alias.startsWith("#") && room_alias.endsWith(suffix)) {
|
||||
room_alias = room_alias.slice(1, -suffix.length);
|
||||
}
|
||||
|
@ -52,22 +52,22 @@ module.exports = React.createClass({
|
|||
},
|
||||
|
||||
onFocus: function(ev) {
|
||||
var target = ev.target;
|
||||
var curr_val = ev.target.value;
|
||||
const target = ev.target;
|
||||
const curr_val = ev.target.value;
|
||||
|
||||
if (this.props.homeserver) {
|
||||
if (curr_val == "") {
|
||||
var self = this;
|
||||
const self = this;
|
||||
setTimeout(function() {
|
||||
target.value = "#:" + self.props.homeserver;
|
||||
target.setSelectionRange(1, 1);
|
||||
}, 0);
|
||||
} else {
|
||||
var suffix = ":" + this.props.homeserver;
|
||||
const suffix = ":" + this.props.homeserver;
|
||||
setTimeout(function() {
|
||||
target.setSelectionRange(
|
||||
curr_val.startsWith("#") ? 1 : 0,
|
||||
curr_val.endsWith(suffix) ? (target.value.length - suffix.length) : target.value.length
|
||||
curr_val.endsWith(suffix) ? (target.value.length - suffix.length) : target.value.length,
|
||||
);
|
||||
}, 0);
|
||||
}
|
||||
|
@ -75,7 +75,7 @@ module.exports = React.createClass({
|
|||
},
|
||||
|
||||
onBlur: function(ev) {
|
||||
var curr_val = ev.target.value;
|
||||
const curr_val = ev.target.value;
|
||||
|
||||
if (this.props.homeserver) {
|
||||
if (curr_val == "#:" + this.props.homeserver) {
|
||||
|
@ -84,8 +84,8 @@ module.exports = React.createClass({
|
|||
}
|
||||
|
||||
if (curr_val != "") {
|
||||
var new_val = ev.target.value;
|
||||
var suffix = ":" + this.props.homeserver;
|
||||
let new_val = ev.target.value;
|
||||
const suffix = ":" + this.props.homeserver;
|
||||
if (!curr_val.startsWith("#")) new_val = "#" + new_val;
|
||||
if (!curr_val.endsWith(suffix)) new_val = new_val + suffix;
|
||||
ev.target.value = new_val;
|
||||
|
@ -97,7 +97,7 @@ module.exports = React.createClass({
|
|||
return (
|
||||
<input type="text" className="mx_RoomAlias" placeholder={_t("Alias (optional)")}
|
||||
onChange={this.onValueChanged} onFocus={this.onFocus} onBlur={this.onBlur}
|
||||
value={this.props.alias}/>
|
||||
value={this.props.alias} />
|
||||
);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
|
|
@ -23,6 +23,7 @@ import MatrixClientPeg from '../../../MatrixClientPeg';
|
|||
import AccessibleButton from '../elements/AccessibleButton';
|
||||
import Promise from 'bluebird';
|
||||
import { addressTypes, getAddressType } from '../../../UserAddress.js';
|
||||
import GroupStoreCache from '../../../stores/GroupStoreCache';
|
||||
|
||||
const TRUNCATE_QUERY_LIST = 40;
|
||||
const QUERY_USER_DIRECTORY_DEBOUNCE_MS = 200;
|
||||
|
@ -241,32 +242,25 @@ module.exports = React.createClass({
|
|||
|
||||
_doNaiveGroupRoomSearch: function(query) {
|
||||
const lowerCaseQuery = query.toLowerCase();
|
||||
MatrixClientPeg.get().getGroupRooms(this.props.groupId).then((resp) => {
|
||||
const results = [];
|
||||
resp.chunk.forEach((r) => {
|
||||
const nameMatch = (r.name || '').toLowerCase().includes(lowerCaseQuery);
|
||||
const topicMatch = (r.topic || '').toLowerCase().includes(lowerCaseQuery);
|
||||
const aliasMatch = (r.canonical_alias || '').toLowerCase().includes(lowerCaseQuery);
|
||||
if (!(nameMatch || topicMatch || aliasMatch)) {
|
||||
return;
|
||||
}
|
||||
results.push({
|
||||
room_id: r.room_id,
|
||||
avatar_url: r.avatar_url,
|
||||
name: r.name || r.canonical_alias,
|
||||
});
|
||||
});
|
||||
this._processResults(results, query);
|
||||
}).catch((err) => {
|
||||
console.error('Error whilst searching group users: ', err);
|
||||
this.setState({
|
||||
searchError: err.errcode ? err.message : _t('Something went wrong!'),
|
||||
});
|
||||
}).done(() => {
|
||||
this.setState({
|
||||
busy: false,
|
||||
const groupStore = GroupStoreCache.getGroupStore(MatrixClientPeg.get(), this.props.groupId);
|
||||
const results = [];
|
||||
groupStore.getGroupRooms().forEach((r) => {
|
||||
const nameMatch = (r.name || '').toLowerCase().includes(lowerCaseQuery);
|
||||
const topicMatch = (r.topic || '').toLowerCase().includes(lowerCaseQuery);
|
||||
const aliasMatch = (r.canonical_alias || '').toLowerCase().includes(lowerCaseQuery);
|
||||
if (!(nameMatch || topicMatch || aliasMatch)) {
|
||||
return;
|
||||
}
|
||||
results.push({
|
||||
room_id: r.room_id,
|
||||
avatar_url: r.avatar_url,
|
||||
name: r.name || r.canonical_alias,
|
||||
});
|
||||
});
|
||||
this._processResults(results, query);
|
||||
this.setState({
|
||||
busy: false,
|
||||
});
|
||||
},
|
||||
|
||||
_doRoomSearch: function(query) {
|
||||
|
|
|
@ -155,7 +155,7 @@ export default class ChatCreateOrReuseDialog extends React.Component {
|
|||
width={48} height={48}
|
||||
/>
|
||||
<div className="mx_ChatCreateOrReuseDialog_profile_name">
|
||||
{this.state.profile.displayName || this.props.userId}
|
||||
{ this.state.profile.displayName || this.props.userId }
|
||||
</div>
|
||||
</div>;
|
||||
}
|
||||
|
@ -177,7 +177,7 @@ export default class ChatCreateOrReuseDialog extends React.Component {
|
|||
const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
|
||||
return (
|
||||
<BaseDialog className='mx_ChatCreateOrReuseDialog'
|
||||
onFinished={ this.props.onFinished.bind(false) }
|
||||
onFinished={this.props.onFinished.bind(false)}
|
||||
title={title}
|
||||
>
|
||||
{ content }
|
||||
|
|
81
src/components/views/dialogs/CreateRoomDialog.js
Normal file
81
src/components/views/dialogs/CreateRoomDialog.js
Normal file
|
@ -0,0 +1,81 @@
|
|||
/*
|
||||
Copyright 2017 Michael Telatynski <7t3chguy@gmail.com>
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import sdk from '../../../index';
|
||||
import SdkConfig from '../../../SdkConfig';
|
||||
import { _t } from '../../../languageHandler';
|
||||
|
||||
export default React.createClass({
|
||||
displayName: 'CreateRoomDialog',
|
||||
propTypes: {
|
||||
onFinished: React.PropTypes.func.isRequired,
|
||||
},
|
||||
|
||||
componentDidMount: function() {
|
||||
const config = SdkConfig.get();
|
||||
// Dialog shows inverse of m.federate (noFederate) strict false check to skip undefined check (default = true)
|
||||
this.defaultNoFederate = config.default_federate === false;
|
||||
},
|
||||
|
||||
onOk: function() {
|
||||
this.props.onFinished(true, this.refs.textinput.value, this.refs.checkbox.checked);
|
||||
},
|
||||
|
||||
onCancel: function() {
|
||||
this.props.onFinished(false);
|
||||
},
|
||||
|
||||
render: function() {
|
||||
const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
|
||||
return (
|
||||
<BaseDialog className="mx_CreateRoomDialog" onFinished={this.props.onFinished}
|
||||
onEnterPressed={this.onOk}
|
||||
title={_t('Create Room')}
|
||||
>
|
||||
<div className="mx_Dialog_content">
|
||||
<div className="mx_CreateRoomDialog_label">
|
||||
<label htmlFor="textinput"> { _t('Room name (optional)') } </label>
|
||||
</div>
|
||||
<div>
|
||||
<input id="textinput" ref="textinput" className="mx_CreateRoomDialog_input" autoFocus={true} size="64" />
|
||||
</div>
|
||||
<br />
|
||||
|
||||
<details className="mx_CreateRoomDialog_details">
|
||||
<summary className="mx_CreateRoomDialog_details_summary">{ _t('Advanced options') }</summary>
|
||||
<div>
|
||||
<input type="checkbox" id="checkbox" ref="checkbox" defaultChecked={this.defaultNoFederate} />
|
||||
<label htmlFor="checkbox">
|
||||
{ _t('Block users on other matrix homeservers from joining this room') }
|
||||
<br />
|
||||
({ _t('This setting cannot be changed later!') })
|
||||
</label>
|
||||
</div>
|
||||
</details>
|
||||
</div>
|
||||
<div className="mx_Dialog_buttons">
|
||||
<button onClick={this.onCancel}>
|
||||
{ _t('Cancel') }
|
||||
</button>
|
||||
<button className="mx_Dialog_primary" onClick={this.onOk}>
|
||||
{ _t('Create Room') }
|
||||
</button>
|
||||
</div>
|
||||
</BaseDialog>
|
||||
);
|
||||
},
|
||||
});
|
|
@ -83,7 +83,7 @@ export default class DeactivateAccountDialog extends React.Component {
|
|||
let error = null;
|
||||
if (this.state.errStr) {
|
||||
error = <div className="error">
|
||||
{this.state.errStr}
|
||||
{ this.state.errStr }
|
||||
</div>;
|
||||
passwordBoxClass = 'error';
|
||||
}
|
||||
|
@ -94,30 +94,30 @@ export default class DeactivateAccountDialog extends React.Component {
|
|||
let cancelButton = null;
|
||||
if (!this.state.busy) {
|
||||
cancelButton = <button onClick={this._onCancel} autoFocus={true}>
|
||||
{_t("Cancel")}
|
||||
{ _t("Cancel") }
|
||||
</button>;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="mx_DeactivateAccountDialog">
|
||||
<div className="mx_Dialog_title danger">
|
||||
{_t("Deactivate Account")}
|
||||
{ _t("Deactivate Account") }
|
||||
</div>
|
||||
<div className="mx_Dialog_content">
|
||||
<p>{_t("This will make your account permanently unusable. You will not be able to re-register the same user ID.")}</p>
|
||||
<p>{ _t("This will make your account permanently unusable. You will not be able to re-register the same user ID.") }</p>
|
||||
|
||||
<p>{_t("This action is irreversible.")}</p>
|
||||
<p>{ _t("This action is irreversible.") }</p>
|
||||
|
||||
<p>{_t("To continue, please enter your password.")}</p>
|
||||
<p>{ _t("To continue, please enter your password.") }</p>
|
||||
|
||||
<p>{_t("Password")}:</p>
|
||||
<p>{ _t("Password") }:</p>
|
||||
<input
|
||||
type="password"
|
||||
onChange={this._onPasswordFieldChange}
|
||||
ref={(e) => {this._passwordField = e;}}
|
||||
className={passwordBoxClass}
|
||||
/>
|
||||
{error}
|
||||
{ error }
|
||||
</div>
|
||||
<div className="mx_Dialog_buttons">
|
||||
<button
|
||||
|
@ -125,10 +125,10 @@ export default class DeactivateAccountDialog extends React.Component {
|
|||
onClick={this._onOk}
|
||||
disabled={!okEnabled}
|
||||
>
|
||||
{okLabel}
|
||||
{ okLabel }
|
||||
</button>
|
||||
|
||||
{cancelButton}
|
||||
{ cancelButton }
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -48,7 +48,7 @@ export default React.createClass({
|
|||
getInitialState: function() {
|
||||
return {
|
||||
authError: null,
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
_onAuthFinished: function(success, result) {
|
||||
|
@ -73,12 +73,12 @@ export default React.createClass({
|
|||
if (this.state.authError) {
|
||||
content = (
|
||||
<div>
|
||||
<div>{this.state.authError.message || this.state.authError.toString()}</div>
|
||||
<div>{ this.state.authError.message || this.state.authError.toString() }</div>
|
||||
<br />
|
||||
<AccessibleButton onClick={this._onDismissClick}
|
||||
className="mx_UserSettings_button"
|
||||
>
|
||||
{_t("Dismiss")}
|
||||
{ _t("Dismiss") }
|
||||
</AccessibleButton>
|
||||
</div>
|
||||
);
|
||||
|
@ -100,7 +100,7 @@ export default React.createClass({
|
|||
onFinished={this.props.onFinished}
|
||||
title={this.state.authError ? 'Error' : (this.props.title || _t('Authentication'))}
|
||||
>
|
||||
{content}
|
||||
{ content }
|
||||
</BaseDialog>
|
||||
);
|
||||
},
|
||||
|
|
|
@ -68,7 +68,7 @@ export default React.createClass({
|
|||
<label htmlFor="textinput"> { this.props.description } </label>
|
||||
</div>
|
||||
<div>
|
||||
<input id="textinput" ref="textinput" className="mx_TextInputDialog_input" defaultValue={this.props.value} autoFocus={this.props.focus} size="64" onKeyDown={this.onKeyDown} />
|
||||
<input id="textinput" ref="textinput" className="mx_TextInputDialog_input" defaultValue={this.props.value} autoFocus={this.props.focus} size="64" />
|
||||
</div>
|
||||
</div>
|
||||
<div className="mx_Dialog_buttons">
|
||||
|
|
|
@ -28,9 +28,9 @@ function DeviceListEntry(props) {
|
|||
|
||||
return (
|
||||
<li>
|
||||
<DeviceVerifyButtons device={ device } userId={ userId } />
|
||||
<DeviceVerifyButtons device={device} userId={userId} />
|
||||
{ device.deviceId }
|
||||
<br/>
|
||||
<br />
|
||||
{ device.getDisplayName() }
|
||||
</li>
|
||||
);
|
||||
|
@ -48,13 +48,13 @@ function UserUnknownDeviceList(props) {
|
|||
const {userId, userDevices} = props;
|
||||
|
||||
const deviceListEntries = Object.keys(userDevices).map((deviceId) =>
|
||||
<DeviceListEntry key={ deviceId } userId={ userId }
|
||||
device={ userDevices[deviceId] } />,
|
||||
<DeviceListEntry key={deviceId} userId={userId}
|
||||
device={userDevices[deviceId]} />,
|
||||
);
|
||||
|
||||
return (
|
||||
<ul className="mx_UnknownDeviceDialog_deviceList">
|
||||
{deviceListEntries}
|
||||
{ deviceListEntries }
|
||||
</ul>
|
||||
);
|
||||
}
|
||||
|
@ -71,13 +71,13 @@ function UnknownDeviceList(props) {
|
|||
const {devices} = props;
|
||||
|
||||
const userListEntries = Object.keys(devices).map((userId) =>
|
||||
<li key={ userId }>
|
||||
<li key={userId}>
|
||||
<p>{ userId }:</p>
|
||||
<UserUnknownDeviceList userId={ userId } userDevices={ devices[userId] } />
|
||||
<UserUnknownDeviceList userId={userId} userDevices={devices[userId]} />
|
||||
</li>,
|
||||
);
|
||||
|
||||
return <ul>{userListEntries}</ul>;
|
||||
return <ul>{ userListEntries }</ul>;
|
||||
}
|
||||
|
||||
UnknownDeviceList.propTypes = {
|
||||
|
@ -120,17 +120,17 @@ export default React.createClass({
|
|||
if (blacklistUnverified) {
|
||||
warning = (
|
||||
<h4>
|
||||
{_t("You are currently blacklisting unverified devices; to send " +
|
||||
"messages to these devices you must verify them.")}
|
||||
{ _t("You are currently blacklisting unverified devices; to send " +
|
||||
"messages to these devices you must verify them.") }
|
||||
</h4>
|
||||
);
|
||||
} else {
|
||||
warning = (
|
||||
<div>
|
||||
<p>
|
||||
{_t("We recommend you go through the verification process " +
|
||||
{ _t("We recommend you go through the verification process " +
|
||||
"for each device to confirm they belong to their legitimate owner, " +
|
||||
"but you can resend the message without verifying if you prefer.")}
|
||||
"but you can resend the message without verifying if you prefer.") }
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
|
@ -149,22 +149,22 @@ export default React.createClass({
|
|||
>
|
||||
<GeminiScrollbar autoshow={false} className="mx_Dialog_content">
|
||||
<h4>
|
||||
{_t('"%(RoomName)s" contains devices that you haven\'t seen before.', {RoomName: this.props.room.name})}
|
||||
{ _t('"%(RoomName)s" contains devices that you haven\'t seen before.', {RoomName: this.props.room.name}) }
|
||||
</h4>
|
||||
{ warning }
|
||||
{_t("Unknown devices")}:
|
||||
{ _t("Unknown devices") }:
|
||||
|
||||
<UnknownDeviceList devices={this.props.devices} />
|
||||
</GeminiScrollbar>
|
||||
<div className="mx_Dialog_buttons">
|
||||
<button className="mx_Dialog_primary" autoFocus={ true }
|
||||
<button className="mx_Dialog_primary" autoFocus={true}
|
||||
onClick={() => {
|
||||
this.props.onFinished();
|
||||
Resend.resendUnsentEvents(this.props.room);
|
||||
}}>
|
||||
{_t("Send anyway")}
|
||||
{ _t("Send anyway") }
|
||||
</button>
|
||||
<button className="mx_Dialog_primary" autoFocus={ true }
|
||||
<button className="mx_Dialog_primary" autoFocus={true}
|
||||
onClick={() => {
|
||||
// XXX: temporary logging to try to diagnose
|
||||
// https://github.com/vector-im/riot-web/issues/3148
|
||||
|
|
|
@ -32,7 +32,7 @@ export default function AccessibleButton(props) {
|
|||
};
|
||||
restProps.tabIndex = restProps.tabIndex || "0";
|
||||
restProps.role = "button";
|
||||
restProps.className = (restProps.className ? restProps.className + " " : "") +
|
||||
restProps.className = (restProps.className ? restProps.className + " " : "") +
|
||||
"mx_AccessibleButton";
|
||||
return React.createElement(element, restProps, children);
|
||||
}
|
||||
|
|
|
@ -79,8 +79,8 @@ export default React.createClass({
|
|||
onMouseLeave={this._onMouseLeave}
|
||||
>
|
||||
<TintableSvg src={this.props.iconPath} width={this.props.size} height={this.props.size} />
|
||||
{tooltip}
|
||||
{ tooltip }
|
||||
</AccessibleButton>
|
||||
);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
|
|
@ -46,8 +46,8 @@ export default React.createClass({
|
|||
|
||||
componentWillReceiveProps: function(props) {
|
||||
// Make sure the selected item isn't outside the list bounds
|
||||
var selected = this.state.selected;
|
||||
var maxSelected = this._maxSelected(props.addressList);
|
||||
const selected = this.state.selected;
|
||||
const maxSelected = this._maxSelected(props.addressList);
|
||||
if (selected > maxSelected) {
|
||||
this.setState({ selected: maxSelected });
|
||||
}
|
||||
|
@ -57,7 +57,7 @@ export default React.createClass({
|
|||
// As the user scrolls with the arrow keys keep the selected item
|
||||
// at the top of the window.
|
||||
if (this.scrollElement && this.props.addressList.length > 0 && !this.state.hover) {
|
||||
var elementHeight = this.addressListElement.getBoundingClientRect().height;
|
||||
const elementHeight = this.addressListElement.getBoundingClientRect().height;
|
||||
this.scrollElement.scrollTop = (this.state.selected * elementHeight) - elementHeight;
|
||||
}
|
||||
},
|
||||
|
@ -75,7 +75,7 @@ export default React.createClass({
|
|||
if (this.state.selected > 0) {
|
||||
this.setState({
|
||||
selected: this.state.selected - 1,
|
||||
hover : false,
|
||||
hover: false,
|
||||
});
|
||||
}
|
||||
},
|
||||
|
@ -84,7 +84,7 @@ export default React.createClass({
|
|||
if (this.state.selected < this._maxSelected(this.props.addressList)) {
|
||||
this.setState({
|
||||
selected: this.state.selected + 1,
|
||||
hover : false,
|
||||
hover: false,
|
||||
});
|
||||
}
|
||||
},
|
||||
|
@ -105,7 +105,7 @@ export default React.createClass({
|
|||
},
|
||||
|
||||
onMouseLeave: function() {
|
||||
this.setState({ hover : false });
|
||||
this.setState({ hover: false });
|
||||
},
|
||||
|
||||
selectAddress: function(index) {
|
||||
|
@ -117,15 +117,15 @@ export default React.createClass({
|
|||
},
|
||||
|
||||
createAddressListTiles: function() {
|
||||
var self = this;
|
||||
var AddressTile = sdk.getComponent("elements.AddressTile");
|
||||
var maxSelected = this._maxSelected(this.props.addressList);
|
||||
var addressList = [];
|
||||
const self = this;
|
||||
const AddressTile = sdk.getComponent("elements.AddressTile");
|
||||
const maxSelected = this._maxSelected(this.props.addressList);
|
||||
const addressList = [];
|
||||
|
||||
// Only create the address elements if there are address
|
||||
if (this.props.addressList.length > 0) {
|
||||
for (var i = 0; i <= maxSelected; i++) {
|
||||
var classes = classNames({
|
||||
for (let i = 0; i <= maxSelected; i++) {
|
||||
const classes = classNames({
|
||||
"mx_AddressSelector_addressListElement": true,
|
||||
"mx_AddressSelector_selected": this.state.selected === i,
|
||||
});
|
||||
|
@ -143,7 +143,7 @@ export default React.createClass({
|
|||
ref={(ref) => { this.addressListElement = ref; }}
|
||||
>
|
||||
<AddressTile address={this.props.addressList[i]} justified={true} networkName="vector" networkUrl="img/search-icon-vector.svg" />
|
||||
</div>
|
||||
</div>,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -151,13 +151,13 @@ export default 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;
|
||||
const listSize = list.length === 0 ? 0 : list.length - 1;
|
||||
const maxSelected = listSize > (this.props.truncateAt - 1) ? (this.props.truncateAt - 1) : listSize;
|
||||
return maxSelected;
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var classes = classNames({
|
||||
const classes = classNames({
|
||||
"mx_AddressSelector": true,
|
||||
"mx_AddressSelector_empty": this.props.addressList.length === 0,
|
||||
});
|
||||
|
@ -168,5 +168,5 @@ export default React.createClass({
|
|||
{ this.createAddressListTiles() }
|
||||
</div>
|
||||
);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
|
|
@ -107,24 +107,24 @@ export default React.createClass({
|
|||
|
||||
let nameNode = null;
|
||||
if (address.displayName) {
|
||||
nameNode = <div className={nameClasses}>{ address.displayName }</div>
|
||||
nameNode = <div className={nameClasses}>{ address.displayName }</div>;
|
||||
}
|
||||
|
||||
info = (
|
||||
<div className="mx_AddressTile_mx">
|
||||
<div className={emailClasses}>{ address.address }</div>
|
||||
{nameNode}
|
||||
{ nameNode }
|
||||
</div>
|
||||
);
|
||||
} else {
|
||||
error = true;
|
||||
var unknownClasses = classNames({
|
||||
const unknownClasses = classNames({
|
||||
"mx_AddressTile_unknown": true,
|
||||
"mx_AddressTile_justified": this.props.justified,
|
||||
});
|
||||
|
||||
info = (
|
||||
<div className={unknownClasses}>{_t("Unknown Address")}</div>
|
||||
<div className={unknownClasses}>{ _t("Unknown Address") }</div>
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -151,5 +151,5 @@ export default React.createClass({
|
|||
{ dismiss }
|
||||
</div>
|
||||
);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
|
|
@ -24,7 +24,7 @@ const CreateRoomButton = function(props) {
|
|||
return (
|
||||
<ActionButton action="view_create_room"
|
||||
mouseOverAction={props.callout ? "callout_create_room" : null}
|
||||
label={ _t("Create new room") }
|
||||
label={_t("Create new room")}
|
||||
iconPath="img/icons-create-room.svg"
|
||||
size={props.size}
|
||||
tooltip={props.tooltip}
|
||||
|
|
|
@ -30,7 +30,7 @@ export default React.createClass({
|
|||
|
||||
getInitialState: function() {
|
||||
return {
|
||||
device: this.props.device
|
||||
device: this.props.device,
|
||||
};
|
||||
},
|
||||
|
||||
|
@ -60,37 +60,37 @@ export default React.createClass({
|
|||
|
||||
onUnverifyClick: function() {
|
||||
MatrixClientPeg.get().setDeviceVerified(
|
||||
this.props.userId, this.state.device.deviceId, false
|
||||
this.props.userId, this.state.device.deviceId, false,
|
||||
);
|
||||
},
|
||||
|
||||
onBlacklistClick: function() {
|
||||
MatrixClientPeg.get().setDeviceBlocked(
|
||||
this.props.userId, this.state.device.deviceId, true
|
||||
this.props.userId, this.state.device.deviceId, true,
|
||||
);
|
||||
},
|
||||
|
||||
onUnblacklistClick: function() {
|
||||
MatrixClientPeg.get().setDeviceBlocked(
|
||||
this.props.userId, this.state.device.deviceId, false
|
||||
this.props.userId, this.state.device.deviceId, false,
|
||||
);
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var blacklistButton = null, verifyButton = null;
|
||||
let blacklistButton = null, verifyButton = null;
|
||||
|
||||
if (this.state.device.isBlocked()) {
|
||||
blacklistButton = (
|
||||
<button className="mx_MemberDeviceInfo_textButton mx_MemberDeviceInfo_unblacklist"
|
||||
onClick={this.onUnblacklistClick}>
|
||||
{_t("Unblacklist")}
|
||||
{ _t("Unblacklist") }
|
||||
</button>
|
||||
);
|
||||
} else {
|
||||
blacklistButton = (
|
||||
<button className="mx_MemberDeviceInfo_textButton mx_MemberDeviceInfo_blacklist"
|
||||
onClick={this.onBlacklistClick}>
|
||||
{_t("Blacklist")}
|
||||
{ _t("Blacklist") }
|
||||
</button>
|
||||
);
|
||||
}
|
||||
|
@ -99,14 +99,14 @@ export default React.createClass({
|
|||
verifyButton = (
|
||||
<button className="mx_MemberDeviceInfo_textButton mx_MemberDeviceInfo_unverify"
|
||||
onClick={this.onUnverifyClick}>
|
||||
{_t("Unverify")}
|
||||
{ _t("Unverify") }
|
||||
</button>
|
||||
);
|
||||
} else {
|
||||
verifyButton = (
|
||||
<button className="mx_MemberDeviceInfo_textButton mx_MemberDeviceInfo_verify"
|
||||
onClick={this.onVerifyClick}>
|
||||
{_t("Verify...")}
|
||||
{ _t("Verify...") }
|
||||
</button>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -95,7 +95,7 @@ export default class DirectorySearchBox extends React.Component {
|
|||
onChange={this._onChange} onKeyUp={this._onKeyUp}
|
||||
placeholder={this.props.placeholder} autoFocus
|
||||
/>
|
||||
{join_button}
|
||||
{ join_button }
|
||||
<span className="mx_DirectorySearchBox_clear_wrapper">
|
||||
<span className="mx_DirectorySearchBox_clear" onClick={this._onClearClick} />
|
||||
</span>
|
||||
|
|
|
@ -26,6 +26,12 @@ class MenuOption extends React.Component {
|
|||
this._onClick = this._onClick.bind(this);
|
||||
}
|
||||
|
||||
getDefaultProps() {
|
||||
return {
|
||||
disabled: false,
|
||||
};
|
||||
}
|
||||
|
||||
_onMouseEnter() {
|
||||
this.props.onMouseEnter(this.props.dropdownKey);
|
||||
}
|
||||
|
@ -46,15 +52,15 @@ class MenuOption extends React.Component {
|
|||
onClick={this._onClick} onKeyPress={this._onKeyPress}
|
||||
onMouseEnter={this._onMouseEnter}
|
||||
>
|
||||
{this.props.children}
|
||||
</div>
|
||||
{ this.props.children }
|
||||
</div>;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
MenuOption.propTypes = {
|
||||
children: React.PropTypes.oneOfType([
|
||||
React.PropTypes.arrayOf(React.PropTypes.node),
|
||||
React.PropTypes.node
|
||||
React.PropTypes.node,
|
||||
]),
|
||||
highlighted: React.PropTypes.bool,
|
||||
dropdownKey: React.PropTypes.string,
|
||||
|
@ -153,6 +159,8 @@ export default class Dropdown extends React.Component {
|
|||
}
|
||||
|
||||
_onInputClick(ev) {
|
||||
if (this.props.disabled) return;
|
||||
|
||||
if (!this.state.expanded) {
|
||||
this.setState({
|
||||
expanded: true,
|
||||
|
@ -250,13 +258,13 @@ export default class Dropdown extends React.Component {
|
|||
onMouseEnter={this._setHighlightedOption}
|
||||
onClick={this._onMenuOptionClick}
|
||||
>
|
||||
{child}
|
||||
{ child }
|
||||
</MenuOption>
|
||||
);
|
||||
});
|
||||
if (options.length === 0) {
|
||||
return [<div key="0" className="mx_Dropdown_option">
|
||||
{_t("No results")}
|
||||
{ _t("No results") }
|
||||
</div>];
|
||||
}
|
||||
return options;
|
||||
|
@ -279,7 +287,7 @@ export default class Dropdown extends React.Component {
|
|||
/>;
|
||||
}
|
||||
menu = <div className="mx_Dropdown_menu" style={menuStyle}>
|
||||
{this._getMenuOptions()}
|
||||
{ this._getMenuOptions() }
|
||||
</div>;
|
||||
}
|
||||
|
||||
|
@ -288,12 +296,13 @@ export default class Dropdown extends React.Component {
|
|||
this.props.getShortOption(this.props.value) :
|
||||
this.childrenByKey[this.props.value];
|
||||
currentValue = <div className="mx_Dropdown_option">
|
||||
{selectedChild}
|
||||
</div>
|
||||
{ selectedChild }
|
||||
</div>;
|
||||
}
|
||||
|
||||
const dropdownClasses = {
|
||||
mx_Dropdown: true,
|
||||
mx_Dropdown_disabled: this.props.disabled,
|
||||
};
|
||||
if (this.props.className) {
|
||||
dropdownClasses[this.props.className] = true;
|
||||
|
@ -303,9 +312,9 @@ export default class Dropdown extends React.Component {
|
|||
// to the input, but overflows below it. The root contains both.
|
||||
return <div className={classnames(dropdownClasses)} ref={this._collectRoot}>
|
||||
<AccessibleButton className="mx_Dropdown_input" onClick={this._onInputClick}>
|
||||
{currentValue}
|
||||
{ currentValue }
|
||||
<span className="mx_Dropdown_arrow"></span>
|
||||
{menu}
|
||||
{ menu }
|
||||
</AccessibleButton>
|
||||
</div>;
|
||||
}
|
||||
|
@ -329,4 +338,6 @@ Dropdown.propTypes = {
|
|||
// in the dropped-down menu.
|
||||
getShortOption: React.PropTypes.func,
|
||||
value: React.PropTypes.string,
|
||||
}
|
||||
// negative for consistency with HTML
|
||||
disabled: React.PropTypes.bool,
|
||||
};
|
||||
|
|
|
@ -16,7 +16,7 @@ limitations under the License.
|
|||
|
||||
'use strict';
|
||||
|
||||
var React = require('react');
|
||||
const React = require('react');
|
||||
|
||||
const KEY_TAB = 9;
|
||||
const KEY_SHIFT = 16;
|
||||
|
@ -95,8 +95,7 @@ module.exports = React.createClass({
|
|||
this.refs.editable_div.setAttribute("class", this.props.className + " " + this.props.placeholderClassName);
|
||||
this.placeholder = true;
|
||||
this.value = '';
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
this.refs.editable_div.textContent = this.value;
|
||||
this.refs.editable_div.setAttribute("class", this.props.className);
|
||||
this.placeholder = false;
|
||||
|
@ -152,8 +151,7 @@ module.exports = React.createClass({
|
|||
|
||||
if (!ev.target.textContent) {
|
||||
this.showPlaceholder(true);
|
||||
}
|
||||
else if (!this.placeholder) {
|
||||
} else if (!this.placeholder) {
|
||||
this.value = ev.target.textContent;
|
||||
}
|
||||
|
||||
|
@ -177,21 +175,21 @@ module.exports = React.createClass({
|
|||
onFocus: function(ev) {
|
||||
//ev.target.setSelectionRange(0, ev.target.textContent.length);
|
||||
|
||||
var node = ev.target.childNodes[0];
|
||||
const node = ev.target.childNodes[0];
|
||||
if (node) {
|
||||
var range = document.createRange();
|
||||
const range = document.createRange();
|
||||
range.setStart(node, 0);
|
||||
range.setEnd(node, node.length);
|
||||
|
||||
var sel = window.getSelection();
|
||||
const sel = window.getSelection();
|
||||
sel.removeAllRanges();
|
||||
sel.addRange(range);
|
||||
}
|
||||
},
|
||||
|
||||
onFinish: function(ev, shouldSubmit) {
|
||||
var self = this;
|
||||
var submit = (ev.key === "Enter") || shouldSubmit;
|
||||
const self = this;
|
||||
const submit = (ev.key === "Enter") || shouldSubmit;
|
||||
this.setState({
|
||||
phase: this.Phases.Display,
|
||||
}, function() {
|
||||
|
@ -202,19 +200,16 @@ module.exports = React.createClass({
|
|||
},
|
||||
|
||||
onBlur: function(ev) {
|
||||
var sel = window.getSelection();
|
||||
const sel = window.getSelection();
|
||||
sel.removeAllRanges();
|
||||
|
||||
if (this.props.blurToCancel)
|
||||
{this.cancelEdit();}
|
||||
else
|
||||
{this.onFinish(ev, this.props.blurToSubmit);}
|
||||
if (this.props.blurToCancel) {this.cancelEdit();} else {this.onFinish(ev, this.props.blurToSubmit);}
|
||||
|
||||
this.showPlaceholder(!this.value);
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var editable_el;
|
||||
let editable_el;
|
||||
|
||||
if (!this.props.editable || (this.state.phase == this.Phases.Display && (this.props.label || this.props.labelClassName) && !this.value)) {
|
||||
// show the label
|
||||
|
@ -226,5 +221,5 @@ module.exports = React.createClass({
|
|||
}
|
||||
|
||||
return editable_el;
|
||||
}
|
||||
},
|
||||
});
|
||||
|
|
|
@ -64,7 +64,7 @@ export default class EditableTextContainer extends React.Component {
|
|||
errorString: error.toString(),
|
||||
busy: false,
|
||||
});
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -96,22 +96,22 @@ export default class EditableTextContainer extends React.Component {
|
|||
errorString: error.toString(),
|
||||
busy: false,
|
||||
});
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
if (this.state.busy) {
|
||||
var Loader = sdk.getComponent("elements.Spinner");
|
||||
const Loader = sdk.getComponent("elements.Spinner");
|
||||
return (
|
||||
<Loader />
|
||||
);
|
||||
} else if (this.state.errorString) {
|
||||
return (
|
||||
<div className="error">{this.state.errorString}</div>
|
||||
<div className="error">{ this.state.errorString }</div>
|
||||
);
|
||||
} else {
|
||||
var EditableText = sdk.getComponent('elements.EditableText');
|
||||
const EditableText = sdk.getComponent('elements.EditableText');
|
||||
return (
|
||||
<EditableText initialValue={this.state.value}
|
||||
placeholder={this.props.placeholder}
|
||||
|
|
|
@ -265,7 +265,7 @@ export default class Flair extends React.Component {
|
|||
return <FlairAvatar key={index} groupProfile={profile} />;
|
||||
});
|
||||
return (
|
||||
<span className="mx_Flair" style={{"marginLeft": "5px", "verticalAlign": "-3px"}}>
|
||||
<span className="mx_Flair">
|
||||
{ avatars }
|
||||
</span>
|
||||
);
|
||||
|
|
|
@ -23,7 +23,7 @@ const HomeButton = function(props) {
|
|||
const ActionButton = sdk.getComponent('elements.ActionButton');
|
||||
return (
|
||||
<ActionButton action="view_home_page"
|
||||
label={ _t("Home") }
|
||||
label={_t("Home")}
|
||||
iconPath="img/icons-home.svg"
|
||||
size={props.size}
|
||||
tooltip={props.tooltip}
|
||||
|
|
|
@ -35,12 +35,12 @@ export default class LanguageDropdown extends React.Component {
|
|||
this.state = {
|
||||
searchQuery: '',
|
||||
langs: null,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
componentWillMount() {
|
||||
languageHandler.getAllLanguagesFromJson().then((langs) => {
|
||||
langs.sort(function(a, b){
|
||||
langs.sort(function(a, b) {
|
||||
if(a.label < b.label) return -1;
|
||||
if(a.label > b.label) return 1;
|
||||
return 0;
|
||||
|
@ -89,7 +89,7 @@ export default class LanguageDropdown extends React.Component {
|
|||
|
||||
const options = displayedLanguages.map((language) => {
|
||||
return <div key={language.value}>
|
||||
{language.label}
|
||||
{ language.label }
|
||||
</div>;
|
||||
});
|
||||
|
||||
|
@ -108,8 +108,8 @@ export default class LanguageDropdown extends React.Component {
|
|||
onOptionChange={this.props.onOptionChange} onSearchChange={this._onSearchChange}
|
||||
searchEnabled={true} value={value}
|
||||
>
|
||||
{options}
|
||||
</Dropdown>
|
||||
{ options }
|
||||
</Dropdown>;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -96,12 +96,12 @@ module.exports = React.createClass({
|
|||
// Transform into consecutive repetitions of the same transition (like 5
|
||||
// consecutive 'joined_and_left's)
|
||||
const coalescedTransitions = this._coalesceRepeatedTransitions(
|
||||
canonicalTransitions
|
||||
canonicalTransitions,
|
||||
);
|
||||
|
||||
const descs = coalescedTransitions.map((t) => {
|
||||
return this._getDescriptionForTransition(
|
||||
t.transitionType, plural, t.repeats
|
||||
t.transitionType, plural, t.repeats,
|
||||
);
|
||||
});
|
||||
|
||||
|
@ -119,7 +119,7 @@ module.exports = React.createClass({
|
|||
return (
|
||||
<span className="mx_TextualEvent mx_MemberEventListSummary_summary">
|
||||
<EmojiText>
|
||||
{summaries.join(", ")}
|
||||
{ summaries.join(", ") }
|
||||
</EmojiText>
|
||||
</span>
|
||||
);
|
||||
|
@ -370,7 +370,7 @@ module.exports = React.createClass({
|
|||
*/
|
||||
_renderCommaSeparatedList(items, itemLimit) {
|
||||
const remaining = itemLimit === undefined ? 0 : Math.max(
|
||||
items.length - itemLimit, 0
|
||||
items.length - itemLimit, 0,
|
||||
);
|
||||
if (items.length === 0) {
|
||||
return "";
|
||||
|
@ -394,8 +394,8 @@ module.exports = React.createClass({
|
|||
);
|
||||
});
|
||||
return (
|
||||
<span className="mx_MemberEventListSummary_avatars" onClick={ this._toggleSummary }>
|
||||
{avatars}
|
||||
<span className="mx_MemberEventListSummary_avatars" onClick={this._toggleSummary}>
|
||||
{ avatars }
|
||||
</span>
|
||||
);
|
||||
},
|
||||
|
@ -419,19 +419,15 @@ module.exports = React.createClass({
|
|||
case 'join':
|
||||
if (e.mxEvent.getPrevContent().membership === 'join') {
|
||||
if (e.mxEvent.getContent().displayname !==
|
||||
e.mxEvent.getPrevContent().displayname)
|
||||
{
|
||||
e.mxEvent.getPrevContent().displayname) {
|
||||
return 'changed_name';
|
||||
}
|
||||
else if (e.mxEvent.getContent().avatar_url !==
|
||||
e.mxEvent.getPrevContent().avatar_url)
|
||||
{
|
||||
} else if (e.mxEvent.getContent().avatar_url !==
|
||||
e.mxEvent.getPrevContent().avatar_url) {
|
||||
return 'changed_avatar';
|
||||
}
|
||||
// console.log("MELS ignoring duplicate membership join event");
|
||||
return null;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return 'joined';
|
||||
}
|
||||
case 'leave':
|
||||
|
@ -483,7 +479,7 @@ module.exports = React.createClass({
|
|||
firstEvent.index < aggregateIndices[seq]) {
|
||||
aggregateIndices[seq] = firstEvent.index;
|
||||
}
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
return {
|
||||
|
@ -494,7 +490,7 @@ module.exports = React.createClass({
|
|||
|
||||
render: function() {
|
||||
const eventsToRender = this.props.events;
|
||||
const eventIds = eventsToRender.map(e => e.getId()).join(',');
|
||||
const eventIds = eventsToRender.map((e) => e.getId()).join(',');
|
||||
const fewEvents = eventsToRender.length < this.props.threshold;
|
||||
const expanded = this.state.expanded || fewEvents;
|
||||
|
||||
|
@ -506,7 +502,7 @@ module.exports = React.createClass({
|
|||
if (fewEvents) {
|
||||
return (
|
||||
<div className="mx_MemberEventListSummary" data-scroll-tokens={eventIds}>
|
||||
{expandedEvents}
|
||||
{ expandedEvents }
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -542,7 +538,7 @@ module.exports = React.createClass({
|
|||
|
||||
// Sort types by order of lowest event index within sequence
|
||||
const orderedTransitionSequences = Object.keys(aggregate.names).sort(
|
||||
(seq1, seq2) => aggregate.indices[seq1] > aggregate.indices[seq2]
|
||||
(seq1, seq2) => aggregate.indices[seq1] > aggregate.indices[seq2],
|
||||
);
|
||||
|
||||
let summaryContainer = null;
|
||||
|
@ -550,24 +546,24 @@ module.exports = React.createClass({
|
|||
summaryContainer = (
|
||||
<div className="mx_EventTile_line">
|
||||
<div className="mx_EventTile_info">
|
||||
{this._renderAvatars(avatarMembers)}
|
||||
{this._renderSummary(aggregate.names, orderedTransitionSequences)}
|
||||
{ this._renderAvatars(avatarMembers) }
|
||||
{ this._renderSummary(aggregate.names, orderedTransitionSequences) }
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
const toggleButton = (
|
||||
<div className={"mx_MemberEventListSummary_toggle"} onClick={this._toggleSummary}>
|
||||
{expanded ? 'collapse' : 'expand'}
|
||||
{ expanded ? 'collapse' : 'expand' }
|
||||
</div>
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="mx_MemberEventListSummary" data-scroll-tokens={eventIds}>
|
||||
{toggleButton}
|
||||
{summaryContainer}
|
||||
{expanded ? <div className="mx_MemberEventListSummary_line"> </div> : null}
|
||||
{expandedEvents}
|
||||
{ toggleButton }
|
||||
{ summaryContainer }
|
||||
{ expanded ? <div className="mx_MemberEventListSummary_line"> </div> : null }
|
||||
{ expandedEvents }
|
||||
</div>
|
||||
);
|
||||
},
|
||||
|
|
|
@ -20,8 +20,8 @@ import React from 'react';
|
|||
import * as Roles from '../../../Roles';
|
||||
import { _t } from '../../../languageHandler';
|
||||
|
||||
var LEVEL_ROLE_MAP = {};
|
||||
var reverseRoles = {};
|
||||
let LEVEL_ROLE_MAP = {};
|
||||
const reverseRoles = {};
|
||||
|
||||
module.exports = React.createClass({
|
||||
displayName: 'PowerSelector',
|
||||
|
@ -46,7 +46,7 @@ module.exports = React.createClass({
|
|||
custom: (LEVEL_ROLE_MAP[this.props.value] === undefined),
|
||||
};
|
||||
},
|
||||
|
||||
|
||||
componentWillMount: function() {
|
||||
LEVEL_ROLE_MAP = Roles.levelRoleMap();
|
||||
Object.keys(LEVEL_ROLE_MAP).forEach(function(key) {
|
||||
|
@ -72,7 +72,7 @@ module.exports = React.createClass({
|
|||
},
|
||||
|
||||
getValue: function() {
|
||||
var value;
|
||||
let value;
|
||||
if (this.refs.select) {
|
||||
value = reverseRoles[this.refs.select.value];
|
||||
if (this.refs.custom) {
|
||||
|
@ -83,30 +83,27 @@ module.exports = React.createClass({
|
|||
},
|
||||
|
||||
render: function() {
|
||||
var customPicker;
|
||||
let customPicker;
|
||||
if (this.state.custom) {
|
||||
var input;
|
||||
let input;
|
||||
if (this.props.disabled) {
|
||||
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 }/>;
|
||||
} else {
|
||||
input = <input ref="custom" type="text" size="3" defaultValue={this.props.value} onBlur={this.onCustomBlur} onKeyDown={this.onCustomKeyDown} />;
|
||||
}
|
||||
customPicker = <span> of { input }</span>;
|
||||
}
|
||||
|
||||
var selectValue;
|
||||
let selectValue;
|
||||
if (this.state.custom) {
|
||||
selectValue = "Custom";
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
selectValue = LEVEL_ROLE_MAP[this.props.value] || "Custom";
|
||||
}
|
||||
var select;
|
||||
let select;
|
||||
if (this.props.disabled) {
|
||||
select = <span>{ selectValue }</span>;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
// Each level must have a definition in LEVEL_ROLE_MAP
|
||||
const levels = [0, 50, 100];
|
||||
let options = levels.map((level) => {
|
||||
|
@ -115,18 +112,18 @@ module.exports = React.createClass({
|
|||
// Give a userDefault (users_default in the power event) of 0 but
|
||||
// because level !== undefined, this should never be used.
|
||||
text: Roles.textualPowerLevel(level, 0),
|
||||
}
|
||||
};
|
||||
});
|
||||
options.push({ value: "Custom", text: _t("Custom level") });
|
||||
options = options.map((op) => {
|
||||
return <option value={op.value} key={op.value}>{op.text}</option>;
|
||||
return <option value={op.value} key={op.value}>{ op.text }</option>;
|
||||
});
|
||||
|
||||
select =
|
||||
<select ref="select"
|
||||
value={ this.props.controlled ? selectValue : undefined }
|
||||
defaultValue={ !this.props.controlled ? selectValue : undefined }
|
||||
onChange={ this.onSelectChange }>
|
||||
value={this.props.controlled ? selectValue : undefined}
|
||||
defaultValue={!this.props.controlled ? selectValue : undefined}
|
||||
onChange={this.onSelectChange}>
|
||||
{ options }
|
||||
</select>;
|
||||
}
|
||||
|
@ -137,5 +134,5 @@ module.exports = React.createClass({
|
|||
{ customPicker }
|
||||
</span>
|
||||
);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
|
|
@ -16,23 +16,23 @@ limitations under the License.
|
|||
|
||||
'use strict';
|
||||
|
||||
var React = require('react');
|
||||
const React = require('react');
|
||||
|
||||
module.exports = React.createClass({
|
||||
displayName: 'ProgressBar',
|
||||
propTypes: {
|
||||
value: React.PropTypes.number,
|
||||
max: React.PropTypes.number
|
||||
max: React.PropTypes.number,
|
||||
},
|
||||
|
||||
render: function() {
|
||||
// Would use an HTML5 progress tag but if that doesn't animate if you
|
||||
// use the HTML attributes rather than styles
|
||||
var progressStyle = {
|
||||
width: ((this.props.value / this.props.max) * 100)+"%"
|
||||
const progressStyle = {
|
||||
width: ((this.props.value / this.props.max) * 100)+"%",
|
||||
};
|
||||
return (
|
||||
<div className="mx_ProgressBar"><div className="mx_ProgressBar_fill" style={progressStyle}></div></div>
|
||||
);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
|
|
@ -24,7 +24,7 @@ const RoomDirectoryButton = function(props) {
|
|||
return (
|
||||
<ActionButton action="view_room_directory"
|
||||
mouseOverAction={props.callout ? "callout_room_directory" : null}
|
||||
label={ _t("Room directory") }
|
||||
label={_t("Room directory")}
|
||||
iconPath="img/icons-directory.svg"
|
||||
size={props.size}
|
||||
tooltip={props.tooltip}
|
||||
|
|
|
@ -23,7 +23,7 @@ const SettingsButton = function(props) {
|
|||
const ActionButton = sdk.getComponent('elements.ActionButton');
|
||||
return (
|
||||
<ActionButton action="view_user_settings"
|
||||
label={ _t("Settings") }
|
||||
label={_t("Settings")}
|
||||
iconPath="img/icons-settings.svg"
|
||||
size={props.size}
|
||||
tooltip={props.tooltip}
|
||||
|
|
|
@ -24,7 +24,7 @@ const StartChatButton = function(props) {
|
|||
return (
|
||||
<ActionButton action="view_create_chat"
|
||||
mouseOverAction={props.callout ? "callout_start_chat" : null}
|
||||
label={ _t("Start chat") }
|
||||
label={_t("Start chat")}
|
||||
iconPath="img/icons-people.svg"
|
||||
size={props.size}
|
||||
tooltip={props.tooltip}
|
||||
|
|
|
@ -16,9 +16,9 @@ limitations under the License.
|
|||
|
||||
'use strict';
|
||||
|
||||
var React = require('react');
|
||||
var ReactDOM = require("react-dom");
|
||||
var Tinter = require("../../../Tinter");
|
||||
const React = require('react');
|
||||
const ReactDOM = require("react-dom");
|
||||
const Tinter = require("../../../Tinter");
|
||||
|
||||
var TintableSvg = React.createClass({
|
||||
displayName: 'TintableSvg',
|
||||
|
@ -63,16 +63,16 @@ var TintableSvg = React.createClass({
|
|||
|
||||
render: function() {
|
||||
return (
|
||||
<object className={ "mx_TintableSvg " + (this.props.className ? this.props.className : "") }
|
||||
<object className={"mx_TintableSvg " + (this.props.className ? this.props.className : "")}
|
||||
type="image/svg+xml"
|
||||
data={ this.props.src }
|
||||
width={ this.props.width }
|
||||
height={ this.props.height }
|
||||
onLoad={ this.onLoad }
|
||||
data={this.props.src}
|
||||
width={this.props.width}
|
||||
height={this.props.height}
|
||||
onLoad={this.onLoad}
|
||||
tabIndex="-1"
|
||||
/>
|
||||
);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
// Register with the Tinter so that we will be told if the tint changes
|
||||
|
|
|
@ -52,19 +52,19 @@ module.exports = React.createClass({
|
|||
},
|
||||
|
||||
render: function() {
|
||||
var self = this;
|
||||
const self = this;
|
||||
return (
|
||||
<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>;
|
||||
})}
|
||||
{ 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>;
|
||||
}) }
|
||||
</ul>
|
||||
<input type="text" ref="user_id_input" defaultValue="" className="mx_UserSelector_userIdInput" placeholder={_t("ex. @bob:example.com")}/>
|
||||
<input type="text" ref="user_id_input" defaultValue="" className="mx_UserSelector_userIdInput" placeholder={_t("ex. @bob:example.com")} />
|
||||
<button onClick={this.onAddUserId} className="mx_UserSelector_AddUserId">
|
||||
{_t("Add User")}
|
||||
{ _t("Add User") }
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
|
|
@ -17,6 +17,7 @@ import React from 'react';
|
|||
import { _t } from '../../../languageHandler';
|
||||
import sdk from '../../../index';
|
||||
import { groupRoomFromApiObject } from '../../../groups';
|
||||
import GroupStoreCache from '../../../stores/GroupStoreCache';
|
||||
import GeminiScrollbar from 'react-gemini-scrollbar';
|
||||
import PropTypes from 'prop-types';
|
||||
import {MatrixClient} from 'matrix-js-sdk';
|
||||
|
@ -34,7 +35,6 @@ export default React.createClass({
|
|||
|
||||
getInitialState: function() {
|
||||
return {
|
||||
fetching: false,
|
||||
rooms: null,
|
||||
truncateAt: INITIAL_LOAD_NUM_ROOMS,
|
||||
searchQuery: "",
|
||||
|
@ -43,21 +43,29 @@ export default React.createClass({
|
|||
|
||||
componentWillMount: function() {
|
||||
this._unmounted = false;
|
||||
this._initGroupStore(this.props.groupId);
|
||||
},
|
||||
|
||||
_initGroupStore: function(groupId) {
|
||||
this._groupStore = GroupStoreCache.getGroupStore(this.context.matrixClient, groupId);
|
||||
this._groupStore.on('update', () => {
|
||||
this._fetchRooms();
|
||||
});
|
||||
this._groupStore.on('error', (err) => {
|
||||
console.error('Error in group store (listened to by GroupRoomList)', err);
|
||||
this.setState({
|
||||
rooms: null,
|
||||
});
|
||||
});
|
||||
this._fetchRooms();
|
||||
},
|
||||
|
||||
_fetchRooms: function() {
|
||||
this.setState({fetching: true});
|
||||
this.context.matrixClient.getGroupRooms(this.props.groupId).then((result) => {
|
||||
this.setState({
|
||||
rooms: result.chunk.map((apiRoom) => {
|
||||
return groupRoomFromApiObject(apiRoom);
|
||||
}),
|
||||
fetching: false,
|
||||
});
|
||||
}).catch((e) => {
|
||||
this.setState({fetching: false});
|
||||
console.error("Failed to get group room list: ", e);
|
||||
if (this._unmounted) return;
|
||||
this.setState({
|
||||
rooms: this._groupStore.getGroupRooms().map((apiRoom) => {
|
||||
return groupRoomFromApiObject(apiRoom);
|
||||
}),
|
||||
});
|
||||
},
|
||||
|
||||
|
@ -110,12 +118,7 @@ export default React.createClass({
|
|||
},
|
||||
|
||||
render: function() {
|
||||
if (this.state.fetching) {
|
||||
const Spinner = sdk.getComponent("elements.Spinner");
|
||||
return (<div className="mx_GroupRoomList">
|
||||
<Spinner />
|
||||
</div>);
|
||||
} else if (this.state.rooms === null) {
|
||||
if (this.state.rooms === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@ import PropTypes from 'prop-types';
|
|||
import sdk from '../../../index';
|
||||
import dis from '../../../dispatcher';
|
||||
import { GroupRoomType } from '../../../groups';
|
||||
import GroupStoreCache from '../../../stores/GroupStoreCache';
|
||||
import Modal from '../../../Modal';
|
||||
|
||||
const GroupRoomTile = React.createClass({
|
||||
|
@ -49,10 +50,10 @@ const GroupRoomTile = React.createClass({
|
|||
|
||||
removeRoomFromGroup: function() {
|
||||
const groupId = this.props.groupId;
|
||||
const groupStore = GroupStoreCache.getGroupStore(this.context.matrixClient, groupId);
|
||||
const roomName = this.state.name;
|
||||
const roomId = this.props.groupRoom.roomId;
|
||||
this.context.matrixClient
|
||||
.removeRoomFromGroup(groupId, roomId)
|
||||
groupStore.removeRoomFromGroup(roomId)
|
||||
.catch((err) => {
|
||||
console.error(`Error whilst removing ${roomId} from ${groupId}`, err);
|
||||
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||
|
|
|
@ -20,7 +20,7 @@ import React from 'react';
|
|||
import ReactDOM from 'react-dom';
|
||||
import { _t, _tJsx } from '../../../languageHandler';
|
||||
|
||||
var DIV_ID = 'mx_recaptcha';
|
||||
const DIV_ID = 'mx_recaptcha';
|
||||
|
||||
/**
|
||||
* A pure UI component which displays a captcha form.
|
||||
|
@ -60,9 +60,9 @@ module.exports = React.createClass({
|
|||
} else {
|
||||
console.log("Loading recaptcha script...");
|
||||
window.mx_on_recaptcha_loaded = () => {this._onCaptchaLoaded();};
|
||||
var protocol = global.location.protocol;
|
||||
const protocol = global.location.protocol;
|
||||
if (protocol === "file:") {
|
||||
var warning = document.createElement('div');
|
||||
const warning = document.createElement('div');
|
||||
// XXX: fix hardcoded app URL. Better solutions include:
|
||||
// * jumping straight to a hosted captcha page (but we don't support that yet)
|
||||
// * embedding the captcha in an iframe (if that works)
|
||||
|
@ -72,11 +72,10 @@ module.exports = React.createClass({
|
|||
/<a>(.*?)<\/a>/,
|
||||
(sub) => { return <a href='https://riot.im/app'>{ sub }</a>; }), warning);
|
||||
this.refs.recaptchaContainer.appendChild(warning);
|
||||
}
|
||||
else {
|
||||
var scriptTag = document.createElement('script');
|
||||
} else {
|
||||
const scriptTag = document.createElement('script');
|
||||
scriptTag.setAttribute(
|
||||
'src', protocol+"//www.google.com/recaptcha/api.js?onload=mx_on_recaptcha_loaded&render=explicit"
|
||||
'src', protocol+"//www.google.com/recaptcha/api.js?onload=mx_on_recaptcha_loaded&render=explicit",
|
||||
);
|
||||
this.refs.recaptchaContainer.appendChild(scriptTag);
|
||||
}
|
||||
|
@ -93,7 +92,7 @@ module.exports = React.createClass({
|
|||
throw new Error("Recaptcha did not load successfully");
|
||||
}
|
||||
|
||||
var publicKey = this.props.sitePublicKey;
|
||||
const publicKey = this.props.sitePublicKey;
|
||||
if (!publicKey) {
|
||||
console.error("No public key for recaptcha!");
|
||||
throw new Error(
|
||||
|
@ -130,18 +129,18 @@ module.exports = React.createClass({
|
|||
if (this.state.errorText) {
|
||||
error = (
|
||||
<div className="error">
|
||||
{this.state.errorText}
|
||||
{ this.state.errorText }
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div ref="recaptchaContainer">
|
||||
{_t("This Home Server would like to make sure you are not a robot")}
|
||||
<br/>
|
||||
{ _t("This Home Server would like to make sure you are not a robot") }
|
||||
<br />
|
||||
<div id={DIV_ID}></div>
|
||||
{error}
|
||||
{ error }
|
||||
</div>
|
||||
);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
|
|
@ -29,9 +29,9 @@ module.exports = React.createClass({
|
|||
render: function() {
|
||||
return (
|
||||
<div>
|
||||
<button onClick={this.props.onSubmit}>{_t("Sign in with CAS")}</button>
|
||||
<button onClick={this.props.onSubmit}>{ _t("Sign in with CAS") }</button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
});
|
||||
|
|
|
@ -69,7 +69,7 @@ export default class CountryDropdown extends React.Component {
|
|||
}
|
||||
|
||||
_flagImgForIso2(iso2) {
|
||||
return <img src={`flags/${iso2}.png`}/>;
|
||||
return <img src={`flags/${iso2}.png`} />;
|
||||
}
|
||||
|
||||
_getShortOption(iso2) {
|
||||
|
@ -111,8 +111,8 @@ export default class CountryDropdown extends React.Component {
|
|||
|
||||
const options = displayedCountries.map((country) => {
|
||||
return <div key={country.iso2}>
|
||||
{this._flagImgForIso2(country.iso2)}
|
||||
{country.name} <span>(+{country.prefix})</span>
|
||||
{ this._flagImgForIso2(country.iso2) }
|
||||
{ country.name } <span>(+{ country.prefix })</span>
|
||||
</div>;
|
||||
});
|
||||
|
||||
|
@ -123,9 +123,9 @@ export default class CountryDropdown extends React.Component {
|
|||
return <Dropdown className={this.props.className + " left_aligned"}
|
||||
onOptionChange={this._onOptionChange} onSearchChange={this._onSearchChange}
|
||||
menuWidth={298} getShortOption={this._getShortOption}
|
||||
value={value} searchEnabled={true}
|
||||
value={value} searchEnabled={true} disabled={this.props.disabled}
|
||||
>
|
||||
{options}
|
||||
{ options }
|
||||
</Dropdown>;
|
||||
}
|
||||
}
|
||||
|
@ -137,4 +137,5 @@ CountryDropdown.propTypes = {
|
|||
showPrefix: React.PropTypes.bool,
|
||||
onOptionChange: React.PropTypes.func.isRequired,
|
||||
value: React.PropTypes.string,
|
||||
disabled: React.PropTypes.bool,
|
||||
};
|
||||
|
|
|
@ -24,27 +24,27 @@ module.exports = React.createClass({
|
|||
return (
|
||||
<div className="mx_ErrorDialog">
|
||||
<div className="mx_Dialog_title">
|
||||
{_t("Custom Server Options")}
|
||||
{ _t("Custom Server Options") }
|
||||
</div>
|
||||
<div className="mx_Dialog_content">
|
||||
<span>
|
||||
{_t("You can use the custom server options to sign into other Matrix " +
|
||||
"servers by specifying a different Home server URL.")}
|
||||
<br/>
|
||||
{_t("This allows you to use this app with an existing Matrix account on " +
|
||||
"a different home server.")}
|
||||
<br/>
|
||||
<br/>
|
||||
{_t("You can also set a custom identity server but this will typically prevent " +
|
||||
"interaction with users based on email address.")}
|
||||
{ _t("You can use the custom server options to sign into other Matrix " +
|
||||
"servers by specifying a different Home server URL.") }
|
||||
<br />
|
||||
{ _t("This allows you to use this app with an existing Matrix account on " +
|
||||
"a different home server.") }
|
||||
<br />
|
||||
<br />
|
||||
{ _t("You can also set a custom identity server but this will typically prevent " +
|
||||
"interaction with users based on email address.") }
|
||||
</span>
|
||||
</div>
|
||||
<div className="mx_Dialog_buttons">
|
||||
<button onClick={this.props.onFinished} autoFocus={true}>
|
||||
{_t("Dismiss")}
|
||||
{ _t("Dismiss") }
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
|
|
@ -129,8 +129,8 @@ export const PasswordAuthEntry = React.createClass({
|
|||
|
||||
return (
|
||||
<div>
|
||||
<p>{_t("To continue, please enter your password.")}</p>
|
||||
<p>{_t("Password:")}</p>
|
||||
<p>{ _t("To continue, please enter your password.") }</p>
|
||||
<p>{ _t("Password:") }</p>
|
||||
<form onSubmit={this._onSubmit}>
|
||||
<input
|
||||
ref="passwordField"
|
||||
|
@ -139,11 +139,11 @@ export const PasswordAuthEntry = React.createClass({
|
|||
type="password"
|
||||
/>
|
||||
<div className="mx_button_row">
|
||||
{submitButtonOrSpinner}
|
||||
{ submitButtonOrSpinner }
|
||||
</div>
|
||||
</form>
|
||||
<div className="error">
|
||||
{this.props.errorText}
|
||||
{ this.props.errorText }
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
@ -178,14 +178,14 @@ export const RecaptchaAuthEntry = React.createClass({
|
|||
}
|
||||
|
||||
const CaptchaForm = sdk.getComponent("views.login.CaptchaForm");
|
||||
var sitePublicKey = this.props.stageParams.public_key;
|
||||
const sitePublicKey = this.props.stageParams.public_key;
|
||||
return (
|
||||
<div>
|
||||
<CaptchaForm sitePublicKey={sitePublicKey}
|
||||
onCaptchaResponse={this._onCaptchaResponse}
|
||||
/>
|
||||
<div className="error">
|
||||
{this.props.errorText}
|
||||
{ this.props.errorText }
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
@ -256,8 +256,8 @@ export const EmailIdentityAuthEntry = React.createClass({
|
|||
} else {
|
||||
return (
|
||||
<div>
|
||||
<p>{_t("An email has been sent to")} <i>{this.props.inputs.emailAddress}</i></p>
|
||||
<p>{_t("Please check your email to continue registration.")}</p>
|
||||
<p>{ _t("An email has been sent to") } <i>{ this.props.inputs.emailAddress }</i></p>
|
||||
<p>{ _t("Please check your email to continue registration.") }</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -333,12 +333,12 @@ export const MsisdnAuthEntry = React.createClass({
|
|||
});
|
||||
|
||||
this.props.matrixClient.submitMsisdnToken(
|
||||
this._sid, this.props.clientSecret, this.state.token
|
||||
this._sid, this.props.clientSecret, this.state.token,
|
||||
).then((result) => {
|
||||
if (result.success) {
|
||||
const idServerParsedUrl = url.parse(
|
||||
this.props.matrixClient.getIdentityServerUrl(),
|
||||
)
|
||||
);
|
||||
this.props.submitAuthDict({
|
||||
type: MsisdnAuthEntry.LOGIN_TYPE,
|
||||
threepid_creds: {
|
||||
|
@ -370,8 +370,8 @@ export const MsisdnAuthEntry = React.createClass({
|
|||
});
|
||||
return (
|
||||
<div>
|
||||
<p>{_t("A text message has been sent to")} +<i>{this._msisdn}</i></p>
|
||||
<p>{_t("Please enter the code it contains:")}</p>
|
||||
<p>{ _t("A text message has been sent to") } +<i>{ this._msisdn }</i></p>
|
||||
<p>{ _t("Please enter the code it contains:") }</p>
|
||||
<div className="mx_InteractiveAuthEntryComponents_msisdnWrapper">
|
||||
<form onSubmit={this._onFormSubmit}>
|
||||
<input type="text"
|
||||
|
@ -386,7 +386,7 @@ export const MsisdnAuthEntry = React.createClass({
|
|||
/>
|
||||
</form>
|
||||
<div className="error">
|
||||
{this.state.errorText}
|
||||
{ this.state.errorText }
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -421,9 +421,9 @@ export const FallbackAuthEntry = React.createClass({
|
|||
},
|
||||
|
||||
_onShowFallbackClick: function() {
|
||||
var url = this.props.matrixClient.getFallbackAuthUrl(
|
||||
const url = this.props.matrixClient.getFallbackAuthUrl(
|
||||
this.props.loginType,
|
||||
this.props.authSessionId
|
||||
this.props.authSessionId,
|
||||
);
|
||||
this._popupWindow = window.open(url);
|
||||
},
|
||||
|
@ -440,9 +440,9 @@ export const FallbackAuthEntry = React.createClass({
|
|||
render: function() {
|
||||
return (
|
||||
<div>
|
||||
<a onClick={this._onShowFallbackClick}>{_t("Start authentication")}</a>
|
||||
<a onClick={this._onShowFallbackClick}>{ _t("Start authentication") }</a>
|
||||
<div className="error">
|
||||
{this.props.errorText}
|
||||
{ this.props.errorText }
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
@ -457,7 +457,7 @@ const AuthEntryComponents = [
|
|||
];
|
||||
|
||||
export function getEntryComponentForLoginType(loginType) {
|
||||
for (var c of AuthEntryComponents) {
|
||||
for (const c of AuthEntryComponents) {
|
||||
if (c.LOGIN_TYPE == loginType) {
|
||||
return c;
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ limitations under the License.
|
|||
|
||||
'use strict';
|
||||
|
||||
var React = require('react');
|
||||
const React = require('react');
|
||||
|
||||
module.exports = React.createClass({
|
||||
displayName: 'LoginHeader',
|
||||
|
@ -27,5 +27,5 @@ module.exports = React.createClass({
|
|||
Matrix
|
||||
</div>
|
||||
);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
|
|
@ -94,7 +94,7 @@ class PasswordLogin extends React.Component {
|
|||
onLoginTypeChange(loginType) {
|
||||
this.setState({
|
||||
loginType: loginType,
|
||||
username: "" // Reset because email and username use the same state
|
||||
username: "", // Reset because email and username use the same state
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -116,11 +116,17 @@ class PasswordLogin extends React.Component {
|
|||
this.props.onPasswordChanged(ev.target.value);
|
||||
}
|
||||
|
||||
renderLoginField(loginType) {
|
||||
renderLoginField(loginType, disabled) {
|
||||
const classes = {
|
||||
mx_Login_field: true,
|
||||
mx_Login_field_disabled: disabled,
|
||||
};
|
||||
|
||||
switch(loginType) {
|
||||
case PasswordLogin.LOGIN_FIELD_EMAIL:
|
||||
classes.mx_Login_email = true;
|
||||
return <input
|
||||
className="mx_Login_field mx_Login_email"
|
||||
className={classNames(classes)}
|
||||
key="email_input"
|
||||
type="text"
|
||||
name="username" // make it a little easier for browser's remember-password
|
||||
|
@ -128,10 +134,12 @@ class PasswordLogin extends React.Component {
|
|||
placeholder="joe@example.com"
|
||||
value={this.state.username}
|
||||
autoFocus
|
||||
disabled={disabled}
|
||||
/>;
|
||||
case PasswordLogin.LOGIN_FIELD_MXID:
|
||||
classes.mx_Login_username = true;
|
||||
return <input
|
||||
className="mx_Login_field mx_Login_username"
|
||||
className={classNames(classes)}
|
||||
key="username_input"
|
||||
type="text"
|
||||
name="username" // make it a little easier for browser's remember-password
|
||||
|
@ -139,9 +147,12 @@ class PasswordLogin extends React.Component {
|
|||
placeholder={_t('User name')}
|
||||
value={this.state.username}
|
||||
autoFocus
|
||||
disabled={disabled}
|
||||
/>;
|
||||
case PasswordLogin.LOGIN_FIELD_PHONE:
|
||||
const CountryDropdown = sdk.getComponent('views.login.CountryDropdown');
|
||||
classes.mx_Login_phoneNumberField = true;
|
||||
classes.mx_Login_field_has_prefix = true;
|
||||
return <div className="mx_Login_phoneSection">
|
||||
<CountryDropdown
|
||||
className="mx_Login_phoneCountry mx_Login_field_prefix"
|
||||
|
@ -150,9 +161,10 @@ class PasswordLogin extends React.Component {
|
|||
value={this.state.phoneCountry}
|
||||
isSmall={true}
|
||||
showPrefix={true}
|
||||
disabled={disabled}
|
||||
/>
|
||||
<input
|
||||
className="mx_Login_phoneNumberField mx_Login_field mx_Login_field_has_prefix"
|
||||
className={classNames(classes)}
|
||||
ref="phoneNumber"
|
||||
key="phone_input"
|
||||
type="text"
|
||||
|
@ -161,13 +173,14 @@ class PasswordLogin extends React.Component {
|
|||
placeholder={_t("Mobile phone number")}
|
||||
value={this.state.phoneNumber}
|
||||
autoFocus
|
||||
disabled={disabled}
|
||||
/>
|
||||
</div>;
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
var forgotPasswordJsx;
|
||||
let forgotPasswordJsx;
|
||||
|
||||
if (this.props.onForgotPasswordClick) {
|
||||
forgotPasswordJsx = (
|
||||
|
@ -177,14 +190,25 @@ class PasswordLogin extends React.Component {
|
|||
);
|
||||
}
|
||||
|
||||
let matrixIdText = '';
|
||||
if (this.props.hsUrl) {
|
||||
try {
|
||||
const parsedHsUrl = new URL(this.props.hsUrl);
|
||||
matrixIdText = _t('%(serverName)s Matrix ID', {serverName: parsedHsUrl.hostname});
|
||||
} catch (e) {
|
||||
// pass
|
||||
}
|
||||
}
|
||||
|
||||
const pwFieldClass = classNames({
|
||||
mx_Login_field: true,
|
||||
mx_Login_field_disabled: matrixIdText === '',
|
||||
error: this.props.loginIncorrect,
|
||||
});
|
||||
|
||||
const Dropdown = sdk.getComponent('elements.Dropdown');
|
||||
|
||||
const loginField = this.renderLoginField(this.state.loginType);
|
||||
const loginField = this.renderLoginField(this.state.loginType, matrixIdText === '');
|
||||
|
||||
return (
|
||||
<div>
|
||||
|
@ -194,20 +218,23 @@ class PasswordLogin extends React.Component {
|
|||
<Dropdown
|
||||
className="mx_Login_type_dropdown"
|
||||
value={this.state.loginType}
|
||||
disabled={matrixIdText === ''}
|
||||
onOptionChange={this.onLoginTypeChange}>
|
||||
<span key={PasswordLogin.LOGIN_FIELD_MXID}>{ _t('my Matrix ID') }</span>
|
||||
<span key={PasswordLogin.LOGIN_FIELD_MXID}>{ matrixIdText }</span>
|
||||
<span key={PasswordLogin.LOGIN_FIELD_EMAIL}>{ _t('Email address') }</span>
|
||||
<span key={PasswordLogin.LOGIN_FIELD_PHONE}>{ _t('Phone') }</span>
|
||||
</Dropdown>
|
||||
</div>
|
||||
{loginField}
|
||||
{ loginField }
|
||||
<input className={pwFieldClass} ref={(e) => {this._passwordField = e;}} type="password"
|
||||
name="password"
|
||||
value={this.state.password} onChange={this.onPasswordChanged}
|
||||
placeholder={ _t('Password') } />
|
||||
placeholder={_t('Password')}
|
||||
disabled={matrixIdText === ''}
|
||||
/>
|
||||
<br />
|
||||
{forgotPasswordJsx}
|
||||
<input className="mx_Login_submit" type="submit" value={ _t('Sign in') } />
|
||||
{ forgotPasswordJsx }
|
||||
<input className="mx_Login_submit" type="submit" value={_t('Sign in')} disabled={matrixIdText === ''} />
|
||||
</form>
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -64,7 +64,7 @@ module.exports = React.createClass({
|
|||
minPasswordLength: 6,
|
||||
onError: function(e) {
|
||||
console.error(e);
|
||||
}
|
||||
},
|
||||
};
|
||||
},
|
||||
|
||||
|
@ -91,16 +91,16 @@ module.exports = React.createClass({
|
|||
this.validateField(FIELD_PHONE_NUMBER);
|
||||
this.validateField(FIELD_EMAIL);
|
||||
|
||||
var self = this;
|
||||
const self = this;
|
||||
if (this.allFieldsValid()) {
|
||||
if (this.refs.email.value == '') {
|
||||
var QuestionDialog = sdk.getComponent("dialogs.QuestionDialog");
|
||||
const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog");
|
||||
Modal.createTrackedDialog('If you don\'t specify an email address...', '', QuestionDialog, {
|
||||
title: _t("Warning!"),
|
||||
description:
|
||||
<div>
|
||||
{_t("If you don't specify an email address, you won't be able to reset your password. " +
|
||||
"Are you sure?")}
|
||||
{ _t("If you don't specify an email address, you won't be able to reset your password. " +
|
||||
"Are you sure?") }
|
||||
</div>,
|
||||
button: _t("Continue"),
|
||||
onFinished: function(confirmed) {
|
||||
|
@ -116,8 +116,8 @@ module.exports = React.createClass({
|
|||
},
|
||||
|
||||
_doSubmit: function(ev) {
|
||||
let email = this.refs.email.value.trim();
|
||||
var promise = this.props.onRegisterClick({
|
||||
const email = this.refs.email.value.trim();
|
||||
const promise = this.props.onRegisterClick({
|
||||
username: this.refs.username.value.trim(),
|
||||
password: this.refs.password.value.trim(),
|
||||
email: email,
|
||||
|
@ -138,8 +138,8 @@ module.exports = React.createClass({
|
|||
* they were validated.
|
||||
*/
|
||||
allFieldsValid: function() {
|
||||
var keys = Object.keys(this.state.fieldValid);
|
||||
for (var i = 0; i < keys.length; ++i) {
|
||||
const keys = Object.keys(this.state.fieldValid);
|
||||
for (let i = 0; i < keys.length; ++i) {
|
||||
if (this.state.fieldValid[keys[i]] == false) {
|
||||
return false;
|
||||
}
|
||||
|
@ -152,8 +152,8 @@ module.exports = React.createClass({
|
|||
},
|
||||
|
||||
validateField: function(field_id) {
|
||||
var pwd1 = this.refs.password.value.trim();
|
||||
var pwd2 = this.refs.passwordConfirm.value.trim();
|
||||
const pwd1 = this.refs.password.value.trim();
|
||||
const pwd2 = this.refs.passwordConfirm.value.trim();
|
||||
|
||||
switch (field_id) {
|
||||
case FIELD_EMAIL:
|
||||
|
@ -162,7 +162,7 @@ module.exports = React.createClass({
|
|||
const matchingTeam = this.props.teamsConfig.teams.find(
|
||||
(team) => {
|
||||
return email.split('@').pop() === team.domain;
|
||||
}
|
||||
},
|
||||
) || null;
|
||||
this.setState({
|
||||
selectedTeam: matchingTeam,
|
||||
|
@ -191,13 +191,13 @@ module.exports = React.createClass({
|
|||
this.markFieldValid(
|
||||
field_id,
|
||||
false,
|
||||
"RegistrationForm.ERR_USERNAME_INVALID"
|
||||
"RegistrationForm.ERR_USERNAME_INVALID",
|
||||
);
|
||||
} else if (username == '') {
|
||||
this.markFieldValid(
|
||||
field_id,
|
||||
false,
|
||||
"RegistrationForm.ERR_USERNAME_BLANK"
|
||||
"RegistrationForm.ERR_USERNAME_BLANK",
|
||||
);
|
||||
} else {
|
||||
this.markFieldValid(field_id, true);
|
||||
|
@ -208,13 +208,13 @@ module.exports = React.createClass({
|
|||
this.markFieldValid(
|
||||
field_id,
|
||||
false,
|
||||
"RegistrationForm.ERR_PASSWORD_MISSING"
|
||||
"RegistrationForm.ERR_PASSWORD_MISSING",
|
||||
);
|
||||
} else if (pwd1.length < this.props.minPasswordLength) {
|
||||
this.markFieldValid(
|
||||
field_id,
|
||||
false,
|
||||
"RegistrationForm.ERR_PASSWORD_LENGTH"
|
||||
"RegistrationForm.ERR_PASSWORD_LENGTH",
|
||||
);
|
||||
} else {
|
||||
this.markFieldValid(field_id, true);
|
||||
|
@ -223,14 +223,14 @@ module.exports = React.createClass({
|
|||
case FIELD_PASSWORD_CONFIRM:
|
||||
this.markFieldValid(
|
||||
field_id, pwd1 == pwd2,
|
||||
"RegistrationForm.ERR_PASSWORD_MISMATCH"
|
||||
"RegistrationForm.ERR_PASSWORD_MISMATCH",
|
||||
);
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
markFieldValid: function(field_id, val, error_code) {
|
||||
var fieldValid = this.state.fieldValid;
|
||||
const fieldValid = this.state.fieldValid;
|
||||
fieldValid[field_id] = val;
|
||||
this.setState({fieldValid: fieldValid});
|
||||
if (!val) {
|
||||
|
@ -271,7 +271,7 @@ module.exports = React.createClass({
|
|||
},
|
||||
|
||||
render: function() {
|
||||
var self = this;
|
||||
const self = this;
|
||||
|
||||
const emailSection = (
|
||||
<div>
|
||||
|
@ -280,7 +280,7 @@ module.exports = React.createClass({
|
|||
defaultValue={this.props.defaultEmail}
|
||||
className={this._classForField(FIELD_EMAIL, 'mx_Login_field')}
|
||||
onBlur={function() {self.validateField(FIELD_EMAIL);}}
|
||||
value={self.state.email}/>
|
||||
value={self.state.email} />
|
||||
</div>
|
||||
);
|
||||
let belowEmailSection;
|
||||
|
@ -291,7 +291,7 @@ module.exports = React.createClass({
|
|||
Sorry, but your university is not registered with us just yet.
|
||||
Email us on
|
||||
<a href={"mailto:" + this.props.teamsConfig.supportEmail}>
|
||||
{this.props.teamsConfig.supportEmail}
|
||||
{ this.props.teamsConfig.supportEmail }
|
||||
</a>
|
||||
to get your university signed up. Or continue to register with Riot to enjoy our open source platform.
|
||||
</p>
|
||||
|
@ -299,7 +299,7 @@ module.exports = React.createClass({
|
|||
} else if (this.state.selectedTeam) {
|
||||
belowEmailSection = (
|
||||
<p className="mx_Login_support">
|
||||
{_t("You are registering with %(SelectedTeamName)s", {SelectedTeamName: this.state.selectedTeam.name})}
|
||||
{ _t("You are registering with %(SelectedTeamName)s", {SelectedTeamName: this.state.selectedTeam.name}) }
|
||||
</p>
|
||||
);
|
||||
}
|
||||
|
@ -321,7 +321,7 @@ module.exports = React.createClass({
|
|||
FIELD_PHONE_NUMBER,
|
||||
'mx_Login_phoneNumberField',
|
||||
'mx_Login_field',
|
||||
'mx_Login_field_has_prefix'
|
||||
'mx_Login_field_has_prefix',
|
||||
)}
|
||||
onBlur={function() {self.validateField(FIELD_PHONE_NUMBER);}}
|
||||
value={self.state.phoneNumber}
|
||||
|
@ -333,16 +333,16 @@ module.exports = React.createClass({
|
|||
<input className="mx_Login_submit" type="submit" value={_t("Register")} />
|
||||
);
|
||||
|
||||
let placeholderUserName = _t("User name");
|
||||
const placeholderUserName = _t("User name");
|
||||
|
||||
return (
|
||||
<div>
|
||||
<form onSubmit={this.onSubmit}>
|
||||
{emailSection}
|
||||
{belowEmailSection}
|
||||
{phoneSection}
|
||||
{ emailSection }
|
||||
{ belowEmailSection }
|
||||
{ phoneSection }
|
||||
<input type="text" ref="username"
|
||||
placeholder={ placeholderUserName } defaultValue={this.props.defaultUsername}
|
||||
placeholder={placeholderUserName} defaultValue={this.props.defaultUsername}
|
||||
className={this._classForField(FIELD_USERNAME, 'mx_Login_field')}
|
||||
onBlur={function() {self.validateField(FIELD_USERNAME);}} />
|
||||
<br />
|
||||
|
@ -357,9 +357,9 @@ module.exports = React.createClass({
|
|||
onBlur={function() {self.validateField(FIELD_PASSWORD_CONFIRM);}}
|
||||
defaultValue={this.props.defaultPassword} />
|
||||
<br />
|
||||
{registerButton}
|
||||
{ registerButton }
|
||||
</form>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
|
|
@ -16,9 +16,9 @@ limitations under the License.
|
|||
|
||||
'use strict';
|
||||
|
||||
var React = require('react');
|
||||
var Modal = require('../../../Modal');
|
||||
var sdk = require('../../../index');
|
||||
const React = require('react');
|
||||
const Modal = require('../../../Modal');
|
||||
const sdk = require('../../../index');
|
||||
import { _t } from '../../../languageHandler';
|
||||
|
||||
/**
|
||||
|
@ -45,7 +45,7 @@ module.exports = React.createClass({
|
|||
customIsUrl: React.PropTypes.string,
|
||||
|
||||
withToggleButton: React.PropTypes.bool,
|
||||
delayTimeMs: React.PropTypes.number // time to wait before invoking onChanged
|
||||
delayTimeMs: React.PropTypes.number, // time to wait before invoking onChanged
|
||||
},
|
||||
|
||||
getDefaultProps: function() {
|
||||
|
@ -54,7 +54,7 @@ module.exports = React.createClass({
|
|||
customHsUrl: "",
|
||||
customIsUrl: "",
|
||||
withToggleButton: false,
|
||||
delayTimeMs: 0
|
||||
delayTimeMs: 0,
|
||||
};
|
||||
},
|
||||
|
||||
|
@ -65,18 +65,18 @@ module.exports = React.createClass({
|
|||
// 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 ||
|
||||
(this.props.customHsUrl !== this.props.defaultHsUrl) ||
|
||||
(this.props.customIsUrl !== this.props.defaultIsUrl)
|
||||
(this.props.customIsUrl !== this.props.defaultIsUrl),
|
||||
};
|
||||
},
|
||||
|
||||
onHomeserverChanged: function(ev) {
|
||||
this.setState({hs_url: ev.target.value}, function() {
|
||||
this._hsTimeoutId = this._waitThenInvoke(this._hsTimeoutId, function() {
|
||||
var hsUrl = this.state.hs_url.trim().replace(/\/$/, "");
|
||||
let hsUrl = this.state.hs_url.trim().replace(/\/$/, "");
|
||||
if (hsUrl === "") hsUrl = this.props.defaultHsUrl;
|
||||
this.props.onServerConfigChange({
|
||||
hsUrl : this.state.hs_url,
|
||||
isUrl : this.state.is_url,
|
||||
hsUrl: this.state.hs_url,
|
||||
isUrl: this.state.is_url,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -85,11 +85,11 @@ module.exports = React.createClass({
|
|||
onIdentityServerChanged: function(ev) {
|
||||
this.setState({is_url: ev.target.value}, function() {
|
||||
this._isTimeoutId = this._waitThenInvoke(this._isTimeoutId, function() {
|
||||
var isUrl = this.state.is_url.trim().replace(/\/$/, "");
|
||||
let isUrl = this.state.is_url.trim().replace(/\/$/, "");
|
||||
if (isUrl === "") isUrl = this.props.defaultIsUrl;
|
||||
this.props.onServerConfigChange({
|
||||
hsUrl : this.state.hs_url,
|
||||
isUrl : this.state.is_url,
|
||||
hsUrl: this.state.hs_url,
|
||||
isUrl: this.state.is_url,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -104,32 +104,31 @@ module.exports = React.createClass({
|
|||
|
||||
onServerConfigVisibleChange: function(visible, ev) {
|
||||
this.setState({
|
||||
configVisible: visible
|
||||
configVisible: visible,
|
||||
});
|
||||
if (!visible) {
|
||||
this.props.onServerConfigChange({
|
||||
hsUrl : this.props.defaultHsUrl,
|
||||
isUrl : this.props.defaultIsUrl,
|
||||
hsUrl: this.props.defaultHsUrl,
|
||||
isUrl: this.props.defaultIsUrl,
|
||||
});
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
this.props.onServerConfigChange({
|
||||
hsUrl : this.state.hs_url,
|
||||
isUrl : this.state.is_url,
|
||||
hsUrl: this.state.hs_url,
|
||||
isUrl: this.state.is_url,
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
showHelpPopup: function() {
|
||||
var CustomServerDialog = sdk.getComponent('login.CustomServerDialog');
|
||||
const CustomServerDialog = sdk.getComponent('login.CustomServerDialog');
|
||||
Modal.createTrackedDialog('Custom Server Dialog', '', CustomServerDialog);
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var serverConfigStyle = {};
|
||||
const serverConfigStyle = {};
|
||||
serverConfigStyle.display = this.state.configVisible ? 'block' : 'none';
|
||||
|
||||
var toggleButton;
|
||||
let toggleButton;
|
||||
if (this.props.withToggleButton) {
|
||||
toggleButton = (
|
||||
<div className="mx_ServerConfig_selector">
|
||||
|
@ -137,14 +136,14 @@ module.exports = React.createClass({
|
|||
checked={!this.state.configVisible}
|
||||
onChange={this.onServerConfigVisibleChange.bind(this, false)} />
|
||||
<label className="mx_Login_label" htmlFor="basic">
|
||||
{_t("Default server")}
|
||||
{ _t("Default server") }
|
||||
</label>
|
||||
|
||||
<input className="mx_Login_radio" id="advanced" name="configVisible" type="radio"
|
||||
checked={this.state.configVisible}
|
||||
onChange={this.onServerConfigVisibleChange.bind(this, true)} />
|
||||
<label className="mx_Login_label" htmlFor="advanced">
|
||||
{_t("Custom server")}
|
||||
{ _t("Custom server") }
|
||||
</label>
|
||||
</div>
|
||||
);
|
||||
|
@ -152,11 +151,11 @@ module.exports = React.createClass({
|
|||
|
||||
return (
|
||||
<div>
|
||||
{toggleButton}
|
||||
{ toggleButton }
|
||||
<div style={serverConfigStyle}>
|
||||
<div className="mx_ServerConfig">
|
||||
<label className="mx_Login_label mx_ServerConfig_hslabel" htmlFor="hsurl">
|
||||
{_t("Home server URL")}
|
||||
{ _t("Home server URL") }
|
||||
</label>
|
||||
<input className="mx_Login_field" id="hsurl" type="text"
|
||||
placeholder={this.props.defaultHsUrl}
|
||||
|
@ -164,7 +163,7 @@ module.exports = React.createClass({
|
|||
value={this.state.hs_url}
|
||||
onChange={this.onHomeserverChanged} />
|
||||
<label className="mx_Login_label mx_ServerConfig_islabel" htmlFor="isurl">
|
||||
{_t("Identity server URL")}
|
||||
{ _t("Identity server URL") }
|
||||
</label>
|
||||
<input className="mx_Login_field" id="isurl" type="text"
|
||||
placeholder={this.props.defaultIsUrl}
|
||||
|
@ -172,11 +171,11 @@ module.exports = React.createClass({
|
|||
value={this.state.is_url}
|
||||
onChange={this.onIdentityServerChanged} />
|
||||
<a className="mx_ServerConfig_help" href="#" onClick={this.showHelpPopup}>
|
||||
{_t("What does this mean?")}
|
||||
{ _t("What does this mean?") }
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
|
|
@ -35,7 +35,7 @@ export default class MAudioBody extends React.Component {
|
|||
}
|
||||
onPlayToggle() {
|
||||
this.setState({
|
||||
playing: !this.state.playing
|
||||
playing: !this.state.playing,
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -49,9 +49,9 @@ export default class MAudioBody extends React.Component {
|
|||
}
|
||||
|
||||
componentDidMount() {
|
||||
var content = this.props.mxEvent.getContent();
|
||||
const content = this.props.mxEvent.getContent();
|
||||
if (content.file !== undefined && this.state.decryptedUrl === null) {
|
||||
var decryptedBlob;
|
||||
let decryptedBlob;
|
||||
decryptFile(content.file).then(function(blob) {
|
||||
decryptedBlob = blob;
|
||||
return readBlobAsDataUri(decryptedBlob);
|
||||
|
@ -70,14 +70,13 @@ export default class MAudioBody extends React.Component {
|
|||
}
|
||||
|
||||
render() {
|
||||
|
||||
const content = this.props.mxEvent.getContent();
|
||||
|
||||
if (this.state.error !== null) {
|
||||
return (
|
||||
<span className="mx_MAudioBody" ref="body">
|
||||
<img src="img/warning.svg" width="16" height="16"/>
|
||||
{_t("Error decrypting audio")}
|
||||
<img src="img/warning.svg" width="16" height="16" />
|
||||
{ _t("Error decrypting audio") }
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
@ -89,7 +88,7 @@ export default class MAudioBody extends React.Component {
|
|||
// Not sure how tall the audio player is so not sure how tall it should actually be.
|
||||
return (
|
||||
<span className="mx_MAudioBody">
|
||||
<img src="img/spinner.gif" alt={content.body} width="16" height="16"/>
|
||||
<img src="img/spinner.gif" alt={content.body} width="16" height="16" />
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -28,10 +28,10 @@ import Modal from '../../../Modal';
|
|||
|
||||
|
||||
// A cached tinted copy of "img/download.svg"
|
||||
var tintedDownloadImageURL;
|
||||
let tintedDownloadImageURL;
|
||||
// Track a list of mounted MFileBody instances so that we can update
|
||||
// the "img/download.svg" when the tint changes.
|
||||
var nextMountId = 0;
|
||||
let nextMountId = 0;
|
||||
const mounts = {};
|
||||
|
||||
/**
|
||||
|
@ -169,11 +169,11 @@ function computedStyle(element) {
|
|||
return "";
|
||||
}
|
||||
const style = window.getComputedStyle(element, null);
|
||||
var cssText = style.cssText;
|
||||
let cssText = style.cssText;
|
||||
if (cssText == "") {
|
||||
// Firefox doesn't implement ".cssText" for computed styles.
|
||||
// https://bugzilla.mozilla.org/show_bug.cgi?id=137687
|
||||
for (var i = 0; i < style.length; i++) {
|
||||
for (let i = 0; i < style.length; i++) {
|
||||
cssText += style[i] + ":";
|
||||
cssText += style.getPropertyValue(style[i]) + ";";
|
||||
}
|
||||
|
@ -202,7 +202,7 @@ module.exports = React.createClass({
|
|||
* @return {string} the human readable link text for the attachment.
|
||||
*/
|
||||
presentableTextForFile: function(content) {
|
||||
var linkText = _t("Attachment");
|
||||
let linkText = _t("Attachment");
|
||||
if (content.body && content.body.length > 0) {
|
||||
// The content body should be the name of the file including a
|
||||
// file extension.
|
||||
|
@ -270,7 +270,7 @@ module.exports = React.createClass({
|
|||
// Need to decrypt the attachment
|
||||
// Wait for the user to click on the link before downloading
|
||||
// and decrypting the attachment.
|
||||
var decrypting = false;
|
||||
let decrypting = false;
|
||||
const decrypt = () => {
|
||||
if (decrypting) {
|
||||
return false;
|
||||
|
@ -328,14 +328,14 @@ module.exports = React.createClass({
|
|||
<span className="mx_MFileBody">
|
||||
<div className="mx_MImageBody_download">
|
||||
<div style={{display: "none"}}>
|
||||
{/*
|
||||
{ /*
|
||||
* Add dummy copy of the "a" tag
|
||||
* We'll use it to learn how the download link
|
||||
* would have been styled if it was rendered inline.
|
||||
*/}
|
||||
<a ref="dummyLink"/>
|
||||
*/ }
|
||||
<a ref="dummyLink" />
|
||||
</div>
|
||||
<iframe src={renderer_url} onLoad={onIframeLoad} ref="iframe"/>
|
||||
<iframe src={renderer_url} onLoad={onIframeLoad} ref="iframe" />
|
||||
</div>
|
||||
</span>
|
||||
);
|
||||
|
@ -356,13 +356,12 @@ module.exports = React.createClass({
|
|||
</div>
|
||||
</span>
|
||||
);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return (
|
||||
<span className="mx_MFileBody">
|
||||
<div className="mx_MImageBody_download">
|
||||
<a href={contentUrl} download={fileName} target="_blank" rel="noopener">
|
||||
<img src={tintedDownloadImageURL} width="12" height="14" ref="downloadImage"/>
|
||||
<img src={tintedDownloadImageURL} width="12" height="14" ref="downloadImage" />
|
||||
{ _t("Download %(text)s", { text: text }) }
|
||||
</a>
|
||||
</div>
|
||||
|
@ -370,7 +369,7 @@ module.exports = React.createClass({
|
|||
);
|
||||
}
|
||||
} else {
|
||||
var extra = text ? (': ' + text) : '';
|
||||
const extra = text ? (': ' + text) : '';
|
||||
return <span className="mx_MFileBody">
|
||||
{ _t("Invalid file%(extra)s", { extra: extra }) }
|
||||
</span>;
|
||||
|
|
|
@ -191,8 +191,8 @@ module.exports = React.createClass({
|
|||
if (this.state.error !== null) {
|
||||
return (
|
||||
<span className="mx_MImageBody" ref="body">
|
||||
<img src="img/warning.svg" width="16" height="16"/>
|
||||
{_t("Error decrypting image")}
|
||||
<img src="img/warning.svg" width="16" height="16" />
|
||||
{ _t("Error decrypting image") }
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
@ -210,7 +210,7 @@ module.exports = React.createClass({
|
|||
}}>
|
||||
<img src="img/spinner.gif" alt={content.body} width="32" height="32" style={{
|
||||
"margin": "auto",
|
||||
}}/>
|
||||
}} />
|
||||
</div>
|
||||
</span>
|
||||
);
|
||||
|
@ -227,7 +227,7 @@ module.exports = React.createClass({
|
|||
if (thumbUrl) {
|
||||
return (
|
||||
<span className="mx_MImageBody" ref="body">
|
||||
<a href={contentUrl} onClick={ this.onClick }>
|
||||
<a href={contentUrl} onClick={this.onClick}>
|
||||
<img className="mx_MImageBody_thumbnail" src={thumbUrl} ref="image"
|
||||
alt={content.body}
|
||||
onMouseEnter={this.onImageEnter}
|
||||
|
@ -239,13 +239,13 @@ module.exports = React.createClass({
|
|||
} else if (content.body) {
|
||||
return (
|
||||
<span className="mx_MImageBody">
|
||||
{_t("Image '%(Body)s' cannot be displayed.", {Body: content.body})}
|
||||
{ _t("Image '%(Body)s' cannot be displayed.", {Body: content.body}) }
|
||||
</span>
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<span className="mx_MImageBody">
|
||||
{_t("This image cannot be displayed.")}
|
||||
{ _t("This image cannot be displayed.") }
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -54,13 +54,12 @@ module.exports = React.createClass({
|
|||
// no scaling needs to be applied
|
||||
return 1;
|
||||
}
|
||||
var widthMulti = thumbWidth / fullWidth;
|
||||
var heightMulti = thumbHeight / fullHeight;
|
||||
const widthMulti = thumbWidth / fullWidth;
|
||||
const heightMulti = thumbHeight / fullHeight;
|
||||
if (widthMulti < heightMulti) {
|
||||
// width is the dominant dimension so scaling will be fixed on that
|
||||
return widthMulti;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
// height is the dominant dimension so scaling will be fixed on that
|
||||
return heightMulti;
|
||||
}
|
||||
|
@ -89,15 +88,15 @@ module.exports = React.createClass({
|
|||
componentDidMount: function() {
|
||||
const content = this.props.mxEvent.getContent();
|
||||
if (content.file !== undefined && this.state.decryptedUrl === null) {
|
||||
var thumbnailPromise = Promise.resolve(null);
|
||||
let thumbnailPromise = Promise.resolve(null);
|
||||
if (content.info.thumbnail_file) {
|
||||
thumbnailPromise = decryptFile(
|
||||
content.info.thumbnail_file
|
||||
content.info.thumbnail_file,
|
||||
).then(function(blob) {
|
||||
return readBlobAsDataUri(blob);
|
||||
});
|
||||
}
|
||||
var decryptedBlob;
|
||||
let decryptedBlob;
|
||||
thumbnailPromise.then((thumbnailUrl) => {
|
||||
return decryptFile(content.file).then(function(blob) {
|
||||
decryptedBlob = blob;
|
||||
|
@ -126,8 +125,8 @@ module.exports = React.createClass({
|
|||
if (this.state.error !== null) {
|
||||
return (
|
||||
<span className="mx_MVideoBody" ref="body">
|
||||
<img src="img/warning.svg" width="16" height="16"/>
|
||||
{_t("Error decrypting video")}
|
||||
<img src="img/warning.svg" width="16" height="16" />
|
||||
{ _t("Error decrypting video") }
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
@ -144,7 +143,7 @@ module.exports = React.createClass({
|
|||
"justify-items": "center",
|
||||
"width": "100%",
|
||||
}}>
|
||||
<img src="img/spinner.gif" alt={content.body} width="16" height="16"/>
|
||||
<img src="img/spinner.gif" alt={content.body} width="16" height="16" />
|
||||
</div>
|
||||
</span>
|
||||
);
|
||||
|
|
|
@ -16,8 +16,8 @@ limitations under the License.
|
|||
|
||||
'use strict';
|
||||
|
||||
var React = require('react');
|
||||
var sdk = require('../../../index');
|
||||
const React = require('react');
|
||||
const sdk = require('../../../index');
|
||||
|
||||
module.exports = React.createClass({
|
||||
displayName: 'MessageEvent',
|
||||
|
@ -47,21 +47,21 @@ module.exports = React.createClass({
|
|||
},
|
||||
|
||||
render: function() {
|
||||
var UnknownBody = sdk.getComponent('messages.UnknownBody');
|
||||
const UnknownBody = sdk.getComponent('messages.UnknownBody');
|
||||
|
||||
var bodyTypes = {
|
||||
const bodyTypes = {
|
||||
'm.text': sdk.getComponent('messages.TextualBody'),
|
||||
'm.notice': sdk.getComponent('messages.TextualBody'),
|
||||
'm.emote': sdk.getComponent('messages.TextualBody'),
|
||||
'm.image': sdk.getComponent('messages.MImageBody'),
|
||||
'm.file': sdk.getComponent('messages.MFileBody'),
|
||||
'm.audio': sdk.getComponent('messages.MAudioBody'),
|
||||
'm.video': sdk.getComponent('messages.MVideoBody')
|
||||
'm.video': sdk.getComponent('messages.MVideoBody'),
|
||||
};
|
||||
|
||||
var content = this.props.mxEvent.getContent();
|
||||
var msgtype = content.msgtype;
|
||||
var BodyType = UnknownBody;
|
||||
const content = this.props.mxEvent.getContent();
|
||||
const msgtype = content.msgtype;
|
||||
let BodyType = UnknownBody;
|
||||
if (msgtype && bodyTypes[msgtype]) {
|
||||
BodyType = bodyTypes[msgtype];
|
||||
} else if (content.url) {
|
||||
|
|
|
@ -31,9 +31,9 @@ module.exports = React.createClass({
|
|||
},
|
||||
|
||||
onAvatarClick: function(name) {
|
||||
var httpUrl = MatrixClientPeg.get().mxcUrlToHttp(this.props.mxEvent.getContent().url);
|
||||
var ImageView = sdk.getComponent("elements.ImageView");
|
||||
var params = {
|
||||
const httpUrl = MatrixClientPeg.get().mxcUrlToHttp(this.props.mxEvent.getContent().url);
|
||||
const ImageView = sdk.getComponent("elements.ImageView");
|
||||
const params = {
|
||||
src: httpUrl,
|
||||
name: name,
|
||||
};
|
||||
|
@ -41,12 +41,12 @@ module.exports = React.createClass({
|
|||
},
|
||||
|
||||
render: function() {
|
||||
var ev = this.props.mxEvent;
|
||||
var senderDisplayName = ev.sender && ev.sender.name ? ev.sender.name : ev.getSender();
|
||||
var BaseAvatar = sdk.getComponent("avatars.BaseAvatar");
|
||||
const ev = this.props.mxEvent;
|
||||
const senderDisplayName = ev.sender && ev.sender.name ? ev.sender.name : ev.getSender();
|
||||
const BaseAvatar = sdk.getComponent("avatars.BaseAvatar");
|
||||
|
||||
var room = MatrixClientPeg.get().getRoom(this.props.mxEvent.getRoomId());
|
||||
var name = _t('%(senderDisplayName)s changed the avatar for %(roomName)s', {
|
||||
const room = MatrixClientPeg.get().getRoom(this.props.mxEvent.getRoomId());
|
||||
const name = _t('%(senderDisplayName)s changed the avatar for %(roomName)s', {
|
||||
senderDisplayName: senderDisplayName,
|
||||
roomName: room ? room.name : '',
|
||||
});
|
||||
|
@ -59,31 +59,31 @@ module.exports = React.createClass({
|
|||
);
|
||||
}
|
||||
|
||||
var url = ContentRepo.getHttpUriForMxc(
|
||||
const url = ContentRepo.getHttpUriForMxc(
|
||||
MatrixClientPeg.get().getHomeserverUrl(),
|
||||
ev.getContent().url,
|
||||
Math.ceil(14 * window.devicePixelRatio),
|
||||
Math.ceil(14 * window.devicePixelRatio),
|
||||
'crop'
|
||||
'crop',
|
||||
);
|
||||
|
||||
// it sucks that _tJsx doesn't support normal _t substitutions :((
|
||||
return (
|
||||
<div className="mx_RoomAvatarEvent">
|
||||
{ _tJsx('$senderDisplayName changed the room avatar to <img/>',
|
||||
{ _tJsx('%(senderDisplayName)s changed the room avatar to <img/>',
|
||||
[
|
||||
/\$senderDisplayName/,
|
||||
/%\(senderDisplayName\)s/,
|
||||
/<img\/>/,
|
||||
],
|
||||
[
|
||||
(sub) => senderDisplayName,
|
||||
(sub) =>
|
||||
<AccessibleButton key="avatar" className="mx_RoomAvatarEvent_avatar"
|
||||
onClick={ this.onAvatarClick.bind(this, name) }>
|
||||
<BaseAvatar width={14} height={14} url={ url }
|
||||
name={ name } />
|
||||
onClick={this.onAvatarClick.bind(this, name)}>
|
||||
<BaseAvatar width={14} height={14} url={url}
|
||||
name={name} />
|
||||
</AccessibleButton>,
|
||||
]
|
||||
],
|
||||
)
|
||||
}
|
||||
</div>
|
||||
|
|
|
@ -104,10 +104,10 @@ module.exports = React.createClass({
|
|||
if (this._unmounted) return;
|
||||
for (let i = 0; i < blocks.length; i++) {
|
||||
if (UserSettingsStore.getSyncedSetting("enableSyntaxHighlightLanguageDetection", false)) {
|
||||
highlight.highlightBlock(blocks[i])
|
||||
highlight.highlightBlock(blocks[i]);
|
||||
} else {
|
||||
// Only syntax highlight if there's a class starting with language-
|
||||
let classes = blocks[i].className.split(/\s+/).filter(function (cl) {
|
||||
const classes = blocks[i].className.split(/\s+/).filter(function(cl) {
|
||||
return cl.startsWith('language-');
|
||||
});
|
||||
|
||||
|
@ -146,7 +146,7 @@ module.exports = React.createClass({
|
|||
//console.log("calculateUrlPreview: ShowUrlPreview for %s is %s", this.props.mxEvent.getId(), this.props.showUrlPreview);
|
||||
|
||||
if (this.props.showUrlPreview && !this.state.links.length) {
|
||||
var links = this.findLinks(this.refs.content.children);
|
||||
let links = this.findLinks(this.refs.content.children);
|
||||
if (links.length) {
|
||||
// de-dup the links (but preserve ordering)
|
||||
const seen = new Set();
|
||||
|
@ -160,7 +160,7 @@ module.exports = React.createClass({
|
|||
|
||||
// lazy-load the hidden state of the preview widget from localstorage
|
||||
if (global.localStorage) {
|
||||
var hidden = global.localStorage.getItem("hide_preview_" + this.props.mxEvent.getId());
|
||||
const hidden = global.localStorage.getItem("hide_preview_" + this.props.mxEvent.getId());
|
||||
this.setState({ widgetHidden: hidden });
|
||||
}
|
||||
}
|
||||
|
@ -197,21 +197,18 @@ module.exports = React.createClass({
|
|||
},
|
||||
|
||||
findLinks: function(nodes) {
|
||||
var links = [];
|
||||
let links = [];
|
||||
|
||||
for (var i = 0; i < nodes.length; i++) {
|
||||
var node = nodes[i];
|
||||
if (node.tagName === "A" && node.getAttribute("href"))
|
||||
{
|
||||
for (let i = 0; i < nodes.length; i++) {
|
||||
const node = nodes[i];
|
||||
if (node.tagName === "A" && node.getAttribute("href")) {
|
||||
if (this.isLinkPreviewable(node)) {
|
||||
links.push(node.getAttribute("href"));
|
||||
}
|
||||
}
|
||||
else if (node.tagName === "PRE" || node.tagName === "CODE" ||
|
||||
} else if (node.tagName === "PRE" || node.tagName === "CODE" ||
|
||||
node.tagName === "BLOCKQUOTE") {
|
||||
continue;
|
||||
}
|
||||
else if (node.children && node.children.length) {
|
||||
} else if (node.children && node.children.length) {
|
||||
links = links.concat(this.findLinks(node.children));
|
||||
}
|
||||
}
|
||||
|
@ -221,8 +218,7 @@ module.exports = React.createClass({
|
|||
isLinkPreviewable: function(node) {
|
||||
// don't try to preview relative links
|
||||
if (!node.getAttribute("href").startsWith("http://") &&
|
||||
!node.getAttribute("href").startsWith("https://"))
|
||||
{
|
||||
!node.getAttribute("href").startsWith("https://")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -231,13 +227,11 @@ module.exports = React.createClass({
|
|||
// or from a full foo.bar/baz style schemeless URL) - or be a markdown-style
|
||||
// link, in which case we check the target text differs from the link value.
|
||||
// TODO: make this configurable?
|
||||
if (node.textContent.indexOf("/") > -1)
|
||||
{
|
||||
if (node.textContent.indexOf("/") > -1) {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
var url = node.getAttribute("href");
|
||||
var host = url.match(/^https?:\/\/(.*?)(\/|$)/)[1];
|
||||
} else {
|
||||
const url = node.getAttribute("href");
|
||||
const host = url.match(/^https?:\/\/(.*?)(\/|$)/)[1];
|
||||
|
||||
// never preview matrix.to links (if anything we should give a smart
|
||||
// preview of the room/user they point to: nobody needs to be reminded
|
||||
|
@ -247,8 +241,7 @@ module.exports = React.createClass({
|
|||
if (node.textContent.toLowerCase().trim().startsWith(host.toLowerCase())) {
|
||||
// it's a "foo.pl" style link
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
// it's a [foo bar](http://foo.com) style link
|
||||
return true;
|
||||
}
|
||||
|
@ -263,7 +256,7 @@ module.exports = React.createClass({
|
|||
button.onclick = (e) => {
|
||||
const copyCode = button.parentNode.getElementsByTagName("code")[0];
|
||||
const successful = this.copyToClipboard(copyCode.textContent);
|
||||
|
||||
|
||||
const GenericTextContextMenu = sdk.getComponent('context_menus.GenericTextContextMenu');
|
||||
const buttonRect = e.target.getBoundingClientRect();
|
||||
|
||||
|
@ -314,7 +307,7 @@ module.exports = React.createClass({
|
|||
|
||||
getInnerText: () => {
|
||||
return this.refs.content.innerText;
|
||||
}
|
||||
},
|
||||
};
|
||||
},
|
||||
|
||||
|
@ -328,28 +321,28 @@ module.exports = React.createClass({
|
|||
// the window.open command occurs in the same stack frame as the onClick callback.
|
||||
|
||||
// Go fetch a scalar token
|
||||
let scalarClient = new ScalarAuthClient();
|
||||
const scalarClient = new ScalarAuthClient();
|
||||
scalarClient.connect().then(() => {
|
||||
let completeUrl = scalarClient.getStarterLink(starterLink);
|
||||
let QuestionDialog = sdk.getComponent("dialogs.QuestionDialog");
|
||||
let integrationsUrl = SdkConfig.get().integrations_ui_url;
|
||||
const completeUrl = scalarClient.getStarterLink(starterLink);
|
||||
const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog");
|
||||
const integrationsUrl = SdkConfig.get().integrations_ui_url;
|
||||
Modal.createTrackedDialog('Add an integration', '', QuestionDialog, {
|
||||
title: _t("Add an Integration"),
|
||||
description:
|
||||
<div>
|
||||
{_t("You are about to be taken to a third-party site so you can " +
|
||||
{ _t("You are about to be taken to a third-party site so you can " +
|
||||
"authenticate your account for use with %(integrationsUrl)s. " +
|
||||
"Do you wish to continue?", { integrationsUrl: integrationsUrl })}
|
||||
"Do you wish to continue?", { integrationsUrl: integrationsUrl }) }
|
||||
</div>,
|
||||
button: _t("Continue"),
|
||||
onFinished: function(confirmed) {
|
||||
if (!confirmed) {
|
||||
return;
|
||||
}
|
||||
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;
|
||||
const width = window.screen.width > 1024 ? 1024 : window.screen.width;
|
||||
const height = window.screen.height > 800 ? 800 : window.screen.height;
|
||||
const left = (window.screen.width - width) / 2;
|
||||
const top = (window.screen.height - height) / 2;
|
||||
window.open(completeUrl, '_blank', `height=${height}, width=${width}, top=${top}, left=${left},`);
|
||||
},
|
||||
});
|
||||
|
@ -358,28 +351,29 @@ module.exports = React.createClass({
|
|||
|
||||
render: function() {
|
||||
const EmojiText = sdk.getComponent('elements.EmojiText');
|
||||
var mxEvent = this.props.mxEvent;
|
||||
var content = mxEvent.getContent();
|
||||
const mxEvent = this.props.mxEvent;
|
||||
const content = mxEvent.getContent();
|
||||
|
||||
var body = HtmlUtils.bodyToHtml(content, this.props.highlights, {});
|
||||
let body = HtmlUtils.bodyToHtml(content, this.props.highlights, {
|
||||
disableBigEmoji: UserSettingsStore.getSyncedSetting('TextualBody.disableBigEmoji', false),
|
||||
});
|
||||
|
||||
if (this.props.highlightLink) {
|
||||
body = <a href={ this.props.highlightLink }>{ body }</a>;
|
||||
}
|
||||
else if (content.data && typeof content.data["org.matrix.neb.starter_link"] === "string") {
|
||||
body = <a href="#" onClick={ this.onStarterLinkClick.bind(this, content.data["org.matrix.neb.starter_link"]) }>{ body }</a>;
|
||||
body = <a href={this.props.highlightLink}>{ body }</a>;
|
||||
} else if (content.data && typeof content.data["org.matrix.neb.starter_link"] === "string") {
|
||||
body = <a href="#" onClick={this.onStarterLinkClick.bind(this, content.data["org.matrix.neb.starter_link"])}>{ body }</a>;
|
||||
}
|
||||
|
||||
var widgets;
|
||||
let widgets;
|
||||
if (this.state.links.length && !this.state.widgetHidden && this.props.showUrlPreview) {
|
||||
var LinkPreviewWidget = sdk.getComponent('rooms.LinkPreviewWidget');
|
||||
const LinkPreviewWidget = sdk.getComponent('rooms.LinkPreviewWidget');
|
||||
widgets = this.state.links.map((link)=>{
|
||||
return <LinkPreviewWidget
|
||||
key={ link }
|
||||
link={ link }
|
||||
mxEvent={ this.props.mxEvent }
|
||||
onCancelClick={ this.onCancelClick }
|
||||
onWidgetLoad={ this.props.onWidgetLoad }/>;
|
||||
key={link}
|
||||
link={link}
|
||||
mxEvent={this.props.mxEvent}
|
||||
onCancelClick={this.onCancelClick}
|
||||
onWidgetLoad={this.props.onWidgetLoad} />;
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -393,7 +387,7 @@ module.exports = React.createClass({
|
|||
className="mx_MEmoteBody_sender"
|
||||
onClick={this.onEmoteSenderClick}
|
||||
>
|
||||
{name}
|
||||
{ name }
|
||||
</EmojiText>
|
||||
|
||||
{ body }
|
||||
|
|
|
@ -16,9 +16,9 @@ limitations under the License.
|
|||
|
||||
'use strict';
|
||||
|
||||
var React = require('react');
|
||||
const React = require('react');
|
||||
|
||||
var TextForEvent = require('../../../TextForEvent');
|
||||
const TextForEvent = require('../../../TextForEvent');
|
||||
import sdk from '../../../index';
|
||||
|
||||
module.exports = React.createClass({
|
||||
|
@ -28,13 +28,13 @@ module.exports = React.createClass({
|
|||
/* the MatrixEvent to show */
|
||||
mxEvent: React.PropTypes.object.isRequired,
|
||||
},
|
||||
|
||||
|
||||
render: function() {
|
||||
const EmojiText = sdk.getComponent('elements.EmojiText');
|
||||
var text = TextForEvent.textForEvent(this.props.mxEvent);
|
||||
const text = TextForEvent.textForEvent(this.props.mxEvent);
|
||||
if (text == null || text.length === 0) return null;
|
||||
return (
|
||||
<EmojiText element="div" className="mx_TextualEvent">{text}</EmojiText>
|
||||
<EmojiText element="div" className="mx_TextualEvent">{ text }</EmojiText>
|
||||
);
|
||||
},
|
||||
});
|
||||
|
|
|
@ -15,12 +15,12 @@ limitations under the License.
|
|||
*/
|
||||
|
||||
import Promise from 'bluebird';
|
||||
var React = require('react');
|
||||
var ObjectUtils = require("../../../ObjectUtils");
|
||||
var MatrixClientPeg = require('../../../MatrixClientPeg');
|
||||
var sdk = require("../../../index");
|
||||
const React = require('react');
|
||||
const ObjectUtils = require("../../../ObjectUtils");
|
||||
const MatrixClientPeg = require('../../../MatrixClientPeg');
|
||||
const sdk = require("../../../index");
|
||||
import { _t } from '../../../languageHandler';
|
||||
var Modal = require("../../../Modal");
|
||||
const Modal = require("../../../Modal");
|
||||
|
||||
module.exports = React.createClass({
|
||||
displayName: 'AliasSettings',
|
||||
|
@ -30,14 +30,14 @@ module.exports = React.createClass({
|
|||
canSetCanonicalAlias: React.PropTypes.bool.isRequired,
|
||||
canSetAliases: React.PropTypes.bool.isRequired,
|
||||
aliasEvents: React.PropTypes.array, // [MatrixEvent]
|
||||
canonicalAliasEvent: React.PropTypes.object // MatrixEvent
|
||||
canonicalAliasEvent: React.PropTypes.object, // MatrixEvent
|
||||
},
|
||||
|
||||
getDefaultProps: function() {
|
||||
return {
|
||||
canSetAliases: false,
|
||||
canSetCanonicalAlias: false,
|
||||
aliasEvents: []
|
||||
aliasEvents: [],
|
||||
};
|
||||
},
|
||||
|
||||
|
@ -48,12 +48,12 @@ module.exports = React.createClass({
|
|||
recalculateState: function(aliasEvents, canonicalAliasEvent) {
|
||||
aliasEvents = aliasEvents || [];
|
||||
|
||||
var state = {
|
||||
const state = {
|
||||
domainToAliases: {}, // { domain.com => [#alias1:domain.com, #alias2:domain.com] }
|
||||
remoteDomains: [], // [ domain.com, foobar.com ]
|
||||
canonicalAlias: null // #canonical:domain.com
|
||||
canonicalAlias: null, // #canonical:domain.com
|
||||
};
|
||||
var localDomain = MatrixClientPeg.get().getDomain();
|
||||
const localDomain = MatrixClientPeg.get().getDomain();
|
||||
|
||||
state.domainToAliases = this.aliasEventsToDictionary(aliasEvents);
|
||||
|
||||
|
@ -69,26 +69,26 @@ module.exports = React.createClass({
|
|||
},
|
||||
|
||||
saveSettings: function() {
|
||||
var promises = [];
|
||||
let promises = [];
|
||||
|
||||
// save new aliases for m.room.aliases
|
||||
var aliasOperations = this.getAliasOperations();
|
||||
for (var i = 0; i < aliasOperations.length; i++) {
|
||||
var alias_operation = aliasOperations[i];
|
||||
const aliasOperations = this.getAliasOperations();
|
||||
for (let i = 0; i < aliasOperations.length; i++) {
|
||||
const alias_operation = aliasOperations[i];
|
||||
console.log("alias %s %s", alias_operation.place, alias_operation.val);
|
||||
switch (alias_operation.place) {
|
||||
case 'add':
|
||||
promises.push(
|
||||
MatrixClientPeg.get().createAlias(
|
||||
alias_operation.val, this.props.roomId
|
||||
)
|
||||
alias_operation.val, this.props.roomId,
|
||||
),
|
||||
);
|
||||
break;
|
||||
case 'del':
|
||||
promises.push(
|
||||
MatrixClientPeg.get().deleteAlias(
|
||||
alias_operation.val
|
||||
)
|
||||
alias_operation.val,
|
||||
),
|
||||
);
|
||||
break;
|
||||
default:
|
||||
|
@ -98,7 +98,7 @@ module.exports = React.createClass({
|
|||
|
||||
|
||||
// save new canonical alias
|
||||
var oldCanonicalAlias = null;
|
||||
let oldCanonicalAlias = null;
|
||||
if (this.props.canonicalAliasEvent) {
|
||||
oldCanonicalAlias = this.props.canonicalAliasEvent.getContent().alias;
|
||||
}
|
||||
|
@ -107,9 +107,9 @@ module.exports = React.createClass({
|
|||
promises = [Promise.all(promises).then(
|
||||
MatrixClientPeg.get().sendStateEvent(
|
||||
this.props.roomId, "m.room.canonical_alias", {
|
||||
alias: this.state.canonicalAlias
|
||||
}, ""
|
||||
)
|
||||
alias: this.state.canonicalAlias,
|
||||
}, "",
|
||||
),
|
||||
)];
|
||||
}
|
||||
|
||||
|
@ -117,7 +117,7 @@ module.exports = React.createClass({
|
|||
},
|
||||
|
||||
aliasEventsToDictionary: function(aliasEvents) { // m.room.alias events
|
||||
var dict = {};
|
||||
const dict = {};
|
||||
aliasEvents.forEach((event) => {
|
||||
dict[event.getStateKey()] = (
|
||||
(event.getContent().aliases || []).slice() // shallow-copy
|
||||
|
@ -132,7 +132,7 @@ module.exports = React.createClass({
|
|||
},
|
||||
|
||||
getAliasOperations: function() {
|
||||
var oldAliases = this.aliasEventsToDictionary(this.props.aliasEvents);
|
||||
const oldAliases = this.aliasEventsToDictionary(this.props.aliasEvents);
|
||||
return ObjectUtils.getKeyValueArrayDiffs(oldAliases, this.state.domainToAliases);
|
||||
},
|
||||
|
||||
|
@ -191,26 +191,26 @@ module.exports = React.createClass({
|
|||
|
||||
onCanonicalAliasChange: function(event) {
|
||||
this.setState({
|
||||
canonicalAlias: event.target.value
|
||||
canonicalAlias: event.target.value,
|
||||
});
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var self = this;
|
||||
var EditableText = sdk.getComponent("elements.EditableText");
|
||||
var EditableItemList = sdk.getComponent("elements.EditableItemList");
|
||||
var localDomain = MatrixClientPeg.get().getDomain();
|
||||
const self = this;
|
||||
const EditableText = sdk.getComponent("elements.EditableText");
|
||||
const EditableItemList = sdk.getComponent("elements.EditableItemList");
|
||||
const localDomain = MatrixClientPeg.get().getDomain();
|
||||
|
||||
var canonical_alias_section;
|
||||
let canonical_alias_section;
|
||||
if (this.props.canSetCanonicalAlias) {
|
||||
canonical_alias_section = (
|
||||
<select onChange={this.onCanonicalAliasChange} defaultValue={ this.state.canonicalAlias }>
|
||||
<select onChange={this.onCanonicalAliasChange} defaultValue={this.state.canonicalAlias}>
|
||||
<option value="" key="unset">{ _t('not specified') }</option>
|
||||
{
|
||||
Object.keys(self.state.domainToAliases).map(function(domain, i) {
|
||||
return self.state.domainToAliases[domain].map(function(alias, j) {
|
||||
return (
|
||||
<option value={ alias } key={ i + "_" + j }>
|
||||
<option value={alias} key={i + "_" + j}>
|
||||
{ alias }
|
||||
</option>
|
||||
);
|
||||
|
@ -219,34 +219,33 @@ module.exports = React.createClass({
|
|||
}
|
||||
</select>
|
||||
);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
canonical_alias_section = (
|
||||
<b>{ this.state.canonicalAlias || _t('not set') }</b>
|
||||
);
|
||||
}
|
||||
|
||||
var remote_aliases_section;
|
||||
let remote_aliases_section;
|
||||
if (this.state.remoteDomains.length) {
|
||||
remote_aliases_section = (
|
||||
<div>
|
||||
<div className="mx_RoomSettings_aliasLabel">
|
||||
{_t("Remote addresses for this room:")}
|
||||
{ _t("Remote addresses for this room:") }
|
||||
</div>
|
||||
<div className="mx_RoomSettings_aliasesTable">
|
||||
{ this.state.remoteDomains.map((domain, i) => {
|
||||
return this.state.domainToAliases[domain].map(function(alias, j) {
|
||||
return (
|
||||
<div className="mx_RoomSettings_aliasesTableRow" key={ i + "_" + j }>
|
||||
<div className="mx_RoomSettings_aliasesTableRow" key={i + "_" + j}>
|
||||
<EditableText
|
||||
className="mx_RoomSettings_alias mx_RoomSettings_editable"
|
||||
blurToCancel={ false }
|
||||
editable={ false }
|
||||
initialValue={ alias } />
|
||||
blurToCancel={false}
|
||||
editable={false}
|
||||
initialValue={alias} />
|
||||
</div>
|
||||
);
|
||||
});
|
||||
})}
|
||||
}) }
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -14,16 +14,16 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
import Promise from 'bluebird';
|
||||
var React = require('react');
|
||||
const React = require('react');
|
||||
|
||||
var sdk = require('../../../index');
|
||||
var Tinter = require('../../../Tinter');
|
||||
var MatrixClientPeg = require("../../../MatrixClientPeg");
|
||||
var Modal = require("../../../Modal");
|
||||
const sdk = require('../../../index');
|
||||
const Tinter = require('../../../Tinter');
|
||||
const MatrixClientPeg = require("../../../MatrixClientPeg");
|
||||
const Modal = require("../../../Modal");
|
||||
|
||||
import dis from '../../../dispatcher';
|
||||
|
||||
var ROOM_COLORS = [
|
||||
const ROOM_COLORS = [
|
||||
// magic room default values courtesy of Ribot
|
||||
["#76cfa6", "#eaf5f0"],
|
||||
["#81bddb", "#eaf1f4"],
|
||||
|
@ -34,28 +34,28 @@ var ROOM_COLORS = [
|
|||
["#dad658", "#f5f4ea"],
|
||||
["#80c553", "#eef5ea"],
|
||||
["#bb814e", "#eee8e3"],
|
||||
["#595959", "#ececec"],
|
||||
//["#595959", "#ececec"], // Grey makes everything appear disabled, so remove it for now
|
||||
];
|
||||
|
||||
module.exports = React.createClass({
|
||||
displayName: 'ColorSettings',
|
||||
|
||||
propTypes: {
|
||||
room: React.PropTypes.object.isRequired
|
||||
room: React.PropTypes.object.isRequired,
|
||||
},
|
||||
|
||||
getInitialState: function() {
|
||||
var data = {
|
||||
const data = {
|
||||
index: 0,
|
||||
primary_color: ROOM_COLORS[0].primary_color,
|
||||
secondary_color: ROOM_COLORS[0].secondary_color,
|
||||
hasChanged: false
|
||||
hasChanged: false,
|
||||
};
|
||||
var event = this.props.room.getAccountData("org.matrix.room.color_scheme");
|
||||
const event = this.props.room.getAccountData("org.matrix.room.color_scheme");
|
||||
if (!event) {
|
||||
return data;
|
||||
}
|
||||
var scheme = event.getContent();
|
||||
const scheme = event.getContent();
|
||||
data.primary_color = scheme.primary_color;
|
||||
data.secondary_color = scheme.secondary_color;
|
||||
data.index = this._getColorIndex(data);
|
||||
|
@ -64,7 +64,7 @@ module.exports = React.createClass({
|
|||
// append the unrecognised colours to our palette
|
||||
data.index = ROOM_COLORS.length;
|
||||
ROOM_COLORS.push([
|
||||
scheme.primary_color, scheme.secondary_color
|
||||
scheme.primary_color, scheme.secondary_color,
|
||||
]);
|
||||
}
|
||||
return data;
|
||||
|
@ -74,7 +74,7 @@ module.exports = React.createClass({
|
|||
if (!this.state.hasChanged) {
|
||||
return Promise.resolve(); // They didn't explicitly give a color to save.
|
||||
}
|
||||
var originalState = this.getInitialState();
|
||||
const originalState = this.getInitialState();
|
||||
if (originalState.primary_color !== this.state.primary_color ||
|
||||
originalState.secondary_color !== this.state.secondary_color) {
|
||||
console.log("ColorSettings: Saving new color");
|
||||
|
@ -84,8 +84,8 @@ module.exports = React.createClass({
|
|||
return MatrixClientPeg.get().setRoomAccountData(
|
||||
this.props.room.roomId, "org.matrix.room.color_scheme", {
|
||||
primary_color: this.state.primary_color,
|
||||
secondary_color: this.state.secondary_color
|
||||
}
|
||||
secondary_color: this.state.secondary_color,
|
||||
},
|
||||
).catch(function(err) {
|
||||
if (err.errcode == 'M_GUEST_ACCESS_FORBIDDEN') {
|
||||
dis.dispatch({action: 'view_set_mxid'});
|
||||
|
@ -100,8 +100,8 @@ module.exports = React.createClass({
|
|||
return -1;
|
||||
}
|
||||
// XXX: we should validate these values
|
||||
for (var i = 0; i < ROOM_COLORS.length; i++) {
|
||||
var room_color = ROOM_COLORS[i];
|
||||
for (let i = 0; i < ROOM_COLORS.length; i++) {
|
||||
const room_color = ROOM_COLORS[i];
|
||||
if (room_color[0] === String(scheme.primary_color).toLowerCase() &&
|
||||
room_color[1] === String(scheme.secondary_color).toLowerCase()) {
|
||||
return i;
|
||||
|
@ -117,34 +117,34 @@ module.exports = React.createClass({
|
|||
index: index,
|
||||
primary_color: ROOM_COLORS[index][0],
|
||||
secondary_color: ROOM_COLORS[index][1],
|
||||
hasChanged: true
|
||||
hasChanged: true,
|
||||
});
|
||||
},
|
||||
|
||||
render: function() {
|
||||
return (
|
||||
<div className="mx_RoomSettings_roomColors">
|
||||
{ROOM_COLORS.map((room_color, i) => {
|
||||
var selected;
|
||||
{ ROOM_COLORS.map((room_color, i) => {
|
||||
let selected;
|
||||
if (i === this.state.index) {
|
||||
selected = (
|
||||
<div className="mx_RoomSettings_roomColor_selected">
|
||||
<img src="img/tick.svg" width="17" height="14" alt="./"/>
|
||||
<img src="img/tick.svg" width="17" height="14" alt="./" />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
var boundClick = this._onColorSchemeChanged.bind(this, i);
|
||||
const boundClick = this._onColorSchemeChanged.bind(this, i);
|
||||
return (
|
||||
<div className="mx_RoomSettings_roomColor"
|
||||
key={ "room_color_" + i }
|
||||
key={"room_color_" + i}
|
||||
style={{ backgroundColor: room_color[1] }}
|
||||
onClick={ boundClick }>
|
||||
onClick={boundClick}>
|
||||
{ selected }
|
||||
<div className="mx_RoomSettings_roomColorPrimary" style={{ backgroundColor: room_color[0] }}></div>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
}) }
|
||||
</div>
|
||||
);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
|
|
@ -15,11 +15,11 @@ limitations under the License.
|
|||
*/
|
||||
|
||||
import Promise from 'bluebird';
|
||||
var React = require('react');
|
||||
var MatrixClientPeg = require('../../../MatrixClientPeg');
|
||||
var sdk = require("../../../index");
|
||||
var Modal = require("../../../Modal");
|
||||
var UserSettingsStore = require('../../../UserSettingsStore');
|
||||
const React = require('react');
|
||||
const MatrixClientPeg = require('../../../MatrixClientPeg');
|
||||
const sdk = require("../../../index");
|
||||
const Modal = require("../../../Modal");
|
||||
const UserSettingsStore = require('../../../UserSettingsStore');
|
||||
import { _t, _tJsx } from '../../../languageHandler';
|
||||
|
||||
|
||||
|
@ -31,11 +31,11 @@ module.exports = React.createClass({
|
|||
},
|
||||
|
||||
getInitialState: function() {
|
||||
var cli = MatrixClientPeg.get();
|
||||
var roomState = this.props.room.currentState;
|
||||
const cli = MatrixClientPeg.get();
|
||||
const roomState = this.props.room.currentState;
|
||||
|
||||
var roomPreviewUrls = this.props.room.currentState.getStateEvents('org.matrix.room.preview_urls', '');
|
||||
var userPreviewUrls = this.props.room.getAccountData("org.matrix.room.preview_urls");
|
||||
const roomPreviewUrls = this.props.room.currentState.getStateEvents('org.matrix.room.preview_urls', '');
|
||||
const userPreviewUrls = this.props.room.getAccountData("org.matrix.room.preview_urls");
|
||||
|
||||
return {
|
||||
globalDisableUrlPreview: (roomPreviewUrls && roomPreviewUrls.getContent().disable) || false,
|
||||
|
@ -49,37 +49,37 @@ module.exports = React.createClass({
|
|||
},
|
||||
|
||||
saveSettings: function() {
|
||||
var promises = [];
|
||||
const promises = [];
|
||||
|
||||
if (this.state.globalDisableUrlPreview !== this.originalState.globalDisableUrlPreview) {
|
||||
console.log("UrlPreviewSettings: Updating room's preview_urls state event");
|
||||
promises.push(
|
||||
MatrixClientPeg.get().sendStateEvent(
|
||||
this.props.room.roomId, "org.matrix.room.preview_urls", {
|
||||
disable: this.state.globalDisableUrlPreview
|
||||
}, ""
|
||||
)
|
||||
disable: this.state.globalDisableUrlPreview,
|
||||
}, "",
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
var content = undefined;
|
||||
let content = undefined;
|
||||
if (this.state.userDisableUrlPreview !== this.originalState.userDisableUrlPreview) {
|
||||
console.log("UrlPreviewSettings: Disabling user's per-room preview_urls");
|
||||
content = this.state.userDisableUrlPreview ? { disable : true } : {};
|
||||
content = this.state.userDisableUrlPreview ? { disable: true } : {};
|
||||
}
|
||||
|
||||
if (this.state.userEnableUrlPreview !== this.originalState.userEnableUrlPreview) {
|
||||
console.log("UrlPreviewSettings: Enabling user's per-room preview_urls");
|
||||
if (!content || content.disable === undefined) {
|
||||
content = this.state.userEnableUrlPreview ? { disable : false } : {};
|
||||
content = this.state.userEnableUrlPreview ? { disable: false } : {};
|
||||
}
|
||||
}
|
||||
|
||||
if (content) {
|
||||
promises.push(
|
||||
MatrixClientPeg.get().setRoomAccountData(
|
||||
this.props.room.roomId, "org.matrix.room.preview_urls", content
|
||||
)
|
||||
this.props.room.roomId, "org.matrix.room.preview_urls", content,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -109,62 +109,59 @@ module.exports = React.createClass({
|
|||
},
|
||||
|
||||
render: function() {
|
||||
var self = this;
|
||||
var roomState = this.props.room.currentState;
|
||||
var cli = MatrixClientPeg.get();
|
||||
const self = this;
|
||||
const roomState = this.props.room.currentState;
|
||||
const cli = MatrixClientPeg.get();
|
||||
|
||||
var maySetRoomPreviewUrls = roomState.mayClientSendStateEvent('org.matrix.room.preview_urls', cli);
|
||||
var disableRoomPreviewUrls;
|
||||
const maySetRoomPreviewUrls = roomState.mayClientSendStateEvent('org.matrix.room.preview_urls', cli);
|
||||
let disableRoomPreviewUrls;
|
||||
if (maySetRoomPreviewUrls) {
|
||||
disableRoomPreviewUrls =
|
||||
<label>
|
||||
<input type="checkbox" ref="globalDisableUrlPreview"
|
||||
onChange={ this.onGlobalDisableUrlPreviewChange }
|
||||
checked={ this.state.globalDisableUrlPreview } />
|
||||
{_t("Disable URL previews by default for participants in this room")}
|
||||
onChange={this.onGlobalDisableUrlPreviewChange}
|
||||
checked={this.state.globalDisableUrlPreview} />
|
||||
{ _t("Disable URL previews by default for participants in this room") }
|
||||
</label>;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
disableRoomPreviewUrls =
|
||||
<label>
|
||||
{_t("URL previews are %(globalDisableUrlPreview)s by default for participants in this room.", {globalDisableUrlPreview: this.state.globalDisableUrlPreview ? _t("disabled") : _t("enabled")})}
|
||||
{ _t("URL previews are %(globalDisableUrlPreview)s by default for participants in this room.", {globalDisableUrlPreview: this.state.globalDisableUrlPreview ? _t("disabled") : _t("enabled")}) }
|
||||
</label>;
|
||||
}
|
||||
|
||||
let urlPreviewText = null;
|
||||
if (UserSettingsStore.getUrlPreviewsDisabled()) {
|
||||
urlPreviewText = (
|
||||
_tJsx("You have <a>disabled</a> URL previews by default.", /<a>(.*?)<\/a>/, (sub)=><a href="#/settings">{sub}</a>)
|
||||
_tJsx("You have <a>disabled</a> URL previews by default.", /<a>(.*?)<\/a>/, (sub)=><a href="#/settings">{ sub }</a>)
|
||||
);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
urlPreviewText = (
|
||||
_tJsx("You have <a>enabled</a> URL previews by default.", /<a>(.*?)<\/a>/, (sub)=><a href="#/settings">{sub}</a>)
|
||||
_tJsx("You have <a>enabled</a> URL previews by default.", /<a>(.*?)<\/a>/, (sub)=><a href="#/settings">{ sub }</a>)
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="mx_RoomSettings_toggles">
|
||||
<h3>{_t("URL Previews")}</h3>
|
||||
<h3>{ _t("URL Previews") }</h3>
|
||||
|
||||
<label>
|
||||
{urlPreviewText}
|
||||
{ urlPreviewText }
|
||||
</label>
|
||||
{ disableRoomPreviewUrls }
|
||||
<label>
|
||||
<input type="checkbox" ref="userEnableUrlPreview"
|
||||
onChange={ this.onUserEnableUrlPreviewChange }
|
||||
checked={ this.state.userEnableUrlPreview } />
|
||||
{_t("Enable URL previews for this room (affects only you)")}
|
||||
onChange={this.onUserEnableUrlPreviewChange}
|
||||
checked={this.state.userEnableUrlPreview} />
|
||||
{ _t("Enable URL previews for this room (affects only you)") }
|
||||
</label>
|
||||
<label>
|
||||
<input type="checkbox" ref="userDisableUrlPreview"
|
||||
onChange={ this.onUserDisableUrlPreviewChange }
|
||||
checked={ this.state.userDisableUrlPreview } />
|
||||
{_t("Disable URL previews for this room (affects only you)")}
|
||||
onChange={this.onUserDisableUrlPreviewChange}
|
||||
checked={this.state.userDisableUrlPreview} />
|
||||
{ _t("Disable URL previews for this room (affects only you)") }
|
||||
</label>
|
||||
</div>
|
||||
);
|
||||
|
||||
}
|
||||
},
|
||||
});
|
||||
|
|
|
@ -233,7 +233,7 @@ export default class Autocomplete extends React.Component {
|
|||
const componentPosition = position;
|
||||
position++;
|
||||
|
||||
const onMouseOver = () => this.setSelection(componentPosition);
|
||||
const onMouseMove = () => this.setSelection(componentPosition);
|
||||
const onClick = () => {
|
||||
this.setSelection(componentPosition);
|
||||
this.onCompletionClicked();
|
||||
|
@ -243,7 +243,7 @@ export default class Autocomplete extends React.Component {
|
|||
key: i,
|
||||
ref: `completion${position - 1}`,
|
||||
className,
|
||||
onMouseOver,
|
||||
onMouseMove,
|
||||
onClick,
|
||||
});
|
||||
});
|
||||
|
@ -251,15 +251,15 @@ export default class Autocomplete extends React.Component {
|
|||
|
||||
return completions.length > 0 ? (
|
||||
<div key={i} className="mx_Autocomplete_ProviderSection">
|
||||
<EmojiText element="div" className="mx_Autocomplete_provider_name">{completionResult.provider.getName()}</EmojiText>
|
||||
{completionResult.provider.renderCompletions(completions)}
|
||||
<EmojiText element="div" className="mx_Autocomplete_provider_name">{ completionResult.provider.getName() }</EmojiText>
|
||||
{ completionResult.provider.renderCompletions(completions) }
|
||||
</div>
|
||||
) : null;
|
||||
}).filter((completion) => !!completion);
|
||||
|
||||
return !this.state.hide && renderedCompletions.length > 0 ? (
|
||||
<div className="mx_Autocomplete" ref={(e) => this.container = e}>
|
||||
{renderedCompletions}
|
||||
{ renderedCompletions }
|
||||
</div>
|
||||
) : null;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
Copyright 2015, 2016 OpenMarket Ltd
|
||||
Copyright 2017 New Vector Ltd
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
@ -83,9 +84,9 @@ module.exports = React.createClass({
|
|||
<div className="mx_RoomView_fileDropTarget">
|
||||
<div className="mx_RoomView_fileDropTargetLabel"
|
||||
title={_t("Drop File Here")}>
|
||||
<TintableSvg src="img/upload-big.svg" width="45" height="59"/>
|
||||
<br/>
|
||||
{_t("Drop file here to upload")}
|
||||
<TintableSvg src="img/upload-big.svg" width="45" height="59" />
|
||||
<br />
|
||||
{ _t("Drop file here to upload") }
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
@ -99,23 +100,23 @@ module.exports = React.createClass({
|
|||
supportedText = _t(" (unsupported)");
|
||||
} else {
|
||||
joinNode = (<span>
|
||||
{_tJsx(
|
||||
{ _tJsx(
|
||||
"Join as <voiceText>voice</voiceText> or <videoText>video</videoText>.",
|
||||
[/<voiceText>(.*?)<\/voiceText>/, /<videoText>(.*?)<\/videoText>/],
|
||||
[
|
||||
(sub) => <a onClick={(event)=>{ this.onConferenceNotificationClick(event, 'voice');}} href="#">{sub}</a>,
|
||||
(sub) => <a onClick={(event)=>{ this.onConferenceNotificationClick(event, 'video');}} href="#">{sub}</a>,
|
||||
]
|
||||
)}
|
||||
(sub) => <a onClick={(event)=>{ this.onConferenceNotificationClick(event, 'voice');}} href="#">{ sub }</a>,
|
||||
(sub) => <a onClick={(event)=>{ this.onConferenceNotificationClick(event, 'video');}} href="#">{ sub }</a>,
|
||||
],
|
||||
) }
|
||||
</span>);
|
||||
}
|
||||
// XXX: the translation here isn't great: appending ' (unsupported)' is likely to not make sense in many languages,
|
||||
// but there are translations for this in the languages we do have so I'm leaving it for now.
|
||||
conferenceCallNotification = (
|
||||
<div className="mx_RoomView_ongoingConfCallNotification">
|
||||
{_t("Ongoing conference call%(supportedText)s.", {supportedText: supportedText})}
|
||||
{ _t("Ongoing conference call%(supportedText)s.", {supportedText: supportedText}) }
|
||||
|
||||
{joinNode}
|
||||
{ joinNode }
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -128,15 +129,12 @@ module.exports = React.createClass({
|
|||
/>
|
||||
);
|
||||
|
||||
let appsDrawer = null;
|
||||
if(UserSettingsStore.isFeatureEnabled('matrix_apps')) {
|
||||
appsDrawer = <AppsDrawer ref="appsDrawer"
|
||||
room={this.props.room}
|
||||
userId={this.props.userId}
|
||||
maxHeight={this.props.maxHeight}
|
||||
showApps={this.props.showApps}
|
||||
/>;
|
||||
}
|
||||
const appsDrawer = <AppsDrawer ref="appsDrawer"
|
||||
room={this.props.room}
|
||||
userId={this.props.userId}
|
||||
maxHeight={this.props.maxHeight}
|
||||
showApps={this.props.showApps}
|
||||
/>;
|
||||
|
||||
return (
|
||||
<div className="mx_RoomView_auxPanel" style={{maxHeight: this.props.maxHeight}} >
|
||||
|
|
|
@ -16,18 +16,18 @@ limitations under the License.
|
|||
|
||||
'use strict';
|
||||
|
||||
var React = require('react');
|
||||
const React = require('react');
|
||||
|
||||
var MatrixClientPeg = require('../../../MatrixClientPeg');
|
||||
var sdk = require('../../../index');
|
||||
const MatrixClientPeg = require('../../../MatrixClientPeg');
|
||||
const sdk = require('../../../index');
|
||||
import AccessibleButton from '../elements/AccessibleButton';
|
||||
import { _t } from '../../../languageHandler';
|
||||
|
||||
|
||||
var PRESENCE_CLASS = {
|
||||
const PRESENCE_CLASS = {
|
||||
"offline": "mx_EntityTile_offline",
|
||||
"online": "mx_EntityTile_online",
|
||||
"unavailable": "mx_EntityTile_unavailable"
|
||||
"unavailable": "mx_EntityTile_unavailable",
|
||||
};
|
||||
|
||||
|
||||
|
@ -62,7 +62,7 @@ module.exports = React.createClass({
|
|||
showInviteButton: React.PropTypes.bool,
|
||||
shouldComponentUpdate: React.PropTypes.func,
|
||||
onClick: React.PropTypes.func,
|
||||
suppressOnHover: React.PropTypes.bool
|
||||
suppressOnHover: React.PropTypes.bool,
|
||||
},
|
||||
|
||||
getDefaultProps: function() {
|
||||
|
@ -73,13 +73,13 @@ module.exports = React.createClass({
|
|||
presenceLastActiveAgo: 0,
|
||||
presenceLastTs: 0,
|
||||
showInviteButton: false,
|
||||
suppressOnHover: false
|
||||
suppressOnHover: false,
|
||||
};
|
||||
},
|
||||
|
||||
getInitialState: function() {
|
||||
return {
|
||||
hover: false
|
||||
hover: false,
|
||||
};
|
||||
},
|
||||
|
||||
|
@ -98,38 +98,37 @@ module.exports = React.createClass({
|
|||
|
||||
render: function() {
|
||||
const presenceClass = presenceClassForMember(
|
||||
this.props.presenceState, this.props.presenceLastActiveAgo
|
||||
this.props.presenceState, this.props.presenceLastActiveAgo,
|
||||
);
|
||||
|
||||
var mainClassName = "mx_EntityTile ";
|
||||
let mainClassName = "mx_EntityTile ";
|
||||
mainClassName += presenceClass + (this.props.className ? (" " + this.props.className) : "");
|
||||
var nameEl;
|
||||
let nameEl;
|
||||
const {name} = this.props;
|
||||
|
||||
const EmojiText = sdk.getComponent('elements.EmojiText');
|
||||
if (this.state.hover && !this.props.suppressOnHover) {
|
||||
var activeAgo = this.props.presenceLastActiveAgo ?
|
||||
const activeAgo = this.props.presenceLastActiveAgo ?
|
||||
(Date.now() - (this.props.presenceLastTs - this.props.presenceLastActiveAgo)) : -1;
|
||||
|
||||
mainClassName += " mx_EntityTile_hover";
|
||||
var PresenceLabel = sdk.getComponent("rooms.PresenceLabel");
|
||||
const PresenceLabel = sdk.getComponent("rooms.PresenceLabel");
|
||||
nameEl = (
|
||||
<div className="mx_EntityTile_details">
|
||||
<img className="mx_EntityTile_chevron" src="img/member_chevron.png" width="8" height="12"/>
|
||||
<EmojiText element="div" className="mx_EntityTile_name_hover" dir="auto">{name}</EmojiText>
|
||||
<PresenceLabel activeAgo={ activeAgo }
|
||||
<img className="mx_EntityTile_chevron" src="img/member_chevron.png" width="8" height="12" />
|
||||
<EmojiText element="div" className="mx_EntityTile_name_hover" dir="auto">{ name }</EmojiText>
|
||||
<PresenceLabel activeAgo={activeAgo}
|
||||
currentlyActive={this.props.presenceCurrentlyActive}
|
||||
presenceState={this.props.presenceState} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
nameEl = (
|
||||
<EmojiText element="div" className="mx_EntityTile_name" dir="auto">{name}</EmojiText>
|
||||
<EmojiText element="div" className="mx_EntityTile_name" dir="auto">{ name }</EmojiText>
|
||||
);
|
||||
}
|
||||
|
||||
var inviteButton;
|
||||
let inviteButton;
|
||||
if (this.props.showInviteButton) {
|
||||
inviteButton = (
|
||||
<div className="mx_EntityTile_invite">
|
||||
|
@ -138,25 +137,25 @@ module.exports = React.createClass({
|
|||
);
|
||||
}
|
||||
|
||||
var power;
|
||||
var powerLevel = this.props.powerLevel;
|
||||
let power;
|
||||
const powerLevel = this.props.powerLevel;
|
||||
if (powerLevel >= 50 && powerLevel < 99) {
|
||||
power = <img src="img/mod.svg" className="mx_EntityTile_power" width="16" height="17" alt={_t("Moderator")}/>;
|
||||
power = <img src="img/mod.svg" className="mx_EntityTile_power" width="16" height="17" alt={_t("Moderator")} />;
|
||||
}
|
||||
if (powerLevel >= 99) {
|
||||
power = <img src="img/admin.svg" className="mx_EntityTile_power" width="16" height="17" alt={_t("Admin")}/>;
|
||||
power = <img src="img/admin.svg" className="mx_EntityTile_power" width="16" height="17" alt={_t("Admin")} />;
|
||||
}
|
||||
|
||||
|
||||
var MemberAvatar = sdk.getComponent('avatars.MemberAvatar');
|
||||
var BaseAvatar = sdk.getComponent('avatars.BaseAvatar');
|
||||
const MemberAvatar = sdk.getComponent('avatars.MemberAvatar');
|
||||
const BaseAvatar = sdk.getComponent('avatars.BaseAvatar');
|
||||
|
||||
var av = this.props.avatarJsx || <BaseAvatar name={this.props.name} width={36} height={36} />;
|
||||
const av = this.props.avatarJsx || <BaseAvatar name={this.props.name} width={36} height={36} />;
|
||||
|
||||
return (
|
||||
<AccessibleButton className={mainClassName} title={ this.props.title }
|
||||
onClick={ this.props.onClick } onMouseEnter={ this.mouseEnter }
|
||||
onMouseLeave={ this.mouseLeave }>
|
||||
<AccessibleButton className={mainClassName} title={this.props.title}
|
||||
onClick={this.props.onClick} onMouseEnter={this.mouseEnter}
|
||||
onMouseLeave={this.mouseLeave}>
|
||||
<div className="mx_EntityTile_avatar">
|
||||
{ av }
|
||||
{ power }
|
||||
|
@ -165,5 +164,5 @@ module.exports = React.createClass({
|
|||
{ inviteButton }
|
||||
</AccessibleButton>
|
||||
);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
|
|
@ -17,38 +17,38 @@ limitations under the License.
|
|||
'use strict';
|
||||
|
||||
|
||||
var React = require('react');
|
||||
var classNames = require("classnames");
|
||||
const React = require('react');
|
||||
const classNames = require("classnames");
|
||||
import { _t } from '../../../languageHandler';
|
||||
var Modal = require('../../../Modal');
|
||||
const Modal = require('../../../Modal');
|
||||
|
||||
var sdk = require('../../../index');
|
||||
var TextForEvent = require('../../../TextForEvent');
|
||||
const sdk = require('../../../index');
|
||||
const TextForEvent = require('../../../TextForEvent');
|
||||
import withMatrixClient from '../../../wrappers/withMatrixClient';
|
||||
|
||||
var ContextualMenu = require('../../structures/ContextualMenu');
|
||||
const ContextualMenu = require('../../structures/ContextualMenu');
|
||||
import dis from '../../../dispatcher';
|
||||
|
||||
var ObjectUtils = require('../../../ObjectUtils');
|
||||
const ObjectUtils = require('../../../ObjectUtils');
|
||||
|
||||
var eventTileTypes = {
|
||||
const eventTileTypes = {
|
||||
'm.room.message': 'messages.MessageEvent',
|
||||
'm.room.member' : 'messages.TextualEvent',
|
||||
'm.call.invite' : 'messages.TextualEvent',
|
||||
'm.call.answer' : 'messages.TextualEvent',
|
||||
'm.call.hangup' : 'messages.TextualEvent',
|
||||
'm.room.name' : 'messages.TextualEvent',
|
||||
'm.room.avatar' : 'messages.RoomAvatarEvent',
|
||||
'm.room.topic' : 'messages.TextualEvent',
|
||||
'm.room.third_party_invite' : 'messages.TextualEvent',
|
||||
'm.room.history_visibility' : 'messages.TextualEvent',
|
||||
'm.room.encryption' : 'messages.TextualEvent',
|
||||
'm.room.power_levels' : 'messages.TextualEvent',
|
||||
'm.room.member': 'messages.TextualEvent',
|
||||
'm.call.invite': 'messages.TextualEvent',
|
||||
'm.call.answer': 'messages.TextualEvent',
|
||||
'm.call.hangup': 'messages.TextualEvent',
|
||||
'm.room.name': 'messages.TextualEvent',
|
||||
'm.room.avatar': 'messages.RoomAvatarEvent',
|
||||
'm.room.topic': 'messages.TextualEvent',
|
||||
'm.room.third_party_invite': 'messages.TextualEvent',
|
||||
'm.room.history_visibility': 'messages.TextualEvent',
|
||||
'm.room.encryption': 'messages.TextualEvent',
|
||||
'm.room.power_levels': 'messages.TextualEvent',
|
||||
|
||||
'im.vector.modular.widgets': 'messages.TextualEvent',
|
||||
};
|
||||
|
||||
var MAX_READ_AVATARS = 5;
|
||||
const MAX_READ_AVATARS = 5;
|
||||
|
||||
// Our component structure for EventTiles on the timeline is:
|
||||
//
|
||||
|
@ -177,7 +177,7 @@ module.exports = withMatrixClient(React.createClass({
|
|||
},
|
||||
|
||||
componentWillUnmount: function() {
|
||||
var client = this.props.matrixClient;
|
||||
const client = this.props.matrixClient;
|
||||
client.removeListener("deviceVerificationChanged",
|
||||
this.onDeviceVerificationChanged);
|
||||
this.props.mxEvent.removeListener("Event.decrypted", this._onDecrypted);
|
||||
|
@ -204,20 +204,20 @@ module.exports = withMatrixClient(React.createClass({
|
|||
|
||||
const verified = await this.props.matrixClient.isEventSenderVerified(mxEvent);
|
||||
this.setState({
|
||||
verified: verified
|
||||
verified: verified,
|
||||
});
|
||||
},
|
||||
|
||||
_propsEqual: function(objA, objB) {
|
||||
var keysA = Object.keys(objA);
|
||||
var keysB = Object.keys(objB);
|
||||
const keysA = Object.keys(objA);
|
||||
const keysB = Object.keys(objB);
|
||||
|
||||
if (keysA.length !== keysB.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (var i = 0; i < keysA.length; i++) {
|
||||
var key = keysA[i];
|
||||
for (let i = 0; i < keysA.length; i++) {
|
||||
const key = keysA[i];
|
||||
|
||||
if (!objB.hasOwnProperty(key)) {
|
||||
return false;
|
||||
|
@ -225,8 +225,8 @@ module.exports = withMatrixClient(React.createClass({
|
|||
|
||||
// need to deep-compare readReceipts
|
||||
if (key == 'readReceipts') {
|
||||
var rA = objA[key];
|
||||
var rB = objB[key];
|
||||
const rA = objA[key];
|
||||
const rB = objB[key];
|
||||
if (rA === rB) {
|
||||
continue;
|
||||
}
|
||||
|
@ -238,7 +238,7 @@ module.exports = withMatrixClient(React.createClass({
|
|||
if (rA.length !== rB.length) {
|
||||
return false;
|
||||
}
|
||||
for (var j = 0; j < rA.length; j++) {
|
||||
for (let j = 0; j < rA.length; j++) {
|
||||
if (rA[j].roomMember.userId !== rB[j].roomMember.userId) {
|
||||
return false;
|
||||
}
|
||||
|
@ -253,12 +253,11 @@ module.exports = withMatrixClient(React.createClass({
|
|||
},
|
||||
|
||||
shouldHighlight: function() {
|
||||
var actions = this.props.matrixClient.getPushActionsForEvent(this.props.mxEvent);
|
||||
const actions = this.props.matrixClient.getPushActionsForEvent(this.props.mxEvent);
|
||||
if (!actions || !actions.tweaks) { return false; }
|
||||
|
||||
// don't show self-highlights from another of our clients
|
||||
if (this.props.mxEvent.getSender() === this.props.matrixClient.credentials.userId)
|
||||
{
|
||||
if (this.props.mxEvent.getSender() === this.props.matrixClient.credentials.userId) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -266,13 +265,13 @@ module.exports = withMatrixClient(React.createClass({
|
|||
},
|
||||
|
||||
onEditClicked: function(e) {
|
||||
var MessageContextMenu = sdk.getComponent('context_menus.MessageContextMenu');
|
||||
var buttonRect = e.target.getBoundingClientRect();
|
||||
const MessageContextMenu = sdk.getComponent('context_menus.MessageContextMenu');
|
||||
const 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 + (buttonRect.height / 2) + window.pageYOffset) - 19;
|
||||
var self = this;
|
||||
const x = buttonRect.right + window.pageXOffset;
|
||||
const y = (buttonRect.top + (buttonRect.height / 2) + window.pageYOffset) - 19;
|
||||
const self = this;
|
||||
ContextualMenu.createMenu(MessageContextMenu, {
|
||||
chevronOffset: 10,
|
||||
mxEvent: this.props.mxEvent,
|
||||
|
@ -281,19 +280,18 @@ module.exports = withMatrixClient(React.createClass({
|
|||
eventTileOps: this.refs.tile && this.refs.tile.getEventTileOps ? this.refs.tile.getEventTileOps() : undefined,
|
||||
onFinished: function() {
|
||||
self.setState({menu: false});
|
||||
}
|
||||
},
|
||||
});
|
||||
this.setState({menu: true});
|
||||
},
|
||||
|
||||
toggleAllReadAvatars: function() {
|
||||
this.setState({
|
||||
allReadAvatars: !this.state.allReadAvatars
|
||||
allReadAvatars: !this.state.allReadAvatars,
|
||||
});
|
||||
},
|
||||
|
||||
getReadAvatars: function() {
|
||||
|
||||
// return early if there are no read receipts
|
||||
if (!this.props.readReceipts || this.props.readReceipts.length === 0) {
|
||||
return (<span className="mx_EventTile_readAvatars"></span>);
|
||||
|
@ -304,11 +302,11 @@ module.exports = withMatrixClient(React.createClass({
|
|||
const receiptOffset = 15;
|
||||
let left = 0;
|
||||
|
||||
var receipts = this.props.readReceipts || [];
|
||||
for (var i = 0; i < receipts.length; ++i) {
|
||||
var receipt = receipts[i];
|
||||
const receipts = this.props.readReceipts || [];
|
||||
for (let i = 0; i < receipts.length; ++i) {
|
||||
const receipt = receipts[i];
|
||||
|
||||
var hidden = true;
|
||||
let hidden = true;
|
||||
if ((i < MAX_READ_AVATARS) || this.state.allReadAvatars) {
|
||||
hidden = false;
|
||||
}
|
||||
|
@ -319,7 +317,7 @@ module.exports = withMatrixClient(React.createClass({
|
|||
// else set it proportional to index
|
||||
left = (hidden ? MAX_READ_AVATARS - 1 : i) * -receiptOffset;
|
||||
|
||||
var userId = receipt.roomMember.userId;
|
||||
const userId = receipt.roomMember.userId;
|
||||
var readReceiptInfo;
|
||||
|
||||
if (this.props.readReceiptMap) {
|
||||
|
@ -340,12 +338,12 @@ module.exports = withMatrixClient(React.createClass({
|
|||
onClick={this.toggleAllReadAvatars}
|
||||
timestamp={receipt.ts}
|
||||
showTwelveHour={this.props.isTwelveHour}
|
||||
/>
|
||||
/>,
|
||||
);
|
||||
}
|
||||
var remText;
|
||||
let remText;
|
||||
if (!this.state.allReadAvatars) {
|
||||
var remainder = receipts.length - MAX_READ_AVATARS;
|
||||
const remainder = receipts.length - MAX_READ_AVATARS;
|
||||
if (remainder > 0) {
|
||||
remText = <span className="mx_EventTile_readAvatarRemainder"
|
||||
onClick={this.toggleAllReadAvatars}
|
||||
|
@ -369,7 +367,7 @@ module.exports = withMatrixClient(React.createClass({
|
|||
},
|
||||
|
||||
onCryptoClicked: function(e) {
|
||||
var event = this.props.mxEvent;
|
||||
const event = this.props.mxEvent;
|
||||
|
||||
Modal.createTrackedDialogAsync('Encrypted Event Dialog', '', (cb) => {
|
||||
require(['../../../async-components/views/dialogs/EncryptedEventDialog'], cb);
|
||||
|
@ -396,12 +394,12 @@ module.exports = withMatrixClient(React.createClass({
|
|||
|
||||
|
||||
if (ev.getContent().msgtype === 'm.bad.encrypted') {
|
||||
return <E2ePadlockUndecryptable {...props}/>;
|
||||
return <E2ePadlockUndecryptable {...props} />;
|
||||
} else if (ev.isEncrypted()) {
|
||||
if (this.state.verified) {
|
||||
return <E2ePadlockVerified {...props}/>;
|
||||
return <E2ePadlockVerified {...props} />;
|
||||
} else {
|
||||
return <E2ePadlockUnverified {...props}/>;
|
||||
return <E2ePadlockUnverified {...props} />;
|
||||
}
|
||||
} else {
|
||||
// XXX: if the event is being encrypted (ie eventSendStatus ===
|
||||
|
@ -412,7 +410,7 @@ module.exports = withMatrixClient(React.createClass({
|
|||
// open padlock
|
||||
const e2eEnabled = this.props.matrixClient.isRoomEncrypted(ev.getRoomId());
|
||||
if (e2eEnabled) {
|
||||
return <E2ePadlockUnencrypted {...props}/>;
|
||||
return <E2ePadlockUnencrypted {...props} />;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -421,27 +419,27 @@ module.exports = withMatrixClient(React.createClass({
|
|||
},
|
||||
|
||||
render: function() {
|
||||
var MessageTimestamp = sdk.getComponent('messages.MessageTimestamp');
|
||||
var SenderProfile = sdk.getComponent('messages.SenderProfile');
|
||||
var MemberAvatar = sdk.getComponent('avatars.MemberAvatar');
|
||||
const MessageTimestamp = sdk.getComponent('messages.MessageTimestamp');
|
||||
const SenderProfile = sdk.getComponent('messages.SenderProfile');
|
||||
const MemberAvatar = sdk.getComponent('avatars.MemberAvatar');
|
||||
|
||||
//console.log("EventTile showUrlPreview for %s is %s", this.props.mxEvent.getId(), this.props.showUrlPreview);
|
||||
|
||||
var content = this.props.mxEvent.getContent();
|
||||
var msgtype = content.msgtype;
|
||||
var eventType = this.props.mxEvent.getType();
|
||||
const content = this.props.mxEvent.getContent();
|
||||
const msgtype = content.msgtype;
|
||||
const eventType = this.props.mxEvent.getType();
|
||||
|
||||
// Info messages are basically information about commands processed on a room
|
||||
var isInfoMessage = (eventType !== 'm.room.message');
|
||||
const isInfoMessage = (eventType !== 'm.room.message');
|
||||
|
||||
var EventTileType = sdk.getComponent(eventTileTypes[eventType]);
|
||||
const EventTileType = sdk.getComponent(eventTileTypes[eventType]);
|
||||
// This shouldn't happen: the caller should check we support this type
|
||||
// before trying to instantiate us
|
||||
if (!EventTileType) {
|
||||
throw new Error("Event type not supported");
|
||||
}
|
||||
|
||||
var isSending = (['sending', 'queued', 'encrypting'].indexOf(this.props.eventSendStatus) !== -1);
|
||||
const isSending = (['sending', 'queued', 'encrypting'].indexOf(this.props.eventSendStatus) !== -1);
|
||||
const isRedacted = (eventType === 'm.room.message') && this.props.isRedacted;
|
||||
|
||||
const classes = classNames({
|
||||
|
@ -468,9 +466,9 @@ module.exports = withMatrixClient(React.createClass({
|
|||
this.props.mxEvent.getRoomId() + "/" +
|
||||
this.props.mxEvent.getId();
|
||||
|
||||
var readAvatars = this.getReadAvatars();
|
||||
const readAvatars = this.getReadAvatars();
|
||||
|
||||
var avatar, sender;
|
||||
let avatar, sender;
|
||||
let avatarSize;
|
||||
let needsSenderProfile;
|
||||
|
||||
|
@ -508,15 +506,14 @@ module.exports = withMatrixClient(React.createClass({
|
|||
if (msgtype === 'm.image') aux = _t('sent an image');
|
||||
else if (msgtype === 'm.video') aux = _t('sent a video');
|
||||
else if (msgtype === 'm.file') aux = _t('uploaded a file');
|
||||
sender = <SenderProfile onClick={ this.onSenderProfileClick } mxEvent={this.props.mxEvent} enableFlair={!aux} aux={aux} />;
|
||||
}
|
||||
else {
|
||||
sender = <SenderProfile onClick={this.onSenderProfileClick} mxEvent={this.props.mxEvent} enableFlair={!aux} aux={aux} />;
|
||||
} else {
|
||||
sender = <SenderProfile mxEvent={this.props.mxEvent} enableFlair={true} />;
|
||||
}
|
||||
}
|
||||
|
||||
const editButton = (
|
||||
<span className="mx_EventTile_editButton" title={ _t("Options") } onClick={this.onEditClicked} />
|
||||
<span className="mx_EventTile_editButton" title={_t("Options")} onClick={this.onEditClicked} />
|
||||
);
|
||||
|
||||
const timestamp = this.props.mxEvent.getTs() ?
|
||||
|
@ -527,13 +524,13 @@ module.exports = withMatrixClient(React.createClass({
|
|||
return (
|
||||
<div className={classes}>
|
||||
<div className="mx_EventTile_roomName">
|
||||
<a href={ permalink } onClick={this.onPermalinkClicked}>
|
||||
<a href={permalink} onClick={this.onPermalinkClicked}>
|
||||
{ room ? room.name : '' }
|
||||
</a>
|
||||
</div>
|
||||
<div className="mx_EventTile_senderDetails">
|
||||
{ avatar }
|
||||
<a href={ permalink } onClick={this.onPermalinkClicked}>
|
||||
<a href={permalink} onClick={this.onPermalinkClicked}>
|
||||
{ sender }
|
||||
{ timestamp }
|
||||
</a>
|
||||
|
@ -548,8 +545,7 @@ module.exports = withMatrixClient(React.createClass({
|
|||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
else if (this.props.tileShape === "file_grid") {
|
||||
} else if (this.props.tileShape === "file_grid") {
|
||||
return (
|
||||
<div className={classes}>
|
||||
<div className="mx_EventTile_line" >
|
||||
|
@ -563,7 +559,7 @@ module.exports = withMatrixClient(React.createClass({
|
|||
</div>
|
||||
<a
|
||||
className="mx_EventTile_senderDetailsLink"
|
||||
href={ permalink }
|
||||
href={permalink}
|
||||
onClick={this.onPermalinkClicked}
|
||||
>
|
||||
<div className="mx_EventTile_senderDetails">
|
||||
|
@ -573,8 +569,7 @@ module.exports = withMatrixClient(React.createClass({
|
|||
</a>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return (
|
||||
<div className={classes}>
|
||||
<div className="mx_EventTile_msgOption">
|
||||
|
@ -583,7 +578,7 @@ module.exports = withMatrixClient(React.createClass({
|
|||
{ avatar }
|
||||
{ sender }
|
||||
<div className="mx_EventTile_line">
|
||||
<a href={ permalink } onClick={this.onPermalinkClicked}>
|
||||
<a href={permalink} onClick={this.onPermalinkClicked}>
|
||||
{ timestamp }
|
||||
</a>
|
||||
{ this._renderE2EPadlock() }
|
||||
|
|
|
@ -16,16 +16,16 @@ limitations under the License.
|
|||
|
||||
'use strict';
|
||||
|
||||
var React = require('react');
|
||||
const React = require('react');
|
||||
|
||||
var sdk = require('../../../index');
|
||||
var MatrixClientPeg = require('../../../MatrixClientPeg');
|
||||
var ImageUtils = require('../../../ImageUtils');
|
||||
var Modal = require('../../../Modal');
|
||||
const sdk = require('../../../index');
|
||||
const MatrixClientPeg = require('../../../MatrixClientPeg');
|
||||
const ImageUtils = require('../../../ImageUtils');
|
||||
const Modal = require('../../../Modal');
|
||||
|
||||
var linkify = require('linkifyjs');
|
||||
var linkifyElement = require('linkifyjs/element');
|
||||
var linkifyMatrix = require('../../../linkify-matrix');
|
||||
const linkify = require('linkifyjs');
|
||||
const linkifyElement = require('linkifyjs/element');
|
||||
const linkifyMatrix = require('../../../linkify-matrix');
|
||||
linkifyMatrix(linkify);
|
||||
|
||||
module.exports = React.createClass({
|
||||
|
@ -40,7 +40,7 @@ module.exports = React.createClass({
|
|||
|
||||
getInitialState: function() {
|
||||
return {
|
||||
preview: null
|
||||
preview: null,
|
||||
};
|
||||
},
|
||||
|
||||
|
@ -52,7 +52,7 @@ module.exports = React.createClass({
|
|||
}
|
||||
this.setState(
|
||||
{ preview: res },
|
||||
this.props.onWidgetLoad
|
||||
this.props.onWidgetLoad,
|
||||
);
|
||||
}, (error)=>{
|
||||
console.error("Failed to get preview for " + this.props.link + " " + error);
|
||||
|
@ -76,17 +76,17 @@ module.exports = React.createClass({
|
|||
},
|
||||
|
||||
onImageClick: function(ev) {
|
||||
var p = this.state.preview;
|
||||
const p = this.state.preview;
|
||||
if (ev.button != 0 || ev.metaKey) return;
|
||||
ev.preventDefault();
|
||||
var ImageView = sdk.getComponent("elements.ImageView");
|
||||
const ImageView = sdk.getComponent("elements.ImageView");
|
||||
|
||||
var src = p["og:image"];
|
||||
let src = p["og:image"];
|
||||
if (src && src.startsWith("mxc://")) {
|
||||
src = MatrixClientPeg.get().mxcUrlToHttp(src);
|
||||
}
|
||||
|
||||
var params = {
|
||||
const params = {
|
||||
src: src,
|
||||
width: p["og:image:width"],
|
||||
height: p["og:image:height"],
|
||||
|
@ -99,27 +99,27 @@ module.exports = React.createClass({
|
|||
},
|
||||
|
||||
render: function() {
|
||||
var p = this.state.preview;
|
||||
const p = this.state.preview;
|
||||
if (!p || Object.keys(p).length === 0) {
|
||||
return <div/>;
|
||||
return <div />;
|
||||
}
|
||||
|
||||
// FIXME: do we want to factor out all image displaying between this and MImageBody - especially for lightboxing?
|
||||
var image = p["og:image"];
|
||||
var imageMaxWidth = 100, imageMaxHeight = 100;
|
||||
let image = p["og:image"];
|
||||
let imageMaxWidth = 100, imageMaxHeight = 100;
|
||||
if (image && image.startsWith("mxc://")) {
|
||||
image = MatrixClientPeg.get().mxcUrlToHttp(image, imageMaxWidth, imageMaxHeight);
|
||||
}
|
||||
|
||||
var thumbHeight = imageMaxHeight;
|
||||
let thumbHeight = imageMaxHeight;
|
||||
if (p["og:image:width"] && p["og:image:height"]) {
|
||||
thumbHeight = ImageUtils.thumbHeight(p["og:image:width"], p["og:image:height"], imageMaxWidth, imageMaxHeight);
|
||||
}
|
||||
|
||||
var img;
|
||||
let img;
|
||||
if (image) {
|
||||
img = <div className="mx_LinkPreviewWidget_image" style={{ height: thumbHeight }}>
|
||||
<img style={{ maxWidth: imageMaxWidth, maxHeight: imageMaxHeight }} src={ image } onClick={ this.onImageClick }/>
|
||||
<img style={{ maxWidth: imageMaxWidth, maxHeight: imageMaxHeight }} src={image} onClick={this.onImageClick} />
|
||||
</div>;
|
||||
}
|
||||
|
||||
|
@ -127,15 +127,15 @@ module.exports = React.createClass({
|
|||
<div className="mx_LinkPreviewWidget" >
|
||||
{ img }
|
||||
<div className="mx_LinkPreviewWidget_caption">
|
||||
<div className="mx_LinkPreviewWidget_title"><a href={ this.props.link } target="_blank" rel="noopener">{ p["og:title"] }</a></div>
|
||||
<div className="mx_LinkPreviewWidget_title"><a href={this.props.link} target="_blank" rel="noopener">{ p["og:title"] }</a></div>
|
||||
<div className="mx_LinkPreviewWidget_siteName">{ p["og:site_name"] ? (" - " + p["og:site_name"]) : null }</div>
|
||||
<div className="mx_LinkPreviewWidget_description" ref="description">
|
||||
{ p["og:description"] }
|
||||
</div>
|
||||
</div>
|
||||
<img className="mx_LinkPreviewWidget_cancel" src="img/cancel.svg" width="18" height="18"
|
||||
onClick={ this.props.onCancelClick }/>
|
||||
onClick={this.props.onCancelClick} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
|
|
@ -20,30 +20,30 @@ import { _t } from '../../../languageHandler';
|
|||
|
||||
export default class MemberDeviceInfo extends React.Component {
|
||||
render() {
|
||||
var indicator = null;
|
||||
var DeviceVerifyButtons = sdk.getComponent('elements.DeviceVerifyButtons');
|
||||
let indicator = null;
|
||||
const DeviceVerifyButtons = sdk.getComponent('elements.DeviceVerifyButtons');
|
||||
|
||||
if (this.props.device.isBlocked()) {
|
||||
indicator = (
|
||||
<div className="mx_MemberDeviceInfo_blacklisted">
|
||||
<img src="img/e2e-blocked.svg" width="12" height="12" style={{ marginLeft: "-1px" }} alt={_t("Blacklisted")}/>
|
||||
<img src="img/e2e-blocked.svg" width="12" height="12" style={{ marginLeft: "-1px" }} alt={_t("Blacklisted")} />
|
||||
</div>
|
||||
);
|
||||
} else if (this.props.device.isVerified()) {
|
||||
indicator = (
|
||||
<div className="mx_MemberDeviceInfo_verified">
|
||||
<img src="img/e2e-verified.svg" width="10" height="12" alt={_t("Verified")}/>
|
||||
<img src="img/e2e-verified.svg" width="10" height="12" alt={_t("Verified")} />
|
||||
</div>
|
||||
);
|
||||
} else {
|
||||
indicator = (
|
||||
<div className="mx_MemberDeviceInfo_unverified">
|
||||
<img src="img/e2e-warning.svg" width="15" height="12" style={{ marginLeft: "-2px" }} alt={_t("Unverified")}/>
|
||||
<img src="img/e2e-warning.svg" width="15" height="12" style={{ marginLeft: "-2px" }} alt={_t("Unverified")} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
var deviceName = this.props.device.ambiguous ?
|
||||
const deviceName = this.props.device.ambiguous ?
|
||||
(this.props.device.getDisplayName() ? this.props.device.getDisplayName() : "") + " (" + this.props.device.deviceId + ")" :
|
||||
this.props.device.getDisplayName();
|
||||
|
||||
|
@ -53,8 +53,8 @@ export default class MemberDeviceInfo extends React.Component {
|
|||
title={_t("device id: ") + this.props.device.deviceId} >
|
||||
<div className="mx_MemberDeviceInfo_deviceInfo">
|
||||
<div className="mx_MemberDeviceInfo_deviceId">
|
||||
{deviceName}
|
||||
{indicator}
|
||||
{ deviceName }
|
||||
{ indicator }
|
||||
</div>
|
||||
</div>
|
||||
<DeviceVerifyButtons userId={this.props.userId} device={this.props.device} />
|
||||
|
|
|
@ -55,7 +55,7 @@ module.exports = withMatrixClient(React.createClass({
|
|||
kick: false,
|
||||
ban: false,
|
||||
mute: false,
|
||||
modifyLevel: false
|
||||
modifyLevel: false,
|
||||
},
|
||||
muted: false,
|
||||
isTargetMod: false,
|
||||
|
@ -97,7 +97,7 @@ module.exports = withMatrixClient(React.createClass({
|
|||
},
|
||||
|
||||
componentWillUnmount: function() {
|
||||
var client = this.props.matrixClient;
|
||||
const client = this.props.matrixClient;
|
||||
if (client) {
|
||||
client.removeListener("deviceVerificationChanged", this.onDeviceVerificationChanged);
|
||||
client.removeListener("Room", this.onRoom);
|
||||
|
@ -120,10 +120,10 @@ module.exports = withMatrixClient(React.createClass({
|
|||
},
|
||||
|
||||
_disambiguateDevices: function(devices) {
|
||||
var names = Object.create(null);
|
||||
for (var i = 0; i < devices.length; i++) {
|
||||
const names = Object.create(null);
|
||||
for (let i = 0; i < devices.length; i++) {
|
||||
var name = devices[i].getDisplayName();
|
||||
var indexList = names[name] || [];
|
||||
const indexList = names[name] || [];
|
||||
indexList.push(i);
|
||||
names[name] = indexList;
|
||||
}
|
||||
|
@ -193,7 +193,7 @@ module.exports = withMatrixClient(React.createClass({
|
|||
},
|
||||
|
||||
_updateStateForNewMember: function(member) {
|
||||
var newState = this._calculateOpsPermissions(member);
|
||||
const newState = this._calculateOpsPermissions(member);
|
||||
newState.devicesLoading = true;
|
||||
newState.devices = null;
|
||||
this.setState(newState);
|
||||
|
@ -211,11 +211,11 @@ module.exports = withMatrixClient(React.createClass({
|
|||
return;
|
||||
}
|
||||
|
||||
var cancelled = false;
|
||||
let cancelled = false;
|
||||
this._cancelDeviceList = function() { cancelled = true; };
|
||||
|
||||
var client = this.props.matrixClient;
|
||||
var self = this;
|
||||
const client = this.props.matrixClient;
|
||||
const self = this;
|
||||
client.downloadKeys([member.userId], true).then(() => {
|
||||
return client.getStoredDevicesForUser(member.userId);
|
||||
}).finally(function() {
|
||||
|
@ -260,7 +260,7 @@ module.exports = withMatrixClient(React.createClass({
|
|||
this.setState({ updating: this.state.updating + 1 });
|
||||
this.props.matrixClient.kick(
|
||||
this.props.member.roomId, this.props.member.userId,
|
||||
reason || undefined
|
||||
reason || undefined,
|
||||
).then(function() {
|
||||
// NO-OP; rely on the m.room.member event coming down else we could
|
||||
// get out of sync if we force setState here!
|
||||
|
@ -272,11 +272,11 @@ module.exports = withMatrixClient(React.createClass({
|
|||
title: _t("Failed to kick"),
|
||||
description: ((err && err.message) ? err.message : "Operation failed"),
|
||||
});
|
||||
}
|
||||
},
|
||||
).finally(()=>{
|
||||
this.setState({ updating: this.state.updating - 1 });
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
},
|
||||
|
||||
|
@ -299,7 +299,7 @@ module.exports = withMatrixClient(React.createClass({
|
|||
} else {
|
||||
promise = this.props.matrixClient.ban(
|
||||
this.props.member.roomId, this.props.member.userId,
|
||||
reason || undefined
|
||||
reason || undefined,
|
||||
);
|
||||
}
|
||||
promise.then(
|
||||
|
@ -314,7 +314,7 @@ module.exports = withMatrixClient(React.createClass({
|
|||
title: _t("Error"),
|
||||
description: _t("Failed to ban user"),
|
||||
});
|
||||
}
|
||||
},
|
||||
).finally(()=>{
|
||||
this.setState({ updating: this.state.updating - 1 });
|
||||
});
|
||||
|
@ -323,30 +323,29 @@ module.exports = withMatrixClient(React.createClass({
|
|||
},
|
||||
|
||||
onMuteToggle: function() {
|
||||
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||
var roomId = this.props.member.roomId;
|
||||
var target = this.props.member.userId;
|
||||
var room = this.props.matrixClient.getRoom(roomId);
|
||||
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||
const roomId = this.props.member.roomId;
|
||||
const target = this.props.member.userId;
|
||||
const room = this.props.matrixClient.getRoom(roomId);
|
||||
if (!room) {
|
||||
return;
|
||||
}
|
||||
var powerLevelEvent = room.currentState.getStateEvents(
|
||||
"m.room.power_levels", ""
|
||||
const powerLevelEvent = room.currentState.getStateEvents(
|
||||
"m.room.power_levels", "",
|
||||
);
|
||||
if (!powerLevelEvent) {
|
||||
return;
|
||||
}
|
||||
var isMuted = this.state.muted;
|
||||
var powerLevels = powerLevelEvent.getContent();
|
||||
var levelToSend = (
|
||||
const isMuted = this.state.muted;
|
||||
const powerLevels = powerLevelEvent.getContent();
|
||||
const levelToSend = (
|
||||
(powerLevels.events ? powerLevels.events["m.room.message"] : null) ||
|
||||
powerLevels.events_default
|
||||
);
|
||||
var level;
|
||||
let level;
|
||||
if (isMuted) { // unmute
|
||||
level = levelToSend;
|
||||
}
|
||||
else { // mute
|
||||
} else { // mute
|
||||
level = levelToSend - 1;
|
||||
}
|
||||
level = parseInt(level);
|
||||
|
@ -364,7 +363,7 @@ module.exports = withMatrixClient(React.createClass({
|
|||
title: _t("Error"),
|
||||
description: _t("Failed to mute user"),
|
||||
});
|
||||
}
|
||||
},
|
||||
).finally(()=>{
|
||||
this.setState({ updating: this.state.updating - 1 });
|
||||
});
|
||||
|
@ -372,28 +371,28 @@ module.exports = withMatrixClient(React.createClass({
|
|||
},
|
||||
|
||||
onModToggle: function() {
|
||||
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||
var roomId = this.props.member.roomId;
|
||||
var target = this.props.member.userId;
|
||||
var room = this.props.matrixClient.getRoom(roomId);
|
||||
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||
const roomId = this.props.member.roomId;
|
||||
const target = this.props.member.userId;
|
||||
const room = this.props.matrixClient.getRoom(roomId);
|
||||
if (!room) {
|
||||
return;
|
||||
}
|
||||
var powerLevelEvent = room.currentState.getStateEvents(
|
||||
"m.room.power_levels", ""
|
||||
const powerLevelEvent = room.currentState.getStateEvents(
|
||||
"m.room.power_levels", "",
|
||||
);
|
||||
if (!powerLevelEvent) {
|
||||
return;
|
||||
}
|
||||
var me = room.getMember(this.props.matrixClient.credentials.userId);
|
||||
const me = room.getMember(this.props.matrixClient.credentials.userId);
|
||||
if (!me) {
|
||||
return;
|
||||
}
|
||||
var defaultLevel = powerLevelEvent.getContent().users_default;
|
||||
var modLevel = me.powerLevel - 1;
|
||||
const defaultLevel = powerLevelEvent.getContent().users_default;
|
||||
let modLevel = me.powerLevel - 1;
|
||||
if (modLevel > 50 && defaultLevel < 50) modLevel = 50; // try to stick with the vector level defaults
|
||||
// toggle the level
|
||||
var newLevel = this.state.isTargetMod ? defaultLevel : modLevel;
|
||||
const newLevel = this.state.isTargetMod ? defaultLevel : modLevel;
|
||||
this.setState({ updating: this.state.updating + 1 });
|
||||
this.props.matrixClient.setPowerLevel(roomId, target, parseInt(newLevel), powerLevelEvent).then(
|
||||
function() {
|
||||
|
@ -410,7 +409,7 @@ module.exports = withMatrixClient(React.createClass({
|
|||
description: _t("Failed to toggle moderator status"),
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
).finally(()=>{
|
||||
this.setState({ updating: this.state.updating - 1 });
|
||||
});
|
||||
|
@ -430,36 +429,36 @@ module.exports = withMatrixClient(React.createClass({
|
|||
title: _t("Error"),
|
||||
description: _t("Failed to change power level"),
|
||||
});
|
||||
}
|
||||
},
|
||||
).finally(()=>{
|
||||
this.setState({ updating: this.state.updating - 1 });
|
||||
}).done();
|
||||
},
|
||||
|
||||
onPowerChange: function(powerLevel) {
|
||||
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||
var roomId = this.props.member.roomId;
|
||||
var target = this.props.member.userId;
|
||||
var room = this.props.matrixClient.getRoom(roomId);
|
||||
var self = this;
|
||||
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||
const roomId = this.props.member.roomId;
|
||||
const target = this.props.member.userId;
|
||||
const room = this.props.matrixClient.getRoom(roomId);
|
||||
const self = this;
|
||||
if (!room) {
|
||||
return;
|
||||
}
|
||||
var powerLevelEvent = room.currentState.getStateEvents(
|
||||
"m.room.power_levels", ""
|
||||
const powerLevelEvent = room.currentState.getStateEvents(
|
||||
"m.room.power_levels", "",
|
||||
);
|
||||
if (!powerLevelEvent) {
|
||||
return;
|
||||
}
|
||||
if (powerLevelEvent.getContent().users) {
|
||||
var myPower = powerLevelEvent.getContent().users[this.props.matrixClient.credentials.userId];
|
||||
const myPower = powerLevelEvent.getContent().users[this.props.matrixClient.credentials.userId];
|
||||
if (parseInt(myPower) === parseInt(powerLevel)) {
|
||||
var QuestionDialog = sdk.getComponent("dialogs.QuestionDialog");
|
||||
const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog");
|
||||
Modal.createTrackedDialog('Promote to PL100 Warning', '', QuestionDialog, {
|
||||
title: _t("Warning!"),
|
||||
description:
|
||||
<div>
|
||||
{ _t("You will not be able to undo this change as you are promoting the user to have the same power level as yourself.") }<br/>
|
||||
{ _t("You will not be able to undo this change as you are promoting the user to have the same power level as yourself.") }<br />
|
||||
{ _t("Are you sure?") }
|
||||
</div>,
|
||||
button: _t("Continue"),
|
||||
|
@ -469,12 +468,10 @@ module.exports = withMatrixClient(React.createClass({
|
|||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
this._applyPowerChange(roomId, target, powerLevel, powerLevelEvent);
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
this._applyPowerChange(roomId, target, powerLevel, powerLevelEvent);
|
||||
}
|
||||
},
|
||||
|
@ -497,14 +494,14 @@ module.exports = withMatrixClient(React.createClass({
|
|||
const defaultPerms = {
|
||||
can: {},
|
||||
muted: false,
|
||||
modifyLevel: false
|
||||
modifyLevel: false,
|
||||
};
|
||||
const room = this.props.matrixClient.getRoom(member.roomId);
|
||||
if (!room) {
|
||||
return defaultPerms;
|
||||
}
|
||||
const powerLevels = room.currentState.getStateEvents(
|
||||
"m.room.power_levels", ""
|
||||
"m.room.power_levels", "",
|
||||
);
|
||||
if (!powerLevels) {
|
||||
return defaultPerms;
|
||||
|
@ -516,10 +513,10 @@ module.exports = withMatrixClient(React.createClass({
|
|||
const them = member;
|
||||
return {
|
||||
can: this._calculateCanPermissions(
|
||||
me, them, powerLevels.getContent()
|
||||
me, them, powerLevels.getContent(),
|
||||
),
|
||||
muted: this._isMuted(them, powerLevels.getContent()),
|
||||
isTargetMod: them.powerLevel > powerLevels.getContent().users_default
|
||||
isTargetMod: them.powerLevel > powerLevels.getContent().users_default,
|
||||
};
|
||||
},
|
||||
|
||||
|
@ -528,7 +525,7 @@ module.exports = withMatrixClient(React.createClass({
|
|||
kick: false,
|
||||
ban: false,
|
||||
mute: false,
|
||||
modifyLevel: false
|
||||
modifyLevel: false,
|
||||
};
|
||||
const canAffectUser = them.powerLevel < me.powerLevel;
|
||||
if (!canAffectUser) {
|
||||
|
@ -556,7 +553,7 @@ module.exports = withMatrixClient(React.createClass({
|
|||
if (!powerLevelContent || !member) {
|
||||
return false;
|
||||
}
|
||||
var levelToSend = (
|
||||
const levelToSend = (
|
||||
(powerLevelContent.events ? powerLevelContent.events["m.room.message"] : null) ||
|
||||
powerLevelContent.events_default
|
||||
);
|
||||
|
@ -566,19 +563,19 @@ module.exports = withMatrixClient(React.createClass({
|
|||
onCancel: function(e) {
|
||||
dis.dispatch({
|
||||
action: "view_user",
|
||||
member: null
|
||||
member: null,
|
||||
});
|
||||
},
|
||||
|
||||
onMemberAvatarClick: function() {
|
||||
var avatarUrl = this.props.member.user ? this.props.member.user.avatarUrl : this.props.member.events.member.getContent().avatar_url;
|
||||
const avatarUrl = this.props.member.user ? this.props.member.user.avatarUrl : this.props.member.events.member.getContent().avatar_url;
|
||||
if(!avatarUrl) return;
|
||||
|
||||
var httpUrl = this.props.matrixClient.mxcUrlToHttp(avatarUrl);
|
||||
var ImageView = sdk.getComponent("elements.ImageView");
|
||||
var params = {
|
||||
const httpUrl = this.props.matrixClient.mxcUrlToHttp(avatarUrl);
|
||||
const ImageView = sdk.getComponent("elements.ImageView");
|
||||
const params = {
|
||||
src: httpUrl,
|
||||
name: this.props.member.name
|
||||
name: this.props.member.name,
|
||||
};
|
||||
|
||||
Modal.createDialog(ImageView, params, "mx_Dialog_lightbox");
|
||||
|
@ -596,11 +593,11 @@ module.exports = withMatrixClient(React.createClass({
|
|||
return null;
|
||||
}
|
||||
|
||||
var devices = this.state.devices;
|
||||
var MemberDeviceInfo = sdk.getComponent('rooms.MemberDeviceInfo');
|
||||
var Spinner = sdk.getComponent("elements.Spinner");
|
||||
const devices = this.state.devices;
|
||||
const MemberDeviceInfo = sdk.getComponent('rooms.MemberDeviceInfo');
|
||||
const Spinner = sdk.getComponent("elements.Spinner");
|
||||
|
||||
var devComponents;
|
||||
let devComponents;
|
||||
if (this.state.devicesLoading) {
|
||||
// still loading
|
||||
devComponents = <Spinner />;
|
||||
|
@ -610,10 +607,10 @@ module.exports = withMatrixClient(React.createClass({
|
|||
devComponents = _t("No devices with registered encryption keys");
|
||||
} else {
|
||||
devComponents = [];
|
||||
for (var i = 0; i < devices.length; i++) {
|
||||
for (let i = 0; i < devices.length; i++) {
|
||||
devComponents.push(<MemberDeviceInfo key={i}
|
||||
userId={this.props.member.userId}
|
||||
device={devices[i]}/>);
|
||||
device={devices[i]} />);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -621,7 +618,7 @@ module.exports = withMatrixClient(React.createClass({
|
|||
<div>
|
||||
<h3>{ _t("Devices") }</h3>
|
||||
<div className="mx_MemberInfo_devices">
|
||||
{devComponents}
|
||||
{ devComponents }
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
@ -678,7 +675,7 @@ module.exports = withMatrixClient(React.createClass({
|
|||
},
|
||||
|
||||
render: function() {
|
||||
var startChat, kickButton, banButton, muteButton, giveModButton, spinner;
|
||||
let startChat, kickButton, banButton, muteButton, giveModButton, spinner;
|
||||
if (this.props.member.userId !== this.props.matrixClient.credentials.userId) {
|
||||
const dmRoomMap = new DMRoomMap(this.props.matrixClient);
|
||||
const dmRooms = dmRoomMap.getDMRoomsForUserId(this.props.member.userId);
|
||||
|
@ -702,7 +699,7 @@ module.exports = withMatrixClient(React.createClass({
|
|||
highlight={highlight}
|
||||
isInvite={me.membership == "invite"}
|
||||
onClick={this.onRoomTileClick}
|
||||
/>
|
||||
/>,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -723,14 +720,14 @@ module.exports = withMatrixClient(React.createClass({
|
|||
|
||||
startChat = <div>
|
||||
<h3>{ _t("Direct chats") }</h3>
|
||||
{tiles}
|
||||
{startNewChat}
|
||||
{ tiles }
|
||||
{ startNewChat }
|
||||
</div>;
|
||||
}
|
||||
|
||||
if (this.state.updating) {
|
||||
var Loader = sdk.getComponent("elements.Spinner");
|
||||
spinner = <Loader imgClassName="mx_ContextualMenu_spinner"/>;
|
||||
const Loader = sdk.getComponent("elements.Spinner");
|
||||
spinner = <Loader imgClassName="mx_ContextualMenu_spinner" />;
|
||||
}
|
||||
|
||||
if (this.state.can.kick) {
|
||||
|
@ -739,7 +736,7 @@ module.exports = withMatrixClient(React.createClass({
|
|||
kickButton = (
|
||||
<AccessibleButton className="mx_MemberInfo_field"
|
||||
onClick={this.onKick}>
|
||||
{kickLabel}
|
||||
{ kickLabel }
|
||||
</AccessibleButton>
|
||||
);
|
||||
}
|
||||
|
@ -751,7 +748,7 @@ module.exports = withMatrixClient(React.createClass({
|
|||
banButton = (
|
||||
<AccessibleButton className="mx_MemberInfo_field"
|
||||
onClick={this.onBanOrUnban}>
|
||||
{label}
|
||||
{ label }
|
||||
</AccessibleButton>
|
||||
);
|
||||
}
|
||||
|
@ -760,31 +757,31 @@ module.exports = withMatrixClient(React.createClass({
|
|||
muteButton = (
|
||||
<AccessibleButton className="mx_MemberInfo_field"
|
||||
onClick={this.onMuteToggle}>
|
||||
{muteLabel}
|
||||
{ muteLabel }
|
||||
</AccessibleButton>
|
||||
);
|
||||
}
|
||||
if (this.state.can.toggleMod) {
|
||||
var giveOpLabel = this.state.isTargetMod ? _t("Revoke Moderator") : _t("Make Moderator");
|
||||
const giveOpLabel = this.state.isTargetMod ? _t("Revoke Moderator") : _t("Make Moderator");
|
||||
giveModButton = <AccessibleButton className="mx_MemberInfo_field" onClick={this.onModToggle}>
|
||||
{giveOpLabel}
|
||||
{ giveOpLabel }
|
||||
</AccessibleButton>;
|
||||
}
|
||||
|
||||
// TODO: we should have an invite button if this MemberInfo is showing a user who isn't actually in the current room yet
|
||||
// e.g. clicking on a linkified userid in a room
|
||||
|
||||
var adminTools;
|
||||
let adminTools;
|
||||
if (kickButton || banButton || muteButton || giveModButton) {
|
||||
adminTools =
|
||||
<div>
|
||||
<h3>{_t("Admin Tools")}</h3>
|
||||
<h3>{ _t("Admin Tools") }</h3>
|
||||
|
||||
<div className="mx_MemberInfo_buttons">
|
||||
{muteButton}
|
||||
{kickButton}
|
||||
{banButton}
|
||||
{giveModButton}
|
||||
{ muteButton }
|
||||
{ kickButton }
|
||||
{ banButton }
|
||||
{ giveModButton }
|
||||
</div>
|
||||
</div>;
|
||||
}
|
||||
|
@ -794,35 +791,35 @@ module.exports = withMatrixClient(React.createClass({
|
|||
if (this.props.member.user) {
|
||||
var presenceState = this.props.member.user.presence;
|
||||
var presenceLastActiveAgo = this.props.member.user.lastActiveAgo;
|
||||
var presenceLastTs = this.props.member.user.lastPresenceTs;
|
||||
const presenceLastTs = this.props.member.user.lastPresenceTs;
|
||||
var presenceCurrentlyActive = this.props.member.user.currentlyActive;
|
||||
}
|
||||
|
||||
var MemberAvatar = sdk.getComponent('avatars.MemberAvatar');
|
||||
var PowerSelector = sdk.getComponent('elements.PowerSelector');
|
||||
var PresenceLabel = sdk.getComponent('rooms.PresenceLabel');
|
||||
const MemberAvatar = sdk.getComponent('avatars.MemberAvatar');
|
||||
const PowerSelector = sdk.getComponent('elements.PowerSelector');
|
||||
const PresenceLabel = sdk.getComponent('rooms.PresenceLabel');
|
||||
const EmojiText = sdk.getComponent('elements.EmojiText');
|
||||
return (
|
||||
<div className="mx_MemberInfo">
|
||||
<GeminiScrollbar autoshow={true}>
|
||||
<AccessibleButton className="mx_MemberInfo_cancel" onClick={this.onCancel}> <img src="img/cancel.svg" width="18" height="18"/></AccessibleButton>
|
||||
<AccessibleButton className="mx_MemberInfo_cancel" onClick={this.onCancel}> <img src="img/cancel.svg" width="18" height="18" /></AccessibleButton>
|
||||
<div className="mx_MemberInfo_avatar">
|
||||
<MemberAvatar onClick={this.onMemberAvatarClick} member={this.props.member} width={48} height={48} />
|
||||
</div>
|
||||
|
||||
<EmojiText element="h2">{memberName}</EmojiText>
|
||||
<EmojiText element="h2">{ memberName }</EmojiText>
|
||||
|
||||
<div className="mx_MemberInfo_profile">
|
||||
<div className="mx_MemberInfo_profileField">
|
||||
{ this.props.member.userId }
|
||||
</div>
|
||||
<div className="mx_MemberInfo_profileField">
|
||||
{ _t("Level:") } <b><PowerSelector controlled={true} value={ parseInt(this.props.member.powerLevel) } disabled={ !this.state.can.modifyLevel } onChange={ this.onPowerChange }/></b>
|
||||
{ _t("Level:") } <b><PowerSelector controlled={true} value={parseInt(this.props.member.powerLevel)} disabled={!this.state.can.modifyLevel} onChange={this.onPowerChange} /></b>
|
||||
</div>
|
||||
<div className="mx_MemberInfo_profileField">
|
||||
<PresenceLabel activeAgo={ presenceLastActiveAgo }
|
||||
currentlyActive={ presenceCurrentlyActive }
|
||||
presenceState={ presenceState } />
|
||||
<PresenceLabel activeAgo={presenceLastActiveAgo}
|
||||
currentlyActive={presenceCurrentlyActive}
|
||||
presenceState={presenceState} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -838,5 +835,5 @@ module.exports = withMatrixClient(React.createClass({
|
|||
</GeminiScrollbar>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
},
|
||||
}));
|
||||
|
|
|
@ -18,11 +18,11 @@ limitations under the License.
|
|||
|
||||
import React from 'react';
|
||||
import { _t } from '../../../languageHandler';
|
||||
var MatrixClientPeg = require("../../../MatrixClientPeg");
|
||||
var sdk = require('../../../index');
|
||||
var GeminiScrollbar = require('react-gemini-scrollbar');
|
||||
var rate_limited_func = require('../../../ratelimitedfunc');
|
||||
var CallHandler = require("../../../CallHandler");
|
||||
const MatrixClientPeg = require("../../../MatrixClientPeg");
|
||||
const sdk = require('../../../index');
|
||||
const GeminiScrollbar = require('react-gemini-scrollbar');
|
||||
const rate_limited_func = require('../../../ratelimitedfunc');
|
||||
const CallHandler = require("../../../CallHandler");
|
||||
|
||||
const INITIAL_LOAD_NUM_MEMBERS = 30;
|
||||
const INITIAL_LOAD_NUM_INVITED = 5;
|
||||
|
@ -49,7 +49,7 @@ module.exports = React.createClass({
|
|||
},
|
||||
|
||||
componentWillMount: function() {
|
||||
var cli = MatrixClientPeg.get();
|
||||
const cli = MatrixClientPeg.get();
|
||||
cli.on("RoomState.members", this.onRoomStateMember);
|
||||
cli.on("RoomMember.name", this.onRoomMemberName);
|
||||
cli.on("RoomState.events", this.onRoomStateEvent);
|
||||
|
@ -62,7 +62,7 @@ module.exports = React.createClass({
|
|||
},
|
||||
|
||||
componentWillUnmount: function() {
|
||||
var cli = MatrixClientPeg.get();
|
||||
const cli = MatrixClientPeg.get();
|
||||
if (cli) {
|
||||
cli.removeListener("RoomState.members", this.onRoomStateMember);
|
||||
cli.removeListener("RoomMember.name", this.onRoomMemberName);
|
||||
|
@ -109,7 +109,7 @@ module.exports = React.createClass({
|
|||
// member tile and re-render it. This is more efficient than every tile
|
||||
// evar attaching their own listener.
|
||||
// console.log("explicit presence from " + user.userId);
|
||||
var tile = this.refs[user.userId];
|
||||
const tile = this.refs[user.userId];
|
||||
if (tile) {
|
||||
this._updateList(); // reorder the membership list
|
||||
}
|
||||
|
@ -146,18 +146,18 @@ module.exports = React.createClass({
|
|||
const newState = {
|
||||
members: this.roomMembers(),
|
||||
};
|
||||
newState.filteredJoinedMembers = this._filterMembers(newState.members, 'join');
|
||||
newState.filteredInvitedMembers = this._filterMembers(newState.members, 'invite');
|
||||
newState.filteredJoinedMembers = this._filterMembers(newState.members, 'join', this.state.searchQuery);
|
||||
newState.filteredInvitedMembers = this._filterMembers(newState.members, 'invite', this.state.searchQuery);
|
||||
this.setState(newState);
|
||||
}, 500),
|
||||
|
||||
getMemberDict: function() {
|
||||
if (!this.props.roomId) return {};
|
||||
var cli = MatrixClientPeg.get();
|
||||
var room = cli.getRoom(this.props.roomId);
|
||||
const cli = MatrixClientPeg.get();
|
||||
const room = cli.getRoom(this.props.roomId);
|
||||
if (!room) return {};
|
||||
|
||||
var all_members = room.currentState.members;
|
||||
const all_members = room.currentState.members;
|
||||
|
||||
Object.keys(all_members).map(function(userId) {
|
||||
// work around a race where you might have a room member object
|
||||
|
@ -175,19 +175,19 @@ module.exports = React.createClass({
|
|||
},
|
||||
|
||||
roomMembers: function() {
|
||||
var all_members = this.memberDict || {};
|
||||
var all_user_ids = Object.keys(all_members);
|
||||
var ConferenceHandler = CallHandler.getConferenceHandler();
|
||||
const all_members = this.memberDict || {};
|
||||
const all_user_ids = Object.keys(all_members);
|
||||
const ConferenceHandler = CallHandler.getConferenceHandler();
|
||||
|
||||
all_user_ids.sort(this.memberSort);
|
||||
|
||||
var to_display = [];
|
||||
var count = 0;
|
||||
for (var i = 0; i < all_user_ids.length; ++i) {
|
||||
var user_id = all_user_ids[i];
|
||||
var m = all_members[user_id];
|
||||
const to_display = [];
|
||||
let count = 0;
|
||||
for (let i = 0; i < all_user_ids.length; ++i) {
|
||||
const user_id = all_user_ids[i];
|
||||
const m = all_members[user_id];
|
||||
|
||||
if (m.membership == 'join' || m.membership == 'invite') {
|
||||
if (m.membership === 'join' || m.membership === 'invite') {
|
||||
if ((ConferenceHandler && !ConferenceHandler.isConferenceUser(user_id)) || !ConferenceHandler) {
|
||||
to_display.push(user_id);
|
||||
++count;
|
||||
|
@ -233,8 +233,7 @@ module.exports = React.createClass({
|
|||
memberString: function(member) {
|
||||
if (!member) {
|
||||
return "(null)";
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return "(" + member.name + ", " + member.powerLevel + ", " + member.user.lastActiveAgo + ", " + member.user.currentlyActive + ")";
|
||||
}
|
||||
},
|
||||
|
@ -248,10 +247,10 @@ module.exports = React.createClass({
|
|||
// ...and then alphabetically.
|
||||
// We could tiebreak instead by "last recently spoken in this room" if we wanted to.
|
||||
|
||||
var memberA = this.memberDict[userIdA];
|
||||
var memberB = this.memberDict[userIdB];
|
||||
var userA = memberA.user;
|
||||
var userB = memberB.user;
|
||||
const memberA = this.memberDict[userIdA];
|
||||
const memberB = this.memberDict[userIdB];
|
||||
const userA = memberA.user;
|
||||
const userB = memberB.user;
|
||||
|
||||
// if (!userA || !userB) {
|
||||
// console.log("comparing " + memberA.name + " user=" + memberA.user + " with " + memberB.name + " user=" + memberB.user);
|
||||
|
@ -269,15 +268,13 @@ module.exports = React.createClass({
|
|||
// console.log(memberA + " and " + memberB + " have same power level");
|
||||
if (memberA.name && memberB.name) {
|
||||
// console.log("comparing names: " + memberA.name + " and " + memberB.name);
|
||||
var nameA = memberA.name[0] === '@' ? memberA.name.substr(1) : memberA.name;
|
||||
var nameB = memberB.name[0] === '@' ? memberB.name.substr(1) : memberB.name;
|
||||
const nameA = memberA.name[0] === '@' ? memberA.name.substr(1) : memberA.name;
|
||||
const nameB = memberB.name[0] === '@' ? memberB.name.substr(1) : memberB.name;
|
||||
return nameA.localeCompare(nameB);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
// console.log("comparing power: " + memberA.powerLevel + " and " + memberB.powerLevel);
|
||||
return memberB.powerLevel - memberA.powerLevel;
|
||||
}
|
||||
|
@ -305,6 +302,7 @@ module.exports = React.createClass({
|
|||
const m = this.memberDict[userId];
|
||||
|
||||
if (query) {
|
||||
query = query.toLowerCase();
|
||||
const matchesName = m.name.toLowerCase().indexOf(query) !== -1;
|
||||
const matchesId = m.userId.toLowerCase().indexOf(query) !== -1;
|
||||
|
||||
|
@ -313,7 +311,7 @@ module.exports = React.createClass({
|
|||
}
|
||||
}
|
||||
|
||||
return m.membership == membership;
|
||||
return m.membership === membership;
|
||||
});
|
||||
},
|
||||
|
||||
|
@ -336,25 +334,25 @@ module.exports = React.createClass({
|
|||
// The HS may have already converted these into m.room.member invites so
|
||||
// we shouldn't add them if the 3pid invite state key (token) is in the
|
||||
// member invite (content.third_party_invite.signed.token)
|
||||
var room = MatrixClientPeg.get().getRoom(this.props.roomId);
|
||||
var EntityTile = sdk.getComponent("rooms.EntityTile");
|
||||
const room = MatrixClientPeg.get().getRoom(this.props.roomId);
|
||||
const EntityTile = sdk.getComponent("rooms.EntityTile");
|
||||
if (room) {
|
||||
room.currentState.getStateEvents("m.room.third_party_invite").forEach(
|
||||
function(e) {
|
||||
// any events without these keys are not valid 3pid invites, so we ignore them
|
||||
var required_keys = ['key_validity_url', 'public_key', 'display_name'];
|
||||
for (var i = 0; i < required_keys.length; ++i) {
|
||||
const required_keys = ['key_validity_url', 'public_key', 'display_name'];
|
||||
for (let i = 0; i < required_keys.length; ++i) {
|
||||
if (e.getContent()[required_keys[i]] === undefined) return;
|
||||
}
|
||||
|
||||
// discard all invites which have a m.room.member event since we've
|
||||
// already added them.
|
||||
var memberEvent = room.currentState.getInviteForThreePidToken(e.getStateKey());
|
||||
const memberEvent = room.currentState.getInviteForThreePidToken(e.getStateKey());
|
||||
if (memberEvent) {
|
||||
return;
|
||||
}
|
||||
memberList.push(
|
||||
<EntityTile key={e.getStateKey()} name={e.getContent().display_name} suppressOnHover={true} />
|
||||
<EntityTile key={e.getStateKey()} name={e.getContent().display_name} suppressOnHover={true} />,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
@ -402,7 +400,7 @@ module.exports = React.createClass({
|
|||
<form autoComplete="off">
|
||||
<input className="mx_MemberList_query" id="mx_MemberList_query" type="text"
|
||||
onChange={this.onSearchQueryChanged} value={this.state.searchQuery}
|
||||
placeholder={ _t('Filter room members') } />
|
||||
placeholder={_t('Filter room members')} />
|
||||
</form>
|
||||
);
|
||||
|
||||
|
@ -415,9 +413,9 @@ module.exports = React.createClass({
|
|||
getChildren={this._getChildrenJoined}
|
||||
getChildCount={this._getChildCountJoined}
|
||||
/>
|
||||
{invitedSection}
|
||||
{ invitedSection }
|
||||
</GeminiScrollbar>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
|
|
@ -16,12 +16,12 @@ limitations under the License.
|
|||
|
||||
'use strict';
|
||||
|
||||
var React = require('react');
|
||||
const React = require('react');
|
||||
|
||||
var MatrixClientPeg = require('../../../MatrixClientPeg');
|
||||
var sdk = require('../../../index');
|
||||
var dis = require('../../../dispatcher');
|
||||
var Modal = require("../../../Modal");
|
||||
const MatrixClientPeg = require('../../../MatrixClientPeg');
|
||||
const sdk = require('../../../index');
|
||||
const dis = require('../../../dispatcher');
|
||||
const Modal = require("../../../Modal");
|
||||
import { _t } from '../../../languageHandler';
|
||||
|
||||
module.exports = React.createClass({
|
||||
|
@ -68,16 +68,16 @@ module.exports = React.createClass({
|
|||
},
|
||||
|
||||
render: function() {
|
||||
var MemberAvatar = sdk.getComponent('avatars.MemberAvatar');
|
||||
var BaseAvatar = sdk.getComponent('avatars.BaseAvatar');
|
||||
var EntityTile = sdk.getComponent('rooms.EntityTile');
|
||||
const MemberAvatar = sdk.getComponent('avatars.MemberAvatar');
|
||||
const BaseAvatar = sdk.getComponent('avatars.BaseAvatar');
|
||||
const EntityTile = sdk.getComponent('rooms.EntityTile');
|
||||
|
||||
var member = this.props.member;
|
||||
var name = this._getDisplayName();
|
||||
var active = -1;
|
||||
var presenceState = member.user ? member.user.presence : null;
|
||||
const member = this.props.member;
|
||||
const name = this._getDisplayName();
|
||||
const active = -1;
|
||||
const presenceState = member.user ? member.user.presence : null;
|
||||
|
||||
var av = (
|
||||
const av = (
|
||||
<MemberAvatar member={member} width={36} height={36} />
|
||||
);
|
||||
|
||||
|
@ -88,11 +88,11 @@ module.exports = React.createClass({
|
|||
|
||||
return (
|
||||
<EntityTile {...this.props} presenceState={presenceState}
|
||||
presenceLastActiveAgo={ member.user ? member.user.lastActiveAgo : 0 }
|
||||
presenceLastTs={ member.user ? member.user.lastPresenceTs : 0 }
|
||||
presenceCurrentlyActive={ member.user ? member.user.currentlyActive : false }
|
||||
presenceLastActiveAgo={member.user ? member.user.lastActiveAgo : 0}
|
||||
presenceLastTs={member.user ? member.user.lastPresenceTs : 0}
|
||||
presenceCurrentlyActive={member.user ? member.user.currentlyActive : false}
|
||||
avatarJsx={av} title={this.getPowerLabel()} onClick={this.onClick}
|
||||
name={name} powerLevel={this.props.member.powerLevel} />
|
||||
);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
Copyright 2015, 2016 OpenMarket Ltd
|
||||
Copyright 2017 New Vector Ltd
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
@ -89,13 +90,13 @@ export default class MessageComposer extends React.Component {
|
|||
}
|
||||
|
||||
uploadFiles(files) {
|
||||
let QuestionDialog = sdk.getComponent("dialogs.QuestionDialog");
|
||||
let TintableSvg = sdk.getComponent("elements.TintableSvg");
|
||||
const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog");
|
||||
const TintableSvg = sdk.getComponent("elements.TintableSvg");
|
||||
|
||||
let fileList = [];
|
||||
const fileList = [];
|
||||
for (let i=0; i<files.length; i++) {
|
||||
fileList.push(<li key={i}>
|
||||
<TintableSvg key={i} src="img/files.svg" width="16" height="16" /> {files[i].name || _t('Attachment')}
|
||||
<TintableSvg key={i} src="img/files.svg" width="16" height="16" /> { files[i].name || _t('Attachment') }
|
||||
</li>);
|
||||
}
|
||||
|
||||
|
@ -105,7 +106,7 @@ export default class MessageComposer extends React.Component {
|
|||
<div>
|
||||
<p>{ _t('Are you sure you want to upload the following files?') }</p>
|
||||
<ul style={{listStyle: 'none', textAlign: 'left'}}>
|
||||
{fileList}
|
||||
{ fileList }
|
||||
</ul>
|
||||
</div>
|
||||
),
|
||||
|
@ -271,32 +272,30 @@ export default class MessageComposer extends React.Component {
|
|||
if (this.props.callState && this.props.callState !== 'ended') {
|
||||
hangupButton =
|
||||
<div key="controls_hangup" className="mx_MessageComposer_hangup" onClick={this.onHangupClick}>
|
||||
<img src="img/hangup.svg" alt={ _t('Hangup') } title={ _t('Hangup') } width="25" height="26"/>
|
||||
<img src="img/hangup.svg" alt={_t('Hangup')} title={_t('Hangup')} width="25" height="26" />
|
||||
</div>;
|
||||
} else {
|
||||
callButton =
|
||||
<div key="controls_call" className="mx_MessageComposer_voicecall" onClick={this.onVoiceCallClick} title={ _t('Voice call') }>
|
||||
<TintableSvg src="img/icon-call.svg" width="35" height="35"/>
|
||||
<div key="controls_call" className="mx_MessageComposer_voicecall" onClick={this.onVoiceCallClick} title={_t('Voice call')}>
|
||||
<TintableSvg src="img/icon-call.svg" width="35" height="35" />
|
||||
</div>;
|
||||
videoCallButton =
|
||||
<div key="controls_videocall" className="mx_MessageComposer_videocall" onClick={this.onCallClick} title={ _t('Video call') }>
|
||||
<TintableSvg src="img/icons-video.svg" width="35" height="35"/>
|
||||
<div key="controls_videocall" className="mx_MessageComposer_videocall" onClick={this.onCallClick} title={_t('Video call')}>
|
||||
<TintableSvg src="img/icons-video.svg" width="35" height="35" />
|
||||
</div>;
|
||||
}
|
||||
|
||||
// Apps
|
||||
if (UserSettingsStore.isFeatureEnabled('matrix_apps')) {
|
||||
if (this.props.showApps) {
|
||||
hideAppsButton =
|
||||
<div key="controls_hide_apps" className="mx_MessageComposer_apps" onClick={this.onHideAppsClick} title={_t("Hide Apps")}>
|
||||
<TintableSvg src="img/icons-hide-apps.svg" width="35" height="35"/>
|
||||
</div>;
|
||||
} else {
|
||||
showAppsButton =
|
||||
<div key="show_apps" className="mx_MessageComposer_apps" onClick={this.onShowAppsClick} title={_t("Show Apps")}>
|
||||
<TintableSvg src="img/icons-show-apps.svg" width="35" height="35"/>
|
||||
</div>;
|
||||
}
|
||||
if (this.props.showApps) {
|
||||
hideAppsButton =
|
||||
<div key="controls_hide_apps" className="mx_MessageComposer_apps" onClick={this.onHideAppsClick} title={_t("Hide Apps")}>
|
||||
<TintableSvg src="img/icons-hide-apps.svg" width="35" height="35" />
|
||||
</div>;
|
||||
} else {
|
||||
showAppsButton =
|
||||
<div key="show_apps" className="mx_MessageComposer_apps" onClick={this.onShowAppsClick} title={_t("Show Apps")}>
|
||||
<TintableSvg src="img/icons-show-apps.svg" width="35" height="35" />
|
||||
</div>;
|
||||
}
|
||||
|
||||
const canSendMessages = this.props.room.currentState.maySendMessage(
|
||||
|
@ -308,8 +307,8 @@ export default class MessageComposer extends React.Component {
|
|||
// complex because of conference calls.
|
||||
const uploadButton = (
|
||||
<div key="controls_upload" className="mx_MessageComposer_upload"
|
||||
onClick={this.onUploadClick} title={ _t('Upload file') }>
|
||||
<TintableSvg src="img/icons-upload.svg" width="35" height="35"/>
|
||||
onClick={this.onUploadClick} title={_t('Upload file')}>
|
||||
<TintableSvg src="img/icons-upload.svg" width="35" height="35" />
|
||||
<input ref="uploadInput" type="file"
|
||||
style={uploadInputStyle}
|
||||
multiple
|
||||
|
@ -363,7 +362,7 @@ export default class MessageComposer extends React.Component {
|
|||
const onFormatButtonClicked = this.onFormatButtonClicked.bind(this, name);
|
||||
const className = 'mx_MessageComposer_format_button mx_filterFlipColor';
|
||||
return <img className={className}
|
||||
title={ _t(name) }
|
||||
title={_t(name)}
|
||||
onMouseDown={onFormatButtonClicked}
|
||||
key={name}
|
||||
src={`img/button-text-${name}${suffix}.svg`}
|
||||
|
@ -375,18 +374,18 @@ export default class MessageComposer extends React.Component {
|
|||
<div className="mx_MessageComposer mx_fadable" style={{ opacity: this.props.opacity }}>
|
||||
<div className="mx_MessageComposer_wrapper">
|
||||
<div className="mx_MessageComposer_row">
|
||||
{controls}
|
||||
{ controls }
|
||||
</div>
|
||||
</div>
|
||||
<div className="mx_MessageComposer_formatbar_wrapper">
|
||||
<div className="mx_MessageComposer_formatbar" style={this.state.showFormatting ? {} : {display: 'none'}}>
|
||||
{formatButtons}
|
||||
{ formatButtons }
|
||||
<div style={{flex: 1}}></div>
|
||||
<img title={ this.state.inputState.isRichtextEnabled ? _t("Turn Markdown on") : _t("Turn Markdown off") }
|
||||
<img title={this.state.inputState.isRichtextEnabled ? _t("Turn Markdown on") : _t("Turn Markdown off")}
|
||||
onMouseDown={this.onToggleMarkdownClicked}
|
||||
className="mx_MessageComposer_formatbar_markdown mx_filterFlipColor"
|
||||
src={`img/button-md-${!this.state.inputState.isRichtextEnabled}.png`} />
|
||||
<img title={ _t("Hide Text Formatting Toolbar") }
|
||||
<img title={_t("Hide Text Formatting Toolbar")}
|
||||
onClick={this.onToggleFormattingClicked}
|
||||
className="mx_MessageComposer_formatbar_cancel mx_filterFlipColor"
|
||||
src="img/icon-text-cancel.svg" />
|
||||
|
|
|
@ -224,7 +224,7 @@ export default class MessageComposerInput extends React.Component {
|
|||
|
||||
return (
|
||||
<a href={url} data-offset-key={entityProps.offsetKey}>
|
||||
{entityProps.children}
|
||||
{ entityProps.children }
|
||||
</a>
|
||||
);
|
||||
},
|
||||
|
@ -286,7 +286,7 @@ export default class MessageComposerInput extends React.Component {
|
|||
/// XXX: Not doing rich-text quoting from formatted-body because draft-js
|
||||
/// has regressed such that when links are quoted, errors are thrown. See
|
||||
/// https://github.com/vector-im/riot-web/issues/4756.
|
||||
let body = escape(payload.text);
|
||||
const body = escape(payload.text);
|
||||
if (body) {
|
||||
let content = RichText.htmlToContentState(`<blockquote>${body}</blockquote>`);
|
||||
if (!this.state.isRichtextEnabled) {
|
||||
|
@ -464,7 +464,7 @@ export default class MessageComposerInput extends React.Component {
|
|||
// autocomplete will probably have different completions to show.
|
||||
if (
|
||||
!state.editorState.getSelection().equals(
|
||||
this.state.editorState.getSelection()
|
||||
this.state.editorState.getSelection(),
|
||||
)
|
||||
&& state.editorState.getCurrentContent().getPlainText() ===
|
||||
this.state.editorState.getCurrentContent().getPlainText()
|
||||
|
@ -974,7 +974,6 @@ export default class MessageComposerInput extends React.Component {
|
|||
editorState = EditorState.forceSelection(editorState,
|
||||
editorState.getSelection());
|
||||
this.setState({editorState});
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -1134,12 +1133,12 @@ export default class MessageComposerInput extends React.Component {
|
|||
onConfirm={this.setDisplayedCompletion}
|
||||
onSelectionChange={this.setDisplayedCompletion}
|
||||
query={this.getAutocompleteQuery(content)}
|
||||
selection={selection}/>
|
||||
selection={selection} />
|
||||
</div>
|
||||
<div className={className}>
|
||||
<img className="mx_MessageComposer_input_markdownIndicator mx_filterFlipColor"
|
||||
onMouseDown={this.onMarkdownToggleClicked}
|
||||
title={ this.state.isRichtextEnabled ? _t("Markdown is disabled") : _t("Markdown is enabled")}
|
||||
title={this.state.isRichtextEnabled ? _t("Markdown is disabled") : _t("Markdown is enabled")}
|
||||
src={`img/button-md-${!this.state.isRichtextEnabled}.png`} />
|
||||
<Editor ref="editor"
|
||||
dir="auto"
|
||||
|
@ -1157,7 +1156,7 @@ export default class MessageComposerInput extends React.Component {
|
|||
onUpArrow={this.onUpArrow}
|
||||
onDownArrow={this.onDownArrow}
|
||||
onEscape={this.onEscape}
|
||||
spellCheck={true}/>
|
||||
spellCheck={true} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -34,23 +34,23 @@ module.exports = React.createClass({
|
|||
currentlyActive: React.PropTypes.bool,
|
||||
|
||||
// offline, online, etc
|
||||
presenceState: React.PropTypes.string
|
||||
presenceState: React.PropTypes.string,
|
||||
},
|
||||
|
||||
getDefaultProps: function() {
|
||||
return {
|
||||
ago: -1,
|
||||
presenceState: null
|
||||
presenceState: null,
|
||||
};
|
||||
},
|
||||
|
||||
getDuration: function(time) {
|
||||
if (!time) return;
|
||||
var t = parseInt(time / 1000);
|
||||
var s = t % 60;
|
||||
var m = parseInt(t / 60) % 60;
|
||||
var h = parseInt(t / (60 * 60)) % 24;
|
||||
var d = parseInt(t / (60 * 60 * 24));
|
||||
const t = parseInt(time / 1000);
|
||||
const s = t % 60;
|
||||
const m = parseInt(t / 60) % 60;
|
||||
const h = parseInt(t / (60 * 60)) % 24;
|
||||
const d = parseInt(t / (60 * 60 * 24));
|
||||
if (t < 60) {
|
||||
if (t < 0) {
|
||||
return _t("for %(amount)ss", {amount: 0});
|
||||
|
@ -58,12 +58,12 @@ module.exports = React.createClass({
|
|||
return _t("for %(amount)ss", {amount: s});
|
||||
}
|
||||
if (t < 60 * 60) {
|
||||
return _t("for %(amount)sm", {amount: m});
|
||||
return _t("for %(amount)sm", {amount: m});
|
||||
}
|
||||
if (t < 24 * 60 * 60) {
|
||||
return _t("for %(amount)sh", {amount: h});
|
||||
return _t("for %(amount)sh", {amount: h});
|
||||
}
|
||||
return _t("for %(amount)sd", {amount: d});
|
||||
return _t("for %(amount)sd", {amount: d});
|
||||
},
|
||||
|
||||
getPrettyPresence: function(presence) {
|
||||
|
@ -75,20 +75,19 @@ module.exports = React.createClass({
|
|||
|
||||
render: function() {
|
||||
if (this.props.activeAgo >= 0) {
|
||||
let duration = this.getDuration(this.props.activeAgo);
|
||||
let ago = this.props.currentlyActive || !duration ? "" : duration;
|
||||
const duration = this.getDuration(this.props.activeAgo);
|
||||
const ago = this.props.currentlyActive || !duration ? "" : duration;
|
||||
return (
|
||||
<div className="mx_PresenceLabel">
|
||||
{ this.getPrettyPresence(this.props.presenceState) } { ago }
|
||||
</div>
|
||||
);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return (
|
||||
<div className="mx_PresenceLabel">
|
||||
{ this.getPrettyPresence(this.props.presenceState) }
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
|
|
|
@ -16,18 +16,18 @@ limitations under the License.
|
|||
|
||||
'use strict';
|
||||
|
||||
var React = require('react');
|
||||
var ReactDOM = require('react-dom');
|
||||
const React = require('react');
|
||||
const ReactDOM = require('react-dom');
|
||||
|
||||
var sdk = require('../../../index');
|
||||
const sdk = require('../../../index');
|
||||
|
||||
var Velociraptor = require('../../../Velociraptor');
|
||||
const Velociraptor = require('../../../Velociraptor');
|
||||
require('../../../VelocityBounce');
|
||||
import { _t } from '../../../languageHandler';
|
||||
|
||||
import DateUtils from '../../../DateUtils';
|
||||
|
||||
var bounce = false;
|
||||
let bounce = false;
|
||||
try {
|
||||
if (global.localStorage) {
|
||||
bounce = global.localStorage.getItem('avatar_bounce') == 'true';
|
||||
|
@ -90,7 +90,7 @@ module.exports = React.createClass({
|
|||
componentWillUnmount: function() {
|
||||
// before we remove the rr, store its location in the map, so that if
|
||||
// it reappears, it can be animated from the right place.
|
||||
var rrInfo = this.props.readReceiptInfo;
|
||||
const rrInfo = this.props.readReceiptInfo;
|
||||
if (!rrInfo) {
|
||||
return;
|
||||
}
|
||||
|
@ -102,7 +102,7 @@ module.exports = React.createClass({
|
|||
return;
|
||||
}
|
||||
|
||||
var avatarNode = ReactDOM.findDOMNode(this);
|
||||
const avatarNode = ReactDOM.findDOMNode(this);
|
||||
rrInfo.top = avatarNode.offsetTop;
|
||||
rrInfo.left = avatarNode.offsetLeft;
|
||||
rrInfo.parent = avatarNode.offsetParent;
|
||||
|
@ -115,14 +115,14 @@ module.exports = React.createClass({
|
|||
}
|
||||
|
||||
// treat new RRs as though they were off the top of the screen
|
||||
var oldTop = -15;
|
||||
let oldTop = -15;
|
||||
|
||||
var oldInfo = this.props.readReceiptInfo;
|
||||
const oldInfo = this.props.readReceiptInfo;
|
||||
if (oldInfo && oldInfo.parent) {
|
||||
oldTop = oldInfo.top + oldInfo.parent.getBoundingClientRect().top;
|
||||
}
|
||||
|
||||
var newElement = ReactDOM.findDOMNode(this);
|
||||
const newElement = ReactDOM.findDOMNode(this);
|
||||
let startTopOffset;
|
||||
if (!newElement.offsetParent) {
|
||||
// this seems to happen sometimes for reasons I don't understand
|
||||
|
@ -137,8 +137,8 @@ module.exports = React.createClass({
|
|||
startTopOffset = oldTop - newElement.offsetParent.getBoundingClientRect().top;
|
||||
}
|
||||
|
||||
var startStyles = [];
|
||||
var enterTransitionOpts = [];
|
||||
const startStyles = [];
|
||||
const enterTransitionOpts = [];
|
||||
|
||||
if (oldInfo && oldInfo.left) {
|
||||
// start at the old height and in the old h pos
|
||||
|
@ -146,7 +146,7 @@ module.exports = React.createClass({
|
|||
startStyles.push({ top: startTopOffset+"px",
|
||||
left: oldInfo.left+"px" });
|
||||
|
||||
var reorderTransitionOpts = {
|
||||
const reorderTransitionOpts = {
|
||||
duration: 100,
|
||||
easing: 'easeOut',
|
||||
};
|
||||
|
@ -171,12 +171,12 @@ module.exports = React.createClass({
|
|||
|
||||
|
||||
render: function() {
|
||||
var MemberAvatar = sdk.getComponent('avatars.MemberAvatar');
|
||||
const MemberAvatar = sdk.getComponent('avatars.MemberAvatar');
|
||||
if (this.state.suppressDisplay) {
|
||||
return <div/>;
|
||||
return <div />;
|
||||
}
|
||||
|
||||
var style = {
|
||||
const style = {
|
||||
left: this.props.leftOffset+'px',
|
||||
top: '0px',
|
||||
visibility: this.props.hidden ? 'hidden' : 'visible',
|
||||
|
|
|
@ -129,6 +129,10 @@ module.exports = React.createClass({
|
|||
}).done();
|
||||
},
|
||||
|
||||
onAvatarRemoveClick: function() {
|
||||
MatrixClientPeg.get().sendStateEvent(this.props.room.roomId, 'm.room.avatar', {url: null}, '');
|
||||
},
|
||||
|
||||
onShowRhsClick: function(ev) {
|
||||
dis.dispatch({ action: 'show_right_panel' });
|
||||
},
|
||||
|
@ -268,11 +272,15 @@ module.exports = React.createClass({
|
|||
<div className="mx_RoomHeader_avatarPicker_edit">
|
||||
<label htmlFor="avatarInput" ref="file_label">
|
||||
<img src="img/camera.svg"
|
||||
alt={_t("Upload avatar")} title={_t("Upload avatar")}
|
||||
width="17" height="15" />
|
||||
alt={_t("Upload avatar")} title={_t("Upload avatar")}
|
||||
width="17" height="15" />
|
||||
</label>
|
||||
<input id="avatarInput" type="file" onChange={this.onAvatarSelected} />
|
||||
</div>
|
||||
<div className="mx_RoomHeader_avatarPicker_remove" onClick={this.onAvatarRemoveClick}>
|
||||
<img src="img/cancel.svg" width="10"
|
||||
alt={_t("Remove avatar")} title={_t("Remove avatar")} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
} else if (this.props.room || (this.props.oobData && this.props.oobData.name)) {
|
||||
|
|
|
@ -16,20 +16,20 @@ limitations under the License.
|
|||
*/
|
||||
|
||||
'use strict';
|
||||
var React = require("react");
|
||||
var ReactDOM = require("react-dom");
|
||||
const React = require("react");
|
||||
const ReactDOM = require("react-dom");
|
||||
import { _t, _tJsx } from '../../../languageHandler';
|
||||
var GeminiScrollbar = require('react-gemini-scrollbar');
|
||||
var MatrixClientPeg = require("../../../MatrixClientPeg");
|
||||
var CallHandler = require('../../../CallHandler');
|
||||
var RoomListSorter = require("../../../RoomListSorter");
|
||||
var Unread = require('../../../Unread');
|
||||
var dis = require("../../../dispatcher");
|
||||
var sdk = require('../../../index');
|
||||
var rate_limited_func = require('../../../ratelimitedfunc');
|
||||
var Rooms = require('../../../Rooms');
|
||||
const GeminiScrollbar = require('react-gemini-scrollbar');
|
||||
const MatrixClientPeg = require("../../../MatrixClientPeg");
|
||||
const CallHandler = require('../../../CallHandler');
|
||||
const RoomListSorter = require("../../../RoomListSorter");
|
||||
const Unread = require('../../../Unread');
|
||||
const dis = require("../../../dispatcher");
|
||||
const sdk = require('../../../index');
|
||||
const rate_limited_func = require('../../../ratelimitedfunc');
|
||||
const Rooms = require('../../../Rooms');
|
||||
import DMRoomMap from '../../../utils/DMRoomMap';
|
||||
var Receipt = require('../../../utils/Receipt');
|
||||
const Receipt = require('../../../utils/Receipt');
|
||||
|
||||
const HIDE_CONFERENCE_CHANS = true;
|
||||
|
||||
|
@ -55,7 +55,7 @@ function phraseForSection(section) {
|
|||
return _t('Drop here to tag %(section)s', {section: section});
|
||||
}
|
||||
return _t('Drop here %(toAction)s', {toAction: verb});
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = React.createClass({
|
||||
displayName: 'RoomList',
|
||||
|
@ -78,7 +78,7 @@ module.exports = React.createClass({
|
|||
componentWillMount: function() {
|
||||
this.mounted = false;
|
||||
|
||||
var cli = MatrixClientPeg.get();
|
||||
const cli = MatrixClientPeg.get();
|
||||
cli.on("Room", this.onRoom);
|
||||
cli.on("deleteRoom", this.onDeleteRoom);
|
||||
cli.on("Room.timeline", this.onRoomTimeline);
|
||||
|
@ -98,7 +98,7 @@ module.exports = React.createClass({
|
|||
|
||||
// loop count to stop a stack overflow if the user keeps waggling the
|
||||
// mouse for >30s in a row, or if running under mocha
|
||||
this._delayedRefreshRoomListLoopCount = 0
|
||||
this._delayedRefreshRoomListLoopCount = 0;
|
||||
},
|
||||
|
||||
componentDidMount: function() {
|
||||
|
@ -124,13 +124,12 @@ module.exports = React.createClass({
|
|||
var call = CallHandler.getCall(payload.room_id);
|
||||
if (call && call.call_state === 'ringing') {
|
||||
this.setState({
|
||||
incomingCall: call
|
||||
incomingCall: call,
|
||||
});
|
||||
this._repositionIncomingCallBox(undefined, true);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
this.setState({
|
||||
incomingCall: null
|
||||
incomingCall: null,
|
||||
});
|
||||
}
|
||||
break;
|
||||
|
@ -174,7 +173,7 @@ module.exports = React.createClass({
|
|||
|
||||
onArchivedHeaderClick: function(isHidden, scrollToPosition) {
|
||||
if (!isHidden) {
|
||||
var self = this;
|
||||
const self = this;
|
||||
this.setState({ isLoadingLeftRooms: true });
|
||||
|
||||
// Try scrolling to position
|
||||
|
@ -265,7 +264,7 @@ module.exports = React.createClass({
|
|||
},
|
||||
|
||||
getRoomLists: function() {
|
||||
var self = this;
|
||||
const self = this;
|
||||
const lists = {};
|
||||
|
||||
lists["im.vector.fake.invite"] = [];
|
||||
|
@ -288,35 +287,28 @@ module.exports = React.createClass({
|
|||
|
||||
if (me.membership == "invite") {
|
||||
lists["im.vector.fake.invite"].push(room);
|
||||
}
|
||||
else if (HIDE_CONFERENCE_CHANS && Rooms.isConfCallRoom(room, me, self.props.ConferenceHandler)) {
|
||||
} else if (HIDE_CONFERENCE_CHANS && Rooms.isConfCallRoom(room, me, self.props.ConferenceHandler)) {
|
||||
// skip past this room & don't put it in any lists
|
||||
}
|
||||
else if (me.membership == "join" || me.membership === "ban" ||
|
||||
(me.membership === "leave" && me.events.member.getSender() !== me.events.member.getStateKey()))
|
||||
{
|
||||
} else if (me.membership == "join" || me.membership === "ban" ||
|
||||
(me.membership === "leave" && me.events.member.getSender() !== me.events.member.getStateKey())) {
|
||||
// Used to split rooms via tags
|
||||
var tagNames = Object.keys(room.tags);
|
||||
const tagNames = Object.keys(room.tags);
|
||||
|
||||
if (tagNames.length) {
|
||||
for (var i = 0; i < tagNames.length; i++) {
|
||||
var tagName = tagNames[i];
|
||||
for (let i = 0; i < tagNames.length; i++) {
|
||||
const tagName = tagNames[i];
|
||||
lists[tagName] = lists[tagName] || [];
|
||||
lists[tagName].push(room);
|
||||
}
|
||||
}
|
||||
else if (dmRoomMap.getUserIdForRoomId(room.roomId)) {
|
||||
} else if (dmRoomMap.getUserIdForRoomId(room.roomId)) {
|
||||
// "Direct Message" rooms (that we're still in and that aren't otherwise tagged)
|
||||
lists["im.vector.fake.direct"].push(room);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
lists["im.vector.fake.recent"].push(room);
|
||||
}
|
||||
}
|
||||
else if (me.membership === "leave") {
|
||||
} else if (me.membership === "leave") {
|
||||
lists["im.vector.fake.archived"].push(room);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
console.error("unrecognised membership: " + me.membership + " - this should never happen");
|
||||
}
|
||||
});
|
||||
|
@ -343,7 +335,7 @@ module.exports = React.createClass({
|
|||
|
||||
_getScrollNode: function() {
|
||||
if (!this.mounted) return null;
|
||||
var panel = ReactDOM.findDOMNode(this);
|
||||
const panel = ReactDOM.findDOMNode(this);
|
||||
if (!panel) return null;
|
||||
|
||||
if (panel.classList.contains('gm-prevented')) {
|
||||
|
@ -367,22 +359,22 @@ module.exports = React.createClass({
|
|||
},
|
||||
|
||||
_repositionIncomingCallBox: function(e, firstTime) {
|
||||
var incomingCallBox = document.getElementById("incomingCallBox");
|
||||
const incomingCallBox = document.getElementById("incomingCallBox");
|
||||
if (incomingCallBox && incomingCallBox.parentElement) {
|
||||
var scrollArea = this._getScrollNode();
|
||||
const scrollArea = this._getScrollNode();
|
||||
if (!scrollArea) return;
|
||||
// Use the offset of the top of the scroll area from the window
|
||||
// as this is used to calculate the CSS fixed top position for the stickies
|
||||
var scrollAreaOffset = scrollArea.getBoundingClientRect().top + window.pageYOffset;
|
||||
const scrollAreaOffset = scrollArea.getBoundingClientRect().top + window.pageYOffset;
|
||||
// Use the offset of the top of the component from the window
|
||||
// as this is used to calculate the CSS fixed top position for the stickies
|
||||
var scrollAreaHeight = ReactDOM.findDOMNode(this).getBoundingClientRect().height;
|
||||
const scrollAreaHeight = ReactDOM.findDOMNode(this).getBoundingClientRect().height;
|
||||
|
||||
var top = (incomingCallBox.parentElement.getBoundingClientRect().top + window.pageYOffset);
|
||||
let 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
|
||||
var bottomMargin = scrollAreaOffset + (scrollAreaHeight - 45);
|
||||
const bottomMargin = scrollAreaOffset + (scrollAreaHeight - 45);
|
||||
top = (top > bottomMargin) ? bottomMargin : top;
|
||||
|
||||
incomingCallBox.style.top = top + "px";
|
||||
|
@ -393,14 +385,14 @@ module.exports = React.createClass({
|
|||
// Doing the sticky headers as raw DOM, for speed, as it gets very stuttery if done
|
||||
// properly through React
|
||||
_initAndPositionStickyHeaders: function(initialise, scrollToPosition) {
|
||||
var scrollArea = this._getScrollNode();
|
||||
const scrollArea = this._getScrollNode();
|
||||
if (!scrollArea) return;
|
||||
// Use the offset of the top of the scroll area from the window
|
||||
// as this is used to calculate the CSS fixed top position for the stickies
|
||||
var scrollAreaOffset = scrollArea.getBoundingClientRect().top + window.pageYOffset;
|
||||
const scrollAreaOffset = scrollArea.getBoundingClientRect().top + window.pageYOffset;
|
||||
// Use the offset of the top of the componet from the window
|
||||
// as this is used to calculate the CSS fixed top position for the stickies
|
||||
var scrollAreaHeight = ReactDOM.findDOMNode(this).getBoundingClientRect().height;
|
||||
const scrollAreaHeight = ReactDOM.findDOMNode(this).getBoundingClientRect().height;
|
||||
|
||||
if (initialise) {
|
||||
// Get a collection of sticky header containers references
|
||||
|
@ -420,7 +412,7 @@ module.exports = React.createClass({
|
|||
sticky.dataset.originalPosition = sticky.offsetTop - scrollArea.offsetTop;
|
||||
|
||||
// Save and set the sticky heights
|
||||
var originalHeight = sticky.getBoundingClientRect().height;
|
||||
const originalHeight = sticky.getBoundingClientRect().height;
|
||||
sticky.dataset.originalHeight = originalHeight;
|
||||
sticky.style.height = originalHeight;
|
||||
|
||||
|
@ -429,8 +421,8 @@ module.exports = React.createClass({
|
|||
}
|
||||
}
|
||||
|
||||
var self = this;
|
||||
var scrollStuckOffset = 0;
|
||||
const self = this;
|
||||
let scrollStuckOffset = 0;
|
||||
// Scroll to the passed in position, i.e. a header was clicked and in a scroll to state
|
||||
// rather than a collapsable one (see RoomSubList.isCollapsableOnClick method for details)
|
||||
if (scrollToPosition !== undefined) {
|
||||
|
@ -438,11 +430,11 @@ module.exports = React.createClass({
|
|||
}
|
||||
// Stick headers to top and bottom, or free them
|
||||
Array.prototype.forEach.call(this.stickies, function(sticky, i, stickyWrappers) {
|
||||
var stickyPosition = sticky.dataset.originalPosition;
|
||||
var stickyHeight = sticky.dataset.originalHeight;
|
||||
var stickyHeader = sticky.childNodes[0];
|
||||
var topStuckHeight = stickyHeight * i;
|
||||
var bottomStuckHeight = stickyHeight * (stickyWrappers.length - i);
|
||||
const stickyPosition = sticky.dataset.originalPosition;
|
||||
const stickyHeight = sticky.dataset.originalHeight;
|
||||
const stickyHeader = sticky.childNodes[0];
|
||||
const topStuckHeight = stickyHeight * i;
|
||||
const bottomStuckHeight = stickyHeight * (stickyWrappers.length - i);
|
||||
|
||||
if (self.scrollAreaSufficient && stickyPosition < (scrollArea.scrollTop + topStuckHeight)) {
|
||||
// Top stickies
|
||||
|
@ -472,7 +464,7 @@ module.exports = React.createClass({
|
|||
},
|
||||
|
||||
_updateStickyHeaders: function(initialise, scrollToPosition) {
|
||||
var self = this;
|
||||
const self = this;
|
||||
|
||||
if (initialise) {
|
||||
// Useing setTimeout to ensure that the code is run after the painting
|
||||
|
@ -507,25 +499,25 @@ module.exports = React.createClass({
|
|||
switch (section) {
|
||||
case 'im.vector.fake.direct':
|
||||
return <div className="mx_RoomList_emptySubListTip">
|
||||
{_tJsx(
|
||||
{ _tJsx(
|
||||
"Press <StartChatButton> to start a chat with someone",
|
||||
[/<StartChatButton>/],
|
||||
[
|
||||
(sub) => <StartChatButton size="16" callout={true}/>
|
||||
]
|
||||
)}
|
||||
(sub) => <StartChatButton size="16" callout={true} />,
|
||||
],
|
||||
) }
|
||||
</div>;
|
||||
case 'im.vector.fake.recent':
|
||||
return <div className="mx_RoomList_emptySubListTip">
|
||||
{_tJsx(
|
||||
{ _tJsx(
|
||||
"You're not in any rooms yet! Press <CreateRoomButton> to make a room or"+
|
||||
" <RoomDirectoryButton> to browse the directory",
|
||||
[/<CreateRoomButton>/, /<RoomDirectoryButton>/],
|
||||
[
|
||||
(sub) => <CreateRoomButton size="16" callout={true}/>,
|
||||
(sub) => <RoomDirectoryButton size="16" callout={true}/>
|
||||
]
|
||||
)}
|
||||
(sub) => <CreateRoomButton size="16" callout={true} />,
|
||||
(sub) => <RoomDirectoryButton size="16" callout={true} />,
|
||||
],
|
||||
) }
|
||||
</div>;
|
||||
}
|
||||
|
||||
|
@ -574,113 +566,112 @@ module.exports = React.createClass({
|
|||
|
||||
const inviteSectionExtraTiles = this._makeGroupInviteTiles();
|
||||
|
||||
var self = this;
|
||||
const self = this;
|
||||
return (
|
||||
<GeminiScrollbar className="mx_RoomList_scrollbar"
|
||||
autoshow={true} onScroll={ self._whenScrolling } ref="gemscroll">
|
||||
autoshow={true} onScroll={self._whenScrolling} ref="gemscroll">
|
||||
<div className="mx_RoomList">
|
||||
<RoomSubList list={ self.state.lists['im.vector.fake.invite'] }
|
||||
label={ _t('Invites') }
|
||||
editable={ false }
|
||||
<RoomSubList list={self.state.lists['im.vector.fake.invite']}
|
||||
label={_t('Invites')}
|
||||
editable={false}
|
||||
order="recent"
|
||||
isInvite={true}
|
||||
selectedRoom={ self.props.selectedRoom }
|
||||
incomingCall={ self.state.incomingCall }
|
||||
collapsed={ self.props.collapsed }
|
||||
searchFilter={ self.props.searchFilter }
|
||||
onHeaderClick={ self.onSubListHeaderClick }
|
||||
onShowMoreRooms={ self.onShowMoreRooms }
|
||||
extraTiles={ inviteSectionExtraTiles }
|
||||
selectedRoom={self.props.selectedRoom}
|
||||
incomingCall={self.state.incomingCall}
|
||||
collapsed={self.props.collapsed}
|
||||
searchFilter={self.props.searchFilter}
|
||||
onHeaderClick={self.onSubListHeaderClick}
|
||||
onShowMoreRooms={self.onShowMoreRooms}
|
||||
extraTiles={inviteSectionExtraTiles}
|
||||
/>
|
||||
|
||||
<RoomSubList list={ self.state.lists['m.favourite'] }
|
||||
label={ _t('Favourites') }
|
||||
<RoomSubList list={self.state.lists['m.favourite']}
|
||||
label={_t('Favourites')}
|
||||
tagName="m.favourite"
|
||||
emptyContent={this._getEmptyContent('m.favourite')}
|
||||
editable={ true }
|
||||
editable={true}
|
||||
order="manual"
|
||||
selectedRoom={ self.props.selectedRoom }
|
||||
incomingCall={ self.state.incomingCall }
|
||||
collapsed={ self.props.collapsed }
|
||||
searchFilter={ self.props.searchFilter }
|
||||
onHeaderClick={ self.onSubListHeaderClick }
|
||||
onShowMoreRooms={ self.onShowMoreRooms } />
|
||||
selectedRoom={self.props.selectedRoom}
|
||||
incomingCall={self.state.incomingCall}
|
||||
collapsed={self.props.collapsed}
|
||||
searchFilter={self.props.searchFilter}
|
||||
onHeaderClick={self.onSubListHeaderClick}
|
||||
onShowMoreRooms={self.onShowMoreRooms} />
|
||||
|
||||
<RoomSubList list={ self.state.lists['im.vector.fake.direct'] }
|
||||
label={ _t('People') }
|
||||
<RoomSubList list={self.state.lists['im.vector.fake.direct']}
|
||||
label={_t('People')}
|
||||
tagName="im.vector.fake.direct"
|
||||
emptyContent={this._getEmptyContent('im.vector.fake.direct')}
|
||||
headerItems={this._getHeaderItems('im.vector.fake.direct')}
|
||||
editable={ true }
|
||||
editable={true}
|
||||
order="recent"
|
||||
selectedRoom={ self.props.selectedRoom }
|
||||
incomingCall={ self.state.incomingCall }
|
||||
collapsed={ self.props.collapsed }
|
||||
alwaysShowHeader={ true }
|
||||
searchFilter={ self.props.searchFilter }
|
||||
onHeaderClick={ self.onSubListHeaderClick }
|
||||
onShowMoreRooms={ self.onShowMoreRooms } />
|
||||
selectedRoom={self.props.selectedRoom}
|
||||
incomingCall={self.state.incomingCall}
|
||||
collapsed={self.props.collapsed}
|
||||
alwaysShowHeader={true}
|
||||
searchFilter={self.props.searchFilter}
|
||||
onHeaderClick={self.onSubListHeaderClick}
|
||||
onShowMoreRooms={self.onShowMoreRooms} />
|
||||
|
||||
<RoomSubList list={ self.state.lists['im.vector.fake.recent'] }
|
||||
label={ _t('Rooms') }
|
||||
editable={ true }
|
||||
<RoomSubList list={self.state.lists['im.vector.fake.recent']}
|
||||
label={_t('Rooms')}
|
||||
editable={true}
|
||||
emptyContent={this._getEmptyContent('im.vector.fake.recent')}
|
||||
headerItems={this._getHeaderItems('im.vector.fake.recent')}
|
||||
order="recent"
|
||||
selectedRoom={ self.props.selectedRoom }
|
||||
incomingCall={ self.state.incomingCall }
|
||||
collapsed={ self.props.collapsed }
|
||||
searchFilter={ self.props.searchFilter }
|
||||
onHeaderClick={ self.onSubListHeaderClick }
|
||||
onShowMoreRooms={ self.onShowMoreRooms } />
|
||||
selectedRoom={self.props.selectedRoom}
|
||||
incomingCall={self.state.incomingCall}
|
||||
collapsed={self.props.collapsed}
|
||||
searchFilter={self.props.searchFilter}
|
||||
onHeaderClick={self.onSubListHeaderClick}
|
||||
onShowMoreRooms={self.onShowMoreRooms} />
|
||||
|
||||
{ Object.keys(self.state.lists).map((tagName) => {
|
||||
if (!tagName.match(/^(m\.(favourite|lowpriority)|im\.vector\.fake\.(invite|recent|direct|archived))$/)) {
|
||||
return <RoomSubList list={ self.state.lists[tagName] }
|
||||
key={ tagName }
|
||||
label={ tagName }
|
||||
tagName={ tagName }
|
||||
return <RoomSubList list={self.state.lists[tagName]}
|
||||
key={tagName}
|
||||
label={tagName}
|
||||
tagName={tagName}
|
||||
emptyContent={this._getEmptyContent(tagName)}
|
||||
editable={ true }
|
||||
editable={true}
|
||||
order="manual"
|
||||
selectedRoom={ self.props.selectedRoom }
|
||||
incomingCall={ self.state.incomingCall }
|
||||
collapsed={ self.props.collapsed }
|
||||
searchFilter={ self.props.searchFilter }
|
||||
onHeaderClick={ self.onSubListHeaderClick }
|
||||
onShowMoreRooms={ self.onShowMoreRooms } />;
|
||||
|
||||
selectedRoom={self.props.selectedRoom}
|
||||
incomingCall={self.state.incomingCall}
|
||||
collapsed={self.props.collapsed}
|
||||
searchFilter={self.props.searchFilter}
|
||||
onHeaderClick={self.onSubListHeaderClick}
|
||||
onShowMoreRooms={self.onShowMoreRooms} />;
|
||||
}
|
||||
}) }
|
||||
|
||||
<RoomSubList list={ self.state.lists['m.lowpriority'] }
|
||||
label={ _t('Low priority') }
|
||||
<RoomSubList list={self.state.lists['m.lowpriority']}
|
||||
label={_t('Low priority')}
|
||||
tagName="m.lowpriority"
|
||||
emptyContent={this._getEmptyContent('m.lowpriority')}
|
||||
editable={ true }
|
||||
editable={true}
|
||||
order="recent"
|
||||
selectedRoom={ self.props.selectedRoom }
|
||||
incomingCall={ self.state.incomingCall }
|
||||
collapsed={ self.props.collapsed }
|
||||
searchFilter={ self.props.searchFilter }
|
||||
onHeaderClick={ self.onSubListHeaderClick }
|
||||
onShowMoreRooms={ self.onShowMoreRooms } />
|
||||
selectedRoom={self.props.selectedRoom}
|
||||
incomingCall={self.state.incomingCall}
|
||||
collapsed={self.props.collapsed}
|
||||
searchFilter={self.props.searchFilter}
|
||||
onHeaderClick={self.onSubListHeaderClick}
|
||||
onShowMoreRooms={self.onShowMoreRooms} />
|
||||
|
||||
<RoomSubList list={ self.state.lists['im.vector.fake.archived'] }
|
||||
label={ _t('Historical') }
|
||||
editable={ false }
|
||||
<RoomSubList list={self.state.lists['im.vector.fake.archived']}
|
||||
label={_t('Historical')}
|
||||
editable={false}
|
||||
order="recent"
|
||||
selectedRoom={ self.props.selectedRoom }
|
||||
collapsed={ self.props.collapsed }
|
||||
alwaysShowHeader={ true }
|
||||
startAsHidden={ true }
|
||||
showSpinner={ self.state.isLoadingLeftRooms }
|
||||
onHeaderClick= { self.onArchivedHeaderClick }
|
||||
incomingCall={ self.state.incomingCall }
|
||||
searchFilter={ self.props.searchFilter }
|
||||
onShowMoreRooms={ self.onShowMoreRooms } />
|
||||
selectedRoom={self.props.selectedRoom}
|
||||
collapsed={self.props.collapsed}
|
||||
alwaysShowHeader={true}
|
||||
startAsHidden={true}
|
||||
showSpinner={self.state.isLoadingLeftRooms}
|
||||
onHeaderClick= {self.onArchivedHeaderClick}
|
||||
incomingCall={self.state.incomingCall}
|
||||
searchFilter={self.props.searchFilter}
|
||||
onShowMoreRooms={self.onShowMoreRooms} />
|
||||
</div>
|
||||
</GeminiScrollbar>
|
||||
);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
|
|
@ -16,9 +16,9 @@ limitations under the License.
|
|||
|
||||
'use strict';
|
||||
|
||||
var React = require('react');
|
||||
var sdk = require('../../../index');
|
||||
var MatrixClientPeg = require('../../../MatrixClientPeg');
|
||||
const React = require('react');
|
||||
const sdk = require('../../../index');
|
||||
const MatrixClientPeg = require('../../../MatrixClientPeg');
|
||||
import { _t } from '../../../languageHandler';
|
||||
|
||||
module.exports = React.createClass({
|
||||
|
@ -29,10 +29,10 @@ module.exports = React.createClass({
|
|||
},
|
||||
|
||||
componentWillMount: function() {
|
||||
var room = this.props.room;
|
||||
var name = room.currentState.getStateEvents('m.room.name', '');
|
||||
var myId = MatrixClientPeg.get().credentials.userId;
|
||||
var defaultName = room.getDefaultRoomName(myId);
|
||||
const room = this.props.room;
|
||||
const name = room.currentState.getStateEvents('m.room.name', '');
|
||||
const myId = MatrixClientPeg.get().credentials.userId;
|
||||
const defaultName = room.getDefaultRoomName(myId);
|
||||
|
||||
this._initialName = name ? name.getContent().name : '';
|
||||
|
||||
|
@ -47,16 +47,16 @@ module.exports = React.createClass({
|
|||
},
|
||||
|
||||
render: function() {
|
||||
var EditableText = sdk.getComponent("elements.EditableText");
|
||||
const EditableText = sdk.getComponent("elements.EditableText");
|
||||
|
||||
return (
|
||||
<div className="mx_RoomHeader_name">
|
||||
<EditableText ref="editor"
|
||||
className="mx_RoomHeader_nametext mx_RoomHeader_editable"
|
||||
placeholderClassName="mx_RoomHeader_placeholder"
|
||||
placeholder={ this._placeholderName }
|
||||
blurToCancel={ false }
|
||||
initialValue={ this._initialName }
|
||||
placeholder={this._placeholderName}
|
||||
blurToCancel={false}
|
||||
initialValue={this._initialName}
|
||||
dir="auto" />
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -17,9 +17,9 @@ limitations under the License.
|
|||
|
||||
'use strict';
|
||||
|
||||
var React = require('react');
|
||||
var sdk = require('../../../index');
|
||||
var MatrixClientPeg = require('../../../MatrixClientPeg');
|
||||
const React = require('react');
|
||||
const sdk = require('../../../index');
|
||||
const MatrixClientPeg = require('../../../MatrixClientPeg');
|
||||
|
||||
import { _t, _tJsx } from '../../../languageHandler';
|
||||
|
||||
|
@ -61,7 +61,7 @@ module.exports = React.createClass({
|
|||
|
||||
getInitialState: function() {
|
||||
return {
|
||||
busy: false
|
||||
busy: false,
|
||||
};
|
||||
},
|
||||
|
||||
|
@ -72,7 +72,7 @@ module.exports = React.createClass({
|
|||
if (this.props.inviterName && this.props.invitedEmail) {
|
||||
this.setState({busy: true});
|
||||
MatrixClientPeg.get().lookupThreePid(
|
||||
'email', this.props.invitedEmail
|
||||
'email', this.props.invitedEmail,
|
||||
).finally(() => {
|
||||
this.setState({busy: false});
|
||||
}).done((result) => {
|
||||
|
@ -90,10 +90,10 @@ module.exports = React.createClass({
|
|||
},
|
||||
|
||||
render: function() {
|
||||
var joinBlock, previewBlock;
|
||||
let joinBlock, previewBlock;
|
||||
|
||||
if (this.props.spinner || this.state.busy) {
|
||||
var Spinner = sdk.getComponent("elements.Spinner");
|
||||
const Spinner = sdk.getComponent("elements.Spinner");
|
||||
return (<div className="mx_RoomPreviewBar">
|
||||
<Spinner />
|
||||
</div>);
|
||||
|
@ -110,11 +110,11 @@ module.exports = React.createClass({
|
|||
const banned = myMember && myMember.membership == 'ban';
|
||||
|
||||
if (this.props.inviterName) {
|
||||
var emailMatchBlock;
|
||||
let emailMatchBlock;
|
||||
if (this.props.invitedEmail) {
|
||||
if (this.state.threePidFetchError) {
|
||||
emailMatchBlock = <div className="error">
|
||||
{_t("Unable to ascertain that the address this invite was sent to matches one associated with your account.")}
|
||||
{ _t("Unable to ascertain that the address this invite was sent to matches one associated with your account.") }
|
||||
</div>;
|
||||
} else if (this.state.invitedEmailMxid != MatrixClientPeg.get().credentials.userId) {
|
||||
emailMatchBlock =
|
||||
|
@ -123,10 +123,10 @@ module.exports = React.createClass({
|
|||
<img src="img/warning.svg" width="24" height="23" title= "/!\\" alt="/!\\" />
|
||||
</div>
|
||||
<div className="mx_RoomPreviewBar_warningText">
|
||||
{_t("This invitation was sent to an email address which is not associated with this account:")}
|
||||
<b><span className="email">{this.props.invitedEmail}</span></b>
|
||||
<br/>
|
||||
{_t("You may wish to login with a different account, or add this email to this account.")}
|
||||
{ _t("This invitation was sent to an email address which is not associated with this account:") }
|
||||
<b><span className="email">{ this.props.invitedEmail }</span></b>
|
||||
<br />
|
||||
{ _t("You may wish to login with a different account, or add this email to this account.") }
|
||||
</div>
|
||||
</div>;
|
||||
}
|
||||
|
@ -141,53 +141,51 @@ module.exports = React.createClass({
|
|||
'Would you like to <acceptText>accept</acceptText> or <declineText>decline</declineText> this invitation?',
|
||||
[/<acceptText>(.*?)<\/acceptText>/, /<declineText>(.*?)<\/declineText>/],
|
||||
[
|
||||
(sub) => <a onClick={ this.props.onJoinClick }>{sub}</a>,
|
||||
(sub) => <a onClick={ this.props.onRejectClick }>{sub}</a>
|
||||
]
|
||||
)}
|
||||
(sub) => <a onClick={this.props.onJoinClick}>{ sub }</a>,
|
||||
(sub) => <a onClick={this.props.onRejectClick}>{ sub }</a>,
|
||||
],
|
||||
) }
|
||||
</div>
|
||||
{emailMatchBlock}
|
||||
{ emailMatchBlock }
|
||||
</div>
|
||||
);
|
||||
|
||||
} else if (kicked || banned) {
|
||||
const roomName = this._roomNameElement(_t('This room'));
|
||||
const kickerMember = this.props.room.currentState.getMember(
|
||||
myMember.events.member.getSender()
|
||||
myMember.events.member.getSender(),
|
||||
);
|
||||
const kickerName = kickerMember ?
|
||||
kickerMember.name : myMember.events.member.getSender();
|
||||
let reason;
|
||||
if (myMember.events.member.getContent().reason) {
|
||||
reason = <div>{_t("Reason: %(reasonText)s", {reasonText: myMember.events.member.getContent().reason})}</div>
|
||||
reason = <div>{ _t("Reason: %(reasonText)s", {reasonText: myMember.events.member.getContent().reason}) }</div>;
|
||||
}
|
||||
let rejoinBlock;
|
||||
if (!banned) {
|
||||
rejoinBlock = <div><a onClick={ this.props.onJoinClick }><b>{_t("Rejoin")}</b></a></div>;
|
||||
rejoinBlock = <div><a onClick={this.props.onJoinClick}><b>{ _t("Rejoin") }</b></a></div>;
|
||||
}
|
||||
|
||||
let actionText;
|
||||
if (kicked) {
|
||||
actionText = _t("You have been kicked from %(roomName)s by %(userName)s.", {roomName: roomName, userName: kickerName});
|
||||
}
|
||||
else if (banned) {
|
||||
} else if (banned) {
|
||||
actionText = _t("You have been banned from %(roomName)s by %(userName)s.", {roomName: roomName, userName: kickerName});
|
||||
} // no other options possible due to the kicked || banned check above.
|
||||
|
||||
joinBlock = (
|
||||
<div>
|
||||
<div className="mx_RoomPreviewBar_join_text">
|
||||
{actionText}
|
||||
{ actionText }
|
||||
<br />
|
||||
{reason}
|
||||
{rejoinBlock}
|
||||
<a onClick={ this.props.onForgetClick }><b>{_t("Forget room")}</b></a>
|
||||
{ reason }
|
||||
{ rejoinBlock }
|
||||
<a onClick={this.props.onForgetClick}><b>{ _t("Forget room") }</b></a>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
} else if (this.props.error) {
|
||||
var name = this.props.roomAlias || _t("This room");
|
||||
var error;
|
||||
const name = this.props.roomAlias || _t("This room");
|
||||
let error;
|
||||
if (this.props.error.errcode == 'M_NOT_FOUND') {
|
||||
error = _t("%(roomName)s does not exist.", {roomName: name});
|
||||
} else {
|
||||
|
@ -206,11 +204,11 @@ module.exports = React.createClass({
|
|||
<div>
|
||||
<div className="mx_RoomPreviewBar_join_text">
|
||||
{ _t('You are trying to access %(roomName)s.', {roomName: name}) }
|
||||
<br/>
|
||||
<br />
|
||||
{ _tJsx("<a>Click here</a> to join the discussion!",
|
||||
/<a>(.*?)<\/a>/,
|
||||
(sub) => <a onClick={ this.props.onJoinClick }><b>{sub}</b></a>
|
||||
)}
|
||||
(sub) => <a onClick={this.props.onJoinClick}><b>{ sub }</b></a>,
|
||||
) }
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
@ -232,5 +230,5 @@ module.exports = React.createClass({
|
|||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
|
|
@ -17,7 +17,7 @@ limitations under the License.
|
|||
|
||||
import Promise from 'bluebird';
|
||||
import React from 'react';
|
||||
import { _t, _tJsx } from '../../../languageHandler';
|
||||
import { _t, _tJsx, _td } from '../../../languageHandler';
|
||||
import MatrixClientPeg from '../../../MatrixClientPeg';
|
||||
import SdkConfig from '../../../SdkConfig';
|
||||
import sdk from '../../../index';
|
||||
|
@ -31,14 +31,39 @@ import AccessibleButton from '../elements/AccessibleButton';
|
|||
// parse a string as an integer; if the input is undefined, or cannot be parsed
|
||||
// as an integer, return a default.
|
||||
function parseIntWithDefault(val, def) {
|
||||
var res = parseInt(val);
|
||||
const res = parseInt(val);
|
||||
return isNaN(res) ? def : res;
|
||||
}
|
||||
|
||||
const plEventsToLabels = {
|
||||
// These will be translated for us later.
|
||||
"m.room.avatar": _td("To change the room's avatar, you must be a"),
|
||||
"m.room.name": _td("To change the room's name, you must be a"),
|
||||
"m.room.canonical_alias": _td("To change the room's main address, you must be a"),
|
||||
"m.room.history_visibility": _td("To change the room's history visibility, you must be a"),
|
||||
"m.room.power_levels": _td("To change the permissions in the room, you must be a"),
|
||||
"m.room.topic": _td("To change the topic, you must be a"),
|
||||
|
||||
"im.vector.modular.widgets": _td("To modify widgets in the room, you must be a"),
|
||||
};
|
||||
|
||||
const plEventsToShow = {
|
||||
// If an event is listed here, it will be shown in the PL settings. Defaults will be calculated.
|
||||
"m.room.avatar": {isState: true},
|
||||
"m.room.name": {isState: true},
|
||||
"m.room.canonical_alias": {isState: true},
|
||||
"m.room.history_visibility": {isState: true},
|
||||
"m.room.power_levels": {isState: true},
|
||||
"m.room.topic": {isState: true},
|
||||
|
||||
"im.vector.modular.widgets": {isState: true},
|
||||
};
|
||||
|
||||
const BannedUser = React.createClass({
|
||||
propTypes: {
|
||||
canUnban: React.PropTypes.bool,
|
||||
member: React.PropTypes.object.isRequired, // js-sdk RoomMember
|
||||
by: React.PropTypes.string.isRequired,
|
||||
reason: React.PropTypes.string,
|
||||
},
|
||||
|
||||
|
@ -77,8 +102,10 @@ const BannedUser = React.createClass({
|
|||
return (
|
||||
<li>
|
||||
{ unbanButton }
|
||||
<strong>{this.props.member.name}</strong> {this.props.member.userId}
|
||||
{this.props.reason ? " " +_t('Reason') + ": " + this.props.reason : ""}
|
||||
<span title={_t("Banned by %(displayName)s", {displayName: this.props.by})}>
|
||||
<strong>{ this.props.member.name }</strong> { this.props.member.userId }
|
||||
{ this.props.reason ? " " +_t('Reason') + ": " + this.props.reason : "" }
|
||||
</span>
|
||||
</li>
|
||||
);
|
||||
},
|
||||
|
@ -93,7 +120,7 @@ module.exports = React.createClass({
|
|||
},
|
||||
|
||||
getInitialState: function() {
|
||||
var tags = {};
|
||||
const tags = {};
|
||||
Object.keys(this.props.room.tags).forEach(function(tagName) {
|
||||
tags[tagName] = ['yep'];
|
||||
});
|
||||
|
@ -122,7 +149,7 @@ module.exports = React.createClass({
|
|||
MatrixClientPeg.get().on("RoomMember.membership", this._onRoomMemberMembership);
|
||||
|
||||
MatrixClientPeg.get().getRoomDirectoryVisibility(
|
||||
this.props.room.roomId
|
||||
this.props.room.roomId,
|
||||
).done((result) => {
|
||||
this.setState({ isRoomPublished: result.visibility === "public" });
|
||||
this._originalIsRoomPublished = result.visibility === "public";
|
||||
|
@ -152,13 +179,13 @@ module.exports = React.createClass({
|
|||
|
||||
setName: function(name) {
|
||||
this.setState({
|
||||
name: name
|
||||
name: name,
|
||||
});
|
||||
},
|
||||
|
||||
setTopic: function(topic) {
|
||||
this.setState({
|
||||
topic: topic
|
||||
topic: topic,
|
||||
});
|
||||
},
|
||||
|
||||
|
@ -169,7 +196,7 @@ module.exports = React.createClass({
|
|||
* `{ state: "fulfilled", value: v }` or `{ state: "rejected", reason: r }`.
|
||||
*/
|
||||
save: function() {
|
||||
var stateWasSetDefer = Promise.defer();
|
||||
const stateWasSetDefer = Promise.defer();
|
||||
// the caller may have JUST called setState on stuff, so we need to re-render before saving
|
||||
// else we won't use the latest values of things.
|
||||
// We can be a bit cheeky here and set a loading flag, and listen for the callback on that
|
||||
|
@ -196,8 +223,8 @@ module.exports = React.createClass({
|
|||
|
||||
_calcSavePromises: function() {
|
||||
const roomId = this.props.room.roomId;
|
||||
var promises = this.saveAliases(); // returns Promise[]
|
||||
var originalState = this.getInitialState();
|
||||
const promises = this.saveAliases(); // returns Promise[]
|
||||
const originalState = this.getInitialState();
|
||||
|
||||
// diff between original state and this.state to work out what has been changed
|
||||
console.log("Original: %s", JSON.stringify(originalState));
|
||||
|
@ -215,14 +242,14 @@ module.exports = React.createClass({
|
|||
promises.push(MatrixClientPeg.get().sendStateEvent(
|
||||
roomId, "m.room.history_visibility",
|
||||
{ history_visibility: this.state.history_visibility },
|
||||
""
|
||||
"",
|
||||
));
|
||||
}
|
||||
|
||||
if (this.state.isRoomPublished !== originalState.isRoomPublished) {
|
||||
promises.push(MatrixClientPeg.get().setRoomDirectoryVisibility(
|
||||
roomId,
|
||||
this.state.isRoomPublished ? "public" : "private"
|
||||
this.state.isRoomPublished ? "public" : "private",
|
||||
));
|
||||
}
|
||||
|
||||
|
@ -230,7 +257,7 @@ module.exports = React.createClass({
|
|||
promises.push(MatrixClientPeg.get().sendStateEvent(
|
||||
roomId, "m.room.join_rules",
|
||||
{ join_rule: this.state.join_rule },
|
||||
""
|
||||
"",
|
||||
));
|
||||
}
|
||||
|
||||
|
@ -238,33 +265,33 @@ module.exports = React.createClass({
|
|||
promises.push(MatrixClientPeg.get().sendStateEvent(
|
||||
roomId, "m.room.guest_access",
|
||||
{ guest_access: this.state.guest_access },
|
||||
""
|
||||
"",
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
// power levels
|
||||
var powerLevels = this._getPowerLevels();
|
||||
const powerLevels = this._getPowerLevels();
|
||||
if (powerLevels) {
|
||||
promises.push(MatrixClientPeg.get().sendStateEvent(
|
||||
roomId, "m.room.power_levels", powerLevels, ""
|
||||
roomId, "m.room.power_levels", powerLevels, "",
|
||||
));
|
||||
}
|
||||
|
||||
// tags
|
||||
if (this.state.tags_changed) {
|
||||
var tagDiffs = ObjectUtils.getKeyValueArrayDiffs(originalState.tags, this.state.tags);
|
||||
const tagDiffs = ObjectUtils.getKeyValueArrayDiffs(originalState.tags, this.state.tags);
|
||||
// [ {place: add, key: "m.favourite", val: ["yep"]} ]
|
||||
tagDiffs.forEach(function(diff) {
|
||||
switch (diff.place) {
|
||||
case "add":
|
||||
promises.push(
|
||||
MatrixClientPeg.get().setRoomTag(roomId, diff.key, {})
|
||||
MatrixClientPeg.get().setRoomTag(roomId, diff.key, {}),
|
||||
);
|
||||
break;
|
||||
case "del":
|
||||
promises.push(
|
||||
MatrixClientPeg.get().deleteRoomTag(roomId, diff.key)
|
||||
MatrixClientPeg.get().deleteRoomTag(roomId, diff.key),
|
||||
);
|
||||
break;
|
||||
default:
|
||||
|
@ -275,14 +302,14 @@ module.exports = React.createClass({
|
|||
}
|
||||
|
||||
// color scheme
|
||||
var p;
|
||||
let p;
|
||||
p = this.saveColor();
|
||||
if (!p.isFulfilled()) {
|
||||
promises.push(p);
|
||||
}
|
||||
|
||||
// url preview settings
|
||||
var ps = this.saveUrlPreviewSettings();
|
||||
const ps = this.saveUrlPreviewSettings();
|
||||
if (ps.length > 0) {
|
||||
promises.push(ps);
|
||||
}
|
||||
|
@ -325,13 +352,13 @@ module.exports = React.createClass({
|
|||
saveEnableEncryption: function() {
|
||||
if (!this.refs.encrypt) { return Promise.resolve(); }
|
||||
|
||||
var encrypt = this.refs.encrypt.checked;
|
||||
const encrypt = this.refs.encrypt.checked;
|
||||
if (!encrypt) { return Promise.resolve(); }
|
||||
|
||||
var roomId = this.props.room.roomId;
|
||||
const roomId = this.props.room.roomId;
|
||||
return MatrixClientPeg.get().sendStateEvent(
|
||||
roomId, "m.room.encryption",
|
||||
{ algorithm: "m.megolm.v1.aes-sha2" }
|
||||
{ algorithm: "m.megolm.v1.aes-sha2" },
|
||||
);
|
||||
},
|
||||
|
||||
|
@ -343,7 +370,7 @@ module.exports = React.createClass({
|
|||
},
|
||||
|
||||
_isRoomBlacklistUnverified: function() {
|
||||
var blacklistUnverifiedDevicesPerRoom = UserSettingsStore.getLocalSettings().blacklistUnverifiedDevicesPerRoom;
|
||||
const blacklistUnverifiedDevicesPerRoom = UserSettingsStore.getLocalSettings().blacklistUnverifiedDevicesPerRoom;
|
||||
if (blacklistUnverifiedDevicesPerRoom) {
|
||||
return blacklistUnverifiedDevicesPerRoom[this.props.room.roomId];
|
||||
}
|
||||
|
@ -351,7 +378,7 @@ module.exports = React.createClass({
|
|||
},
|
||||
|
||||
_setRoomBlacklistUnverified: function(value) {
|
||||
var blacklistUnverifiedDevicesPerRoom = UserSettingsStore.getLocalSettings().blacklistUnverifiedDevicesPerRoom || {};
|
||||
const blacklistUnverifiedDevicesPerRoom = UserSettingsStore.getLocalSettings().blacklistUnverifiedDevicesPerRoom || {};
|
||||
blacklistUnverifiedDevicesPerRoom[this.props.room.roomId] = value;
|
||||
UserSettingsStore.setLocalSetting('blacklistUnverifiedDevicesPerRoom', blacklistUnverifiedDevicesPerRoom);
|
||||
|
||||
|
@ -369,10 +396,15 @@ module.exports = React.createClass({
|
|||
_getPowerLevels: function() {
|
||||
if (!this.state.power_levels_changed) return undefined;
|
||||
|
||||
var powerLevels = this.props.room.currentState.getStateEvents('m.room.power_levels', '');
|
||||
let powerLevels = this.props.room.currentState.getStateEvents('m.room.power_levels', '');
|
||||
powerLevels = powerLevels ? powerLevels.getContent() : {};
|
||||
|
||||
var newPowerLevels = {
|
||||
for (const key of Object.keys(this.refs).filter((k) => k.startsWith("event_levels_"))) {
|
||||
const eventType = key.substring("event_levels_".length);
|
||||
powerLevels.events[eventType] = parseInt(this.refs[key].getValue());
|
||||
}
|
||||
|
||||
const newPowerLevels = {
|
||||
ban: parseInt(this.refs.ban.getValue()),
|
||||
kick: parseInt(this.refs.kick.getValue()),
|
||||
redact: parseInt(this.refs.redact.getValue()),
|
||||
|
@ -389,39 +421,40 @@ module.exports = React.createClass({
|
|||
|
||||
onPowerLevelsChanged: function() {
|
||||
this.setState({
|
||||
power_levels_changed: true
|
||||
power_levels_changed: true,
|
||||
});
|
||||
},
|
||||
|
||||
_yankValueFromEvent: function(stateEventType, keyName, defaultValue) {
|
||||
// E.g.("m.room.name","name") would yank the "name" content key from "m.room.name"
|
||||
var event = this.props.room.currentState.getStateEvents(stateEventType, '');
|
||||
const event = this.props.room.currentState.getStateEvents(stateEventType, '');
|
||||
if (!event) {
|
||||
return defaultValue;
|
||||
}
|
||||
return event.getContent()[keyName] || defaultValue;
|
||||
const content = event.getContent();
|
||||
return keyName in content ? content[keyName] : defaultValue;
|
||||
},
|
||||
|
||||
_onHistoryRadioToggle: function(ev) {
|
||||
var self = this;
|
||||
var QuestionDialog = sdk.getComponent("dialogs.QuestionDialog");
|
||||
const self = this;
|
||||
const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog");
|
||||
|
||||
// cancel the click unless the user confirms it
|
||||
ev.preventDefault();
|
||||
var value = ev.target.value;
|
||||
const value = ev.target.value;
|
||||
|
||||
Modal.createTrackedDialog('Privacy warning', '', QuestionDialog, {
|
||||
title: _t('Privacy warning'),
|
||||
description:
|
||||
<div>
|
||||
{ _t('Changes to who can read history will only apply to future messages in this room') }.<br/>
|
||||
{ _t('Changes to who can read history will only apply to future messages in this room') }.<br />
|
||||
{ _t('The visibility of existing history will be unchanged') }.
|
||||
</div>,
|
||||
button: _t('Continue'),
|
||||
onFinished: function(confirmed) {
|
||||
if (confirmed) {
|
||||
self.setState({
|
||||
history_visibility: value
|
||||
history_visibility: value,
|
||||
});
|
||||
}
|
||||
},
|
||||
|
@ -429,7 +462,6 @@ module.exports = React.createClass({
|
|||
},
|
||||
|
||||
_onRoomAccessRadioToggle: function(ev) {
|
||||
|
||||
// join_rule
|
||||
// INVITE | PUBLIC
|
||||
// ----------------------+----------------
|
||||
|
@ -467,7 +499,7 @@ module.exports = React.createClass({
|
|||
|
||||
_onToggle: function(keyName, checkedValue, uncheckedValue, ev) {
|
||||
console.log("Checkbox toggle: %s %s", keyName, ev.target.checked);
|
||||
var state = {};
|
||||
const state = {};
|
||||
state[keyName] = ev.target.checked ? checkedValue : uncheckedValue;
|
||||
this.setState(state);
|
||||
},
|
||||
|
@ -476,26 +508,24 @@ module.exports = React.createClass({
|
|||
if (event.target.checked) {
|
||||
if (tagName === 'm.favourite') {
|
||||
delete this.state.tags['m.lowpriority'];
|
||||
}
|
||||
else if (tagName === 'm.lowpriority') {
|
||||
} else if (tagName === 'm.lowpriority') {
|
||||
delete this.state.tags['m.favourite'];
|
||||
}
|
||||
|
||||
this.state.tags[tagName] = this.state.tags[tagName] || ["yep"];
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
delete this.state.tags[tagName];
|
||||
}
|
||||
|
||||
this.setState({
|
||||
tags: this.state.tags,
|
||||
tags_changed: true
|
||||
tags_changed: true,
|
||||
});
|
||||
},
|
||||
|
||||
mayChangeRoomAccess: function() {
|
||||
var cli = MatrixClientPeg.get();
|
||||
var roomState = this.props.room.currentState;
|
||||
const cli = MatrixClientPeg.get();
|
||||
const roomState = this.props.room.currentState;
|
||||
return (roomState.mayClientSendStateEvent("m.room.join_rules", cli) &&
|
||||
roomState.mayClientSendStateEvent("m.room.guest_access", cli));
|
||||
},
|
||||
|
@ -512,8 +542,8 @@ module.exports = React.createClass({
|
|||
MatrixClientPeg.get().forget(this.props.room.roomId).done(function() {
|
||||
dis.dispatch({ action: 'view_next_room' });
|
||||
}, function(err) {
|
||||
var errCode = err.errcode || _t('unknown error code');
|
||||
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||
const errCode = err.errcode || _t('unknown error code');
|
||||
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||
Modal.createTrackedDialog('Failed to forget room', '', ErrorDialog, {
|
||||
title: _t('Error'),
|
||||
description: _t("Failed to forget room %(errCode)s", { errCode: errCode }),
|
||||
|
@ -524,7 +554,7 @@ module.exports = React.createClass({
|
|||
onEnableEncryptionClick() {
|
||||
if (!this.refs.encrypt.checked) return;
|
||||
|
||||
var QuestionDialog = sdk.getComponent("dialogs.QuestionDialog");
|
||||
const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog");
|
||||
Modal.createTrackedDialog('E2E Enable Warning', '', QuestionDialog, {
|
||||
title: _t('Warning!'),
|
||||
description: (
|
||||
|
@ -536,7 +566,7 @@ module.exports = React.createClass({
|
|||
<p>{ _t('Encrypted messages will not be visible on clients that do not yet implement encryption') }.</p>
|
||||
</div>
|
||||
),
|
||||
onFinished: confirm=>{
|
||||
onFinished: (confirm)=>{
|
||||
if (!confirm) {
|
||||
this.refs.encrypt.checked = false;
|
||||
}
|
||||
|
@ -549,18 +579,26 @@ module.exports = React.createClass({
|
|||
this.forceUpdate();
|
||||
},
|
||||
|
||||
_renderEncryptionSection: function() {
|
||||
var cli = MatrixClientPeg.get();
|
||||
var roomState = this.props.room.currentState;
|
||||
var isEncrypted = cli.isRoomEncrypted(this.props.room.roomId);
|
||||
var isGlobalBlacklistUnverified = UserSettingsStore.getLocalSettings().blacklistUnverifiedDevices;
|
||||
var isRoomBlacklistUnverified = this._isRoomBlacklistUnverified();
|
||||
_populateDefaultPlEvents: function(eventsSection, stateLevel, eventsLevel) {
|
||||
for (const desiredEvent of Object.keys(plEventsToShow)) {
|
||||
if (!(desiredEvent in eventsSection)) {
|
||||
eventsSection[desiredEvent] = (plEventsToShow[desiredEvent].isState ? stateLevel : eventsLevel);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
var settings =
|
||||
_renderEncryptionSection: function() {
|
||||
const cli = MatrixClientPeg.get();
|
||||
const roomState = this.props.room.currentState;
|
||||
const isEncrypted = cli.isRoomEncrypted(this.props.room.roomId);
|
||||
const isGlobalBlacklistUnverified = UserSettingsStore.getLocalSettings().blacklistUnverifiedDevices;
|
||||
const isRoomBlacklistUnverified = this._isRoomBlacklistUnverified();
|
||||
|
||||
const settings =
|
||||
<label>
|
||||
<input type="checkbox" ref="blacklistUnverified"
|
||||
defaultChecked={ isGlobalBlacklistUnverified || isRoomBlacklistUnverified }
|
||||
disabled={ isGlobalBlacklistUnverified || (this.refs.encrypt && !this.refs.encrypt.checked) }/>
|
||||
defaultChecked={isGlobalBlacklistUnverified || isRoomBlacklistUnverified}
|
||||
disabled={isGlobalBlacklistUnverified || (this.refs.encrypt && !this.refs.encrypt.checked)} />
|
||||
{ _t('Never send encrypted messages to unverified devices in this room from this device') }.
|
||||
</label>;
|
||||
|
||||
|
@ -568,7 +606,7 @@ module.exports = React.createClass({
|
|||
return (
|
||||
<div>
|
||||
<label>
|
||||
<input type="checkbox" ref="encrypt" onClick={ this.onEnableEncryptionClick }/>
|
||||
<input type="checkbox" ref="encrypt" onClick={this.onEnableEncryptionClick} />
|
||||
<img className="mx_RoomSettings_e2eIcon mx_filterFlipColor" src="img/e2e-unencrypted.svg" width="12" height="12" />
|
||||
{ _t('Enable encryption') } { _t('(warning: cannot be disabled again!)') }
|
||||
</label>
|
||||
|
@ -595,41 +633,43 @@ module.exports = React.createClass({
|
|||
// TODO: go through greying out things you don't have permission to change
|
||||
// (or turning them into informative stuff)
|
||||
|
||||
var AliasSettings = sdk.getComponent("room_settings.AliasSettings");
|
||||
var ColorSettings = sdk.getComponent("room_settings.ColorSettings");
|
||||
var UrlPreviewSettings = sdk.getComponent("room_settings.UrlPreviewSettings");
|
||||
var RelatedGroupSettings = sdk.getComponent("room_settings.RelatedGroupSettings");
|
||||
var EditableText = sdk.getComponent('elements.EditableText');
|
||||
var PowerSelector = sdk.getComponent('elements.PowerSelector');
|
||||
var Loader = sdk.getComponent("elements.Spinner");
|
||||
const AliasSettings = sdk.getComponent("room_settings.AliasSettings");
|
||||
const ColorSettings = sdk.getComponent("room_settings.ColorSettings");
|
||||
const UrlPreviewSettings = sdk.getComponent("room_settings.UrlPreviewSettings");
|
||||
const RelatedGroupSettings = sdk.getComponent("room_settings.RelatedGroupSettings");
|
||||
const EditableText = sdk.getComponent('elements.EditableText');
|
||||
const PowerSelector = sdk.getComponent('elements.PowerSelector');
|
||||
const Loader = sdk.getComponent("elements.Spinner");
|
||||
|
||||
var cli = MatrixClientPeg.get();
|
||||
var roomState = this.props.room.currentState;
|
||||
var user_id = cli.credentials.userId;
|
||||
const cli = MatrixClientPeg.get();
|
||||
const roomState = this.props.room.currentState;
|
||||
const user_id = cli.credentials.userId;
|
||||
|
||||
var power_level_event = roomState.getStateEvents('m.room.power_levels', '');
|
||||
var power_levels = power_level_event ? power_level_event.getContent() : {};
|
||||
var events_levels = power_levels.events || {};
|
||||
var user_levels = power_levels.users || {};
|
||||
const power_level_event = roomState.getStateEvents('m.room.power_levels', '');
|
||||
const power_levels = power_level_event ? power_level_event.getContent() : {};
|
||||
const events_levels = power_levels.events || {};
|
||||
const user_levels = power_levels.users || {};
|
||||
|
||||
var ban_level = parseIntWithDefault(power_levels.ban, 50);
|
||||
var kick_level = parseIntWithDefault(power_levels.kick, 50);
|
||||
var redact_level = parseIntWithDefault(power_levels.redact, 50);
|
||||
var invite_level = parseIntWithDefault(power_levels.invite, 50);
|
||||
var send_level = parseIntWithDefault(power_levels.events_default, 0);
|
||||
var state_level = power_level_event ? parseIntWithDefault(power_levels.state_default, 50) : 0;
|
||||
var default_user_level = parseIntWithDefault(power_levels.users_default, 0);
|
||||
const ban_level = parseIntWithDefault(power_levels.ban, 50);
|
||||
const kick_level = parseIntWithDefault(power_levels.kick, 50);
|
||||
const redact_level = parseIntWithDefault(power_levels.redact, 50);
|
||||
const invite_level = parseIntWithDefault(power_levels.invite, 50);
|
||||
const send_level = parseIntWithDefault(power_levels.events_default, 0);
|
||||
const state_level = power_level_event ? parseIntWithDefault(power_levels.state_default, 50) : 0;
|
||||
const default_user_level = parseIntWithDefault(power_levels.users_default, 0);
|
||||
|
||||
var current_user_level = user_levels[user_id];
|
||||
this._populateDefaultPlEvents(events_levels, state_level, send_level);
|
||||
|
||||
let current_user_level = user_levels[user_id];
|
||||
if (current_user_level === undefined) {
|
||||
current_user_level = default_user_level;
|
||||
}
|
||||
|
||||
var can_change_levels = roomState.mayClientSendStateEvent("m.room.power_levels", cli);
|
||||
const can_change_levels = roomState.mayClientSendStateEvent("m.room.power_levels", cli);
|
||||
|
||||
var canSetTag = !cli.isGuest();
|
||||
const canSetTag = !cli.isGuest();
|
||||
|
||||
var self = this;
|
||||
const self = this;
|
||||
|
||||
let relatedGroupsSection;
|
||||
if (UserSettingsStore.isFeatureEnabled('feature_groups')) {
|
||||
|
@ -639,23 +679,22 @@ module.exports = React.createClass({
|
|||
relatedGroupsEvent={this.props.room.currentState.getStateEvents('m.room.related_groups', '')} />;
|
||||
}
|
||||
|
||||
var userLevelsSection;
|
||||
let userLevelsSection;
|
||||
if (Object.keys(user_levels).length) {
|
||||
userLevelsSection =
|
||||
<div>
|
||||
<h3>{ _t('Privileged Users') }</h3>
|
||||
<ul className="mx_RoomSettings_userLevels">
|
||||
{Object.keys(user_levels).map(function(user, i) {
|
||||
{ Object.keys(user_levels).map(function(user, i) {
|
||||
return (
|
||||
<li className="mx_RoomSettings_userLevel" key={user}>
|
||||
{ _t("%(user)s is a", {user: user}) } <PowerSelector value={ user_levels[user] } disabled={true}/>
|
||||
{ _t("%(user)s is a", {user: user}) } <PowerSelector value={user_levels[user]} disabled={true} />
|
||||
</li>
|
||||
);
|
||||
})}
|
||||
}) }
|
||||
</ul>
|
||||
</div>;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
userLevelsSection = <div>{ _t('No users have specific privileges in this room') }.</div>;
|
||||
}
|
||||
|
||||
|
@ -667,18 +706,21 @@ module.exports = React.createClass({
|
|||
<div>
|
||||
<h3>{ _t('Banned users') }</h3>
|
||||
<ul className="mx_RoomSettings_banned">
|
||||
{banned.map(function(member) {
|
||||
{ banned.map(function(member) {
|
||||
const banEvent = member.events.member.getContent();
|
||||
const sender = self.props.room.getMember(member.events.member.getSender());
|
||||
let bannedBy = member.events.member.getSender(); // start by falling back to mxid
|
||||
if (sender) bannedBy = sender.name;
|
||||
return (
|
||||
<BannedUser key={member.userId} canUnban={canBanUsers} member={member} reason={banEvent.reason} />
|
||||
<BannedUser key={member.userId} canUnban={canBanUsers} member={member} reason={banEvent.reason} by={bannedBy} />
|
||||
);
|
||||
})}
|
||||
}) }
|
||||
</ul>
|
||||
</div>;
|
||||
}
|
||||
|
||||
var unfederatableSection;
|
||||
if (this._yankValueFromEvent("m.room.create", "m.federate") === false) {
|
||||
let unfederatableSection;
|
||||
if (this._yankValueFromEvent("m.room.create", "m.federate", true) === false) {
|
||||
unfederatableSection = (
|
||||
<div className="mx_RoomSettings_powerLevel">
|
||||
{ _t('This room is not accessible by remote Matrix servers') }.
|
||||
|
@ -686,19 +728,18 @@ module.exports = React.createClass({
|
|||
);
|
||||
}
|
||||
|
||||
var leaveButton = null;
|
||||
var myMember = this.props.room.getMember(user_id);
|
||||
let leaveButton = null;
|
||||
const myMember = this.props.room.getMember(user_id);
|
||||
if (myMember) {
|
||||
if (myMember.membership === "join") {
|
||||
leaveButton = (
|
||||
<AccessibleButton className="mx_RoomSettings_leaveButton" onClick={ this.onLeaveClick }>
|
||||
<AccessibleButton className="mx_RoomSettings_leaveButton" onClick={this.onLeaveClick}>
|
||||
{ _t('Leave room') }
|
||||
</AccessibleButton>
|
||||
);
|
||||
}
|
||||
else if (myMember.membership === "leave") {
|
||||
} else if (myMember.membership === "leave") {
|
||||
leaveButton = (
|
||||
<AccessibleButton className="mx_RoomSettings_leaveButton" onClick={ this.onForgetClick }>
|
||||
<AccessibleButton className="mx_RoomSettings_leaveButton" onClick={this.onForgetClick}>
|
||||
{ _t('Forget room') }
|
||||
</AccessibleButton>
|
||||
);
|
||||
|
@ -708,7 +749,7 @@ module.exports = React.createClass({
|
|||
// TODO: support editing custom events_levels
|
||||
// TODO: support editing custom user_levels
|
||||
|
||||
var tags = [
|
||||
const tags = [
|
||||
{ name: "m.favourite", label: _t('Favourite'), ref: "tag_favourite" },
|
||||
{ name: "m.lowpriority", label: _t('Low priority'), ref: "tag_lowpriority" },
|
||||
];
|
||||
|
@ -723,13 +764,13 @@ module.exports = React.createClass({
|
|||
if (canSetTag || self.state.tags) {
|
||||
var tagsSection =
|
||||
<div className="mx_RoomSettings_tags">
|
||||
{_t("Tagged as: ")}{ canSetTag ?
|
||||
{ _t("Tagged as: ") }{ canSetTag ?
|
||||
(tags.map(function(tag, i) {
|
||||
return (<label key={ i }>
|
||||
return (<label key={i}>
|
||||
<input type="checkbox"
|
||||
ref={ tag.ref }
|
||||
checked={ tag.name in self.state.tags }
|
||||
onChange={ self._onTagChange.bind(self, tag.name) }/>
|
||||
ref={tag.ref}
|
||||
checked={tag.name in self.state.tags}
|
||||
onChange={self._onTagChange.bind(self, tag.name)} />
|
||||
{ tag.label }
|
||||
</label>);
|
||||
})) : (self.state.tags && self.state.tags.join) ? self.state.tags.join(", ") : ""
|
||||
|
@ -739,11 +780,11 @@ module.exports = React.createClass({
|
|||
|
||||
// If there is no history_visibility, it is assumed to be 'shared'.
|
||||
// http://matrix.org/docs/spec/r0.0.0/client_server.html#id31
|
||||
var historyVisibility = this.state.history_visibility || "shared";
|
||||
const historyVisibility = this.state.history_visibility || "shared";
|
||||
|
||||
var addressWarning;
|
||||
var aliasEvents = this.props.room.currentState.getStateEvents('m.room.aliases') || [];
|
||||
var aliasCount = 0;
|
||||
let addressWarning;
|
||||
const aliasEvents = this.props.room.currentState.getStateEvents('m.room.aliases') || [];
|
||||
let aliasCount = 0;
|
||||
aliasEvents.forEach((event) => {
|
||||
aliasCount += event.getContent().aliases.length;
|
||||
});
|
||||
|
@ -754,16 +795,16 @@ module.exports = React.createClass({
|
|||
{ _tJsx(
|
||||
'To link to a room it must have <a>an address</a>.',
|
||||
/<a>(.*?)<\/a>/,
|
||||
(sub) => <a href="#addresses">{sub}</a>
|
||||
)}
|
||||
(sub) => <a href="#addresses">{ sub }</a>,
|
||||
) }
|
||||
</div>;
|
||||
}
|
||||
|
||||
var inviteGuestWarning;
|
||||
let inviteGuestWarning;
|
||||
if (this.state.join_rule !== "public" && this.state.guest_access === "forbidden") {
|
||||
inviteGuestWarning =
|
||||
<div className="mx_RoomSettings_warning">
|
||||
{ _t('Guests cannot join this room even if explicitly invited.') } <a href="#" onClick={ (e) => {
|
||||
{ _t('Guests cannot join this room even if explicitly invited.') } <a href="#" onClick={(e) => {
|
||||
this.setState({ join_rule: "invite", guest_access: "can_join" });
|
||||
e.preventDefault();
|
||||
}}>{ _t('Click here to fix') }</a>.
|
||||
|
@ -783,61 +824,61 @@ module.exports = React.createClass({
|
|||
{ inviteGuestWarning }
|
||||
<label>
|
||||
<input type="radio" name="roomVis" value="invite_only"
|
||||
disabled={ !this.mayChangeRoomAccess() }
|
||||
disabled={!this.mayChangeRoomAccess()}
|
||||
onChange={this._onRoomAccessRadioToggle}
|
||||
checked={this.state.join_rule !== "public"}/>
|
||||
checked={this.state.join_rule !== "public"} />
|
||||
{ _t('Only people who have been invited') }
|
||||
</label>
|
||||
<label>
|
||||
<input type="radio" name="roomVis" value="public_no_guests"
|
||||
disabled={ !this.mayChangeRoomAccess() }
|
||||
disabled={!this.mayChangeRoomAccess()}
|
||||
onChange={this._onRoomAccessRadioToggle}
|
||||
checked={this.state.join_rule === "public" && this.state.guest_access !== "can_join"}/>
|
||||
checked={this.state.join_rule === "public" && this.state.guest_access !== "can_join"} />
|
||||
{ _t('Anyone who knows the room\'s link, apart from guests') }
|
||||
</label>
|
||||
<label>
|
||||
<input type="radio" name="roomVis" value="public_with_guests"
|
||||
disabled={ !this.mayChangeRoomAccess() }
|
||||
disabled={!this.mayChangeRoomAccess()}
|
||||
onChange={this._onRoomAccessRadioToggle}
|
||||
checked={this.state.join_rule === "public" && this.state.guest_access === "can_join"}/>
|
||||
checked={this.state.join_rule === "public" && this.state.guest_access === "can_join"} />
|
||||
{ _t('Anyone who knows the room\'s link, including guests') }
|
||||
</label>
|
||||
{ addressWarning }
|
||||
<br/>
|
||||
<br />
|
||||
{ this._renderEncryptionSection() }
|
||||
<label>
|
||||
<input type="checkbox" disabled={ !roomState.mayClientSendStateEvent("m.room.aliases", cli) }
|
||||
onChange={ this._onToggle.bind(this, "isRoomPublished", true, false)}
|
||||
checked={this.state.isRoomPublished}/>
|
||||
{_t("Publish this room to the public in %(domain)s's room directory?", { domain: MatrixClientPeg.get().getDomain() })}
|
||||
<input type="checkbox" disabled={!roomState.mayClientSendStateEvent("m.room.aliases", cli)}
|
||||
onChange={this._onToggle.bind(this, "isRoomPublished", true, false)}
|
||||
checked={this.state.isRoomPublished} />
|
||||
{ _t("Publish this room to the public in %(domain)s's room directory?", { domain: MatrixClientPeg.get().getDomain() }) }
|
||||
</label>
|
||||
</div>
|
||||
<div className="mx_RoomSettings_settings">
|
||||
<h3>{ _t('Who can read history?') }</h3>
|
||||
<label>
|
||||
<input type="radio" name="historyVis" value="world_readable"
|
||||
disabled={ !roomState.mayClientSendStateEvent("m.room.history_visibility", cli) }
|
||||
disabled={!roomState.mayClientSendStateEvent("m.room.history_visibility", cli)}
|
||||
checked={historyVisibility === "world_readable"}
|
||||
onChange={this._onHistoryRadioToggle} />
|
||||
{_t("Anyone")}
|
||||
{ _t("Anyone") }
|
||||
</label>
|
||||
<label>
|
||||
<input type="radio" name="historyVis" value="shared"
|
||||
disabled={ !roomState.mayClientSendStateEvent("m.room.history_visibility", cli) }
|
||||
disabled={!roomState.mayClientSendStateEvent("m.room.history_visibility", cli)}
|
||||
checked={historyVisibility === "shared"}
|
||||
onChange={this._onHistoryRadioToggle} />
|
||||
{ _t('Members only') } ({ _t('since the point in time of selecting this option') })
|
||||
</label>
|
||||
<label>
|
||||
<input type="radio" name="historyVis" value="invited"
|
||||
disabled={ !roomState.mayClientSendStateEvent("m.room.history_visibility", cli) }
|
||||
disabled={!roomState.mayClientSendStateEvent("m.room.history_visibility", cli)}
|
||||
checked={historyVisibility === "invited"}
|
||||
onChange={this._onHistoryRadioToggle} />
|
||||
{ _t('Members only') } ({ _t('since they were invited') })
|
||||
</label>
|
||||
<label >
|
||||
<input type="radio" name="historyVis" value="joined"
|
||||
disabled={ !roomState.mayClientSendStateEvent("m.room.history_visibility", cli) }
|
||||
disabled={!roomState.mayClientSendStateEvent("m.room.history_visibility", cli)}
|
||||
checked={historyVisibility === "joined"}
|
||||
onChange={this._onHistoryRadioToggle} />
|
||||
{ _t('Members only') } ({ _t('since they joined') })
|
||||
|
@ -851,11 +892,11 @@ module.exports = React.createClass({
|
|||
<ColorSettings ref="color_settings" room={this.props.room} />
|
||||
</div>
|
||||
|
||||
<a id="addresses"/>
|
||||
<a id="addresses" />
|
||||
|
||||
<AliasSettings ref="alias_settings"
|
||||
roomId={this.props.room.roomId}
|
||||
canSetCanonicalAlias={ roomState.mayClientSendStateEvent("m.room.canonical_alias", cli) }
|
||||
canSetCanonicalAlias={roomState.mayClientSendStateEvent("m.room.canonical_alias", cli)}
|
||||
canSetAliases={
|
||||
true
|
||||
/* Originally, we arbitrarily restricted creating aliases to room admins: roomState.mayClientSendStateEvent("m.room.aliases", cli) */
|
||||
|
@ -871,41 +912,45 @@ module.exports = React.createClass({
|
|||
<div className="mx_RoomSettings_powerLevels mx_RoomSettings_settings">
|
||||
<div className="mx_RoomSettings_powerLevel">
|
||||
<span className="mx_RoomSettings_powerLevelKey">{ _t('The default role for new room members is') } </span>
|
||||
<PowerSelector ref="users_default" value={default_user_level} controlled={false} disabled={!can_change_levels || current_user_level < default_user_level} onChange={this.onPowerLevelsChanged}/>
|
||||
<PowerSelector ref="users_default" value={default_user_level} controlled={false} disabled={!can_change_levels || current_user_level < default_user_level} onChange={this.onPowerLevelsChanged} />
|
||||
</div>
|
||||
<div className="mx_RoomSettings_powerLevel">
|
||||
<span className="mx_RoomSettings_powerLevelKey">{ _t('To send messages') }, { _t('you must be a') } </span>
|
||||
<PowerSelector ref="events_default" value={send_level} controlled={false} disabled={!can_change_levels || current_user_level < send_level} onChange={this.onPowerLevelsChanged}/>
|
||||
<span className="mx_RoomSettings_powerLevelKey">{ _t('To send messages, you must be a') } </span>
|
||||
<PowerSelector ref="events_default" value={send_level} controlled={false} disabled={!can_change_levels || current_user_level < send_level} onChange={this.onPowerLevelsChanged} />
|
||||
</div>
|
||||
<div className="mx_RoomSettings_powerLevel">
|
||||
<span className="mx_RoomSettings_powerLevelKey">{ _t('To invite users into the room') }, { _t('you must be a') } </span>
|
||||
<PowerSelector ref="invite" value={invite_level} controlled={false} disabled={!can_change_levels || current_user_level < invite_level} onChange={this.onPowerLevelsChanged}/>
|
||||
<span className="mx_RoomSettings_powerLevelKey">{ _t('To invite users into the room, you must be a') } </span>
|
||||
<PowerSelector ref="invite" value={invite_level} controlled={false} disabled={!can_change_levels || current_user_level < invite_level} onChange={this.onPowerLevelsChanged} />
|
||||
</div>
|
||||
<div className="mx_RoomSettings_powerLevel">
|
||||
<span className="mx_RoomSettings_powerLevelKey">{ _t('To configure the room') }, { _t('you must be a') } </span>
|
||||
<PowerSelector ref="state_default" value={state_level} controlled={false} disabled={!can_change_levels || current_user_level < state_level} onChange={this.onPowerLevelsChanged}/>
|
||||
<span className="mx_RoomSettings_powerLevelKey">{ _t('To configure the room, you must be a') } </span>
|
||||
<PowerSelector ref="state_default" value={state_level} controlled={false} disabled={!can_change_levels || current_user_level < state_level} onChange={this.onPowerLevelsChanged} />
|
||||
</div>
|
||||
<div className="mx_RoomSettings_powerLevel">
|
||||
<span className="mx_RoomSettings_powerLevelKey">{ _t('To kick users') }, { _t('you must be a') } </span>
|
||||
<PowerSelector ref="kick" value={kick_level} controlled={false} disabled={!can_change_levels || current_user_level < kick_level} onChange={this.onPowerLevelsChanged}/>
|
||||
<span className="mx_RoomSettings_powerLevelKey">{ _t('To kick users, you must be a') } </span>
|
||||
<PowerSelector ref="kick" value={kick_level} controlled={false} disabled={!can_change_levels || current_user_level < kick_level} onChange={this.onPowerLevelsChanged} />
|
||||
</div>
|
||||
<div className="mx_RoomSettings_powerLevel">
|
||||
<span className="mx_RoomSettings_powerLevelKey">{ _t('To ban users') }, { _t('you must be a') } </span>
|
||||
<PowerSelector ref="ban" value={ban_level} controlled={false} disabled={!can_change_levels || current_user_level < ban_level} onChange={this.onPowerLevelsChanged}/>
|
||||
<span className="mx_RoomSettings_powerLevelKey">{ _t('To ban users, you must be a') } </span>
|
||||
<PowerSelector ref="ban" value={ban_level} controlled={false} disabled={!can_change_levels || current_user_level < ban_level} onChange={this.onPowerLevelsChanged} />
|
||||
</div>
|
||||
<div className="mx_RoomSettings_powerLevel">
|
||||
<span className="mx_RoomSettings_powerLevelKey">{ _t('To remove other users\' messages') }, { _t('you must be a') } </span>
|
||||
<PowerSelector ref="redact" value={redact_level} controlled={false} disabled={!can_change_levels || current_user_level < redact_level} onChange={this.onPowerLevelsChanged}/>
|
||||
<span className="mx_RoomSettings_powerLevelKey">{ _t('To remove other users\' messages, you must be a') } </span>
|
||||
<PowerSelector ref="redact" value={redact_level} controlled={false} disabled={!can_change_levels || current_user_level < redact_level} onChange={this.onPowerLevelsChanged} />
|
||||
</div>
|
||||
|
||||
{Object.keys(events_levels).map(function(event_type, i) {
|
||||
{ Object.keys(events_levels).map(function(event_type, i) {
|
||||
let label = plEventsToLabels[event_type];
|
||||
if (label) label = _t(label);
|
||||
else label = _tJsx("To send events of type <eventType/>, you must be a", /<eventType\/>/, () => <code>{ event_type }</code>);
|
||||
return (
|
||||
<div className="mx_RoomSettings_powerLevel" key={event_type}>
|
||||
<span className="mx_RoomSettings_powerLevelKey">{ _t('To send events of type') } <code>{ event_type }</code>, { _t('you must be a') } </span>
|
||||
<PowerSelector value={ events_levels[event_type] } controlled={false} disabled={true} onChange={self.onPowerLevelsChanged}/>
|
||||
<span className="mx_RoomSettings_powerLevelKey">{ label } </span>
|
||||
<PowerSelector ref={"event_levels_"+event_type} value={events_levels[event_type]} onChange={self.onPowerLevelsChanged}
|
||||
controlled={false} disabled={!can_change_levels || current_user_level < events_levels[event_type]} />
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
}) }
|
||||
|
||||
{ unfederatableSection }
|
||||
</div>
|
||||
|
@ -920,5 +965,5 @@ module.exports = React.createClass({
|
|||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
|
|
@ -17,17 +17,17 @@ limitations under the License.
|
|||
|
||||
'use strict';
|
||||
|
||||
var React = require('react');
|
||||
var ReactDOM = require("react-dom");
|
||||
var classNames = require('classnames');
|
||||
var MatrixClientPeg = require('../../../MatrixClientPeg');
|
||||
const React = require('react');
|
||||
const ReactDOM = require("react-dom");
|
||||
const classNames = require('classnames');
|
||||
const MatrixClientPeg = require('../../../MatrixClientPeg');
|
||||
import DMRoomMap from '../../../utils/DMRoomMap';
|
||||
var sdk = require('../../../index');
|
||||
var ContextualMenu = require('../../structures/ContextualMenu');
|
||||
var RoomNotifs = require('../../../RoomNotifs');
|
||||
var FormattingUtils = require('../../../utils/FormattingUtils');
|
||||
const sdk = require('../../../index');
|
||||
const ContextualMenu = require('../../structures/ContextualMenu');
|
||||
const RoomNotifs = require('../../../RoomNotifs');
|
||||
const FormattingUtils = require('../../../utils/FormattingUtils');
|
||||
import AccessibleButton from '../elements/AccessibleButton';
|
||||
var UserSettingsStore = require('../../../UserSettingsStore');
|
||||
const UserSettingsStore = require('../../../UserSettingsStore');
|
||||
import ActiveRoomObserver from '../../../ActiveRoomObserver';
|
||||
import RoomViewStore from '../../../stores/RoomViewStore';
|
||||
|
||||
|
@ -56,8 +56,8 @@ module.exports = React.createClass({
|
|||
|
||||
getInitialState: function() {
|
||||
return({
|
||||
hover : false,
|
||||
badgeHover : false,
|
||||
hover: false,
|
||||
badgeHover: false,
|
||||
menuDisplayed: false,
|
||||
notifState: RoomNotifs.getRoomNotifsState(this.props.room.roomId),
|
||||
selected: this.props.room.roomId === RoomViewStore.getRoomId(),
|
||||
|
@ -74,7 +74,7 @@ module.exports = React.createClass({
|
|||
},
|
||||
|
||||
_isDirectMessageRoom: function(roomId) {
|
||||
var dmRooms = DMRoomMap.shared().getUserIdForRoomId(roomId);
|
||||
const dmRooms = DMRoomMap.shared().getUserIdForRoomId(roomId);
|
||||
if (dmRooms) {
|
||||
return true;
|
||||
} else {
|
||||
|
@ -102,7 +102,7 @@ module.exports = React.createClass({
|
|||
},
|
||||
|
||||
componentWillUnmount: function() {
|
||||
var cli = MatrixClientPeg.get();
|
||||
const cli = MatrixClientPeg.get();
|
||||
if (cli) {
|
||||
MatrixClientPeg.get().removeListener("accountData", this.onAccountData);
|
||||
}
|
||||
|
@ -116,12 +116,12 @@ module.exports = React.createClass({
|
|||
},
|
||||
|
||||
onMouseEnter: function() {
|
||||
this.setState( { hover : true });
|
||||
this.setState( { hover: true });
|
||||
this.badgeOnMouseEnter();
|
||||
},
|
||||
|
||||
onMouseLeave: function() {
|
||||
this.setState( { hover : false });
|
||||
this.setState( { hover: false });
|
||||
this.badgeOnMouseLeave();
|
||||
},
|
||||
|
||||
|
@ -129,25 +129,24 @@ module.exports = React.createClass({
|
|||
// Only allow non-guests to access the context menu
|
||||
// and only change it if it needs to change
|
||||
if (!MatrixClientPeg.get().isGuest() && !this.state.badgeHover) {
|
||||
this.setState( { badgeHover : true } );
|
||||
this.setState( { badgeHover: true } );
|
||||
}
|
||||
},
|
||||
|
||||
badgeOnMouseLeave: function() {
|
||||
this.setState( { badgeHover : false } );
|
||||
this.setState( { badgeHover: false } );
|
||||
},
|
||||
|
||||
onBadgeClicked: function(e) {
|
||||
// Only allow none guests to access the context menu
|
||||
if (!MatrixClientPeg.get().isGuest()) {
|
||||
|
||||
// If the badge is clicked, then no longer show tooltip
|
||||
if (this.props.collapsed) {
|
||||
this.setState({ hover: false });
|
||||
}
|
||||
|
||||
var RoomTileContextMenu = sdk.getComponent('context_menus.RoomTileContextMenu');
|
||||
var elementRect = e.target.getBoundingClientRect();
|
||||
const RoomTileContextMenu = sdk.getComponent('context_menus.RoomTileContextMenu');
|
||||
const elementRect = e.target.getBoundingClientRect();
|
||||
|
||||
// The window X and Y offsets are to adjust position when zoomed in to page
|
||||
const x = elementRect.right + window.pageXOffset + 3;
|
||||
|
@ -155,7 +154,7 @@ module.exports = React.createClass({
|
|||
let y = (elementRect.top + (elementRect.height / 2) + window.pageYOffset);
|
||||
y = y - (chevronOffset + 8); // where 8 is half the height of the chevron
|
||||
|
||||
var self = this;
|
||||
const self = this;
|
||||
ContextualMenu.createMenu(RoomTileContextMenu, {
|
||||
chevronOffset: chevronOffset,
|
||||
left: x,
|
||||
|
@ -164,7 +163,7 @@ module.exports = React.createClass({
|
|||
onFinished: function() {
|
||||
self.setState({ menuDisplayed: false });
|
||||
self.props.refreshSubList();
|
||||
}
|
||||
},
|
||||
});
|
||||
this.setState({ menuDisplayed: true });
|
||||
}
|
||||
|
@ -173,17 +172,17 @@ module.exports = React.createClass({
|
|||
},
|
||||
|
||||
render: function() {
|
||||
var myUserId = MatrixClientPeg.get().credentials.userId;
|
||||
var me = this.props.room.currentState.members[myUserId];
|
||||
const myUserId = MatrixClientPeg.get().credentials.userId;
|
||||
const me = this.props.room.currentState.members[myUserId];
|
||||
|
||||
var notificationCount = this.props.room.getUnreadNotificationCount();
|
||||
const notificationCount = this.props.room.getUnreadNotificationCount();
|
||||
// var highlightCount = this.props.room.getUnreadNotificationCount("highlight");
|
||||
|
||||
const notifBadges = notificationCount > 0 && this._shouldShowNotifBadge();
|
||||
const mentionBadges = this.props.highlight && this._shouldShowMentionBadge();
|
||||
const badges = notifBadges || mentionBadges;
|
||||
|
||||
var classes = classNames({
|
||||
const classes = classNames({
|
||||
'mx_RoomTile': true,
|
||||
'mx_RoomTile_selected': this.state.selected,
|
||||
'mx_RoomTile_unread': this.props.unread,
|
||||
|
@ -194,53 +193,53 @@ module.exports = React.createClass({
|
|||
'mx_RoomTile_noBadges': !badges,
|
||||
});
|
||||
|
||||
var avatarClasses = classNames({
|
||||
const avatarClasses = classNames({
|
||||
'mx_RoomTile_avatar': true,
|
||||
});
|
||||
|
||||
var badgeClasses = classNames({
|
||||
const badgeClasses = classNames({
|
||||
'mx_RoomTile_badge': true,
|
||||
'mx_RoomTile_badgeButton': this.state.badgeHover || this.state.menuDisplayed,
|
||||
});
|
||||
|
||||
// XXX: We should never display raw room IDs, but sometimes the
|
||||
// room name js sdk gives is undefined (cannot repro this -- k)
|
||||
var name = this.props.room.name || this.props.room.roomId;
|
||||
let name = this.props.room.name || this.props.room.roomId;
|
||||
name = name.replace(":", ":\u200b"); // add a zero-width space to allow linewrapping after the colon
|
||||
|
||||
var badge;
|
||||
var badgeContent;
|
||||
let badge;
|
||||
let badgeContent;
|
||||
|
||||
if (this.state.badgeHover || this.state.menuDisplayed) {
|
||||
badgeContent = "\u00B7\u00B7\u00B7";
|
||||
} else if (badges) {
|
||||
var limitedCount = FormattingUtils.formatCount(notificationCount);
|
||||
const limitedCount = FormattingUtils.formatCount(notificationCount);
|
||||
badgeContent = notificationCount ? limitedCount : '!';
|
||||
} else {
|
||||
badgeContent = '\u200B';
|
||||
}
|
||||
|
||||
badge = <div className={ badgeClasses } onClick={this.onBadgeClicked}>{ badgeContent }</div>;
|
||||
badge = <div className={badgeClasses} onClick={this.onBadgeClicked}>{ badgeContent }</div>;
|
||||
|
||||
const EmojiText = sdk.getComponent('elements.EmojiText');
|
||||
var label;
|
||||
var tooltip;
|
||||
let label;
|
||||
let tooltip;
|
||||
if (!this.props.collapsed) {
|
||||
var nameClasses = classNames({
|
||||
const nameClasses = classNames({
|
||||
'mx_RoomTile_name': true,
|
||||
'mx_RoomTile_invite': this.props.isInvite,
|
||||
'mx_RoomTile_badgeShown': badges || this.state.badgeHover || this.state.menuDisplayed,
|
||||
});
|
||||
|
||||
if (this.state.selected) {
|
||||
let nameSelected = <EmojiText>{name}</EmojiText>;
|
||||
const nameSelected = <EmojiText>{ name }</EmojiText>;
|
||||
|
||||
label = <div title={ name } className={ nameClasses } dir="auto">{ nameSelected }</div>;
|
||||
label = <div title={name} className={nameClasses} dir="auto">{ nameSelected }</div>;
|
||||
} else {
|
||||
label = <EmojiText element="div" title={ name } className={ nameClasses } dir="auto">{name}</EmojiText>;
|
||||
label = <EmojiText element="div" title={name} className={nameClasses} dir="auto">{ name }</EmojiText>;
|
||||
}
|
||||
} else if (this.state.hover) {
|
||||
var RoomTooltip = sdk.getComponent("rooms.RoomTooltip");
|
||||
const RoomTooltip = sdk.getComponent("rooms.RoomTooltip");
|
||||
tooltip = <RoomTooltip className="mx_RoomTile_tooltip" room={this.props.room} dir="auto" />;
|
||||
}
|
||||
|
||||
|
@ -250,34 +249,34 @@ module.exports = React.createClass({
|
|||
// incomingCallBox = <IncomingCallBox incomingCall={ this.props.incomingCall }/>;
|
||||
//}
|
||||
|
||||
var RoomAvatar = sdk.getComponent('avatars.RoomAvatar');
|
||||
const RoomAvatar = sdk.getComponent('avatars.RoomAvatar');
|
||||
|
||||
var directMessageIndicator;
|
||||
let directMessageIndicator;
|
||||
if (this._isDirectMessageRoom(this.props.room.roomId)) {
|
||||
directMessageIndicator = <img src="img/icon_person.svg" className="mx_RoomTile_dm" width="11" height="13" alt="dm"/>;
|
||||
directMessageIndicator = <img src="img/icon_person.svg" className="mx_RoomTile_dm" width="11" height="13" alt="dm" />;
|
||||
}
|
||||
|
||||
// These props are injected by React DnD,
|
||||
// as defined by your `collect` function above:
|
||||
var isDragging = this.props.isDragging;
|
||||
var connectDragSource = this.props.connectDragSource;
|
||||
var connectDropTarget = this.props.connectDropTarget;
|
||||
const isDragging = this.props.isDragging;
|
||||
const connectDragSource = this.props.connectDragSource;
|
||||
const connectDropTarget = this.props.connectDropTarget;
|
||||
|
||||
|
||||
let ret = (
|
||||
<div> { /* Only native elements can be wrapped in a DnD object. */}
|
||||
<div> { /* Only native elements can be wrapped in a DnD object. */ }
|
||||
<AccessibleButton className={classes} tabIndex="0" onClick={this.onClick} onMouseEnter={this.onMouseEnter} onMouseLeave={this.onMouseLeave}>
|
||||
<div className={avatarClasses}>
|
||||
<div className="mx_RoomTile_avatar_container">
|
||||
<RoomAvatar room={this.props.room} width={24} height={24} />
|
||||
{directMessageIndicator}
|
||||
{ directMessageIndicator }
|
||||
</div>
|
||||
</div>
|
||||
<div className="mx_RoomTile_nameContainer">
|
||||
{ label }
|
||||
{ badge }
|
||||
</div>
|
||||
{/* { incomingCallBox } */}
|
||||
{ /* { incomingCallBox } */ }
|
||||
{ tooltip }
|
||||
</AccessibleButton>
|
||||
</div>
|
||||
|
@ -287,5 +286,5 @@ module.exports = React.createClass({
|
|||
if (connectDragSource) ret = connectDragSource(ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
},
|
||||
});
|
||||
|
|
|
@ -16,8 +16,8 @@ limitations under the License.
|
|||
|
||||
'use strict';
|
||||
|
||||
var React = require('react');
|
||||
var sdk = require('../../../index');
|
||||
const React = require('react');
|
||||
const sdk = require('../../../index');
|
||||
import { _t } from "../../../languageHandler";
|
||||
|
||||
module.exports = React.createClass({
|
||||
|
@ -28,8 +28,8 @@ module.exports = React.createClass({
|
|||
},
|
||||
|
||||
componentWillMount: function() {
|
||||
var room = this.props.room;
|
||||
var topic = room.currentState.getStateEvents('m.room.topic', '');
|
||||
const room = this.props.room;
|
||||
const topic = room.currentState.getStateEvents('m.room.topic', '');
|
||||
this._initialTopic = topic ? topic.getContent().topic : '';
|
||||
},
|
||||
|
||||
|
@ -38,15 +38,15 @@ module.exports = React.createClass({
|
|||
},
|
||||
|
||||
render: function() {
|
||||
var EditableText = sdk.getComponent("elements.EditableText");
|
||||
const EditableText = sdk.getComponent("elements.EditableText");
|
||||
|
||||
return (
|
||||
<EditableText ref="editor"
|
||||
className="mx_RoomHeader_topic mx_RoomHeader_editable"
|
||||
placeholderClassName="mx_RoomHeader_placeholder"
|
||||
placeholder={_t("Add a topic")}
|
||||
blurToCancel={ false }
|
||||
initialValue={ this._initialTopic }
|
||||
blurToCancel={false}
|
||||
initialValue={this._initialTopic}
|
||||
dir="auto" />
|
||||
);
|
||||
},
|
||||
|
|
|
@ -16,8 +16,8 @@ limitations under the License.
|
|||
|
||||
'use strict';
|
||||
|
||||
var React = require('react');
|
||||
var sdk = require('../../../index');
|
||||
const React = require('react');
|
||||
const sdk = require('../../../index');
|
||||
|
||||
module.exports = React.createClass({
|
||||
displayName: 'SearchResult',
|
||||
|
@ -36,20 +36,20 @@ module.exports = React.createClass({
|
|||
},
|
||||
|
||||
render: function() {
|
||||
var DateSeparator = sdk.getComponent('messages.DateSeparator');
|
||||
var EventTile = sdk.getComponent('rooms.EventTile');
|
||||
var result = this.props.searchResult;
|
||||
var mxEv = result.context.getEvent();
|
||||
var eventId = mxEv.getId();
|
||||
const DateSeparator = sdk.getComponent('messages.DateSeparator');
|
||||
const EventTile = sdk.getComponent('rooms.EventTile');
|
||||
const result = this.props.searchResult;
|
||||
const mxEv = result.context.getEvent();
|
||||
const eventId = mxEv.getId();
|
||||
|
||||
var ts1 = mxEv.getTs();
|
||||
var ret = [<DateSeparator key={ts1 + "-search"} ts={ts1}/>];
|
||||
const ts1 = mxEv.getTs();
|
||||
const ret = [<DateSeparator key={ts1 + "-search"} ts={ts1} />];
|
||||
|
||||
var timeline = result.context.getTimeline();
|
||||
const timeline = result.context.getTimeline();
|
||||
for (var j = 0; j < timeline.length; j++) {
|
||||
var ev = timeline[j];
|
||||
const ev = timeline[j];
|
||||
var highlights;
|
||||
var contextual = (j != result.context.getOurEventIndex());
|
||||
const contextual = (j != result.context.getOurEventIndex());
|
||||
if (!contextual) {
|
||||
highlights = this.props.searchHighlights;
|
||||
}
|
||||
|
@ -61,7 +61,7 @@ module.exports = React.createClass({
|
|||
}
|
||||
return (
|
||||
<li data-scroll-tokens={eventId+"+"+j}>
|
||||
{ret}
|
||||
{ ret }
|
||||
</li>);
|
||||
},
|
||||
});
|
||||
|
|
|
@ -13,16 +13,16 @@ 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 MatrixClientPeg = require("../../../MatrixClientPeg");
|
||||
var Modal = require("../../../Modal");
|
||||
var sdk = require("../../../index");
|
||||
const React = require('react');
|
||||
const MatrixClientPeg = require("../../../MatrixClientPeg");
|
||||
const Modal = require("../../../Modal");
|
||||
const sdk = require("../../../index");
|
||||
import { _t } from '../../../languageHandler';
|
||||
var GeminiScrollbar = require('react-gemini-scrollbar');
|
||||
const GeminiScrollbar = require('react-gemini-scrollbar');
|
||||
|
||||
// A list capable of displaying entities which conform to the SearchableEntity
|
||||
// interface which is an object containing getJsx(): Jsx and matches(query: string): boolean
|
||||
var SearchableEntityList = React.createClass({
|
||||
const SearchableEntityList = React.createClass({
|
||||
displayName: 'SearchableEntityList',
|
||||
|
||||
propTypes: {
|
||||
|
@ -31,7 +31,7 @@ var SearchableEntityList = React.createClass({
|
|||
onQueryChanged: React.PropTypes.func, // fn(inputText)
|
||||
onSubmit: React.PropTypes.func, // fn(inputText)
|
||||
entities: React.PropTypes.array,
|
||||
truncateAt: React.PropTypes.number
|
||||
truncateAt: React.PropTypes.number,
|
||||
},
|
||||
|
||||
getDefaultProps: function() {
|
||||
|
@ -40,7 +40,7 @@ var SearchableEntityList = React.createClass({
|
|||
entities: [],
|
||||
emptyQueryShowsAll: false,
|
||||
onSubmit: function() {},
|
||||
onQueryChanged: function(input) {}
|
||||
onQueryChanged: function(input) {},
|
||||
};
|
||||
},
|
||||
|
||||
|
@ -49,14 +49,14 @@ var SearchableEntityList = React.createClass({
|
|||
query: "",
|
||||
focused: false,
|
||||
truncateAt: this.props.truncateAt,
|
||||
results: this.getSearchResults("", this.props.entities)
|
||||
results: this.getSearchResults("", this.props.entities),
|
||||
};
|
||||
},
|
||||
|
||||
componentWillReceiveProps: function(newProps) {
|
||||
// recalculate the search results in case we got new entities
|
||||
this.setState({
|
||||
results: this.getSearchResults(this.state.query, newProps.entities)
|
||||
results: this.getSearchResults(this.state.query, newProps.entities),
|
||||
});
|
||||
},
|
||||
|
||||
|
@ -73,17 +73,17 @@ var SearchableEntityList = React.createClass({
|
|||
setQuery: function(input) {
|
||||
this.setState({
|
||||
query: input,
|
||||
results: this.getSearchResults(input, this.props.entities)
|
||||
results: this.getSearchResults(input, this.props.entities),
|
||||
});
|
||||
},
|
||||
|
||||
onQueryChanged: function(ev) {
|
||||
var q = ev.target.value;
|
||||
const q = ev.target.value;
|
||||
this.setState({
|
||||
query: q,
|
||||
// reset truncation if they back out the entire text
|
||||
truncateAt: (q.length === 0 ? this.props.truncateAt : this.state.truncateAt),
|
||||
results: this.getSearchResults(q, this.props.entities)
|
||||
results: this.getSearchResults(q, this.props.entities),
|
||||
}, () => {
|
||||
// invoke the callback AFTER we've flushed the new state. We need to
|
||||
// do this because onQueryChanged can result in new props being passed
|
||||
|
@ -110,13 +110,13 @@ var SearchableEntityList = React.createClass({
|
|||
|
||||
_showAll: function() {
|
||||
this.setState({
|
||||
truncateAt: -1
|
||||
truncateAt: -1,
|
||||
});
|
||||
},
|
||||
|
||||
_createOverflowEntity: function(overflowCount, totalCount) {
|
||||
var EntityTile = sdk.getComponent("rooms.EntityTile");
|
||||
var BaseAvatar = sdk.getComponent("avatars.BaseAvatar");
|
||||
const EntityTile = sdk.getComponent("rooms.EntityTile");
|
||||
const BaseAvatar = sdk.getComponent("avatars.BaseAvatar");
|
||||
const text = _t("and %(count)s others...", { count: overflowCount });
|
||||
return (
|
||||
<EntityTile className="mx_EntityTile_ellipsis" avatarJsx={
|
||||
|
@ -127,7 +127,7 @@ var SearchableEntityList = React.createClass({
|
|||
},
|
||||
|
||||
render: function() {
|
||||
var inputBox;
|
||||
let inputBox;
|
||||
|
||||
if (this.props.showInputBox) {
|
||||
inputBox = (
|
||||
|
@ -136,31 +136,30 @@ var SearchableEntityList = React.createClass({
|
|||
onChange={this.onQueryChanged} value={this.state.query}
|
||||
onFocus= {() => { this.setState({ focused: true }); }}
|
||||
onBlur= {() => { this.setState({ focused: false }); }}
|
||||
placeholder={ _t("Search") } />
|
||||
placeholder={_t("Search")} />
|
||||
</form>
|
||||
);
|
||||
}
|
||||
|
||||
var list;
|
||||
let list;
|
||||
if (this.state.results.length > 1 || this.state.focused) {
|
||||
if (this.props.truncateAt) { // caller wants list truncated
|
||||
var TruncatedList = sdk.getComponent("elements.TruncatedList");
|
||||
const TruncatedList = sdk.getComponent("elements.TruncatedList");
|
||||
list = (
|
||||
<TruncatedList className="mx_SearchableEntityList_list"
|
||||
truncateAt={this.state.truncateAt} // use state truncation as it may be expanded
|
||||
createOverflowElement={this._createOverflowEntity}>
|
||||
{this.state.results.map((entity) => {
|
||||
{ this.state.results.map((entity) => {
|
||||
return entity.getJsx();
|
||||
})}
|
||||
}) }
|
||||
</TruncatedList>
|
||||
);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
list = (
|
||||
<div className="mx_SearchableEntityList_list">
|
||||
{this.state.results.map((entity) => {
|
||||
{ this.state.results.map((entity) => {
|
||||
return entity.getJsx();
|
||||
})}
|
||||
}) }
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -173,13 +172,13 @@ var SearchableEntityList = React.createClass({
|
|||
}
|
||||
|
||||
return (
|
||||
<div className={ "mx_SearchableEntityList " + (list ? "mx_SearchableEntityList_expanded" : "") }>
|
||||
<div className={"mx_SearchableEntityList " + (list ? "mx_SearchableEntityList_expanded" : "")}>
|
||||
{ inputBox }
|
||||
{ list }
|
||||
{ list ? <div className="mx_SearchableEntityList_hrWrapper"><hr/></div> : '' }
|
||||
{ list ? <div className="mx_SearchableEntityList_hrWrapper"><hr /></div> : '' }
|
||||
</div>
|
||||
);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
module.exports = SearchableEntityList;
|
||||
|
|
|
@ -17,9 +17,9 @@ limitations under the License.
|
|||
|
||||
'use strict';
|
||||
|
||||
var React = require('react');
|
||||
const React = require('react');
|
||||
import { _t } from '../../../languageHandler';
|
||||
var sdk = require('../../../index');
|
||||
const sdk = require('../../../index');
|
||||
|
||||
module.exports = React.createClass({
|
||||
displayName: 'TopUnreadMessagesBar',
|
||||
|
@ -35,8 +35,8 @@ module.exports = React.createClass({
|
|||
<div className="mx_TopUnreadMessagesBar_scrollUp"
|
||||
onClick={this.props.onScrollUpClick}>
|
||||
<img src="img/scrollto.svg" width="24" height="24"
|
||||
alt={ _t('Scroll to unread messages') }
|
||||
title={ _t('Scroll to unread messages') }/>
|
||||
alt={_t('Scroll to unread messages')}
|
||||
title={_t('Scroll to unread messages')} />
|
||||
{ _t("Jump to first unread message.") }
|
||||
</div>
|
||||
<img className="mx_TopUnreadMessagesBar_close mx_filterFlipColor"
|
||||
|
|
|
@ -16,41 +16,41 @@ limitations under the License.
|
|||
|
||||
'use strict';
|
||||
|
||||
var React = require('react');
|
||||
const React = require('react');
|
||||
|
||||
var Avatar = require("../../../Avatar");
|
||||
var MatrixClientPeg = require('../../../MatrixClientPeg');
|
||||
var sdk = require('../../../index');
|
||||
var dis = require('../../../dispatcher');
|
||||
var Modal = require("../../../Modal");
|
||||
const Avatar = require("../../../Avatar");
|
||||
const MatrixClientPeg = require('../../../MatrixClientPeg');
|
||||
const sdk = require('../../../index');
|
||||
const dis = require('../../../dispatcher');
|
||||
const Modal = require("../../../Modal");
|
||||
|
||||
module.exports = React.createClass({
|
||||
displayName: 'UserTile',
|
||||
|
||||
propTypes: {
|
||||
user: React.PropTypes.any.isRequired // User
|
||||
user: React.PropTypes.any.isRequired, // User
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var EntityTile = sdk.getComponent("rooms.EntityTile");
|
||||
var user = this.props.user;
|
||||
var name = user.displayName || user.userId;
|
||||
var active = -1;
|
||||
const EntityTile = sdk.getComponent("rooms.EntityTile");
|
||||
const user = this.props.user;
|
||||
const name = user.displayName || user.userId;
|
||||
let active = -1;
|
||||
|
||||
// FIXME: make presence data update whenever User.presence changes...
|
||||
active = user.lastActiveAgo ?
|
||||
(Date.now() - (user.lastPresenceTs - user.lastActiveAgo)) : -1;
|
||||
|
||||
var BaseAvatar = sdk.getComponent('avatars.BaseAvatar');
|
||||
var avatarJsx = (
|
||||
const BaseAvatar = sdk.getComponent('avatars.BaseAvatar');
|
||||
const avatarJsx = (
|
||||
<BaseAvatar width={36} height={36} name={name} idName={user.userId}
|
||||
url={ Avatar.avatarUrlForUser(user, 36, 36, "crop") } />
|
||||
url={Avatar.avatarUrlForUser(user, 36, 36, "crop")} />
|
||||
);
|
||||
|
||||
return (
|
||||
<EntityTile {...this.props} presenceState={user.presence} presenceActiveAgo={active}
|
||||
presenceCurrentlyActive={ user.currentlyActive }
|
||||
presenceCurrentlyActive={user.currentlyActive}
|
||||
name={name} title={user.userId} avatarJsx={avatarJsx} />
|
||||
);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
|
|
@ -81,7 +81,7 @@ export default withMatrixClient(React.createClass({
|
|||
this._promptForMsisdnVerificationCode(resp.msisdn);
|
||||
}).catch((err) => {
|
||||
console.error("Unable to add phone number: " + err);
|
||||
let msg = err.message;
|
||||
const msg = err.message;
|
||||
Modal.createTrackedDialog('Add Phone Number Error', '', ErrorDialog, {
|
||||
title: _t("Error"),
|
||||
description: msg,
|
||||
|
@ -94,22 +94,22 @@ export default withMatrixClient(React.createClass({
|
|||
this.setState({msisdn_add_pending: true});
|
||||
},
|
||||
|
||||
_promptForMsisdnVerificationCode:function (msisdn, err) {
|
||||
_promptForMsisdnVerificationCode: function(msisdn, err) {
|
||||
if (this._unmounted) return;
|
||||
const TextInputDialog = sdk.getComponent("dialogs.TextInputDialog");
|
||||
let msgElements = [
|
||||
<div key="_static" >{ _t("A text message has been sent to +%(msisdn)s. Please enter the verification code it contains", { msisdn: msisdn} ) }</div>
|
||||
const msgElements = [
|
||||
<div key="_static" >{ _t("A text message has been sent to +%(msisdn)s. Please enter the verification code it contains", { msisdn: msisdn} ) }</div>,
|
||||
];
|
||||
if (err) {
|
||||
let msg = err.error;
|
||||
if (err.errcode == 'M_THREEPID_AUTH_FAILED') {
|
||||
msg = _t("Incorrect verification code");
|
||||
}
|
||||
msgElements.push(<div key="_error" className="error">{msg}</div>);
|
||||
msgElements.push(<div key="_error" className="error">{ msg }</div>);
|
||||
}
|
||||
Modal.createTrackedDialog('Prompt for MSISDN Verification Code', '', TextInputDialog, {
|
||||
title: _t("Enter Code"),
|
||||
description: <div>{msgElements}</div>,
|
||||
description: <div>{ msgElements }</div>,
|
||||
button: _t("Submit"),
|
||||
onFinished: (should_verify, token) => {
|
||||
if (!should_verify) {
|
||||
|
@ -128,7 +128,7 @@ export default withMatrixClient(React.createClass({
|
|||
if (this._unmounted) return;
|
||||
this.setState({msisdn_add_pending: false});
|
||||
}).done();
|
||||
}
|
||||
},
|
||||
});
|
||||
},
|
||||
|
||||
|
@ -146,7 +146,7 @@ export default withMatrixClient(React.createClass({
|
|||
return (
|
||||
<form className="mx_UserSettings_profileTableRow" onSubmit={this._onAddMsisdnSubmit}>
|
||||
<div className="mx_UserSettings_profileLabelCell">
|
||||
<label>{_t('Phone')}</label>
|
||||
<label>{ _t('Phone') }</label>
|
||||
</div>
|
||||
<div className="mx_UserSettings_profileInputCell">
|
||||
<div className="mx_UserSettings_phoneSection">
|
||||
|
@ -158,7 +158,7 @@ export default withMatrixClient(React.createClass({
|
|||
<input type="text"
|
||||
ref={this._collectAddMsisdnInput}
|
||||
className="mx_UserSettings_phoneNumberField"
|
||||
placeholder={ _t('Add phone number') }
|
||||
placeholder={_t('Add phone number')}
|
||||
value={this.state.phoneNumber}
|
||||
onChange={this._onPhoneNumberChange}
|
||||
/>
|
||||
|
@ -169,5 +169,5 @@ export default withMatrixClient(React.createClass({
|
|||
</div>
|
||||
</form>
|
||||
);
|
||||
}
|
||||
}))
|
||||
},
|
||||
}));
|
||||
|
|
|
@ -14,9 +14,9 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
var React = require('react');
|
||||
var MatrixClientPeg = require("../../../MatrixClientPeg");
|
||||
var sdk = require('../../../index');
|
||||
const React = require('react');
|
||||
const MatrixClientPeg = require("../../../MatrixClientPeg");
|
||||
const sdk = require('../../../index');
|
||||
import { _t } from '../../../languageHandler';
|
||||
|
||||
module.exports = React.createClass({
|
||||
|
@ -28,7 +28,7 @@ module.exports = React.createClass({
|
|||
showUploadSection: React.PropTypes.bool,
|
||||
width: React.PropTypes.number,
|
||||
height: React.PropTypes.number,
|
||||
className: React.PropTypes.string
|
||||
className: React.PropTypes.string,
|
||||
},
|
||||
|
||||
Phases: {
|
||||
|
@ -53,31 +53,57 @@ module.exports = React.createClass({
|
|||
};
|
||||
},
|
||||
|
||||
componentWillMount: function() {
|
||||
MatrixClientPeg.get().on("RoomState.events", this.onRoomStateEvents);
|
||||
},
|
||||
|
||||
componentWillReceiveProps: function(newProps) {
|
||||
if (this.avatarSet) {
|
||||
// don't clobber what the user has just set
|
||||
return;
|
||||
}
|
||||
this.setState({
|
||||
avatarUrl: newProps.initialAvatarUrl
|
||||
avatarUrl: newProps.initialAvatarUrl,
|
||||
});
|
||||
},
|
||||
|
||||
componentWillUnmount: function() {
|
||||
if (MatrixClientPeg.get()) {
|
||||
MatrixClientPeg.get().removeListener("RoomState.events", this.onRoomStateEvents);
|
||||
}
|
||||
},
|
||||
|
||||
onRoomStateEvents: function(ev) {
|
||||
if (!this.props.room) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (ev.getRoomId() !== this.props.room.roomId || ev.getType() !== 'm.room.avatar'
|
||||
|| ev.getSender() !== MatrixClientPeg.get().getUserId()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ev.getContent().url) {
|
||||
this.avatarSet = false;
|
||||
this.setState({}); // force update
|
||||
}
|
||||
},
|
||||
|
||||
setAvatarFromFile: function(file) {
|
||||
var newUrl = null;
|
||||
let newUrl = null;
|
||||
|
||||
this.setState({
|
||||
phase: this.Phases.Uploading
|
||||
phase: this.Phases.Uploading,
|
||||
});
|
||||
var self = this;
|
||||
var httpPromise = MatrixClientPeg.get().uploadContent(file).then(function(url) {
|
||||
const self = this;
|
||||
const httpPromise = MatrixClientPeg.get().uploadContent(file).then(function(url) {
|
||||
newUrl = url;
|
||||
if (self.props.room) {
|
||||
return MatrixClientPeg.get().sendStateEvent(
|
||||
self.props.room.roomId,
|
||||
'm.room.avatar',
|
||||
{url: url},
|
||||
''
|
||||
'',
|
||||
);
|
||||
} else {
|
||||
return MatrixClientPeg.get().setAvatarUrl(url);
|
||||
|
@ -87,11 +113,11 @@ module.exports = React.createClass({
|
|||
httpPromise.done(function() {
|
||||
self.setState({
|
||||
phase: self.Phases.Display,
|
||||
avatarUrl: MatrixClientPeg.get().mxcUrlToHttp(newUrl)
|
||||
avatarUrl: MatrixClientPeg.get().mxcUrlToHttp(newUrl),
|
||||
});
|
||||
}, function(error) {
|
||||
self.setState({
|
||||
phase: self.Phases.Error
|
||||
phase: self.Phases.Error,
|
||||
});
|
||||
self.onError(error);
|
||||
});
|
||||
|
@ -106,31 +132,31 @@ module.exports = React.createClass({
|
|||
|
||||
onError: function(error) {
|
||||
this.setState({
|
||||
errorText: _t("Failed to upload profile picture!")
|
||||
errorText: _t("Failed to upload profile picture!"),
|
||||
});
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var avatarImg;
|
||||
let avatarImg;
|
||||
// Having just set an avatar we just display that since it will take a little
|
||||
// time to propagate through to the RoomAvatar.
|
||||
if (this.props.room && !this.avatarSet) {
|
||||
var RoomAvatar = sdk.getComponent('avatars.RoomAvatar');
|
||||
avatarImg = <RoomAvatar room={this.props.room} width={ this.props.width } height={ this.props.height } resizeMethod='crop' />;
|
||||
const RoomAvatar = sdk.getComponent('avatars.RoomAvatar');
|
||||
avatarImg = <RoomAvatar room={this.props.room} width={this.props.width} height={this.props.height} resizeMethod='crop' />;
|
||||
} else {
|
||||
var BaseAvatar = sdk.getComponent("avatars.BaseAvatar");
|
||||
const 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;
|
||||
let uploadSection;
|
||||
if (this.props.showUploadSection) {
|
||||
uploadSection = (
|
||||
<div className={this.props.className}>
|
||||
{_t("Upload new:")}
|
||||
<input type="file" accept="image/*" onChange={this.onFileSelected}/>
|
||||
{this.state.errorText}
|
||||
{ _t("Upload new:") }
|
||||
<input type="file" accept="image/*" onChange={this.onFileSelected} />
|
||||
{ this.state.errorText }
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -141,9 +167,9 @@ module.exports = React.createClass({
|
|||
return (
|
||||
<div>
|
||||
<div className={this.props.className}>
|
||||
{avatarImg}
|
||||
{ avatarImg }
|
||||
</div>
|
||||
{uploadSection}
|
||||
{ uploadSection }
|
||||
</div>
|
||||
);
|
||||
case this.Phases.Uploading:
|
||||
|
@ -152,5 +178,5 @@ module.exports = React.createClass({
|
|||
<Loader />
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
|
|
|
@ -15,23 +15,22 @@ limitations under the License.
|
|||
*/
|
||||
|
||||
'use strict';
|
||||
var React = require('react');
|
||||
var sdk = require('../../../index');
|
||||
var MatrixClientPeg = require("../../../MatrixClientPeg");
|
||||
const React = require('react');
|
||||
const sdk = require('../../../index');
|
||||
const MatrixClientPeg = require("../../../MatrixClientPeg");
|
||||
import { _t } from '../../../languageHandler';
|
||||
|
||||
module.exports = React.createClass({
|
||||
displayName: 'ChangeDisplayName',
|
||||
|
||||
_getDisplayName: function() {
|
||||
var cli = MatrixClientPeg.get();
|
||||
const cli = MatrixClientPeg.get();
|
||||
return cli.getProfileInfo(cli.credentials.userId).then(function(result) {
|
||||
var displayname = result.displayname;
|
||||
let displayname = result.displayname;
|
||||
if (!displayname) {
|
||||
if (MatrixClientPeg.get().isGuest()) {
|
||||
displayname = "Guest " + MatrixClientPeg.get().getUserIdLocalpart();
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
displayname = MatrixClientPeg.get().getUserIdLocalpart();
|
||||
}
|
||||
}
|
||||
|
@ -42,14 +41,14 @@ module.exports = React.createClass({
|
|||
},
|
||||
|
||||
_changeDisplayName: function(new_displayname) {
|
||||
var cli = MatrixClientPeg.get();
|
||||
const cli = MatrixClientPeg.get();
|
||||
return cli.setDisplayName(new_displayname).catch(function(e) {
|
||||
throw new Error("Failed to set display name");
|
||||
});
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var EditableTextContainer = sdk.getComponent('elements.EditableTextContainer');
|
||||
const EditableTextContainer = sdk.getComponent('elements.EditableTextContainer');
|
||||
return (
|
||||
<EditableTextContainer
|
||||
getInitialValue={this._getDisplayName}
|
||||
|
@ -57,5 +56,5 @@ module.exports = React.createClass({
|
|||
blurToSubmit={true}
|
||||
onSubmit={this._changeDisplayName} />
|
||||
);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
|
|
@ -16,10 +16,10 @@ limitations under the License.
|
|||
|
||||
'use strict';
|
||||
|
||||
var React = require('react');
|
||||
var MatrixClientPeg = require("../../../MatrixClientPeg");
|
||||
var Modal = require("../../../Modal");
|
||||
var sdk = require("../../../index");
|
||||
const React = require('react');
|
||||
const MatrixClientPeg = require("../../../MatrixClientPeg");
|
||||
const Modal = require("../../../Modal");
|
||||
const sdk = require("../../../index");
|
||||
|
||||
import Promise from 'bluebird';
|
||||
import AccessibleButton from '../elements/AccessibleButton';
|
||||
|
@ -45,7 +45,7 @@ module.exports = React.createClass({
|
|||
Phases: {
|
||||
Edit: "edit",
|
||||
Uploading: "uploading",
|
||||
Error: "error"
|
||||
Error: "error",
|
||||
},
|
||||
|
||||
getDefaultProps: function() {
|
||||
|
@ -55,11 +55,11 @@ module.exports = React.createClass({
|
|||
onCheckPassword: function(oldPass, newPass, confirmPass) {
|
||||
if (newPass !== confirmPass) {
|
||||
return {
|
||||
error: _t("New passwords don't match")
|
||||
error: _t("New passwords don't match"),
|
||||
};
|
||||
} else if (!newPass || newPass.length === 0) {
|
||||
return {
|
||||
error: _t("Passwords can't be empty")
|
||||
error: _t("Passwords can't be empty"),
|
||||
};
|
||||
}
|
||||
},
|
||||
|
@ -112,7 +112,7 @@ module.exports = React.createClass({
|
|||
'Changing password will currently reset any end-to-end encryption keys on all devices, ' +
|
||||
'making encrypted chat history unreadable, unless you first export your room keys ' +
|
||||
'and re-import them afterwards. ' +
|
||||
'In future this will be improved.'
|
||||
'In future this will be improved.',
|
||||
) } (<a href="https://github.com/vector-im/riot-web/issues/2671">https://github.com/vector-im/riot-web/issues/2671</a>)
|
||||
</div>,
|
||||
button: _t("Continue"),
|
||||
|
@ -120,7 +120,7 @@ module.exports = React.createClass({
|
|||
<button className="mx_Dialog_primary"
|
||||
onClick={this._onExportE2eKeysClicked}>
|
||||
{ _t('Export E2E room keys') }
|
||||
</button>
|
||||
</button>,
|
||||
],
|
||||
onFinished: (confirmed) => {
|
||||
if (confirmed) {
|
||||
|
@ -254,5 +254,5 @@ module.exports = React.createClass({
|
|||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
|
|
|
@ -52,7 +52,7 @@ export default class DevicesPanel extends React.Component {
|
|||
},
|
||||
(error) => {
|
||||
if (this._unmounted) { return; }
|
||||
var errtxt;
|
||||
let errtxt;
|
||||
if (error.httpStatus == 404) {
|
||||
// 404 probably means the HS doesn't yet support the API.
|
||||
errtxt = _t("Your home server does not support device management.");
|
||||
|
@ -61,7 +61,7 @@ export default class DevicesPanel extends React.Component {
|
|||
errtxt = _t("Unable to load device list");
|
||||
}
|
||||
this.setState({deviceLoadError: errtxt});
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -89,14 +89,14 @@ 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 };
|
||||
});
|
||||
}
|
||||
|
||||
_renderDevice(device) {
|
||||
var DevicesPanelEntry = sdk.getComponent('settings.DevicesPanelEntry');
|
||||
const DevicesPanelEntry = sdk.getComponent('settings.DevicesPanelEntry');
|
||||
return (
|
||||
<DevicesPanelEntry key={device.device_id} device={device}
|
||||
onDeleted={()=>{this._onDeviceDeleted(device);}} />
|
||||
|
@ -110,7 +110,7 @@ export default class DevicesPanel extends React.Component {
|
|||
const classes = classNames(this.props.className, "error");
|
||||
return (
|
||||
<div className={classes}>
|
||||
{this.state.deviceLoadError}
|
||||
{ this.state.deviceLoadError }
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -119,7 +119,7 @@ export default class DevicesPanel extends React.Component {
|
|||
if (devices === undefined) {
|
||||
// still loading
|
||||
const classes = this.props.className;
|
||||
return <Spinner className={classes}/>;
|
||||
return <Spinner className={classes} />;
|
||||
}
|
||||
|
||||
devices.sort(this._deviceCompare);
|
||||
|
@ -128,12 +128,12 @@ export default class DevicesPanel extends React.Component {
|
|||
return (
|
||||
<div className={classes}>
|
||||
<div className="mx_DevicesPanel_header">
|
||||
<div className="mx_DevicesPanel_deviceId">{_t("Device ID")}</div>
|
||||
<div className="mx_DevicesPanel_deviceName">{_t("Device Name")}</div>
|
||||
<div className="mx_DevicesPanel_deviceLastSeen">{_t("Last seen")}</div>
|
||||
<div className="mx_DevicesPanel_deviceId">{ _t("Device ID") }</div>
|
||||
<div className="mx_DevicesPanel_deviceName">{ _t("Device Name") }</div>
|
||||
<div className="mx_DevicesPanel_deviceLastSeen">{ _t("Last seen") }</div>
|
||||
<div className="mx_DevicesPanel_deviceButtons"></div>
|
||||
</div>
|
||||
{devices.map(this._renderDevice)}
|
||||
{ devices.map(this._renderDevice) }
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -69,7 +69,7 @@ export default class DevicesPanelEntry extends React.Component {
|
|||
}
|
||||
|
||||
// pop up an interactive auth dialog
|
||||
var InteractiveAuthDialog = sdk.getComponent("dialogs.InteractiveAuthDialog");
|
||||
const InteractiveAuthDialog = sdk.getComponent("dialogs.InteractiveAuthDialog");
|
||||
|
||||
Modal.createTrackedDialog('Delete Device Dialog', '', InteractiveAuthDialog, {
|
||||
title: _t("Authentication"),
|
||||
|
@ -101,7 +101,7 @@ export default class DevicesPanelEntry extends React.Component {
|
|||
this.props.onDeleted();
|
||||
if (this._unmounted) { return; }
|
||||
this.setState({ deleting: false });
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -129,7 +129,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"
|
||||
|
@ -139,15 +139,15 @@ export default class DevicesPanelEntry extends React.Component {
|
|||
);
|
||||
}
|
||||
|
||||
var myDeviceClass = '';
|
||||
let myDeviceClass = '';
|
||||
if (device.device_id === MatrixClientPeg.get().getDeviceId()) {
|
||||
myDeviceClass = " mx_DevicesPanel_myDevice";
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={ "mx_DevicesPanel_device" + myDeviceClass }>
|
||||
<div className={"mx_DevicesPanel_device" + myDeviceClass}>
|
||||
<div className="mx_DevicesPanel_deviceId">
|
||||
{device.device_id}
|
||||
{ device.device_id }
|
||||
</div>
|
||||
<div className="mx_DevicesPanel_deviceName">
|
||||
<EditableTextContainer initialValue={device.display_name}
|
||||
|
@ -156,10 +156,10 @@ export default class DevicesPanelEntry extends React.Component {
|
|||
/>
|
||||
</div>
|
||||
<div className="mx_DevicesPanel_lastSeen">
|
||||
{lastSeen}
|
||||
{ lastSeen }
|
||||
</div>
|
||||
<div className="mx_DevicesPanel_deviceButtons">
|
||||
{deleteButton}
|
||||
{ deleteButton }
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -15,9 +15,9 @@ limitations under the License.
|
|||
*/
|
||||
|
||||
'use strict';
|
||||
var React = require("react");
|
||||
var Notifier = require("../../../Notifier");
|
||||
var dis = require("../../../dispatcher");
|
||||
const React = require("react");
|
||||
const Notifier = require("../../../Notifier");
|
||||
const dis = require("../../../dispatcher");
|
||||
import { _t } from '../../../languageHandler';
|
||||
|
||||
module.exports = React.createClass({
|
||||
|
@ -43,7 +43,7 @@ module.exports = React.createClass({
|
|||
},
|
||||
|
||||
onClick: function() {
|
||||
var self = this;
|
||||
const self = this;
|
||||
if (!Notifier.supportsDesktopNotifications()) {
|
||||
return;
|
||||
}
|
||||
|
@ -61,15 +61,15 @@ module.exports = React.createClass({
|
|||
if (this.enabled()) {
|
||||
return (
|
||||
<button className="mx_EnableNotificationsButton" onClick={this.onClick}>
|
||||
{_t("Disable Notifications")}
|
||||
{ _t("Disable Notifications") }
|
||||
</button>
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<button className="mx_EnableNotificationsButton" onClick={this.onClick}>
|
||||
{_t("Enable Notifications")}
|
||||
{ _t("Enable Notifications") }
|
||||
</button>
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue