diff --git a/src/components/connection-modal/connected-step.jsx b/src/components/connection-modal/connected-step.jsx index 53b7b6356a86e1e6a20f7095f1398522886a59a5..c02f644bc4e55d807124bd8cc41004a98cdca24b 100644 --- a/src/components/connection-modal/connected-step.jsx +++ b/src/components/connection-modal/connected-step.jsx @@ -4,13 +4,26 @@ import React from 'react'; import Box from '../box/box.jsx'; import Dots from './dots.jsx'; - +import bluetoothIcon from './icons/bluetooth-white.svg'; import styles from './connection-modal.css'; import classNames from 'classnames'; const ConnectedStep = props => ( <Box className={styles.body}> - <Box className={styles.activityArea} /> + <Box className={styles.activityArea}> + <Box className={styles.centeredRow}> + <div className={styles.deviceActivity}> + <img + className={styles.deviceActivityIcon} + src={props.deviceImage} + /> + <img + className={styles.bluetoothConnectedIcon} + src={bluetoothIcon} + /> + </div> + </Box> + </Box> <Box className={styles.bottomArea}> <Box className={styles.instructions}> <FormattedMessage @@ -50,6 +63,7 @@ const ConnectedStep = props => ( ); ConnectedStep.propTypes = { + deviceImage: PropTypes.string.isRequired, onCancel: PropTypes.func, onDisconnect: PropTypes.func }; diff --git a/src/components/connection-modal/connecting-step.jsx b/src/components/connection-modal/connecting-step.jsx index 7b0fd6f43020962451ae4b7e69b514f46c327c79..063e67a826c79f4c9f55548e321d499d8c86d6a3 100644 --- a/src/components/connection-modal/connecting-step.jsx +++ b/src/components/connection-modal/connecting-step.jsx @@ -5,11 +5,27 @@ import React from 'react'; import Box from '../box/box.jsx'; import Dots from './dots.jsx'; +import bluetoothIcon from './icons/bluetooth-white.svg'; +import closeIcon from '../close-button/icon--close.svg'; + import styles from './connection-modal.css'; const ConnectingStep = props => ( <Box className={styles.body}> - <Box className={styles.activityArea} /> + <Box className={styles.activityArea}> + <Box className={styles.centeredRow}> + <div className={styles.deviceActivity}> + <img + className={styles.deviceActivityIcon} + src={props.deviceImage} + /> + <img + className={styles.bluetoothConnectingIcon} + src={bluetoothIcon} + /> + </div> + </Box> + </Box> <Box className={styles.bottomArea}> <Box className={styles.instructions}> <FormattedMessage @@ -22,21 +38,33 @@ const ConnectingStep = props => ( counter={1} total={3} /> - <button - className={styles.connectionButton} - onClick={props.onDisconnect} - > - <FormattedMessage - defaultMessage="X" - description="Button to cancel connecting" - id="gui.connection.cancelbutton" - /> - </button> + <div className={styles.segmentedButton}> + <button + disabled + className={styles.connectionButton} + > + <FormattedMessage + defaultMessage="Connecting..." + description="Label indicating that connection is in progress" + id="gui.connection.connecting-cancelbutton" + /> + </button> + <button + className={styles.connectionButton} + onClick={props.onDisconnect} + > + <img + className={styles.abortConnectingIcon} + src={closeIcon} + /> + </button> + </div> </Box> </Box> ); ConnectingStep.propTypes = { + deviceImage: PropTypes.string.isRequired, onDisconnect: PropTypes.func }; diff --git a/src/components/connection-modal/connection-modal.css b/src/components/connection-modal/connection-modal.css index 410569fa5ea293b8a7ac53751f3831ba69fb2e36..ee0a0aae1e6ee354f7c3a2decd302f65b000644d 100644 --- a/src/components/connection-modal/connection-modal.css +++ b/src/components/connection-modal/connection-modal.css @@ -18,14 +18,26 @@ margin: 0 0 0.75rem; } +.centered-row { + display: flex; + flex-direction: row; + justify-content: center; + align-items: center; +} + .device-tile-pane { - overflow-y: scroll; + overflow-y: auto; width: 100%; height: 100%; padding: 0.5rem; } .device-tile { + display: flex; + flex-direction: row; + justify-content: space-between; + align-items: center; + background-color: $ui-white; border-radius: 0.25rem; padding: 10px; @@ -34,22 +46,133 @@ margin-bottom: 0.5rem; } +.device-tile-name { + display: flex; + align-items: center; +} + +.device-tile-image { + margin-right: 0.5rem; +} + +.device-tile-name-wrapper { + display: flex; + flex-direction: column; + justify-content: center; + align-items: flex-start; +} + +.device-tile-name-label { + font-weight: bold; + font-size: 0.625rem; +} + +.device-tile-name-text { + font-size: 0.875rem; +} + .device-tile button { - padding: 0.75rem 1rem; + padding: 0.6rem 0.75rem; + border: none; border-radius: 0.25rem; font-weight: 600; font-size: 0.85rem; background: $motion-primary; border: $motion-primary; color: white; + cursor: pointer; +} + +.signal-strength-meter { + display: flex; + justify-content: space-between; + align-items: flex-end; + width: 22px; + height: 16px; + margin-right: 1rem; +} + +.signal-bar { + width: 4px; + border-radius: 4px; + background-color: #DBDBDB; +} + +.signal-bar:nth-of-type(1) { height: 25%; } +.signal-bar:nth-of-type(2) { height: 50%; } +.signal-bar:nth-of-type(3) { height: 75%; } +.signal-bar:nth-of-type(4) { height: 100%; } + +.green-bar { + background-color: $pen-primary; +} + +.radar { + width: 40px; + height: 40px; + margin-right: 0.5rem; + animation: spin 4s linear infinite; +} + +@keyframes spin { + 100% { + transform: rotate(360deg); + } +} + + +.device-activity { + position: relative; +} + +.device-activity-icon { + /* width: 80px; + height: 80px; */ } -.signal-strength-text { - margin: 5px; +.bluetooth-connecting-icon { + position: absolute; + top: -5px; + right: -15px; + padding: 5px 5px; + background-color: $motion-primary; + border-radius: 100%; + box-shadow: 0px 0px 0px 4px $motion-transparent; + /* animation: pulse-blue-ring 1s infinite ease-in-out alternate; */ + animation: wiggle 0.5s infinite ease-in-out alternate; + +} + +@keyframes pulse-blue-ring { + 100% { + box-shadow: 0px 0px 0px 8px $motion-light-transparent; + } +} + + +.bluetooth-connected-icon { + position: absolute; + top: -5px; + right: -15px; + padding: 5px 5px; + background-color: $pen-primary; + border-radius: 100%; + box-shadow: 0px 0px 0px 4px $pen-transparent; +} + + + +@keyframes wiggle { + 0% {transform: rotate(3deg) scale(1.05);} + 25% {transform: rotate(-3deg) scale(1.05);} + 50% {transform: rotate(5deg) scale(1.05);} + 75% {transform: rotate(-2deg) scale(1.05);} + 100% {transform: rotate(0deg) scale(1.05);} } .device-tile-widgets { - float: right; + display: flex; + align-items: center; } .activityArea { @@ -63,16 +186,54 @@ .button-row { font-weight: bolder; text-align: center; + display: flex; +} + +.abort-connecting-icon { + width: 10px; + transform: rotate(45deg); } .connection-button { - padding: 0.75rem 1rem; + padding: 0.6rem 0.75rem; border-radius: 0.5rem; background: $motion-primary; color: white; font-weight: 600; font-size: 0.85rem; margin: 0.25rem; + border: none; + cursor: pointer; + display: flex; + align-items: center; +} + +.connection-button:disabled { + background: $motion-transparent; +} + +.segmented-button { + display: flex; +} + +.segmented-button .connection-button:first-of-type { + border-top-right-radius: 0; + border-bottom-right-radius: 0; + margin-right: 0; +} + +.segmented-button .connection-button:last-of-type { + margin-left: 1px; + border-top-left-radius: 0; + border-bottom-left-radius: 0; +} + +.button-icon-right { + margin-left: 0.5rem; +} + +.button-icon-left { + margin-right: 0.5rem; } .red-button { @@ -82,13 +243,17 @@ .corner-buttons { display: flex; justify-content: space-between; - padding: 1rem; + width: 100%; + padding: 0 1rem; } .bottom-area { - height: 150px; background-color: $ui-white; text-align: center; + display: flex; + flex-direction: column; + align-items: center; + padding-bottom: 12px; } .instructions { @@ -106,7 +271,7 @@ .dots-holder { display: flex; - padding: 0.2rem; + padding: 0.25rem 0.1rem; border-radius: 1rem; background: $motion-light-transparent; } diff --git a/src/components/connection-modal/connection-modal.jsx b/src/components/connection-modal/connection-modal.jsx index 3392f3fbe5a56e17584d3a1867fbfff7f933631a..b150d7fd8ce546eac8f1cff561d87192d7936c10 100644 --- a/src/components/connection-modal/connection-modal.jsx +++ b/src/components/connection-modal/connection-modal.jsx @@ -20,19 +20,12 @@ const PHASES = keyMirror({ error: null }); -const messages = defineMessages({ - connectionModalLabel: { - defaultMessage: 'Scratch Device Connection Modal', - description: 'Title for scratch device connection modal', - id: 'gui.connectionModal.modalLabel' - } -}); - const ConnectionModalComponent = props => ( <Modal className={styles.modalContent} - contentLabel={props.intl.formatMessage(messages.connectionModalLabel)} + contentLabel={props.name} headerClassName={styles.header} + headerImage={props.smallDeviceImage} onRequestClose={props.onCancel} > <Box className={styles.body}> @@ -46,8 +39,10 @@ const ConnectionModalComponent = props => ( ConnectionModalComponent.propTypes = { intl: intlShape, + name: PropTypes.node, onCancel: PropTypes.func.isRequired, phase: PropTypes.oneOf(Object.keys(PHASES)).isRequired, + smallDeviceImage: PropTypes.string, title: PropTypes.string.isRequired }; diff --git a/src/components/connection-modal/device-tile.jsx b/src/components/connection-modal/device-tile.jsx index 365b5ea7ac4e45f077a905b92e74022d4fbbcc9a..c806453aa0ff60828462376bf9c01a3a38ae550f 100644 --- a/src/components/connection-modal/device-tile.jsx +++ b/src/components/connection-modal/device-tile.jsx @@ -1,5 +1,6 @@ import {FormattedMessage} from 'react-intl'; import PropTypes from 'prop-types'; +import classNames from 'classnames'; import React from 'react'; import bindAll from 'lodash.bindall'; import Box from '../box/box.jsx'; @@ -19,21 +20,57 @@ class DeviceTile extends React.Component { render () { return ( <Box className={styles.deviceTile}> - <Box> - <span>{this.props.name}</span> - <Box className={styles.deviceTileWidgets}> - <span className={styles.signalStrengthText}>{this.props.rssi}</span> - <button - onClick={this.handleConnecting} - > + <Box className={styles.deviceTileName}> + <img + className={styles.deviceTileImage} + src={this.props.smallDeviceImage} + /> + <Box className={styles.deviceTileNameWrapper}> + <Box className={styles.deviceTileNameLabel}> <FormattedMessage - defaultMessage="Connect" - description="Button to start connecting to a specific device" - id="gui.connection.connect" + defaultMessage="Device name" + description="Label for field showing the device name" + id="gui.connection.device-name-label" /> - </button> + </Box> + <Box className={styles.deviceTileNameText}> + {this.props.name} + </Box> </Box> </Box> + <Box className={styles.deviceTileWidgets}> + <Box className={styles.signalStrengthMeter}> + <div + className={classNames(styles.signalBar, { + [styles.greenBar]: this.props.rssi > -80 + })} + /> + <div + className={classNames(styles.signalBar, { + [styles.greenBar]: this.props.rssi > -60 + })} + /> + <div + className={classNames(styles.signalBar, { + [styles.greenBar]: this.props.rssi > -40 + })} + /> + <div + className={classNames(styles.signalBar, { + [styles.greenBar]: this.props.rssi > -20 + })} + /> + </Box> + <button + onClick={this.handleConnecting} + > + <FormattedMessage + defaultMessage="Connect" + description="Button to start connecting to a specific device" + id="gui.connection.connect" + /> + </button> + </Box> </Box> ); } @@ -43,7 +80,8 @@ DeviceTile.propTypes = { name: PropTypes.string, onConnecting: PropTypes.func, peripheralId: PropTypes.string, - rssi: PropTypes.number + rssi: PropTypes.number, + smallDeviceImage: PropTypes.string }; export default DeviceTile; diff --git a/src/components/connection-modal/error-step.jsx b/src/components/connection-modal/error-step.jsx index 11af0a29b72159c3b0b319dca38b18bcd29b4497..681d74b72a2b278b13ae23d39d853becf5b4116d 100644 --- a/src/components/connection-modal/error-step.jsx +++ b/src/components/connection-modal/error-step.jsx @@ -4,12 +4,23 @@ import React from 'react'; import Box from '../box/box.jsx'; import Dots from './dots.jsx'; +import helpIcon from './icons/help.svg'; +import backIcon from './icons/back.svg'; import styles from './connection-modal.css'; const ErrorStep = props => ( <Box className={styles.body}> - <Box className={styles.activityArea} /> + <Box className={styles.activityArea}> + <Box className={styles.centeredRow}> + <div className={styles.deviceActivity}> + <img + className={styles.deviceActivityIcon} + src={props.deviceImage} + /> + </div> + </Box> + </Box> <Box className={styles.bottomArea}> <div className={styles.instructions}> <FormattedMessage @@ -27,6 +38,10 @@ const ErrorStep = props => ( className={styles.connectionButton} onClick={props.onScanning} > + <img + className={styles.buttonIconLeft} + src={backIcon} + /> <FormattedMessage defaultMessage="Try again" description="Button to initiate trying the device connection again after an error" @@ -37,6 +52,10 @@ const ErrorStep = props => ( className={styles.connectionButton} onClick={props.onHelp} > + <img + className={styles.buttonIconLeft} + src={helpIcon} + /> <FormattedMessage defaultMessage="Help" description="Button to view help content" @@ -49,6 +68,7 @@ const ErrorStep = props => ( ); ErrorStep.propTypes = { + deviceImage: PropTypes.string.isRequired, onHelp: PropTypes.func, onScanning: PropTypes.func }; diff --git a/src/components/connection-modal/icons/back.svg b/src/components/connection-modal/icons/back.svg new file mode 100644 index 0000000000000000000000000000000000000000..42f7508f279eaeee36aac930e3f343d2bfc7c518 Binary files /dev/null and b/src/components/connection-modal/icons/back.svg differ diff --git a/src/components/connection-modal/icons/bluetooth-white.svg b/src/components/connection-modal/icons/bluetooth-white.svg new file mode 100644 index 0000000000000000000000000000000000000000..df2ae141ebce92e1af1ad8f3f6e90b57c8248225 Binary files /dev/null and b/src/components/connection-modal/icons/bluetooth-white.svg differ diff --git a/src/components/connection-modal/icons/cancel.svg b/src/components/connection-modal/icons/cancel.svg new file mode 100644 index 0000000000000000000000000000000000000000..b30decdb65a22a832208426f4258a5fa1dea00b7 Binary files /dev/null and b/src/components/connection-modal/icons/cancel.svg differ diff --git a/src/components/connection-modal/icons/close.svg b/src/components/connection-modal/icons/close.svg new file mode 100644 index 0000000000000000000000000000000000000000..a537fc800d01115552a00073103be09cf5ce9fcf Binary files /dev/null and b/src/components/connection-modal/icons/close.svg differ diff --git a/src/components/connection-modal/icons/help.svg b/src/components/connection-modal/icons/help.svg new file mode 100644 index 0000000000000000000000000000000000000000..2938e8340ebb54dd699f80eaf48794bd383a96a4 Binary files /dev/null and b/src/components/connection-modal/icons/help.svg differ diff --git a/src/components/connection-modal/icons/refresh.svg b/src/components/connection-modal/icons/refresh.svg new file mode 100644 index 0000000000000000000000000000000000000000..3d4aebb47071a08f9214c5e4c5eafb035e2b86ea Binary files /dev/null and b/src/components/connection-modal/icons/refresh.svg differ diff --git a/src/components/connection-modal/icons/searching.png b/src/components/connection-modal/icons/searching.png new file mode 100644 index 0000000000000000000000000000000000000000..260f3227f2ef09cc1aa6fbca0fc928e2b5be0e28 Binary files /dev/null and b/src/components/connection-modal/icons/searching.png differ diff --git a/src/components/connection-modal/scanning-step.jsx b/src/components/connection-modal/scanning-step.jsx index b10f538a0212fcafc919e81dd6aebbd50428a6d1..1728e1fd5d55df75790f0301ef00386783d95b15 100644 --- a/src/components/connection-modal/scanning-step.jsx +++ b/src/components/connection-modal/scanning-step.jsx @@ -6,6 +6,9 @@ import Box from '../box/box.jsx'; import DeviceTile from './device-tile.jsx'; import Dots from './dots.jsx'; +import radarIcon from './icons/searching.png'; +import refreshIcon from './icons/refresh.svg'; + import styles from './connection-modal.css'; const ScanningStep = props => ( @@ -14,11 +17,17 @@ const ScanningStep = props => ( {props.scanning ? ( props.deviceList.length === 0 ? ( <div className={styles.activityAreaInfo}> - <FormattedMessage - defaultMessage="Looking for devices" - description="" - id="gui.connection.scanning.lookingfordevices" - /> + <div className={styles.centeredRow}> + <img + className={styles.radar} + src={radarIcon} + /> + <FormattedMessage + defaultMessage="Looking for devices" + description="Text shown while scanning for devices" + id="gui.connection.scanning.lookingfordevices" + /> + </div> </div> ) : ( <Box className={styles.deviceTilePane}> @@ -28,6 +37,7 @@ const ScanningStep = props => ( name={device.name} peripheralId={device.peripheralId} rssi={device.rssi} + smallDeviceImage={props.smallDeviceImage} onConnecting={props.onConnecting} />) )} @@ -37,7 +47,7 @@ const ScanningStep = props => ( <Box className={styles.instructions}> <FormattedMessage defaultMessage="No devices found" - description="" + description="Text shown when no devices could be found" id="gui.connection.scanning.noDevicesFound" /> </Box> @@ -47,7 +57,7 @@ const ScanningStep = props => ( <Box className={styles.instructions}> <FormattedMessage defaultMessage="Select your device in the list above." - description="" + description="Prompt for choosing a device to connect to" id="gui.connection.scanning.instructions" /> </Box> @@ -60,10 +70,14 @@ const ScanningStep = props => ( onClick={props.onRefresh} > <FormattedMessage - defaultMessage="refresh" + defaultMessage="Refresh" description="Button in prompt for starting a search" id="gui.connection.search" /> + <img + className={styles.buttonIconRight} + src={refreshIcon} + /> </button> </Box> </Box> @@ -77,7 +91,8 @@ ScanningStep.propTypes = { })), onConnecting: PropTypes.func, onRefresh: PropTypes.func, - scanning: PropTypes.bool.isRequired + scanning: PropTypes.bool.isRequired, + smallDeviceImage: PropTypes.string }; ScanningStep.defaultProps = { diff --git a/src/components/modal/modal.css b/src/components/modal/modal.css index 3aa21280beba80b61181349e5ae8a1bc38b52459..9a5a035a7de18edba2d6d5343fdc4fa97f213878 100644 --- a/src/components/modal/modal.css +++ b/src/components/modal/modal.css @@ -83,6 +83,10 @@ $sides: 20rem; user-select: none; } +.header-image { + margin-right: 0.5rem; +} + .header-item-filter { display: flex; flex-basis: $sides; diff --git a/src/components/modal/modal.jsx b/src/components/modal/modal.jsx index 631e77261c247a83f8f05109b1f7bd0b8b18f10b..940af75586f59e05291f9970b5bf972f353ccdb3 100644 --- a/src/components/modal/modal.jsx +++ b/src/components/modal/modal.jsx @@ -33,6 +33,12 @@ const ModalComponent = props => ( styles.headerItemTitle )} > + {props.headerImage ? ( + <img + className={styles.headerImage} + src={props.headerImage} + /> + ) : null} {props.contentLabel} </div> <div @@ -75,6 +81,7 @@ ModalComponent.propTypes = { ]).isRequired, fullScreen: PropTypes.bool, headerClassName: PropTypes.string, + headerImage: PropTypes.string, onRequestClose: PropTypes.func }; diff --git a/src/containers/blocks.jsx b/src/containers/blocks.jsx index ca327d2cefc8f538fbef34ca05758a86eb3aef06..20c6d482ff5c9a927d731d84200192b514fe2269 100644 --- a/src/containers/blocks.jsx +++ b/src/containers/blocks.jsx @@ -12,6 +12,7 @@ import Prompt from './prompt.jsx'; import ConnectionModal from './connection-modal.jsx'; import BlocksComponent from '../components/blocks/blocks.jsx'; import ExtensionLibrary from './extension-library.jsx'; +import extensionData from '../lib/libraries/extensions/index.jsx'; import CustomProcedures from './custom-procedures.jsx'; import errorBoundaryHOC from '../lib/error-boundary-hoc.jsx'; import {STAGE_DISPLAY_SIZES} from '../lib/layout-constants'; @@ -318,6 +319,11 @@ class Blocks extends React.Component { this.handleExtensionAdded(blocksInfo); } handleCategorySelected (categoryId) { + const extension = extensionData.find(ext => ext.extensionId === categoryId); + if (extension && extension.launchDeviceConnectionFlow) { + this.handleConnectionModalStart(categoryId); + } + this.withToolboxUpdates(() => { this.workspace.toolbox_.setSelectedCategoryById(categoryId); }); @@ -338,10 +344,15 @@ class Blocks extends React.Component { this.setState(p); } handleConnectionModalStart (extensionId) { - const c = {connectionModal: { - extensionId: extensionId - }}; - this.setState(c); + const extension = extensionData.find(ext => ext.extensionId === extensionId); + if (extension) { + this.setState({connectionModal: { + extensionId: extensionId, + deviceImage: extension.deviceImage, + smallDeviceImage: extension.smallDeviceImage, + name: extension.name + }}); + } } handleConnectionModalClose () { this.setState({connectionModal: null}); @@ -402,7 +413,10 @@ class Blocks extends React.Component { ) : null} {this.state.connectionModal ? ( <ConnectionModal + deviceImage={this.state.connectionModal.deviceImage} extensionId={this.state.connectionModal.extensionId} + name={this.state.connectionModal.name} + smallDeviceImage={this.state.connectionModal.smallDeviceImage} vm={vm} onCancel={this.handleConnectionModalClose} onStatusButtonUpdate={this.handleStatusButtonUpdate} diff --git a/src/containers/connection-modal.jsx b/src/containers/connection-modal.jsx index 5443646e4d2f225f3bc7d0cf71eb20f7dd29340a..b256b03095835eca16d1d33520a8185fbe6b7461 100644 --- a/src/containers/connection-modal.jsx +++ b/src/containers/connection-modal.jsx @@ -73,8 +73,11 @@ class ConnectionModal extends React.Component { render () { return ( <ConnectionModalComponent + deviceImage={this.props.deviceImage} extensionId={this.props.extensionId} + name={this.props.name} phase={this.state.phase} + smallDeviceImage={this.props.smallDeviceImage} title={this.props.extensionId} vm={this.props.vm} onCancel={this.props.onCancel} @@ -89,9 +92,12 @@ class ConnectionModal extends React.Component { } ConnectionModal.propTypes = { + deviceImage: PropTypes.string.isRequired, extensionId: PropTypes.string.isRequired, + name: PropTypes.node.isRequired, onCancel: PropTypes.func.isRequired, onStatusButtonUpdate: PropTypes.func.isRequired, + smallDeviceImage: PropTypes.string.isRequired, vm: PropTypes.instanceOf(VM).isRequired }; diff --git a/src/containers/scanning-step.jsx b/src/containers/scanning-step.jsx index 600eb8da8e0c05f3571446997d2efecab813923b..ecc19318913845154c248f716dfad6d440147c2e 100644 --- a/src/containers/scanning-step.jsx +++ b/src/containers/scanning-step.jsx @@ -53,6 +53,7 @@ class ScanningStep extends React.Component { <ScanningStepComponent deviceList={this.state.deviceList} phase={this.state.phase} + smallDeviceImage={this.props.smallDeviceImage} title={this.props.extensionId} onConnected={this.props.onConnected} onConnecting={this.props.onConnecting} @@ -66,6 +67,7 @@ ScanningStep.propTypes = { extensionId: PropTypes.string.isRequired, onConnected: PropTypes.func.isRequired, onConnecting: PropTypes.func.isRequired, + smallDeviceImage: PropTypes.string, vm: PropTypes.instanceOf(VM).isRequired }; diff --git a/src/lib/libraries/extensions/device-connection/ev3/ev3-hub-illustration.svg b/src/lib/libraries/extensions/device-connection/ev3/ev3-hub-illustration.svg new file mode 100644 index 0000000000000000000000000000000000000000..7f8c8c395969e202e01d4e18c0225b5ab98c49b0 Binary files /dev/null and b/src/lib/libraries/extensions/device-connection/ev3/ev3-hub-illustration.svg differ diff --git a/src/lib/libraries/extensions/device-connection/ev3/ev3-menu-icon.svg b/src/lib/libraries/extensions/device-connection/ev3/ev3-menu-icon.svg new file mode 100644 index 0000000000000000000000000000000000000000..7c8ea12abb768d48c8d544b1984fabf621e28c42 Binary files /dev/null and b/src/lib/libraries/extensions/device-connection/ev3/ev3-menu-icon.svg differ diff --git a/src/lib/libraries/extensions/device-connection/microbit/microbit-illustration.svg b/src/lib/libraries/extensions/device-connection/microbit/microbit-illustration.svg new file mode 100644 index 0000000000000000000000000000000000000000..3ef892bcc456fd9196e72356742391fd74b67a93 Binary files /dev/null and b/src/lib/libraries/extensions/device-connection/microbit/microbit-illustration.svg differ diff --git a/src/lib/libraries/extensions/device-connection/microbit/microbit-menu-icon.svg b/src/lib/libraries/extensions/device-connection/microbit/microbit-menu-icon.svg new file mode 100644 index 0000000000000000000000000000000000000000..af97b7948e8930b49c230a7386517aef091e0a51 Binary files /dev/null and b/src/lib/libraries/extensions/device-connection/microbit/microbit-menu-icon.svg differ diff --git a/src/lib/libraries/extensions/index.jsx b/src/lib/libraries/extensions/index.jsx index 71404f8fb0e2abd8a47018569487c350ad581074..a9d1018ce2053315e9f774752ace027860e9b93f 100644 --- a/src/lib/libraries/extensions/index.jsx +++ b/src/lib/libraries/extensions/index.jsx @@ -11,6 +11,12 @@ import ev3Image from './ev3.png'; import boostImage from './boost.png'; import translateImage from './translate.png'; +import ev3DeviceImage from './device-connection/ev3/ev3-hub-illustration.svg'; +import ev3MenuImage from './device-connection/ev3/ev3-menu-icon.svg'; + +import microbitDeviceImage from './device-connection/microbit/microbit-illustration.svg'; +import microbitMenuImage from './device-connection/microbit/microbit-menu-icon.svg'; + export default [ { name: ( @@ -121,6 +127,9 @@ export default [ ), featured: true, disabled: true + launchDeviceConnectionFlow: true, + deviceImage: microbitDeviceImage, + smallDeviceImage: microbitMenuImage }, { name: 'LEGO WeDo 2.0', @@ -149,6 +158,9 @@ export default [ ), featured: true, disabled: true + launchDeviceConnectionFlow: true, + deviceImage: ev3DeviceImage, + smallDeviceImage: ev3MenuImage }, { name: 'LEGO Boost',