Merge branch 'develop' into travis/well-known

This commit is contained in:
Travis Ralston 2018-11-21 13:30:57 -07:00
commit 6f0f930e0a
140 changed files with 4922 additions and 683 deletions

View file

@ -33,12 +33,12 @@ module.exports = React.createClass({
},
getInitialState: function() {
return({
directoryHover : false,
roomsHover : false,
return ({
directoryHover: false,
roomsHover: false,
homeHover: false,
peopleHover : false,
settingsHover : false,
peopleHover: false,
settingsHover: false,
});
},
@ -145,7 +145,7 @@ module.exports = React.createClass({
// Get the label/tooltip to show
getLabel: function(label, show) {
if (show) {
var RoomTooltip = sdk.getComponent("rooms.RoomTooltip");
const RoomTooltip = sdk.getComponent("rooms.RoomTooltip");
return <RoomTooltip className="mx_BottomLeftMenu_tooltip" label={label} />;
}
},

View file

@ -16,18 +16,18 @@ limitations under the License.
'use strict';
var React = require('react');
const React = require('react');
import { _t } from '../../languageHandler';
module.exports = React.createClass({
displayName: 'CompatibilityPage',
propTypes: {
onAccept: React.PropTypes.func
onAccept: React.PropTypes.func,
},
getDefaultProps: function() {
return {
onAccept: function() {} // NOP
onAccept: function() {}, // NOP
};
},
@ -36,7 +36,6 @@ module.exports = React.createClass({
},
render: function() {
return (
<div className="mx_CompatibilityPage">
<div className="mx_CompatibilityPage_box">
@ -69,5 +68,5 @@ module.exports = React.createClass({
</div>
</div>
);
}
},
});

View file

@ -36,10 +36,10 @@ module.exports = React.createClass({
},
phases: {
CONFIG: "CONFIG", // We're waiting for user to configure and hit create.
CREATING: "CREATING", // We're sending the request.
CREATED: "CREATED", // We successfully created the room.
ERROR: "ERROR", // There was an error while trying to create room.
CONFIG: "CONFIG", // We're waiting for user to configure and hit create.
CREATING: "CREATING", // We're sending the request.
CREATED: "CREATED", // We successfully created the room.
ERROR: "ERROR", // There was an error while trying to create room.
},
getDefaultProps: function() {

View file

@ -746,14 +746,38 @@ export default React.createClass({
});
},
_leaveGroupWarnings: function() {
const warnings = [];
if (this.state.isUserPrivileged) {
warnings.push((
<span className="warning">
{ " " /* Whitespace, otherwise the sentences get smashed together */ }
{ _t("You are an administrator of this community. You will not be " +
"able to rejoin without an invite from another administrator.") }
</span>
));
}
return warnings;
},
_onLeaveClick: function() {
const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog");
const warnings = this._leaveGroupWarnings();
Modal.createTrackedDialog('Leave Group', '', QuestionDialog, {
title: _t("Leave Community"),
description: _t("Leave %(groupName)s?", {groupName: this.props.groupId}),
description: (
<span>
{ _t("Leave %(groupName)s?", {groupName: this.props.groupId}) }
{ warnings }
</span>
),
button: _t("Leave"),
danger: true,
onFinished: async (confirmed) => {
danger: this.state.isUserPrivileged,
onFinished: async(confirmed) => {
if (!confirmed) return;
this.setState({membershipBusy: true});

View file

@ -23,6 +23,8 @@ import request from 'browser-request';
import { _t } from '../../languageHandler';
import sanitizeHtml from 'sanitize-html';
import sdk from '../../index';
import { MatrixClient } from 'matrix-js-sdk';
import dis from '../../dispatcher';
class HomePage extends React.Component {
static displayName = 'HomePage';
@ -37,6 +39,10 @@ class HomePage extends React.Component {
homePageUrl: PropTypes.string,
};
static contextTypes = {
matrixClient: PropTypes.instanceOf(MatrixClient),
};
state = {
iframeSrc: '',
page: '',
@ -52,15 +58,14 @@ class HomePage extends React.Component {
if (this.props.teamToken && this.props.teamServerUrl) {
this.setState({
iframeSrc: `${this.props.teamServerUrl}/static/${this.props.teamToken}/home.html`
iframeSrc: `${this.props.teamServerUrl}/static/${this.props.teamToken}/home.html`,
});
}
else {
} else {
// we use request() to inline the homepage into the react component
// so that it can inherit CSS and theming easily rather than mess around
// with iframes and trying to synchronise document.stylesheets.
let src = this.props.homePageUrl || 'home.html';
const src = this.props.homePageUrl || 'home.html';
request(
{ method: "GET", url: src },
@ -77,7 +82,7 @@ class HomePage extends React.Component {
body = body.replace(/_t\(['"]([\s\S]*?)['"]\)/mg, (match, g1)=>this.translate(g1));
this.setState({ page: body });
}
},
);
}
}
@ -86,18 +91,55 @@ class HomePage extends React.Component {
this._unmounted = true;
}
onLoginClick() {
dis.dispatch({ action: 'start_login' });
}
onRegisterClick() {
dis.dispatch({ action: 'start_registration' });
}
render() {
if (this.state.iframeSrc) {
return (
<div className="mx_HomePage">
<iframe src={ this.state.iframeSrc } />
let guestWarning = "";
if (this.context.matrixClient.isGuest()) {
guestWarning = (
<div className="mx_HomePage_guest_warning">
<img src="img/warning.svg" width="24" height="23" />
<div>
<div>
{ _t("You are currently using Riot anonymously as a guest.") }
</div>
<div>
{ _t(
'If you would like to create a Matrix account you can <a>register</a> now.',
{},
{ 'a': (sub) => <a href="#" onClick={this.onRegisterClick}>{ sub }</a> },
) }
</div>
<div>
{ _t(
'If you already have a Matrix account you can <a>log in</a> instead.',
{},
{ 'a': (sub) => <a href="#" onClick={this.onLoginClick}>{ sub }</a> },
) }
</div>
</div>
</div>
);
}
else {
if (this.state.iframeSrc) {
return (
<div className="mx_HomePage">
{ guestWarning }
<iframe src={ this.state.iframeSrc } />
</div>
);
} else {
const GeminiScrollbarWrapper = sdk.getComponent("elements.GeminiScrollbarWrapper");
return (
<GeminiScrollbarWrapper autoshow={true} className="mx_HomePage">
{ guestWarning }
<div className="mx_HomePage_body" dangerouslySetInnerHTML={{ __html: this.state.page }}>
</div>
</GeminiScrollbarWrapper>
@ -106,4 +148,4 @@ class HomePage extends React.Component {
}
}
module.exports = HomePage;
module.exports = HomePage;

View file

@ -68,6 +68,11 @@ export default React.createClass({
// If true, poll to see if the auth flow has been completed
// out-of-band
poll: PropTypes.bool,
// If true, components will be told that the 'Continue' button
// is managed by some other party and should not be managed by
// the component itself.
continueIsManaged: PropTypes.bool,
},
getInitialState: function() {
@ -128,6 +133,12 @@ export default React.createClass({
}
},
tryContinue: function() {
if (this.refs.stageComponent && this.refs.stageComponent.tryContinue) {
this.refs.stageComponent.tryContinue();
}
},
_authStateUpdated: function(stageType, stageState) {
const oldStage = this.state.authStage;
this.setState({
@ -192,6 +203,7 @@ export default React.createClass({
fail={this._onAuthStageFailed}
setEmailSid={this._setEmailSid}
makeRegistrationUrl={this.props.makeRegistrationUrl}
showContinue={!this.props.continueIsManaged}
/>
);
},

View file

@ -28,7 +28,7 @@ import VectorConferenceHandler from '../../VectorConferenceHandler';
import SettingsStore from '../../settings/SettingsStore';
var LeftPanel = React.createClass({
const LeftPanel = React.createClass({
displayName: 'LeftPanel',
// NB. If you add props, don't forget to update
@ -181,14 +181,8 @@ var LeftPanel = React.createClass({
const BottomLeftMenu = sdk.getComponent('structures.BottomLeftMenu');
const CallPreview = sdk.getComponent('voip.CallPreview');
let topBox;
if (this.context.matrixClient.isGuest()) {
const LoginBox = sdk.getComponent('structures.LoginBox');
topBox = <LoginBox collapsed={ this.props.collapsed }/>;
} else {
const SearchBox = sdk.getComponent('structures.SearchBox');
topBox = <SearchBox collapsed={ this.props.collapsed } onSearch={ this.onSearch } />;
}
const SearchBox = sdk.getComponent('structures.SearchBox');
const topBox = <SearchBox collapsed={ this.props.collapsed } onSearch={ this.onSearch } />;
const classes = classNames(
"mx_LeftPanel",
@ -220,11 +214,11 @@ var LeftPanel = React.createClass({
collapsed={this.props.collapsed}
searchFilter={this.state.searchFilter}
ConferenceHandler={VectorConferenceHandler} />
<BottomLeftMenu collapsed={this.props.collapsed}/>
<BottomLeftMenu collapsed={this.props.collapsed} />
</aside>
</div>
);
}
},
});
module.exports = LeftPanel;

View file

@ -64,6 +64,9 @@ const LoggedInView = React.createClass({
teamToken: PropTypes.string,
// Used by the RoomView to handle joining rooms
viaServers: PropTypes.arrayOf(PropTypes.string),
// and lots and lots of other stuff.
},
@ -186,13 +189,13 @@ const LoggedInView = React.createClass({
_updateServerNoticeEvents: async function() {
const roomLists = RoomListStore.getRoomLists();
if (!roomLists['m.server_notice']) return [];
const pinnedEvents = [];
for (const room of roomLists['m.server_notice']) {
const pinStateEvent = room.currentState.getStateEvents("m.room.pinned_events", "");
if (!pinStateEvent || !pinStateEvent.getContent().pinned) continue;
const pinnedEventIds = pinStateEvent.getContent().pinned.slice(0, MAX_PINNED_NOTICES_PER_ROOM);
for (const eventId of pinnedEventIds) {
const timeline = await this._matrixClient.getEventTimeline(room.getUnfilteredTimelineSet(), eventId, 0);
@ -204,7 +207,7 @@ const LoggedInView = React.createClass({
serverNoticeEvents: pinnedEvents,
});
},
_onKeyDown: function(ev) {
/*
@ -389,6 +392,7 @@ const LoggedInView = React.createClass({
onRegistered={this.props.onRegistered}
thirdPartyInvite={this.props.thirdPartyInvite}
oobData={this.props.roomOobData}
viaServers={this.props.viaServers}
eventPixelOffset={this.props.initialEventPixelOffset}
key={this.props.currentRoomId || 'roomview'}
disabled={this.props.middleDisabled}

View file

@ -1,5 +1,6 @@
/*
Copyright 2017 Vector Creations Ltd
Copyright 2018 New Vector Ltd
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -16,31 +17,15 @@ limitations under the License.
'use strict';
var React = require('react');
const React = require('react');
import { _t } from '../../languageHandler';
var sdk = require('../../index')
var dis = require('../../dispatcher');
var rate_limited_func = require('../../ratelimitedfunc');
var AccessibleButton = require('../../components/views/elements/AccessibleButton');
const dis = require('../../dispatcher');
const AccessibleButton = require('../../components/views/elements/AccessibleButton');
module.exports = React.createClass({
displayName: 'LoginBox',
propTypes: {
collapsed: React.PropTypes.bool,
},
onToggleCollapse: function(show) {
if (show) {
dis.dispatch({
action: 'show_left_panel',
});
}
else {
dis.dispatch({
action: 'hide_left_panel',
});
}
},
onLoginClick: function() {
@ -52,42 +37,21 @@ module.exports = React.createClass({
},
render: function() {
var TintableSvg = sdk.getComponent('elements.TintableSvg');
var toggleCollapse;
if (this.props.collapsed) {
toggleCollapse =
<AccessibleButton className="mx_SearchBox_maximise" onClick={ this.onToggleCollapse.bind(this, true) }>
<TintableSvg src="img/maximise.svg" width="10" height="16" alt="Expand panel"/>
const loginButton = (
<div className="mx_LoginBox_loginButton_wrapper">
<AccessibleButton className="mx_LoginBox_loginButton" element="button" onClick={this.onLoginClick}>
{ _t("Login") }
</AccessibleButton>
}
else {
toggleCollapse =
<AccessibleButton className="mx_SearchBox_minimise" onClick={ this.onToggleCollapse.bind(this, false) }>
<TintableSvg src="img/minimise.svg" width="10" height="16" alt="Collapse panel"/>
<AccessibleButton className="mx_LoginBox_registerButton" element="button" onClick={this.onRegisterClick}>
{ _t("Register") }
</AccessibleButton>
}
var loginButton;
if (!this.props.collapsed) {
loginButton = (
<div className="mx_LoginBox_loginButton_wrapper">
<AccessibleButton className="mx_LoginBox_loginButton" element="button" onClick={this.onLoginClick}>
{ _t("Login") }
</AccessibleButton>
<AccessibleButton className="mx_LoginBox_registerButton" element="button" onClick={this.onRegisterClick}>
{ _t("Register") }
</AccessibleButton>
</div>
);
}
var self = this;
return (
<div className="mx_SearchBox mx_LoginBox">
{ loginButton }
{ toggleCollapse }
</div>
);
}
return (
<div className="mx_LoginBox">
{ loginButton }
</div>
);
},
});

View file

@ -840,6 +840,7 @@ export default React.createClass({
page_type: PageTypes.RoomView,
thirdPartyInvite: roomInfo.third_party_invite,
roomOobData: roomInfo.oob_data,
viaServers: roomInfo.via_servers,
};
if (roomInfo.room_alias) {
@ -1034,6 +1035,7 @@ export default React.createClass({
{ warnings }
</span>
),
button: _t("Leave"),
onFinished: (shouldLeave) => {
if (shouldLeave) {
const d = MatrixClientPeg.get().leave(roomId);
@ -1373,6 +1375,7 @@ export default React.createClass({
cli.on("crypto.roomKeyRequestCancellation", (req) => {
krh.handleKeyRequestCancellation(req);
});
cli.on("Room", (room) => {
if (MatrixClientPeg.get().isCryptoEnabled()) {
const blacklistEnabled = SettingsStore.getValueAt(
@ -1406,8 +1409,8 @@ export default React.createClass({
// Fire the tinter right on startup to ensure the default theme is applied
// A later sync can/will correct the tint to be the right value for the user
const color_scheme = SettingsStore.getValue("roomColor");
Tinter.tint(color_scheme.primary_color, color_scheme.secondary_color);
const colorScheme = SettingsStore.getValue("roomColor");
Tinter.tint(colorScheme.primary_color, colorScheme.secondary_color);
},
/**
@ -1488,9 +1491,21 @@ export default React.createClass({
inviterName: params.inviter_name,
};
// on our URLs there might be a ?via=matrix.org or similar to help
// joins to the room succeed. We'll pass these through as an array
// to other levels. If there's just one ?via= then params.via is a
// single string. If someone does something like ?via=one.com&via=two.com
// then params.via is an array of strings.
let via = [];
if (params.via) {
if (typeof(params.via) === 'string') via = [params.via];
else via = params.via;
}
const payload = {
action: 'view_room',
event_id: eventId,
via_servers: via,
// If an event ID is given in the URL hash, notify RoomViewStore to mark
// it as highlighted, which will propagate to RoomView and highlight the
// associated EventTile.

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 ContentRepo = require("matrix-js-sdk").ContentRepo;
var Modal = require('../../Modal');
var sdk = require('../../index');
var dis = require('../../dispatcher');
const MatrixClientPeg = require('../../MatrixClientPeg');
const ContentRepo = require("matrix-js-sdk").ContentRepo;
const Modal = require('../../Modal');
const sdk = require('../../index');
const dis = require('../../dispatcher');
var linkify = require('linkifyjs');
var linkifyString = require('linkifyjs/string');
var linkifyMatrix = require('../../linkify-matrix');
var sanitizeHtml = require('sanitize-html');
const linkify = require('linkifyjs');
const linkifyString = require('linkifyjs/string');
const linkifyMatrix = require('../../linkify-matrix');
const sanitizeHtml = require('sanitize-html');
import Promise from 'bluebird';
import { _t } from '../../languageHandler';
@ -46,7 +46,7 @@ module.exports = React.createClass({
getDefaultProps: function() {
return {
config: {},
}
};
},
getInitialState: function() {
@ -58,7 +58,7 @@ module.exports = React.createClass({
includeAll: false,
roomServer: null,
filterString: null,
}
};
},
componentWillMount: function() {
@ -134,13 +134,12 @@ module.exports = React.createClass({
opts.include_all_networks = true;
}
if (this.nextBatch) opts.since = this.nextBatch;
if (my_filter_string) opts.filter = { generic_search_term: my_filter_string } ;
if (my_filter_string) opts.filter = { generic_search_term: my_filter_string };
return MatrixClientPeg.get().publicRooms(opts).then((data) => {
if (
my_filter_string != this.state.filterString ||
my_server != this.state.roomServer ||
my_next_batch != this.nextBatch)
{
my_next_batch != this.nextBatch) {
// if the filter or server has changed since this request was sent,
// throw away the result (don't even clear the busy flag
// since we must still have a request in flight)
@ -163,8 +162,7 @@ module.exports = React.createClass({
if (
my_filter_string != this.state.filterString ||
my_server != this.state.roomServer ||
my_next_batch != this.nextBatch)
{
my_next_batch != this.nextBatch) {
// as above: we don't care about errors for old
// requests either
return;
@ -177,10 +175,10 @@ module.exports = React.createClass({
this.setState({ loading: false });
console.error("Failed to get publicRooms: %s", JSON.stringify(err));
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
Modal.createTrackedDialog('Failed to get public room list', '', ErrorDialog, {
title: _t('Failed to get public room list'),
description: ((err && err.message) ? err.message : _t('The server may be unavailable or overloaded'))
description: ((err && err.message) ? err.message : _t('The server may be unavailable or overloaded')),
});
});
},
@ -193,13 +191,13 @@ module.exports = React.createClass({
* this needs SPEC-417.
*/
removeFromDirectory: function(room) {
var alias = get_display_alias_for_room(room);
var name = room.name || alias || _t('Unnamed room');
const alias = get_display_alias_for_room(room);
const name = room.name || alias || _t('Unnamed room');
var QuestionDialog = sdk.getComponent("dialogs.QuestionDialog");
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog");
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
var desc;
let desc;
if (alias) {
desc = _t('Delete the room alias %(alias)s and remove %(name)s from the directory?', {alias: alias, name: name});
} else {
@ -212,9 +210,9 @@ module.exports = React.createClass({
onFinished: (should_delete) => {
if (!should_delete) return;
var Loader = sdk.getComponent("elements.Spinner");
var modal = Modal.createDialog(Loader);
var step = _t('remove %(name)s from the directory.', {name: name});
const Loader = sdk.getComponent("elements.Spinner");
const modal = Modal.createDialog(Loader);
let step = _t('remove %(name)s from the directory.', {name: name});
MatrixClientPeg.get().setRoomDirectoryVisibility(room.room_id, 'private').then(() => {
if (!alias) return;
@ -229,10 +227,10 @@ module.exports = React.createClass({
console.error("Failed to " + step + ": " + err);
Modal.createTrackedDialog('Remove from Directory Error', '', ErrorDialog, {
title: _t('Error'),
description: ((err && err.message) ? err.message : _t('The server may be unavailable or overloaded'))
description: ((err && err.message) ? err.message : _t('The server may be unavailable or overloaded')),
});
});
}
},
});
},
@ -347,7 +345,7 @@ module.exports = React.createClass({
},
showRoom: function(room, room_alias) {
var payload = {action: 'view_room'};
const payload = {action: 'view_room'};
if (room) {
// Don't let the user view a room they won't be able to either
// peek or join: fail earlier so they don't have to click back
@ -383,16 +381,16 @@ module.exports = React.createClass({
},
getRows: function() {
var BaseAvatar = sdk.getComponent('avatars.BaseAvatar');
const BaseAvatar = sdk.getComponent('avatars.BaseAvatar');
if (!this.state.publicRooms) return [];
var rooms = this.state.publicRooms;
var rows = [];
var self = this;
var guestRead, guestJoin, perms;
for (var i = 0; i < rooms.length; i++) {
var name = rooms[i].name || get_display_alias_for_room(rooms[i]) || _t('Unnamed room');
const rooms = this.state.publicRooms;
const rows = [];
const self = this;
let guestRead; let guestJoin; let perms;
for (let i = 0; i < rooms.length; i++) {
const name = rooms[i].name || get_display_alias_for_room(rooms[i]) || _t('Unnamed room');
guestRead = null;
guestJoin = null;
@ -412,7 +410,7 @@ module.exports = React.createClass({
perms = <div className="mx_RoomDirectory_perms">{guestRead}{guestJoin}</div>;
}
var topic = rooms[i].topic || '';
let topic = rooms[i].topic || '';
topic = linkifyString(sanitizeHtml(topic));
rows.push(
@ -432,14 +430,14 @@ module.exports = React.createClass({
<div className="mx_RoomDirectory_name">{ name }</div>&nbsp;
{ perms }
<div className="mx_RoomDirectory_topic"
onClick={ function(e) { e.stopPropagation() } }
dangerouslySetInnerHTML={{ __html: topic }}/>
onClick={ function(e) { e.stopPropagation(); } }
dangerouslySetInnerHTML={{ __html: topic }} />
<div className="mx_RoomDirectory_alias">{ get_display_alias_for_room(rooms[i]) }</div>
</td>
<td className="mx_RoomDirectory_roomMemberCount">
{ rooms[i].num_joined_members }
</td>
</tr>
</tr>,
);
}
return rows;
@ -524,7 +522,7 @@ module.exports = React.createClass({
onFillRequest={ this.onFillRequest }
stickyBottom={false}
startAtBottom={false}
onResize={function(){}}
onResize={function() {}}
>
{ scrollpanel_content }
</ScrollPanel>;
@ -577,11 +575,11 @@ module.exports = React.createClass({
</div>
</div>
);
}
},
});
// Similar to matrix-react-sdk's MatrixTools.getDisplayAliasForRoom
// but works with the objects we get from the public room list
function get_display_alias_for_room(room) {
return room.canonical_alias || (room.aliases ? room.aliases[0] : "");
return room.canonical_alias || (room.aliases ? room.aliases[0] : "");
}

View file

@ -37,7 +37,7 @@ function getUnsentMessages(room) {
return room.getPendingEvents().filter(function(ev) {
return ev.status === Matrix.EventStatus.NOT_SENT;
});
};
}
module.exports = React.createClass({
displayName: 'RoomStatusBar',
@ -303,7 +303,7 @@ module.exports = React.createClass({
const errorIsMauError = Boolean(
this.state.syncStateData &&
this.state.syncStateData.error &&
this.state.syncStateData.error.errcode === 'M_RESOURCE_LIMIT_EXCEEDED'
this.state.syncStateData.error.errcode === 'M_RESOURCE_LIMIT_EXCEEDED',
);
return this.state.syncState === "ERROR" && !errorIsMauError;
},

View file

@ -88,6 +88,9 @@ module.exports = React.createClass({
// is the RightPanel collapsed?
collapsedRhs: PropTypes.bool,
// Servers the RoomView can use to try and assist joins
viaServers: PropTypes.arrayOf(PropTypes.string),
},
getInitialState: function() {
@ -678,8 +681,8 @@ module.exports = React.createClass({
if (!room) return;
console.log("Tinter.tint from updateTint");
const color_scheme = SettingsStore.getValue("roomColor", room.roomId);
Tinter.tint(color_scheme.primary_color, color_scheme.secondary_color);
const colorScheme = SettingsStore.getValue("roomColor", room.roomId);
Tinter.tint(colorScheme.primary_color, colorScheme.secondary_color);
},
onAccountData: function(event) {
@ -694,10 +697,10 @@ module.exports = React.createClass({
if (room.roomId == this.state.roomId) {
const type = event.getType();
if (type === "org.matrix.room.color_scheme") {
const color_scheme = event.getContent();
const colorScheme = event.getContent();
// XXX: we should validate the event
console.log("Tinter.tint from onRoomAccountData");
Tinter.tint(color_scheme.primary_color, color_scheme.secondary_color);
Tinter.tint(colorScheme.primary_color, colorScheme.secondary_color);
} else if (type === "org.matrix.room.preview_urls" || type === "im.vector.web.settings") {
// non-e2ee url previews are stored in legacy event type `org.matrix.room.preview_urls`
this._updatePreviewUrlVisibility(room);
@ -833,7 +836,7 @@ module.exports = React.createClass({
action: 'do_after_sync_prepared',
deferred_action: {
action: 'join_room',
opts: { inviteSignUrl: signUrl },
opts: { inviteSignUrl: signUrl, viaServers: this.props.viaServers },
},
});
@ -875,7 +878,7 @@ module.exports = React.createClass({
this.props.thirdPartyInvite.inviteSignUrl : undefined;
dis.dispatch({
action: 'join_room',
opts: { inviteSignUrl: signUrl },
opts: { inviteSignUrl: signUrl, viaServers: this.props.viaServers },
});
return Promise.resolve();
});
@ -1514,6 +1517,7 @@ module.exports = React.createClass({
canPreview={false} error={this.state.roomLoadError}
roomAlias={roomAlias}
spinner={this.state.joining}
spinnerState="joining"
inviterName={inviterName}
invitedEmail={invitedEmail}
room={this.state.room}
@ -1558,6 +1562,7 @@ module.exports = React.createClass({
inviterName={inviterName}
canPreview={false}
spinner={this.state.joining}
spinnerState="joining"
room={this.state.room}
/>
</div>
@ -1645,6 +1650,7 @@ module.exports = React.createClass({
onForgetClick={this.onForgetClick}
onRejectClick={this.onRejectThreepidInviteButtonClicked}
spinner={this.state.joining}
spinnerState="joining"
inviterName={inviterName}
invitedEmail={invitedEmail}
canPreview={this.state.canPeek}
@ -1667,10 +1673,10 @@ module.exports = React.createClass({
</AuxPanel>
);
let messageComposer, searchInfo;
let messageComposer; let searchInfo;
const canSpeak = (
// joined and not showing search results
myMembership == 'join' && !this.state.searchResults
myMembership === 'join' && !this.state.searchResults
);
if (canSpeak) {
messageComposer =
@ -1684,6 +1690,11 @@ module.exports = React.createClass({
/>;
}
if (MatrixClientPeg.get().isGuest()) {
const LoginBox = sdk.getComponent('structures.LoginBox');
messageComposer = <LoginBox />;
}
// TODO: Why aren't we storing the term/scope/count in this format
// in this.state if this is what RoomHeader desires?
if (this.state.searchResults) {
@ -1695,7 +1706,7 @@ module.exports = React.createClass({
}
if (inCall) {
let zoomButton, voiceMuteButton, videoMuteButton;
let zoomButton; let voiceMuteButton; let videoMuteButton;
if (call.type === "video") {
zoomButton = (

View file

@ -72,7 +72,7 @@ module.exports = React.createClass({
function() {
this.props.onSearch(this.refs.search.value);
},
100
100,
),
onToggleCollapse: function(show) {
@ -80,8 +80,7 @@ module.exports = React.createClass({
dis.dispatch({
action: 'show_left_panel',
});
}
else {
} else {
dis.dispatch({
action: 'hide_left_panel',
});
@ -103,25 +102,24 @@ module.exports = React.createClass({
},
render: function() {
var TintableSvg = sdk.getComponent('elements.TintableSvg');
const TintableSvg = sdk.getComponent('elements.TintableSvg');
var collapseTabIndex = this.refs.search && this.refs.search.value !== "" ? "-1" : "0";
const collapseTabIndex = this.refs.search && this.refs.search.value !== "" ? "-1" : "0";
var toggleCollapse;
let toggleCollapse;
if (this.props.collapsed) {
toggleCollapse =
<AccessibleButton className="mx_SearchBox_maximise" tabIndex={collapseTabIndex} onClick={ this.onToggleCollapse.bind(this, true) }>
<TintableSvg src="img/maximise.svg" width="10" height="16" alt={ _t("Expand panel") }/>
</AccessibleButton>
}
else {
<TintableSvg src="img/maximise.svg" width="10" height="16" alt={ _t("Expand panel") } />
</AccessibleButton>;
} else {
toggleCollapse =
<AccessibleButton className="mx_SearchBox_minimise" tabIndex={collapseTabIndex} onClick={ this.onToggleCollapse.bind(this, false) }>
<TintableSvg src="img/minimise.svg" width="10" height="16" alt={ _t("Collapse panel") }/>
</AccessibleButton>
<TintableSvg src="img/minimise.svg" width="10" height="16" alt={ _t("Collapse panel") } />
</AccessibleButton>;
}
var searchControls;
let searchControls;
if (!this.props.collapsed) {
searchControls = [
this.state.searchTerm.length > 0 ?
@ -148,16 +146,16 @@ module.exports = React.createClass({
onChange={ this.onChange }
onKeyDown={ this._onKeyDown }
placeholder={ _t('Filter room names') }
/>
/>,
];
}
var self = this;
const self = this;
return (
<div className="mx_SearchBox">
{ searchControls }
{ toggleCollapse }
</div>
);
}
},
});

View file

@ -829,7 +829,7 @@ var TimelinePanel = React.createClass({
// 4. Also, if pos === null, the event might not be paginated - show the unread bar
const pos = this.getReadMarkerPosition();
return this.state.readMarkerEventId !== null && // 1.
this.state.readMarkerEventId !== this._getCurrentReadReceipt() && // 2.
this.state.readMarkerEventId !== this._getCurrentReadReceipt() && // 2.
(pos < 0 || pos === null); // 3., 4.
},

View file

@ -82,6 +82,9 @@ const SIMPLE_SETTINGS = [
{ id: "TagPanel.disableTagPanel" },
{ id: "enableWidgetScreenshots" },
{ id: "RoomSubList.showEmpty" },
{ id: "pinMentionedRooms" },
{ id: "pinUnreadRooms" },
{ id: "showDeveloperTools" },
];
// These settings must be defined in SettingsStore
@ -586,23 +589,21 @@ module.exports = React.createClass({
},
_onExportE2eKeysClicked: function() {
Modal.createTrackedDialogAsync('Export E2E Keys', '', (cb) => {
require.ensure(['../../async-components/views/dialogs/ExportE2eKeysDialog'], () => {
cb(require('../../async-components/views/dialogs/ExportE2eKeysDialog'));
}, "e2e-export");
}, {
matrixClient: MatrixClientPeg.get(),
});
Modal.createTrackedDialogAsync('Export E2E Keys', '',
import('../../async-components/views/dialogs/ExportE2eKeysDialog'),
{
matrixClient: MatrixClientPeg.get(),
},
);
},
_onImportE2eKeysClicked: function() {
Modal.createTrackedDialogAsync('Import E2E Keys', '', (cb) => {
require.ensure(['../../async-components/views/dialogs/ImportE2eKeysDialog'], () => {
cb(require('../../async-components/views/dialogs/ImportE2eKeysDialog'));
}, "e2e-export");
}, {
matrixClient: MatrixClientPeg.get(),
});
Modal.createTrackedDialogAsync('Import E2E Keys', '',
import('../../async-components/views/dialogs/ImportE2eKeysDialog'),
{
matrixClient: MatrixClientPeg.get(),
},
);
},
_renderGroupSettings: function() {
@ -736,6 +737,16 @@ module.exports = React.createClass({
</div>
);
}
let keyBackupSection;
if (SettingsStore.isFeatureEnabled("feature_keybackup")) {
const KeyBackupPanel = sdk.getComponent('views.settings.KeyBackupPanel');
keyBackupSection = <div className="mx_UserSettings_section">
<h3>{ _t("Key Backup") }</h3>
<KeyBackupPanel />
</div>;
}
return (
<div>
<h3>{ _t("Cryptography") }</h3>
@ -751,6 +762,7 @@ module.exports = React.createClass({
<div className="mx_UserSettings_section">
{ CRYPTO_SETTINGS.map( this._renderDeviceSetting ) }
</div>
{keyBackupSection}
</div>
);
},
@ -844,7 +856,7 @@ module.exports = React.createClass({
SettingsStore.getLabsFeatures().forEach((featureId) => {
// TODO: this ought to be a separate component so that we don't need
// to rebind the onChange each time we render
const onChange = async (e) => {
const onChange = async(e) => {
const checked = e.target.checked;
if (featureId === "feature_lazyloading") {
const confirmed = await this._onLazyLoadChanging(checked);
@ -1297,7 +1309,7 @@ module.exports = React.createClass({
// If the olmVersion is not defined then either crypto is disabled, or
// we are using a version old version of olm. We assume the former.
let olmVersionString = "<not-enabled>";
if (olmVersion !== undefined) {
if (olmVersion) {
olmVersionString = `${olmVersion[0]}.${olmVersion[1]}.${olmVersion[2]}`;
}

View file

@ -53,5 +53,5 @@ module.exports = React.createClass({
</SyntaxHighlight>
</div>
);
}
},
});

View file

@ -121,13 +121,12 @@ module.exports = React.createClass({
},
_onExportE2eKeysClicked: function() {
Modal.createTrackedDialogAsync('Export E2E Keys', 'Forgot Password', (cb) => {
require.ensure(['../../../async-components/views/dialogs/ExportE2eKeysDialog'], () => {
cb(require('../../../async-components/views/dialogs/ExportE2eKeysDialog'));
}, "e2e-export");
}, {
matrixClient: MatrixClientPeg.get(),
});
Modal.createTrackedDialogAsync('Export E2E Keys', 'Forgot Password',
import('../../../async-components/views/dialogs/ExportE2eKeysDialog'),
{
matrixClient: MatrixClientPeg.get(),
},
);
},
onInputChanged: function(stateKey, ev) {

View file

@ -90,7 +90,10 @@ module.exports = React.createClass({
// letting you do that login type
this._stepRendererMap = {
'm.login.password': this._renderPasswordStep,
'm.login.cas': this._renderCasStep,
// CAS and SSO are the same thing, modulo the url we link to
'm.login.cas': () => this._renderSsoStep(this._loginLogic.getSsoLoginUrl("cas")),
'm.login.sso': () => this._renderSsoStep(this._loginLogic.getSsoLoginUrl("sso")),
};
this._initLoginLogic();
@ -201,10 +204,6 @@ module.exports = React.createClass({
}).done();
},
onCasLogin: function() {
this._loginLogic.redirectToCas();
},
_onLoginAsGuestClick: function() {
const self = this;
self.setState({
@ -541,10 +540,9 @@ module.exports = React.createClass({
);
},
_renderCasStep: function() {
const CasLogin = sdk.getComponent('login.CasLogin');
_renderSsoStep: function(url) {
return (
<CasLogin onSubmit={this.onCasLogin} />
<a href={url} className="mx_Login_sso_link">{ _t('Sign in with single sign-on') }</a>
);
},