import 'regenerator-runtime/runtime'; import {FormattedMessage} from 'react-intl'; import PropTypes from 'prop-types'; import classNames from 'classnames'; import React from 'react'; import bindAll from 'lodash.bindall'; import keyMirror from 'keymirror'; import BalancedFormattedMessage from '../../containers/balanced-formatted-message.jsx'; import Box from '../box/box.jsx'; import ProgressRingComponent from '../progress-ring/progress-ring.jsx'; import backIcon from './icons/back.svg'; import sendUpdateIcon from './icons/send-update.svg'; import sendUpdateGlyph from './icons/send-update-white.svg'; import styles from './connection-modal.css'; /** @enum{string} UPDATE_ACTIVITY */ const UPDATE_ACTIVITY = keyMirror({ getReady: null, sendUpdate: null, results: null }); const microBitFirmwareUrl = 'https://microbit.org/get-started/user-guide/firmware/'; class UpdatePeripheralStep extends React.Component { constructor (props) { super(props); bindAll(this, [ 'handleSendUpdate' ]); this.state = { /** @type {UPDATE_ACTIVITY} */ activity: UPDATE_ACTIVITY.getReady, /** @type {number} */ progressPercentage: 0, /** @type {Error?} */ err: null, /** @type {any} */ res: null }; } async handleSendUpdate () { this.setState({ activity: UPDATE_ACTIVITY.sendUpdate, progress: 0, err: null, res: null }); try { const res = await this.props.onSendPeripheralUpdate(progress => { // On my computer, I get a progress update every 0.005% or so. // Rendering the progress ring is a little expensive, so filtering updates here reduces the CPU load. // Updating every 1% doesn't look very smooth, but 0.5% (1/200) looks good to me. this.setState({progressPercentage: Math.floor(progress * 200) / 2}); }); this.setState({ activity: UPDATE_ACTIVITY.results, res }); } catch (err) { this.setState({ activity: UPDATE_ACTIVITY.results, err }); } } renderGetReady () { return ( {'1'} { // The instructions for getting the peripheral ready for the update process will vary // depending on the peripheral. Should we get this from the extension somehow? } {'2'} ); } renderSendUpdate () { return ( ); } renderResults () { let resultsContent; if (this.state.err === null) { resultsContent = (); } else if (this.state.err.message === 'No valid interfaces found.') { // this is a special case where the micro:bit's communication firmware is too old to support WebUSB resultsContent = ( {microBitFirmwareUrl} }} />); } else { resultsContent = ( ); } return ( {resultsContent} ); } render () { const showGetReady = this.state.activity === UPDATE_ACTIVITY.getReady; const showSendUpdate = this.state.activity === UPDATE_ACTIVITY.sendUpdate; const showResults = this.state.activity === UPDATE_ACTIVITY.results; const showBadResults = showResults && !!this.state.err; return ( {showGetReady && this.renderGetReady()} {showSendUpdate && this.renderSendUpdate()} {showResults && this.renderResults()} {!showResults && } {!showSendUpdate && {(showGetReady || showBadResults) && } } ); } } UpdatePeripheralStep.propTypes = { connectionSmallIconURL: PropTypes.string, name: PropTypes.string.isRequired, onScanning: PropTypes.func.isRequired, onSendPeripheralUpdate: PropTypes.func.isRequired }; export default UpdatePeripheralStep;