aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDan Finlay <dan@danfinlay.com>2016-05-21 03:40:44 +0800
committerDan Finlay <dan@danfinlay.com>2016-05-21 03:40:44 +0800
commit7d5aaaa5bd8a0f34694eb3e8ce5ba6bbecf03d71 (patch)
tree9032a488654844f1aad0c4c0bfc892e2786c4aa2
parentb0f92e05b12fa5cde453c7b53a19f6b0bca74f75 (diff)
downloadtangerine-wallet-browser-7d5aaaa5bd8a0f34694eb3e8ce5ba6bbecf03d71.tar.gz
tangerine-wallet-browser-7d5aaaa5bd8a0f34694eb3e8ce5ba6bbecf03d71.tar.zst
tangerine-wallet-browser-7d5aaaa5bd8a0f34694eb3e8ce5ba6bbecf03d71.zip
Add ability to add account to vault
Scrolling to the bottom of the accounts page now reveals a downward-facing chevron button. Pressing this button shows loading indication, adds a new account to the identity vault, displays it in the list, and scrolls the list to the bottom of the page. Any number of accounts can be generated in this way, and the UX feels intuitive without having to overly explain how HD paths work.
-rw-r--r--app/scripts/background.js1
-rw-r--r--app/scripts/lib/idStore.js15
-rw-r--r--ui/app/accounts.js55
-rw-r--r--ui/app/actions.js15
-rw-r--r--ui/app/css/lib.css4
-rw-r--r--ui/app/reducers/app.js6
6 files changed, 89 insertions, 7 deletions
diff --git a/app/scripts/background.js b/app/scripts/background.js
index a52eab2d3..e77df1519 100644
--- a/app/scripts/background.js
+++ b/app/scripts/background.js
@@ -182,6 +182,7 @@ function setupControllerConnection(stream){
setLocked: idStore.setLocked.bind(idStore),
clearSeedWordCache: idStore.clearSeedWordCache.bind(idStore),
exportAccount: idStore.exportAccount.bind(idStore),
+ revealAccount: idStore.revealAccount.bind(idStore),
})
stream.pipe(dnode).pipe(stream)
dnode.on('remote', function(remote){
diff --git a/app/scripts/lib/idStore.js b/app/scripts/lib/idStore.js
index 6d3d0c0aa..0604c4bca 100644
--- a/app/scripts/lib/idStore.js
+++ b/app/scripts/lib/idStore.js
@@ -115,6 +115,21 @@ IdentityStore.prototype.setSelectedAddress = function(address, cb){
if (cb) return cb(null, address)
}
+IdentityStore.prototype.revealAccount = function(cb) {
+ let addresses = this._getAddresses()
+ const derivedKey = this._idmgmt.derivedKey
+ const keyStore = this._keyStore
+
+ keyStore.setDefaultHdDerivationPath(this.hdPathString)
+ keyStore.generateNewAddress(derivedKey, 1)
+ configManager.setWallet(keyStore.serialize())
+
+ addresses = this._getAddresses()
+ this._loadIdentities()
+ this._didUpdate()
+ cb(null)
+}
+
IdentityStore.prototype.getNetwork = function(tries) {
if (tries === 0) return
this.web3.version.getNetwork((err, network) => {
diff --git a/ui/app/accounts.js b/ui/app/accounts.js
index e609e7424..0f3030829 100644
--- a/ui/app/accounts.js
+++ b/ui/app/accounts.js
@@ -9,6 +9,7 @@ const EtherBalance = require('./components/eth-balance')
const valuesFor = require('./util').valuesFor
const addressSummary = require('./util').addressSummary
const formatBalance = require('./util').formatBalance
+const findDOMNode = require('react-dom').findDOMNode
module.exports = connect(mapStateToProps)(AccountsScreen)
@@ -20,6 +21,7 @@ function mapStateToProps(state) {
unconfTxs: state.metamask.unconfTxs,
selectedAddress: state.metamask.selectedAddress,
currentDomain: state.appState.currentDomain,
+ scrollToBottom: state.appState.scrollToBottom,
}
}
@@ -36,13 +38,19 @@ AccountsScreen.prototype.render = function() {
var actions = {
onSelect: this.onSelect.bind(this),
onShowDetail: this.onShowDetail.bind(this),
+ revealAccount: this.onRevealAccount.bind(this),
}
return (
- h('.accounts-section.flex-column.flex-grow', [
+ h('.accounts-section.flex-grow', [
// subtitle and nav
- h('.section-title.flex-column.flex-center', [
+ h('.section-title.flex-center', [
+ h('i.fa.fa-arrow-left.fa-lg.pointer.hover-white', {
+ onClick: (event) => {
+ state.dispatch(actions.goHome())
+ }
+ }),
h('h2.page-subtitle', 'Select Account'),
]),
@@ -51,12 +59,32 @@ AccountsScreen.prototype.render = function() {
// identity selection
h('section.identity-section.flex-column', {
style: {
+ height: '418px',
overflowY: 'auto',
overflowX: 'hidden',
}
},
- identityList.map(renderAccountPanel)
- ),
+ [
+ identityList.map(renderAccountPanel),
+
+ h('hr.horizontal-line', {key: 'horizontal-line1'}),
+ h('div.footer.hover-white.pointer', {
+ key: 'reveal-account-bar',
+ onClick:() => {
+ actions.revealAccount()
+ },
+ style: {
+ display: 'flex',
+ flex: '1 0 auto',
+ height: '40px',
+ paddint: '10px',
+ justifyContent: 'center',
+ alignItems: 'center',
+ }
+ }, [
+ h('i.fa.fa-chevron-down.fa-lg', {key: ''}),
+ ]),
+ ]),
unconfTxList.length ? (
@@ -70,10 +98,7 @@ AccountsScreen.prototype.render = function() {
) : (
null
),
-
-
])
-
)
function renderAccountPanel(identity){
@@ -90,6 +115,7 @@ AccountsScreen.prototype.render = function() {
return (
h('.accounts-list-option.flex-row.flex-space-between.cursor-pointer', {
+ key: `account-panel-${identity.address}`,
style: {
flex: '1 0 auto',
background: isSelected ? 'white' : 'none',
@@ -120,6 +146,17 @@ AccountsScreen.prototype.render = function() {
}
}
+// If a new account was revealed, scroll to the bottom
+AccountsScreen.prototype.componentDidUpdate = function(){
+ const scrollToBottom = this.props.scrollToBottom
+
+ if (scrollToBottom) {
+ var container = findDOMNode(this)
+ var scrollable = container.querySelector('.identity-section')
+ scrollable.scrollTop = scrollable.scrollHeight
+ }
+}
+
AccountsScreen.prototype.navigateToConfTx = function(){
event.stopPropagation()
this.props.dispatch(actions.showConfTxPage())
@@ -136,3 +173,7 @@ AccountsScreen.prototype.onShowDetail = function(address, event){
event.stopPropagation()
this.props.dispatch(actions.showAccountDetail(address))
}
+
+AccountsScreen.prototype.onRevealAccount = function() {
+ this.props.dispatch(actions.revealAccount())
+}
diff --git a/ui/app/actions.js b/ui/app/actions.js
index ee5e417d4..5d6f503e2 100644
--- a/ui/app/actions.js
+++ b/ui/app/actions.js
@@ -48,6 +48,8 @@ var actions = {
SHOW_ACCOUNTS_PAGE: 'SHOW_ACCOUNTS_PAGE',
SHOW_CONF_TX_PAGE: 'SHOW_CONF_TX_PAGE',
SHOW_CONF_MSG_PAGE: 'SHOW_CONF_MSG_PAGE',
+ REVEAL_ACCOUNT: 'REVEAL_ACCOUNT',
+ revealAccount: revealAccount,
// account detail screen
SHOW_SEND_PAGE: 'SHOW_SEND_PAGE',
showSendPage: showSendPage,
@@ -175,6 +177,19 @@ function setSelectedAddress(address) {
}
}
+function revealAccount() {
+ return (dispatch) => {
+ dispatch(this.showLoadingIndication())
+ _accountManager.revealAccount((err) => {
+ dispatch(this.hideLoadingIndication())
+ if (err) return dispatch(this.displayWarning(err.message))
+ dispatch({
+ type: this.REVEAL_ACCOUNT,
+ })
+ })
+ }
+}
+
function signMsg(msgData) {
return (dispatch) => {
dispatch(this.showLoadingIndication())
diff --git a/ui/app/css/lib.css b/ui/app/css/lib.css
index 1eba7465b..97ff02c46 100644
--- a/ui/app/css/lib.css
+++ b/ui/app/css/lib.css
@@ -107,6 +107,10 @@
user-select: none;
}
+.hover-white:hover {
+ background: white;
+}
+
.pointer {
cursor: pointer;
}
diff --git a/ui/app/reducers/app.js b/ui/app/reducers/app.js
index 1c0154cd5..a29a8f79c 100644
--- a/ui/app/reducers/app.js
+++ b/ui/app/reducers/app.js
@@ -191,6 +191,12 @@ function reduceApp(state, action) {
transForward: true,
isLoading: false,
warning: null,
+ scrollToBottom: false,
+ })
+
+ case actions.REVEAL_ACCOUNT:
+ return extend(appState, {
+ scrollToBottom: true,
})
case actions.SHOW_CONF_TX_PAGE: