2017-11-14 08:04:23 -08:00
|
|
|
const inherits = require('util').inherits
|
|
|
|
const Component = require('react').Component
|
|
|
|
const connect = require('react-redux').connect
|
|
|
|
const h = require('react-hyperscript')
|
2017-11-15 09:35:18 -08:00
|
|
|
const actions = require('../../ui/app/actions')
|
2018-04-12 14:06:59 -07:00
|
|
|
const log = require('loglevel')
|
2017-11-14 08:04:23 -08:00
|
|
|
// mascara
|
|
|
|
const MascaraFirstTime = require('../../mascara/src/app/first-time').default
|
|
|
|
const MascaraBuyEtherScreen = require('../../mascara/src/app/first-time/buy-ether-screen').default
|
|
|
|
// init
|
|
|
|
const InitializeMenuScreen = require('./first-time/init-menu')
|
|
|
|
const NewKeyChainScreen = require('./new-keychain')
|
|
|
|
// unlock
|
|
|
|
const UnlockScreen = require('./unlock')
|
|
|
|
// accounts
|
|
|
|
const AccountDetailScreen = require('./account-detail')
|
|
|
|
const SendTransactionScreen = require('./send')
|
|
|
|
const ConfirmTxScreen = require('./conf-tx')
|
|
|
|
// notice
|
|
|
|
const NoticeScreen = require('./components/notice')
|
|
|
|
const generateLostAccountsNotice = require('../lib/lost-accounts-notice')
|
|
|
|
// other views
|
|
|
|
const ConfigScreen = require('./config')
|
|
|
|
const AddTokenScreen = require('./add-token')
|
2018-07-24 04:59:24 -07:00
|
|
|
const RemoveTokenScreen = require('./remove-token')
|
2017-11-14 08:04:23 -08:00
|
|
|
const Import = require('./accounts/import')
|
|
|
|
const InfoScreen = require('./info')
|
|
|
|
const Loading = require('./components/loading')
|
|
|
|
const Dropdown = require('./components/dropdown').Dropdown
|
|
|
|
const DropdownMenuItem = require('./components/dropdown').DropdownMenuItem
|
|
|
|
const NetworkIndicator = require('./components/network')
|
|
|
|
const BuyView = require('./components/buy-button-subview')
|
|
|
|
const QrView = require('./components/qr-code')
|
|
|
|
const HDCreateVaultComplete = require('./keychains/hd/create-vault-complete')
|
|
|
|
const HDRestoreVaultScreen = require('./keychains/hd/restore-vault')
|
|
|
|
const RevealSeedConfirmation = require('./keychains/hd/recover-seed/confirmation')
|
|
|
|
const AccountDropdowns = require('./components/account-dropdowns').AccountDropdowns
|
2018-07-24 12:16:54 -07:00
|
|
|
const DeleteRpc = require('./components/delete-rpc')
|
2018-08-14 07:35:55 -07:00
|
|
|
const DeleteImportedAccount = require('./components/delete-imported-account')
|
2018-08-20 07:47:58 -07:00
|
|
|
const ConfirmChangePassword = require('./components/confirm-change-password')
|
2018-08-17 08:07:51 -07:00
|
|
|
const ethNetProps = require('eth-net-props')
|
2017-11-14 08:04:23 -08:00
|
|
|
|
|
|
|
module.exports = connect(mapStateToProps)(App)
|
|
|
|
|
|
|
|
inherits(App, Component)
|
|
|
|
function App () { Component.call(this) }
|
|
|
|
|
|
|
|
function mapStateToProps (state) {
|
|
|
|
const {
|
|
|
|
identities,
|
|
|
|
accounts,
|
|
|
|
address,
|
|
|
|
keyrings,
|
|
|
|
isInitialized,
|
|
|
|
noActiveNotices,
|
|
|
|
seedWords,
|
|
|
|
featureFlags,
|
|
|
|
} = state.metamask
|
|
|
|
const selected = address || Object.keys(accounts)[0]
|
|
|
|
|
|
|
|
return {
|
|
|
|
// state from plugin
|
|
|
|
isLoading: state.appState.isLoading,
|
|
|
|
loadingMessage: state.appState.loadingMessage,
|
|
|
|
noActiveNotices: state.metamask.noActiveNotices,
|
|
|
|
isInitialized: state.metamask.isInitialized,
|
|
|
|
isUnlocked: state.metamask.isUnlocked,
|
|
|
|
currentView: state.appState.currentView,
|
2018-05-21 17:58:48 -07:00
|
|
|
selectedAddress: state.metamask.selectedAddress,
|
2017-11-14 08:04:23 -08:00
|
|
|
transForward: state.appState.transForward,
|
|
|
|
isMascara: state.metamask.isMascara,
|
|
|
|
isOnboarding: Boolean(!noActiveNotices || seedWords || !isInitialized),
|
|
|
|
seedWords: state.metamask.seedWords,
|
|
|
|
unapprovedTxs: state.metamask.unapprovedTxs,
|
|
|
|
unapprovedMsgs: state.metamask.unapprovedMsgs,
|
|
|
|
menuOpen: state.appState.menuOpen,
|
|
|
|
network: state.metamask.network,
|
|
|
|
provider: state.metamask.provider,
|
|
|
|
forgottenPassword: state.appState.forgottenPassword,
|
2018-06-13 23:30:31 -07:00
|
|
|
nextUnreadNotice: state.metamask.nextUnreadNotice,
|
2017-11-14 08:04:23 -08:00
|
|
|
lostAccounts: state.metamask.lostAccounts,
|
|
|
|
frequentRpcList: state.metamask.frequentRpcList || [],
|
|
|
|
featureFlags,
|
|
|
|
|
|
|
|
// state needed to get account dropdown temporarily rendering from app bar
|
|
|
|
identities,
|
|
|
|
selected,
|
|
|
|
keyrings,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
App.prototype.render = function () {
|
|
|
|
var props = this.props
|
|
|
|
const { isLoading, loadingMessage, transForward, network } = props
|
2018-07-24 12:16:54 -07:00
|
|
|
const isLoadingNetwork = network === 'loading' && props.currentView.name !== 'config' && props.currentView.name !== 'delete-rpc'
|
2017-11-14 08:04:23 -08:00
|
|
|
const loadMessage = loadingMessage || isLoadingNetwork ?
|
|
|
|
`Connecting to ${this.getNetworkName()}` : null
|
|
|
|
log.debug('Main ui render function')
|
|
|
|
|
|
|
|
return (
|
2017-12-08 08:36:56 -08:00
|
|
|
h('.flex-column.full-height', {
|
|
|
|
style: {
|
|
|
|
// Windows was showing a vertical scroll bar:
|
|
|
|
overflow: 'hidden',
|
|
|
|
position: 'relative',
|
|
|
|
alignItems: 'center',
|
2018-07-31 07:47:46 -07:00
|
|
|
background: (props.isUnlocked || props.currentView.name === 'restoreVault' || props.currentView.name === 'config') ? 'white' : 'linear-gradient(rgb(84, 36, 147), rgb(104, 45, 182))',
|
2017-12-08 08:36:56 -08:00
|
|
|
},
|
|
|
|
}, [
|
|
|
|
|
|
|
|
// app bar
|
|
|
|
this.renderAppBar(),
|
|
|
|
this.renderNetworkDropdown(),
|
|
|
|
this.renderDropdown(),
|
|
|
|
|
|
|
|
this.renderLoadingIndicator({ isLoading, isLoadingNetwork, loadMessage }),
|
|
|
|
|
|
|
|
// panel content
|
2018-07-26 17:16:24 -07:00
|
|
|
h('.app-primary' + (transForward ? '.from-right' : '.from-left'), {
|
|
|
|
style: {
|
2018-07-31 07:47:46 -07:00
|
|
|
background: (props.isUnlocked || props.currentView.name === 'restoreVault' || props.currentView.name === 'config') ? 'white' : 'transparent',
|
2018-07-27 09:54:23 -07:00
|
|
|
},
|
2018-07-26 17:16:24 -07:00
|
|
|
}, [
|
2017-12-08 08:36:56 -08:00
|
|
|
this.renderPrimary(),
|
|
|
|
]),
|
2017-11-14 08:04:23 -08:00
|
|
|
])
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2018-07-31 10:39:02 -07:00
|
|
|
App.prototype.changeState = function (isMainMenuOpen) {
|
|
|
|
this.setState({
|
|
|
|
isMainMenuOpen,
|
|
|
|
sandwichClass: isMainMenuOpen ? 'sandwich-expando expanded' : 'sandwich-expando',
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2017-11-14 08:04:23 -08:00
|
|
|
App.prototype.renderAppBar = function () {
|
|
|
|
if (window.METAMASK_UI_TYPE === 'notification') {
|
|
|
|
return null
|
|
|
|
}
|
|
|
|
|
|
|
|
const props = this.props
|
|
|
|
const state = this.state || {}
|
|
|
|
const isNetworkMenuOpen = state.isNetworkMenuOpen || false
|
|
|
|
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', {
|
|
|
|
height: '38px',
|
|
|
|
}, [
|
|
|
|
|
|
|
|
h('.app-header.flex-row.flex-space-between', {
|
|
|
|
style: {
|
|
|
|
alignItems: 'center',
|
|
|
|
visibility: props.isUnlocked ? 'visible' : 'none',
|
2018-07-26 11:15:51 -07:00
|
|
|
background: 'white',
|
2017-11-14 08:04:23 -08:00
|
|
|
height: '38px',
|
|
|
|
position: 'relative',
|
|
|
|
zIndex: 12,
|
|
|
|
},
|
|
|
|
}, [
|
|
|
|
|
|
|
|
h('div.left-menu-section', {
|
|
|
|
style: {
|
|
|
|
display: 'flex',
|
|
|
|
flexDirection: 'row',
|
|
|
|
alignItems: 'center',
|
|
|
|
},
|
|
|
|
}, [
|
|
|
|
|
|
|
|
// mini logo
|
|
|
|
h('img', {
|
|
|
|
height: 24,
|
|
|
|
width: 24,
|
2018-03-28 22:30:35 -07:00
|
|
|
src: './images/icon-128.png',
|
2017-11-14 08:04:23 -08:00
|
|
|
}),
|
|
|
|
|
|
|
|
h(NetworkIndicator, {
|
|
|
|
network: this.props.network,
|
|
|
|
provider: this.props.provider,
|
2018-08-07 06:23:56 -07:00
|
|
|
isUnlocked: this.props.isUnlocked,
|
2017-11-14 08:04:23 -08:00
|
|
|
onClick: (event) => {
|
|
|
|
event.preventDefault()
|
|
|
|
event.stopPropagation()
|
|
|
|
this.setState({ isNetworkMenuOpen: !isNetworkMenuOpen })
|
|
|
|
},
|
|
|
|
}),
|
2018-05-04 04:57:19 -07:00
|
|
|
|
2017-11-14 08:04:23 -08:00
|
|
|
]),
|
|
|
|
|
|
|
|
props.isUnlocked && h('div', {
|
|
|
|
style: {
|
|
|
|
display: 'flex',
|
|
|
|
flexDirection: 'row',
|
|
|
|
alignItems: 'center',
|
|
|
|
},
|
|
|
|
}, [
|
|
|
|
|
|
|
|
props.isUnlocked && h(AccountDropdowns, {
|
|
|
|
style: {},
|
|
|
|
enableAccountsSelector: true,
|
|
|
|
identities: this.props.identities,
|
2018-05-21 17:58:48 -07:00
|
|
|
selected: this.props.selectedAddress,
|
2017-11-14 08:04:23 -08:00
|
|
|
network: this.props.network,
|
|
|
|
keyrings: this.props.keyrings,
|
|
|
|
}, []),
|
|
|
|
|
|
|
|
// hamburger
|
2018-07-31 10:39:02 -07:00
|
|
|
props.isUnlocked && h('div', {
|
|
|
|
className: state.sandwichClass || 'sandwich-expando',
|
|
|
|
style: {
|
|
|
|
width: 16,
|
|
|
|
height: 16,
|
|
|
|
padding: 0,
|
2017-11-14 08:04:23 -08:00
|
|
|
},
|
2018-07-31 10:39:02 -07:00
|
|
|
onClick: () => this.changeState(!state.isMainMenuOpen),
|
2017-11-14 08:04:23 -08:00
|
|
|
}),
|
|
|
|
]),
|
|
|
|
]),
|
|
|
|
])
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
App.prototype.renderNetworkDropdown = function () {
|
|
|
|
const props = this.props
|
2018-08-08 10:16:19 -07:00
|
|
|
const { provider: { type: providerType } } = props
|
2017-11-14 08:04:23 -08:00
|
|
|
const rpcList = props.frequentRpcList
|
|
|
|
const state = this.state || {}
|
|
|
|
const isOpen = state.isNetworkMenuOpen
|
|
|
|
|
|
|
|
return h(Dropdown, {
|
|
|
|
useCssTransition: true,
|
|
|
|
isOpen,
|
|
|
|
onClickOutside: (event) => {
|
|
|
|
const { classList } = event.target
|
|
|
|
const isNotToggleElement = [
|
|
|
|
classList.contains('menu-icon'),
|
|
|
|
classList.contains('network-name'),
|
|
|
|
classList.contains('network-indicator'),
|
|
|
|
].filter(bool => bool).length === 0
|
|
|
|
// classes from three constituent nodes of the toggle element
|
|
|
|
|
|
|
|
if (isNotToggleElement) {
|
|
|
|
this.setState({ isNetworkMenuOpen: false })
|
|
|
|
}
|
|
|
|
},
|
|
|
|
zIndex: 11,
|
|
|
|
style: {
|
|
|
|
position: 'absolute',
|
|
|
|
left: '2px',
|
|
|
|
top: '36px',
|
2018-08-06 05:47:42 -07:00
|
|
|
width: '270px',
|
2017-11-14 08:04:23 -08:00
|
|
|
},
|
|
|
|
innerStyle: {
|
|
|
|
padding: '2px 16px 2px 0px',
|
|
|
|
},
|
|
|
|
}, [
|
|
|
|
|
|
|
|
h(
|
|
|
|
DropdownMenuItem,
|
|
|
|
{
|
2018-07-19 12:29:22 -07:00
|
|
|
key: 'poa',
|
2017-11-14 08:04:23 -08:00
|
|
|
closeMenu: () => this.setState({ isNetworkMenuOpen: !isOpen }),
|
2018-07-19 12:29:22 -07:00
|
|
|
onClick: () => props.dispatch(actions.setProviderType('poa')),
|
2017-11-14 08:04:23 -08:00
|
|
|
style: {
|
2018-07-26 11:15:51 -07:00
|
|
|
paddingLeft: '20px',
|
|
|
|
fontSize: '16px',
|
2018-07-26 17:16:24 -07:00
|
|
|
color: providerType === 'poa' ? 'white' : '',
|
2017-11-14 08:04:23 -08:00
|
|
|
},
|
|
|
|
},
|
2018-07-27 08:21:01 -07:00
|
|
|
[h(providerType === 'poa' ? 'div.selected-network' : ''),
|
2018-08-17 08:07:51 -07:00
|
|
|
ethNetProps.props.getNetworkDisplayName(99),
|
2017-11-14 08:04:23 -08:00
|
|
|
]
|
|
|
|
),
|
|
|
|
|
2018-07-18 10:41:53 -07:00
|
|
|
h(
|
|
|
|
DropdownMenuItem,
|
|
|
|
{
|
|
|
|
key: 'sokol',
|
|
|
|
closeMenu: () => this.setState({ isNetworkMenuOpen: !isOpen }),
|
|
|
|
onClick: () => props.dispatch(actions.setProviderType('sokol')),
|
|
|
|
style: {
|
2018-07-26 11:15:51 -07:00
|
|
|
paddingLeft: '20px',
|
|
|
|
fontSize: '16px',
|
2018-07-26 17:16:24 -07:00
|
|
|
color: providerType === 'sokol' ? 'white' : '',
|
2018-07-18 10:41:53 -07:00
|
|
|
},
|
|
|
|
},
|
2018-07-27 08:21:01 -07:00
|
|
|
[h(providerType === 'sokol' ? 'div.selected-network' : ''),
|
2018-08-17 08:07:51 -07:00
|
|
|
ethNetProps.props.getNetworkDisplayName(77),
|
2018-07-18 10:41:53 -07:00
|
|
|
]
|
|
|
|
),
|
|
|
|
|
2018-07-19 12:29:22 -07:00
|
|
|
h(
|
|
|
|
DropdownMenuItem,
|
|
|
|
{
|
|
|
|
key: 'main',
|
|
|
|
closeMenu: () => this.setState({ isNetworkMenuOpen: !isOpen }),
|
|
|
|
onClick: () => props.dispatch(actions.setProviderType('mainnet')),
|
|
|
|
style: {
|
2018-07-26 11:15:51 -07:00
|
|
|
paddingLeft: '20px',
|
|
|
|
fontSize: '16px',
|
2018-07-26 17:16:24 -07:00
|
|
|
color: providerType === 'mainnet' ? 'white' : '',
|
2018-07-19 12:29:22 -07:00
|
|
|
},
|
|
|
|
},
|
2018-07-27 08:21:01 -07:00
|
|
|
[h(providerType === 'mainnet' ? 'div.selected-network' : ''),
|
2018-08-17 08:07:51 -07:00
|
|
|
ethNetProps.props.getNetworkDisplayName(1),
|
2018-07-19 12:29:22 -07:00
|
|
|
]
|
|
|
|
),
|
|
|
|
|
2017-11-14 08:04:23 -08:00
|
|
|
h(
|
|
|
|
DropdownMenuItem,
|
|
|
|
{
|
|
|
|
key: 'ropsten',
|
|
|
|
closeMenu: () => this.setState({ isNetworkMenuOpen: !isOpen }),
|
|
|
|
onClick: () => props.dispatch(actions.setProviderType('ropsten')),
|
|
|
|
style: {
|
2018-07-26 11:15:51 -07:00
|
|
|
paddingLeft: '20px',
|
|
|
|
fontSize: '16px',
|
2018-07-26 17:16:24 -07:00
|
|
|
color: providerType === 'ropsten' ? 'white' : '',
|
2017-11-14 08:04:23 -08:00
|
|
|
},
|
|
|
|
},
|
2018-07-27 08:21:01 -07:00
|
|
|
[h(providerType === 'ropsten' ? 'div.selected-network' : ''),
|
2018-08-17 08:07:51 -07:00
|
|
|
ethNetProps.props.getNetworkDisplayName(3),
|
2017-11-14 08:04:23 -08:00
|
|
|
]
|
|
|
|
),
|
|
|
|
|
|
|
|
h(
|
|
|
|
DropdownMenuItem,
|
|
|
|
{
|
|
|
|
key: 'kovan',
|
|
|
|
closeMenu: () => this.setState({ isNetworkMenuOpen: !isOpen }),
|
|
|
|
onClick: () => props.dispatch(actions.setProviderType('kovan')),
|
|
|
|
style: {
|
2018-07-26 11:15:51 -07:00
|
|
|
paddingLeft: '20px',
|
|
|
|
fontSize: '16px',
|
2018-07-26 17:16:24 -07:00
|
|
|
color: providerType === 'kovan' ? 'white' : '',
|
2017-11-14 08:04:23 -08:00
|
|
|
},
|
|
|
|
},
|
2018-07-27 08:21:01 -07:00
|
|
|
[h(providerType === 'kovan' ? 'div.selected-network' : ''),
|
2018-08-17 08:07:51 -07:00
|
|
|
ethNetProps.props.getNetworkDisplayName(42),
|
2017-11-14 08:04:23 -08:00
|
|
|
]
|
|
|
|
),
|
|
|
|
|
|
|
|
h(
|
|
|
|
DropdownMenuItem,
|
|
|
|
{
|
|
|
|
key: 'rinkeby',
|
|
|
|
closeMenu: () => this.setState({ isNetworkMenuOpen: !isOpen }),
|
|
|
|
onClick: () => props.dispatch(actions.setProviderType('rinkeby')),
|
|
|
|
style: {
|
2018-07-26 11:15:51 -07:00
|
|
|
paddingLeft: '20px',
|
|
|
|
fontSize: '16px',
|
2018-07-26 17:16:24 -07:00
|
|
|
color: providerType === 'rinkeby' ? 'white' : '',
|
2017-11-14 08:04:23 -08:00
|
|
|
},
|
|
|
|
},
|
2018-07-27 08:21:01 -07:00
|
|
|
[h(providerType === 'rinkeby' ? 'div.selected-network' : ''),
|
2018-08-17 08:07:51 -07:00
|
|
|
ethNetProps.props.getNetworkDisplayName(4),
|
2017-11-14 08:04:23 -08:00
|
|
|
]
|
|
|
|
),
|
|
|
|
|
|
|
|
h(
|
|
|
|
DropdownMenuItem,
|
|
|
|
{
|
|
|
|
key: 'default',
|
|
|
|
closeMenu: () => this.setState({ isNetworkMenuOpen: !isOpen }),
|
|
|
|
onClick: () => props.dispatch(actions.setProviderType('localhost')),
|
|
|
|
style: {
|
2018-07-26 11:15:51 -07:00
|
|
|
paddingLeft: '20px',
|
|
|
|
fontSize: '16px',
|
2018-08-08 10:16:19 -07:00
|
|
|
color: providerType === 'localhost' ? 'white' : '',
|
2017-11-14 08:04:23 -08:00
|
|
|
},
|
|
|
|
},
|
2018-08-08 10:16:19 -07:00
|
|
|
[h(providerType === 'localhost' ? 'div.selected-network' : ''),
|
2018-07-27 09:54:23 -07:00
|
|
|
'Localhost 8545',
|
2017-11-14 08:04:23 -08:00
|
|
|
]
|
|
|
|
),
|
|
|
|
|
|
|
|
this.renderCustomOption(props.provider),
|
|
|
|
this.renderCommonRpc(rpcList, props.provider),
|
|
|
|
|
|
|
|
h(
|
|
|
|
DropdownMenuItem,
|
|
|
|
{
|
|
|
|
closeMenu: () => this.setState({ isNetworkMenuOpen: !isOpen }),
|
|
|
|
onClick: () => this.props.dispatch(actions.showConfigPage()),
|
|
|
|
style: {
|
2018-07-26 11:15:51 -07:00
|
|
|
paddingLeft: '20px',
|
|
|
|
fontSize: '16px',
|
2018-08-20 09:45:52 -07:00
|
|
|
color: '#60db97',
|
2017-11-14 08:04:23 -08:00
|
|
|
},
|
|
|
|
},
|
|
|
|
[
|
2018-07-27 09:54:23 -07:00
|
|
|
'Custom RPC',
|
2017-11-14 08:04:23 -08:00
|
|
|
]
|
|
|
|
),
|
|
|
|
|
|
|
|
])
|
|
|
|
}
|
|
|
|
|
|
|
|
App.prototype.renderDropdown = function () {
|
|
|
|
const state = this.state || {}
|
|
|
|
const isOpen = state.isMainMenuOpen
|
2018-07-31 10:39:02 -07:00
|
|
|
const isMainMenuOpen = !isOpen
|
2017-11-14 08:04:23 -08:00
|
|
|
|
|
|
|
return h(Dropdown, {
|
|
|
|
useCssTransition: true,
|
|
|
|
isOpen: isOpen,
|
|
|
|
zIndex: 11,
|
|
|
|
onClickOutside: (event) => {
|
|
|
|
const classList = event.target.classList
|
|
|
|
const parentClassList = event.target.parentElement.classList
|
|
|
|
|
|
|
|
const isToggleElement = classList.contains('sandwich-expando') ||
|
|
|
|
parentClassList.contains('sandwich-expando')
|
|
|
|
|
|
|
|
if (isOpen && !isToggleElement) {
|
2018-07-27 09:54:23 -07:00
|
|
|
this.setState({
|
2018-07-27 09:52:28 -07:00
|
|
|
isMainMenuOpen: false,
|
2018-07-31 10:39:02 -07:00
|
|
|
sandwichClass: 'sandwich-expando',
|
2018-07-27 09:52:28 -07:00
|
|
|
})
|
2017-11-14 08:04:23 -08:00
|
|
|
}
|
|
|
|
},
|
|
|
|
style: {
|
|
|
|
position: 'absolute',
|
|
|
|
right: '2px',
|
|
|
|
top: '38px',
|
|
|
|
},
|
|
|
|
innerStyle: {},
|
|
|
|
}, [
|
|
|
|
h(DropdownMenuItem, {
|
2018-07-31 10:39:02 -07:00
|
|
|
closeMenu: () => this.changeState(isMainMenuOpen),
|
2017-11-14 08:04:23 -08:00
|
|
|
onClick: () => { this.props.dispatch(actions.showConfigPage()) },
|
|
|
|
}, 'Settings'),
|
|
|
|
|
|
|
|
h(DropdownMenuItem, {
|
2018-07-31 10:39:02 -07:00
|
|
|
closeMenu: () => this.changeState(isMainMenuOpen),
|
2017-11-14 08:04:23 -08:00
|
|
|
onClick: () => { this.props.dispatch(actions.lockMetamask()) },
|
2018-01-16 18:17:28 -08:00
|
|
|
}, 'Log Out'),
|
2017-11-14 08:04:23 -08:00
|
|
|
|
|
|
|
h(DropdownMenuItem, {
|
2018-07-31 10:39:02 -07:00
|
|
|
closeMenu: () => this.changeState(isMainMenuOpen),
|
2017-11-14 08:04:23 -08:00
|
|
|
onClick: () => { this.props.dispatch(actions.showInfoPage()) },
|
|
|
|
}, 'Info/Help'),
|
|
|
|
])
|
|
|
|
}
|
|
|
|
|
|
|
|
App.prototype.renderLoadingIndicator = function ({ isLoading, isLoadingNetwork, loadMessage }) {
|
|
|
|
const { isMascara } = this.props
|
|
|
|
|
|
|
|
return isMascara
|
|
|
|
? null
|
|
|
|
: h(Loading, {
|
|
|
|
isLoading: isLoading || isLoadingNetwork,
|
|
|
|
loadingMessage: loadMessage,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
App.prototype.renderBackButton = function (style, justArrow = false) {
|
|
|
|
var props = this.props
|
|
|
|
return (
|
|
|
|
h('.flex-row', {
|
|
|
|
key: 'leftArrow',
|
|
|
|
style: style,
|
|
|
|
onClick: () => props.dispatch(actions.goBackToInitView()),
|
|
|
|
}, [
|
|
|
|
h('i.fa.fa-arrow-left.cursor-pointer'),
|
|
|
|
justArrow ? null : h('div.cursor-pointer', {
|
|
|
|
style: {
|
|
|
|
marginLeft: '3px',
|
|
|
|
},
|
|
|
|
onClick: () => props.dispatch(actions.goBackToInitView()),
|
|
|
|
}, 'BACK'),
|
|
|
|
])
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
App.prototype.renderPrimary = function () {
|
|
|
|
log.debug('rendering primary')
|
|
|
|
var props = this.props
|
|
|
|
const {isMascara, isOnboarding} = props
|
|
|
|
|
|
|
|
if (isMascara && isOnboarding) {
|
|
|
|
return h(MascaraFirstTime)
|
|
|
|
}
|
|
|
|
|
|
|
|
// notices
|
|
|
|
if (!props.noActiveNotices) {
|
|
|
|
log.debug('rendering notice screen for unread notices.')
|
2018-02-20 17:04:55 -08:00
|
|
|
return h('div', {
|
|
|
|
style: { width: '100%' },
|
|
|
|
}, [
|
2018-02-08 15:33:23 -08:00
|
|
|
|
|
|
|
h(NoticeScreen, {
|
2018-06-13 23:30:31 -07:00
|
|
|
notice: props.nextUnreadNotice,
|
2018-02-08 15:33:23 -08:00
|
|
|
key: 'NoticeScreen',
|
2018-06-13 23:30:31 -07:00
|
|
|
onConfirm: () => props.dispatch(actions.markNoticeRead(props.nextUnreadNotice)),
|
2018-02-08 15:33:23 -08:00
|
|
|
}),
|
|
|
|
|
|
|
|
])
|
2017-11-14 08:04:23 -08:00
|
|
|
} else if (props.lostAccounts && props.lostAccounts.length > 0) {
|
|
|
|
log.debug('rendering notice screen for lost accounts view.')
|
|
|
|
return h(NoticeScreen, {
|
|
|
|
notice: generateLostAccountsNotice(props.lostAccounts),
|
|
|
|
key: 'LostAccountsNotice',
|
|
|
|
onConfirm: () => props.dispatch(actions.markAccountsFound()),
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
// show initialize screen
|
|
|
|
if (!props.isInitialized || props.forgottenPassword) {
|
|
|
|
// show current view
|
|
|
|
log.debug('rendering an initialize screen')
|
|
|
|
switch (props.currentView.name) {
|
|
|
|
|
|
|
|
case 'restoreVault':
|
|
|
|
log.debug('rendering restore vault screen')
|
|
|
|
return h(HDRestoreVaultScreen, {key: 'HDRestoreVaultScreen'})
|
|
|
|
|
|
|
|
default:
|
|
|
|
log.debug('rendering menu screen')
|
|
|
|
return h(InitializeMenuScreen, {key: 'menuScreenInit'})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// show unlock screen
|
|
|
|
if (!props.isUnlocked) {
|
|
|
|
switch (props.currentView.name) {
|
|
|
|
|
|
|
|
case 'restoreVault':
|
|
|
|
log.debug('rendering restore vault screen')
|
|
|
|
return h(HDRestoreVaultScreen, {key: 'HDRestoreVaultScreen'})
|
|
|
|
|
|
|
|
case 'config':
|
|
|
|
log.debug('rendering config screen from unlock screen.')
|
|
|
|
return h(ConfigScreen, {key: 'config'})
|
|
|
|
|
|
|
|
default:
|
|
|
|
log.debug('rendering locked screen')
|
|
|
|
return h(UnlockScreen, {key: 'locked'})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-01-16 18:34:24 -08:00
|
|
|
// show seed words screen
|
|
|
|
if (props.seedWords) {
|
|
|
|
log.debug('rendering seed words')
|
|
|
|
return h(HDCreateVaultComplete, {key: 'HDCreateVaultComplete'})
|
|
|
|
}
|
|
|
|
|
2017-11-14 08:04:23 -08:00
|
|
|
// show current view
|
|
|
|
switch (props.currentView.name) {
|
|
|
|
|
|
|
|
case 'accountDetail':
|
|
|
|
log.debug('rendering account detail screen')
|
|
|
|
return h(AccountDetailScreen, {key: 'account-detail'})
|
|
|
|
|
|
|
|
case 'sendTransaction':
|
|
|
|
log.debug('rendering send tx screen')
|
|
|
|
return h(SendTransactionScreen, {key: 'send-transaction'})
|
|
|
|
|
|
|
|
case 'newKeychain':
|
|
|
|
log.debug('rendering new keychain screen')
|
|
|
|
return h(NewKeyChainScreen, {key: 'new-keychain'})
|
|
|
|
|
|
|
|
case 'confTx':
|
|
|
|
log.debug('rendering confirm tx screen')
|
|
|
|
return h(ConfirmTxScreen, {key: 'confirm-tx'})
|
|
|
|
|
|
|
|
case 'add-token':
|
|
|
|
log.debug('rendering add-token screen from unlock screen.')
|
|
|
|
return h(AddTokenScreen, {key: 'add-token'})
|
|
|
|
|
2018-07-24 04:59:24 -07:00
|
|
|
case 'remove-token':
|
|
|
|
log.debug('rendering remove-token screen from unlock screen.')
|
|
|
|
return h(RemoveTokenScreen, {key: 'remove-token', ...props.currentView.context })
|
|
|
|
|
2017-11-14 08:04:23 -08:00
|
|
|
case 'config':
|
|
|
|
log.debug('rendering config screen')
|
|
|
|
return h(ConfigScreen, {key: 'config'})
|
|
|
|
|
|
|
|
case 'import-menu':
|
|
|
|
log.debug('rendering import screen')
|
|
|
|
return h(Import, {key: 'import-menu'})
|
|
|
|
|
|
|
|
case 'reveal-seed-conf':
|
|
|
|
log.debug('rendering reveal seed confirmation screen')
|
|
|
|
return h(RevealSeedConfirmation, {key: 'reveal-seed-conf'})
|
|
|
|
|
|
|
|
case 'info':
|
|
|
|
log.debug('rendering info screen')
|
|
|
|
return h(InfoScreen, {key: 'info'})
|
|
|
|
|
|
|
|
case 'buyEth':
|
|
|
|
log.debug('rendering buy ether screen')
|
|
|
|
return h(BuyView, {key: 'buyEthView'})
|
|
|
|
|
|
|
|
case 'onboardingBuyEth':
|
|
|
|
log.debug('rendering onboarding buy ether screen')
|
|
|
|
return h(MascaraBuyEtherScreen, {key: 'buyEthView'})
|
|
|
|
|
|
|
|
case 'qr':
|
|
|
|
log.debug('rendering show qr screen')
|
|
|
|
return h('div', {
|
|
|
|
style: {
|
|
|
|
height: '100%',
|
|
|
|
top: '0px',
|
|
|
|
left: '0px',
|
2018-07-26 15:54:07 -07:00
|
|
|
width: '100%',
|
2017-11-14 08:04:23 -08:00
|
|
|
},
|
|
|
|
}, [
|
2018-07-31 11:34:13 -07:00
|
|
|
h('.section-title.flex-row.flex-center', [
|
|
|
|
h('i.fa.fa-arrow-left.fa-lg.cursor-pointer', {
|
2018-07-26 15:54:07 -07:00
|
|
|
onClick: () => props.dispatch(actions.backToAccountDetail(props.selectedAddress)),
|
|
|
|
style: {
|
2018-07-31 11:34:13 -07:00
|
|
|
marginLeft: '30px',
|
|
|
|
marginTop: '5px',
|
2018-07-26 15:54:07 -07:00
|
|
|
position: 'absolute',
|
|
|
|
left: '0',
|
|
|
|
},
|
|
|
|
}),
|
|
|
|
h('h2.page-subtitle', {
|
|
|
|
style: {
|
|
|
|
fontFamily: 'Nunito SemiBold',
|
2018-07-31 11:34:13 -07:00
|
|
|
marginTop: '10px',
|
2018-07-26 15:54:07 -07:00
|
|
|
marginBottom: '0px',
|
|
|
|
textAlign: 'center',
|
2018-07-27 09:54:23 -07:00
|
|
|
},
|
2018-07-26 15:54:07 -07:00
|
|
|
}, 'QR Code'),
|
|
|
|
]),
|
2018-08-06 11:11:06 -07:00
|
|
|
h('div', [
|
2017-11-14 08:04:23 -08:00
|
|
|
h(QrView, {key: 'qr'}),
|
|
|
|
]),
|
|
|
|
])
|
2018-07-24 12:16:54 -07:00
|
|
|
case 'delete-rpc':
|
|
|
|
log.debug('rendering delete rpc confirmation screen')
|
|
|
|
return h(DeleteRpc, {key: 'delete-rpc'})
|
2018-08-14 07:35:55 -07:00
|
|
|
case 'delete-imported-account':
|
|
|
|
log.debug('rendering delete imported account confirmation screen')
|
|
|
|
return h(DeleteImportedAccount, {key: 'delete-imported-account'})
|
2018-08-20 07:47:58 -07:00
|
|
|
case 'confirm-change-password':
|
|
|
|
log.debug('rendering confirm password changing screen')
|
|
|
|
return h(ConfirmChangePassword, {key: 'confirm-change-password'})
|
2017-11-14 08:04:23 -08:00
|
|
|
default:
|
|
|
|
log.debug('rendering default, account detail screen')
|
|
|
|
return h(AccountDetailScreen, {key: 'account-detail'})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
App.prototype.toggleMetamaskActive = function () {
|
|
|
|
if (!this.props.isUnlocked) {
|
|
|
|
// currently inactive: redirect to password box
|
|
|
|
var passwordBox = document.querySelector('input[type=password]')
|
|
|
|
if (!passwordBox) return
|
|
|
|
passwordBox.focus()
|
|
|
|
} else {
|
|
|
|
// currently active: deactivate
|
|
|
|
this.props.dispatch(actions.lockMetamask(false))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
App.prototype.renderCustomOption = function (provider) {
|
|
|
|
const { rpcTarget, type } = provider
|
|
|
|
const props = this.props
|
|
|
|
|
|
|
|
if (type !== 'rpc') return null
|
|
|
|
|
|
|
|
// Concatenate long URLs
|
|
|
|
let label = rpcTarget
|
|
|
|
if (rpcTarget.length > 31) {
|
|
|
|
label = label.substr(0, 34) + '...'
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (rpcTarget) {
|
|
|
|
|
|
|
|
case 'http://localhost:8545':
|
|
|
|
return null
|
|
|
|
|
|
|
|
default:
|
|
|
|
return h(
|
|
|
|
DropdownMenuItem,
|
|
|
|
{
|
|
|
|
key: rpcTarget,
|
|
|
|
onClick: () => props.dispatch(actions.setRpcTarget(rpcTarget)),
|
|
|
|
closeMenu: () => this.setState({ isNetworkMenuOpen: false }),
|
2018-07-26 11:15:51 -07:00
|
|
|
style: {
|
|
|
|
paddingLeft: '20px',
|
|
|
|
fontSize: '16px',
|
2018-07-26 17:16:24 -07:00
|
|
|
color: 'white',
|
2018-07-26 11:15:51 -07:00
|
|
|
},
|
2017-11-14 08:04:23 -08:00
|
|
|
},
|
2018-07-27 08:21:01 -07:00
|
|
|
[h('div.selected-network'),
|
2018-08-20 01:37:47 -07:00
|
|
|
h('.span.custom-rpc', label),
|
2018-08-14 07:35:55 -07:00
|
|
|
h('.remove', {
|
2018-08-06 05:47:42 -07:00
|
|
|
onClick: (event) => {
|
|
|
|
event.preventDefault()
|
|
|
|
event.stopPropagation()
|
|
|
|
this.setState({ isNetworkMenuOpen: false })
|
|
|
|
props.dispatch(actions.showDeleteRPC(label))
|
2018-08-06 05:55:58 -07:00
|
|
|
},
|
|
|
|
}),
|
2017-11-14 08:04:23 -08:00
|
|
|
]
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
App.prototype.getNetworkName = function () {
|
2018-08-17 08:07:51 -07:00
|
|
|
const { network } = this.props
|
2018-08-21 07:16:47 -07:00
|
|
|
return ethNetProps.props.getNetworkDisplayName(network)
|
2017-11-14 08:04:23 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
App.prototype.renderCommonRpc = function (rpcList, provider) {
|
|
|
|
const props = this.props
|
|
|
|
const rpcTarget = provider.rpcTarget
|
|
|
|
|
|
|
|
return rpcList.map((rpc) => {
|
2018-07-25 10:59:10 -07:00
|
|
|
if ((rpc === 'http://localhost:8545') || (provider.type === 'rpc' && rpc === rpcTarget)) {
|
2017-11-14 08:04:23 -08:00
|
|
|
return null
|
|
|
|
} else {
|
|
|
|
return h(
|
|
|
|
DropdownMenuItem,
|
|
|
|
{
|
|
|
|
key: `common${rpc}`,
|
|
|
|
closeMenu: () => this.setState({ isNetworkMenuOpen: false }),
|
|
|
|
onClick: () => props.dispatch(actions.setRpcTarget(rpc)),
|
2018-07-26 11:15:51 -07:00
|
|
|
style: {
|
|
|
|
paddingLeft: '20px',
|
|
|
|
fontSize: '16px',
|
|
|
|
},
|
2017-11-14 08:04:23 -08:00
|
|
|
},
|
|
|
|
[
|
2018-08-20 01:37:47 -07:00
|
|
|
h('.span.custom-rpc', rpc),
|
2018-08-14 07:35:55 -07:00
|
|
|
h('.remove', {
|
2018-08-06 05:47:42 -07:00
|
|
|
onClick: (event) => {
|
|
|
|
event.preventDefault()
|
|
|
|
event.stopPropagation()
|
|
|
|
this.setState({ isNetworkMenuOpen: false })
|
|
|
|
props.dispatch(actions.showDeleteRPC(rpc))
|
2018-08-06 05:55:58 -07:00
|
|
|
},
|
|
|
|
}),
|
2017-11-14 08:04:23 -08:00
|
|
|
]
|
|
|
|
)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|