-
-
-
-
-
-
-
-
-
-
+
+
+ Please be aware that this version is still under development
+
+
+ )
+ }
+
+ render () {
+ const { isPopup } = this.props
+
+ return (
+
+ { !isPopup && this.renderAppBar() }
+
+
+
+
+
+
+
+
+
+
+
+
)
}
@@ -73,6 +97,7 @@ const mapStateToProps = ({ metamask }) => {
isMascara,
isUnlocked,
welcomeScreenSeen,
+ isPopup,
} = metamask
return {
@@ -84,6 +109,7 @@ const mapStateToProps = ({ metamask }) => {
forgottenPassword,
isUnlocked,
welcomeScreenSeen,
+ isPopup,
}
}
diff --git a/package-lock.json b/package-lock.json
index 1bd8ecfa8..45245dab5 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1365,12 +1365,37 @@
}
}
},
+ "@types/jss": {
+ "version": "9.5.2",
+ "resolved": "https://registry.npmjs.org/@types/jss/-/jss-9.5.2.tgz",
+ "integrity": "sha512-EX87yNYcisXO5BU9tT7stB7OGuDJyV3JwtMwhfUprrmHwYKWh9a3vchAy6DYzUSbmTA7bD46h8qata5jP1V7Zw==",
+ "requires": {
+ "csstype": "2.4.2",
+ "indefinite-observable": "1.0.1"
+ }
+ },
"@types/node": {
"version": "8.5.5",
"resolved": "https://registry.npmjs.org/@types/node/-/node-8.5.5.tgz",
"integrity": "sha512-JRnfoh0Ll4ElmIXKxbUfcOodkGvcNHljct6mO1X9hE/mlrMzAx0hYCLAD7sgT53YAY1HdlpzUcV0CkmDqUqTuA==",
"dev": true
},
+ "@types/react": {
+ "version": "16.3.14",
+ "resolved": "https://registry.npmjs.org/@types/react/-/react-16.3.14.tgz",
+ "integrity": "sha512-wNUGm49fPl7eE2fnYdF0v5vSOrUMdKMQD/4NwtQRnb6mnPwtkhabmuFz37eq90+hhyfz0pWd38jkZHOcaZ6LGw==",
+ "requires": {
+ "csstype": "2.4.2"
+ }
+ },
+ "@types/react-transition-group": {
+ "version": "2.0.9",
+ "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-2.0.9.tgz",
+ "integrity": "sha512-Id2MtQcmOgLymqqLqg1VjzNpN7O5vGoF47h3s7jxhzqWdMCtk2GwxFUqcKbGrRmHzzQGyRatfG8yahonIys74Q==",
+ "requires": {
+ "@types/react": "16.3.14"
+ }
+ },
"JSONStream": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.2.tgz",
@@ -3862,8 +3887,7 @@
"brcast": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/brcast/-/brcast-3.0.1.tgz",
- "integrity": "sha512-eI3yqf9YEqyGl9PCNTR46MGvDylGtaHjalcz6Q3fAPnP/PhpKkkve52vFdfGpwp4VUvK6LUr4TQN+2stCrEwTg==",
- "dev": true
+ "integrity": "sha512-eI3yqf9YEqyGl9PCNTR46MGvDylGtaHjalcz6Q3fAPnP/PhpKkkve52vFdfGpwp4VUvK6LUr4TQN+2stCrEwTg=="
},
"brfs": {
"version": "1.4.3",
@@ -5907,6 +5931,14 @@
}
}
},
+ "css-vendor": {
+ "version": "0.3.8",
+ "resolved": "https://registry.npmjs.org/css-vendor/-/css-vendor-0.3.8.tgz",
+ "integrity": "sha1-ZCHP0wNM5mT+dnOXL9ARn8KJQfo=",
+ "requires": {
+ "is-in-browser": "1.1.3"
+ }
+ },
"css-what": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.0.tgz",
@@ -6053,8 +6085,7 @@
"csstype": {
"version": "2.4.2",
"resolved": "https://registry.npmjs.org/csstype/-/csstype-2.4.2.tgz",
- "integrity": "sha512-1TnkyZwDy0oUl//6685j2bTMNe61SzntWntijNdmmEzvpYbGmVMZkj204gv4glcQp6z/ypg+YRziT91XVFmOyg==",
- "dev": true
+ "integrity": "sha512-1TnkyZwDy0oUl//6685j2bTMNe61SzntWntijNdmmEzvpYbGmVMZkj204gv4glcQp6z/ypg+YRziT91XVFmOyg=="
},
"currency-formatter": {
"version": "1.4.2",
@@ -13161,8 +13192,7 @@
"hyphenate-style-name": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/hyphenate-style-name/-/hyphenate-style-name-1.0.2.tgz",
- "integrity": "sha1-MRYKNpMK2vH8BMYHT360FGXU7Es=",
- "dev": true
+ "integrity": "sha1-MRYKNpMK2vH8BMYHT360FGXU7Es="
},
"i": {
"version": "0.3.6",
@@ -13301,6 +13331,21 @@
"resolved": "https://registry.npmjs.org/in-publish/-/in-publish-2.0.0.tgz",
"integrity": "sha1-4g/146KvwmkDILbcVSaCqcf631E="
},
+ "indefinite-observable": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/indefinite-observable/-/indefinite-observable-1.0.1.tgz",
+ "integrity": "sha1-CZFUI8yNb36xy3iCrRNGM8mm7cM=",
+ "requires": {
+ "symbol-observable": "1.0.4"
+ },
+ "dependencies": {
+ "symbol-observable": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.0.4.tgz",
+ "integrity": "sha1-Kb9hXUqnEhvdiYsi1LP5vE4qoD0="
+ }
+ }
+ },
"indent-string": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz",
@@ -13792,6 +13837,11 @@
"resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-1.0.1.tgz",
"integrity": "sha1-bghLvJIGH7sJcexYts5tQE4k2mk="
},
+ "is-in-browser": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/is-in-browser/-/is-in-browser-1.1.3.tgz",
+ "integrity": "sha1-Vv9NtoOgeMYILrldrX3GLh0E+DU="
+ },
"is-my-ip-valid": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-my-ip-valid/-/is-my-ip-valid-1.0.0.tgz",
@@ -14755,6 +14805,101 @@
"verror": "1.10.0"
}
},
+ "jss": {
+ "version": "9.8.1",
+ "resolved": "https://registry.npmjs.org/jss/-/jss-9.8.1.tgz",
+ "integrity": "sha512-a9dXInEPTRmdSmzw3LNhbAwdQVZgCRmFU7dFzrpLTMAcdolHXNamhxQ6J+PNIqUtWa9yRbZIzWX6aUlI55LZ/A==",
+ "requires": {
+ "is-in-browser": "1.1.3",
+ "symbol-observable": "1.1.0",
+ "warning": "3.0.0"
+ }
+ },
+ "jss-camel-case": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/jss-camel-case/-/jss-camel-case-6.1.0.tgz",
+ "integrity": "sha512-HPF2Q7wmNW1t79mCqSeU2vdd/vFFGpkazwvfHMOhPlMgXrJDzdj9viA2SaHk9ZbD5pfL63a8ylp4++irYbbzMQ==",
+ "requires": {
+ "hyphenate-style-name": "1.0.2"
+ }
+ },
+ "jss-compose": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/jss-compose/-/jss-compose-5.0.0.tgz",
+ "integrity": "sha512-YofRYuiA0+VbeOw0VjgkyO380sA4+TWDrW52nSluD9n+1FWOlDzNbgpZ/Sb3Y46+DcAbOS21W5jo6SAqUEiuwA==",
+ "requires": {
+ "warning": "3.0.0"
+ }
+ },
+ "jss-default-unit": {
+ "version": "8.0.2",
+ "resolved": "https://registry.npmjs.org/jss-default-unit/-/jss-default-unit-8.0.2.tgz",
+ "integrity": "sha512-WxNHrF/18CdoAGw2H0FqOEvJdREXVXLazn7PQYU7V6/BWkCV0GkmWsppNiExdw8dP4TU1ma1dT9zBNJ95feLmg=="
+ },
+ "jss-expand": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/jss-expand/-/jss-expand-5.3.0.tgz",
+ "integrity": "sha512-NiM4TbDVE0ykXSAw6dfFmB1LIqXP/jdd0ZMnlvlGgEMkMt+weJIl8Ynq1DsuBY9WwkNyzWktdqcEW2VN0RAtQg=="
+ },
+ "jss-extend": {
+ "version": "6.2.0",
+ "resolved": "https://registry.npmjs.org/jss-extend/-/jss-extend-6.2.0.tgz",
+ "integrity": "sha512-YszrmcB6o9HOsKPszK7NeDBNNjVyiW864jfoiHoMlgMIg2qlxKw70axZHqgczXHDcoyi/0/ikP1XaHDPRvYtEA==",
+ "requires": {
+ "warning": "3.0.0"
+ }
+ },
+ "jss-global": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/jss-global/-/jss-global-3.0.0.tgz",
+ "integrity": "sha512-wxYn7vL+TImyQYGAfdplg7yaxnPQ9RaXY/cIA8hawaVnmmWxDHzBK32u1y+RAvWboa3lW83ya3nVZ/C+jyjZ5Q=="
+ },
+ "jss-nested": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/jss-nested/-/jss-nested-6.0.1.tgz",
+ "integrity": "sha512-rn964TralHOZxoyEgeq3hXY8hyuCElnvQoVrQwKHVmu55VRDd6IqExAx9be5HgK0yN/+hQdgAXQl/GUrBbbSTA==",
+ "requires": {
+ "warning": "3.0.0"
+ }
+ },
+ "jss-preset-default": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/jss-preset-default/-/jss-preset-default-4.5.0.tgz",
+ "integrity": "sha512-qZbpRVtHT7hBPpZEBPFfafZKWmq3tA/An5RNqywDsZQGrlinIF/mGD9lmj6jGqu8GrED2SMHZ3pPKLmjCZoiaQ==",
+ "requires": {
+ "jss-camel-case": "6.1.0",
+ "jss-compose": "5.0.0",
+ "jss-default-unit": "8.0.2",
+ "jss-expand": "5.3.0",
+ "jss-extend": "6.2.0",
+ "jss-global": "3.0.0",
+ "jss-nested": "6.0.1",
+ "jss-props-sort": "6.0.0",
+ "jss-template": "1.0.1",
+ "jss-vendor-prefixer": "7.0.0"
+ }
+ },
+ "jss-props-sort": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/jss-props-sort/-/jss-props-sort-6.0.0.tgz",
+ "integrity": "sha512-E89UDcrphmI0LzmvYk25Hp4aE5ZBsXqMWlkFXS0EtPkunJkRr+WXdCNYbXbksIPnKlBenGB9OxzQY+mVc70S+g=="
+ },
+ "jss-template": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/jss-template/-/jss-template-1.0.1.tgz",
+ "integrity": "sha512-m5BqEWha17fmIVXm1z8xbJhY6GFJxNB9H68GVnCWPyGYfxiAgY9WTQyvDAVj+pYRgrXSOfN5V1T4+SzN1sJTeg==",
+ "requires": {
+ "warning": "3.0.0"
+ }
+ },
+ "jss-vendor-prefixer": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/jss-vendor-prefixer/-/jss-vendor-prefixer-7.0.0.tgz",
+ "integrity": "sha512-Agd+FKmvsI0HLcYXkvy8GYOw3AAASBUpsmIRvVQheps+JWaN892uFOInTr0DRydwaD91vSSUCU4NssschvF7MA==",
+ "requires": {
+ "css-vendor": "0.3.8"
+ }
+ },
"jstransform": {
"version": "10.1.0",
"resolved": "https://registry.npmjs.org/jstransform/-/jstransform-10.1.0.tgz",
@@ -15134,8 +15279,7 @@
"keycode": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/keycode/-/keycode-2.2.0.tgz",
- "integrity": "sha1-PQr1bce4uOXLqNCpfxByBO7CKwQ=",
- "dev": true
+ "integrity": "sha1-PQr1bce4uOXLqNCpfxByBO7CKwQ="
},
"keyv": {
"version": "3.0.0",
@@ -16642,6 +16786,78 @@
"integrity": "sha1-UpJZPmdUyxvMK5gDDk4Najr8nqE=",
"dev": true
},
+ "material-ui": {
+ "version": "1.0.0-beta.44",
+ "resolved": "https://registry.npmjs.org/material-ui/-/material-ui-1.0.0-beta.44.tgz",
+ "integrity": "sha512-m5SJxvDz77bVKcjyZG/AyG6RBR+UUwkPgvHHLJa2jyAHBNtJMCQ5GVouTXOxaUKlvD5cbO/mcH0YtzugyQTAVg==",
+ "requires": {
+ "@types/jss": "9.5.2",
+ "@types/react-transition-group": "2.0.9",
+ "babel-runtime": "6.26.0",
+ "brcast": "3.0.1",
+ "classnames": "2.2.5",
+ "deepmerge": "2.1.0",
+ "dom-helpers": "3.3.1",
+ "hoist-non-react-statics": "2.5.0",
+ "jss": "9.8.1",
+ "jss-camel-case": "6.1.0",
+ "jss-default-unit": "8.0.2",
+ "jss-global": "3.0.0",
+ "jss-nested": "6.0.1",
+ "jss-props-sort": "6.0.0",
+ "jss-vendor-prefixer": "7.0.0",
+ "keycode": "2.2.0",
+ "lodash": "4.17.4",
+ "normalize-scroll-left": "0.1.2",
+ "prop-types": "15.6.1",
+ "react-event-listener": "0.5.3",
+ "react-jss": "8.4.0",
+ "react-lifecycles-compat": "2.0.2",
+ "react-popper": "0.10.4",
+ "react-scrollbar-size": "2.1.0",
+ "react-transition-group": "2.2.1",
+ "recompose": "0.27.0",
+ "scroll": "2.0.3",
+ "warning": "3.0.0"
+ },
+ "dependencies": {
+ "deepmerge": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-2.1.0.tgz",
+ "integrity": "sha512-Q89Z26KAfA3lpPGhbF6XMfYAm3jIV3avViy6KOJ2JLzFbeWHOvPQUu5aSJIWXap3gDZC2y1eF5HXEPI2wGqgvw=="
+ },
+ "hoist-non-react-statics": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-2.5.0.tgz",
+ "integrity": "sha512-6Bl6XsDT1ntE0lHbIhr4Kp2PGcleGZ66qu5Jqk8lc0Xc/IeG6gVLmwUGs/K0Us+L8VWoKgj0uWdPMataOsm31w=="
+ },
+ "react-lifecycles-compat": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-2.0.2.tgz",
+ "integrity": "sha512-BPksUj7VMAAFhcCw79sZA0Ow/LTAEjs3Sio1AQcuwLeOP+ua0f/08Su2wyiW+JjDDH6fRqNy3h5CLXh21u1mVg=="
+ },
+ "recompose": {
+ "version": "0.27.0",
+ "resolved": "https://registry.npmjs.org/recompose/-/recompose-0.27.0.tgz",
+ "integrity": "sha512-hivr1EopLhzjchhv2Y7VcLA2H5NGztwV/qfYqmIAhTkNowNQ9PyXdfq9Q8QCa0TMrPM1NtStlUyi5I/p8XfUNQ==",
+ "requires": {
+ "babel-runtime": "6.26.0",
+ "change-emitter": "0.1.6",
+ "fbjs": "0.8.16",
+ "hoist-non-react-statics": "2.5.0",
+ "react-lifecycles-compat": "3.0.3",
+ "symbol-observable": "1.1.0"
+ },
+ "dependencies": {
+ "react-lifecycles-compat": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.3.tgz",
+ "integrity": "sha512-bOr65SSYgxDgDNqLnDqt+gropXGPNB1Wbyys4tOYiNuP/qYWC4qFM9XH1ruzq+tT6EjE29pJsCr19rclKtpUEg=="
+ }
+ }
+ }
+ }
+ },
"math-expression-evaluator": {
"version": "1.2.17",
"resolved": "https://registry.npmjs.org/math-expression-evaluator/-/math-expression-evaluator-1.2.17.tgz",
@@ -18140,6 +18356,11 @@
"resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz",
"integrity": "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI="
},
+ "normalize-scroll-left": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/normalize-scroll-left/-/normalize-scroll-left-0.1.2.tgz",
+ "integrity": "sha512-F9YMRls0zCF6BFIE2YnXDRpHPpfd91nOIaNdDgrx5YMoPLo8Wqj+6jNXHQsYBavJeXP4ww8HCt0xQAKc5qk2Fg=="
+ },
"normalize-selector": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/normalize-selector/-/normalize-selector-0.2.0.tgz",
@@ -23395,6 +23616,14 @@
"performance-now": "2.1.0"
}
},
+ "rafl": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/rafl/-/rafl-1.2.2.tgz",
+ "integrity": "sha1-/pMPdYIRAg1H44gV9Rlqi+QVB0A=",
+ "requires": {
+ "global": "4.3.2"
+ }
+ },
"railroad-diagrams": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/railroad-diagrams/-/railroad-diagrams-1.0.0.tgz",
@@ -23688,6 +23917,17 @@
"integrity": "sha512-FlsPxavEyMuR6TjVbSSywovXSEyOg6ZDj5+Z8nbsRl9EkOzAhEIcS+GLoQDC5fz/t9suhUXWmUrOBrgeUvrMxw==",
"dev": true
},
+ "react-event-listener": {
+ "version": "0.5.3",
+ "resolved": "https://registry.npmjs.org/react-event-listener/-/react-event-listener-0.5.3.tgz",
+ "integrity": "sha512-fTGYvhe7eTsqq0m664Km0rxKQcqLIGZWZINmy1LU0fu312tay8Mt3Twq2P5Xj1dfDVvvzT1Ql3/FDkiMPJ1MOg==",
+ "requires": {
+ "babel-runtime": "6.26.0",
+ "fbjs": "0.8.16",
+ "prop-types": "15.6.1",
+ "warning": "3.0.0"
+ }
+ },
"react-fuzzy": {
"version": "0.5.2",
"resolved": "https://registry.npmjs.org/react-fuzzy/-/react-fuzzy-0.5.2.tgz",
@@ -23747,6 +23987,18 @@
"is-dom": "1.0.9"
}
},
+ "react-jss": {
+ "version": "8.4.0",
+ "resolved": "https://registry.npmjs.org/react-jss/-/react-jss-8.4.0.tgz",
+ "integrity": "sha512-yIi4udcTIIh5u4KJ47wsL3UZYMuSrp5xR1YBvPeRNshpCdRoJxt5BWmCu1RA3LIa+//dnRsAtAQmMAYeg1W9oQ==",
+ "requires": {
+ "hoist-non-react-statics": "2.3.1",
+ "jss": "9.8.1",
+ "jss-preset-default": "4.5.0",
+ "prop-types": "15.6.1",
+ "theming": "1.3.0"
+ }
+ },
"react-lifecycles-compat": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.2.tgz",
@@ -23800,6 +24052,22 @@
"integrity": "sha512-p84kBqGaMoa7VYT0vZ/aOYRfJB+gw34yjpda1Z5KeLflg70HipZOT+MXQenEhdkPAABuE2Astq4zEPdMqUQxcg==",
"dev": true
},
+ "react-popper": {
+ "version": "0.10.4",
+ "resolved": "https://registry.npmjs.org/react-popper/-/react-popper-0.10.4.tgz",
+ "integrity": "sha1-rypBXqIike3VBGeNev2opu4ylao=",
+ "requires": {
+ "popper.js": "1.14.3",
+ "prop-types": "15.6.1"
+ },
+ "dependencies": {
+ "popper.js": {
+ "version": "1.14.3",
+ "resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.14.3.tgz",
+ "integrity": "sha1-FDj5jQRqz3tNeM1QK/QYrGTU8JU="
+ }
+ }
+ },
"react-redux": {
"version": "5.0.6",
"resolved": "https://registry.npmjs.org/react-redux/-/react-redux-5.0.6.tgz",
@@ -23855,6 +24123,17 @@
"warning": "3.0.0"
}
},
+ "react-scrollbar-size": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/react-scrollbar-size/-/react-scrollbar-size-2.1.0.tgz",
+ "integrity": "sha512-9dDUJvk7S48r0TRKjlKJ9e/LkLLYgc9LdQR6W21I8ZqtSrEsedPOoMji4nU3DHy7fx2l8YMScJS/N7qiloYzXQ==",
+ "requires": {
+ "babel-runtime": "6.26.0",
+ "prop-types": "15.6.1",
+ "react-event-listener": "0.5.3",
+ "stifle": "1.0.4"
+ }
+ },
"react-select": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/react-select/-/react-select-1.1.0.tgz",
@@ -25106,6 +25385,14 @@
}
}
},
+ "scroll": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/scroll/-/scroll-2.0.3.tgz",
+ "integrity": "sha512-3ncZzf8gUW739h3LeS68nSssO60O+GGjT3SxzgofQmT8PIoyHzebql9HHPJopZX8iT6TKOdwaWFMqL6LzUN3DQ==",
+ "requires": {
+ "rafl": "1.2.2"
+ }
+ },
"scrypt": {
"version": "6.0.3",
"resolved": "https://registry.npmjs.org/scrypt/-/scrypt-6.0.3.tgz",
@@ -26522,6 +26809,11 @@
"resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz",
"integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks="
},
+ "stifle": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/stifle/-/stifle-1.0.4.tgz",
+ "integrity": "sha1-izvN9SQZsKnHnjWtrc5QEjwdjpk="
+ },
"stream-browserify": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.1.tgz",
@@ -27985,6 +28277,17 @@
"integrity": "sha1-ZUhjk+4fK7A5pgy7oFsLaL2VAdI=",
"dev": true
},
+ "theming": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/theming/-/theming-1.3.0.tgz",
+ "integrity": "sha512-ya5Ef7XDGbTPBv5ENTwrwkPUexrlPeiAg/EI9kdlUAZhNlRbCdhMKRgjNX1IcmsmiPcqDQZE6BpSaH+cr31FKw==",
+ "requires": {
+ "brcast": "3.0.1",
+ "is-function": "1.0.1",
+ "is-plain-object": "2.0.4",
+ "prop-types": "15.6.1"
+ }
+ },
"thenify": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.0.tgz",
diff --git a/package.json b/package.json
index 535c5f662..c31e8dbb1 100644
--- a/package.json
+++ b/package.json
@@ -136,6 +136,7 @@
"lodash.shuffle": "^4.2.0",
"lodash.uniqby": "^4.7.0",
"loglevel": "^1.4.1",
+ "material-ui": "1.0.0-beta.44",
"metamascara": "^2.0.0",
"metamask-logo": "^2.1.4",
"mkdirp": "^0.5.1",
diff --git a/test/integration/lib/mascara-first-time.js b/test/integration/lib/mascara-first-time.js
index 5e07ab0b4..f43a30c74 100644
--- a/test/integration/lib/mascara-first-time.js
+++ b/test/integration/lib/mascara-first-time.js
@@ -1,5 +1,4 @@
const PASSWORD = 'password123'
-const reactTriggerChange = require('react-trigger-change')
const {
timeout,
findAsync,
@@ -11,6 +10,11 @@ async function runFirstTimeUsageTest (assert, done) {
const app = await queryAsync($, '#app-content')
+ // Used to set values on TextField input component
+ const nativeInputValueSetter = Object.getOwnPropertyDescriptor(
+ window.HTMLInputElement.prototype, 'value'
+ ).set
+
await skipNotices(app)
const welcomeButton = (await findAsync(app, '.welcome-screen__button'))[0]
@@ -21,12 +25,14 @@ async function runFirstTimeUsageTest (assert, done) {
assert.equal(title, 'Create Password', 'create password screen')
// enter password
- const pwBox = (await findAsync(app, '.first-time-flow__input'))[0]
- const confBox = (await findAsync(app, '.first-time-flow__input'))[1]
- pwBox.value = PASSWORD
- confBox.value = PASSWORD
- reactTriggerChange(pwBox)
- reactTriggerChange(confBox)
+ const pwBox = (await findAsync(app, '#create-password'))[0]
+ const confBox = (await findAsync(app, '#confirm-password'))[0]
+
+ nativeInputValueSetter.call(pwBox, PASSWORD)
+ pwBox.dispatchEvent(new Event('input', { bubbles: true}))
+
+ nativeInputValueSetter.call(confBox, PASSWORD)
+ confBox.dispatchEvent(new Event('input', { bubbles: true}))
// Create Password
const createButton = (await findAsync(app, 'button.first-time-flow__button'))[0]
@@ -71,10 +77,16 @@ async function runFirstTimeUsageTest (assert, done) {
assert.ok(lock, 'Lock menu item found')
lock.click()
- const pwBox2 = (await findAsync(app, '#password-box'))[0]
- pwBox2.value = PASSWORD
+ await timeout(1000)
- const createButton2 = (await findAsync(app, 'button.primary'))[0]
+ const pwBox2 = (await findAsync(app, '#password'))[0]
+ pwBox2.focus()
+ await timeout(1000)
+
+ nativeInputValueSetter.call(pwBox2, PASSWORD)
+ pwBox2.dispatchEvent(new Event('input', { bubbles: true}))
+
+ const createButton2 = (await findAsync(app, 'button[type="submit"]'))[0]
createButton2.click()
const detail2 = (await findAsync(app, '.wallet-view'))[0]
diff --git a/test/integration/lib/tx-list-items.js b/test/integration/lib/tx-list-items.js
index 0c0c5a77f..4856b3852 100644
--- a/test/integration/lib/tx-list-items.js
+++ b/test/integration/lib/tx-list-items.js
@@ -21,7 +21,7 @@ async function runTxListItemsTest(assert, done) {
selectState.val('tx list items')
reactTriggerChange(selectState[0])
- const metamaskLogo = await queryAsync($, '.left-menu-wrapper')
+ const metamaskLogo = await queryAsync($, '.app-header__logo-container')
assert.ok(metamaskLogo[0], 'metamask logo present')
metamaskLogo[0].click()
@@ -46,7 +46,7 @@ async function runTxListItemsTest(assert, done) {
const failedTx = txListItems[4]
const failedTxRenderedStatus = await findAsync($(failedTx), '.tx-list-status')
assert.equal(failedTxRenderedStatus[0].textContent, 'Failed', 'failedTx has correct label')
-
+
const shapeShiftTx = txListItems[5]
const shapeShiftTxStatus = await findAsync($(shapeShiftTx), '.flex-column div:eq(1)')
assert.equal(shapeShiftTxStatus[0].textContent, 'No deposits received', 'shapeShiftTx has correct status')
diff --git a/test/screens/new-ui.js b/test/screens/new-ui.js
index e176da529..6a8822eb3 100644
--- a/test/screens/new-ui.js
+++ b/test/screens/new-ui.js
@@ -74,8 +74,8 @@ async function captureAllScreens() {
await driver.findElement(By.css('button')).click()
await captureLanguageScreenShots('create password')
- const passwordBox = await driver.findElement(By.css('input[type=password]:nth-of-type(1)'))
- const passwordBoxConfirm = await driver.findElement(By.css('input[type=password]:nth-of-type(2)'))
+ const passwordBox = await driver.findElement(By.css('input#create-password'))
+ const passwordBoxConfirm = await driver.findElement(By.css('input#confirm-password'))
passwordBox.sendKeys('123456789')
passwordBoxConfirm.sendKeys('123456789')
await delay(500)
diff --git a/ui/app/actions.js b/ui/app/actions.js
index f060e40bd..9c4de9551 100644
--- a/ui/app/actions.js
+++ b/ui/app/actions.js
@@ -317,6 +317,7 @@ function tryUnlockMetamask (password) {
background.verifySeedPhrase(err => {
if (err) {
dispatch(actions.displayWarning(err.message))
+ return reject(err)
}
resolve()
@@ -330,6 +331,7 @@ function tryUnlockMetamask (password) {
.catch(err => {
dispatch(actions.unlockFailed(err.message))
dispatch(actions.hideLoadingIndication())
+ return Promise.reject(err)
})
}
}
diff --git a/ui/app/app.js b/ui/app/app.js
index c93a6314c..5bc571c64 100644
--- a/ui/app/app.js
+++ b/ui/app/app.js
@@ -1,7 +1,7 @@
const { Component } = require('react')
const PropTypes = require('prop-types')
const connect = require('react-redux').connect
-const { Route, Switch, withRouter } = require('react-router-dom')
+const { Route, Switch, withRouter, matchPath } = require('react-router-dom')
const { compose } = require('recompose')
const h = require('react-hyperscript')
const actions = require('./actions')
@@ -22,7 +22,7 @@ const Home = require('./components/pages/home')
const Authenticated = require('./components/pages/authenticated')
const Initialized = require('./components/pages/initialized')
const Settings = require('./components/pages/settings')
-const UnlockPage = require('./components/pages/unlock')
+const UnlockPage = require('./components/pages/unlock-page')
const RestoreVaultPage = require('./components/pages/keychains/restore-vault')
const RevealSeedConfirmation = require('./components/pages/keychains/reveal-seed')
const AddTokenPage = require('./components/pages/add-token')
@@ -30,8 +30,6 @@ const CreateAccountPage = require('./components/pages/create-account')
const NoticeScreen = require('./components/pages/notice')
const Loading = require('./components/loading-screen')
-const NetworkIndicator = require('./components/network')
-const Identicon = require('./components/identicon')
const ReactCSSTransitionGroup = require('react-addons-css-transition-group')
const NetworkDropdown = require('./components/dropdowns/network-dropdown')
const AccountMenu = require('./components/account-menu')
@@ -39,6 +37,8 @@ const AccountMenu = require('./components/account-menu')
// Global Modals
const Modal = require('./components/modals/index').Modal
+const AppHeader = require('./components/app-header')
+
// Routes
const {
DEFAULT_ROUTE,
@@ -69,11 +69,11 @@ class App extends Component {
return (
h(Switch, [
h(Route, { path: INITIALIZE_ROUTE, component: InitializeScreen }),
- h(Initialized, { path: REVEAL_SEED_ROUTE, exact, component: RevealSeedConfirmation }),
h(Initialized, { path: UNLOCK_ROUTE, exact, component: UnlockPage }),
- h(Initialized, { path: SETTINGS_ROUTE, component: Settings }),
h(Initialized, { path: RESTORE_VAULT_ROUTE, exact, component: RestoreVaultPage }),
- h(Initialized, { path: NOTICE_ROUTE, exact, component: NoticeScreen }),
+ h(Authenticated, { path: REVEAL_SEED_ROUTE, exact, component: RevealSeedConfirmation }),
+ h(Authenticated, { path: SETTINGS_ROUTE, component: Settings }),
+ h(Authenticated, { path: NOTICE_ROUTE, exact, component: NoticeScreen }),
h(Authenticated, { path: CONFIRM_TRANSACTION_ROUTE, component: ConfirmTxScreen }),
h(Authenticated, { path: SEND_ROUTE, exact, component: SendTransactionScreen2 }),
h(Authenticated, { path: ADD_TOKEN_ROUTE, exact, component: AddTokenPage }),
@@ -83,6 +83,15 @@ class App extends Component {
)
}
+ renderAppHeader () {
+ const { location } = this.props
+ const isInitializing = matchPath(location.pathname, {
+ path: INITIALIZE_ROUTE, exact: false,
+ })
+
+ return isInitializing ? null : h(AppHeader)
+ }
+
render () {
const {
isLoading,
@@ -119,8 +128,7 @@ class App extends Component {
// global modal
h(Modal, {}, []),
- // app bar
- this.renderAppBar(),
+ this.renderAppHeader(),
// sidebar
this.renderSidebar(),
@@ -197,110 +205,6 @@ class App extends Component {
])
}
- renderAppBar () {
- const {
- isUnlocked,
- network,
- provider,
- networkDropdownOpen,
- showNetworkDropdown,
- hideNetworkDropdown,
- isInitialized,
- welcomeScreenSeen,
- isPopup,
- betaUI,
- } = this.props
-
- if (window.METAMASK_UI_TYPE === 'notification') {
- return null
- }
-
- const props = this.props
- const {isMascara, isOnboarding} = props
-
- // Do not render header if user is in mascara onboarding
- if (isMascara && isOnboarding) {
- return null
- }
-
- // Do not render header if user is in mascara buy ether
- if (isMascara && props.currentView.name === 'buyEth') {
- return null
- }
-
- return (
-
- h('.full-width', {
- style: {},
- }, [
-
- (isInitialized || welcomeScreenSeen || isPopup || !betaUI) && h('.app-header.flex-row.flex-space-between', {
- className: classnames({
- 'app-header--initialized': !isOnboarding,
- }),
- }, [
- h('div.app-header-contents', {}, [
- h('div.left-menu-wrapper', {
- onClick: () => props.history.push(DEFAULT_ROUTE),
- }, [
- // mini logo
- h('img.metafox-icon', {
- height: 42,
- width: 42,
- src: '/images/metamask-fox.svg',
- }),
-
- // metamask name
- h('.flex-row', [
- h('h1', this.context.t('appName')),
- h('div.beta-label', this.context.t('beta')),
- ]),
-
- ]),
-
- betaUI && isInitialized && h('div.header__right-actions', [
- h('div.network-component-wrapper', {
- style: {},
- }, [
- // Network Indicator
- h(NetworkIndicator, {
- network,
- provider,
- disabled: this.props.location.pathname === CONFIRM_TRANSACTION_ROUTE,
- onClick: (event) => {
- event.preventDefault()
- event.stopPropagation()
- return networkDropdownOpen === false
- ? showNetworkDropdown()
- : hideNetworkDropdown()
- },
- }),
-
- ]),
-
- isUnlocked && h('div.account-menu__icon', { onClick: this.props.toggleAccountMenu }, [
- h(Identicon, {
- address: this.props.selectedAddress,
- diameter: 32,
- }),
- ]),
- ]),
- ]),
- ]),
-
- !isInitialized && !isPopup && betaUI && h('.alpha-warning__container', {}, [
- h('h2', {
- className: classnames({
- 'alpha-warning': welcomeScreenSeen,
- 'alpha-warning-welcome-screen': !welcomeScreenSeen,
- }),
- }, 'Please be aware that this version is still under development'),
- ]),
-
- ])
- )
- }
-
toggleMetamaskActive () {
if (!this.props.isUnlocked) {
// currently inactive: redirect to password box
diff --git a/ui/app/components/app-header/app-header.component.js b/ui/app/components/app-header/app-header.component.js
new file mode 100644
index 000000000..cf36e0d79
--- /dev/null
+++ b/ui/app/components/app-header/app-header.component.js
@@ -0,0 +1,106 @@
+import React, { Component } from 'react'
+import PropTypes from 'prop-types'
+import classnames from 'classnames'
+
+const { ENVIRONMENT_TYPE_NOTIFICATION } = require('../../../../app/scripts/lib/enums')
+const { DEFAULT_ROUTE, CONFIRM_TRANSACTION_ROUTE } = require('../../routes')
+const Identicon = require('../identicon')
+const NetworkIndicator = require('../network')
+
+class AppHeader extends Component {
+ static propTypes = {
+ history: PropTypes.object,
+ location: PropTypes.object,
+ network: PropTypes.string,
+ provider: PropTypes.object,
+ networkDropdownOpen: PropTypes.bool,
+ showNetworkDropdown: PropTypes.func,
+ hideNetworkDropdown: PropTypes.func,
+ toggleAccountMenu: PropTypes.func,
+ selectedAddress: PropTypes.string,
+ isUnlocked: PropTypes.bool,
+ }
+
+ static contextTypes = {
+ t: PropTypes.func,
+ }
+
+ handleNetworkIndicatorClick (event) {
+ event.preventDefault()
+ event.stopPropagation()
+
+ const { networkDropdownOpen, showNetworkDropdown, hideNetworkDropdown } = this.props
+
+ return networkDropdownOpen === false
+ ? showNetworkDropdown()
+ : hideNetworkDropdown()
+ }
+
+ renderAccountMenu () {
+ const { isUnlocked, toggleAccountMenu, selectedAddress } = this.props
+
+ return isUnlocked && (
+
+
+
+ )
+ }
+
+ render () {
+ const {
+ network,
+ provider,
+ history,
+ location,
+ isUnlocked,
+ } = this.props
+
+ if (window.METAMASK_UI_TYPE === ENVIRONMENT_TYPE_NOTIFICATION) {
+ return null
+ }
+
+ return (
+
+
+
history.push(DEFAULT_ROUTE)}
+ >
+
+
+
{ this.context.t('appName') }
+
+ { this.context.t('beta') }
+
+
+
+
+
+ this.handleNetworkIndicatorClick(event)}
+ disabled={location.pathname === CONFIRM_TRANSACTION_ROUTE}
+ />
+
+ { this.renderAccountMenu() }
+
+
+
+ )
+ }
+}
+
+export default AppHeader
diff --git a/ui/app/components/app-header/app-header.container.js b/ui/app/components/app-header/app-header.container.js
new file mode 100644
index 000000000..30d3f8cc4
--- /dev/null
+++ b/ui/app/components/app-header/app-header.container.js
@@ -0,0 +1,38 @@
+import { connect } from 'react-redux'
+import { withRouter } from 'react-router-dom'
+import { compose } from 'recompose'
+
+import AppHeader from './app-header.component'
+const actions = require('../../actions')
+
+const mapStateToProps = state => {
+ const { appState, metamask } = state
+ const { networkDropdownOpen } = appState
+ const {
+ network,
+ provider,
+ selectedAddress,
+ isUnlocked,
+ } = metamask
+
+ return {
+ networkDropdownOpen,
+ network,
+ provider,
+ selectedAddress,
+ isUnlocked,
+ }
+}
+
+const mapDispatchToProps = dispatch => {
+ return {
+ showNetworkDropdown: () => dispatch(actions.showNetworkDropdown()),
+ hideNetworkDropdown: () => dispatch(actions.hideNetworkDropdown()),
+ toggleAccountMenu: () => dispatch(actions.toggleAccountMenu()),
+ }
+}
+
+export default compose(
+ withRouter,
+ connect(mapStateToProps, mapDispatchToProps)
+)(AppHeader)
diff --git a/ui/app/components/app-header/index.js b/ui/app/components/app-header/index.js
new file mode 100644
index 000000000..daa31f621
--- /dev/null
+++ b/ui/app/components/app-header/index.js
@@ -0,0 +1,2 @@
+import AppHeader from './app-header.container'
+module.exports = AppHeader
diff --git a/ui/app/components/export-text-container/export-text-container.scss b/ui/app/components/export-text-container/export-text-container.scss
index a42de8233..975d62f70 100644
--- a/ui/app/components/export-text-container/export-text-container.scss
+++ b/ui/app/components/export-text-container/export-text-container.scss
@@ -37,7 +37,7 @@
display: flex;
justify-content: center;
align-items: center;
- font-size: 14px;
+ font-size: 12px;
cursor: pointer;
color: $curious-blue;
diff --git a/ui/app/components/pages/unlock-page/index.js b/ui/app/components/pages/unlock-page/index.js
new file mode 100644
index 000000000..be80cde4f
--- /dev/null
+++ b/ui/app/components/pages/unlock-page/index.js
@@ -0,0 +1,2 @@
+import UnlockPage from './unlock-page.container'
+module.exports = UnlockPage
diff --git a/ui/app/components/pages/unlock-page/unlock-page.component.js b/ui/app/components/pages/unlock-page/unlock-page.component.js
new file mode 100644
index 000000000..d5e2a3224
--- /dev/null
+++ b/ui/app/components/pages/unlock-page/unlock-page.component.js
@@ -0,0 +1,181 @@
+import React, { Component } from 'react'
+import PropTypes from 'prop-types'
+import Button from 'material-ui/Button'
+import TextField from '../../text-field'
+
+const { ENVIRONMENT_TYPE_POPUP } = require('../../../../../app/scripts/lib/enums')
+const { getEnvironmentType } = require('../../../../../app/scripts/lib/util')
+const getCaretCoordinates = require('textarea-caret')
+const EventEmitter = require('events').EventEmitter
+const Mascot = require('../../mascot')
+const { DEFAULT_ROUTE, RESTORE_VAULT_ROUTE } = require('../../../routes')
+
+class UnlockPage extends Component {
+ static contextTypes = {
+ t: PropTypes.func,
+ }
+
+ constructor (props) {
+ super(props)
+
+ this.state = {
+ password: '',
+ error: null,
+ }
+
+ this.animationEventEmitter = new EventEmitter()
+ }
+
+ componentWillMount () {
+ const { isUnlocked, history } = this.props
+
+ if (isUnlocked) {
+ history.push(DEFAULT_ROUTE)
+ }
+ }
+
+ tryUnlockMetamask (password) {
+ const { tryUnlockMetamask, history } = this.props
+ tryUnlockMetamask(password)
+ .then(() => history.push(DEFAULT_ROUTE))
+ .catch(({ message }) => this.setState({ error: message }))
+ }
+
+ handleSubmit (event) {
+ event.preventDefault()
+ event.stopPropagation()
+
+ const { password } = this.state
+ const { tryUnlockMetamask, history } = this.props
+
+ if (password === '') {
+ return
+ }
+
+ this.setState({ error: null })
+
+ tryUnlockMetamask(password)
+ .then(() => history.push(DEFAULT_ROUTE))
+ .catch(({ message }) => this.setState({ error: message }))
+ }
+
+ handleInputChange ({ target }) {
+ this.setState({ password: target.value, error: null })
+
+ // tell mascot to look at page action
+ const element = target
+ const boundingRect = element.getBoundingClientRect()
+ const coordinates = getCaretCoordinates(element, element.selectionEnd)
+ this.animationEventEmitter.emit('point', {
+ x: boundingRect.left + coordinates.left - element.scrollLeft,
+ y: boundingRect.top + coordinates.top - element.scrollTop,
+ })
+ }
+
+ renderSubmitButton () {
+ const style = {
+ backgroundColor: '#f7861c',
+ color: 'white',
+ marginTop: '20px',
+ height: '60px',
+ fontWeight: '400',
+ boxShadow: 'none',
+ borderRadius: '4px',
+ }
+
+ return (
+
+ )
+ }
+
+ render () {
+ const { error } = this.state
+
+ return (
+
+
+
+
+
+
+ { this.context.t('welcomeBack') }
+
+
{ this.context.t('unlockMessage') }
+
+ { this.renderSubmitButton() }
+
+
{
+ this.props.markPasswordForgotten()
+ this.props.history.push(RESTORE_VAULT_ROUTE)
+
+ if (getEnvironmentType(window.location.href) === ENVIRONMENT_TYPE_POPUP) {
+ global.platform.openExtensionInBrowser()
+ }
+ }}
+ >
+ { this.context.t('restoreFromSeed') }
+
+
{
+ this.props.markPasswordForgotten()
+ this.props.history.push(RESTORE_VAULT_ROUTE)
+
+ if (getEnvironmentType(window.location.href) === ENVIRONMENT_TYPE_POPUP) {
+ global.platform.openExtensionInBrowser()
+ }
+ }}
+ >
+ { this.context.t('importUsingSeed') }
+
+
+
+
+ )
+ }
+}
+
+UnlockPage.propTypes = {
+ forgotPassword: PropTypes.func,
+ tryUnlockMetamask: PropTypes.func,
+ markPasswordForgotten: PropTypes.func,
+ history: PropTypes.object,
+ isUnlocked: PropTypes.bool,
+ t: PropTypes.func,
+ useOldInterface: PropTypes.func,
+ setNetworkEndpoints: PropTypes.func,
+}
+
+export default UnlockPage
diff --git a/ui/app/components/pages/unlock-page/unlock-page.container.js b/ui/app/components/pages/unlock-page/unlock-page.container.js
new file mode 100644
index 000000000..9788a18ea
--- /dev/null
+++ b/ui/app/components/pages/unlock-page/unlock-page.container.js
@@ -0,0 +1,33 @@
+import { connect } from 'react-redux'
+import { withRouter } from 'react-router-dom'
+import { compose } from 'recompose'
+
+const {
+ tryUnlockMetamask,
+ forgotPassword,
+ markPasswordForgotten,
+ setNetworkEndpoints,
+} = require('../../../actions')
+
+import UnlockPage from './unlock-page.component'
+
+const mapStateToProps = state => {
+ const { metamask: { isUnlocked } } = state
+ return {
+ isUnlocked,
+ }
+}
+
+const mapDispatchToProps = dispatch => {
+ return {
+ forgotPassword: () => dispatch(forgotPassword()),
+ tryUnlockMetamask: password => dispatch(tryUnlockMetamask(password)),
+ markPasswordForgotten: () => dispatch(markPasswordForgotten()),
+ setNetworkEndpoints: type => dispatch(setNetworkEndpoints(type)),
+ }
+}
+
+export default compose(
+ withRouter,
+ connect(mapStateToProps, mapDispatchToProps)
+)(UnlockPage)
diff --git a/ui/app/components/pages/unlock-page/unlock-page.scss b/ui/app/components/pages/unlock-page/unlock-page.scss
new file mode 100644
index 000000000..3d44bd037
--- /dev/null
+++ b/ui/app/components/pages/unlock-page/unlock-page.scss
@@ -0,0 +1,51 @@
+.unlock-page {
+ display: flex;
+ flex-direction: column;
+ justify-content: flex-start;
+ align-items: center;
+ width: 357px;
+ padding: 30px;
+ font-weight: 400;
+ color: $silver-chalice;
+
+ &__container {
+ background: $white;
+ display: flex;
+ align-self: stretch;
+ justify-content: center;
+ flex: 1 0 auto;
+ }
+
+ &__mascot-container {
+ margin-top: 24px;
+ }
+
+ &__title {
+ margin-top: 5px;
+ font-size: 2rem;
+ font-weight: 800;
+ color: $tundora;
+ }
+
+ &__form {
+ width: 100%;
+ margin: 56px 0 8px;
+ }
+
+ &__links {
+ margin-top: 25px;
+ width: 100%;
+ }
+
+ &__link {
+ cursor: pointer;
+
+ &--import {
+ color: $ecstasy;
+ }
+
+ &--use-classic {
+ margin-top: 10px;
+ }
+ }
+}
diff --git a/ui/app/components/pages/unlock.js b/ui/app/components/pages/unlock.js
deleted file mode 100644
index 30144b978..000000000
--- a/ui/app/components/pages/unlock.js
+++ /dev/null
@@ -1,194 +0,0 @@
-const { Component } = require('react')
-const PropTypes = require('prop-types')
-const connect = require('../../metamask-connect')
-const h = require('react-hyperscript')
-const { withRouter } = require('react-router-dom')
-const { compose } = require('recompose')
-const {
- tryUnlockMetamask,
- forgotPassword,
- markPasswordForgotten,
- setNetworkEndpoints,
- setFeatureFlag,
-} = require('../../actions')
-const { ENVIRONMENT_TYPE_POPUP } = require('../../../../app/scripts/lib/enums')
-const { getEnvironmentType } = require('../../../../app/scripts/lib/util')
-const getCaretCoordinates = require('textarea-caret')
-const EventEmitter = require('events').EventEmitter
-const Mascot = require('../mascot')
-const { OLD_UI_NETWORK_TYPE } = require('../../../../app/scripts/controllers/network/enums')
-const { DEFAULT_ROUTE, RESTORE_VAULT_ROUTE } = require('../../routes')
-
-class UnlockScreen extends Component {
- constructor (props) {
- super(props)
-
- this.state = {
- error: null,
- }
-
- this.animationEventEmitter = new EventEmitter()
- }
-
- componentWillMount () {
- const { isUnlocked, history } = this.props
-
- if (isUnlocked) {
- history.push(DEFAULT_ROUTE)
- }
- }
-
- componentDidMount () {
- const passwordBox = document.getElementById('password-box')
-
- if (passwordBox) {
- passwordBox.focus()
- }
- }
-
- tryUnlockMetamask (password) {
- const { tryUnlockMetamask, history } = this.props
- tryUnlockMetamask(password)
- .then(() => history.push(DEFAULT_ROUTE))
- .catch(({ message }) => this.setState({ error: message }))
- }
-
- onSubmit (event) {
- const input = document.getElementById('password-box')
- const password = input.value
- this.tryUnlockMetamask(password)
- }
-
- onKeyPress (event) {
- if (event.key === 'Enter') {
- this.submitPassword(event)
- }
- }
-
- submitPassword (event) {
- var element = event.target
- var password = element.value
- // reset input
- element.value = ''
- this.tryUnlockMetamask(password)
- }
-
- inputChanged (event) {
- // tell mascot to look at page action
- var element = event.target
- var boundingRect = element.getBoundingClientRect()
- var coordinates = getCaretCoordinates(element, element.selectionEnd)
- this.animationEventEmitter.emit('point', {
- x: boundingRect.left + coordinates.left - element.scrollLeft,
- y: boundingRect.top + coordinates.top - element.scrollTop,
- })
- }
-
- render () {
- const { error } = this.state
- return (
- h('.unlock-screen', [
-
- h(Mascot, {
- animationEventEmitter: this.animationEventEmitter,
- }),
-
- h('h1', {
- style: {
- fontSize: '1.4em',
- textTransform: 'uppercase',
- color: '#7F8082',
- },
- }, this.props.t('appName')),
-
- h('input.large-input', {
- type: 'password',
- id: 'password-box',
- placeholder: 'enter password',
- style: {
- background: 'white',
- },
- onKeyPress: this.onKeyPress.bind(this),
- onInput: this.inputChanged.bind(this),
- }),
-
- h('.error', {
- style: {
- display: error ? 'block' : 'none',
- padding: '0 20px',
- textAlign: 'center',
- },
- }, error),
-
- h('button.primary.cursor-pointer', {
- onClick: this.onSubmit.bind(this),
- style: {
- margin: 10,
- },
- }, this.props.t('login')),
-
- h('p.pointer', {
- onClick: () => {
- this.props.markPasswordForgotten()
- this.props.history.push(RESTORE_VAULT_ROUTE)
-
- if (getEnvironmentType(window.location.href) === ENVIRONMENT_TYPE_POPUP) {
- global.platform.openExtensionInBrowser()
- }
- },
- style: {
- fontSize: '0.8em',
- color: 'rgb(247, 134, 28)',
- textDecoration: 'underline',
- },
- }, this.props.t('restoreFromSeed')),
-
- h('p.pointer', {
- onClick: () => {
- this.props.useOldInterface()
- .then(() => this.props.setNetworkEndpoints(OLD_UI_NETWORK_TYPE))
- },
- style: {
- fontSize: '0.8em',
- color: '#aeaeae',
- textDecoration: 'underline',
- marginTop: '32px',
- },
- }, this.props.t('classicInterface')),
- ])
- )
- }
-}
-
-UnlockScreen.propTypes = {
- forgotPassword: PropTypes.func,
- tryUnlockMetamask: PropTypes.func,
- markPasswordForgotten: PropTypes.func,
- history: PropTypes.object,
- isUnlocked: PropTypes.bool,
- t: PropTypes.func,
- useOldInterface: PropTypes.func,
- setNetworkEndpoints: PropTypes.func,
-}
-
-const mapStateToProps = state => {
- const { metamask: { isUnlocked } } = state
- return {
- isUnlocked,
- }
-}
-
-const mapDispatchToProps = dispatch => {
- return {
- forgotPassword: () => dispatch(forgotPassword()),
- tryUnlockMetamask: password => dispatch(tryUnlockMetamask(password)),
- markPasswordForgotten: () => dispatch(markPasswordForgotten()),
- useOldInterface: () => dispatch(setFeatureFlag('betaUI', false, 'OLD_UI_NOTIFICATION_MODAL')),
- setNetworkEndpoints: type => dispatch(setNetworkEndpoints(type)),
- }
-}
-
-module.exports = compose(
- withRouter,
- connect(mapStateToProps, mapDispatchToProps)
-)(UnlockScreen)
diff --git a/ui/app/components/text-field/index.js b/ui/app/components/text-field/index.js
new file mode 100644
index 000000000..171caf7a4
--- /dev/null
+++ b/ui/app/components/text-field/index.js
@@ -0,0 +1,2 @@
+import TextField from './text-field.component'
+module.exports = TextField
diff --git a/ui/app/components/text-field/text-field.component.js b/ui/app/components/text-field/text-field.component.js
new file mode 100644
index 000000000..6fd3b82b4
--- /dev/null
+++ b/ui/app/components/text-field/text-field.component.js
@@ -0,0 +1,59 @@
+import React from 'react'
+import PropTypes from 'prop-types'
+import { withStyles } from 'material-ui/styles'
+import { default as MaterialTextField } from 'material-ui/TextField'
+
+const styles = {
+ cssLabel: {
+ '&$cssFocused': {
+ color: '#aeaeae',
+ },
+ '&$cssError': {
+ color: '#aeaeae',
+ },
+ fontWeight: '400',
+ color: '#aeaeae',
+ },
+ cssFocused: {},
+ cssUnderline: {
+ '&:after': {
+ backgroundColor: '#f7861c',
+ },
+ },
+ cssError: {},
+}
+
+const TextField = props => {
+ const { error, classes, ...textFieldProps } = props
+
+ return (
+
+ )
+}
+
+TextField.defaultProps = {
+ error: null,
+}
+
+TextField.propTypes = {
+ error: PropTypes.string,
+ classes: PropTypes.object,
+}
+
+export default withStyles(styles)(TextField)
diff --git a/ui/app/components/text-field/text-field.stories.js b/ui/app/components/text-field/text-field.stories.js
new file mode 100644
index 000000000..ee3e5faaf
--- /dev/null
+++ b/ui/app/components/text-field/text-field.stories.js
@@ -0,0 +1,24 @@
+import React from 'react'
+import { storiesOf } from '@storybook/react'
+import TextField from './'
+
+storiesOf('TextField', module)
+ .add('text', () =>
+
+ )
+ .add('password', () =>
+
+ )
+ .add('error', () =>
+
+ )
diff --git a/ui/app/components/wallet-view.js b/ui/app/components/wallet-view.js
index 9e430f87b..3b29dacac 100644
--- a/ui/app/components/wallet-view.js
+++ b/ui/app/components/wallet-view.js
@@ -102,6 +102,7 @@ WalletView.prototype.render = function () {
selectedIdentity,
keyrings,
showAccountDetailModal,
+ sidebarOpen,
hideSidebar,
history,
} = this.props
@@ -182,7 +183,10 @@ WalletView.prototype.render = function () {
h(TokenList),
h('button.btn-primary.wallet-view__add-token-button', {
- onClick: () => history.push(ADD_TOKEN_ROUTE),
+ onClick: () => {
+ history.push(ADD_TOKEN_ROUTE)
+ sidebarOpen && hideSidebar()
+ },
}, this.context.t('addToken')),
])
}
diff --git a/ui/app/css/itcss/components/header.scss b/ui/app/css/itcss/components/header.scss
index eeed9ee06..cef61d0e2 100644
--- a/ui/app/css/itcss/components/header.scss
+++ b/ui/app/css/itcss/components/header.scss
@@ -1,15 +1,15 @@
.app-header {
align-items: center;
- visibility: visible;
background: $gallery;
position: relative;
z-index: $header-z-index;
display: flex;
flex-flow: column nowrap;
+ width: 100%;
+ flex: 0 0 auto;
@media screen and (max-width: 575px) {
padding: 12px;
- width: 100%;
box-shadow: 0 0 0 1px rgba(0, 0, 0, .08);
z-index: $mobile-header-z-index;
}
@@ -17,48 +17,75 @@
@media screen and (min-width: 576px) {
height: 75px;
justify-content: center;
- }
- .metafox-icon {
- cursor: pointer;
- }
-}
-
-.app-header--initialized {
-
- @media screen and (min-width: 576px) {
- &::after {
- content: '';
- position: absolute;
- width: 100%;
- height: 32px;
- background: $gallery;
- bottom: -32px;
+ &--back-drop {
+ &::after {
+ content: '';
+ position: absolute;
+ width: 100%;
+ height: 32px;
+ background: $gallery;
+ bottom: -32px;
+ }
}
}
-}
-.app-header-contents {
- display: flex;
- justify-content: space-between;
- flex-flow: row nowrap;
- width: 100%;
- height: 6.9vh;
-
- @media screen and (max-width: 575px) {
- height: 100%;
+ &__metafox {
+ cursor: pointer;
}
- @media screen and (min-width: 576px) {
- width: 85vw;
+ &__beta-label {
+ font-family: Roboto;
+ text-transform: uppercase;
+ font-weight: 500;
+ font-size: .8rem;
+ color: $buttercup;
+ margin-left: 5px;
+ line-height: initial;
+
+ @media screen and (max-width: 575px) {
+ display: none;
+ }
}
- @media screen and (min-width: 769px) {
- width: 80vw;
+ &__contents {
+ display: flex;
+ justify-content: space-between;
+ flex-flow: row nowrap;
+ width: 100%;
+
+ @media screen and (max-width: 575px) {
+ height: 100%;
+ }
+
+ @media screen and (min-width: 576px) {
+ width: 85vw;
+ }
+
+ @media screen and (min-width: 769px) {
+ width: 80vw;
+ }
+
+ @media screen and (min-width: 1281px) {
+ width: 62vw;
+ }
}
- @media screen and (min-width: 1281px) {
- width: 62vw;
+ &__logo-container {
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ cursor: pointer;
+ }
+
+ &__account-menu-container {
+ display: flex;
+ flex-flow: row nowrap;
+ align-items: center;
+
+ .identicon {
+ cursor: pointer;
+ }
}
}
@@ -76,20 +103,6 @@
}
}
-.beta-label {
- font-family: Roboto;
- text-transform: uppercase;
- font-weight: 500;
- font-size: .8rem;
- color: $buttercup;
- margin-left: 5px;
- line-height: initial;
-
- @media screen and (max-width: 575px) {
- display: none;
- }
-}
-
h2.page-subtitle {
text-transform: uppercase;
color: #aeaeae;
@@ -102,20 +115,3 @@ h2.page-subtitle {
flex-direction: row;
align-items: center;
}
-
-.left-menu-wrapper {
- display: flex;
- flex-direction: row;
- align-items: center;
- cursor: pointer;
-}
-
-.header__right-actions {
- display: flex;
- flex-flow: row nowrap;
- align-items: center;
-
- .identicon {
- cursor: pointer;
- }
-}
diff --git a/ui/app/css/itcss/components/pages/index.scss b/ui/app/css/itcss/components/pages/index.scss
index d0b59da53..195185fff 100644
--- a/ui/app/css/itcss/components/pages/index.scss
+++ b/ui/app/css/itcss/components/pages/index.scss
@@ -1,3 +1,3 @@
-@import './unlock.scss';
-
@import './reveal-seed.scss';
+
+@import '../../../../components/pages/unlock-page/unlock-page.scss';
diff --git a/ui/app/css/itcss/components/pages/unlock.scss b/ui/app/css/itcss/components/pages/unlock.scss
deleted file mode 100644
index 5d438377b..000000000
--- a/ui/app/css/itcss/components/pages/unlock.scss
+++ /dev/null
@@ -1,9 +0,0 @@
-.unlock-page {
- box-shadow: none;
- display: flex;
- flex-direction: column;
- align-items: center;
- justify-content: center;
- background: rgb(247, 247, 247);
- width: 100%;
-}
diff --git a/ui/app/css/itcss/components/sections.scss b/ui/app/css/itcss/components/sections.scss
index ace46bd8a..feec71c89 100644
--- a/ui/app/css/itcss/components/sections.scss
+++ b/ui/app/css/itcss/components/sections.scss
@@ -95,19 +95,6 @@ textarea.twelve-word-phrase {
margin: -2px 8px 0px -8px;
}
-.unlock-screen #metamask-mascot-container {
- margin-top: 24px;
-}
-
-.unlock-screen h1 {
- margin-top: -28px;
- margin-bottom: 42px;
-}
-
-.unlock-screen input[type=password] {
- width: 260px;
-}
-
.sizing-input {
font-size: 14px;
height: 30px;
@@ -118,34 +105,6 @@ textarea.twelve-word-phrase {
display: flex;
}
-/* Webkit */
-
-.unlock-screen input::-webkit-input-placeholder {
- text-align: center;
- font-size: 1.2em;
-}
-
-/* Firefox 18- */
-
-.unlock-screen input:-moz-placeholder {
- text-align: center;
- font-size: 1.2em;
-}
-
-/* Firefox 19+ */
-
-.unlock-screen input::-moz-placeholder {
- text-align: center;
- font-size: 1.2em;
-}
-
-/* IE */
-
-.unlock-screen input:-ms-input-placeholder {
- text-align: center;
- font-size: 1.2em;
-}
-
/* accounts */
.accounts-section {
diff --git a/ui/app/css/itcss/components/settings.scss b/ui/app/css/itcss/components/settings.scss
index dcc9b98d5..0dd61ac5e 100644
--- a/ui/app/css/itcss/components/settings.scss
+++ b/ui/app/css/itcss/components/settings.scss
@@ -3,8 +3,6 @@
background: $white;
display: flex;
flex-flow: column nowrap;
- height: auto;
- overflow: auto;
}
.settings__header {
@@ -29,6 +27,8 @@
.settings__content {
padding: 0 25px;
+ height: auto;
+ overflow: auto;
}
.settings__content-row {
diff --git a/ui/app/css/itcss/components/welcome-screen.scss b/ui/app/css/itcss/components/welcome-screen.scss
index bfd174ad9..af1d67398 100644
--- a/ui/app/css/itcss/components/welcome-screen.scss
+++ b/ui/app/css/itcss/components/welcome-screen.scss
@@ -1,59 +1,60 @@
.welcome-screen {
+ display: flex;
+ flex-flow: column;
+ justify-content: center;
+ align-items: center;
+ font-family: Roboto;
+ font-weight: 400;
+ width: 100%;
+ flex: 1 0 auto;
+ padding: 70px 0;
+ background: $white;
+
+ @media screen and (max-width: 575px) {
+ padding: 0;
+ }
+
+ &__info {
display: flex;
flex-flow: column;
- justify-content: center;
- align-items: center;
- font-family: Roboto;
- font-weight: 400;
width: 100%;
- flex: 1 0 auto;
- padding: 70px 0;
- background: $white;
+ height: 100%;
+ align-items: center;
+ justify-content: center;
- @media screen and (max-width: 575px) {
- padding: 0;
+ &__header {
+ font-size: 1.65em;
+ margin-bottom: 14px;
+
+ @media screen and (max-width: 575px) {
+ font-size: 1.5em;
+ }
}
- &__info {
- display: flex;
- flex-flow: column;
- width: 100%;
- height: 100%;
- align-items: center;
-
- &__header {
- font-size: 1.65em;
- margin-bottom: 14px;
-
- @media screen and (max-width: 575px) {
- font-size: 1.5em;
- }
- }
-
- &__copy {
- font-size: 1em;
- width: 400px;
- max-width: 90vw;
- text-align: center;
-
- @media screen and (max-width: 575px) {
- font-size: 0.9em;
- }
- }
- }
-
- &__button {
- height: 54px;
- width: 198px;
- box-shadow: 0 2px 4px 0 rgba(0,0,0,0.14);
- color: #FFFFFF;
- font-size: 20px;
- font-weight: 500;
- line-height: 26px;
+ &__copy {
+ font-size: 1em;
+ width: 400px;
+ max-width: 90vw;
text-align: center;
- text-transform: uppercase;
- margin: 35px 0 14px;
- transition: 200ms ease-in-out;
- background-color: rgba(247, 134, 28, 0.9);
+
+ @media screen and (max-width: 575px) {
+ font-size: .9em;
+ }
}
+ }
+
+ &__button {
+ height: 54px;
+ width: 198px;
+ box-shadow: 0 2px 4px 0 rgba(0, 0, 0, .14);
+ color: #fff;
+ font-size: 20px;
+ font-weight: 500;
+ line-height: 26px;
+ text-align: center;
+ text-transform: uppercase;
+ margin: 35px 0 14px;
+ transition: 200ms ease-in-out;
+ background-color: rgba(247, 134, 28, .9);
+ }
}
diff --git a/ui/app/css/itcss/generic/index.scss b/ui/app/css/itcss/generic/index.scss
index b484d5a91..9b2982096 100644
--- a/ui/app/css/itcss/generic/index.scss
+++ b/ui/app/css/itcss/generic/index.scss
@@ -205,10 +205,8 @@ input.large-input {
}
&__content {
- height: 100%;
overflow-y: auto;
- min-height: 250px;
- max-height: 400px;
+ flex: 1;
}
&__warning-container {
@@ -256,6 +254,7 @@ input.large-input {
overflow-y: auto;
background-color: $white;
border-radius: 0;
+ flex: 1;
}
}
diff --git a/ui/app/main-container.js b/ui/app/main-container.js
index c305687ea..c9b05db3b 100644
--- a/ui/app/main-container.js
+++ b/ui/app/main-container.js
@@ -3,7 +3,7 @@ const h = require('react-hyperscript')
const inherits = require('util').inherits
const AccountAndTransactionDetails = require('./account-and-transaction-details')
const Settings = require('./components/pages/settings')
-const UnlockScreen = require('./components/pages/unlock')
+const UnlockScreen = require('./components/pages/unlock-page')
const log = require('loglevel')
module.exports = MainContainer
diff --git a/ui/app/unlock.js b/ui/app/unlock.js
deleted file mode 100644
index 099e5f9c6..000000000
--- a/ui/app/unlock.js
+++ /dev/null
@@ -1,141 +0,0 @@
-const inherits = require('util').inherits
-const Component = require('react').Component
-const PropTypes = require('prop-types')
-const h = require('react-hyperscript')
-const connect = require('react-redux').connect
-const actions = require('./actions')
-const getCaretCoordinates = require('textarea-caret')
-const EventEmitter = require('events').EventEmitter
-const { OLD_UI_NETWORK_TYPE } = require('../../app/scripts/controllers/network/enums')
-const { getEnvironmentType } = require('../../app/scripts/lib/util')
-const { ENVIRONMENT_TYPE_POPUP } = require('../../app/scripts/lib/enums')
-
-const Mascot = require('./components/mascot')
-
-UnlockScreen.contextTypes = {
- t: PropTypes.func,
-}
-
-module.exports = connect(mapStateToProps)(UnlockScreen)
-
-
-inherits(UnlockScreen, Component)
-function UnlockScreen () {
- Component.call(this)
- this.animationEventEmitter = new EventEmitter()
-}
-
-function mapStateToProps (state) {
- return {
- warning: state.appState.warning,
- }
-}
-
-UnlockScreen.prototype.render = function () {
- const state = this.props
- const warning = state.warning
- return (
- h('.unlock-screen', [
-
- h(Mascot, {
- animationEventEmitter: this.animationEventEmitter,
- }),
-
- h('h1', {
- style: {
- fontSize: '1.4em',
- textTransform: 'uppercase',
- color: '#7F8082',
- },
- }, this.context.t('appName')),
-
- h('input.large-input', {
- type: 'password',
- id: 'password-box',
- placeholder: 'enter password',
- style: {
- background: 'white',
- },
- onKeyPress: this.onKeyPress.bind(this),
- onInput: this.inputChanged.bind(this),
- }),
-
- h('.error', {
- style: {
- display: warning ? 'block' : 'none',
- padding: '0 20px',
- textAlign: 'center',
- },
- }, warning),
-
- h('button.primary.cursor-pointer', {
- onClick: this.onSubmit.bind(this),
- style: {
- margin: 10,
- },
- }, this.context.t('login')),
-
- h('p.pointer', {
- onClick: () => {
- this.props.dispatch(actions.markPasswordForgotten())
- if (getEnvironmentType(window.location.href) === ENVIRONMENT_TYPE_POPUP) {
- global.platform.openExtensionInBrowser()
- }
- },
- style: {
- fontSize: '0.8em',
- color: 'rgb(247, 134, 28)',
- textDecoration: 'underline',
- },
- }, this.context.t('restoreFromSeed')),
-
- h('p.pointer', {
- onClick: () => {
- this.props.dispatch(actions.setFeatureFlag('betaUI', false, 'OLD_UI_NOTIFICATION_MODAL'))
- .then(() => this.props.dispatch(actions.setNetworkEndpoints(OLD_UI_NETWORK_TYPE)))
- },
- style: {
- fontSize: '0.8em',
- color: '#aeaeae',
- textDecoration: 'underline',
- marginTop: '32px',
- },
- }, this.context.t('classicInterface')),
- ])
- )
-}
-
-UnlockScreen.prototype.componentDidMount = function () {
- document.getElementById('password-box').focus()
-}
-
-UnlockScreen.prototype.onSubmit = function (event) {
- const input = document.getElementById('password-box')
- const password = input.value
- this.props.dispatch(actions.tryUnlockMetamask(password))
-}
-
-UnlockScreen.prototype.onKeyPress = function (event) {
- if (event.key === 'Enter') {
- this.submitPassword(event)
- }
-}
-
-UnlockScreen.prototype.submitPassword = function (event) {
- var element = event.target
- var password = element.value
- // reset input
- element.value = ''
- this.props.dispatch(actions.tryUnlockMetamask(password))
-}
-
-UnlockScreen.prototype.inputChanged = function (event) {
- // tell mascot to look at page action
- var element = event.target
- var boundingRect = element.getBoundingClientRect()
- var coordinates = getCaretCoordinates(element, element.selectionEnd)
- this.animationEventEmitter.emit('point', {
- x: boundingRect.left + coordinates.left - element.scrollLeft,
- y: boundingRect.top + coordinates.top - element.scrollTop,
- })
-}