/* @flow */ import React, { Component } from 'react'; import Select from 'react-select'; import TrezorConnect from 'trezor-connect'; import type { Props } from './index'; import type { TrezorDevice } from '~/flowtype'; export const DeviceSelect = (props: Props) => { const { devices } = props; const { transport } = props.connect; const selected: ?TrezorDevice = props.wallet.selectedDevice; if (!selected) return null; let deviceStatus: string = 'Connected'; let css: string = 'device-select device'; if (props.deviceDropdownOpened) css += ' opened'; if (!selected.connected) { css += ' disconnected'; deviceStatus = 'Disconnected'; } else if (!selected.available) { css += ' unavailable'; deviceStatus = 'Unavailable'; } else { if (selected.type === 'acquired') { if (selected.status === 'occupied') { css += ' used-elsewhere'; deviceStatus = 'Used in other window'; } else if (selected.status === 'used') { css += ' reload-features'; } } else if (selected.type === 'unacquired') { css += ' unacquired'; deviceStatus = 'Used in other window'; } } if (selected.features && selected.features.major_version > 1) { css += ' trezor-t'; } const handleOpen = () => { props.toggleDeviceDropdown(!props.deviceDropdownOpened); }; const deviceCount = devices.length; const webusb: boolean = !!((transport && transport.version.indexOf('webusb') >= 0)); const disabled: boolean = (devices.length < 1 && !webusb) || (devices.length === 1 && !selected.features); if (disabled) { css += ' disabled'; } return (
{ selected.instanceLabel } { deviceStatus }
{ deviceCount > 1 ?
{ deviceCount }
: null }
); }; type DeviceMenuItem = { type: string; label: string; } export class DeviceDropdown extends Component { mouseDownHandler: (event: MouseEvent) => void; blurHandler: (event: FocusEvent) => void; constructor(props: Props) { super(props); this.mouseDownHandler = this.mouseDownHandler.bind(this); this.blurHandler = this.blurHandler.bind(this); } componentDidUpdate() { const { transport } = this.props.connect; if (transport && transport.version.indexOf('webusb') >= 0) TrezorConnect.renderWebUSBButton(); } mouseDownHandler(event: MouseEvent): void { let elem: any = (event.target: any); let block: boolean = false; while (elem.parentElement) { if (elem.tagName.toLowerCase() === 'aside' || (elem.className && elem.className.indexOf && elem.className.indexOf('modal-container') >= 0)) { block = true; break; } elem = elem.parentElement; } if (!block) { this.props.toggleDeviceDropdown(false); } } blurHandler(event: FocusEvent): void { this.props.toggleDeviceDropdown(false); } componentDidMount(): void { window.addEventListener('mousedown', this.mouseDownHandler, false); // window.addEventListener('blur', this.blurHandler, false); const { transport } = this.props.connect; if (transport && transport.version.indexOf('webusb') >= 0) TrezorConnect.renderWebUSBButton(); } componentWillUnmount(): void { window.removeEventListener('mousedown', this.mouseDownHandler, false); // window.removeEventListener('blur', this.blurHandler, false); } onDeviceMenuClick(item: DeviceMenuItem, device: TrezorDevice): void { if (item.type === 'reload') { this.props.acquireDevice(); } else if (item.type === 'forget') { this.props.forgetDevice(device); } else if (item.type === 'clone') { this.props.duplicateDevice(device); } else if (item.type === 'settings') { this.props.toggleDeviceDropdown(false); this.props.gotoDeviceSettings(device); } } render() { const { devices } = this.props; const { transport } = this.props.connect; const selected: ?TrezorDevice = this.props.wallet.selectedDevice; if (!selected) return; let webUsbButton = null; if (transport && transport.version.indexOf('webusb') >= 0) { webUsbButton = ; } let currentDeviceMenu = null; if (selected.features) { const deviceMenuItems: Array = []; if (selected.status !== 'available') { deviceMenuItems.push({ type: 'reload', label: 'Renew session' }); } deviceMenuItems.push({ type: 'settings', label: 'Device settings' }); if (selected.features.passphrase_protection && selected.connected && selected.available) { deviceMenuItems.push({ type: 'clone', label: 'Clone device' }); } //if (selected.remember) { deviceMenuItems.push({ type: 'forget', label: 'Forget device' }); //} const deviceMenuButtons = deviceMenuItems.map((item, index) => (
this.onDeviceMenuClick(item, selected)}>{ item.label}
)); currentDeviceMenu = deviceMenuButtons.length < 1 ? null : (
{ deviceMenuButtons }
); } const deviceList = devices.map((dev, index) => { if (dev === selected) return null; let deviceStatus: string = 'Connected'; let css: string = 'device item'; if (!dev.features || (dev.features && dev.status === 'occupied')) { deviceStatus = 'Used in other window'; css += ' unacquired'; } else if (!dev.connected) { deviceStatus = 'Disconnected'; css += ' disconnected'; } else if (!dev.available) { deviceStatus = 'Unavailable'; css += ' unavailable'; } if (dev.features && dev.features.major_version > 1) { css += ' trezor-t'; } return (
this.props.onSelectDevice(dev)}>
{ dev.instanceLabel } { deviceStatus }
{ event.stopPropagation(); event.preventDefault(); this.onDeviceMenuClick({ type: 'forget', label: '' }, dev); }} />
); }); return (
{ currentDeviceMenu } { deviceList.length > 1 ?
Other devices
: null } { deviceList } { webUsbButton }
); } }