Fix merge-conflict

Signed-off-by: Stefan Parviainen <pafcu@iki.fi>
This commit is contained in:
Stefan Parviainen 2017-10-11 20:02:14 +02:00
commit f694fb24ff
169 changed files with 2857 additions and 2914 deletions

View file

@ -17,9 +17,9 @@ limitations under the License.
'use strict';
var classNames = require('classnames');
var React = require('react');
var ReactDOM = require('react-dom');
const classNames = require('classnames');
const React = require('react');
const ReactDOM = require('react-dom');
// Shamelessly ripped off Modal.js. There's probably a better way
// of doing reusable widgets like dialog boxes & menus where we go and
@ -36,7 +36,7 @@ module.exports = {
},
getOrCreateContainer: function() {
var container = document.getElementById(this.ContextualMenuContainerId);
let container = document.getElementById(this.ContextualMenuContainerId);
if (!container) {
container = document.createElement("div");
@ -48,9 +48,9 @@ module.exports = {
},
createMenu: function(Element, props) {
var self = this;
const self = this;
var closeMenu = function() {
const closeMenu = function() {
ReactDOM.unmountComponentAtNode(self.getOrCreateContainer());
if (props && props.onFinished) {
@ -58,17 +58,17 @@ module.exports = {
}
};
var position = {
const position = {
top: props.top,
};
var chevronOffset = {};
const chevronOffset = {};
if (props.chevronOffset) {
chevronOffset.top = props.chevronOffset;
}
// To override the default chevron colour, if it's been set
var chevronCSS = "";
let chevronCSS = "";
if (props.menuColour) {
chevronCSS = `
.mx_ContextualMenu_chevron_left:after {
@ -81,7 +81,7 @@ module.exports = {
`;
}
var chevron = null;
let chevron = null;
if (props.left) {
chevron = <div style={chevronOffset} className="mx_ContextualMenu_chevron_left"></div>;
position.left = props.left;
@ -90,15 +90,15 @@ module.exports = {
position.right = props.right;
}
var className = 'mx_ContextualMenu_wrapper';
const className = 'mx_ContextualMenu_wrapper';
var menuClasses = classNames({
const menuClasses = classNames({
'mx_ContextualMenu': true,
'mx_ContextualMenu_left': props.left,
'mx_ContextualMenu_right': !props.left,
});
var menuStyle = {};
const menuStyle = {};
if (props.menuWidth) {
menuStyle.width = props.menuWidth;
}
@ -113,14 +113,14 @@ module.exports = {
// FIXME: If a menu uses getDefaultProps it clobbers the onFinished
// property set here so you can't close the menu from a button click!
var menu = (
const menu = (
<div className={className} style={position}>
<div className={menuClasses} style={menuStyle}>
{chevron}
<Element {...props} onFinished={closeMenu}/>
{ chevron }
<Element {...props} onFinished={closeMenu} />
</div>
<div className="mx_ContextualMenu_background" onClick={closeMenu}></div>
<style>{chevronCSS}</style>
<style>{ chevronCSS }</style>
</div>
);

View file

@ -61,7 +61,7 @@ module.exports = React.createClass({
},
onCreateRoom: function() {
var options = {};
const options = {};
if (this.state.room_name) {
options.name = this.state.room_name;
@ -79,14 +79,14 @@ module.exports = React.createClass({
{
type: "m.room.join_rules",
content: {
"join_rule": this.state.is_private ? "invite" : "public"
}
"join_rule": this.state.is_private ? "invite" : "public",
},
},
{
type: "m.room.history_visibility",
content: {
"history_visibility": this.state.share_history ? "shared" : "invited"
}
"history_visibility": this.state.share_history ? "shared" : "invited",
},
},
];
}
@ -94,19 +94,19 @@ module.exports = React.createClass({
options.invite = this.state.invited_users;
var alias = this.getAliasLocalpart();
const alias = this.getAliasLocalpart();
if (alias) {
options.room_alias_name = alias;
}
var cli = MatrixClientPeg.get();
const cli = MatrixClientPeg.get();
if (!cli) {
// TODO: Error.
console.error("Cannot create room: No matrix client.");
return;
}
var deferred = cli.createRoom(options);
const deferred = cli.createRoom(options);
if (this.state.encrypt) {
// TODO
@ -116,7 +116,7 @@ module.exports = React.createClass({
phase: this.phases.CREATING,
});
var self = this;
const self = this;
deferred.then(function(resp) {
self.setState({
@ -209,7 +209,7 @@ module.exports = React.createClass({
onAliasChanged: function(alias) {
this.setState({
alias: alias
alias: alias,
});
},
@ -220,64 +220,64 @@ module.exports = React.createClass({
},
render: function() {
var curr_phase = this.state.phase;
const curr_phase = this.state.phase;
if (curr_phase == this.phases.CREATING) {
var Loader = sdk.getComponent("elements.Spinner");
const Loader = sdk.getComponent("elements.Spinner");
return (
<Loader/>
<Loader />
);
} else {
var error_box = "";
let error_box = "";
if (curr_phase == this.phases.ERROR) {
error_box = (
<div className="mx_Error">
{_t('An error occurred: %(error_string)s', {error_string: this.state.error_string})}
{ _t('An error occurred: %(error_string)s', {error_string: this.state.error_string}) }
</div>
);
}
var CreateRoomButton = sdk.getComponent("create_room.CreateRoomButton");
var RoomAlias = sdk.getComponent("create_room.RoomAlias");
var Presets = sdk.getComponent("create_room.Presets");
var UserSelector = sdk.getComponent("elements.UserSelector");
var SimpleRoomHeader = sdk.getComponent("rooms.SimpleRoomHeader");
const CreateRoomButton = sdk.getComponent("create_room.CreateRoomButton");
const RoomAlias = sdk.getComponent("create_room.RoomAlias");
const Presets = sdk.getComponent("create_room.Presets");
const UserSelector = sdk.getComponent("elements.UserSelector");
const SimpleRoomHeader = sdk.getComponent("rooms.SimpleRoomHeader");
var domain = MatrixClientPeg.get().getDomain();
const domain = MatrixClientPeg.get().getDomain();
return (
<div className="mx_CreateRoom">
<SimpleRoomHeader title={_t("Create Room")} collapsedRhs={ this.props.collapsedRhs }/>
<SimpleRoomHeader title={_t("Create Room")} collapsedRhs={this.props.collapsedRhs} />
<div className="mx_CreateRoom_body">
<input type="text" ref="room_name" value={this.state.room_name} onChange={this.onNameChange} placeholder={_t('Name')}/> <br />
<textarea className="mx_CreateRoom_description" ref="topic" value={this.state.topic} onChange={this.onTopicChange} placeholder={_t('Topic')}/> <br />
<RoomAlias ref="alias" alias={this.state.alias} homeserver={ domain } onChange={this.onAliasChanged}/> <br />
<UserSelector ref="user_selector" selected_users={this.state.invited_users} onChange={this.onInviteChanged}/> <br />
<Presets ref="presets" onChange={this.onPresetChanged} preset={this.state.preset}/> <br />
<input type="text" ref="room_name" value={this.state.room_name} onChange={this.onNameChange} placeholder={_t('Name')} /> <br />
<textarea className="mx_CreateRoom_description" ref="topic" value={this.state.topic} onChange={this.onTopicChange} placeholder={_t('Topic')} /> <br />
<RoomAlias ref="alias" alias={this.state.alias} homeserver={domain} onChange={this.onAliasChanged} /> <br />
<UserSelector ref="user_selector" selected_users={this.state.invited_users} onChange={this.onInviteChanged} /> <br />
<Presets ref="presets" onChange={this.onPresetChanged} preset={this.state.preset} /> <br />
<div>
<label>
<input type="checkbox" ref="is_private" checked={this.state.is_private} onChange={this.onPrivateChanged}/>
{_t('Make this room private')}
<input type="checkbox" ref="is_private" checked={this.state.is_private} onChange={this.onPrivateChanged} />
{ _t('Make this room private') }
</label>
</div>
<div>
<label>
<input type="checkbox" ref="share_history" checked={this.state.share_history} onChange={this.onShareHistoryChanged}/>
{_t('Share message history with new users')}
<input type="checkbox" ref="share_history" checked={this.state.share_history} onChange={this.onShareHistoryChanged} />
{ _t('Share message history with new users') }
</label>
</div>
<div className="mx_CreateRoom_encrypt">
<label>
<input type="checkbox" ref="encrypt" checked={this.state.encrypt} onChange={this.onEncryptChanged}/>
{_t('Encrypt room')}
<input type="checkbox" ref="encrypt" checked={this.state.encrypt} onChange={this.onEncryptChanged} />
{ _t('Encrypt room') }
</label>
</div>
<div>
<CreateRoomButton onCreateRoom={this.onCreateRoom} /> <br />
</div>
{error_box}
{ error_box }
</div>
</div>
);
}
}
},
});

View file

@ -24,7 +24,7 @@ import { _t, _tJsx } from '../../languageHandler';
/*
* Component which shows the filtered file using a TimelinePanel
*/
var FilePanel = React.createClass({
const FilePanel = React.createClass({
displayName: 'FilePanel',
propTypes: {
@ -55,33 +55,33 @@ var FilePanel = React.createClass({
},
updateTimelineSet: function(roomId) {
var client = MatrixClientPeg.get();
var room = client.getRoom(roomId);
const client = MatrixClientPeg.get();
const room = client.getRoom(roomId);
this.noRoom = !room;
if (room) {
var filter = new Matrix.Filter(client.credentials.userId);
const filter = new Matrix.Filter(client.credentials.userId);
filter.setDefinition(
{
"room": {
"timeline": {
"contains_url": true
"contains_url": true,
},
}
}
},
},
);
// FIXME: we shouldn't be doing this every time we change room - see comment above.
client.getOrCreateFilter("FILTER_FILES_" + client.credentials.userId, filter).then(
(filterId)=>{
filter.filterId = filterId;
var timelineSet = room.getOrCreateFilteredTimelineSet(filter);
const timelineSet = room.getOrCreateFilteredTimelineSet(filter);
this.setState({ timelineSet: timelineSet });
},
(error)=>{
console.error("Failed to get or create file panel filter", error);
}
},
);
} else {
console.error("Failed to add filtered timelineSet for FilePanel as no room!");
@ -92,18 +92,18 @@ var FilePanel = React.createClass({
if (MatrixClientPeg.get().isGuest()) {
return <div className="mx_FilePanel mx_RoomView_messageListWrapper">
<div className="mx_RoomView_empty">
{_tJsx("You must <a>register</a> to use this functionality", /<a>(.*?)<\/a>/, (sub) => <a href="#/register" key="sub">{sub}</a>)}
{ _tJsx("You must <a>register</a> to use this functionality", /<a>(.*?)<\/a>/, (sub) => <a href="#/register" key="sub">{ sub }</a>) }
</div>
</div>;
} else if (this.noRoom) {
return <div className="mx_FilePanel mx_RoomView_messageListWrapper">
<div className="mx_RoomView_empty">{_t("You must join the room to see its files")}</div>
<div className="mx_RoomView_empty">{ _t("You must join the room to see its files") }</div>
</div>;
}
// wrap a TimelinePanel with the jump-to-event bits turned off.
var TimelinePanel = sdk.getComponent("structures.TimelinePanel");
var Loader = sdk.getComponent("elements.Spinner");
const TimelinePanel = sdk.getComponent("structures.TimelinePanel");
const Loader = sdk.getComponent("elements.Spinner");
if (this.state.timelineSet) {
// console.log("rendering TimelinePanel for timelineSet " + this.state.timelineSet.room.roomId + " " +
@ -114,17 +114,16 @@ var FilePanel = React.createClass({
manageReadReceipts={false}
manageReadMarkers={false}
timelineSet={this.state.timelineSet}
showUrlPreview = { false }
showUrlPreview = {false}
tileShape="file_grid"
opacity={ this.props.opacity }
opacity={this.props.opacity}
empty={_t('There are no visible files in this room')}
/>
);
}
else {
} else {
return (
<div className="mx_FilePanel">
<Loader/>
<Loader />
</div>
);
}

View file

@ -107,7 +107,7 @@ export default React.createClass({
const msg = error.message || error.toString();
this.setState({
errorText: msg
errorText: msg,
});
}).done();
@ -207,7 +207,7 @@ export default React.createClass({
if (this.state.errorText) {
error = (
<div className="error">
{this.state.errorText}
{ this.state.errorText }
</div>
);
}
@ -215,8 +215,8 @@ export default React.createClass({
return (
<div>
<div>
{this._renderCurrentStage()}
{error}
{ this._renderCurrentStage() }
{ error }
</div>
</div>
);

View file

@ -164,7 +164,7 @@ export default React.createClass({
case KeyCode.UP:
case KeyCode.DOWN:
if (ev.altKey && !ev.shiftKey && !ev.ctrlKey && !ev.metaKey) {
let action = ev.keyCode == KeyCode.UP ?
const action = ev.keyCode == KeyCode.UP ?
'view_prev_room' : 'view_next_room';
dis.dispatch({action: action});
handled = true;
@ -206,8 +206,7 @@ export default React.createClass({
_onScrollKeyPressed: function(ev) {
if (this.refs.roomView) {
this.refs.roomView.handleScrollKey(ev);
}
else if (this.refs.roomDirectory) {
} else if (this.refs.roomDirectory) {
this.refs.roomDirectory.handleScrollKey(ev);
}
},
@ -255,7 +254,7 @@ export default React.createClass({
referralBaseUrl={this.props.config.referralBaseUrl}
teamToken={this.props.teamToken}
/>;
if (!this.props.collapseRhs) right_panel = <RightPanel opacity={this.props.rightOpacity}/>;
if (!this.props.collapseRhs) right_panel = <RightPanel opacity={this.props.rightOpacity} />;
break;
case PageTypes.MyGroups:
@ -267,7 +266,7 @@ export default React.createClass({
onRoomCreated={this.props.onRoomCreated}
collapsedRhs={this.props.collapseRhs}
/>;
if (!this.props.collapseRhs) right_panel = <RightPanel opacity={this.props.rightOpacity}/>;
if (!this.props.collapseRhs) right_panel = <RightPanel opacity={this.props.rightOpacity} />;
break;
case PageTypes.RoomDirectory:
@ -320,7 +319,7 @@ export default React.createClass({
topBar = <MatrixToolbar />;
}
var bodyClasses = 'mx_MatrixChat';
let bodyClasses = 'mx_MatrixChat';
if (topBar) {
bodyClasses += ' mx_MatrixChat_toolbarShowing';
}
@ -330,7 +329,7 @@ export default React.createClass({
return (
<div className='mx_MatrixChat_wrapper'>
{topBar}
{ topBar }
<div className={bodyClasses}>
<LeftPanel
selectedRoom={this.props.currentRoomId}
@ -338,9 +337,9 @@ export default React.createClass({
opacity={this.props.leftOpacity}
/>
<main className='mx_MatrixChat_middlePanel'>
{page_element}
{ page_element }
</main>
{right_panel}
{ right_panel }
</div>
</div>
);

View file

@ -773,15 +773,13 @@ module.exports = React.createClass({
dis.dispatch({action: 'view_set_mxid'});
return;
}
const TextInputDialog = sdk.getComponent("dialogs.TextInputDialog");
Modal.createTrackedDialog('Create Room', '', TextInputDialog, {
title: _t('Create Room'),
description: _t('Room name (optional)'),
button: _t('Create Room'),
onFinished: (shouldCreate, name) => {
const CreateRoomDialog = sdk.getComponent('dialogs.CreateRoomDialog');
Modal.createTrackedDialog('Create Room', '', CreateRoomDialog, {
onFinished: (shouldCreate, name, noFederate) => {
if (shouldCreate) {
const createOpts = {};
if (name) createOpts.name = name;
if (noFederate) createOpts.creation_content = {'m.federate': false};
createRoom({createOpts}).done();
}
},

View file

@ -154,15 +154,15 @@ module.exports = React.createClass({
// 0: read marker is within the window
// +1: read marker is below the window
getReadMarkerPosition: function() {
var readMarker = this.refs.readMarkerNode;
var messageWrapper = this.refs.scrollPanel;
const readMarker = this.refs.readMarkerNode;
const messageWrapper = this.refs.scrollPanel;
if (!readMarker || !messageWrapper) {
return null;
}
var wrapperRect = ReactDOM.findDOMNode(messageWrapper).getBoundingClientRect();
var readMarkerRect = readMarker.getBoundingClientRect();
const wrapperRect = ReactDOM.findDOMNode(messageWrapper).getBoundingClientRect();
const readMarkerRect = readMarker.getBoundingClientRect();
// the read-marker pretends to have zero height when it is actually
// two pixels high; +2 here to account for that.
@ -262,7 +262,7 @@ module.exports = React.createClass({
this.eventNodes = {};
var i;
let i;
// first figure out which is the last event in the list which we're
// actually going to show; this allows us to behave slightly
@ -272,9 +272,9 @@ module.exports = React.createClass({
// a local echo, to manage the read-marker.
let lastShownEvent;
var lastShownNonLocalEchoIndex = -1;
let lastShownNonLocalEchoIndex = -1;
for (i = this.props.events.length-1; i >= 0; i--) {
var mxEv = this.props.events[i];
const mxEv = this.props.events[i];
if (!this._shouldShowEvent(mxEv)) {
continue;
}
@ -292,12 +292,12 @@ module.exports = React.createClass({
break;
}
var ret = [];
const ret = [];
var prevEvent = null; // the last event we showed
let prevEvent = null; // the last event we showed
// assume there is no read marker until proven otherwise
var readMarkerVisible = false;
let readMarkerVisible = false;
// if the readmarker has moved, cancel any active ghost.
if (this.currentReadMarkerEventId && this.props.readMarkerEventId &&
@ -309,16 +309,16 @@ module.exports = React.createClass({
const isMembershipChange = (e) => e.getType() === 'm.room.member';
for (i = 0; i < this.props.events.length; i++) {
let mxEv = this.props.events[i];
let eventId = mxEv.getId();
let last = (mxEv === lastShownEvent);
const mxEv = this.props.events[i];
const eventId = mxEv.getId();
const last = (mxEv === lastShownEvent);
const wantTile = this._shouldShowEvent(mxEv);
// Wrap consecutive member events in a ListSummary, ignore if redacted
if (isMembershipChange(mxEv) && wantTile) {
let readMarkerInMels = false;
let ts1 = mxEv.getTs();
const ts1 = mxEv.getTs();
// Ensure that the key of the MemberEventListSummary does not change with new
// member events. This will prevent it from being re-created unnecessarily, and
// instead will allow new props to be provided. In turn, the shouldComponentUpdate
@ -330,7 +330,7 @@ module.exports = React.createClass({
const key = "membereventlistsummary-" + (prevEvent ? mxEv.getId() : "initial");
if (this._wantsDateSeparator(prevEvent, mxEv.getDate())) {
let dateSeparator = <li key={ts1+'~'}><DateSeparator key={ts1+'~'} ts={ts1} showTwelveHour={this.props.isTwelveHour}/></li>;
const dateSeparator = <li key={ts1+'~'}><DateSeparator key={ts1+'~'} ts={ts1} showTwelveHour={this.props.isTwelveHour} /></li>;
ret.push(dateSeparator);
}
@ -339,7 +339,7 @@ module.exports = React.createClass({
readMarkerInMels = true;
}
let summarisedEvents = [mxEv];
const summarisedEvents = [mxEv];
for (;i + 1 < this.props.events.length; i++) {
const collapsedMxEv = this.props.events[i + 1];
@ -390,7 +390,7 @@ module.exports = React.createClass({
onToggle={this._onWidgetLoad} // Update scroll state
startExpanded={highlightInMels}
>
{eventTiles}
{ eventTiles }
</MemberEventListSummary>);
if (readMarkerInMels) {
@ -408,7 +408,7 @@ module.exports = React.createClass({
prevEvent = mxEv;
}
var isVisibleReadMarker = false;
let isVisibleReadMarker = false;
if (eventId == this.props.readMarkerEventId) {
var visible = this.props.readMarkerVisible;
@ -448,10 +448,10 @@ module.exports = React.createClass({
_getTilesForEvent: function(prevEvent, mxEv, last) {
const EventTile = sdk.getComponent('rooms.EventTile');
const DateSeparator = sdk.getComponent('messages.DateSeparator');
var ret = [];
const ret = [];
// is this a continuation of the previous message?
var continuation = false;
let continuation = false;
if (prevEvent !== null
&& prevEvent.sender && mxEv.sender
@ -476,8 +476,8 @@ module.exports = React.createClass({
// local echoes have a fake date, which could even be yesterday. Treat them
// as 'today' for the date separators.
var ts1 = mxEv.getTs();
var eventDate = mxEv.getDate();
let ts1 = mxEv.getTs();
let eventDate = mxEv.getDate();
if (mxEv.status) {
eventDate = new Date();
ts1 = eventDate.getTime();
@ -485,19 +485,19 @@ module.exports = React.createClass({
// do we need a date separator since the last event?
if (this._wantsDateSeparator(prevEvent, eventDate)) {
var dateSeparator = <li key={ts1}><DateSeparator key={ts1} ts={ts1} showTwelveHour={this.props.isTwelveHour}/></li>;
const dateSeparator = <li key={ts1}><DateSeparator key={ts1} ts={ts1} showTwelveHour={this.props.isTwelveHour} /></li>;
ret.push(dateSeparator);
continuation = false;
}
var eventId = mxEv.getId();
var highlight = (eventId == this.props.highlightedEventId);
const eventId = mxEv.getId();
const highlight = (eventId == this.props.highlightedEventId);
// we can't use local echoes as scroll tokens, because their event IDs change.
// Local echos have a send "status".
var scrollToken = mxEv.status ? undefined : eventId;
const scrollToken = mxEv.status ? undefined : eventId;
var readReceipts;
let readReceipts;
if (this.props.showReadReceipts) {
readReceipts = this._getReadReceiptsForEvent(mxEv);
}
@ -515,8 +515,8 @@ module.exports = React.createClass({
eventSendStatus={mxEv.status}
tileShape={this.props.tileShape}
isTwelveHour={this.props.isTwelveHour}
last={last} isSelectedEvent={highlight}/>
</li>
last={last} isSelectedEvent={highlight} />
</li>,
);
return ret;
@ -551,7 +551,7 @@ module.exports = React.createClass({
if (!room) {
return null;
}
let receipts = [];
const receipts = [];
room.getReceiptsForEvent(event).forEach((r) => {
if (!r.userId || r.type !== "m.read" || r.userId === myUserId) {
return; // ignore non-read receipts and receipts from self.
@ -559,7 +559,7 @@ module.exports = React.createClass({
if (MatrixClientPeg.get().isUserIgnored(r.userId)) {
return; // ignore ignored users
}
let member = room.getMember(r.userId);
const member = room.getMember(r.userId);
if (!member) {
return; // ignore unknown user IDs
}
@ -575,7 +575,7 @@ module.exports = React.createClass({
},
_getReadMarkerTile: function(visible) {
var hr;
let hr;
if (visible) {
hr = <hr className="mx_RoomView_myReadMarker"
style={{opacity: 1, width: '99%'}}
@ -585,7 +585,7 @@ module.exports = React.createClass({
return (
<li key="_readupto" ref="readMarkerNode"
className="mx_RoomView_myReadMarker_container">
{hr}
{ hr }
</li>
);
},
@ -604,7 +604,7 @@ module.exports = React.createClass({
},
_getReadMarkerGhostTile: function() {
var hr = <hr className="mx_RoomView_myReadMarker"
const hr = <hr className="mx_RoomView_myReadMarker"
style={{opacity: 1, width: '99%'}}
ref={this._startAnimation}
/>;
@ -615,7 +615,7 @@ module.exports = React.createClass({
return (
<li key={"_readuptoghost_"+this.currentGhostEventId}
className="mx_RoomView_myReadMarker_container">
{hr}
{ hr }
</li>
);
},
@ -627,7 +627,7 @@ module.exports = React.createClass({
// once dynamic content in the events load, make the scrollPanel check the
// scroll offsets.
_onWidgetLoad: function() {
var scrollPanel = this.refs.scrollPanel;
const scrollPanel = this.refs.scrollPanel;
if (scrollPanel) {
scrollPanel.forceUpdate();
}
@ -638,9 +638,9 @@ module.exports = React.createClass({
},
render: function() {
var ScrollPanel = sdk.getComponent("structures.ScrollPanel");
var Spinner = sdk.getComponent("elements.Spinner");
var topSpinner, bottomSpinner;
const ScrollPanel = sdk.getComponent("structures.ScrollPanel");
const Spinner = sdk.getComponent("elements.Spinner");
let topSpinner, bottomSpinner;
if (this.props.backPaginating) {
topSpinner = <li key="_topSpinner"><Spinner /></li>;
}
@ -648,25 +648,25 @@ module.exports = React.createClass({
bottomSpinner = <li key="_bottomSpinner"><Spinner /></li>;
}
var style = this.props.hidden ? { display: 'none' } : {};
const style = this.props.hidden ? { display: 'none' } : {};
style.opacity = this.props.opacity;
var className = this.props.className + " mx_fadable";
let className = this.props.className + " mx_fadable";
if (this.props.alwaysShowTimestamps) {
className += " mx_MessagePanel_alwaysShowTimestamps";
}
return (
<ScrollPanel ref="scrollPanel" className={ className }
onScroll={ this.props.onScroll }
onResize={ this.onResize }
onFillRequest={ this.props.onFillRequest }
onUnfillRequest={ this.props.onUnfillRequest }
style={ style }
stickyBottom={ this.props.stickyBottom }>
{topSpinner}
{this._getEventTiles()}
{bottomSpinner}
<ScrollPanel ref="scrollPanel" className={className}
onScroll={this.props.onScroll}
onResize={this.onResize}
onFillRequest={this.props.onFillRequest}
onUnfillRequest={this.props.onUnfillRequest}
style={style}
stickyBottom={this.props.stickyBottom}>
{ topSpinner }
{ this._getEventTiles() }
{ bottomSpinner }
</ScrollPanel>
);
},

View file

@ -14,18 +14,18 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
var React = require('react');
var ReactDOM = require("react-dom");
const React = require('react');
const ReactDOM = require("react-dom");
import { _t } from '../../languageHandler';
var Matrix = require("matrix-js-sdk");
var sdk = require('../../index');
var MatrixClientPeg = require("../../MatrixClientPeg");
var dis = require("../../dispatcher");
const Matrix = require("matrix-js-sdk");
const sdk = require('../../index');
const MatrixClientPeg = require("../../MatrixClientPeg");
const dis = require("../../dispatcher");
/*
* Component which shows the global notification list using a TimelinePanel
*/
var NotificationPanel = React.createClass({
const NotificationPanel = React.createClass({
displayName: 'NotificationPanel',
propTypes: {
@ -33,10 +33,10 @@ var NotificationPanel = React.createClass({
render: function() {
// wrap a TimelinePanel with the jump-to-event bits turned off.
var TimelinePanel = sdk.getComponent("structures.TimelinePanel");
var Loader = sdk.getComponent("elements.Spinner");
const TimelinePanel = sdk.getComponent("structures.TimelinePanel");
const Loader = sdk.getComponent("elements.Spinner");
var timelineSet = MatrixClientPeg.get().getNotifTimelineSet();
const timelineSet = MatrixClientPeg.get().getNotifTimelineSet();
if (timelineSet) {
return (
<TimelinePanel key={"NotificationPanel_" + this.props.roomId}
@ -44,18 +44,17 @@ var NotificationPanel = React.createClass({
manageReadReceipts={false}
manageReadMarkers={false}
timelineSet={timelineSet}
showUrlPreview = { false }
opacity={ this.props.opacity }
showUrlPreview = {false}
opacity={this.props.opacity}
tileShape="notif"
empty={ _t('You have no visible notifications') }
empty={_t('You have no visible notifications')}
/>
);
}
else {
} else {
console.error("No notifTimelineSet available!");
return (
<div className="mx_NotificationPanel">
<Loader/>
<Loader />
</div>
);
}

View file

@ -103,7 +103,7 @@ module.exports = React.createClass({
componentWillUnmount: function() {
// we may have entirely lost our client as we're logging out before clicking login on the guest bar...
var client = MatrixClientPeg.get();
const client = MatrixClientPeg.get();
if (client) {
client.removeListener("sync", this.onSyncStateChange);
client.removeListener("RoomMember.typing", this.onRoomMemberTyping);
@ -115,7 +115,7 @@ module.exports = React.createClass({
return;
}
this.setState({
syncState: state
syncState: state,
});
},
@ -126,7 +126,7 @@ module.exports = React.createClass({
},
// Check whether current size is greater than 0, if yes call props.onVisible
_checkSize: function () {
_checkSize: function() {
if (this.props.onVisible && this._getSize()) {
this.props.onVisible();
}
@ -157,9 +157,9 @@ module.exports = React.createClass({
if (this.props.numUnreadMessages) {
return (
<div className="mx_RoomStatusBar_scrollDownIndicator"
onClick={ this.props.onScrollToBottomClick }>
onClick={this.props.onScrollToBottomClick}>
<img src="img/newmessages.svg" width="24" height="24"
alt=""/>
alt="" />
</div>
);
}
@ -167,18 +167,18 @@ module.exports = React.createClass({
if (!this.props.atEndOfLiveTimeline) {
return (
<div className="mx_RoomStatusBar_scrollDownIndicator"
onClick={ this.props.onScrollToBottomClick }>
onClick={this.props.onScrollToBottomClick}>
<img src="img/scrolldown.svg" width="24" height="24"
alt={ _t("Scroll to bottom of page") }
title={ _t("Scroll to bottom of page") }/>
alt={_t("Scroll to bottom of page")}
title={_t("Scroll to bottom of page")} />
</div>
);
}
if (this.props.hasActiveCall) {
var TintableSvg = sdk.getComponent("elements.TintableSvg");
const TintableSvg = sdk.getComponent("elements.TintableSvg");
return (
<TintableSvg src="img/sound-indicator.svg" width="23" height="20"/>
<TintableSvg src="img/sound-indicator.svg" width="23" height="20" />
);
}
@ -189,7 +189,7 @@ module.exports = React.createClass({
if (wantPlaceholder) {
return (
<div className="mx_RoomStatusBar_typingIndicatorAvatars">
{this._renderTypingIndicatorAvatars(this.props.whoIsTypingLimit)}
{ this._renderTypingIndicatorAvatars(this.props.whoIsTypingLimit) }
</div>
);
}
@ -221,8 +221,8 @@ module.exports = React.createClass({
if (othersCount > 0) {
avatars.push(
<span className="mx_RoomStatusBar_typingIndicatorRemaining" key="others">
+{othersCount}
</span>
+{ othersCount }
</span>,
);
}
@ -240,12 +240,12 @@ module.exports = React.createClass({
if (this.state.syncState === "ERROR") {
return (
<div className="mx_RoomStatusBar_connectionLostBar">
<img src="img/warning.svg" width="24" height="23" title="/!\ " alt="/!\ "/>
<img src="img/warning.svg" width="24" height="23" title="/!\ " alt="/!\ " />
<div className="mx_RoomStatusBar_connectionLostBar_title">
{_t('Connectivity to the server has been lost.')}
{ _t('Connectivity to the server has been lost.') }
</div>
<div className="mx_RoomStatusBar_connectionLostBar_desc">
{_t('Sent messages will be stored until your connection has returned.')}
{ _t('Sent messages will be stored until your connection has returned.') }
</div>
</div>
);
@ -254,18 +254,18 @@ module.exports = React.createClass({
if (this.props.unsentMessageError) {
return (
<div className="mx_RoomStatusBar_connectionLostBar">
<img src="img/warning.svg" width="24" height="23" title="/!\ " alt="/!\ "/>
<img src="img/warning.svg" width="24" height="23" title="/!\ " alt="/!\ " />
<div className="mx_RoomStatusBar_connectionLostBar_title">
{ this.props.unsentMessageError }
</div>
<div className="mx_RoomStatusBar_connectionLostBar_desc">
{_tJsx("<a>Resend all</a> or <a>cancel all</a> now. You can also select individual messages to resend or cancel.",
{ _tJsx("<a>Resend all</a> or <a>cancel all</a> now. You can also select individual messages to resend or cancel.",
[/<a>(.*?)<\/a>/, /<a>(.*?)<\/a>/],
[
(sub) => <a className="mx_RoomStatusBar_resend_link" key="resend" onClick={ this.props.onResendAllClick }>{sub}</a>,
(sub) => <a className="mx_RoomStatusBar_resend_link" key="cancel" onClick={ this.props.onCancelAllClick }>{sub}</a>,
]
)}
(sub) => <a className="mx_RoomStatusBar_resend_link" key="resend" onClick={this.props.onResendAllClick}>{ sub }</a>,
(sub) => <a className="mx_RoomStatusBar_resend_link" key="cancel" onClick={this.props.onCancelAllClick}>{ sub }</a>,
],
) }
</div>
</div>
);
@ -275,24 +275,24 @@ module.exports = React.createClass({
// set when you've scrolled up
if (this.props.numUnreadMessages) {
// MUST use var name "count" for pluralization to kick in
var unreadMsgs = _t("%(count)s new messages", {count: this.props.numUnreadMessages});
const unreadMsgs = _t("%(count)s new messages", {count: this.props.numUnreadMessages});
return (
<div className="mx_RoomStatusBar_unreadMessagesBar"
onClick={ this.props.onScrollToBottomClick }>
{unreadMsgs}
onClick={this.props.onScrollToBottomClick}>
{ unreadMsgs }
</div>
);
}
const typingString = WhoIsTyping.whoIsTypingString(
this.state.usersTyping,
this.props.whoIsTypingLimit
this.props.whoIsTypingLimit,
);
if (typingString) {
return (
<div className="mx_RoomStatusBar_typingBar">
<EmojiText>{typingString}</EmojiText>
<EmojiText>{ typingString }</EmojiText>
</div>
);
}
@ -300,7 +300,7 @@ module.exports = React.createClass({
if (this.props.hasActiveCall) {
return (
<div className="mx_RoomStatusBar_callBar">
<b>{_t('Active call')}</b>
<b>{ _t('Active call') }</b>
</div>
);
}
@ -310,15 +310,15 @@ module.exports = React.createClass({
render: function() {
var content = this._getContent();
var indicator = this._getIndicator(this.state.usersTyping.length > 0);
const content = this._getContent();
const indicator = this._getIndicator(this.state.usersTyping.length > 0);
return (
<div className="mx_RoomStatusBar">
<div className="mx_RoomStatusBar_indicator">
{indicator}
{ indicator }
</div>
{content}
{ content }
</div>
);
},

View file

@ -22,25 +22,25 @@ limitations under the License.
import shouldHideEvent from "../../shouldHideEvent";
var React = require("react");
var ReactDOM = require("react-dom");
const React = require("react");
const ReactDOM = require("react-dom");
import Promise from 'bluebird';
var classNames = require("classnames");
var Matrix = require("matrix-js-sdk");
const classNames = require("classnames");
const Matrix = require("matrix-js-sdk");
import { _t } from '../../languageHandler';
var UserSettingsStore = require('../../UserSettingsStore');
var MatrixClientPeg = require("../../MatrixClientPeg");
var ContentMessages = require("../../ContentMessages");
var Modal = require("../../Modal");
var sdk = require('../../index');
var CallHandler = require('../../CallHandler');
var Resend = require("../../Resend");
var dis = require("../../dispatcher");
var Tinter = require("../../Tinter");
var rate_limited_func = require('../../ratelimitedfunc');
var ObjectUtils = require('../../ObjectUtils');
var Rooms = require('../../Rooms');
const UserSettingsStore = require('../../UserSettingsStore');
const MatrixClientPeg = require("../../MatrixClientPeg");
const ContentMessages = require("../../ContentMessages");
const Modal = require("../../Modal");
const sdk = require('../../index');
const CallHandler = require('../../CallHandler');
const Resend = require("../../Resend");
const dis = require("../../dispatcher");
const Tinter = require("../../Tinter");
const rate_limited_func = require('../../ratelimitedfunc');
const ObjectUtils = require('../../ObjectUtils');
const Rooms = require('../../Rooms');
import KeyCode from '../../KeyCode';
@ -49,7 +49,7 @@ import UserProvider from '../../autocomplete/UserProvider';
import RoomViewStore from '../../stores/RoomViewStore';
import RoomScrollStateStore from '../../stores/RoomScrollStateStore';
let DEBUG = false;
const DEBUG = false;
let debuglog = function() {};
const BROWSER_SUPPORTS_SANDBOX = 'sandbox' in document.createElement('iframe');
@ -307,10 +307,10 @@ module.exports = React.createClass({
},
componentDidMount: function() {
var call = this._getCallForRoom();
var callState = call ? call.call_state : "ended";
const call = this._getCallForRoom();
const callState = call ? call.call_state : "ended";
this.setState({
callState: callState
callState: callState,
});
this._updateConfCallNotification();
@ -327,9 +327,8 @@ module.exports = React.createClass({
this.state.room.getJoinedMembers().length == 1 &&
this.state.room.getLiveTimeline() &&
this.state.room.getLiveTimeline().getEvents() &&
this.state.room.getLiveTimeline().getEvents().length <= 6)
{
var inviteBox = document.getElementById("mx_SearchableEntityList_query");
this.state.room.getLiveTimeline().getEvents().length <= 6) {
const inviteBox = document.getElementById("mx_SearchableEntityList_query");
setTimeout(function() {
if (inviteBox) {
inviteBox.focus();
@ -345,7 +344,7 @@ module.exports = React.createClass({
componentDidUpdate: function() {
if (this.refs.roomView) {
var roomView = ReactDOM.findDOMNode(this.refs.roomView);
const roomView = ReactDOM.findDOMNode(this.refs.roomView);
if (!roomView.ondrop) {
roomView.addEventListener('drop', this.onDrop);
roomView.addEventListener('dragover', this.onDragOver);
@ -372,7 +371,7 @@ module.exports = React.createClass({
// is really just for hygiene - we're going to be
// deleted anyway, so it doesn't matter if the event listeners
// don't get cleaned up.
var roomView = ReactDOM.findDOMNode(this.refs.roomView);
const roomView = ReactDOM.findDOMNode(this.refs.roomView);
roomView.removeEventListener('drop', this.onDrop);
roomView.removeEventListener('dragover', this.onDragOver);
roomView.removeEventListener('dragleave', this.onDragLeaveOrEnd);
@ -478,8 +477,7 @@ module.exports = React.createClass({
if (call) {
callState = call.call_state;
}
else {
} else {
callState = "ended";
}
@ -591,17 +589,17 @@ module.exports = React.createClass({
},
_calculatePeekRules: function(room) {
var guestAccessEvent = room.currentState.getStateEvents("m.room.guest_access", "");
const guestAccessEvent = room.currentState.getStateEvents("m.room.guest_access", "");
if (guestAccessEvent && guestAccessEvent.getContent().guest_access === "can_join") {
this.setState({
guestsCanJoin: true
guestsCanJoin: true,
});
}
var historyVisibility = room.currentState.getStateEvents("m.room.history_visibility", "");
const historyVisibility = room.currentState.getStateEvents("m.room.history_visibility", "");
if (historyVisibility && historyVisibility.getContent().history_visibility === "world_readable") {
this.setState({
canPeek: true
canPeek: true,
});
}
},
@ -610,35 +608,35 @@ module.exports = React.createClass({
// console.log("_updatePreviewUrlVisibility");
// check our per-room overrides
var roomPreviewUrls = room.getAccountData("org.matrix.room.preview_urls");
const roomPreviewUrls = room.getAccountData("org.matrix.room.preview_urls");
if (roomPreviewUrls && roomPreviewUrls.getContent().disable !== undefined) {
this.setState({
showUrlPreview: !roomPreviewUrls.getContent().disable
showUrlPreview: !roomPreviewUrls.getContent().disable,
});
return;
}
// check our global disable override
var userRoomPreviewUrls = MatrixClientPeg.get().getAccountData("org.matrix.preview_urls");
const userRoomPreviewUrls = MatrixClientPeg.get().getAccountData("org.matrix.preview_urls");
if (userRoomPreviewUrls && userRoomPreviewUrls.getContent().disable) {
this.setState({
showUrlPreview: false
showUrlPreview: false,
});
return;
}
// check the room state event
var roomStatePreviewUrls = room.currentState.getStateEvents('org.matrix.room.preview_urls', '');
const roomStatePreviewUrls = room.currentState.getStateEvents('org.matrix.room.preview_urls', '');
if (roomStatePreviewUrls && roomStatePreviewUrls.getContent().disable) {
this.setState({
showUrlPreview: false
showUrlPreview: false,
});
return;
}
// otherwise, we assume they're on.
this.setState({
showUrlPreview: true
showUrlPreview: true,
});
},
@ -654,11 +652,11 @@ module.exports = React.createClass({
},
updateTint: function() {
var room = this.state.room;
const room = this.state.room;
if (!room) return;
var color_scheme_event = room.getAccountData("org.matrix.room.color_scheme");
var color_scheme = {};
const color_scheme_event = room.getAccountData("org.matrix.room.color_scheme");
let color_scheme = {};
if (color_scheme_event) {
color_scheme = color_scheme_event.getContent();
// XXX: we should validate the event
@ -676,12 +674,11 @@ module.exports = React.createClass({
onRoomAccountData: function(event, room) {
if (room.roomId == this.state.roomId) {
if (event.getType() === "org.matrix.room.color_scheme") {
var color_scheme = event.getContent();
const color_scheme = event.getContent();
// XXX: we should validate the event
console.log("Tinter.tint from onRoomAccountData");
Tinter.tint(color_scheme.primary_color, color_scheme.secondary_color);
}
else if (event.getType() === "org.matrix.room.preview_urls") {
} else if (event.getType() === "org.matrix.room.preview_urls") {
this._updatePreviewUrlVisibility(room);
}
}
@ -720,7 +717,7 @@ module.exports = React.createClass({
// if we are now a member of the room, where we were not before, that
// means we have finished joining a room we were previously peeking
// into.
var me = MatrixClientPeg.get().credentials.userId;
const me = MatrixClientPeg.get().credentials.userId;
if (this.state.joining && this.state.room.hasMembershipState(me, "join")) {
// Having just joined a room, check to see if it looks like a DM room, and if so,
// mark it as one. This is to work around the fact that some clients don't support
@ -754,18 +751,18 @@ module.exports = React.createClass({
},
_updateConfCallNotification: function() {
var room = this.state.room;
const room = this.state.room;
if (!room || !this.props.ConferenceHandler) {
return;
}
var confMember = room.getMember(
this.props.ConferenceHandler.getConferenceUserIdForRoom(room.roomId)
const confMember = room.getMember(
this.props.ConferenceHandler.getConferenceUserIdForRoom(room.roomId),
);
if (!confMember) {
return;
}
var confCall = this.props.ConferenceHandler.getConferenceCallForRoom(confMember.roomId);
const confCall = this.props.ConferenceHandler.getConferenceCallForRoom(confMember.roomId);
// A conf call notification should be displayed if there is an ongoing
// conf call but this cilent isn't a part of it.
@ -773,7 +770,7 @@ module.exports = React.createClass({
displayConfCallNotification: (
(!confCall || confCall.call_state === "ended") &&
confMember.membership === "join"
)
),
});
},
@ -788,7 +785,7 @@ module.exports = React.createClass({
if (this.state.searchResults.next_batch) {
debuglog("requesting more search results");
var searchPromise = MatrixClientPeg.get().backPaginateRoomEventsSearch(
const searchPromise = MatrixClientPeg.get().backPaginateRoomEventsSearch(
this.state.searchResults);
return this._handleSearchResult(searchPromise);
} else {
@ -883,8 +880,7 @@ module.exports = React.createClass({
numUnreadMessages: 0,
atEndOfLiveTimeline: true,
});
}
else {
} else {
this.setState({
atEndOfLiveTimeline: false,
});
@ -898,10 +894,10 @@ module.exports = React.createClass({
ev.dataTransfer.dropEffect = 'none';
var items = ev.dataTransfer.items;
const items = ev.dataTransfer.items;
if (items.length == 1) {
if (items[0].kind == 'file') {
this.setState({ draggingFile : true });
this.setState({ draggingFile: true });
ev.dataTransfer.dropEffect = 'copy';
}
}
@ -910,8 +906,8 @@ module.exports = React.createClass({
onDrop: function(ev) {
ev.stopPropagation();
ev.preventDefault();
this.setState({ draggingFile : false });
var files = ev.dataTransfer.files;
this.setState({ draggingFile: false });
const files = ev.dataTransfer.files;
if (files.length == 1) {
this.uploadFile(files[0]);
}
@ -920,7 +916,7 @@ module.exports = React.createClass({
onDragLeaveOrEnd: function(ev) {
ev.stopPropagation();
ev.preventDefault();
this.setState({ draggingFile : false });
this.setState({ draggingFile: false });
},
uploadFile: function(file) {
@ -930,7 +926,7 @@ module.exports = React.createClass({
}
ContentMessages.sendContentToRoom(
file, this.state.room.roomId, MatrixClientPeg.get()
file, this.state.room.roomId, MatrixClientPeg.get(),
).done(undefined, (error) => {
if (error.name === "UnknownDeviceError") {
dis.dispatch({
@ -969,19 +965,19 @@ module.exports = React.createClass({
// todo: should cancel any previous search requests.
this.searchId = new Date().getTime();
var filter;
let filter;
if (scope === "Room") {
filter = {
// XXX: it's unintuitive that the filter for searching doesn't have the same shape as the v2 filter API :(
rooms: [
this.state.room.roomId
]
this.state.room.roomId,
],
};
}
debuglog("sending search request");
var searchPromise = MatrixClientPeg.get().searchRoomEvents({
const searchPromise = MatrixClientPeg.get().searchRoomEvents({
filter: filter,
term: term,
});
@ -989,11 +985,11 @@ module.exports = React.createClass({
},
_handleSearchResult: function(searchPromise) {
var self = this;
const self = this;
// keep a record of the current search id, so that if the search terms
// change before we get a response, we can ignore the results.
var localSearchId = this.searchId;
const localSearchId = this.searchId;
this.setState({
searchInProgress: true,
@ -1012,7 +1008,7 @@ module.exports = React.createClass({
// In either case, we want to highlight the literal search term
// whether it was used by the search engine or not.
var highlights = results.highlights;
let highlights = results.highlights;
if (highlights.indexOf(self.state.searchTerm) < 0) {
highlights = highlights.concat(self.state.searchTerm);
}
@ -1020,14 +1016,15 @@ module.exports = React.createClass({
// For overlapping highlights,
// favour longer (more specific) terms first
highlights = highlights.sort(function(a, b) {
return b.length - a.length; });
return b.length - a.length;
});
self.setState({
searchHighlights: highlights,
searchResults: results,
});
}, function(error) {
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
console.error("Search failed: " + error);
Modal.createTrackedDialog('Search failed', '', ErrorDialog, {
title: _t("Search failed"),
@ -1035,17 +1032,17 @@ module.exports = React.createClass({
});
}).finally(function() {
self.setState({
searchInProgress: false
searchInProgress: false,
});
});
},
getSearchResultTiles: function() {
var EventTile = sdk.getComponent('rooms.EventTile');
var SearchResultTile = sdk.getComponent('rooms.SearchResultTile');
var Spinner = sdk.getComponent("elements.Spinner");
const EventTile = sdk.getComponent('rooms.EventTile');
const SearchResultTile = sdk.getComponent('rooms.SearchResultTile');
const Spinner = sdk.getComponent("elements.Spinner");
var cli = MatrixClientPeg.get();
const cli = MatrixClientPeg.get();
// XXX: todo: merge overlapping results somehow?
// XXX: why doesn't searching on name work?
@ -1055,7 +1052,7 @@ module.exports = React.createClass({
return [];
}
var ret = [];
const ret = [];
if (this.state.searchInProgress) {
ret.push(<li key="search-spinner">
@ -1067,32 +1064,32 @@ module.exports = React.createClass({
if (this.state.searchResults.results.length == 0) {
ret.push(<li key="search-top-marker">
<h2 className="mx_RoomView_topMarker">{ _t("No results") }</h2>
</li>
</li>,
);
} else {
ret.push(<li key="search-top-marker">
<h2 className="mx_RoomView_topMarker">{ _t("No more results") }</h2>
</li>
</li>,
);
}
}
// once dynamic content in the search results load, make the scrollPanel check
// the scroll offsets.
var onWidgetLoad = () => {
var scrollPanel = this.refs.searchResultsPanel;
const onWidgetLoad = () => {
const scrollPanel = this.refs.searchResultsPanel;
if (scrollPanel) {
scrollPanel.checkScroll();
}
};
var lastRoomId;
let lastRoomId;
for (var i = this.state.searchResults.results.length - 1; i >= 0; i--) {
var result = this.state.searchResults.results[i];
for (let i = this.state.searchResults.results.length - 1; i >= 0; i--) {
const result = this.state.searchResults.results[i];
var mxEv = result.context.getEvent();
var roomId = mxEv.getRoomId();
const mxEv = result.context.getEvent();
const roomId = mxEv.getRoomId();
if (!EventTile.haveTileForEvent(mxEv)) {
// XXX: can this ever happen? It will make the result count
@ -1102,13 +1099,13 @@ module.exports = React.createClass({
if (this.state.searchScope === 'All') {
if(roomId != lastRoomId) {
var room = cli.getRoom(roomId);
const room = cli.getRoom(roomId);
// XXX: if we've left the room, we might not know about
// it. We should tell the js sdk to go and find out about
// it. But that's not an issue currently, as synapse only
// returns results for rooms we're joined to.
var roomName = room ? room.name : _t("Unknown room %(roomId)s", { roomId: roomId });
const roomName = room ? room.name : _t("Unknown room %(roomId)s", { roomId: roomId });
ret.push(<li key={mxEv.getId() + "-room"}>
<h1>{ _t("Room") }: { roomName }</h1>
@ -1117,13 +1114,13 @@ module.exports = React.createClass({
}
}
var resultLink = "#/room/"+roomId+"/"+mxEv.getId();
const resultLink = "#/room/"+roomId+"/"+mxEv.getId();
ret.push(<SearchResultTile key={mxEv.getId()}
searchResult={result}
searchHighlights={this.state.searchHighlights}
resultLink={resultLink}
onWidgetLoad={onWidgetLoad}/>);
onWidgetLoad={onWidgetLoad} />);
}
return ret;
},
@ -1139,38 +1136,37 @@ module.exports = React.createClass({
uploadingRoomSettings: true,
});
var newName = this.refs.header.getEditedName();
const newName = this.refs.header.getEditedName();
if (newName !== undefined) {
this.refs.room_settings.setName(newName);
}
var newTopic = this.refs.header.getEditedTopic();
const newTopic = this.refs.header.getEditedTopic();
if (newTopic !== undefined) {
this.refs.room_settings.setTopic(newTopic);
}
this.refs.room_settings.save().then((results) => {
var fails = results.filter(function(result) { return result.state !== "fulfilled"; });
const fails = results.filter(function(result) { return result.state !== "fulfilled"; });
console.log("Settings saved with %s errors", fails.length);
if (fails.length) {
fails.forEach(function(result) {
console.error(result.reason);
});
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
Modal.createTrackedDialog('Failed to save room settings', '', ErrorDialog, {
title: _t("Failed to save settings"),
description: fails.map(function(result) { return result.reason; }).join("\n"),
});
// still editing room settings
}
else {
} else {
this.setState({
editingRoomSettings: false
editingRoomSettings: false,
});
}
}).finally(() => {
this.setState({
uploadingRoomSettings: false,
editingRoomSettings: false
editingRoomSettings: false,
});
}).done();
},
@ -1201,8 +1197,8 @@ module.exports = React.createClass({
MatrixClientPeg.get().forget(this.state.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 }),
@ -1211,20 +1207,20 @@ module.exports = React.createClass({
},
onRejectButtonClicked: function(ev) {
var self = this;
const self = this;
this.setState({
rejecting: true
rejecting: true,
});
MatrixClientPeg.get().leave(this.state.roomId).done(function() {
dis.dispatch({ action: 'view_next_room' });
self.setState({
rejecting: false
rejecting: false,
});
}, function(error) {
console.error("Failed to reject invite: %s", error);
var msg = error.message ? error.message : JSON.stringify(error);
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
const msg = error.message ? error.message : JSON.stringify(error);
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
Modal.createTrackedDialog('Failed to reject invite', '', ErrorDialog, {
title: _t("Failed to reject invite"),
description: msg,
@ -1232,7 +1228,7 @@ module.exports = React.createClass({
self.setState({
rejecting: false,
rejectError: error
rejectError: error,
});
});
},
@ -1292,7 +1288,7 @@ module.exports = React.createClass({
// restored when we switch back to it.
//
_getScrollState: function() {
var messagePanel = this.refs.messagePanel;
const messagePanel = this.refs.messagePanel;
if (!messagePanel) return null;
// if we're following the live timeline, we want to return null; that
@ -1307,7 +1303,7 @@ module.exports = React.createClass({
return null;
}
var scrollState = messagePanel.getScrollState();
const scrollState = messagePanel.getScrollState();
if (scrollState.stuckAtBottom) {
// we don't really expect to be in this state, but it will
@ -1334,7 +1330,7 @@ module.exports = React.createClass({
// a maxHeight on the underlying remote video tag.
// header + footer + status + give us at least 120px of scrollback at all times.
var auxPanelMaxHeight = window.innerHeight -
let auxPanelMaxHeight = window.innerHeight -
(83 + // height of RoomHeader
36 + // height of the status area
72 + // minimum height of the message compmoser
@ -1353,26 +1349,26 @@ module.exports = React.createClass({
onFullscreenClick: function() {
dis.dispatch({
action: 'video_fullscreen',
fullscreen: true
fullscreen: true,
}, true);
},
onMuteAudioClick: function() {
var call = this._getCallForRoom();
const call = this._getCallForRoom();
if (!call) {
return;
}
var newState = !call.isMicrophoneMuted();
const newState = !call.isMicrophoneMuted();
call.setMicrophoneMuted(newState);
this.forceUpdate(); // TODO: just update the voip buttons
},
onMuteVideoClick: function() {
var call = this._getCallForRoom();
const call = this._getCallForRoom();
if (!call) {
return;
}
var newState = !call.isLocalVideoMuted();
const newState = !call.isLocalVideoMuted();
call.setLocalVideoMuted(newState);
this.forceUpdate(); // TODO: just update the voip buttons
},
@ -1408,7 +1404,7 @@ module.exports = React.createClass({
* We pass it down to the scroll panel.
*/
handleScrollKey: function(ev) {
var panel;
let panel;
if(this.refs.searchResultsPanel) {
panel = this.refs.searchResultsPanel;
} else if(this.refs.messagePanel) {
@ -1478,13 +1474,13 @@ module.exports = React.createClass({
<RoomHeader ref="header"
room={this.state.room}
oobData={this.props.oobData}
collapsedRhs={ this.props.collapsedRhs }
collapsedRhs={this.props.collapsedRhs}
/>
<div className="mx_RoomView_auxPanel">
<RoomPreviewBar onJoinClick={ this.onJoinButtonClicked }
onForgetClick={ this.onForgetClick }
onRejectClick={ this.onRejectThreepidInviteButtonClicked }
canPreview={ false } error={ this.state.roomLoadError }
<RoomPreviewBar onJoinClick={this.onJoinButtonClicked}
onForgetClick={this.onForgetClick}
onRejectClick={this.onRejectThreepidInviteButtonClicked}
canPreview={false} error={this.state.roomLoadError}
roomAlias={roomAlias}
spinner={this.state.joining}
inviterName={inviterName}
@ -1498,8 +1494,8 @@ module.exports = React.createClass({
}
}
var myUserId = MatrixClientPeg.get().credentials.userId;
var myMember = this.state.room.getMember(myUserId);
const myUserId = MatrixClientPeg.get().credentials.userId;
const myMember = this.state.room.getMember(myUserId);
if (myMember && myMember.membership == 'invite') {
if (this.state.joining || this.state.rejecting) {
return (
@ -1508,7 +1504,7 @@ module.exports = React.createClass({
</div>
);
} else {
var inviteEvent = myMember.events.member;
const inviteEvent = myMember.events.member;
var inviterName = inviteEvent.sender ? inviteEvent.sender.name : inviteEvent.getSender();
// We deliberately don't try to peek into invites, even if we have permission to peek
@ -1521,14 +1517,14 @@ module.exports = React.createClass({
<RoomHeader
ref="header"
room={this.state.room}
collapsedRhs={ this.props.collapsedRhs }
collapsedRhs={this.props.collapsedRhs}
/>
<div className="mx_RoomView_auxPanel">
<RoomPreviewBar onJoinClick={ this.onJoinButtonClicked }
onForgetClick={ this.onForgetClick }
onRejectClick={ this.onRejectButtonClicked }
inviterName={ inviterName }
canPreview={ false }
<RoomPreviewBar onJoinClick={this.onJoinButtonClicked}
onForgetClick={this.onForgetClick}
onRejectClick={this.onRejectButtonClicked}
inviterName={inviterName}
canPreview={false}
spinner={this.state.joining}
room={this.state.room}
/>
@ -1542,24 +1538,24 @@ module.exports = React.createClass({
// We have successfully loaded this room, and are not previewing.
// Display the "normal" room view.
var call = this._getCallForRoom();
var inCall = false;
const call = this._getCallForRoom();
let inCall = false;
if (call && (this.state.callState !== 'ended' && this.state.callState !== 'ringing')) {
inCall = true;
}
var scrollheader_classes = classNames({
const scrollheader_classes = classNames({
mx_RoomView_scrollheader: true,
});
var statusBar;
let statusBar;
let isStatusAreaExpanded = true;
if (ContentMessages.getCurrentUploads().length > 0) {
var UploadBar = sdk.getComponent('structures.UploadBar');
const UploadBar = sdk.getComponent('structures.UploadBar');
statusBar = <UploadBar room={this.state.room} />;
} else if (!this.state.searchResults) {
var RoomStatusBar = sdk.getComponent('structures.RoomStatusBar');
const RoomStatusBar = sdk.getComponent('structures.RoomStatusBar');
isStatusAreaExpanded = this.state.statusBarVisible;
statusBar = <RoomStatusBar
room={this.state.room}
@ -1582,12 +1578,12 @@ module.exports = React.createClass({
if (this.state.editingRoomSettings) {
aux = <RoomSettings ref="room_settings" onSaveClick={this.onSettingsSaveClick} onCancelClick={this.onCancelClick} room={this.state.room} />;
} else if (this.state.uploadingRoomSettings) {
aux = <Loader/>;
aux = <Loader />;
} else if (this.state.forwardingEvent !== null) {
aux = <ForwardMessage onCancelClick={this.onCancelClick} />;
} else if (this.state.searching) {
hideCancel = true; // has own cancel
aux = <SearchBar ref="search_bar" searchInProgress={this.state.searchInProgress } onCancelClick={this.onCancelSearchClick} onSearch={this.onSearch}/>;
aux = <SearchBar ref="search_bar" searchInProgress={this.state.searchInProgress} onCancelClick={this.onCancelSearchClick} onSearch={this.onSearch} />;
} else if (!myMember || myMember.membership !== "join") {
// We do have a room object for this room, but we're not currently in it.
// We may have a 3rd party invite to it.
@ -1602,7 +1598,7 @@ module.exports = React.createClass({
hideCancel = true;
aux = (
<RoomPreviewBar onJoinClick={this.onJoinButtonClicked}
onForgetClick={ this.onForgetClick }
onForgetClick={this.onForgetClick}
onRejectClick={this.onRejectThreepidInviteButtonClicked}
spinner={this.state.joining}
inviterName={inviterName}
@ -1613,7 +1609,7 @@ module.exports = React.createClass({
);
}
var auxPanel = (
const auxPanel = (
<AuxPanel ref="auxPanel" room={this.state.room}
userId={MatrixClientPeg.get().credentials.userId}
conferenceHandler={this.props.ConferenceHandler}
@ -1626,8 +1622,8 @@ module.exports = React.createClass({
</AuxPanel>
);
var messageComposer, searchInfo;
var canSpeak = (
let messageComposer, searchInfo;
const canSpeak = (
// joined and not showing search results
myMember && (myMember.membership == 'join') && !this.state.searchResults
);
@ -1638,8 +1634,8 @@ module.exports = React.createClass({
onResize={this.onChildResize}
uploadFile={this.uploadFile}
callState={this.state.callState}
opacity={ this.props.opacity }
showApps={ this.state.showApps }
opacity={this.props.opacity}
showApps={this.state.showApps}
/>;
}
@ -1647,19 +1643,19 @@ module.exports = React.createClass({
// in this.state if this is what RoomHeader desires?
if (this.state.searchResults) {
searchInfo = {
searchTerm : this.state.searchTerm,
searchScope : this.state.searchScope,
searchCount : this.state.searchResults.count,
searchTerm: this.state.searchTerm,
searchScope: this.state.searchScope,
searchCount: this.state.searchResults.count,
};
}
if (inCall) {
var zoomButton, voiceMuteButton, videoMuteButton;
let zoomButton, voiceMuteButton, videoMuteButton;
if (call.type === "video") {
zoomButton = (
<div className="mx_RoomView_voipButton" onClick={this.onFullscreenClick} title={ _t("Fill screen") }>
<TintableSvg src="img/fullscreen.svg" width="29" height="22" style={{ marginTop: 1, marginRight: 4 }}/>
<div className="mx_RoomView_voipButton" onClick={this.onFullscreenClick} title={_t("Fill screen")}>
<TintableSvg src="img/fullscreen.svg" width="29" height="22" style={{ marginTop: 1, marginRight: 4 }} />
</div>
);
@ -1667,14 +1663,14 @@ module.exports = React.createClass({
<div className="mx_RoomView_voipButton" onClick={this.onMuteVideoClick}>
<TintableSvg src={call.isLocalVideoMuted() ? "img/video-unmute.svg" : "img/video-mute.svg"}
alt={call.isLocalVideoMuted() ? _t("Click to unmute video") : _t("Click to mute video")}
width="31" height="27"/>
width="31" height="27" />
</div>;
}
voiceMuteButton =
<div className="mx_RoomView_voipButton" onClick={this.onMuteAudioClick}>
<TintableSvg src={call.isMicrophoneMuted() ? "img/voice-unmute.svg" : "img/voice-mute.svg"}
alt={call.isMicrophoneMuted() ? _t("Click to unmute audio") : _t("Click to mute audio")}
width="21" height="26"/>
width="21" height="26" />
</div>;
// wrap the existing status bar into a 'callStatusBar' which adds more knobs.
@ -1684,25 +1680,25 @@ module.exports = React.createClass({
{ videoMuteButton }
{ zoomButton }
{ statusBar }
<TintableSvg className="mx_RoomView_voipChevron" src="img/voip-chevron.svg" width="22" height="17"/>
<TintableSvg className="mx_RoomView_voipChevron" src="img/voip-chevron.svg" width="22" height="17" />
</div>;
}
// if we have search results, we keep the messagepanel (so that it preserves its
// scroll state), but hide it.
var searchResultsPanel;
var hideMessagePanel = false;
let searchResultsPanel;
let hideMessagePanel = false;
if (this.state.searchResults) {
searchResultsPanel = (
<ScrollPanel ref="searchResultsPanel"
className="mx_RoomView_messagePanel mx_RoomView_searchResultsPanel"
onFillRequest={ this.onSearchResultsFillRequest }
onResize={ this.onSearchResultsResize }
onFillRequest={this.onSearchResultsFillRequest}
onResize={this.onSearchResultsResize}
style={{ opacity: this.props.opacity }}
>
<li className={scrollheader_classes}></li>
{this.getSearchResultTiles()}
{ this.getSearchResultTiles() }
</ScrollPanel>
);
hideMessagePanel = true;
@ -1717,7 +1713,7 @@ module.exports = React.createClass({
}
// console.log("ShowUrlPreview for %s is %s", this.state.room.roomId, this.state.showUrlPreview);
var messagePanel = (
const messagePanel = (
<TimelinePanel ref={this._gatherTimelinePanelRef}
timelineSet={this.state.room.getUnfilteredTimelineSet()}
showReadReceipts={!UserSettingsStore.getSyncedSetting('hideReadReceipts', false)}
@ -1727,16 +1723,16 @@ module.exports = React.createClass({
highlightedEventId={highlightedEventId}
eventId={this.state.initialEventId}
eventPixelOffset={this.state.initialEventPixelOffset}
onScroll={ this.onMessageListScroll }
onReadMarkerUpdated={ this._updateTopUnreadMessagesBar }
showUrlPreview = { this.state.showUrlPreview }
opacity={ this.props.opacity }
onScroll={this.onMessageListScroll}
onReadMarkerUpdated={this._updateTopUnreadMessagesBar}
showUrlPreview = {this.state.showUrlPreview}
opacity={this.props.opacity}
className="mx_RoomView_messagePanel"
/>);
var topUnreadMessagesBar = null;
let topUnreadMessagesBar = null;
if (this.state.showTopUnreadMessagesBar) {
var TopUnreadMessagesBar = sdk.getComponent('rooms.TopUnreadMessagesBar');
const TopUnreadMessagesBar = sdk.getComponent('rooms.TopUnreadMessagesBar');
topUnreadMessagesBar = (
<div className="mx_RoomView_topUnreadMessagesBar mx_fadable" style={{ opacity: this.props.opacity }}>
<TopUnreadMessagesBar
@ -1752,13 +1748,13 @@ module.exports = React.createClass({
}
return (
<div className={ "mx_RoomView" + (inCall ? " mx_RoomView_inCall" : "") } ref="roomView">
<div className={"mx_RoomView" + (inCall ? " mx_RoomView_inCall" : "")} ref="roomView">
<RoomHeader ref="header" room={this.state.room} searchInfo={searchInfo}
oobData={this.props.oobData}
editing={this.state.editingRoomSettings}
saving={this.state.uploadingRoomSettings}
inRoom={myMember && myMember.membership === 'join'}
collapsedRhs={ this.props.collapsedRhs }
collapsedRhs={this.props.collapsedRhs}
onSearchClick={this.onSearchClick}
onSettingsClick={this.onSettingsClick}
onSaveClick={this.onSettingsSaveClick}

View file

@ -14,13 +14,13 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
var React = require("react");
var ReactDOM = require("react-dom");
var GeminiScrollbar = require('react-gemini-scrollbar');
const React = require("react");
const ReactDOM = require("react-dom");
const GeminiScrollbar = require('react-gemini-scrollbar');
import Promise from 'bluebird';
var KeyCode = require('../../KeyCode');
const KeyCode = require('../../KeyCode');
var DEBUG_SCROLL = false;
const DEBUG_SCROLL = false;
// var DEBUG_SCROLL = true;
// The amount of extra scroll distance to allow prior to unfilling.
@ -178,7 +178,7 @@ module.exports = React.createClass({
},
onScroll: function(ev) {
var sn = this._getScrollNode();
const sn = this._getScrollNode();
debuglog("Scroll event: offset now:", sn.scrollTop,
"_lastSetScroll:", this._lastSetScroll);
@ -238,7 +238,7 @@ module.exports = React.createClass({
// about whether the the content is scrolled down right now, irrespective of
// whether it will stay that way when the children update.
isAtBottom: function() {
var sn = this._getScrollNode();
const sn = this._getScrollNode();
// there seems to be some bug with flexbox/gemini/chrome/richvdh's
// understanding of the box model, wherein the scrollNode ends up 2
@ -281,7 +281,7 @@ module.exports = React.createClass({
// |#########| |
// `---------' -
_getExcessHeight: function(backwards) {
var sn = this._getScrollNode();
const sn = this._getScrollNode();
if (backwards) {
return sn.scrollTop - sn.clientHeight - UNPAGINATION_PADDING;
} else {
@ -295,7 +295,7 @@ module.exports = React.createClass({
return;
}
var sn = this._getScrollNode();
const sn = this._getScrollNode();
// if there is less than a screenful of messages above or below the
// viewport, try to get some more messages.
@ -377,7 +377,7 @@ module.exports = React.createClass({
// check if there is already a pending fill request. If not, set one off.
_maybeFill: function(backwards) {
var dir = backwards ? 'b' : 'f';
const dir = backwards ? 'b' : 'f';
if (this._pendingFillRequests[dir]) {
debuglog("ScrollPanel: Already a "+dir+" fill in progress - not starting another");
return;
@ -470,8 +470,8 @@ module.exports = React.createClass({
* mult: -1 to page up, +1 to page down
*/
scrollRelative: function(mult) {
var scrollNode = this._getScrollNode();
var delta = mult * scrollNode.clientHeight * 0.5;
const scrollNode = this._getScrollNode();
const delta = mult * scrollNode.clientHeight * 0.5;
this._setScrollTop(scrollNode.scrollTop + delta);
this._saveScrollState();
},
@ -535,7 +535,7 @@ module.exports = React.createClass({
this.scrollState = {
stuckAtBottom: false,
trackedScrollToken: scrollToken,
pixelOffset: pixelOffset
pixelOffset: pixelOffset,
};
// ... then make it so.
@ -546,10 +546,10 @@ module.exports = React.createClass({
// given offset in the window. A helper for _restoreSavedScrollState.
_scrollToToken: function(scrollToken, pixelOffset) {
/* find the dom node with the right scrolltoken */
var node;
var messages = this.refs.itemlist.children;
for (var i = messages.length-1; i >= 0; --i) {
var m = messages[i];
let node;
const messages = this.refs.itemlist.children;
for (let i = messages.length-1; i >= 0; --i) {
const m = messages[i];
// 'data-scroll-tokens' is a DOMString of comma-separated scroll tokens
// There might only be one scroll token
if (m.dataset.scrollTokens &&
@ -564,10 +564,10 @@ module.exports = React.createClass({
return;
}
var scrollNode = this._getScrollNode();
var wrapperRect = ReactDOM.findDOMNode(this).getBoundingClientRect();
var boundingRect = node.getBoundingClientRect();
var scrollDelta = boundingRect.bottom + pixelOffset - wrapperRect.bottom;
const scrollNode = this._getScrollNode();
const wrapperRect = ReactDOM.findDOMNode(this).getBoundingClientRect();
const boundingRect = node.getBoundingClientRect();
const scrollDelta = boundingRect.bottom + pixelOffset - wrapperRect.bottom;
debuglog("ScrollPanel: scrolling to token '" + scrollToken + "'+" +
pixelOffset + " (delta: "+scrollDelta+")");
@ -575,7 +575,6 @@ module.exports = React.createClass({
if(scrollDelta != 0) {
this._setScrollTop(scrollNode.scrollTop + scrollDelta);
}
},
_saveScrollState: function() {
@ -585,16 +584,16 @@ module.exports = React.createClass({
return;
}
var itemlist = this.refs.itemlist;
var wrapperRect = ReactDOM.findDOMNode(this).getBoundingClientRect();
var messages = itemlist.children;
const itemlist = this.refs.itemlist;
const wrapperRect = ReactDOM.findDOMNode(this).getBoundingClientRect();
const messages = itemlist.children;
let newScrollState = null;
for (var i = messages.length-1; i >= 0; --i) {
var node = messages[i];
for (let i = messages.length-1; i >= 0; --i) {
const node = messages[i];
if (!node.dataset.scrollTokens) continue;
var boundingRect = node.getBoundingClientRect();
const boundingRect = node.getBoundingClientRect();
newScrollState = {
stuckAtBottom: false,
trackedScrollToken: node.dataset.scrollTokens.split(',')[0],
@ -619,8 +618,8 @@ module.exports = React.createClass({
},
_restoreSavedScrollState: function() {
var scrollState = this.scrollState;
var scrollNode = this._getScrollNode();
const scrollState = this.scrollState;
const scrollNode = this._getScrollNode();
if (scrollState.stuckAtBottom) {
this._setScrollTop(Number.MAX_VALUE);
@ -631,9 +630,9 @@ module.exports = React.createClass({
},
_setScrollTop: function(scrollTop) {
var scrollNode = this._getScrollNode();
const scrollNode = this._getScrollNode();
var prevScroll = scrollNode.scrollTop;
const prevScroll = scrollNode.scrollTop;
// FF ignores attempts to set scrollTop to very large numbers
scrollNode.scrollTop = Math.min(scrollTop, scrollNode.scrollHeight);
@ -676,7 +675,7 @@ module.exports = React.createClass({
className={this.props.className} style={this.props.style}>
<div className="mx_RoomView_messageListWrapper">
<ol ref="itemlist" className="mx_RoomView_MessageList" aria-live="polite">
{this.props.children}
{ this.props.children }
</ol>
</div>
</GeminiScrollbar>

View file

@ -15,27 +15,27 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
var React = require('react');
var ReactDOM = require("react-dom");
const React = require('react');
const ReactDOM = require("react-dom");
import Promise from 'bluebird';
var Matrix = require("matrix-js-sdk");
var EventTimeline = Matrix.EventTimeline;
const Matrix = require("matrix-js-sdk");
const EventTimeline = Matrix.EventTimeline;
var sdk = require('../../index');
const sdk = require('../../index');
import { _t } from '../../languageHandler';
var MatrixClientPeg = require("../../MatrixClientPeg");
var dis = require("../../dispatcher");
var ObjectUtils = require('../../ObjectUtils');
var Modal = require("../../Modal");
var UserActivity = require("../../UserActivity");
var KeyCode = require('../../KeyCode');
const MatrixClientPeg = require("../../MatrixClientPeg");
const dis = require("../../dispatcher");
const ObjectUtils = require('../../ObjectUtils');
const Modal = require("../../Modal");
const UserActivity = require("../../UserActivity");
const KeyCode = require('../../KeyCode');
import UserSettingsStore from '../../UserSettingsStore';
var PAGINATE_SIZE = 20;
var INITIAL_SIZE = 20;
const PAGINATE_SIZE = 20;
const INITIAL_SIZE = 20;
var DEBUG = false;
const DEBUG = false;
if (DEBUG) {
// using bind means that we get to keep useful line numbers in the console
@ -260,7 +260,7 @@ var TimelinePanel = React.createClass({
dis.unregister(this.dispatcherRef);
var client = MatrixClientPeg.get();
const client = MatrixClientPeg.get();
if (client) {
client.removeListener("Room.timeline", this.onRoomTimeline);
client.removeListener("Room.timelineReset", this.onRoomTimelineReset);
@ -275,20 +275,20 @@ var TimelinePanel = React.createClass({
onMessageListUnfillRequest: function(backwards, scrollToken) {
// If backwards, unpaginate from the back (i.e. the start of the timeline)
let dir = backwards ? EventTimeline.BACKWARDS : EventTimeline.FORWARDS;
const dir = backwards ? EventTimeline.BACKWARDS : EventTimeline.FORWARDS;
debuglog("TimelinePanel: unpaginating events in direction", dir);
// All tiles are inserted by MessagePanel to have a scrollToken === eventId, and
// this particular event should be the first or last to be unpaginated.
let eventId = scrollToken;
const eventId = scrollToken;
let marker = this.state.events.findIndex(
const marker = this.state.events.findIndex(
(ev) => {
return ev.getId() === eventId;
}
},
);
let count = backwards ? marker + 1 : this.state.events.length - marker;
const count = backwards ? marker + 1 : this.state.events.length - marker;
if (count > 0) {
debuglog("TimelinePanel: Unpaginating", count, "in direction", dir);
@ -305,9 +305,9 @@ var TimelinePanel = React.createClass({
// set off a pagination request.
onMessageListFillRequest: function(backwards) {
var dir = backwards ? EventTimeline.BACKWARDS : EventTimeline.FORWARDS;
var canPaginateKey = backwards ? 'canBackPaginate' : 'canForwardPaginate';
var paginatingKey = backwards ? 'backPaginating' : 'forwardPaginating';
const dir = backwards ? EventTimeline.BACKWARDS : EventTimeline.FORWARDS;
const canPaginateKey = backwards ? 'canBackPaginate' : 'canForwardPaginate';
const paginatingKey = backwards ? 'backPaginating' : 'forwardPaginating';
if (!this.state[canPaginateKey]) {
debuglog("TimelinePanel: have given up", dir, "paginating this timeline");
@ -328,7 +328,7 @@ var TimelinePanel = React.createClass({
debuglog("TimelinePanel: paginate complete backwards:"+backwards+"; success:"+r);
var newState = {
const newState = {
[paginatingKey]: false,
[canPaginateKey]: r,
events: this._getEvents(),
@ -336,8 +336,8 @@ var TimelinePanel = React.createClass({
// moving the window in this direction may mean that we can now
// paginate in the other where we previously could not.
var otherDirection = backwards ? EventTimeline.FORWARDS : EventTimeline.BACKWARDS;
var canPaginateOtherWayKey = backwards ? 'canForwardPaginate' : 'canBackPaginate';
const otherDirection = backwards ? EventTimeline.FORWARDS : EventTimeline.BACKWARDS;
const canPaginateOtherWayKey = backwards ? 'canForwardPaginate' : 'canBackPaginate';
if (!this.state[canPaginateOtherWayKey] &&
this._timelineWindow.canPaginate(otherDirection)) {
debuglog('TimelinePanel: can now', otherDirection, 'paginate again');
@ -420,15 +420,15 @@ var TimelinePanel = React.createClass({
this._timelineWindow.paginate(EventTimeline.FORWARDS, 1, false).done(() => {
if (this.unmounted) { return; }
var events = this._timelineWindow.getEvents();
var lastEv = events[events.length-1];
const events = this._timelineWindow.getEvents();
const lastEv = events[events.length-1];
// if we're at the end of the live timeline, append the pending events
if (this.props.timelineSet.room && !this._timelineWindow.canPaginate(EventTimeline.FORWARDS)) {
events.push(...this.props.timelineSet.room.getPendingEvents());
}
var updatedState = {events: events};
const updatedState = {events: events};
if (this.props.manageReadMarkers) {
// when a new event arrives when the user is not watching the
@ -439,8 +439,8 @@ var TimelinePanel = React.createClass({
// read-marker when a remote echo of an event we have just sent takes
// more than the timeout on userCurrentlyActive.
//
var myUserId = MatrixClientPeg.get().credentials.userId;
var sender = ev.sender ? ev.sender.userId : null;
const myUserId = MatrixClientPeg.get().credentials.userId;
const sender = ev.sender ? ev.sender.userId : null;
var callback = null;
if (sender != myUserId && !UserActivity.userCurrentlyActive()) {
updatedState.readMarkerVisible = true;
@ -646,7 +646,7 @@ var TimelinePanel = React.createClass({
// and we'll get confused when their ID changes and we can't figure out
// where the RM is pointing to. The read marker will be invisible for
// now anyway, so this doesn't really matter.
var lastDisplayedIndex = this._getLastDisplayedEventIndex({
const lastDisplayedIndex = this._getLastDisplayedEventIndex({
allowPartial: true,
ignoreEchoes: true,
});
@ -655,7 +655,7 @@ var TimelinePanel = React.createClass({
return;
}
var lastDisplayedEvent = this.state.events[lastDisplayedIndex];
const lastDisplayedEvent = this.state.events[lastDisplayedIndex];
this._setReadMarker(lastDisplayedEvent.getId(),
lastDisplayedEvent.getTs());
@ -676,7 +676,7 @@ var TimelinePanel = React.createClass({
// we call _timelineWindow.getEvents() rather than using
// this.state.events, because react batches the update to the latter, so it
// may not have been updated yet.
var events = this._timelineWindow.getEvents();
const events = this._timelineWindow.getEvents();
// first find where the current RM is
for (var i = 0; i < events.length; i++) {
@ -689,7 +689,7 @@ var TimelinePanel = React.createClass({
}
// now think about advancing it
var myUserId = MatrixClientPeg.get().credentials.userId;
const myUserId = MatrixClientPeg.get().credentials.userId;
for (i++; i < events.length; i++) {
var ev = events[i];
if (!ev.sender || ev.sender.userId != myUserId) {
@ -734,7 +734,7 @@ var TimelinePanel = React.createClass({
//
// a quick way to figure out if we've loaded the relevant event is
// simply to check if the messagepanel knows where the read-marker is.
var ret = this.refs.messagePanel.getReadMarkerPosition();
const ret = this.refs.messagePanel.getReadMarkerPosition();
if (ret !== null) {
// The messagepanel knows where the RM is, so we must have loaded
// the relevant event.
@ -755,13 +755,13 @@ var TimelinePanel = React.createClass({
forgetReadMarker: function() {
if (!this.props.manageReadMarkers) return;
var rmId = this._getCurrentReadReceipt();
const rmId = this._getCurrentReadReceipt();
// see if we know the timestamp for the rr event
var tl = this.props.timelineSet.getTimelineForEvent(rmId);
var rmTs;
const tl = this.props.timelineSet.getTimelineForEvent(rmId);
let rmTs;
if (tl) {
var event = tl.getEvents().find((e) => { return e.getId() == rmId; });
const event = tl.getEvents().find((e) => { return e.getId() == rmId; });
if (event) {
rmTs = event.getTs();
}
@ -801,7 +801,7 @@ var TimelinePanel = React.createClass({
if (!this.props.manageReadMarkers) return null;
if (!this.refs.messagePanel) return null;
var ret = this.refs.messagePanel.getReadMarkerPosition();
const ret = this.refs.messagePanel.getReadMarkerPosition();
if (ret !== null) {
return ret;
}
@ -844,8 +844,7 @@ var TimelinePanel = React.createClass({
// jump to the live timeline on ctrl-end, rather than the end of the
// timeline window.
if (ev.ctrlKey && !ev.shiftKey && !ev.altKey && !ev.metaKey &&
ev.keyCode == KeyCode.END)
{
ev.keyCode == KeyCode.END) {
this.jumpToLiveTimeline();
} else {
this.refs.messagePanel.handleScrollKey(ev);
@ -853,12 +852,12 @@ var TimelinePanel = React.createClass({
},
_initTimeline: function(props) {
var initialEvent = props.eventId;
var pixelOffset = props.eventPixelOffset;
const initialEvent = props.eventId;
const pixelOffset = props.eventPixelOffset;
// if a pixelOffset is given, it is relative to the bottom of the
// container. If not, put the event in the middle of the container.
var offsetBase = 1;
let offsetBase = 1;
if (pixelOffset == null) {
offsetBase = 0.5;
}
@ -887,7 +886,7 @@ var TimelinePanel = React.createClass({
MatrixClientPeg.get(), this.props.timelineSet,
{windowLimit: this.props.timelineCap});
var onLoaded = () => {
const onLoaded = () => {
this._reloadEvents();
// If we switched away from the room while there were pending
@ -922,15 +921,15 @@ var TimelinePanel = React.createClass({
});
};
var onError = (error) => {
const onError = (error) => {
this.setState({timelineLoading: false});
console.error(
`Error loading timeline panel at ${eventId}: ${error}`,
);
var msg = error.message ? error.message : JSON.stringify(error);
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
const msg = error.message ? error.message : JSON.stringify(error);
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
var onFinished;
let onFinished;
// if we were given an event ID, then when the user closes the
// dialog, let's jump to the end of the timeline. If we weren't,
@ -945,7 +944,7 @@ var TimelinePanel = React.createClass({
});
};
}
var message = (error.errcode == 'M_FORBIDDEN')
const message = (error.errcode == 'M_FORBIDDEN')
? _t("Tried to load a specific point in this room's timeline, but you do not have permission to view the message in question.")
: _t("Tried to load a specific point in this room's timeline, but was unable to find it.");
Modal.createTrackedDialog('Failed to load timeline position', '', ErrorDialog, {
@ -955,7 +954,7 @@ var TimelinePanel = React.createClass({
});
};
var prom = this._timelineWindow.load(eventId, INITIAL_SIZE);
let prom = this._timelineWindow.load(eventId, INITIAL_SIZE);
// if we already have the event in question, TimelineWindow.load
// returns a resolved promise.
@ -996,7 +995,7 @@ var TimelinePanel = React.createClass({
// get the list of events from the timeline window and the pending event list
_getEvents: function() {
var events = this._timelineWindow.getEvents();
const events = this._timelineWindow.getEvents();
// if we're at the end of the live timeline, append the pending events
if (!this._timelineWindow.canPaginate(EventTimeline.FORWARDS)) {
@ -1007,7 +1006,7 @@ var TimelinePanel = React.createClass({
},
_indexForEventId: function(evId) {
for (var i = 0; i < this.state.events.length; ++i) {
for (let i = 0; i < this.state.events.length; ++i) {
if (evId == this.state.events[i].getId()) {
return i;
}
@ -1017,18 +1016,18 @@ var TimelinePanel = React.createClass({
_getLastDisplayedEventIndex: function(opts) {
opts = opts || {};
var ignoreOwn = opts.ignoreOwn || false;
var ignoreEchoes = opts.ignoreEchoes || false;
var allowPartial = opts.allowPartial || false;
const ignoreOwn = opts.ignoreOwn || false;
const ignoreEchoes = opts.ignoreEchoes || false;
const allowPartial = opts.allowPartial || false;
var messagePanel = this.refs.messagePanel;
const messagePanel = this.refs.messagePanel;
if (messagePanel === undefined) return null;
var wrapperRect = ReactDOM.findDOMNode(messagePanel).getBoundingClientRect();
var myUserId = MatrixClientPeg.get().credentials.userId;
const wrapperRect = ReactDOM.findDOMNode(messagePanel).getBoundingClientRect();
const myUserId = MatrixClientPeg.get().credentials.userId;
for (var i = this.state.events.length-1; i >= 0; --i) {
var ev = this.state.events[i];
for (let i = this.state.events.length-1; i >= 0; --i) {
const ev = this.state.events[i];
if (ignoreOwn && ev.sender && ev.sender.userId == myUserId) {
continue;
@ -1039,10 +1038,10 @@ var TimelinePanel = React.createClass({
continue;
}
var node = messagePanel.getNodeForEventId(ev.getId());
const node = messagePanel.getNodeForEventId(ev.getId());
if (!node) continue;
var boundingRect = node.getBoundingClientRect();
const boundingRect = node.getBoundingClientRect();
if ((allowPartial && boundingRect.top < wrapperRect.bottom) ||
(!allowPartial && boundingRect.bottom < wrapperRect.bottom)) {
return i;
@ -1060,18 +1059,18 @@ var TimelinePanel = React.createClass({
* SDK.
*/
_getCurrentReadReceipt: function(ignoreSynthesized) {
var client = MatrixClientPeg.get();
const client = MatrixClientPeg.get();
// the client can be null on logout
if (client == null) {
return null;
}
var myUserId = client.credentials.userId;
const myUserId = client.credentials.userId;
return this.props.timelineSet.room.getEventReadUpTo(myUserId, ignoreSynthesized);
},
_setReadMarker: function(eventId, eventTs, inhibitSetState) {
var roomId = this.props.timelineSet.room.roomId;
const roomId = this.props.timelineSet.room.roomId;
// don't update the state (and cause a re-render) if there is
// no change to the RM.
@ -1096,8 +1095,8 @@ var TimelinePanel = React.createClass({
},
render: function() {
var MessagePanel = sdk.getComponent("structures.MessagePanel");
var Loader = sdk.getComponent("elements.Spinner");
const MessagePanel = sdk.getComponent("structures.MessagePanel");
const Loader = sdk.getComponent("elements.Spinner");
// just show a spinner while the timeline loads.
//
@ -1112,7 +1111,7 @@ var TimelinePanel = React.createClass({
// exist.
if (this.state.timelineLoading) {
return (
<div className={ this.props.className + " mx_RoomView_messageListWrapper" }>
<div className={this.props.className + " mx_RoomView_messageListWrapper"}>
<Loader />
</div>
);
@ -1120,7 +1119,7 @@ var TimelinePanel = React.createClass({
if (this.state.events.length == 0 && !this.state.canBackPaginate && this.props.empty) {
return (
<div className={ this.props.className + " mx_RoomView_messageListWrapper" }>
<div className={this.props.className + " mx_RoomView_messageListWrapper"}>
<div className="mx_RoomView_empty">{ this.props.empty }</div>
</div>
);
@ -1134,7 +1133,7 @@ var TimelinePanel = React.createClass({
// forwards, otherwise if somebody hits the bottom of the loaded
// events when viewing historical messages, we get stuck in a loop
// of paginating our way through the entire history of the room.
var stickyBottom = !this._timelineWindow.canPaginate(EventTimeline.FORWARDS);
const stickyBottom = !this._timelineWindow.canPaginate(EventTimeline.FORWARDS);
// If the state is PREPARED, we're still waiting for the js-sdk to sync with
// the HS and fetch the latest events, so we are effectively forward paginating.
@ -1143,26 +1142,26 @@ var TimelinePanel = React.createClass({
);
return (
<MessagePanel ref="messagePanel"
hidden={ this.props.hidden }
backPaginating={ this.state.backPaginating }
forwardPaginating={ forwardPaginating }
events={ this.state.events }
highlightedEventId={ this.props.highlightedEventId }
readMarkerEventId={ this.state.readMarkerEventId }
readMarkerVisible={ this.state.readMarkerVisible }
suppressFirstDateSeparator={ this.state.canBackPaginate }
showUrlPreview={ this.props.showUrlPreview }
showReadReceipts={ this.props.showReadReceipts }
ourUserId={ MatrixClientPeg.get().credentials.userId }
stickyBottom={ stickyBottom }
onScroll={ this.onMessageListScroll }
onFillRequest={ this.onMessageListFillRequest }
onUnfillRequest={ this.onMessageListUnfillRequest }
opacity={ this.props.opacity }
isTwelveHour={ this.state.isTwelveHour }
alwaysShowTimestamps={ this.state.alwaysShowTimestamps }
className={ this.props.className }
tileShape={ this.props.tileShape }
hidden={this.props.hidden}
backPaginating={this.state.backPaginating}
forwardPaginating={forwardPaginating}
events={this.state.events}
highlightedEventId={this.props.highlightedEventId}
readMarkerEventId={this.state.readMarkerEventId}
readMarkerVisible={this.state.readMarkerVisible}
suppressFirstDateSeparator={this.state.canBackPaginate}
showUrlPreview={this.props.showUrlPreview}
showReadReceipts={this.props.showReadReceipts}
ourUserId={MatrixClientPeg.get().credentials.userId}
stickyBottom={stickyBottom}
onScroll={this.onMessageListScroll}
onFillRequest={this.onMessageListFillRequest}
onUnfillRequest={this.onMessageListUnfillRequest}
opacity={this.props.opacity}
isTwelveHour={this.state.isTwelveHour}
alwaysShowTimestamps={this.state.alwaysShowTimestamps}
className={this.props.className}
tileShape={this.props.tileShape}
/>
);
},

View file

@ -14,15 +14,15 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
var React = require('react');
var ContentMessages = require('../../ContentMessages');
var dis = require('../../dispatcher');
var filesize = require('filesize');
const React = require('react');
const ContentMessages = require('../../ContentMessages');
const dis = require('../../dispatcher');
const filesize = require('filesize');
import { _t } from '../../languageHandler';
module.exports = React.createClass({displayName: 'UploadBar',
propTypes: {
room: React.PropTypes.object
room: React.PropTypes.object,
},
componentDidMount: function() {
@ -46,7 +46,7 @@ module.exports = React.createClass({displayName: 'UploadBar',
},
render: function() {
var uploads = ContentMessages.getCurrentUploads();
const uploads = ContentMessages.getCurrentUploads();
// for testing UI... - also fix up the ContentMessages.getCurrentUploads().length
// check in RoomView
@ -62,8 +62,8 @@ module.exports = React.createClass({displayName: 'UploadBar',
return <div />;
}
var upload;
for (var i = 0; i < uploads.length; ++i) {
let upload;
for (let i = 0; i < uploads.length; ++i) {
if (uploads[i].roomId == this.props.room.roomId) {
upload = uploads[i];
break;
@ -73,32 +73,32 @@ module.exports = React.createClass({displayName: 'UploadBar',
return <div />;
}
var innerProgressStyle = {
width: ((upload.loaded / (upload.total || 1)) * 100) + '%'
const innerProgressStyle = {
width: ((upload.loaded / (upload.total || 1)) * 100) + '%',
};
var uploadedSize = filesize(upload.loaded);
var totalSize = filesize(upload.total);
let uploadedSize = filesize(upload.loaded);
const totalSize = filesize(upload.total);
if (uploadedSize.replace(/^.* /, '') === totalSize.replace(/^.* /, '')) {
uploadedSize = uploadedSize.replace(/ .*/, '');
}
// MUST use var name 'count' for pluralization to kick in
var uploadText = _t("Uploading %(filename)s and %(count)s others", {filename: upload.fileName, count: (uploads.length - 1)});
const uploadText = _t("Uploading %(filename)s and %(count)s others", {filename: upload.fileName, count: (uploads.length - 1)});
return (
<div className="mx_UploadBar">
<div className="mx_UploadBar_uploadProgressOuter">
<div className="mx_UploadBar_uploadProgressInner" style={innerProgressStyle}></div>
</div>
<img className="mx_UploadBar_uploadIcon mx_filterFlipColor" src="img/fileicon.png" width="17" height="22"/>
<img className="mx_UploadBar_uploadIcon mx_filterFlipColor" src="img/fileicon.png" width="17" height="22" />
<img className="mx_UploadBar_uploadCancel mx_filterFlipColor" src="img/cancel.svg" width="18" height="18"
onClick={function() { ContentMessages.cancelUpload(upload.promise); }}
/>
<div className="mx_UploadBar_uploadBytes">
{ uploadedSize } / { totalSize }
</div>
<div className="mx_UploadBar_uploadFilename">{uploadText}</div>
<div className="mx_UploadBar_uploadFilename">{ uploadText }</div>
</div>
);
}
},
});

View file

@ -17,13 +17,13 @@ limitations under the License.
'use strict';
var React = require('react');
const React = require('react');
import { _t } from '../../../languageHandler';
var sdk = require('../../../index');
var Modal = require("../../../Modal");
var MatrixClientPeg = require('../../../MatrixClientPeg');
const sdk = require('../../../index');
const Modal = require("../../../Modal");
const MatrixClientPeg = require('../../../MatrixClientPeg');
var PasswordReset = require("../../../PasswordReset");
const PasswordReset = require("../../../PasswordReset");
module.exports = React.createClass({
displayName: 'ForgotPassword',
@ -35,30 +35,30 @@ module.exports = React.createClass({
customIsUrl: React.PropTypes.string,
onLoginClick: React.PropTypes.func,
onRegisterClick: React.PropTypes.func,
onComplete: React.PropTypes.func.isRequired
onComplete: React.PropTypes.func.isRequired,
},
getInitialState: function() {
return {
enteredHomeserverUrl: this.props.customHsUrl || this.props.defaultHsUrl,
enteredIdentityServerUrl: this.props.customIsUrl || this.props.defaultIsUrl,
progress: null
progress: null,
};
},
submitPasswordReset: function(hsUrl, identityUrl, email, password) {
this.setState({
progress: "sending_email"
progress: "sending_email",
});
this.reset = new PasswordReset(hsUrl, identityUrl);
this.reset.resetPassword(email, password).done(() => {
this.setState({
progress: "sent_email"
progress: "sent_email",
});
}, (err) => {
this.showErrorDialog(_t('Failed to send email') + ": " + err.message);
this.setState({
progress: null
progress: null,
});
});
},
@ -81,15 +81,12 @@ module.exports = React.createClass({
if (!this.state.email) {
this.showErrorDialog(_t('The email address linked to your account must be entered.'));
}
else if (!this.state.password || !this.state.password2) {
} else if (!this.state.password || !this.state.password2) {
this.showErrorDialog(_t('A new password must be entered.'));
}
else if (this.state.password !== this.state.password2) {
} else if (this.state.password !== this.state.password2) {
this.showErrorDialog(_t('New passwords must match each other.'));
}
else {
var QuestionDialog = sdk.getComponent("dialogs.QuestionDialog");
} else {
const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog");
Modal.createTrackedDialog('Forgot Password Warning', '', QuestionDialog, {
title: _t('Warning!'),
description:
@ -99,7 +96,7 @@ module.exports = React.createClass({
'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.'
'them afterwards. In future this will be improved.',
) }
</div>,
button: _t('Continue'),
@ -107,13 +104,13 @@ module.exports = React.createClass({
<button className="mx_Dialog_primary"
onClick={this._onExportE2eKeysClicked}>
{ _t('Export E2E room keys') }
</button>
</button>,
],
onFinished: (confirmed) => {
if (confirmed) {
this.submitPasswordReset(
this.state.enteredHomeserverUrl, this.state.enteredIdentityServerUrl,
this.state.email, this.state.password
this.state.email, this.state.password,
);
}
},
@ -133,7 +130,7 @@ module.exports = React.createClass({
onInputChanged: function(stateKey, ev) {
this.setState({
[stateKey]: ev.target.value
[stateKey]: ev.target.value,
});
},
@ -149,7 +146,7 @@ module.exports = React.createClass({
},
showErrorDialog: function(body, title) {
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
Modal.createTrackedDialog('Forgot Password Error', '', ErrorDialog, {
title: title,
description: body,
@ -157,37 +154,34 @@ module.exports = React.createClass({
},
render: function() {
var LoginHeader = sdk.getComponent("login.LoginHeader");
var LoginFooter = sdk.getComponent("login.LoginFooter");
var ServerConfig = sdk.getComponent("login.ServerConfig");
var Spinner = sdk.getComponent("elements.Spinner");
const LoginHeader = sdk.getComponent("login.LoginHeader");
const LoginFooter = sdk.getComponent("login.LoginFooter");
const ServerConfig = sdk.getComponent("login.ServerConfig");
const Spinner = sdk.getComponent("elements.Spinner");
var resetPasswordJsx;
let resetPasswordJsx;
if (this.state.progress === "sending_email") {
resetPasswordJsx = <Spinner />;
}
else if (this.state.progress === "sent_email") {
} else if (this.state.progress === "sent_email") {
resetPasswordJsx = (
<div>
{ _t('An email has been sent to') } {this.state.email}. { _t("Once you've followed the link it contains, click below") }.
{ _t('An email has been sent to') } { this.state.email }. { _t("Once you've followed the link it contains, click below") }.
<br />
<input className="mx_Login_submit" type="button" onClick={this.onVerify}
value={ _t('I have verified my email address') } />
value={_t('I have verified my email address')} />
</div>
);
}
else if (this.state.progress === "complete") {
} else if (this.state.progress === "complete") {
resetPasswordJsx = (
<div>
<p>{ _t('Your password has been reset') }.</p>
<p>{ _t('You have been logged out of all devices and will no longer receive push notifications. To re-enable notifications, sign in again on each device') }.</p>
<input className="mx_Login_submit" type="button" onClick={this.props.onComplete}
value={ _t('Return to login screen') } />
value={_t('Return to login screen')} />
</div>
);
}
else {
} else {
resetPasswordJsx = (
<div>
<div className="mx_Login_prompt">
@ -199,21 +193,21 @@ module.exports = React.createClass({
name="reset_email" // define a name so browser's password autofill gets less confused
value={this.state.email}
onChange={this.onInputChanged.bind(this, "email")}
placeholder={ _t('Email address') } autoFocus />
placeholder={_t('Email address')} autoFocus />
<br />
<input className="mx_Login_field" ref="pass" type="password"
name="reset_password"
value={this.state.password}
onChange={this.onInputChanged.bind(this, "password")}
placeholder={ _t('New password') } />
placeholder={_t('New password')} />
<br />
<input className="mx_Login_field" ref="pass" type="password"
name="reset_password_confirm"
value={this.state.password2}
onChange={this.onInputChanged.bind(this, "password2")}
placeholder={ _t('Confirm your new password') } />
placeholder={_t('Confirm your new password')} />
<br />
<input className="mx_Login_submit" type="submit" value={ _t('Send Reset Email') } />
<input className="mx_Login_submit" type="submit" value={_t('Send Reset Email')} />
</form>
<ServerConfig ref="serverConfig"
withToggleButton={true}
@ -222,11 +216,11 @@ module.exports = React.createClass({
customHsUrl={this.props.customHsUrl}
customIsUrl={this.props.customIsUrl}
onServerConfigChange={this.onServerConfigChange}
delayTimeMs={0}/>
delayTimeMs={0} />
<div className="mx_Login_error">
</div>
<a className="mx_Login_create" onClick={this.props.onLoginClick} href="#">
{_t('Return to login screen')}
{ _t('Return to login screen') }
</a>
<a className="mx_Login_create" onClick={this.props.onRegisterClick} href="#">
{ _t('Create an account') }
@ -242,9 +236,9 @@ module.exports = React.createClass({
<div className="mx_Login">
<div className="mx_Login_box">
<LoginHeader />
{resetPasswordJsx}
{ resetPasswordJsx }
</div>
</div>
);
}
},
});

View file

@ -134,7 +134,7 @@ module.exports = React.createClass({
},
_onLoginAsGuestClick: function() {
var self = this;
const self = this;
self.setState({
busy: true,
errorText: null,
@ -156,7 +156,7 @@ module.exports = React.createClass({
});
}).finally(function() {
self.setState({
busy: false
busy: false,
});
}).done();
},
@ -183,8 +183,8 @@ module.exports = React.createClass({
},
onServerConfigChange: function(config) {
var self = this;
let newState = {
const self = this;
const newState = {
errorText: null, // reset err messages
};
if (config.hsUrl !== undefined) {
@ -199,13 +199,13 @@ module.exports = React.createClass({
},
_initLoginLogic: function(hsUrl, isUrl) {
var self = this;
const self = this;
hsUrl = hsUrl || this.state.enteredHomeserverUrl;
isUrl = isUrl || this.state.enteredIdentityServerUrl;
var fallbackHsUrl = hsUrl == this.props.defaultHsUrl ? this.props.fallbackHsUrl : null;
const fallbackHsUrl = hsUrl == this.props.defaultHsUrl ? this.props.fallbackHsUrl : null;
var loginLogic = new Login(hsUrl, isUrl, fallbackHsUrl, {
const loginLogic = new Login(hsUrl, isUrl, fallbackHsUrl, {
defaultDeviceDisplayName: this.props.defaultDeviceDisplayName,
});
this._loginLogic = loginLogic;
@ -259,15 +259,15 @@ module.exports = React.createClass({
{ _tJsx("Can't connect to homeserver via HTTP when an HTTPS URL is in your browser bar. " +
"Either use HTTPS or <a>enable unsafe scripts</a>.",
/<a>(.*?)<\/a>/,
(sub) => { return <a href="https://www.google.com/search?&q=enable%20unsafe%20scripts">{ sub }</a>; }
)}
(sub) => { return <a href="https://www.google.com/search?&q=enable%20unsafe%20scripts">{ sub }</a>; },
) }
</span>;
} else {
errorText = <span>
{ _tJsx("Can't connect to homeserver - please check your connectivity, ensure your <a>homeserver's SSL certificate</a> is trusted, and that a browser extension is not blocking requests.",
/<a>(.*?)<\/a>/,
(sub) => { return <a href={this.state.enteredHomeserverUrl}>{ sub }</a>; }
)}
(sub) => { return <a href={this.state.enteredHomeserverUrl}>{ sub }</a>; },
) }
</span>;
}
}
@ -290,6 +290,7 @@ module.exports = React.createClass({
onPhoneNumberChanged={this.onPhoneNumberChanged}
onForgotPasswordClick={this.props.onForgotPasswordClick}
loginIncorrect={this.state.loginIncorrect}
hsUrl={this.state.enteredHomeserverUrl}
/>
);
case 'm.login.cas':
@ -303,7 +304,7 @@ module.exports = React.createClass({
}
return (
<div>
{ _t('Sorry, this homeserver is using a login which is not recognised ')}({step})
{ _t('Sorry, this homeserver is using a login which is not recognised ') }({ step })
</div>
);
}
@ -333,19 +334,19 @@ module.exports = React.createClass({
const ServerConfig = sdk.getComponent("login.ServerConfig");
const loader = this.state.busy ? <div className="mx_Login_loader"><Loader /></div> : null;
var loginAsGuestJsx;
let loginAsGuestJsx;
if (this.props.enableGuest) {
loginAsGuestJsx =
<a className="mx_Login_create" onClick={this._onLoginAsGuestClick} href="#">
{ _t('Login as guest')}
{ _t('Login as guest') }
</a>;
}
var returnToAppJsx;
let returnToAppJsx;
if (this.props.onCancelClick) {
returnToAppJsx =
<a className="mx_Login_create" onClick={this.props.onCancelClick} href="#">
{ _t('Return to app')}
{ _t('Return to app') }
</a>;
}
@ -354,7 +355,7 @@ module.exports = React.createClass({
<div className="mx_Login_box">
<LoginHeader />
<div>
<h2>{ _t('Sign in')}
<h2>{ _t('Sign in') }
{ loader }
</h2>
{ this.componentForStep(this.state.currentFlow) }
@ -365,12 +366,12 @@ module.exports = React.createClass({
defaultHsUrl={this.props.defaultHsUrl}
defaultIsUrl={this.props.defaultIsUrl}
onServerConfigChange={this.onServerConfigChange}
delayTimeMs={1000}/>
delayTimeMs={1000} />
<div className="mx_Login_error">
{ this.state.errorText }
</div>
<a className="mx_Login_create" onClick={this.props.onRegisterClick} href="#">
{ _t('Create an account')}
{ _t('Create an account') }
</a>
{ loginAsGuestJsx }
{ returnToAppJsx }
@ -380,5 +381,5 @@ module.exports = React.createClass({
</div>
</div>
);
}
},
});

View file

@ -25,14 +25,14 @@ module.exports = React.createClass({
displayName: 'PostRegistration',
propTypes: {
onComplete: React.PropTypes.func.isRequired
onComplete: React.PropTypes.func.isRequired,
},
getInitialState: function() {
return {
avatarUrl: null,
errorString: null,
busy: false
busy: false,
};
},
@ -40,26 +40,26 @@ module.exports = React.createClass({
// There is some assymetry between ChangeDisplayName and ChangeAvatar,
// as ChangeDisplayName will auto-get the name but ChangeAvatar expects
// the URL to be passed to you (because it's also used for room avatars).
var cli = MatrixClientPeg.get();
const cli = MatrixClientPeg.get();
this.setState({busy: true});
var self = this;
const self = this;
cli.getProfileInfo(cli.credentials.userId).done(function(result) {
self.setState({
avatarUrl: MatrixClientPeg.get().mxcUrlToHttp(result.avatar_url),
busy: false
busy: false,
});
}, function(error) {
self.setState({
errorString: _t("Failed to fetch avatar URL"),
busy: false
busy: false,
});
});
},
render: function() {
var ChangeDisplayName = sdk.getComponent('settings.ChangeDisplayName');
var ChangeAvatar = sdk.getComponent('settings.ChangeAvatar');
var LoginHeader = sdk.getComponent('login.LoginHeader');
const ChangeDisplayName = sdk.getComponent('settings.ChangeDisplayName');
const ChangeAvatar = sdk.getComponent('settings.ChangeAvatar');
const LoginHeader = sdk.getComponent('login.LoginHeader');
return (
<div className="mx_Login">
<div className="mx_Login_box">
@ -71,10 +71,10 @@ module.exports = React.createClass({
<ChangeAvatar
initialAvatarUrl={this.state.avatarUrl} />
<button onClick={this.props.onComplete}>{ _t('Continue') }</button>
{this.state.errorString}
{ this.state.errorString }
</div>
</div>
</div>
);
}
},
});

View file

@ -57,7 +57,7 @@ module.exports = React.createClass({
// registration shouldn't know or care how login is done.
onLoginClick: React.PropTypes.func.isRequired,
onCancelClick: React.PropTypes.func
onCancelClick: React.PropTypes.func,
},
getInitialState: function() {
@ -121,7 +121,7 @@ module.exports = React.createClass({
},
onServerConfigChange: function(config) {
let newState = {};
const newState = {};
if (config.hsUrl !== undefined) {
newState.hsUrl = config.hsUrl;
}
@ -195,7 +195,7 @@ module.exports = React.createClass({
this._rtsClient.getTeam(teamToken).then((team) => {
console.log(
`User successfully registered with team ${team.name}`
`User successfully registered with team ${team.name}`,
);
if (!team.rooms) {
return;
@ -223,7 +223,7 @@ module.exports = React.createClass({
deviceId: response.device_id,
homeserverUrl: this._matrixClient.getHomeserverUrl(),
identityServerUrl: this._matrixClient.getIdentityServerUrl(),
accessToken: response.access_token
accessToken: response.access_token,
}, teamToken);
}).then((cli) => {
return this._setupPushers(cli);
@ -253,7 +253,7 @@ module.exports = React.createClass({
},
onFormValidationFailed: function(errCode) {
var errMsg;
let errMsg;
switch (errCode) {
case "RegistrationForm.ERR_PASSWORD_MISSING":
errMsg = _t('Missing password.');
@ -282,7 +282,7 @@ module.exports = React.createClass({
break;
}
this.setState({
errorText: errMsg
errorText: errMsg,
});
},
@ -316,7 +316,7 @@ module.exports = React.createClass({
emailAddress: this.state.formVals.email,
phoneCountry: this.state.formVals.phoneCountry,
phoneNumber: this.state.formVals.phoneNumber,
}
};
},
render: function() {
@ -346,7 +346,7 @@ module.exports = React.createClass({
} else {
let errorSection;
if (this.state.errorText) {
errorSection = <div className="mx_Login_error">{this.state.errorText}</div>;
errorSection = <div className="mx_Login_error">{ this.state.errorText }</div>;
}
registerBody = (
<div>
@ -362,7 +362,7 @@ module.exports = React.createClass({
onRegisterClick={this.onFormSubmit}
onTeamSelected={this.onTeamSelected}
/>
{errorSection}
{ errorSection }
<ServerConfig ref="serverConfig"
withToggleButton={true}
customHsUrl={this.props.customHsUrl}
@ -380,7 +380,7 @@ module.exports = React.createClass({
if (this.props.onCancelClick) {
returnToAppJsx = (
<a className="mx_Login_create" onClick={this.props.onCancelClick} href="#">
{_t('Return to app')}
{ _t('Return to app') }
</a>
);
}
@ -393,15 +393,15 @@ module.exports = React.createClass({
this.state.teamSelected.domain + "/icon.png" :
null}
/>
<h2>{_t('Create an account')}</h2>
{registerBody}
<h2>{ _t('Create an account') }</h2>
{ registerBody }
<a className="mx_Login_create" onClick={this.props.onLoginClick} href="#">
{_t('I already have an account')}
{ _t('I already have an account') }
</a>
{returnToAppJsx}
{ returnToAppJsx }
<LoginFooter />
</div>
</div>
);
}
},
});

View file

@ -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 its 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} />
);
}
}
},
});

View file

@ -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} />
);
}
},
});

View file

@ -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>
);
}
},
});

View file

@ -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>
);
}
},
});

View file

@ -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} />
);
}
},
});

View file

@ -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) {

View file

@ -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 }

View 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>
);
},
});

View file

@ -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>
);

View file

@ -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>
);
},

View file

@ -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">

View file

@ -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

View file

@ -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);
}

View file

@ -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>
);
}
},
});

View file

@ -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>
);
}
},
});

View file

@ -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>
);
}
},
});

View file

@ -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}

View file

@ -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>
);
}

View file

@ -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>

View file

@ -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,
};

View file

@ -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;
}
},
});

View file

@ -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}

View file

@ -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>
);

View file

@ -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}

View file

@ -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>;
}
}

View file

@ -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">&nbsp;</div> : null}
{expandedEvents}
{ toggleButton }
{ summaryContainer }
{ expanded ? <div className="mx_MemberEventListSummary_line">&nbsp;</div> : null }
{ expandedEvents }
</div>
);
},

View file

@ -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>
);
}
},
});

View file

@ -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>
);
}
},
});

View file

@ -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}

View file

@ -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}

View file

@ -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}

View file

@ -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

View file

@ -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>
);
}
},
});

View file

@ -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;
}

View file

@ -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");

View file

@ -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>
);
}
},
});

View file

@ -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>
);
}
},
});

View file

@ -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,
};

View file

@ -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>
);
}
},
});

View file

@ -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;
}

View file

@ -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>
);
}
},
});

View file

@ -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>
);

View file

@ -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.&nbsp;
Email us on&nbsp;
<a href={"mailto:" + this.props.teamsConfig.supportEmail}>
{this.props.teamsConfig.supportEmail}
{ this.props.teamsConfig.supportEmail }
</a>&nbsp;
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>
);
}
},
});

View file

@ -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>
&nbsp;&nbsp;
<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>
);
}
},
});

View file

@ -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>
);
}

View file

@ -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>;

View file

@ -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>
);
}

View file

@ -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>
);

View file

@ -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) {

View file

@ -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,12 +59,12 @@ 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 :((
@ -79,11 +79,11 @@ module.exports = React.createClass({
(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>

View file

@ -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,27 @@ 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, {});
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 +385,7 @@ module.exports = React.createClass({
className="mx_MEmoteBody_sender"
onClick={this.onEmoteSenderClick}
>
{name}
{ name }
</EmojiText>
&nbsp;
{ body }

View file

@ -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>
);
},
});

View file

@ -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>
);

View file

@ -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"],
@ -41,21 +41,21 @@ 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>
);
}
},
});

View file

@ -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>
);
}
},
});

View file

@ -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;
}

View file

@ -83,9 +83,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 +99,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}) }
&nbsp;
{joinNode}
{ joinNode }
</div>
);
}

View file

@ -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>
);
}
},
});

View file

@ -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() }

View file

@ -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>
);
}
},
});

View file

@ -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} />

View file

@ -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>
);
@ -633,7 +630,7 @@ module.exports = withMatrixClient(React.createClass({
if (this.props.member.userId !== this.props.matrixClient.getUserId()) {
ignoreButton = (
<AccessibleButton onClick={this.onIgnoreToggle} className="mx_MemberInfo_field">
{this.state.isIgnoring ? _t("Unignore") : _t("Ignore")}
{ this.state.isIgnoring ? _t("Unignore") : _t("Ignore") }
</AccessibleButton>
);
}
@ -644,14 +641,14 @@ module.exports = withMatrixClient(React.createClass({
<div>
<h3>{ _t("User Options") }</h3>
<div className="mx_MemberInfo_buttons">
{ignoreButton}
{ ignoreButton }
</div>
</div>
);
},
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);
@ -675,7 +672,7 @@ module.exports = withMatrixClient(React.createClass({
highlight={highlight}
isInvite={me.membership == "invite"}
onClick={this.onRoomTileClick}
/>
/>,
);
}
}
@ -696,14 +693,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) {
@ -712,7 +709,7 @@ module.exports = withMatrixClient(React.createClass({
kickButton = (
<AccessibleButton className="mx_MemberInfo_field"
onClick={this.onKick}>
{kickLabel}
{ kickLabel }
</AccessibleButton>
);
}
@ -724,7 +721,7 @@ module.exports = withMatrixClient(React.createClass({
banButton = (
<AccessibleButton className="mx_MemberInfo_field"
onClick={this.onBanOrUnban}>
{label}
{ label }
</AccessibleButton>
);
}
@ -733,31 +730,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>;
}
@ -767,35 +764,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>
@ -811,5 +808,5 @@ module.exports = withMatrixClient(React.createClass({
</GeminiScrollbar>
</div>
);
}
},
}));

View file

@ -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
}
@ -153,11 +153,11 @@ module.exports = React.createClass({
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,17 +175,17 @@ 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 ((ConferenceHandler && !ConferenceHandler.isConferenceUser(user_id)) || !ConferenceHandler) {
@ -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;
}
@ -336,25 +333,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 +399,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 +412,9 @@ module.exports = React.createClass({
getChildren={this._getChildrenJoined}
getChildCount={this._getChildCountJoined}
/>
{invitedSection}
{ invitedSection }
</GeminiScrollbar>
</div>
);
}
},
});

View file

@ -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} />
);
}
},
});

View file

@ -89,13 +89,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 +105,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,16 +271,16 @@ 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>;
}
@ -289,12 +289,12 @@ export default class MessageComposer extends React.Component {
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"/>
<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"/>
<TintableSvg src="img/icons-show-apps.svg" width="35" height="35" />
</div>;
}
}
@ -308,8 +308,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 +363,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 +375,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" />

View file

@ -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>
);

View file

@ -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>
);
}
}
},
});

View file

@ -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',

View file

@ -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>
);
}
},
});

View file

@ -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>
);

View file

@ -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>
);
}
},
});

View file

@ -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>
);
}
},
});

View file

@ -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;
}
},
});

View file

@ -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" />
);
},

View file

@ -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>);
},
});

View file

@ -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;

View file

@ -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"

View file

@ -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} />
);
}
},
});

View file

@ -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>
);
}
}))
},
}));

View file

@ -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: {
@ -59,25 +59,25 @@ module.exports = React.createClass({
return;
}
this.setState({
avatarUrl: newProps.initialAvatarUrl
avatarUrl: newProps.initialAvatarUrl,
});
},
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 +87,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 +106,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 +141,9 @@ module.exports = React.createClass({
return (
<div>
<div className={this.props.className}>
{avatarImg}
{ avatarImg }
</div>
{uploadSection}
{ uploadSection }
</div>
);
case this.Phases.Uploading:
@ -152,5 +152,5 @@ module.exports = React.createClass({
<Loader />
);
}
}
},
});

View file

@ -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} />
);
}
},
});

View file

@ -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>
);
}
}
},
});

View file

@ -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>
);
}

Some files were not shown because too many files have changed in this diff Show more