diff --git a/package.json b/package.json
index 62795433..e1217a56 100644
--- a/package.json
+++ b/package.json
@@ -12,7 +12,7 @@
},
"license": "LGPL-3.0+",
"scripts": {
- "dev": "babel-node ./webpack/server.js --library",
+ "dev": "babel-node ./webpack/server.js --connect",
"dev:library": "babel-node ./webpack/server.js --library",
"dev:connect": "babel-node ./webpack/server.js --connect",
"build": "rm -rf build && webpack --config ./webpack/webpack.config.prod.babel.js",
diff --git a/src/images/browser-chrome.png b/src/images/browser-chrome.png
new file mode 100644
index 00000000..29573624
Binary files /dev/null and b/src/images/browser-chrome.png differ
diff --git a/src/images/browser-firefox.png b/src/images/browser-firefox.png
new file mode 100644
index 00000000..577e6dc0
Binary files /dev/null and b/src/images/browser-firefox.png differ
diff --git a/src/js/components/landing/ConnectDevice.js b/src/js/components/landing/ConnectDevice.js
index f5dcb671..7fb78238 100644
--- a/src/js/components/landing/ConnectDevice.js
+++ b/src/js/components/landing/ConnectDevice.js
@@ -1,36 +1,57 @@
/* @flow */
'use strict';
-import React from 'react';
-import Header from '../common/Header';
-import Footer from '../common/Footer';
+import React, { Component } from 'react';
+import TrezorConnect from 'trezor-connect';
-export default (props: any): any => {
- return (
-
-
+export default class InstallBridge extends Component {
+
+ componentDidUpdate() {
+ if (this.props.transport.indexOf('webusb') >= 0)
+ TrezorConnect.renderWebUSBButton();
+ }
+
+ render() {
+ let webusb = null;
+ let connectClaim = 'Connect TREZOR to continue';
+ let and = null;
+ let bridgeClaim = null;
+ if (this.props.transport.indexOf('webusb') >= 0) {
+ webusb =
;
+ connectClaim = 'Connect TREZOR';
+ and =
and
;
+ bridgeClaim =
Device not recognized? Try installing the TREZOR Bridge.;
+ }
+
+ return (
- The private bank in your hands.
+ The private bank in your hands.
TREZOR Wallet is an easy-to-use interface for your TREZOR.
TREZOR Wallet allows you to easily control your funds, manage your balance and initiate transfers.
-
- Connect TREZOR to continue
+
+
+ { connectClaim }
+
+
+ { and }
+ { webusb }
+
+
+
+ { bridgeClaim }
+ Don't have TREZOR? Get one
- {/*
Don't have TREZOR? Get one
*/}
-
- Don't have TREZOR? Get one
-
-
- );
+ );
+ }
}
\ No newline at end of file
diff --git a/src/js/components/landing/InstallBridge.js b/src/js/components/landing/InstallBridge.js
new file mode 100644
index 00000000..a3c3fac4
--- /dev/null
+++ b/src/js/components/landing/InstallBridge.js
@@ -0,0 +1,64 @@
+/* @flow */
+'use strict';
+
+import React, { Component } from 'react';
+import Select from 'react-select';
+
+type State = {
+ version: string;
+ target: string;
+ url: string;
+}
+
+const installers = [
+ { id: 'Windows', value: 'trezor-bridge-2.0.11-win32-install.exe', label: 'Windows' },
+ { id: 'macOS', value: 'trezor-bridge-2.0.11.pkg', label: 'Mac OS X' },
+ { id: 'Linux', value: 'trezor-bridge_2.0.11_amd64.deb', label: 'Linux 64-bit (deb)' },
+ { id: 'Linux-rpm', value: 'trezor-bridge_2.0.11_amd64.rpm', label: 'Linux 64-bit (rpm)' },
+ { value: 'trezor-bridge_2.0.11_amd32.deb', label: 'Linux 32-bit (deb)' },
+ { value: 'trezor-bridge_2.0.11_amd32.rpm', label: 'Linux 32-bit (rpm)' },
+];
+
+export default class InstallBridge extends Component {
+
+ state: State;
+
+ constructor(props) {
+ super(props);
+
+ const currentTarget = installers.find(i => i.id === props.browserState.osname);
+ this.state = {
+ version: '2.0.11',
+ target: currentTarget,
+ url: 'https://wallet.trezor.io/data/bridge/2.0.11/'
+ };
+ }
+
+ onChange(value) {
+ this.setState({
+ target: value
+ });
+ }
+
+ render() {
+ const url = `${ this.state.url }${ this.state.target.value }`;
+ return (
+
+ TREZOR Bridge. Version 2.0.11
+ New communication tool to facilitate the connection between your TREZOR and your internet browser.
+
+ Learn more about latest version in Changelog
+
+ );
+ }
+}
\ No newline at end of file
diff --git a/src/js/components/landing/LandingPage.js b/src/js/components/landing/LandingPage.js
index e38cb86f..7bb2bf29 100644
--- a/src/js/components/landing/LandingPage.js
+++ b/src/js/components/landing/LandingPage.js
@@ -4,69 +4,73 @@
import React from 'react';
import Preloader from './Preloader';
import ConnectDevice from './ConnectDevice';
+import InstallBridge from './InstallBridge';
import LocalStorageError from './LocalStorageError';
import TrezorConnectError from './TrezorConnectError';
import Header from '../common/Header';
import Footer from '../common/Footer';
import Log from '../common/Log';
-import { Notification } from '../common/Notification';
+// import { Notification } from '../common/Notification';
+import Notifications, { Notification } from '../common/Notification';
+
+
+const BrowserNotSupported = (props: any) => {
+ return (
+
+ Your browser is not supported
+ Please choose one of the supported browsers
+
+
+ )
+}
export default (props: any): any => {
const web3 = props.web3;
- const { devices } = props.connect;
+ const { devices, browserState, transport } = props.connect;
const localStorageError = props.localStorage.error;
const connectError = props.connect.error;
let notification = null;
+ let body = null;
+ let css: string = 'app landing';
+ const bridgeRoute: boolean = props.router.location.params.hasOwnProperty('bridge');
if (localStorageError) {
notification = ();
- }
-
- if (connectError) {
- notification = ();
+ css += ' config-error';
+ } else if (!browserState.supported) {
+ css += ' browser-not-supported'
+ body = ;
+ } else if (connectError || bridgeRoute) {
+ css += ' install-bridge';
+ body = ;
+ } else {
+ css += ' connect-device';
+ body = ;
}
if (notification || (web3.length > 0 && devices.length < 1)) {
return (
-
+
{ notification }
+
-
- The private bank in your hands.
- TREZOR Wallet is an easy-to-use interface for your TREZOR.
- TREZOR Wallet allows you to easily control your funds, manage your balance and initiate transfers.
-
-
-
-
- Connect TREZOR to continue
-
-
- {/*
*/}
- {/*
Don't have TREZOR? Get one
*/}
-
-
-
+ { body }
);
diff --git a/src/js/router/index.js b/src/js/router/index.js
index b2872867..b8e1aadf 100644
--- a/src/js/router/index.js
+++ b/src/js/router/index.js
@@ -30,6 +30,7 @@ export default (
+
diff --git a/src/js/services/RouterService.js b/src/js/services/RouterService.js
index 83e37603..98d2a31c 100644
--- a/src/js/services/RouterService.js
+++ b/src/js/services/RouterService.js
@@ -103,7 +103,7 @@ const RouterService = (store: any) => (next: any) => (action: any) => {
console.warn("Modal still opened");
} else if (landingPage) {
// keep route on landing page
- if (action.payload.pathname !== '/'){
+ if (action.payload.pathname !== '/' && action.payload.pathname !== '/bridge'){
redirectPath = '/';
}
} else {
diff --git a/src/js/services/TrezorConnectService.js b/src/js/services/TrezorConnectService.js
index d233c554..68fe9c92 100644
--- a/src/js/services/TrezorConnectService.js
+++ b/src/js/services/TrezorConnectService.js
@@ -10,6 +10,7 @@ import { init as initWeb3 } from '../actions/Web3Actions';
import * as WEB3 from '../actions/constants/Web3';
import * as STORAGE from '../actions/constants/LocalStorage';
import * as CONNECT from '../actions/constants/TrezorConnect';
+import * as NOTIFICATION from '../actions/constants/notification';
import * as ACTIONS from '../actions';
@@ -25,6 +26,16 @@ const TrezorConnectService = (store: any) => (next: any) => (action: any) => {
} else if (action.type === TRANSPORT.ERROR) {
store.dispatch( push('/') );
+ } else if (action.type === TRANSPORT.UNREADABLE) {
+ store.dispatch({
+ type: NOTIFICATION.ADD,
+ payload: {
+ type: 'error',
+ title: 'Unreadable HID device',
+ message: 'What to do?',
+ cancelable: true,
+ }
+ })
} else if (action.type === WEB3.READY) {
store.dispatch( TrezorConnectActions.postInit() );
diff --git a/src/styles/fonts.less b/src/styles/fonts.less
index 51bb91e5..773e64e6 100644
--- a/src/styles/fonts.less
+++ b/src/styles/fonts.less
@@ -166,3 +166,8 @@
.icomoon-base();
content: "\e91f";
}
+
+.icomoon-download {
+ .icomoon-base();
+ content: "\e91f";
+}
diff --git a/src/styles/inputs.less b/src/styles/inputs.less
index a79945f7..af6fd55c 100644
--- a/src/styles/inputs.less
+++ b/src/styles/inputs.less
@@ -44,7 +44,7 @@ input {
}
}
-
+a.button,
button {
padding: 12px 24px;
border-radius: 3px;
@@ -218,7 +218,7 @@ a.green:visited {
&:hover,
&:active {
&:after {
- border-color: @color_white;
+ border-color: transparent;
}
}
}
diff --git a/src/styles/landingPage.less b/src/styles/landingPage.less
index f8e22317..a214e87e 100644
--- a/src/styles/landingPage.less
+++ b/src/styles/landingPage.less
@@ -1,15 +1,173 @@
.app {
- &.connect-device {
+
+ &.landing {
//min-height: 100vh;
// overflow: hidden;
background: @color_landing;
+ .notification {
+ min-width: 100%;
+ padding: 24px 0px;
+ .notification-body {
+ max-width: 1170px;
+ margin: 0px auto;
+ padding: 0px 32px 0px 64px;
+ position: relative;
+ }
+ h2:before {
+ top: -7px;
+ left: 24px;
+ }
+ }
+
main {
flex-direction: column;
text-align: center;
padding-top: 65px;
margin-top: 0px;
background: @color_landing;
+ }
+
+ footer {
+ border: 0px;
+ justify-content: center;
+ width: 100%;
+ max-width: 1170px;
+ margin: 0px auto;
+ }
+
+ }
+
+ &.browser-not-supported {
+ main {
+ padding-top: 0px;
+ justify-content: center;
+ width: auto;
+ p {
+ padding: 24px 0px;
+ color: @color_text_secondary;
+ }
+ }
+
+ .row {
+ display: flex;
+ flex-direction: row;
+ justify-content: space-between;
+
+ div {
+ &:before {
+ content: '';
+ width: 43px;
+ height: 43px;
+ display: block;
+ margin: 0 auto;
+ }
+ p {
+ font-size: 12px;
+ padding: 12px 0px;
+ }
+ a {
+ display: block;
+ }
+
+ &.chrome {
+ &:before {
+ background-image: url('../images/browser-chrome.png');
+ }
+ }
+ &.firefox {
+ &:before {
+ background-image: url('../images/browser-firefox.png');
+ }
+ }
+ }
+ }
+ }
+
+ &.install-bridge {
+
+ main {
+ padding-top: 0px;
+ justify-content: center;
+ max-width: 500px;
+
+ p {
+ color: @color_text_secondary;
+ font-size: 16px;
+ line-height: 1.6;
+ }
+ }
+
+ .Select {
+ flex: 1;
+ height: 34px;
+ margin-right: 4px;
+
+ .Select-control {
+ height: 34px;
+ border: 1px solid @color_divider;
+ border-radius: 0px 2px 2px 0px;
+ background: @color_white;
+ }
+
+ .Select-option {
+ .hover();
+ &.is-focused {
+ background: @color_gray_light;
+ }
+
+ &.is-selected {
+ background: @color_divider;
+ }
+ }
+ }
+
+ .claim {
+ font-size: 36px;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ margin-bottom: 24px;
+ span {
+ color: @color_green_primary;
+ padding: 6px 10px;
+ border: 1px solid @color_green_primary;
+ border-radius: 3px;
+ font-size: 14px;
+ font-weight: 300;
+ margin-left: 24px;
+ }
+ }
+
+ .row {
+ display: flex;
+ flex-direction: row;
+ justify-content: space-around;
+ padding: 24px 0px;
+
+ .button {
+ padding: 0px 24px;
+ height: 34px;
+ line-height: 34px;
+ text-align: left;
+ &:before {
+ .icomoon-download;
+ position: relative;
+ top: 5px;
+ margin-right: 10px;
+ }
+ }
+ }
+
+ .installers {
+ width: 120px;
+ text-align: left;
+ }
+ }
+
+ &.connect-device {
+
+ main {
h2.claim {
font-size: 36px;
@@ -19,10 +177,10 @@
.row {
display: flex;
flex-direction: row;
- justify-content: space-around;
+ justify-content: space-between;
padding: 36px 0px;
margin: 0 auto;
- width: 720px;
+ width: 420px;
p {
// flex: 1;
@@ -51,10 +209,8 @@
font-weight: 500;
span {
- vertical-align: top;
position: relative;
top: 1px;
- left: 12px;
animation: pulsate 1.3s ease-out infinite;
position: relative;
@@ -83,6 +239,10 @@
left: 0;
right: 0;
margin: 0px auto;
+
+ span {
+ display: block;
+ }
}
}
@@ -97,19 +257,55 @@
.connect-usb-cable {
animation: connect 1.3s ease-out infinite;
}
-
- footer {
- border: 0px;
- justify-content: center;
- width: 100%;
- max-width: 1170px;
- margin: 0px auto;
- }
-
- .notification {
- width: 100%;
- max-width: 1170px;
- margin: 0px auto;
+
+ // a copy of webusb.less from trezor-connect
+ .trezor-webusb-button {
+ position: relative;
+ padding: 12px 24px 12px 40px;
+ background: transparent;
+ color: @color_green_primary;
+ border: 1px solid @color_green_primary;
+ .hover();
+
+ &:before,
+ &:after {
+ content: '';
+ position: absolute;
+ background: @color_green_primary;
+ top: 0;
+ bottom: 0;
+ margin: auto;
+ .hover();
+ }
+
+ &:before {
+ width: 12px;
+ height: 2px;
+ left: 18px;
+ }
+
+ &:after {
+ width: 2px;
+ height: 12px;
+ left: 23px;
+ }
+
+ &:hover {
+ background: @color_green_primary;
+ color: @color_white;
+
+ &:before,
+ &:after {
+ background: @color_white;
+ }
+ }
+
+ iframe {
+ position: absolute;
+ top: 0;
+ left: 0;
+ z-index: 1;
+ }
}
}
}
diff --git a/src/styles/notification.less b/src/styles/notification.less
index 7811cca7..dc8aab70 100644
--- a/src/styles/notification.less
+++ b/src/styles/notification.less
@@ -25,6 +25,7 @@
padding: 12px;
color: inherit;
transition: opacity 0.3s;
+ z-index: 1;
&:after {
.icomoon-close;
diff --git a/webpack/webpack.config.connect.js b/webpack/webpack.config.connect.js
index e3727222..bb23b081 100644
--- a/webpack/webpack.config.connect.js
+++ b/webpack/webpack.config.connect.js
@@ -1,4 +1,4 @@
-import { TREZOR_CONNECT, TREZOR_IFRAME, TREZOR_POPUP, TREZOR_CONNECT_FILES } from './constants';
+import { TREZOR_CONNECT, TREZOR_IFRAME, TREZOR_POPUP, TREZOR_CONNECT_FILES, TREZOR_CONNECT_HTML } from './constants';
import path from 'path';
import webpack from 'webpack';
import webpackMerge from 'webpack-merge';
@@ -8,7 +8,7 @@ import HtmlWebpackPlugin from 'html-webpack-plugin';
module.exports = webpackMerge(baseConfig, {
entry: {
'trezor-connect2': `${TREZOR_CONNECT}.js`,
- 'iframe': `${TREZOR_IFRAME}`,
+ 'iframe': ['babel-polyfill', `${TREZOR_IFRAME}`],
'popup': `${TREZOR_POPUP}`,
},
resolve: {
@@ -20,13 +20,13 @@ module.exports = webpackMerge(baseConfig, {
new HtmlWebpackPlugin({
chunks: ['iframe'],
filename: `iframe.html`,
- template: `${TREZOR_CONNECT_FILES}iframe.html`,
+ template: `${TREZOR_CONNECT_HTML}iframe.html`,
inject: true
}),
new HtmlWebpackPlugin({
chunks: ['popup'],
filename: 'popup.html',
- template: `${TREZOR_CONNECT_FILES}popup.html`,
+ template: `${TREZOR_CONNECT_HTML}popup.html`,
inject: true
}),
new webpack.DefinePlugin({
diff --git a/webpack/webpack.config.dev.js b/webpack/webpack.config.dev.js
index 8891d939..84347f07 100644
--- a/webpack/webpack.config.dev.js
+++ b/webpack/webpack.config.dev.js
@@ -88,6 +88,7 @@ module.exports = {
inject: true
}),
new CopyWebpackPlugin([
+ { from: `${TREZOR_CONNECT_FILES}config.json`, to: './data/config.json' },
{ from: `${TREZOR_CONNECT_FILES}coins.json`, to: './data/coins.json' },
{ from: `${TREZOR_CONNECT_FILES}releases-1.json`, to: './data/releases-1.json' },
{ from: `${TREZOR_CONNECT_FILES}latest.txt`, to: './data/latest.txt' },