Add Go to Coinbase; Show Buy Ether after signup

feature/default_network_editable
Jacky Chan 7 years ago committed by Chi Kei Chan
parent 4ecd28ca9b
commit 85e485128f
  1. 11
      mascara/src/app/first-time/backup-phrase-screen.js
  2. 75
      mascara/src/app/first-time/buy-ether-screen.js
  3. 7
      mascara/src/app/first-time/import-account-screen.js
  4. 1
      mascara/src/app/first-time/index.css
  5. 31
      mascara/src/app/first-time/index.js
  6. 5
      mascara/src/app/first-time/notice-screen.js
  7. 5
      mascara/src/app/first-time/unique-image-screen.js
  8. 2
      ui/app/actions.js
  9. 17
      ui/app/app.js
  10. 9
      ui/app/keychains/hd/create-vault-complete.js

@ -4,6 +4,7 @@ import classnames from 'classnames'
import Identicon from '../../../../ui/app/components/identicon' import Identicon from '../../../../ui/app/components/identicon'
import {confirmSeedWords} from '../../../../ui/app/actions' import {confirmSeedWords} from '../../../../ui/app/actions'
import Breadcrumbs from './breadcrumbs' import Breadcrumbs from './breadcrumbs'
import LoadingScreen from './loading-screen'
const LockIcon = props => ( const LockIcon = props => (
<svg <svg
@ -36,9 +37,10 @@ const LockIcon = props => (
class BackupPhraseScreen extends Component { class BackupPhraseScreen extends Component {
static propTypes = { static propTypes = {
isLoading: PropTypes.bool.isRequired,
address: PropTypes.string.isRequired, address: PropTypes.string.isRequired,
seedWords: PropTypes.string.isRequired, seedWords: PropTypes.string.isRequired,
next: PropTypes.func.isRequired next: PropTypes.func.isRequired,
}; };
static defaultProps = { static defaultProps = {
@ -211,7 +213,9 @@ class BackupPhraseScreen extends Component {
} }
render() { render() {
return ( return this.props.isLoading
? <LoadingScreen loadingMessage="Creating your new account" />
: (
<div className="backup-phrase"> <div className="backup-phrase">
{this.renderBack()} {this.renderBack()}
<Identicon address={this.props.address} diameter={70} /> <Identicon address={this.props.address} diameter={70} />
@ -222,8 +226,9 @@ class BackupPhraseScreen extends Component {
} }
export default connect( export default connect(
({ metamask: { selectedAddress, seedWords } }) => ({ ({ metamask: { selectedAddress, seedWords }, appState: { isLoading } }) => ({
seedWords, seedWords,
isLoading,
address: selectedAddress address: selectedAddress
}), }),
dispatch => ({ dispatch => ({

@ -2,7 +2,9 @@ import React, {Component, PropTypes} from 'react'
import classnames from 'classnames' import classnames from 'classnames'
import {connect} from 'react-redux' import {connect} from 'react-redux'
import {qrcode} from 'qrcode-npm' import {qrcode} from 'qrcode-npm'
import copyToClipboard from 'copy-to-clipboard'
import Identicon from '../../../../ui/app/components/identicon' import Identicon from '../../../../ui/app/components/identicon'
import {buyEth, showAccountDetail} from '../../../../ui/app/actions'
class BuyEtherScreen extends Component { class BuyEtherScreen extends Component {
static OPTION_VALUES = { static OPTION_VALUES = {
@ -28,10 +30,34 @@ class BuyEtherScreen extends Component {
static propTypes = { static propTypes = {
address: PropTypes.string, address: PropTypes.string,
goToCoinbase: PropTypes.func.isRequired,
showAccountDetail: PropTypes.func.isRequired,
} }
state = { state = {
selectedOption: BuyEtherScreen.OPTION_VALUES.COINBASE, selectedOption: BuyEtherScreen.OPTION_VALUES.COINBASE,
justCopied: false
}
copyToClipboard = () => {
const { address } = this.props;
this.setState({ justCopied: true }, () => copyToClipboard(address))
setTimeout(() => this.setState({ justCopied: false }), 1000)
}
renderSkipStep() {
const {showAccountDetail, address} = this.props
return (
<button
className="first-time-flow__button--tertiary"
onClick={() => showAccountDetail(address)}
>
Skip this step
</button>
)
} }
renderCoinbaseLogo() { renderCoinbaseLogo() {
@ -59,12 +85,7 @@ class BuyEtherScreen extends Component {
) )
} }
renderContent() { renderCoinbaseForm() {
const { OPTION_VALUES } = BuyEtherScreen;
const { address } = this.props;
switch (this.state.selectedOption) {
case OPTION_VALUES.COINBASE:
return ( return (
<div className="buy-ether__action-content-wrapper"> <div className="buy-ether__action-content-wrapper">
<div>{this.renderCoinbaseLogo()}</div> <div>{this.renderCoinbaseLogo()}</div>
@ -73,18 +94,25 @@ class BuyEtherScreen extends Component {
<div className="buy-ether__buttons"> <div className="buy-ether__buttons">
<button <button
className="first-time-flow__button" className="first-time-flow__button"
onClick={() => this.goToCoinbase(address)}
> >
Buy Buy
</button> </button>
<div className="buy-ether__button-separator-text">or</div> <div className="buy-ether__button-separator-text">or</div>
<button {this.renderSkipStep()}
className="first-time-flow__button--tertiary"
>
Skip this step
</button>
</div> </div>
</div> </div>
) )
}
renderContent() {
const { OPTION_VALUES } = BuyEtherScreen
const { address, goToCoinbase } = this.props
const { justCopied } = this.state
switch (this.state.selectedOption) {
case OPTION_VALUES.COINBASE:
return this.renderCoinbaseForm()
case OPTION_VALUES.SHAPESHIFT: case OPTION_VALUES.SHAPESHIFT:
return ( return (
<div className="buy-ether__action-content-wrapper"> <div className="buy-ether__action-content-wrapper">
@ -97,11 +125,7 @@ class BuyEtherScreen extends Component {
Buy Buy
</button> </button>
<div className="buy-ether__button-separator-text">or</div> <div className="buy-ether__button-separator-text">or</div>
<button {this.renderSkipStep()}
className="first-time-flow__button--tertiary"
>
Skip this step
</button>
</div> </div>
</div> </div>
) )
@ -117,15 +141,13 @@ class BuyEtherScreen extends Component {
<div className="buy-ether__buttons"> <div className="buy-ether__buttons">
<button <button
className="first-time-flow__button" className="first-time-flow__button"
onClick={this.copyToClipboard}
disabled={justCopied}
> >
Copy { justCopied ? 'Copied' : 'Copy' }
</button> </button>
<div className="buy-ether__button-separator-text">or</div> <div className="buy-ether__button-separator-text">or</div>
<button {this.renderSkipStep()}
className="first-time-flow__button--tertiary"
>
Skip this step
</button>
</div> </div>
</div> </div>
) )
@ -177,8 +199,11 @@ class BuyEtherScreen extends Component {
} }
export default connect( export default connect(
({ metamask: { identities } }) => ({ ({ metamask: { selectedAddress } }) => ({
address: Object.entries(identities) address: selectedAddress
.map(([key]) => key)[0] }),
dispatch => ({
goToCoinbase: address => dispatch(buyEth({ network: '1', address, amount: 0 })),
showAccountDetail: address => dispatch(showAccountDetail(address)),
}) })
)(BuyEtherScreen) )(BuyEtherScreen)

@ -1,7 +1,8 @@
import React, {Component, PropTypes} from 'react' import React, {Component, PropTypes} from 'react'
import {connect} from 'react-redux';
import classnames from 'classnames' import classnames from 'classnames'
import LoadingScreen from './loading-screen'
import {importNewAccount, hideWarning} from '../../../../ui/app/actions' import {importNewAccount, hideWarning} from '../../../../ui/app/actions'
import {connect} from 'react-redux';
const Input = ({ label, placeholder, onChange, errorMessage, type = 'text' }) => ( const Input = ({ label, placeholder, onChange, errorMessage, type = 'text' }) => (
<div className="import-account__input-wrapper"> <div className="import-account__input-wrapper">
@ -132,7 +133,9 @@ class ImportAccountScreen extends Component {
const { OPTIONS } = ImportAccountScreen; const { OPTIONS } = ImportAccountScreen;
const { selectedOption } = this.state; const { selectedOption } = this.state;
return ( return isLoading
? <LoadingScreen loadingMessage="Creating your new account" />
: (
<div className="import-account"> <div className="import-account">
<a <a
className="import-account__back-button" className="import-account__back-button"

@ -2,6 +2,7 @@
height: 100vh; height: 100vh;
width: 100vw; width: 100vw;
background-color: #FFF; background-color: #FFF;
overflow: auto;
} }
.create-password, .create-password,

@ -6,19 +6,22 @@ import NoticeScreen from './notice-screen'
import BackupPhraseScreen from './backup-phrase-screen' import BackupPhraseScreen from './backup-phrase-screen'
import ImportAccountScreen from './import-account-screen' import ImportAccountScreen from './import-account-screen'
import BuyEtherScreen from './buy-ether-screen' import BuyEtherScreen from './buy-ether-screen'
import {buyEthView} from '../../../../ui/app/actions'
class FirstTimeFlow extends Component { class FirstTimeFlow extends Component {
static propTypes = { static propTypes = {
isInitialized: PropTypes.bool, isInitialized: PropTypes.bool,
seedWords: PropTypes.string, seedWords: PropTypes.string,
noActiveNotices: PropTypes.bool address: PropTypes.string,
noActiveNotices: PropTypes.bool,
goToBuyEtherView: PropTypes.func.isRequired,
}; };
static defaultProps = { static defaultProps = {
isInitialized: false, isInitialized: false,
seedWords: '', seedWords: '',
noActiveNotices: false noActiveNotices: false,
}; };
static SCREEN_TYPE = { static SCREEN_TYPE = {
@ -28,7 +31,6 @@ class FirstTimeFlow extends Component {
NOTICE: 'notice', NOTICE: 'notice',
BACK_UP_PHRASE: 'back_up_phrase', BACK_UP_PHRASE: 'back_up_phrase',
CONFIRM_BACK_UP_PHRASE: 'confirm_back_up_phrase', CONFIRM_BACK_UP_PHRASE: 'confirm_back_up_phrase',
BUY_ETHER: 'buy_ether'
}; };
constructor(props) { constructor(props) {
@ -43,7 +45,11 @@ class FirstTimeFlow extends Component {
} }
getScreenType() { getScreenType() {
const {isInitialized, seedWords, noActiveNotices} = this.props; const {
isInitialized,
seedWords,
noActiveNotices,
} = this.props;
const {SCREEN_TYPE} = FirstTimeFlow const {SCREEN_TYPE} = FirstTimeFlow
// return SCREEN_TYPE.IMPORT_ACCOUNT // return SCREEN_TYPE.IMPORT_ACCOUNT
@ -63,6 +69,7 @@ class FirstTimeFlow extends Component {
renderScreen() { renderScreen() {
const {SCREEN_TYPE} = FirstTimeFlow const {SCREEN_TYPE} = FirstTimeFlow
const {goToBuyEtherView, address} = this.props
switch (this.state.screenType) { switch (this.state.screenType) {
case SCREEN_TYPE.CREATE_PASSWORD: case SCREEN_TYPE.CREATE_PASSWORD:
@ -94,13 +101,7 @@ class FirstTimeFlow extends Component {
case SCREEN_TYPE.BACK_UP_PHRASE: case SCREEN_TYPE.BACK_UP_PHRASE:
return ( return (
<BackupPhraseScreen <BackupPhraseScreen
next={() => this.setScreenType(SCREEN_TYPE.BUY_ETHER)} next={() => goToBuyEtherView(address)}
/>
)
case SCREEN_TYPE.BUY_ETHER:
return (
<BuyEtherScreen
/> />
) )
default: default:
@ -119,10 +120,14 @@ class FirstTimeFlow extends Component {
} }
export default connect( export default connect(
({ metamask: { isInitialized, seedWords, noActiveNotices } }) => ({ ({ metamask: { isInitialized, seedWords, noActiveNotices, selectedAddress } }) => ({
isInitialized, isInitialized,
seedWords, seedWords,
noActiveNotices noActiveNotices,
address: selectedAddress,
}),
dispatch => ({
goToBuyEtherView: address => dispatch(buyEthView(address))
}) })
)(FirstTimeFlow) )(FirstTimeFlow)

@ -57,10 +57,9 @@ class NoticeScreen extends Component {
} }
export default connect( export default connect(
({ metamask: { identities, lastUnreadNotice } }) => ({ ({ metamask: { selectedAddress, lastUnreadNotice } }) => ({
lastUnreadNotice, lastUnreadNotice,
address: Object.entries(identities) address: selectedAddress
.map(([key]) => key)[0]
}), }),
dispatch => ({ dispatch => ({
markNoticeRead: notice => dispatch(markNoticeRead(notice)) markNoticeRead: notice => dispatch(markNoticeRead(notice))

@ -33,8 +33,7 @@ class UniqueImageScreen extends Component {
} }
export default connect( export default connect(
({ metamask: { identities } }) => ({ ({ metamask: { selectedAddress } }) => ({
address: Object.entries(identities) address: selectedAddress
.map(([key]) => key)[0]
}) })
)(UniqueImageScreen) )(UniqueImageScreen)

@ -224,7 +224,7 @@ function confirmSeedWords () {
} }
log.info('Seed word cache cleared. ' + account) log.info('Seed word cache cleared. ' + account)
dispatch(actions.showAccountDetail(account)) dispatch(actions.showAccountsPage())
resolve(account) resolve(account)
}) })
}) })

@ -5,6 +5,7 @@ const h = require('react-hyperscript')
const actions = require('./actions') const actions = require('./actions')
// mascara // mascara
const MascaraFirstTime = require('../../mascara/src/app/first-time').default const MascaraFirstTime = require('../../mascara/src/app/first-time').default
const MascaraBuyEtherScreen = require('../../mascara/src/app/first-time/buy-ether-screen').default
// init // init
const InitializeMenuScreen = require('./first-time/init-menu') const InitializeMenuScreen = require('./first-time/init-menu')
const NewKeyChainScreen = require('./new-keychain') const NewKeyChainScreen = require('./new-keychain')
@ -130,10 +131,16 @@ App.prototype.renderAppBar = function () {
const isNetworkMenuOpen = state.isNetworkMenuOpen || false const isNetworkMenuOpen = state.isNetworkMenuOpen || false
const {isMascara, isOnboarding} = props const {isMascara, isOnboarding} = props
// Do not render header if user is in mascara onboarding
if (isMascara && isOnboarding) { if (isMascara && isOnboarding) {
return null return null
} }
// Do not render header if user is in mascara buy ether
if (isMascara && props.currentView.name === 'buyEth') {
return null
}
return ( return (
h('.full-width', { h('.full-width', {
@ -433,9 +440,9 @@ App.prototype.renderPrimary = function () {
var props = this.props var props = this.props
const {isMascara, isOnboarding} = props const {isMascara, isOnboarding} = props
if (isMascara && isOnboarding) { // if (isMascara && isOnboarding) {
return h(MascaraFirstTime) // return h(MascaraFirstTime)
} // }
// notices // notices
if (!props.noActiveNotices) { if (!props.noActiveNotices) {
@ -534,7 +541,9 @@ App.prototype.renderPrimary = function () {
case 'buyEth': case 'buyEth':
log.debug('rendering buy ether screen') log.debug('rendering buy ether screen')
return h(BuyView, {key: 'buyEthView'}) return isMascara
? h(MascaraBuyEtherScreen, {key: 'buyEthView'})
: h(BuyView, {key: 'buyEthView'})
case 'qr': case 'qr':
log.debug('rendering show qr screen') log.debug('rendering show qr screen')

@ -62,7 +62,8 @@ CreateVaultCompleteScreen.prototype.render = function () {
}), }),
h('button.primary', { h('button.primary', {
onClick: () => this.confirmSeedWords(), onClick: () => this.confirmSeedWords()
.then(account => this.showAccountDetail(account)),
style: { style: {
margin: '24px', margin: '24px',
fontSize: '0.9em', fontSize: '0.9em',
@ -82,5 +83,9 @@ CreateVaultCompleteScreen.prototype.render = function () {
} }
CreateVaultCompleteScreen.prototype.confirmSeedWords = function () { CreateVaultCompleteScreen.prototype.confirmSeedWords = function () {
this.props.dispatch(actions.confirmSeedWords()) return this.props.dispatch(actions.confirmSeedWords())
}
CreateVaultCompleteScreen.prototype.showAccountDetail = function (account) {
return this.props.dispatch(actions.showAccountDetail(account))
} }

Loading…
Cancel
Save