Implement UI for using bulk device deletion API

This commit is contained in:
Luke Barnard 2017-11-28 15:23:09 +00:00
parent bbaa46f773
commit 1c71983610
3 changed files with 103 additions and 106 deletions

View file

@ -19,24 +19,15 @@ import React from 'react';
import sdk from '../../../index';
import { _t } from '../../../languageHandler';
import MatrixClientPeg from '../../../MatrixClientPeg';
import Modal from '../../../Modal';
import DateUtils from '../../../DateUtils';
const AUTH_CACHE_AGE = 5 * 60 * 1000; // 5 minutes
export default class DevicesPanelEntry extends React.Component {
constructor(props, context) {
super(props, context);
this.state = {
deleting: false,
deleteError: undefined,
};
this._unmounted = false;
this._onDeleteClick = this._onDeleteClick.bind(this);
this.onDeviceToggled = this.onDeviceToggled.bind(this);
this._onDisplayNameChanged = this._onDisplayNameChanged.bind(this);
this._makeDeleteRequest = this._makeDeleteRequest.bind(this);
}
componentWillUnmount() {
@ -53,56 +44,8 @@ export default class DevicesPanelEntry extends React.Component {
});
}
_onDeleteClick() {
this.setState({deleting: true});
if (this.context.authCache.lastUpdate < Date.now() - AUTH_CACHE_AGE) {
this.context.authCache.auth = null;
}
// try with auth cache (which is null, so no interactive auth, to start off)
this._makeDeleteRequest(this.context.authCache.auth).catch((error) => {
if (this._unmounted) { return; }
if (error.httpStatus !== 401 || !error.data || !error.data.flows) {
// doesn't look like an interactive-auth failure
throw error;
}
// pop up an interactive auth dialog
const InteractiveAuthDialog = sdk.getComponent("dialogs.InteractiveAuthDialog");
Modal.createTrackedDialog('Delete Device Dialog', '', InteractiveAuthDialog, {
title: _t("Authentication"),
matrixClient: MatrixClientPeg.get(),
authData: error.data,
makeRequest: this._makeDeleteRequest,
});
this.setState({
deleting: false,
});
}).catch((e) => {
console.error("Error deleting device", e);
if (this._unmounted) { return; }
this.setState({
deleting: false,
deleteError: _t("Failed to delete device"),
});
}).done();
}
_makeDeleteRequest(auth) {
this.context.authCache.auth = auth;
this.context.authCache.lastUpdate = Date.now();
const device = this.props.device;
return MatrixClientPeg.get().deleteDevice(device.device_id, auth).then(
() => {
this.props.onDeleted();
if (this._unmounted) { return; }
this.setState({ deleting: false });
},
);
onDeviceToggled() {
this.props.onDeviceToggled(this.props.device);
}
render() {
@ -110,16 +53,6 @@ export default class DevicesPanelEntry extends React.Component {
const device = this.props.device;
if (this.state.deleting) {
const Spinner = sdk.getComponent("elements.Spinner");
return (
<div className="mx_DevicesPanel_device">
<Spinner />
</div>
);
}
let lastSeen = "";
if (device.last_seen_ts) {
const lastSeenDate = DateUtils.formatDate(new Date(device.last_seen_ts));
@ -127,18 +60,6 @@ export default class DevicesPanelEntry extends React.Component {
lastSeenDate.toLocaleString();
}
let deleteButton;
if (this.state.deleteError) {
deleteButton = <div className="error">{ this.state.deleteError }</div>;
} else {
deleteButton = (
<div className="mx_textButton"
onClick={this._onDeleteClick}>
{ _t("Delete") }
</div>
);
}
let myDeviceClass = '';
if (device.device_id === MatrixClientPeg.get().getDeviceId()) {
myDeviceClass = " mx_DevicesPanel_myDevice";
@ -159,7 +80,7 @@ export default class DevicesPanelEntry extends React.Component {
{ lastSeen }
</div>
<div className="mx_DevicesPanel_deviceButtons">
{ deleteButton }
<input type="checkbox" onClick={this.onDeviceToggled} checked={this.props.selected} />
</div>
</div>
);
@ -168,13 +89,9 @@ export default class DevicesPanelEntry extends React.Component {
DevicesPanelEntry.propTypes = {
device: React.PropTypes.object.isRequired,
onDeleted: React.PropTypes.func,
};
DevicesPanelEntry.contextTypes = {
authCache: React.PropTypes.object,
onDeviceToggled: React.PropTypes.func,
};
DevicesPanelEntry.defaultProps = {
onDeleted: function() {},
onDeviceToggled: function() {},
};