mirror of
https://github.com/trezor/trezor-wallet
synced 2025-01-12 09:00:58 +00:00
clone custom name
This commit is contained in:
parent
ff7f79eb14
commit
2beaeff8ac
@ -56,7 +56,7 @@ export const ConfirmUnverifiedAddress = (props: Props) => {
|
||||
return (
|
||||
<div className="confirm-address-unverified">
|
||||
<button className="close-modal transparent" onClick={ onCancel }></button>
|
||||
<h3>{ device.instanceLabel } is not connected</h3>
|
||||
<h3>{ device.label } is not connected</h3>
|
||||
<p>To prevent phishing attacks, you should verify the address on your TREZOR first. Please reconnect your device to continue with the verification process.</p>
|
||||
<button onClick={ event => {
|
||||
onCancel();
|
||||
@ -74,7 +74,7 @@ export const ConfirmUnverifiedAddress = (props: Props) => {
|
||||
return (
|
||||
<div className="confirm-address-unverified">
|
||||
<button className="close-modal transparent" onClick={ onCancel }></button>
|
||||
<h3>{ device.instanceLabel } is unavailable</h3>
|
||||
<h3>{ device.label } is unavailable</h3>
|
||||
<p>To prevent phishing attacks, you should verify the address on your TREZOR first. { enable } passphrase settings to continue with the verification process.</p>
|
||||
<button onClick={ event => {
|
||||
onCancel();
|
||||
|
@ -5,6 +5,10 @@ import React from 'react';
|
||||
import type { Props } from './index';
|
||||
|
||||
const Confirmation = (props: Props) => {
|
||||
|
||||
if (!props.modal.opened) return null;
|
||||
const { device } = props.modal;
|
||||
|
||||
const {
|
||||
amount,
|
||||
address,
|
||||
@ -18,8 +22,8 @@ const Confirmation = (props: Props) => {
|
||||
return (
|
||||
<div className="confirm-tx">
|
||||
<div className="header">
|
||||
<h3>Confirm transaction on your TREZOR</h3>
|
||||
<p>Details are shown on device</p>
|
||||
<h3>Confirm transaction on { device.label } device</h3>
|
||||
<p>Details are shown on display</p>
|
||||
</div>
|
||||
<div className="content">
|
||||
<label>Send </label>
|
||||
|
@ -1,21 +1,63 @@
|
||||
/* @flow */
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
import React, { Component } from 'react';
|
||||
import { getNewInstance } from '../../reducers/TrezorConnectReducer'
|
||||
import type { Props } from './index';
|
||||
|
||||
const RememberDevice = (props: Props) => {
|
||||
if (!props.modal.opened) return null;
|
||||
const { device } = props.modal;
|
||||
const { onCancel, onDuplicateDevice } = props.modalActions;
|
||||
return (
|
||||
<div className="duplicate">
|
||||
<h3>Clone { device.instanceLabel }?</h3>
|
||||
<p>This will create new instance of device which can be used with different passphrase</p>
|
||||
<button onClick={ event => onDuplicateDevice( { ...device, instanceLabel: "TODO: user label from input" } ) }>Create new instance</button>
|
||||
<button className="white" onClick={ onCancel }>Cancel</button>
|
||||
</div>
|
||||
);
|
||||
type State = {
|
||||
defaultName: string;
|
||||
instanceName: ?string;
|
||||
}
|
||||
|
||||
export default RememberDevice;
|
||||
export default class DuplicateDevice extends Component<Props, State> {
|
||||
|
||||
state: State;
|
||||
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
|
||||
const device = props.modal.opened ? props.modal.device : null;
|
||||
if (!device) return;
|
||||
|
||||
const instance = getNewInstance(props.connect.devices, device);
|
||||
|
||||
this.state = {
|
||||
defaultName: `${device.label} (${instance.toString()})`,
|
||||
instanceName: null
|
||||
}
|
||||
}
|
||||
|
||||
onNameChange = (value: string): void => {
|
||||
this.setState({
|
||||
instanceName: value.length > 0 ? value : null
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
|
||||
if (!this.props.modal.opened) return null;
|
||||
|
||||
const { device } = this.props.modal;
|
||||
const { onCancel, onDuplicateDevice } = this.props.modalActions;
|
||||
|
||||
return (
|
||||
<div className="duplicate">
|
||||
<h3>Clone { device.label }?</h3>
|
||||
<p>This will create new instance of device which can be used with different passphrase</p>
|
||||
<label>Instance name</label>
|
||||
<input
|
||||
type="text"
|
||||
autoComplete="off"
|
||||
autoCorrect="off"
|
||||
autoCapitalize="off"
|
||||
spellCheck="false"
|
||||
placeholder={ this.state.defaultName }
|
||||
onChange={ event => this.onNameChange(event.currentTarget.value) }
|
||||
defaultValue={ this.state.instanceName } />
|
||||
<button onClick={ event => onDuplicateDevice( { ...device, instanceName: this.state.instanceName } ) }>Create new instance</button>
|
||||
<button className="white" onClick={ onCancel }>Cancel</button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
@ -10,7 +10,7 @@ const InvalidPin = (props: Props) => {
|
||||
const { device } = props.modal;
|
||||
return (
|
||||
<div className="pin">
|
||||
<h3>Entered PIN for { device.label } is not correct.</h3>
|
||||
<h3>Entered PIN for { device.label } is not correct</h3>
|
||||
<p>Retrying...</p>
|
||||
</div>
|
||||
);
|
||||
|
@ -2,12 +2,17 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
import type { Props } from './index';
|
||||
|
||||
const Confirmation = (props: Props) => {
|
||||
|
||||
if (!props.modal.opened) return null;
|
||||
const { device } = props.modal;
|
||||
|
||||
const Confirmation = () => {
|
||||
return (
|
||||
<div className="confirm-tx">
|
||||
<div className="header">
|
||||
<h3>Complete the action on your TREZOR device</h3>
|
||||
<h3>Complete the action on { device.label } device</h3>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
@ -67,16 +67,15 @@ export default class RememberDevice extends Component<Props, State> {
|
||||
const { onForgetDevice, onRememberDevice } = this.props.modalActions;
|
||||
|
||||
let label = device.label;
|
||||
let devicePlural: string = "device or to remember it";
|
||||
if (instances && instances.length > 1) {
|
||||
const devicePlural: string = instances && instances.length > 1 ? "devices or to remember them" : "device or to remember it";
|
||||
if (instances && instances.length > 0) {
|
||||
label = instances.map((instance, index) => {
|
||||
let comma: string = '';
|
||||
if (index > 0) comma = ', ';
|
||||
return (
|
||||
<span key={ index }>{ comma }{ instance.instanceLabel }</span>
|
||||
);
|
||||
})
|
||||
devicePlural = "devices or to remember them";
|
||||
});
|
||||
}
|
||||
return (
|
||||
<div className="remember">
|
||||
|
@ -51,6 +51,7 @@ export type TrezorDevice = {
|
||||
state: ?string;
|
||||
instance?: number;
|
||||
instanceLabel: string;
|
||||
instanceName: ?string;
|
||||
features?: Features;
|
||||
unacquired?: boolean;
|
||||
acquiring: boolean;
|
||||
|
@ -81,6 +81,24 @@ export const isSavedDevice = (state: State, device: any): ?Array<TrezorDevice> =
|
||||
});
|
||||
}
|
||||
|
||||
export const getNewInstance = (devices: Array<TrezorDevice>, device: Device | TrezorDevice): number => {
|
||||
|
||||
const affectedDevices: Array<TrezorDevice> = devices.filter(d => d.features && device.features && d.features.device_id === device.features.device_id)
|
||||
.sort((a, b) => {
|
||||
if (!a.instance) {
|
||||
return -1;
|
||||
} else {
|
||||
return !b.instance || a.instance > b.instance ? 1 : -1;
|
||||
}
|
||||
});
|
||||
|
||||
const instance: number = affectedDevices.reduce((inst, dev) => {
|
||||
return dev.instance ? dev.instance + 1 : inst + 1;
|
||||
}, 0);
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
const mergeDevices = (current: TrezorDevice, upcoming: Object): TrezorDevice => {
|
||||
|
||||
// do not merge if passphrase protection was changed
|
||||
@ -95,7 +113,7 @@ const mergeDevices = (current: TrezorDevice, upcoming: Object): TrezorDevice =>
|
||||
if (upcoming.label !== current.label) {
|
||||
instanceLabel = upcoming.label
|
||||
if (typeof current.instance === 'number') {
|
||||
instanceLabel += ` (${current.instance})`;
|
||||
instanceLabel += ` (${current.instanceName || current.instance})`;
|
||||
}
|
||||
}
|
||||
|
||||
@ -112,21 +130,14 @@ const mergeDevices = (current: TrezorDevice, upcoming: Object): TrezorDevice =>
|
||||
acquiring: typeof upcoming.acquiring === 'boolean' ? upcoming.acquiring : current.acquiring,
|
||||
ts: typeof upcoming.ts === 'number' ? upcoming.ts : current.ts,
|
||||
}
|
||||
|
||||
// corner-case: trying to merge unacquired device with acquired
|
||||
// make sure that sensitive fields will not be changed and device will remain acquired
|
||||
if (upcoming.unacquired && current.state) {
|
||||
dev.instanceLabel = current.instanceLabel;
|
||||
dev.unacquired = false;
|
||||
dev.features = current.features;
|
||||
dev.label = current.label;
|
||||
dev.unacquired = false;
|
||||
} else if (!upcoming.unacquired && current.unacquired) {
|
||||
// dev.instanceLabel = upcoming.label;
|
||||
// if (typeof dev.instance === 'number') {
|
||||
// dev.instanceLabel = `${upcoming.label} TODO:(${dev.instance})`;
|
||||
// }
|
||||
}
|
||||
|
||||
|
||||
|
||||
return dev;
|
||||
}
|
||||
|
||||
@ -151,14 +162,17 @@ const addDevice = (state: State, device: Device): State => {
|
||||
}
|
||||
|
||||
if (affectedDevices.length > 0 ) {
|
||||
// replace existing values
|
||||
// const changedDevices: Array<TrezorDevice> = affectedDevices.map(d => mergeDevices(d, { ...device, connected: true} ));
|
||||
// check if freshly added device has different "passphrase_protection" settings
|
||||
let cloneInstance: number = 1;
|
||||
let hasDifferentPassphraseSettings: boolean = false;
|
||||
let hasInstancesWithPassphraseSettings: boolean = false;
|
||||
const changedDevices: Array<TrezorDevice> = affectedDevices.map(d => {
|
||||
if (d.features && d.features.passphrase_protection === device.features.passphrase_protection) {
|
||||
cloneInstance = 0;
|
||||
hasInstancesWithPassphraseSettings = true;
|
||||
return mergeDevices(d, { ...device, connected: true, available: true } );
|
||||
} else {
|
||||
hasDifferentPassphraseSettings = true;
|
||||
if (d.instance && cloneInstance > 0) {
|
||||
cloneInstance = d.instance + 1;
|
||||
}
|
||||
@ -167,9 +181,12 @@ const addDevice = (state: State, device: Device): State => {
|
||||
}
|
||||
});
|
||||
|
||||
if (cloneInstance > 0) {
|
||||
// edge case: freshly connected device has different "passphrase_protection" than saved instances
|
||||
// need to automatically create another instance with default instance name
|
||||
if (hasDifferentPassphraseSettings && !hasInstancesWithPassphraseSettings) {
|
||||
// TODO: instance should be calculated form affectedDevice
|
||||
const instance = cloneInstance; //new Date().getTime();
|
||||
// const instance = cloneInstance; //new Date().getTime();
|
||||
const instance = getNewInstance(affectedDevices, device);
|
||||
|
||||
const newDevice: TrezorDevice = {
|
||||
...device,
|
||||
@ -182,14 +199,15 @@ const addDevice = (state: State, device: Device): State => {
|
||||
state: null,
|
||||
instance,
|
||||
instanceLabel: `${device.label} (${instance})`,
|
||||
instanceName: null,
|
||||
ts: new Date().getTime(),
|
||||
}
|
||||
changedDevices.push(newDevice);
|
||||
}
|
||||
|
||||
newState.devices = otherDevices.concat(changedDevices);
|
||||
|
||||
} else {
|
||||
|
||||
const newDevice: TrezorDevice = {
|
||||
...device,
|
||||
acquiring: false,
|
||||
@ -199,14 +217,11 @@ const addDevice = (state: State, device: Device): State => {
|
||||
path: device.path,
|
||||
label: device.label,
|
||||
state: null,
|
||||
// instance: 0,
|
||||
instanceLabel: device.label,
|
||||
instanceName: null,
|
||||
ts: new Date().getTime(),
|
||||
}
|
||||
newState.devices.push(newDevice);
|
||||
|
||||
// const clone = { ...newDevice, instance: 1, instanceLabel: device.label + '#1' };
|
||||
// newState.devices.push(clone);
|
||||
}
|
||||
|
||||
return newState;
|
||||
@ -251,9 +266,15 @@ const changeDevice = (state: State, device: Object): State => {
|
||||
if (affectedDevices.length > 0) {
|
||||
|
||||
const isAffectedUnacquired: number = affectedDevices.findIndex(d => d.unacquired);
|
||||
if (isAffectedUnacquired >= 0 && affectedDevices.length > 1){
|
||||
affectedDevices.splice(isAffectedUnacquired, 1);
|
||||
}
|
||||
// if (isAffectedUnacquired >= 0 && affectedDevices.length > 1){
|
||||
if (isAffectedUnacquired >= 0){
|
||||
// TODO: should unacquired device be removed? or merged?
|
||||
//affectedDevices.splice(isAffectedUnacquired, 1);
|
||||
} else {
|
||||
// replace existing values
|
||||
const changedDevices: Array<TrezorDevice> = affectedDevices.map(d => mergeDevices(d, device));
|
||||
newState.devices = otherDevices.concat(changedDevices);
|
||||
}
|
||||
|
||||
// else if (isAffectedUnacquired >= 0 && !device.unacquired && affectedDevices.length > 1) {
|
||||
// affectedDevices.splice(isAffectedUnacquired, 1);
|
||||
@ -263,12 +284,6 @@ const changeDevice = (state: State, device: Object): State => {
|
||||
if (state.selectedDevice && device.path === state.selectedDevice.id && affectedDevices.length > 1) {
|
||||
// affectedDevices = affectedDevices.filter(d => d.path !== state.selectedDevice.id && d.features);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// replace existing values
|
||||
const changedDevices: Array<TrezorDevice> = affectedDevices.map(d => mergeDevices(d, device));
|
||||
newState.devices = otherDevices.concat(changedDevices);
|
||||
}
|
||||
|
||||
return newState;
|
||||
@ -336,30 +351,33 @@ const devicesFromLocalStorage = (devices: Array<any>): Array<TrezorDevice> => {
|
||||
|
||||
const duplicate = (state: State, device: TrezorDevice): State => {
|
||||
const newState: State = { ...state };
|
||||
const affectedDevices: Array<TrezorDevice> = state.devices.filter(d => d.features && device.features && d.features.device_id === device.features.device_id)
|
||||
.sort((a, b) => {
|
||||
if (!a.instance) {
|
||||
return -1;
|
||||
} else {
|
||||
return !b.instance || a.instance > b.instance ? 1 : -1;
|
||||
}
|
||||
});
|
||||
// const affectedDevices: Array<TrezorDevice> = state.devices.filter(d => d.features && device.features && d.features.device_id === device.features.device_id)
|
||||
// .sort((a, b) => {
|
||||
// if (!a.instance) {
|
||||
// return -1;
|
||||
// } else {
|
||||
// return !b.instance || a.instance > b.instance ? 1 : -1;
|
||||
// }
|
||||
// });
|
||||
|
||||
const instance: number = affectedDevices.reduce((inst, dev) => {
|
||||
return dev.instance ? dev.instance + 1 : inst + 1;
|
||||
}, 0);
|
||||
// const instance: number = affectedDevices.reduce((inst, dev) => {
|
||||
// return dev.instance ? dev.instance + 1 : inst + 1;
|
||||
// }, 0);
|
||||
|
||||
const instance: number = getNewInstance(state.devices, device);
|
||||
|
||||
const newDevice: TrezorDevice = {
|
||||
...device,
|
||||
acquiring: false,
|
||||
// acquiring: false,
|
||||
remember: false,
|
||||
connected: device.connected,
|
||||
available: device.available,
|
||||
path: device.path,
|
||||
label: device.label,
|
||||
// connected: device.connected,
|
||||
// available: device.available,
|
||||
// path: device.path,
|
||||
// label: device.label,
|
||||
state: null,
|
||||
instance,
|
||||
instanceLabel: `${device.label} (${instance})`,
|
||||
// instanceLabel: `${device.label} (${instance})`,
|
||||
instanceLabel: `${device.label} (${ device.instanceName || instance })`,
|
||||
ts: new Date().getTime(),
|
||||
}
|
||||
newState.devices.push(newDevice);
|
||||
@ -450,7 +468,7 @@ export default function connect(state: State = initialState, action: Action): St
|
||||
case DEVICE.CONNECT_UNACQUIRED :
|
||||
return addDevice(state, action.device);
|
||||
case DEVICE.CHANGED :
|
||||
return changeDevice(state, { ...action.device, connected: true, available: true });
|
||||
return changeDevice(state, { ...action.device, connected: true, available: true }); // TODO: check if available will propagate to unavailable
|
||||
case DEVICE.DISCONNECT :
|
||||
case DEVICE.DISCONNECT_UNACQUIRED :
|
||||
return disconnectDevice(state, action.device);
|
||||
|
Loading…
Reference in New Issue
Block a user