1
0
mirror of https://github.com/kremalicious/metamask-extension.git synced 2024-12-22 17:33:23 +01:00

Merge pull request #171 from MetaMask/MoveAccountExportToSubview

Move account export into own view
This commit is contained in:
Dan Finlay 2016-05-05 12:13:12 -07:00
commit 895fa023d1
8 changed files with 158 additions and 70 deletions

View File

@ -3,6 +3,9 @@
## Current Master
- Add support for calls to `eth.sign`.
- Moved account exporting within transitioning subview on the account detail view.
- Added buttons to the account export process.
- Improved visual appearance of account detail transition where button heights would change.
## 1.7.0 2016-04-29

View File

@ -1,11 +1,15 @@
const inherits = require('util').inherits
const extend = require('xtend')
const Component = require('react').Component
const h = require('react-hyperscript')
const connect = require('react-redux').connect
const copyToClipboard = require('copy-to-clipboard')
const actions = require('./actions')
const ReactCSSTransitionGroup = require('react-addons-css-transition-group')
const AccountPanel = require('./components/account-panel')
const transactionList = require('./components/transaction-list')
const ExportAccountView = require('./components/account-export')
module.exports = connect(mapStateToProps)(AccountDetailScreen)
@ -35,7 +39,11 @@ AccountDetailScreen.prototype.render = function() {
return (
h('.account-detail-section.flex-column.flex-grow', [
h('.account-detail-section.flex-column.flex-grow', {
style: {
width: '330px',
},
}, [
// subtitle and nav
h('.section-title.flex-row.flex-center', [
@ -78,12 +86,13 @@ AccountDetailScreen.prototype.render = function() {
}, 'EXPORT'),
]),
transactionList(transactions
.filter(tx => tx.txParams.from === state.address)
.filter(tx => tx.txParams.metamaskNetworkId === state.networkVersion)
.sort((a, b) => b.time - a.time), state.networkVersion),
this.exportedAccount(accountDetail),
h(ReactCSSTransitionGroup, {
transitionName: "main",
transitionEnterTimeout: 300,
transitionLeaveTimeout: 300,
}, [
this.subview(),
]),
// transaction table
/*
h('section.flex-column', [
@ -94,72 +103,41 @@ AccountDetailScreen.prototype.render = function() {
)
}
AccountDetailScreen.prototype.subview = function() {
var subview
try {
subview = this.props.accountDetail.subview
} catch (e) {
subview = null
}
switch (subview) {
case 'transactions':
return this.transactionList()
case 'export':
var state = extend({key: 'export'}, this.props)
return h(ExportAccountView, state)
default:
return this.transactionList()
}
}
AccountDetailScreen.prototype.transactionList = function() {
var state = this.props
var transactions = state.transactions
return transactionList(transactions
.filter(tx => tx.txParams.from === state.address)
.filter(tx => tx.txParams.metamaskNetworkId === state.networkVersion)
.sort((a, b) => b.time - a.time), state.networkVersion)
}
AccountDetailScreen.prototype.navigateToAccounts = function(event){
event.stopPropagation()
this.props.dispatch(actions.showAccountsPage())
}
AccountDetailScreen.prototype.exportAccount = function(address) {
this.props.dispatch(actions.exportAccount(address))
}
AccountDetailScreen.prototype.requestAccountExport = function() {
this.props.dispatch(actions.requestExportAccount())
}
AccountDetailScreen.prototype.exportedAccount = function(accountDetail) {
if (!accountDetail) return
var accountExport = accountDetail.accountExport
var notExporting = accountExport === 'none'
var exportRequested = accountExport === 'requested'
var accountExported = accountExport === 'completed'
if (notExporting) return
if (exportRequested) {
var warning = `Exporting your private key is very dangerous,
and you should only do it if you know what you're doing.`
var confirmation = `If you're absolutely sure, type "I understand" below and
hit Enter.`
return h('div', {}, [
h('p.error', warning),
h('p', confirmation),
h('input#exportAccount', {
onKeyPress: this.onExportKeyPress.bind(this),
})
])
}
if (accountExported) {
return h('div.privateKey', {
}, [
h('label', 'Your private key (click to copy):'),
h('p.error.cursor-pointer', {
style: {
textOverflow: 'ellipsis',
overflow: 'hidden',
webkitUserSelect: 'text',
width: '100%',
},
onClick: function(event) {
copyToClipboard(accountDetail.privateKey)
}
}, accountDetail.privateKey),
])
}
}
AccountDetailScreen.prototype.onExportKeyPress = function(event) {
if (event.key !== 'Enter') return
event.preventDefault()
var input = document.getElementById('exportAccount')
if (input.value === 'I understand') {
this.props.dispatch(actions.exportAccount(this.props.address))
} else {
input.value = ''
input.placeholder = 'Please retype "I understand" exactly.'
}
}

View File

@ -108,7 +108,6 @@ function tryUnlockMetamask(password) {
return (dispatch) => {
dispatch(this.unlockInProgress())
_accountManager.submitPassword(password, (err, selectedAccount) => {
dispatch(this.hideLoadingIndication())
if (err) {
dispatch(this.unlockFailed())
} else {

View File

@ -65,7 +65,7 @@ App.prototype.render = function() {
h('.flex-column.flex-grow.full-height', {
style: {
// Windows was showing a vertical scroll bar:
overflowY: 'hidden',
overflow: 'hidden',
}
},
[
@ -82,6 +82,7 @@ App.prototype.render = function() {
h('.app-primary.flex-grow' + (transForward ? '.from-right' : '.from-left'), {
style: {
height: '380px',
width: '360px',
}
}, [
h(ReactCSSTransitionGroup, {

View File

@ -0,0 +1,87 @@
const Component = require('react').Component
const h = require('react-hyperscript')
const inherits = require('util').inherits
const actions = require('../actions')
module.exports = ExportAccountView
inherits(ExportAccountView, Component)
function ExportAccountView() {
Component.call(this)
}
ExportAccountView.prototype.render = function() {
console.log("EXPORT VIEW")
console.dir(this.props)
var state = this.props
var accountDetail = state.accountDetail
if (!accountDetail) return h('div')
var accountExport = accountDetail.accountExport
var notExporting = accountExport === 'none'
var exportRequested = accountExport === 'requested'
var accountExported = accountExport === 'completed'
if (notExporting) return h('div')
if (exportRequested) {
var warning = `Exporting your private key is very dangerous,
and you should only do it if you know what you're doing.`
var confirmation = `If you're absolutely sure, type "I understand" below and
submit.`
return h('div', { key: 'exporting' }, [
h('p.error', warning),
h('p', confirmation),
h('input#exportAccount', {
onKeyPress: this.onExportKeyPress.bind(this),
}),
h('button', {
onClick: () => this.onExportKeyPress({ key: 'Enter', preventDefault: () => {} }),
}, 'Submit'),
h('button', {
onClick: () => this.props.dispatch(actions.backToAccountDetail(this.props.address))
}, 'Cancel'),
])
}
if (accountExported) {
return h('div.privateKey', {
}, [
h('label', 'Your private key (click to copy):'),
h('p.error.cursor-pointer', {
style: {
textOverflow: 'ellipsis',
overflow: 'hidden',
webkitUserSelect: 'text',
width: '100%',
},
onClick: function(event) {
copyToClipboard(accountDetail.privateKey)
}
}, accountDetail.privateKey),
h('button', {
onClick: () => this.props.dispatch(actions.backToAccountDetail(this.props.address))
}, 'Done'),
])
}
}
ExportAccountView.prototype.onExportKeyPress = function(event) {
if (event.key !== 'Enter') return
event.preventDefault()
var input = document.getElementById('exportAccount')
if (input.value === 'I understand') {
this.props.dispatch(actions.exportAccount(this.props.address))
} else {
input.value = ''
input.placeholder = 'Please retype "I understand" exactly.'
}
}
ExportAccountView.prototype.exportAccount = function(address) {
this.props.dispatch(actions.exportAccount(address))
}

View File

@ -4,7 +4,7 @@ const addressSummary = require('../util').addressSummary
const explorerLink = require('../../lib/explorer-link')
module.exports = function(transactions, network) {
return h('details', [
return h('details', { key: 'transaction-list' }, [
h('summary', [
h('div.font-small', {style: {display: 'inline'}}, 'Transactions'),

View File

@ -19,6 +19,7 @@
position: absolute;
width: 100%;
transition: transform 300ms ease-in-out;
overflow-x: hidden;
}
/* final positions */

View File

@ -23,6 +23,9 @@ function reduceApp(state, action) {
var appState = extend({
currentView: seedWords ? seedConfView : defaultView,
accountDetail: {
subview: 'transactions',
},
currentDomain: 'example.com',
transForward: true, // Used to render transition direction
isLoading: false, // Used to display loading indicator
@ -109,7 +112,9 @@ function reduceApp(state, action) {
case actions.UNLOCK_METAMASK:
return extend(appState, {
currentView: {},
detailView: {},
transForward: true,
isLoading: false,
warning: null,
})
@ -131,6 +136,7 @@ function reduceApp(state, action) {
return extend(appState, {
currentView: {},
accountDetail: {
subview: 'transactions',
accountExport: 'none',
privateKey: '',
},
@ -144,6 +150,7 @@ function reduceApp(state, action) {
context: action.value || account,
},
accountDetail: {
subview: 'transactions',
accountExport: 'none',
privateKey: '',
},
@ -157,6 +164,7 @@ function reduceApp(state, action) {
context: action.value,
},
accountDetail: {
subview: 'transactions',
accountExport: 'none',
privateKey: '',
},
@ -218,6 +226,9 @@ function reduceApp(state, action) {
name: 'accountDetail',
context: state.metamask.selectedAddress,
},
accountDetail: {
subview: 'transactions',
},
})
}
@ -285,7 +296,13 @@ function reduceApp(state, action) {
case actions.REQUEST_ACCOUNT_EXPORT:
return extend(appState, {
transForward: true,
currentView: {
name: 'accountDetail',
context: appState.currentView.context,
},
accountDetail: {
subview: 'export',
accountExport: 'requested',
},
})
@ -293,6 +310,7 @@ function reduceApp(state, action) {
case actions.EXPORT_ACCOUNT:
return extend(appState, {
accountDetail: {
subview: 'export',
accountExport: 'completed',
},
})
@ -300,6 +318,7 @@ function reduceApp(state, action) {
case actions.SHOW_PRIVATE_KEY:
return extend(appState, {
accountDetail: {
subview: 'export',
accountExport: 'completed',
privateKey: action.value,
},