Merge branch 'develop' into travis/well-known
This commit is contained in:
commit
6f0f930e0a
140 changed files with 4922 additions and 683 deletions
|
@ -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} />;
|
||||
}
|
||||
},
|
||||
|
|
|
@ -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>
|
||||
);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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});
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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}
|
||||
/>
|
||||
);
|
||||
},
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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}
|
||||
|
|
|
@ -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>
|
||||
);
|
||||
},
|
||||
});
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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>
|
||||
{ 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] : "");
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
},
|
||||
|
|
|
@ -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 = (
|
||||
|
|
|
@ -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>
|
||||
);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
|
|
@ -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.
|
||||
},
|
||||
|
||||
|
|
|
@ -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]}`;
|
||||
}
|
||||
|
||||
|
|
|
@ -53,5 +53,5 @@ module.exports = React.createClass({
|
|||
</SyntaxHighlight>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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>
|
||||
);
|
||||
},
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue