Merge pull request #3648 from vector-im/rav/rageshake_progress

Progress updates for rageshake uploads
pull/3651/head
Richard van der Hoff 2017-04-18 17:23:03 +01:00 committed by GitHub
commit 66a473863a
2 changed files with 64 additions and 16 deletions

View File

@ -16,7 +16,6 @@ limitations under the License.
import React from 'react'; import React from 'react';
import sdk from 'matrix-react-sdk'; import sdk from 'matrix-react-sdk';
import submit_rageshake from '../../../vector/submit-rageshake';
import SdkConfig from 'matrix-react-sdk/lib/SdkConfig'; import SdkConfig from 'matrix-react-sdk/lib/SdkConfig';
export default class BugReportDialog extends React.Component { export default class BugReportDialog extends React.Component {
@ -27,11 +26,18 @@ export default class BugReportDialog extends React.Component {
busy: false, busy: false,
err: null, err: null,
text: "", text: "",
progress: null,
}; };
this._unmounted = false;
this._onSubmit = this._onSubmit.bind(this); this._onSubmit = this._onSubmit.bind(this);
this._onCancel = this._onCancel.bind(this); this._onCancel = this._onCancel.bind(this);
this._onTextChange = this._onTextChange.bind(this); this._onTextChange = this._onTextChange.bind(this);
this._onSendLogsChange = this._onSendLogsChange.bind(this); this._onSendLogsChange = this._onSendLogsChange.bind(this);
this._sendProgressCallback = this._sendProgressCallback.bind(this);
}
componentWillUnmount() {
this._unmounted = true;
} }
_onCancel(ev) { _onCancel(ev) {
@ -47,15 +53,27 @@ export default class BugReportDialog extends React.Component {
}); });
return; return;
} }
this.setState({ busy: true, err: null }); this.setState({ busy: true, progress: null, err: null });
submit_rageshake(SdkConfig.get().bug_report_endpoint_url, { this._sendProgressCallback("Loading bug report module");
userText: userText,
sendLogs: sendLogs, require(['../../../vector/submit-rageshake'], (s) => {
}).then(() => { s(SdkConfig.get().bug_report_endpoint_url, {
this.setState({ busy: false }); userText: userText,
this.props.onFinished(false); sendLogs: sendLogs,
}, (err) => { progressCallback: this._sendProgressCallback,
this.setState({ busy: false, err: `Failed: ${err.message}` }); }).then(() => {
if (!this._unmounted) {
this.setState({ busy: false, progress: null });
this.props.onFinished(false);
}
}, (err) => {
if (!this._unmounted) {
this.setState({
busy: false, progress: null,
err: `Failed to send report: ${err.message}`,
});
}
});
}); });
} }
@ -67,6 +85,13 @@ export default class BugReportDialog extends React.Component {
this.setState({ sendLogs: ev.target.checked }); this.setState({ sendLogs: ev.target.checked });
} }
_sendProgressCallback(progress) {
if (this._unmounted) {
return;
}
this.setState({progress: progress});
}
render() { render() {
const Loader = sdk.getComponent("elements.Spinner"); const Loader = sdk.getComponent("elements.Spinner");
@ -77,8 +102,6 @@ export default class BugReportDialog extends React.Component {
</div>; </div>;
} }
const okLabel = this.state.busy ? <Loader /> : 'Send';
let cancelButton = null; let cancelButton = null;
if (!this.state.busy) { if (!this.state.busy) {
cancelButton = <button onClick={this._onCancel}> cancelButton = <button onClick={this._onCancel}>
@ -86,6 +109,16 @@ export default class BugReportDialog extends React.Component {
</button>; </button>;
} }
let progress = null;
if (this.state.busy) {
progress = (
<div className="progress">
<Loader />
{this.state.progress} ...
</div>
);
}
return ( return (
<div className="mx_BugReportDialog"> <div className="mx_BugReportDialog">
<div className="mx_Dialog_title"> <div className="mx_Dialog_title">
@ -108,6 +141,7 @@ export default class BugReportDialog extends React.Component {
<input type="checkbox" checked={this.state.sendLogs} <input type="checkbox" checked={this.state.sendLogs}
onChange={this._onSendLogsChange} id="mx_BugReportDialog_logs"/> onChange={this._onSendLogsChange} id="mx_BugReportDialog_logs"/>
<label htmlFor="mx_BugReportDialog_logs">Send logs</label> <label htmlFor="mx_BugReportDialog_logs">Send logs</label>
{progress}
{error} {error}
</div> </div>
<div className="mx_Dialog_buttons"> <div className="mx_Dialog_buttons">
@ -115,8 +149,9 @@ export default class BugReportDialog extends React.Component {
className="mx_Dialog_primary danger" className="mx_Dialog_primary danger"
onClick={this._onSubmit} onClick={this._onSubmit}
autoFocus={true} autoFocus={true}
disabled={this.state.busy}
> >
{okLabel} Send
</button> </button>
{cancelButton} {cancelButton}

View File

@ -30,10 +30,17 @@ if (!TextEncoder) {
/** /**
* Send a bug report. * Send a bug report.
*
* @param {string} bugReportEndpoint HTTP url to send the report to * @param {string} bugReportEndpoint HTTP url to send the report to
*
* @param {object} opts optional dictionary of options * @param {object} opts optional dictionary of options
*
* @param {string} opts.userText Any additional user input. * @param {string} opts.userText Any additional user input.
*
* @param {boolean} opts.sendLogs True to send logs * @param {boolean} opts.sendLogs True to send logs
*
* @param {function(string)} opts.progressCallback Callback to call with progress updates
*
* @return {Promise} Resolved when the bug report is sent. * @return {Promise} Resolved when the bug report is sent.
*/ */
export default async function sendBugReport(bugReportEndpoint, opts) { export default async function sendBugReport(bugReportEndpoint, opts) {
@ -42,7 +49,9 @@ export default async function sendBugReport(bugReportEndpoint, opts) {
} }
opts = opts || {}; opts = opts || {};
const progressCallback = opts.progressCallback || (() => {});
progressCallback("Collecting app version information");
let version = "UNKNOWN"; let version = "UNKNOWN";
try { try {
version = await PlatformPeg.get().getAppVersion(); version = await PlatformPeg.get().getAppVersion();
@ -63,6 +72,7 @@ export default async function sendBugReport(bugReportEndpoint, opts) {
body.append('user_agent', userAgent); body.append('user_agent', userAgent);
if (opts.sendLogs) { if (opts.sendLogs) {
progressCallback("Collecting logs");
const logs = await rageshake.getLogsForReport(); const logs = await rageshake.getLogsForReport();
for (let entry of logs) { for (let entry of logs) {
// encode as UTF-8 // encode as UTF-8
@ -72,17 +82,20 @@ export default async function sendBugReport(bugReportEndpoint, opts) {
} }
} }
await _submitReport(bugReportEndpoint, body); progressCallback("Uploading report");
await _submitReport(bugReportEndpoint, body, progressCallback);
} }
function _submitReport(endpoint, body) { function _submitReport(endpoint, body, progressCallback) {
const deferred = q.defer(); const deferred = q.defer();
const req = new XMLHttpRequest(); const req = new XMLHttpRequest();
req.open("POST", endpoint); req.open("POST", endpoint);
req.timeout = 5 * 60 * 1000; req.timeout = 5 * 60 * 1000;
req.onreadystatechange = function() { req.onreadystatechange = function() {
if (req.readyState === XMLHttpRequest.DONE) { if (req.readyState === XMLHttpRequest.LOADING) {
progressCallback("Waiting for response from server");
} else if (req.readyState === XMLHttpRequest.DONE) {
on_done(); on_done();
} }
}; };