UI fixes in SessionRestoreErrorDialog
* Make the 'delete my data' button not the default * Make it red * Give it a confirmation dialog * Remove the 'cancel' button: what does it mean to cancel an error? In this case, it tried again and almost certainly got the same error. * Remove the top-right 'x' and don't cancel on esc for the same reason. * Move 'send bug report' to a button rather than a 'click here' link * Add a 'refresh' button which, even if it's no more likely to work, will at least look like it's doing something (it's mostly so if you don't have a bug report endpoint, there's still a button other than the one that deletes all your data).
This commit is contained in:
parent
fba8a7d7d6
commit
fc136607f1
5 changed files with 79 additions and 43 deletions
|
@ -250,6 +250,7 @@ textarea {
|
|||
.mx_Dialog button.danger, .mx_Dialog input[type="submit"].danger {
|
||||
background-color: $warning-color;
|
||||
border: solid 1px $warning-color;
|
||||
color: $accent-fg-color;
|
||||
}
|
||||
|
||||
.mx_Dialog button:disabled, .mx_Dialog input[type="submit"]:disabled {
|
||||
|
|
|
@ -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.
|
||||
|
@ -41,6 +42,13 @@ export default React.createClass({
|
|||
// cancelled (BaseDialog itself only calls this with false).
|
||||
onFinished: PropTypes.func.isRequired,
|
||||
|
||||
// Whether the dialog should have a 'close' button that will
|
||||
// cause the dialog to be cancelled. This should only be set
|
||||
// to true if there is nothing the app can sensibly do if the
|
||||
// dialog is cancelled, eg. "We can't restore your session and
|
||||
// the app cannot work".
|
||||
hasCancel: PropTypes.bool,
|
||||
|
||||
// called when a key is pressed
|
||||
onKeyDown: PropTypes.func,
|
||||
|
||||
|
@ -59,6 +67,12 @@ export default React.createClass({
|
|||
contentId: React.PropTypes.string,
|
||||
},
|
||||
|
||||
getDefaultProps: function() {
|
||||
return {
|
||||
hasCancel: true,
|
||||
};
|
||||
},
|
||||
|
||||
childContextTypes: {
|
||||
matrixClient: PropTypes.instanceOf(MatrixClient),
|
||||
},
|
||||
|
@ -77,7 +91,7 @@ export default React.createClass({
|
|||
if (this.props.onKeyDown) {
|
||||
this.props.onKeyDown(e);
|
||||
}
|
||||
if (e.keyCode === KeyCode.ESCAPE) {
|
||||
if (this.props.hasCancel && e.keyCode === KeyCode.ESCAPE) {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
this.props.onFinished(false);
|
||||
|
@ -104,11 +118,11 @@ export default React.createClass({
|
|||
// AT users can skip its presentation.
|
||||
aria-describedby={this.props.contentId}
|
||||
>
|
||||
<AccessibleButton onClick={this._onCancelClick}
|
||||
{ this.props.hasCancel ? <AccessibleButton onClick={this._onCancelClick}
|
||||
className="mx_Dialog_cancelButton"
|
||||
>
|
||||
<TintableSvg src="img/icons-close-button.svg" width="35" height="35" />
|
||||
</AccessibleButton>
|
||||
</AccessibleButton> : null }
|
||||
<div className={'mx_Dialog_title ' + this.props.titleClass} id='mx_BaseDialog_title'>
|
||||
{ this.props.title }
|
||||
</div>
|
||||
|
|
|
@ -31,63 +31,73 @@ export default React.createClass({
|
|||
onFinished: PropTypes.func.isRequired,
|
||||
},
|
||||
|
||||
componentDidMount: function() {
|
||||
if (this.refs.bugreportLink) {
|
||||
this.refs.bugreportLink.focus();
|
||||
}
|
||||
},
|
||||
|
||||
_sendBugReport: function() {
|
||||
const BugReportDialog = sdk.getComponent("dialogs.BugReportDialog");
|
||||
Modal.createTrackedDialog('Session Restore Error', 'Send Bug Report Dialog', BugReportDialog, {});
|
||||
},
|
||||
|
||||
_onContinueClick: function() {
|
||||
this.props.onFinished(true);
|
||||
_onClearStorageClick: function() {
|
||||
const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog");
|
||||
Modal.createTrackedDialog('Session Restore Confirm Logout', '', QuestionDialog, {
|
||||
title: _t("Sign out"),
|
||||
description:
|
||||
<div>{ _t("Log out and remove encryption keys?") }</div>,
|
||||
button: _t("Sign out"),
|
||||
danger: true,
|
||||
onFinished: this.props.onFinished,
|
||||
});
|
||||
},
|
||||
|
||||
_onCancelClick: function() {
|
||||
this.props.onFinished(false);
|
||||
_onRefreshClick: function() {
|
||||
// Is this likely to help? Probably not, but giving only one button
|
||||
// that clears your storage seems awful.
|
||||
window.location.reload(true);
|
||||
},
|
||||
|
||||
render: function() {
|
||||
const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
|
||||
const DialogButtons = sdk.getComponent('views.elements.DialogButtons');
|
||||
let bugreport;
|
||||
|
||||
let dialogButtons;
|
||||
if (SdkConfig.get().bug_report_endpoint_url) {
|
||||
bugreport = (
|
||||
<p>
|
||||
{ _t(
|
||||
"Otherwise, <a>click here</a> to send a bug report.",
|
||||
{},
|
||||
{ 'a': (sub) => <a ref="bugreportLink" onClick={this._sendBugReport}
|
||||
key="bugreport" href='#'>{ sub }</a> },
|
||||
) }
|
||||
</p>
|
||||
);
|
||||
dialogButtons = <DialogButtons primaryButton={_t("Send Logs")}
|
||||
onPrimaryButtonClick={this._sendBugReport}
|
||||
focus={true}
|
||||
hasCancel={false}
|
||||
>
|
||||
<button onClick={this._onClearStorageClick} className="danger">
|
||||
{ _t("Clear Storage and Sign Out") }
|
||||
</button>
|
||||
</DialogButtons>
|
||||
} else {
|
||||
dialogButtons = <DialogButtons primaryButton={_t("Refresh")}
|
||||
onPrimaryButtonClick={this._onRefreshClick}
|
||||
focus={true}
|
||||
hasCancel={false}
|
||||
>
|
||||
<button onClick={this._onClearStorageClick} className="danger">
|
||||
{ _t("Clear Storage and Sign Out") }
|
||||
</button>
|
||||
</DialogButtons>
|
||||
}
|
||||
const shouldFocusContinueButton =!(bugreport==true);
|
||||
|
||||
return (
|
||||
<BaseDialog className="mx_ErrorDialog" onFinished={this.props.onFinished}
|
||||
title={_t('Unable to restore session')}
|
||||
title={_t('Unable to restore session')}
|
||||
contentId='mx_Dialog_content'
|
||||
hasCancel={false}
|
||||
>
|
||||
<div className="mx_Dialog_content" id='mx_Dialog_content'>
|
||||
<p>{ _t("We encountered an error trying to restore your previous session. If " +
|
||||
"you continue, you will need to log in again, and encrypted chat " +
|
||||
"history will be unreadable.") }</p>
|
||||
<p>{ _t("We encountered an error trying to restore your previous session.") }</p>
|
||||
|
||||
<p>{ _t("If you have previously used a more recent version of Riot, your session " +
|
||||
"may be incompatible with this version. Close this window and return " +
|
||||
"to the more recent version.") }</p>
|
||||
|
||||
{ bugreport }
|
||||
<p>{ _t("Clearing your browser's storage may fix the problem, but will sign you " +
|
||||
"out and cause any encrypted chat history to become unreadable.") }</p>
|
||||
</div>
|
||||
<DialogButtons primaryButton={_t("Continue anyway")}
|
||||
onPrimaryButtonClick={this._onContinueClick} focus={shouldFocusContinueButton}
|
||||
onCancel={this._onCancelClick} />
|
||||
{ dialogButtons }
|
||||
</BaseDialog>
|
||||
);
|
||||
},
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
Copyright 2017 Aidan Gauland
|
||||
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.
|
||||
|
@ -14,8 +15,6 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
import React from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import { _t } from '../../../languageHandler';
|
||||
|
@ -33,12 +32,21 @@ module.exports = React.createClass({
|
|||
// onClick handler for the primary button.
|
||||
onPrimaryButtonClick: PropTypes.func.isRequired,
|
||||
|
||||
// should there be a cancel button? default: true
|
||||
hasCancel: PropTypes.bool,
|
||||
|
||||
// onClick handler for the cancel button.
|
||||
onCancel: PropTypes.func.isRequired,
|
||||
onCancel: PropTypes.func,
|
||||
|
||||
focus: PropTypes.bool,
|
||||
},
|
||||
|
||||
getDefaultProps: function() {
|
||||
return {
|
||||
hasCancel: true,
|
||||
}
|
||||
},
|
||||
|
||||
_onCancelClick: function() {
|
||||
this.props.onCancel();
|
||||
},
|
||||
|
@ -57,9 +65,9 @@ module.exports = React.createClass({
|
|||
{ this.props.primaryButton }
|
||||
</button>
|
||||
{ this.props.children }
|
||||
<button onClick={this._onCancelClick}>
|
||||
{ this.props.hasCancel ? <button onClick={this._onCancelClick}>
|
||||
{ _t("Cancel") }
|
||||
</button>
|
||||
</button> : null }
|
||||
</div>
|
||||
);
|
||||
},
|
||||
|
|
|
@ -103,7 +103,6 @@
|
|||
"You need to be logged in.": "You need to be logged in.",
|
||||
"You need to be able to invite users to do that.": "You need to be able to invite users to do that.",
|
||||
"Unable to create widget.": "Unable to create widget.",
|
||||
"Popout widget": "Popout widget",
|
||||
"Missing roomId.": "Missing roomId.",
|
||||
"Failed to send request.": "Failed to send request.",
|
||||
"This room is not recognised.": "This room is not recognised.",
|
||||
|
@ -655,6 +654,7 @@
|
|||
"Delete widget": "Delete widget",
|
||||
"Revoke widget access": "Revoke widget access",
|
||||
"Minimize apps": "Minimize apps",
|
||||
"Popout widget": "Popout widget",
|
||||
"Picture": "Picture",
|
||||
"Edit": "Edit",
|
||||
"Create new room": "Create new room",
|
||||
|
@ -807,11 +807,15 @@
|
|||
"Ignore request": "Ignore request",
|
||||
"Loading device info...": "Loading device info...",
|
||||
"Encryption key request": "Encryption key request",
|
||||
"Otherwise, <a>click here</a> to send a bug report.": "Otherwise, <a>click here</a> to send a bug report.",
|
||||
"Sign out": "Sign out",
|
||||
"Log out and remove encryption keys?": "Log out and remove encryption keys?",
|
||||
"Send Logs": "Send Logs",
|
||||
"Clear Storage and Sign Out": "Clear Storage and Sign Out",
|
||||
"Refresh": "Refresh",
|
||||
"Unable to restore session": "Unable to restore session",
|
||||
"We encountered an error trying to restore your previous session. If you continue, you will need to log in again, and encrypted chat history will be unreadable.": "We encountered an error trying to restore your previous session. If you continue, you will need to log in again, and encrypted chat history will be unreadable.",
|
||||
"We encountered an error trying to restore your previous session.": "We encountered an error trying to restore your previous session.",
|
||||
"If you have previously used a more recent version of Riot, your session may be incompatible with this version. Close this window and return to the more recent version.": "If you have previously used a more recent version of Riot, your session may be incompatible with this version. Close this window and return to the more recent version.",
|
||||
"Continue anyway": "Continue anyway",
|
||||
"Clearing your browser's storage may fix the problem, but will sign you out and cause any encrypted chat history to become unreadable.": "Clearing your browser's storage may fix the problem, but will sign you out and cause any encrypted chat history to become unreadable.",
|
||||
"Invalid Email Address": "Invalid Email Address",
|
||||
"This doesn't appear to be a valid email address": "This doesn't appear to be a valid email address",
|
||||
"Verification Pending": "Verification Pending",
|
||||
|
@ -1015,7 +1019,6 @@
|
|||
"Status.im theme": "Status.im theme",
|
||||
"Can't load user settings": "Can't load user settings",
|
||||
"Server may be unavailable or overloaded": "Server may be unavailable or overloaded",
|
||||
"Sign out": "Sign out",
|
||||
"For security, logging out will delete any end-to-end encryption keys from this browser. If you want to be able to decrypt your conversation history from future Riot sessions, please export your room keys for safe-keeping.": "For security, logging out will delete any end-to-end encryption keys from this browser. If you want to be able to decrypt your conversation history from future Riot sessions, please export your room keys for safe-keeping.",
|
||||
"Success": "Success",
|
||||
"Your password was successfully changed. You will not receive push notifications on other devices until you log back in to them": "Your password was successfully changed. You will not receive push notifications on other devices until you log back in to them",
|
||||
|
|
Loading…
Reference in a new issue