diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index d36980f1..0fc29c48 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -3,6 +3,10 @@ image: node:10.15.1
variables:
CYPRESS_CACHE_FOLDER: "$CI_PROJECT_DIR/cache/Cypress"
+before_script:
+ - "apt-get update"
+ - "apt-get install -y build-essential"
+
cache:
key: ${CI_COMMIT_REF_SLUG}
paths:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index d3ed0cac..77c7312a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -9,6 +9,7 @@ __changed__
- static (without animation) active tab indicator
- input validation - mandatory leading 0 for float numbers
- regexps refactored to functions, added unit tests
+- limit passphrase length to 50 bytes
__removed__
- Text "already used" from token select in case of already added tokens
diff --git a/package.json b/package.json
index 37ae1f73..3c632632 100644
--- a/package.json
+++ b/package.json
@@ -33,6 +33,7 @@
},
"dependencies": {
"@babel/polyfill": "^7.2.5",
+ "@hot-loader/react-dom": "16.8.6",
"bignumber.js": "8.0.2",
"color-hash": "^1.0.3",
"commander": "^2.19.0",
@@ -81,7 +82,7 @@
"styled-normalize": "^8.0.6",
"trezor-bridge-communicator": "1.0.2",
"trezor-connect": "7.0.2",
- "trezor-ui-components": "^1.0.0-beta.14",
+ "trezor-ui-components": "^1.0.0-beta.18",
"wallet-address-validator": "^0.2.4",
"web3": "1.0.0-beta.35",
"webpack": "^4.29.3",
diff --git a/src/actions/DiscoveryActions.js b/src/actions/DiscoveryActions.js
index 9347ea84..c3734327 100644
--- a/src/actions/DiscoveryActions.js
+++ b/src/actions/DiscoveryActions.js
@@ -178,7 +178,7 @@ const begin = (device: TrezorDevice, networkName: string): AsyncAction => async
dispatch({
type: NOTIFICATION.ADD,
payload: {
- type: 'error',
+ variant: 'error',
title: ,
message: error.message,
cancelable: true,
@@ -266,7 +266,7 @@ const discoverAccount = (device: TrezorDevice, discoveryProcess: Discovery): Asy
dispatch({
type: NOTIFICATION.ADD,
payload: {
- type: 'error',
+ variant: 'error',
title: ,
message: error.message,
cancelable: true,
diff --git a/src/actions/ImportAccountActions.js b/src/actions/ImportAccountActions.js
index 5e673f60..91a16277 100644
--- a/src/actions/ImportAccountActions.js
+++ b/src/actions/ImportAccountActions.js
@@ -80,7 +80,7 @@ export const importAddress = (
dispatch({
type: NOTIFICATION.ADD,
payload: {
- type: 'success',
+ variant: 'success',
title: 'The account has been successfully imported',
cancelable: true,
},
@@ -132,7 +132,7 @@ export const importAddress = (
dispatch({
type: NOTIFICATION.ADD,
payload: {
- type: 'success',
+ variant: 'success',
title: 'The account has been successfully imported',
cancelable: true,
},
@@ -147,7 +147,7 @@ export const importAddress = (
dispatch({
type: NOTIFICATION.ADD,
payload: {
- type: 'error',
+ variant: 'error',
title: 'Import account error',
message: error.message,
cancelable: true,
diff --git a/src/actions/NotificationActions.js b/src/actions/NotificationActions.js
index 9f847a33..9d9af9c2 100644
--- a/src/actions/NotificationActions.js
+++ b/src/actions/NotificationActions.js
@@ -16,7 +16,7 @@ export type NotificationAction =
| {
type: typeof NOTIFICATION.ADD,
payload: {
- +type: string,
+ +variant: string,
+title: React.Node | MessageDescriptor | string,
+message?: ?(React.Node | string),
+cancelable: boolean,
diff --git a/src/actions/ReceiveActions.js b/src/actions/ReceiveActions.js
index 2aee2821..7516d195 100644
--- a/src/actions/ReceiveActions.js
+++ b/src/actions/ReceiveActions.js
@@ -114,7 +114,7 @@ export const showAddress = (path: Array): AsyncAction => async (
dispatch({
type: NOTIFICATION.ADD,
payload: {
- type: 'error',
+ variant: 'error',
title: ,
message: response.payload.error,
cancelable: true,
diff --git a/src/actions/SelectedAccountActions.js b/src/actions/SelectedAccountActions.js
index 75ef722d..a0459b9f 100644
--- a/src/actions/SelectedAccountActions.js
+++ b/src/actions/SelectedAccountActions.js
@@ -139,6 +139,7 @@ const getAccountNotification = (
if (blockchain && !blockchain.connected) {
return {
type: 'backend',
+ variant: 'error',
title: `${network.name} backend is not connected`,
shouldRender: false,
};
@@ -148,6 +149,7 @@ const getAccountNotification = (
if (account && discovery && !discovery.completed && !discovery.waitingForDevice) {
return {
type: 'info',
+ variant: 'info',
title: 'Loading other accounts...',
shouldRender: true,
};
@@ -157,6 +159,7 @@ const getAccountNotification = (
if (!device.connected) {
return {
type: 'info',
+ variant: 'info',
title: `Device ${device.instanceLabel} is disconnected`,
shouldRender: true,
};
@@ -167,6 +170,7 @@ const getAccountNotification = (
if (!device.available) {
return {
type: 'info',
+ variant: 'info',
title: `Device ${device.instanceLabel} is unavailable`,
message: 'Change passphrase settings to use this device',
shouldRender: true,
diff --git a/src/actions/SignVerifyActions.js b/src/actions/SignVerifyActions.js
index 30878e30..a0722196 100644
--- a/src/actions/SignVerifyActions.js
+++ b/src/actions/SignVerifyActions.js
@@ -67,7 +67,7 @@ const sign = (path: Array, message: string, hex: boolean = false): Async
dispatch({
type: NOTIFICATION.ADD,
payload: {
- type: 'error',
+ variant: 'error',
title: ,
message: response.payload.error,
cancelable: true,
@@ -112,7 +112,7 @@ const verify = (
dispatch({
type: NOTIFICATION.ADD,
payload: {
- type: 'success',
+ variant: 'success',
title: ,
message: ,
cancelable: true,
@@ -122,7 +122,7 @@ const verify = (
dispatch({
type: NOTIFICATION.ADD,
payload: {
- type: 'error',
+ variant: 'error',
title: ,
message: response.payload.error,
cancelable: true,
diff --git a/src/actions/TrezorConnectActions.js b/src/actions/TrezorConnectActions.js
index 87c3d4be..e60931ab 100644
--- a/src/actions/TrezorConnectActions.js
+++ b/src/actions/TrezorConnectActions.js
@@ -268,7 +268,7 @@ export const authorizeDevice = (): AsyncAction => async (
type: NOTIFICATION.ADD,
payload: {
devicePath: selected.path,
- type: 'error',
+ variant: 'error',
title: ,
message: response.payload.error,
cancelable: false,
@@ -355,6 +355,7 @@ export function acquire(): AsyncAction {
type: NOTIFICATION.ADD,
payload: {
type: 'error',
+ variant: 'error',
title: ,
message: response.payload.error,
cancelable: true,
diff --git a/src/actions/ethereum/SendFormActions.js b/src/actions/ethereum/SendFormActions.js
index 4fec6257..92877a12 100644
--- a/src/actions/ethereum/SendFormActions.js
+++ b/src/actions/ethereum/SendFormActions.js
@@ -717,7 +717,7 @@ export const onSend = (): AsyncAction => async (
dispatch({
type: NOTIFICATION.ADD,
payload: {
- type: 'error',
+ variant: 'error',
title: ,
message: signedTransaction.payload.error,
cancelable: true,
@@ -807,7 +807,7 @@ export const onSend = (): AsyncAction => async (
dispatch({
type: NOTIFICATION.ADD,
payload: {
- type: 'success',
+ variant: 'success',
title: ,
message: (
@@ -822,7 +822,7 @@ export const onSend = (): AsyncAction => async (
dispatch({
type: NOTIFICATION.ADD,
payload: {
- type: 'error',
+ variant: 'error',
title: ,
message: error.message || error,
cancelable: true,
diff --git a/src/actions/ripple/SendFormActions.js b/src/actions/ripple/SendFormActions.js
index ae237a5a..fce5ef8b 100644
--- a/src/actions/ripple/SendFormActions.js
+++ b/src/actions/ripple/SendFormActions.js
@@ -457,7 +457,7 @@ export const onSend = (): AsyncAction => async (
dispatch({
type: NOTIFICATION.ADD,
payload: {
- type: 'error',
+ variant: 'error',
title: ,
message: signedTransaction.payload.error,
cancelable: true,
@@ -476,7 +476,7 @@ export const onSend = (): AsyncAction => async (
dispatch({
type: NOTIFICATION.ADD,
payload: {
- type: 'error',
+ variant: 'error',
title: ,
message: push.payload.error,
cancelable: true,
@@ -499,7 +499,7 @@ export const onSend = (): AsyncAction => async (
dispatch({
type: NOTIFICATION.ADD,
payload: {
- type: 'success',
+ variant: 'success',
title: ,
message: txid,
cancelable: true,
diff --git a/src/components/Header/index.js b/src/components/Header/index.js
index 24a7fc8b..622bc178 100644
--- a/src/components/Header/index.js
+++ b/src/components/Header/index.js
@@ -1,237 +1,49 @@
/* eslint-disable jsx-a11y/accessible-emoji */
/* @flow */
-import React from 'react';
-import styled from 'styled-components';
-import { NavLink } from 'react-router-dom';
-import { SCREEN_SIZE } from 'config/variables';
-import { Icon, icons, colors } from 'trezor-ui-components';
+import * as React from 'react';
+import { Header } from 'trezor-ui-components';
import { FormattedMessage } from 'react-intl';
+import { Link } from 'react-router-dom';
import type { toggleSidebar as toggleSidebarType } from 'actions/WalletActions';
import l10nMessages from './index.messages';
import LanguagePicker from './components/LanguagePicker/Container';
-const Wrapper = styled.header`
- width: 100%;
- height: 52px;
- background: ${colors.HEADER};
- z-index: 200;
-`;
-
-const LayoutWrapper = styled.div`
- width: 100%;
- height: 100%;
- max-width: 1170px;
- margin: 0 auto;
- display: flex;
- align-items: center;
- justify-content: space-between;
-
- @media screen and (max-width: 1170px) {
- padding: 0 25px;
- }
-`;
-
-const Left = styled.div`
- display: none;
- flex: 0 0 33%;
-
- @media screen and (max-width: ${SCREEN_SIZE.SM}) {
- display: initial;
- }
-`;
-
-const MenuToggler = styled.div`
- display: none;
- white-space: nowrap;
- color: ${colors.WHITE};
- align-self: center;
- align-items: center;
- cursor: pointer;
- user-select: none;
- padding: 10px 0px;
- transition: all 0.1s ease-in;
-
- @media screen and (max-width: ${SCREEN_SIZE.SM}) {
- display: flex;
- }
-`;
-
-const TogglerText = styled.div`
- margin-left: 6px;
-`;
-
-const TREZOR = styled.div``;
-const T = styled.div``;
-
-const Logo = styled.div`
- flex: 1;
- justify-content: flex-start;
- display: flex;
-
- ${T} {
- display: none;
- width: 20px;
- }
-
- ${TREZOR} {
- width: 100px;
- }
-
- svg {
- fill: ${colors.WHITE};
- height: 28px;
- }
-
- @media screen and (max-width: ${SCREEN_SIZE.SM}) {
- flex: 1 0 33%;
- justify-content: center;
- }
-
- @media screen and (max-width: ${SCREEN_SIZE.XS}) {
- /* hides full width trezor logo, shows only trezor icon */
- ${TREZOR} {
- display: none;
- }
-
- ${T} {
- display: inherit;
- }
- }
-`;
-
-const MenuLinks = styled.div`
- display: flex;
- align-content: center;
- justify-content: flex-end;
- flex: 0;
- height: 100%;
-
- @media screen and (max-width: ${SCREEN_SIZE.SM}) {
- flex: 0 1 33%;
- }
-`;
-
-const Projects = styled.div`
- display: flex;
- align-items: center;
- height: 100%;
- border-right: 1px solid ${colors.HEADER_DIVIDER};
- padding-right: 24px;
- margin-right: 24px;
-
- @media screen and (max-width: ${SCREEN_SIZE.SM}) {
- display: none;
- }
-`;
-
-const A = styled.a`
- color: ${colors.WHITE};
- margin-left: 24px;
- transition: all 0.1s ease-in;
- white-space: nowrap;
-
- &:visited {
- color: ${colors.WHITE};
- margin-left: 24px;
- }
-
- &:first-child {
- margin: 0px;
- }
-
- &:hover,
- &:active {
- color: ${colors.TEXT_SECONDARY};
- }
-`;
-
-type Props = {
+type MyProps = {
sidebarEnabled?: boolean,
sidebarOpened?: ?boolean,
toggleSidebar?: toggleSidebarType,
};
-const Header = ({ sidebarEnabled, sidebarOpened, toggleSidebar }: Props) => (
-
-
-
- {sidebarEnabled && (
-
- {sidebarOpened ? (
- <>
-
-
-
-
- >
- ) : (
- <>
-
-
-
-
- >
- )}
-
- )}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+const MyHeader = ({ sidebarEnabled, sidebarOpened, toggleSidebar }: MyProps) => (
+ }
+ togglerCloseText={}
+ links={[
+ {
+ href: 'https://trezor.io/',
+ title: ,
+ },
+ {
+ href: 'https://wiki.trezor.io/',
+ title: ,
+ },
+ {
+ href: 'https://blog.trezor.io/',
+ title: ,
+ },
+ {
+ href: 'https://trezor.io/support/',
+ title: ,
+ },
+ ]}
+ logoLinkComponent={}
+ rightAddon={}
+ />
);
-export default Header;
+export default MyHeader;
diff --git a/src/components/Log/index.js b/src/components/Log/index.js
index acd51053..7993bd6d 100644
--- a/src/components/Log/index.js
+++ b/src/components/Log/index.js
@@ -28,7 +28,7 @@ type Props = {| ...OwnProps, ...StateProps, ...DispatchProps |};
const Wrapper = styled.div`
position: relative;
color: ${colors.INFO_PRIMARY};
- background: ${colors.INFO_SECONDARY};
+ background: ${colors.INFO_LIGHT};
padding: 24px;
display: flex;
flex-direction: column;
diff --git a/src/components/modals/confirm/NoBackup/index.js b/src/components/modals/confirm/NoBackup/index.js
index 2bd46830..37b1b840 100644
--- a/src/components/modals/confirm/NoBackup/index.js
+++ b/src/components/modals/confirm/NoBackup/index.js
@@ -36,20 +36,6 @@ const BackupButton = styled(Button)`
margin-bottom: 10px;
`;
-const ProceedButton = styled(Button)`
- background: transparent;
- border-color: ${colors.WARNING_PRIMARY};
- color: ${colors.WARNING_PRIMARY};
-
- &:focus,
- &:hover,
- &:active {
- color: ${colors.WHITE};
- background: ${colors.WARNING_PRIMARY};
- box-shadow: none;
- }
-`;
-
const StyledP = styled(P)`
/* boost-specificity hack to override P base styling */
&& {
@@ -80,9 +66,9 @@ const Confirmation = (props: Props) => (
- props.onReceiveConfirmation(true)}>
+
+
);
diff --git a/src/components/modals/confirm/UnverifiedAddress/index.js b/src/components/modals/confirm/UnverifiedAddress/index.js
index 9f8c75eb..790a6406 100644
--- a/src/components/modals/confirm/UnverifiedAddress/index.js
+++ b/src/components/modals/confirm/UnverifiedAddress/index.js
@@ -64,20 +64,6 @@ const BackupButton = styled(Button)`
width: 100%;
`;
-const WarnButton = styled(Button)`
- background: transparent;
- border-color: ${colors.WARNING_PRIMARY};
- color: ${colors.WARNING_PRIMARY};
-
- &:focus,
- &:hover,
- &:active {
- color: ${colors.WHITE};
- background: ${colors.WARNING_PRIMARY};
- box-shadow: none;
- }
-`;
-
class ConfirmUnverifiedAddress extends PureComponent {
componentDidMount(): void {
this.keyboardHandler = this.keyboardHandler.bind(this);
@@ -161,9 +147,13 @@ class ConfirmUnverifiedAddress extends PureComponent {
- this.showUnverifiedAddress()}>
+
+
{needsBackup && }
diff --git a/src/components/modals/passphrase/Passphrase/index.js b/src/components/modals/passphrase/Passphrase/index.js
index e0ef1989..4377ce47 100644
--- a/src/components/modals/passphrase/Passphrase/index.js
+++ b/src/components/modals/passphrase/Passphrase/index.js
@@ -2,6 +2,7 @@
import React, { PureComponent } from 'react';
import PropTypes from 'prop-types';
import styled from 'styled-components';
+import { byteLength } from 'utils/formatUtils';
import { FormattedMessage } from 'react-intl';
import { Button, Input, Checkbox, P, H5, colors } from 'trezor-ui-components';
import { FONT_SIZE } from 'config/variables';
@@ -24,6 +25,7 @@ type State = {
passphraseCheckInputValue: string,
doPassphraseInputsMatch: boolean,
isPassphraseHidden: boolean,
+ byteLength: number,
};
const Wrapper = styled.div`
@@ -91,6 +93,7 @@ class Passphrase extends PureComponent {
passphraseCheckInputValue: '',
doPassphraseInputsMatch: true,
isPassphraseHidden: true,
+ byteLength: 0,
};
}
@@ -117,6 +120,9 @@ class Passphrase extends PureComponent {
let doPassphraseInputsMatch = false;
if (inputName === 'passphraseInputValue') {
+ this.setState({
+ byteLength: byteLength(inputValue),
+ });
// If passphrase is not hidden the second input should get filled automatically
// and should be disabled
if (this.state.isPassphraseHidden) {
@@ -181,13 +187,28 @@ class Passphrase extends PureComponent {
handleKeyPress(event: KeyboardEvent) {
if (event.key === 'Enter') {
event.preventDefault();
- if (this.state.doPassphraseInputsMatch) {
+ if (this.state.doPassphraseInputsMatch && this.state.byteLength <= 50) {
this.submitPassphrase();
}
}
}
render() {
+ let error = null;
+ if (this.state.byteLength > 50) {
+ error = (
+
+
+
+ );
+ } else if (!this.state.doPassphraseInputsMatch) {
+ error = (
+
+
+
+ );
+ }
+
return (
@@ -236,11 +257,7 @@ class Passphrase extends PureComponent {
/>
)}
- {!this.state.doPassphraseInputsMatch && (
-
-
-
- )}
+ {error}
{
-
diff --git a/src/components/modals/passphrase/Passphrase/index.messages.js b/src/components/modals/passphrase/Passphrase/index.messages.js
index 4f6e14f0..4b6c1c49 100644
--- a/src/components/modals/passphrase/Passphrase/index.messages.js
+++ b/src/components/modals/passphrase/Passphrase/index.messages.js
@@ -24,6 +24,10 @@ const definedMessages: Messages = defineMessages({
id: 'TR_PASSPHRASES_DO_NOT_MATCH',
defaultMessage: 'Passphrases do not match!',
},
+ TR_PASSPHRASE_IS_TOO_LONG: {
+ id: 'TR_PASSPHRASE_IS_TOO_LONG',
+ defaultMessage: 'Passphrase is too long!',
+ },
TR_SHOW_PASSPHRASE: {
id: 'TR_SHOW_PASSPHRASE',
defaultMessage: 'Show passphrase',
diff --git a/src/components/modals/pin/Pin/index.js b/src/components/modals/pin/Pin/index.js
index d87e7fb9..4a6e4878 100644
--- a/src/components/modals/pin/Pin/index.js
+++ b/src/components/modals/pin/Pin/index.js
@@ -23,12 +23,12 @@ type State = {
const Wrapper = styled.div`
padding: 30px 48px;
+ max-width: 260px;
`;
const InputWrapper = styled.div`
margin-top: 24px;
margin-bottom: 10px;
- max-width: 260px;
`;
const PinRow = styled.div`
display: flex;
diff --git a/src/components/notifications/App/components/NoBackup/index.js b/src/components/notifications/App/components/NoBackup/index.js
index bbe7ffb1..6d6846d3 100644
--- a/src/components/notifications/App/components/NoBackup/index.js
+++ b/src/components/notifications/App/components/NoBackup/index.js
@@ -13,7 +13,7 @@ export default (props: Props) => {
return (
}
message={}
actions={[
diff --git a/src/components/notifications/App/components/OnlineStatus/index.js b/src/components/notifications/App/components/OnlineStatus/index.js
index 529c40a1..5002ee67 100644
--- a/src/components/notifications/App/components/OnlineStatus/index.js
+++ b/src/components/notifications/App/components/OnlineStatus/index.js
@@ -11,7 +11,7 @@ export default (props: Props) => {
return (
diff --git a/src/components/notifications/App/components/UpdateBridge/index.js b/src/components/notifications/App/components/UpdateBridge/index.js
index d5bb1131..1e451bd1 100644
--- a/src/components/notifications/App/components/UpdateBridge/index.js
+++ b/src/components/notifications/App/components/UpdateBridge/index.js
@@ -11,7 +11,7 @@ export default (props: Props) => {
return (
{
return (
{
// TODO: this is a different component with "auto resolve" button
return (
{
}
return (
diff --git a/src/components/notifications/Context/components/Action/components/NotificationsGroups/components/Group/index.js b/src/components/notifications/Context/components/Action/components/NotificationsGroups/components/Group/index.js
index 2e9fffae..74232118 100644
--- a/src/components/notifications/Context/components/Action/components/NotificationsGroups/components/Group/index.js
+++ b/src/components/notifications/Context/components/Action/components/NotificationsGroups/components/Group/index.js
@@ -77,17 +77,17 @@ class Group extends PureComponent {
};
render() {
- const { type, groupNotifications, close } = this.props;
- const color = getPrimaryColor(type);
+ const { variant, groupNotifications, close } = this.props;
+ const color = getPrimaryColor(variant);
return (
{groupNotifications.length > 1 && (
-
+
{groupNotifications.length}{' '}
- {groupNotifications.length > 1 ? `${type}s` : type}
+ {groupNotifications.length > 1 ? `${variant}s` : variant}
@@ -105,7 +105,7 @@ class Group extends PureComponent {
{groupNotifications.slice(0, this.state.visibleCount).map(notification => (
notifications.reduce((acc, obj) => {
- const key = obj.type;
+ const key = obj.variant;
if (!acc[key]) {
acc[key] = [];
}
@@ -20,6 +20,7 @@ class NotificationsGroup extends PureComponent {
}, {});
sortByPriority(notifications) {
+ //TODO
return notifications;
}
@@ -29,51 +30,53 @@ class NotificationsGroup extends PureComponent {
// {
// key: 1,
// title: 'this is a title of error notification',
- // type: 'error',
+ // variant: 'error',
// message: 'this is a message of error notification',
// },
// {
// key: 2,
// title: 'this is a title of warning notification',
- // type: 'warning',
+ // variant: 'warning',
// message: 'this is a message of warning notification',
// },
// {
// key: 3,
// title: 'this is a title of warning notification',
- // type: 'warning',
+ // variant: 'warning',
// message: 'this is a message of warning notification',
// },
// {
// key: 4,
// title: 'this is a title of warning notification sds d',
- // type: 'warning',
+ // variant: 'warning',
// message: 'this is a message of warning notification',
// },
// {
// key: 5,
// title: 'this is a title of warning notification as',
- // type: 'success',
+ // variant: 'success',
// },
// {
// key: 6,
// title: 'this is a title of warning notification as',
- // type: 'info',
+ // variant: 'info',
// message: 'this is a message of warning notification',
// },
// {
// key: 7,
// title: 'this is a title of info notification s ',
- // type: 'info',
+ // variant: 'info',
// message: 'this is a message of info notification',
- // actions:
- // [{
+ // actions: [
+ // {
// label: 'Update',
// callback: 'props.routerActions.gotoBridgeUpdate',
- // }],
+ // },
+ // ],
// },
// ];
const notificationGroups = this.groupNotifications(notifications);
+ console.log(notificationGroups);
const sortedNotifications = this.sortByPriority(notificationGroups);
return (
@@ -82,7 +85,7 @@ class NotificationsGroup extends PureComponent {
))}
diff --git a/src/components/notifications/Context/components/Static/index.js b/src/components/notifications/Context/components/Static/index.js
index d14c5aa0..fa30ff68 100644
--- a/src/components/notifications/Context/components/Static/index.js
+++ b/src/components/notifications/Context/components/Static/index.js
@@ -30,7 +30,7 @@ export default withRouter((props: {| ...Props, ...ContextRouter |}) => {
notifications.push(
}
@@ -61,7 +61,7 @@ export default withRouter((props: {| ...Props, ...ContextRouter |}) => {
notifications.push(
@@ -72,7 +72,7 @@ export default withRouter((props: {| ...Props, ...ContextRouter |}) => {
notifications.push(
diff --git a/src/reducers/NotificationReducer.js b/src/reducers/NotificationReducer.js
index a13cd240..4e387698 100644
--- a/src/reducers/NotificationReducer.js
+++ b/src/reducers/NotificationReducer.js
@@ -16,7 +16,7 @@ export type NotificationEntry = {
+key: string, // React.Key
+id: ?string,
+devicePath: ?string,
- +type: string,
+ +variant: string,
+title: React.Node | string,
+message: ?(React.Node | string),
+cancelable: boolean,
@@ -42,7 +42,7 @@ const addNotification = (state: State, payload: any): State => {
key: new Date().getTime().toString(),
id: payload.id,
devicePath: payload.devicePath,
- type: payload.type,
+ variant: payload.variant,
title: payload.title,
message: payload.message,
cancelable: payload.cancelable,
diff --git a/src/reducers/SelectedAccountReducer.js b/src/reducers/SelectedAccountReducer.js
index 4ae2fa08..ee58ab0e 100644
--- a/src/reducers/SelectedAccountReducer.js
+++ b/src/reducers/SelectedAccountReducer.js
@@ -10,7 +10,7 @@ export type Loader = {
};
export type Notification = {
- type: string,
+ variant: string,
title: string,
message?: string,
};
diff --git a/src/store.js b/src/store.js
index e6895fa7..aceb7240 100644
--- a/src/store.js
+++ b/src/store.js
@@ -20,8 +20,8 @@ const enhancers = [];
const middlewares = [thunk, routerMiddleware(history)];
-// sentry io middleware only in dev and beta build
-if (buildUtils.isDev() || buildUtils.isBeta()) {
+// sentry io middleware only in beta build
+if (buildUtils.isBeta()) {
const RAVEN_KEY = 'https://34b8c09deb6c4cd2a4dc3f0029cd02d8@sentry.io/1279550';
const ravenMiddleware = RavenMiddleware(RAVEN_KEY);
Raven.config(RAVEN_KEY).install();
diff --git a/src/utils/__tests__/formatUtils.test.js b/src/utils/__tests__/formatUtils.test.js
index 4d57d0d1..67defb4a 100644
--- a/src/utils/__tests__/formatUtils.test.js
+++ b/src/utils/__tests__/formatUtils.test.js
@@ -21,4 +21,14 @@ describe('format utils', () => {
expect(utils.fromDecimalAmount('a', 'a')).toBe('0');
expect(utils.fromDecimalAmount('a', '1')).toBe('0');
});
+
+ describe('byteLength', () => {
+ it('should return correct byte length for strings with special ASCII characters', () => {
+ expect(utils.byteLength('testString')).toEqual(10);
+ expect(utils.byteLength('~!@#$%^&*()_+{}|:?><')).toEqual(20);
+ expect(utils.byteLength('😀')).toEqual(4);
+ expect(utils.byteLength('ä')).toEqual(2);
+ expect(utils.byteLength('áľščť')).toEqual(10);
+ });
+ });
});
diff --git a/src/utils/__tests__/notification.test.js b/src/utils/__tests__/notification.test.js
index c2ef912d..176c6a80 100644
--- a/src/utils/__tests__/notification.test.js
+++ b/src/utils/__tests__/notification.test.js
@@ -11,13 +11,13 @@ describe('notification utils', () => {
expect(utils.getPrimaryColor('')).toBe(null);
});
- it('get secondary color from status', () => {
- expect(utils.getSecondaryColor('info')).toBe(colors.INFO_SECONDARY);
- expect(utils.getSecondaryColor('warning')).toBe(colors.WARNING_SECONDARY);
- expect(utils.getSecondaryColor('error')).toBe(colors.ERROR_SECONDARY);
- expect(utils.getSecondaryColor('success')).toBe(colors.SUCCESS_SECONDARY);
- expect(utils.getSecondaryColor('kdsjflds')).toBe(null);
- expect(utils.getSecondaryColor('')).toBe(null);
+ it('get notification bg color from status', () => {
+ expect(utils.getNotificationBgColor('info')).toBe(colors.INFO_LIGHT);
+ expect(utils.getNotificationBgColor('warning')).toBe(colors.WARNING_LIGHT);
+ expect(utils.getNotificationBgColor('error')).toBe(colors.ERROR_LIGHT);
+ expect(utils.getNotificationBgColor('success')).toBe(colors.SUCCESS_LIGHT);
+ expect(utils.getNotificationBgColor('kdsjflds')).toBe(null);
+ expect(utils.getNotificationBgColor('')).toBe(null);
});
it('get icon according to status', () => {
diff --git a/src/utils/formatUtils.js b/src/utils/formatUtils.js
index 4cea3e00..392ef109 100644
--- a/src/utils/formatUtils.js
+++ b/src/utils/formatUtils.js
@@ -27,3 +27,14 @@ export const fromDecimalAmount = (amount: string | number, decimals: number): st
return '0';
}
};
+
+export const byteLength = (text: string): number => {
+ // returns length of the text in bytes, 0 in case of error.
+ try {
+ // regexp is handling cases when encodeURI returns '%uXXXX' or %XX%XX
+ return encodeURI(text).split(/%(?:u[0-9A-F]{2})?[0-9A-F]{2}|./).length - 1;
+ } catch (error) {
+ console.error(error);
+ return 0;
+ }
+};
diff --git a/src/utils/notification.js b/src/utils/notification.js
index 884a6dd8..2e9c62e8 100644
--- a/src/utils/notification.js
+++ b/src/utils/notification.js
@@ -22,20 +22,20 @@ const getPrimaryColor = type => {
return color;
};
-const getSecondaryColor = type => {
+const getNotificationBgColor = type => {
let color;
switch (type) {
case 'info':
- color = colors.INFO_SECONDARY;
+ color = colors.INFO_LIGHT;
break;
case 'error':
- color = colors.ERROR_SECONDARY;
+ color = colors.ERROR_LIGHT;
break;
case 'warning':
- color = colors.WARNING_SECONDARY;
+ color = colors.WARNING_LIGHT;
break;
case 'success':
- color = colors.SUCCESS_SECONDARY;
+ color = colors.SUCCESS_LIGHT;
break;
default:
color = null;
@@ -46,4 +46,4 @@ const getSecondaryColor = type => {
const getIcon = type => icons[type.toUpperCase()];
-export { getPrimaryColor, getSecondaryColor, getIcon };
+export { getPrimaryColor, getNotificationBgColor, getIcon };
diff --git a/src/views/Landing/components/InitializationError/index.js b/src/views/Landing/components/InitializationError/index.js
index bb19573f..f39bc2e9 100644
--- a/src/views/Landing/components/InitializationError/index.js
+++ b/src/views/Landing/components/InitializationError/index.js
@@ -13,7 +13,7 @@ const InitializationError = (props: { error: string }) => (
diff --git a/src/views/Wallet/views/Account/Receive/ethereum/index.js b/src/views/Wallet/views/Account/Receive/ethereum/index.js
index c5813bf0..044a7e0c 100644
--- a/src/views/Wallet/views/Account/Receive/ethereum/index.js
+++ b/src/views/Wallet/views/Account/Receive/ethereum/index.js
@@ -78,7 +78,7 @@ const QrWrapper = styled.div`
`;
const StyledDeviceIcon = styled(DeviceIcon)`
- margin: 0 6px;
+ margin-right: 6px;
`;
const AccountReceive = (props: Props) => {
@@ -118,7 +118,7 @@ const AccountReceive = (props: Props) => {
topLabel={props.intl.formatMessage(l10nCommonMessages.TR_ADDRESS)}
value={address}
isPartiallyHidden={isAddressHidden}
- trezorAction={
+ tooltipAction={
isAddressVerifying ? (
{
@@ -124,7 +124,7 @@ const AccountReceive = (props: Props) => {
topLabel={props.intl.formatMessage(l10nCommonMessages.TR_ADDRESS)}
value={address}
isPartiallyHidden={isAddressHidden}
- trezorAction={
+ tooltipAction={
isAddressVerifying ? (
{
}
}}
loadOptions={input => props.loadTokens(input, account.network)}
- formatOptionLabel={option => option.name}
+ formatOptionLabel={option => {
+ const isAdded = tokens.find(t => t.symbol === option.symbol);
+ if (isAdded) {
+ return `${option.name} (${props.intl.formatMessage(
+ l10nSummaryMessages.TR_ALREADY_ADDED
+ )})`;
+ }
+ return option.name;
+ }}
getOptionLabel={option => option.name}
getOptionValue={option => option.symbol}
/>
diff --git a/src/views/Wallet/views/Acquire/index.js b/src/views/Wallet/views/Acquire/index.js
index 8e84263f..de2dede0 100644
--- a/src/views/Wallet/views/Acquire/index.js
+++ b/src/views/Wallet/views/Acquire/index.js
@@ -37,7 +37,7 @@ const Acquire = (props: Props) => (
{
isDisabled={
!selectedNetwork || address === '' || props.importAccount.loading
}
+ isLoading={props.importAccount.loading}
onClick={() =>
props.importAddress(
address,
diff --git a/src/views/Wallet/views/UnreadableDevice/index.js b/src/views/Wallet/views/UnreadableDevice/index.js
index 847f59a5..2ef951d9 100644
--- a/src/views/Wallet/views/UnreadableDevice/index.js
+++ b/src/views/Wallet/views/UnreadableDevice/index.js
@@ -14,7 +14,7 @@ const UnreadableDevice = ({ intl }: { intl: IntlShape }) => (
diff --git a/translations/master.json b/translations/master.json
index 8e42c6e0..2931d9ca 100644
--- a/translations/master.json
+++ b/translations/master.json
@@ -1615,6 +1615,14 @@
]
}
},
+ "TR_ALREADY_ADDED": {
+ "source": "Already added",
+ "meta": {
+ "occurrences": [
+ "src/views/Wallet/views/Account/Summary/common.messages.js"
+ ]
+ }
+ },
"TR_HISTORY": {
"source": "History",
"meta": {
diff --git a/webpack/dev.babel.js b/webpack/dev.babel.js
index 21e25db7..3cc7f6e9 100644
--- a/webpack/dev.babel.js
+++ b/webpack/dev.babel.js
@@ -88,6 +88,7 @@ module.exports = {
alias: {
public: PUBLIC,
react: path.resolve('./node_modules/react'),
+ 'react-dom': '@hot-loader/react-dom',
},
modules: [SRC, 'node_modules'],
symlinks: false,
diff --git a/yarn.lock b/yarn.lock
index 9780960c..dfb730d3 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -858,6 +858,16 @@
resolved "https://registry.yarnpkg.com/@emotion/utils/-/utils-0.8.2.tgz#576ff7fb1230185b619a75d258cbc98f0867a8dc"
integrity sha512-rLu3wcBWH4P5q1CGoSSH/i9hrXs7SlbRLkoq9IGuoPYNGQvDJ3pt/wmOM+XgYjIDRMVIdkUWt0RsfzF50JfnCw==
+"@hot-loader/react-dom@16.8.6":
+ version "16.8.6"
+ resolved "https://registry.yarnpkg.com/@hot-loader/react-dom/-/react-dom-16.8.6.tgz#7923ba27db1563a7cc48d4e0b2879a140df461ea"
+ integrity sha512-+JHIYh33FVglJYZAUtRjfT5qZoT2mueJGNzU5weS2CVw26BgbxGKSujlJhO85BaRbg8sqNWyW1hYBILgK3ZCgA==
+ dependencies:
+ loose-envify "^1.1.0"
+ object-assign "^4.1.1"
+ prop-types "^15.6.2"
+ scheduler "^0.13.6"
+
"@mrmlnc/readdir-enhanced@^2.2.1":
version "2.2.1"
resolved "https://registry.yarnpkg.com/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz#524af240d1a360527b730475ecfa1344aa540dde"
@@ -11194,10 +11204,10 @@ trezor-translations-manager@^1.0.5:
request "^2.88.0"
request-promise-native "^1.0.5"
-trezor-ui-components@^1.0.0-beta.14:
- version "1.0.0-beta.14"
- resolved "https://registry.yarnpkg.com/trezor-ui-components/-/trezor-ui-components-1.0.0-beta.14.tgz#5d6dd3a8f5e1ace33a03eae7bb6d089ae0866575"
- integrity sha512-jJ8hMn6Y97lg1a3YMUgQoCosYiPH3L43IJPapAw1c6PSVCPk43QUcbPxtA629Iv32EdCiMlDvANlZgyY9kH98g==
+trezor-ui-components@^1.0.0-beta.18:
+ version "1.0.0-beta.18"
+ resolved "https://registry.yarnpkg.com/trezor-ui-components/-/trezor-ui-components-1.0.0-beta.18.tgz#2408dbdedc83e986abcde9d8b2aec3ec37bbdc43"
+ integrity sha512-mwS7dqrAUto25ytZpF9K2BQpjTBH78/PJjHVGBoZrLJkONogqOvCCdIbkrUSkNR+ZTep4MoxDF3ZN7SXGsFr+g==
dependencies:
"@tippy.js/react" "^2.1.1"
prop-types "^15.7.2"