Merge branch 'develop' into matthew/e2e_backups
This commit is contained in:
commit
25216d4660
824 changed files with 43369 additions and 3899 deletions
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
Copyright 2015, 2016 OpenMarket Ltd
|
||||
Copyright 2017 Vector Creations Ltd
|
||||
Copyright 2017 New Vector Ltd
|
||||
Copyright 2017, 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.
|
||||
|
@ -165,12 +165,18 @@ export default React.createClass({
|
|||
newVersionReleaseNotes: null,
|
||||
checkingForUpdate: null,
|
||||
|
||||
showCookieBar: false,
|
||||
|
||||
// Parameters used in the registration dance with the IS
|
||||
register_client_secret: null,
|
||||
register_session_id: null,
|
||||
register_hs_url: null,
|
||||
register_is_url: null,
|
||||
register_id_sid: null,
|
||||
|
||||
// When showing Modal dialogs we need to set aria-hidden on the root app element
|
||||
// and disable it when there are no dialogs
|
||||
hideToSRUsers: false,
|
||||
};
|
||||
return s;
|
||||
},
|
||||
|
@ -223,8 +229,6 @@ export default React.createClass({
|
|||
componentWillMount: function() {
|
||||
SdkConfig.put(this.props.config);
|
||||
|
||||
if (!SettingsStore.getValue("analyticsOptOut")) Analytics.enable();
|
||||
|
||||
// Used by _viewRoom before getting state from sync
|
||||
this.firstSyncComplete = false;
|
||||
this.firstSyncPromise = Promise.defer();
|
||||
|
@ -287,6 +291,8 @@ export default React.createClass({
|
|||
this.handleResize();
|
||||
window.addEventListener('resize', this.handleResize);
|
||||
|
||||
this._pageChanging = false;
|
||||
|
||||
// check we have the right tint applied for this theme.
|
||||
// N.B. we don't call the whole of setTheme() here as we may be
|
||||
// racing with the theme CSS download finishing from index.js
|
||||
|
@ -345,16 +351,26 @@ export default React.createClass({
|
|||
guestIsUrl: this.getCurrentIsUrl(),
|
||||
defaultDeviceDisplayName: this.props.defaultDeviceDisplayName,
|
||||
});
|
||||
}).catch((e) => {
|
||||
console.error(`Error attempting to load session: ${e}`);
|
||||
return false;
|
||||
}).then((loadedSession) => {
|
||||
if (!loadedSession) {
|
||||
// fall back to showing the login screen
|
||||
dis.dispatch({action: "start_login"});
|
||||
}
|
||||
});
|
||||
}).done();
|
||||
// Note we don't catch errors from this: we catch everything within
|
||||
// loadSession as there's logic there to ask the user if they want
|
||||
// to try logging out.
|
||||
});
|
||||
|
||||
if (SettingsStore.getValue("showCookieBar")) {
|
||||
this.setState({
|
||||
showCookieBar: true,
|
||||
});
|
||||
}
|
||||
|
||||
if (SettingsStore.getValue("analyticsOptIn")) {
|
||||
Analytics.enable();
|
||||
}
|
||||
},
|
||||
|
||||
componentWillUnmount: function() {
|
||||
|
@ -364,13 +380,62 @@ export default React.createClass({
|
|||
window.removeEventListener('resize', this.handleResize);
|
||||
},
|
||||
|
||||
componentDidUpdate: function() {
|
||||
componentWillUpdate: function(props, state) {
|
||||
if (this.shouldTrackPageChange(this.state, state)) {
|
||||
this.startPageChangeTimer();
|
||||
}
|
||||
},
|
||||
|
||||
componentDidUpdate: function(prevProps, prevState) {
|
||||
if (this.shouldTrackPageChange(prevState, this.state)) {
|
||||
const durationMs = this.stopPageChangeTimer();
|
||||
Analytics.trackPageChange(durationMs);
|
||||
}
|
||||
if (this.focusComposer) {
|
||||
dis.dispatch({action: 'focus_composer'});
|
||||
this.focusComposer = false;
|
||||
}
|
||||
},
|
||||
|
||||
startPageChangeTimer() {
|
||||
// This shouldn't happen because componentWillUpdate and componentDidUpdate
|
||||
// are used.
|
||||
if (this._pageChanging) {
|
||||
console.warn('MatrixChat.startPageChangeTimer: timer already started');
|
||||
return;
|
||||
}
|
||||
this._pageChanging = true;
|
||||
performance.mark('riot_MatrixChat_page_change_start');
|
||||
},
|
||||
|
||||
stopPageChangeTimer() {
|
||||
if (!this._pageChanging) {
|
||||
console.warn('MatrixChat.stopPageChangeTimer: timer not started');
|
||||
return;
|
||||
}
|
||||
this._pageChanging = false;
|
||||
performance.mark('riot_MatrixChat_page_change_stop');
|
||||
performance.measure(
|
||||
'riot_MatrixChat_page_change_delta',
|
||||
'riot_MatrixChat_page_change_start',
|
||||
'riot_MatrixChat_page_change_stop',
|
||||
);
|
||||
performance.clearMarks('riot_MatrixChat_page_change_start');
|
||||
performance.clearMarks('riot_MatrixChat_page_change_stop');
|
||||
const measurement = performance.getEntriesByName('riot_MatrixChat_page_change_delta').pop();
|
||||
|
||||
// In practice, sometimes the entries list is empty, so we get no measurement
|
||||
if (!measurement) return null;
|
||||
|
||||
return measurement.duration;
|
||||
},
|
||||
|
||||
shouldTrackPageChange(prevState, state) {
|
||||
return prevState.currentRoomId !== state.currentRoomId ||
|
||||
prevState.view !== state.view ||
|
||||
prevState.page_type !== state.page_type;
|
||||
},
|
||||
|
||||
setStateForNewView: function(state) {
|
||||
if (state.view === undefined) {
|
||||
throw new Error("setStateForNewView with no view!");
|
||||
|
@ -608,6 +673,33 @@ export default React.createClass({
|
|||
case 'send_event':
|
||||
this.onSendEvent(payload.room_id, payload.event);
|
||||
break;
|
||||
case 'aria_hide_main_app':
|
||||
this.setState({
|
||||
hideToSRUsers: true,
|
||||
});
|
||||
break;
|
||||
case 'aria_unhide_main_app':
|
||||
this.setState({
|
||||
hideToSRUsers: false,
|
||||
});
|
||||
break;
|
||||
case 'accept_cookies':
|
||||
SettingsStore.setValue("analyticsOptIn", null, SettingLevel.DEVICE, true);
|
||||
SettingsStore.setValue("showCookieBar", null, SettingLevel.DEVICE, false);
|
||||
|
||||
this.setState({
|
||||
showCookieBar: false,
|
||||
});
|
||||
Analytics.enable();
|
||||
break;
|
||||
case 'reject_cookies':
|
||||
SettingsStore.setValue("analyticsOptIn", null, SettingLevel.DEVICE, false);
|
||||
SettingsStore.setValue("showCookieBar", null, SettingLevel.DEVICE, false);
|
||||
|
||||
this.setState({
|
||||
showCookieBar: false,
|
||||
});
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -618,18 +710,26 @@ export default React.createClass({
|
|||
},
|
||||
|
||||
_startRegistration: function(params) {
|
||||
this.setStateForNewView({
|
||||
const newState = {
|
||||
view: VIEWS.REGISTER,
|
||||
// these params may be undefined, but if they are,
|
||||
// unset them from our state: we don't want to
|
||||
// resume a previous registration session if the
|
||||
// user just clicked 'register'
|
||||
register_client_secret: params.client_secret,
|
||||
register_session_id: params.session_id,
|
||||
register_hs_url: params.hs_url,
|
||||
register_is_url: params.is_url,
|
||||
register_id_sid: params.sid,
|
||||
});
|
||||
};
|
||||
|
||||
// Only honour params if they are all present, otherwise we reset
|
||||
// HS and IS URLs when switching to registration.
|
||||
if (params.client_secret &&
|
||||
params.session_id &&
|
||||
params.hs_url &&
|
||||
params.is_url &&
|
||||
params.sid
|
||||
) {
|
||||
newState.register_client_secret = params.client_secret;
|
||||
newState.register_session_id = params.session_id;
|
||||
newState.register_hs_url = params.hs_url;
|
||||
newState.register_is_url = params.is_url;
|
||||
newState.register_id_sid = params.sid;
|
||||
}
|
||||
|
||||
this.setStateForNewView(newState);
|
||||
this.notifyNewScreen('register');
|
||||
},
|
||||
|
||||
|
@ -847,16 +947,37 @@ export default React.createClass({
|
|||
}).close;
|
||||
},
|
||||
|
||||
_leaveRoomWarnings: function(roomId) {
|
||||
const roomToLeave = MatrixClientPeg.get().getRoom(roomId);
|
||||
// Show a warning if there are additional complications.
|
||||
const joinRules = roomToLeave.currentState.getStateEvents('m.room.join_rules', '');
|
||||
const warnings = [];
|
||||
if (joinRules) {
|
||||
const rule = joinRules.getContent().join_rule;
|
||||
if (rule !== "public") {
|
||||
warnings.push((
|
||||
<span className="warning" key="non_public_warning">
|
||||
{' '/* Whitespace, otherwise the sentences get smashed together */ }
|
||||
{ _t("This room is not public. You will not be able to rejoin without an invite.") }
|
||||
</span>
|
||||
));
|
||||
}
|
||||
}
|
||||
return warnings;
|
||||
},
|
||||
|
||||
_leaveRoom: function(roomId) {
|
||||
const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog");
|
||||
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||
|
||||
const roomToLeave = MatrixClientPeg.get().getRoom(roomId);
|
||||
const warnings = this._leaveRoomWarnings(roomId);
|
||||
|
||||
Modal.createTrackedDialog('Leave room', '', QuestionDialog, {
|
||||
title: _t("Leave room"),
|
||||
description: (
|
||||
<span>
|
||||
{ _t("Are you sure you want to leave the room '%(roomName)s'?", {roomName: roomToLeave.name}) }
|
||||
{ warnings }
|
||||
</span>
|
||||
),
|
||||
onFinished: (shouldLeave) => {
|
||||
|
@ -1066,10 +1187,10 @@ export default React.createClass({
|
|||
// this if we are not scrolled up in the view. To find out, delegate to
|
||||
// the timeline panel. If the timeline panel doesn't exist, then we assume
|
||||
// it is safe to reset the timeline.
|
||||
if (!self._loggedInView) {
|
||||
if (!self._loggedInView || !self._loggedInView.child) {
|
||||
return true;
|
||||
}
|
||||
return self._loggedInView.getDecoratedComponentInstance().canResetTimelineInRoom(roomId);
|
||||
return self._loggedInView.child.canResetTimelineInRoom(roomId);
|
||||
});
|
||||
|
||||
cli.on('sync', function(state, prevState) {
|
||||
|
@ -1111,6 +1232,28 @@ export default React.createClass({
|
|||
action: 'logout',
|
||||
});
|
||||
});
|
||||
cli.on('no_consent', function(message, consentUri) {
|
||||
const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog");
|
||||
Modal.createTrackedDialog('No Consent Dialog', '', QuestionDialog, {
|
||||
title: _t('Terms and Conditions'),
|
||||
description: <div>
|
||||
<p> { _t(
|
||||
'To continue using the %(homeserverDomain)s homeserver ' +
|
||||
'you must review and agree to our terms and conditions.',
|
||||
{ homeserverDomain: cli.getDomain() },
|
||||
) }
|
||||
</p>
|
||||
</div>,
|
||||
button: _t('Review terms and conditions'),
|
||||
cancelButton: _t('Dismiss'),
|
||||
onFinished: (confirmed) => {
|
||||
if (confirmed) {
|
||||
window.open(consentUri, '_blank');
|
||||
}
|
||||
},
|
||||
}, null, true);
|
||||
});
|
||||
|
||||
cli.on("accountData", function(ev) {
|
||||
if (ev.getType() === 'im.vector.web.settings') {
|
||||
if (ev.getContent() && ev.getContent().theme) {
|
||||
|
@ -1149,18 +1292,6 @@ export default React.createClass({
|
|||
cli.on("crypto.warning", (type) => {
|
||||
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||
switch (type) {
|
||||
case 'CRYPTO_WARNING_ACCOUNT_MIGRATED':
|
||||
Modal.createTrackedDialog('Crypto migrated', '', ErrorDialog, {
|
||||
title: _t('Cryptography data migrated'),
|
||||
description: _t(
|
||||
"A one-off migration of cryptography data has been performed. "+
|
||||
"End-to-end encryption will not work if you go back to an older "+
|
||||
"version of Riot. If you need to use end-to-end cryptography on "+
|
||||
"an older version, log out of Riot first. To retain message history, "+
|
||||
"export and re-import your keys.",
|
||||
),
|
||||
});
|
||||
break;
|
||||
case 'CRYPTO_WARNING_OLD_VERSION_DETECTED':
|
||||
Modal.createTrackedDialog('Crypto migrated', '', ErrorDialog, {
|
||||
title: _t('Old cryptography data detected'),
|
||||
|
@ -1317,7 +1448,6 @@ export default React.createClass({
|
|||
if (this.props.onNewScreen) {
|
||||
this.props.onNewScreen(screen);
|
||||
}
|
||||
Analytics.trackPageChange();
|
||||
},
|
||||
|
||||
onAliasClick: function(event, alias) {
|
||||
|
@ -1487,6 +1617,17 @@ export default React.createClass({
|
|||
}
|
||||
},
|
||||
|
||||
onServerConfigChange(config) {
|
||||
const newState = {};
|
||||
if (config.hsUrl) {
|
||||
newState.register_hs_url = config.hsUrl;
|
||||
}
|
||||
if (config.isUrl) {
|
||||
newState.register_is_url = config.isUrl;
|
||||
}
|
||||
this.setState(newState);
|
||||
},
|
||||
|
||||
_makeRegistrationUrl: function(params) {
|
||||
if (this.props.startingFragmentQueryParams.referrer) {
|
||||
params.referrer = this.props.startingFragmentQueryParams.referrer;
|
||||
|
@ -1536,6 +1677,7 @@ export default React.createClass({
|
|||
onRegistered={this.onRegistered}
|
||||
currentRoomId={this.state.currentRoomId}
|
||||
teamToken={this._teamToken}
|
||||
showCookieBar={this.state.showCookieBar}
|
||||
{...this.props}
|
||||
{...this.state}
|
||||
/>
|
||||
|
@ -1575,6 +1717,7 @@ export default React.createClass({
|
|||
onLoginClick={this.onLoginClick}
|
||||
onRegisterClick={this.onRegisterClick}
|
||||
onCancelClick={MatrixClientPeg.get() ? this.onReturnToAppClick : null}
|
||||
onServerConfigChange={this.onServerConfigChange}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
@ -1609,6 +1752,7 @@ export default React.createClass({
|
|||
onForgotPasswordClick={this.onForgotPasswordClick}
|
||||
enableGuest={this.props.enableGuest}
|
||||
onCancelClick={MatrixClientPeg.get() ? this.onReturnToAppClick : null}
|
||||
onServerConfigChange={this.onServerConfigChange}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue