// @flow import * as React from 'react'; import { Component, Text, View, TextInput } from 'reactxp'; import { Button, BlueButton, GreenButton, Label } from './styled'; import { Layout, Container } from './Layout'; import styles from './SupportStyles'; import Img from './Img'; import type { AccountToken } from '../lib/daemon-rpc'; import type { SupportReportForm } from '../redux/support/actions'; type SupportState = { email: string, message: string, savedReport: ?string, sendState: 'INITIAL' | 'CONFIRM_NO_EMAIL' | 'LOADING' | 'SUCCESS' | 'FAILED', }; export type SupportProps = { defaultEmail: string, defaultMessage: string, accountHistory: Array, onClose: () => void, viewLog: (path: string) => void, saveReportForm: (form: SupportReportForm) => void, clearReportForm: () => void, collectProblemReport: (accountsToRedact: Array) => Promise, sendProblemReport: (email: string, message: string, savedReport: string) => Promise, }; export default class Support extends Component { state = { email: '', message: '', savedReport: null, sendState: 'INITIAL', }; _collectLogPromise: ?Promise; constructor(props: SupportProps) { super(props); // seed initial data from props this.state.email = props.defaultEmail; this.state.message = props.defaultMessage; } validate() { return this.state.message.trim().length > 0; } onChangeEmail = (email: string) => { this.setState({ email: email }, () => { this._saveFormData(); }); }; onChangeDescription = (description: string) => { this.setState({ message: description }, () => { this._saveFormData(); }); }; onViewLog = async (): Promise => { try { const reportPath = await this._collectLog(); this.props.viewLog(reportPath); } catch (error) { // TODO: handle error } }; _saveFormData() { this.props.saveReportForm({ email: this.state.email, message: this.state.message, }); } async _collectLog(): Promise { if (this._collectLogPromise) { return this._collectLogPromise; } else { const collectPromise = this.props.collectProblemReport(this.props.accountHistory); // save promise to prevent subsequent requests this._collectLogPromise = collectPromise; try { const reportPath = await collectPromise; return new Promise((resolve) => { this.setState({ savedReport: reportPath }, () => resolve(reportPath)); }); } catch (error) { this._collectLogPromise = null; throw error; } } } onSend = async (): Promise => { if (this.state.sendState === 'INITIAL' && this.state.email.length === 0) { return new Promise((resolve) => { this.setState({ sendState: 'CONFIRM_NO_EMAIL' }, () => resolve()); }); } else { try { await this._sendReport(); } catch (error) { // No-op } } }; _sendReport(): Promise { return new Promise((resolve, reject) => { this.setState({ sendState: 'LOADING' }, async () => { try { const { email, message } = this.state; const reportPath = await this._collectLog(); await this.props.sendProblemReport(email, message, reportPath); this.props.clearReportForm(); this.setState({ sendState: 'SUCCESS' }, () => { resolve(); }); } catch (error) { this.setState({ sendState: 'FAILED' }, () => { reject(error); }); } }); }); } render() { const { sendState } = this.state; const header = ( Report a problem {(sendState === 'INITIAL' || sendState === 'CONFIRM_NO_EMAIL') && ( { "To help you more effectively, your app's log file will be attached to this message. Your data will remain secure and private, as it is anonymised before being sent over an encrypted channel." } )} ); const content = this._renderContent(); return ( {header} {content} ); } _renderContent() { switch (this.state.sendState) { case 'INITIAL': case 'CONFIRM_NO_EMAIL': return this._renderForm(); case 'LOADING': return this._renderLoading(); case 'SUCCESS': return this._renderSent(); case 'FAILED': return this._renderFailed(); default: return null; } } _renderForm() { return ( {this.state.sendState === 'CONFIRM_NO_EMAIL' ? this._renderNoEmailWarning() : this._renderActionButtons()} ); } _renderNoEmailWarning() { return ( You are about to send the problem report without a way for us to get back to you. If you want an answer to your report you will have to enter an email address. Send anyway ); } _renderActionButtons() { return [ , Send , ]; } _renderLoading() { return ( Secure Connection Sending... ); } _renderSent() { return ( Secure Connection Sent Thanks! We will look into this. {this.state.email.trim().length > 0 ? ( If needed we will contact you on {'\u00A0'} {this.state.email} ) : null} ); } _renderFailed() { return ( Secure Connection Failed to send this.setState({ sendState: 'INITIAL' })}> Edit message Try again ); } }