/* @flow */ 'use strict'; import React, { Component } from 'react'; import Select from 'react-select'; import TrezorConnect from 'trezor-connect'; import { findSelectedDevice } from '~/js/reducers/TrezorConnectReducer'; import type { Props } from './index'; import type { TrezorDevice } from '~/flowtype'; export const DeviceSelect = (props: Props) => { const { devices, transport } = props.connect; const selected: ?TrezorDevice = findSelectedDevice(props.connect); 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.unacquired) { css += " unacquired"; deviceStatus = "Used in other window"; } if (selected.isUsedElsewhere) { css += " used-elsewhere"; deviceStatus = "Used in other window"; } else if (selected.featuresNeedsReload) { css += " reload-features"; } } if (selected.features && selected.features.major_version > 1) { css += " trezor-t"; } const handleOpen = () => { props.toggleDeviceDropdown(props.deviceDropdownOpened ? false : true); } const deviceCount = devices.length; const webusb: boolean = (transport && transport.version.indexOf('webusb') >= 0) ? true : false; 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, transport } = this.props.connect; const selected: ?TrezorDevice = findSelectedDevice(this.props.connect); 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.isUsedElsewhere) { deviceMenuItems.push({ type: "reload", label: "Renew session" }); } else if (selected.featuresNeedsReload) { deviceMenuItems.push({ type: "reload", label: "Renew session" }); } deviceMenuItems.push({ type: "settings", label: "Device settings" }); if (selected.features && 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) => { return (
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.unacquired || dev.isUsedElsewhere) { 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 }
); } }