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

Merge branch 'NewUI' into feat/mm-ui-5-merged

This commit is contained in:
sdtsui 2017-08-06 20:24:04 -07:00
commit 5c7adc911d
18 changed files with 334 additions and 91 deletions

View File

@ -2,8 +2,9 @@
## Current Master
- Replace account scren with an account drop-down menu.
- Replace confusing buttons with an new account-specific drop-down menu.
- Replace account screen with an account drop-down menu.
- Replace confusing buttons with a new account-specific drop-down menu.
## 3.9.5 2017-8-04
- Improved phishing detection configuration update rate
@ -88,7 +89,7 @@
## 3.7.8 2017-6-12
- Add a `ethereum:` prefix to the QR code address
- Add an `ethereum:` prefix to the QR code address
- The default network on installation is now MainNet
- Fix currency API URL from cryptonator.
- Update gasLimit params with every new block seen.
@ -244,7 +245,7 @@
- Add ability to import accounts in JSON file format (used by Mist, Geth, MyEtherWallet, and more!)
- Fix unapproved messages not being included in extension badge.
- Fix rendering bug where the Confirm transaction view would lets you approve transactions when the account has insufficient balance.
- Fix rendering bug where the Confirm transaction view would let you approve transactions when the account has insufficient balance.
## 3.1.2 2017-1-24
@ -267,8 +268,8 @@
## 3.0.0 2017-1-16
- Fix seed word account generation (https://medium.com/metamask/metamask-3-migration-guide-914b79533cdd#.t4i1qmmsz).
- Fix Bug where you see a empty transaction flash by on the confirm transaction view.
- Create visible difference in transaction history between a approved but not yet included in a block transaction and a transaction who has been confirmed.
- Fix Bug where you see an empty transaction flash by on the confirm transaction view.
- Create visible difference in transaction history between an approved but not yet included in a block transaction and a transaction who has been confirmed.
- Fix memory leak in RPC Cache
- Override RPC commands eth_syncing and web3_clientVersion
- Remove certain non-essential permissions from certain builds.
@ -323,7 +324,7 @@
- Fix bug where gas estimate would sometimes be very high.
- Increased our gas estimate from 100k gas to 20% of estimate.
- Fix github link on info page to point at current repository.
- Fix GitHub link on info page to point at current repository.
## 2.13.6 2016-10-26
@ -399,7 +400,7 @@ popup notification opens up.
- Block negative values from transactions.
- Fixed a memory leak.
- MetaMask logo now renders as super lightweight SVG, improving compatibility and performance.
- Now showing loading indication during vault unlocking, to clarify behavior for users who are experience slow unlocks.
- Now showing loading indication during vault unlocking, to clarify behavior for users who are experiencing slow unlocks.
- Now only initially creates one wallet when restoring a vault, to reduce some users' confusion.
## 2.10.2 2016-09-02

View File

@ -93,7 +93,6 @@
"inject-css": "^0.1.1",
"jazzicon": "^1.2.0",
"loglevel": "^1.4.1",
"menu-droppo": "2.0.1",
"metamask-logo": "^2.1.2",
"mississippi": "^1.2.0",
"mkdirp": "^0.5.1",
@ -112,7 +111,6 @@
"qrcode-npm": "0.0.3",
"react": "^15.0.2",
"react-addons-css-transition-group": "^15.6.0",
"react-burger-menu": "^2.1.4",
"react-dom": "^15.5.4",
"react-hyperscript": "^2.2.2",
"react-markdown": "^2.3.0",

View File

@ -1,23 +1,19 @@
var fs = require('fs')
var path = require('path')
var browserify = require('browserify')
var tests = fs.readdirSync(path.join(__dirname, 'lib'))
var bundlePath = path.join(__dirname, 'bundle.js')
const fs = require('fs')
const path = require('path')
const browserify = require('browserify')
const tests = fs.readdirSync(path.join(__dirname, 'lib'))
const bundlePath = path.join(__dirname, 'bundle.js')
var b = browserify()
const b = browserify()
// Remove old bundle
try {
fs.unlinkSync(bundlePath)
const writeStream = fs.createWriteStream(bundlePath)
var writeStream = fs.createWriteStream(bundlePath)
tests.forEach(function (fileName) {
tests.forEach(function (fileName) {
b.add(path.join(__dirname, 'lib', fileName))
})
b.bundle().pipe(writeStream)
} catch (e) {
console.error('Integration build failure', e)
}
})
b.bundle()
.pipe(writeStream)
.on('error', (err) => {
throw err
})

View File

@ -90,7 +90,13 @@ QUnit.test('render init screen', function (assert) {
return wait()
}).then(function (){
var qrButton = app.find('.fa.fa-qrcode')[0]
var qrButton = app.find('.fa.fa-ellipsis-h')[0] // open account settings dropdown
qrButton.click()
return wait(1000)
}).then(function (){
var qrButton = app.find('.dropdown-menu-item')[1] // qr code item
qrButton.click()
return wait(1000)

View File

@ -128,6 +128,7 @@ AccountDetailScreen.prototype.render = function () {
selected,
network,
identities: props.identities,
enableAccountOptions: true,
},
),
]
@ -152,7 +153,6 @@ AccountDetailScreen.prototype.render = function () {
fontSize: '13px',
fontFamily: 'Montserrat Light',
textRendering: 'geometricPrecision',
marginTop: '10px',
marginBottom: '15px',
color: '#AEAEAE',
},

View File

@ -18,7 +18,6 @@ const generateLostAccountsNotice = require('../lib/lost-accounts-notice')
// slideout menu
const WalletView = require('./components/wallet-view')
const SlideoutMenu = require('react-burger-menu').slide
// other views
const ConfigScreen = require('./config')
@ -36,6 +35,7 @@ const HDCreateVaultComplete = require('./keychains/hd/create-vault-complete')
const HDRestoreVaultScreen = require('./keychains/hd/restore-vault')
const RevealSeedConfirmation = require('./keychains/hd/recover-seed/confirmation')
const ReactCSSTransitionGroup = require('react-addons-css-transition-group')
const AccountDropdowns = require('./components/account-dropdowns').AccountDropdowns
module.exports = connect(mapStateToProps, mapDispatchToProps)(App)
@ -43,6 +43,13 @@ inherits(App, Component)
function App () { Component.call(this) }
function mapStateToProps (state) {
const {
identities,
accounts,
address,
} = state.metamask
const selected = address || Object.keys(accounts)[0]
return {
// state from plugin
sidebarOpen: state.appState.sidebarOpen,
@ -64,6 +71,10 @@ function mapStateToProps (state) {
lastUnreadNotice: state.metamask.lastUnreadNotice,
lostAccounts: state.metamask.lostAccounts,
frequentRpcList: state.metamask.frequentRpcList || [],
// state needed to get account dropdown temporarily rendering from app bar
identities,
selected,
}
}
@ -233,6 +244,7 @@ App.prototype.renderNetworkDropdown = function () {
const isOpen = state.isNetworkMenuOpen
return h(Dropdown, {
useCssTransition: true,
isOpen,
onClickOutside: (event) => {
const { classList } = event.target
@ -240,7 +252,7 @@ App.prototype.renderNetworkDropdown = function () {
classList.contains('menu-icon'),
classList.contains('network-name'),
classList.contains('network-indicator'),
].filter(bool => bool).length === 0;
].filter(bool => bool).length === 0
// classes from three constituent nodes of the toggle element
if (isNotToggleElement) {
@ -264,6 +276,9 @@ App.prototype.renderNetworkDropdown = function () {
key: 'main',
closeMenu: () => this.setState({ isNetworkMenuOpen: !isOpen }),
onClick: () => props.dispatch(actions.setProviderType('mainnet')),
style: {
fontSize: '18px',
},
},
[
h('.menu-icon.diamond'),
@ -278,6 +293,9 @@ App.prototype.renderNetworkDropdown = function () {
key: 'ropsten',
closeMenu: () => this.setState({ isNetworkMenuOpen: !isOpen }),
onClick: () => props.dispatch(actions.setProviderType('ropsten')),
style: {
fontSize: '18px',
},
},
[
h('.menu-icon.red-dot'),
@ -292,6 +310,9 @@ App.prototype.renderNetworkDropdown = function () {
key: 'kovan',
closeMenu: () => this.setState({ isNetworkMenuOpen: !isOpen }),
onClick: () => props.dispatch(actions.setProviderType('kovan')),
style: {
fontSize: '18px',
},
},
[
h('.menu-icon.hollow-diamond'),
@ -306,6 +327,9 @@ App.prototype.renderNetworkDropdown = function () {
key: 'rinkeby',
closeMenu: () => this.setState({ isNetworkMenuOpen: !isOpen }),
onClick: () => props.dispatch(actions.setProviderType('rinkeby')),
style: {
fontSize: '18px',
},
},
[
h('.menu-icon.golden-square'),
@ -320,6 +344,9 @@ App.prototype.renderNetworkDropdown = function () {
key: 'default',
closeMenu: () => this.setState({ isNetworkMenuOpen: !isOpen }),
onClick: () => props.dispatch(actions.setDefaultRpcTarget()),
style: {
fontSize: '18px',
},
},
[
h('i.fa.fa-question-circle.fa-lg.menu-icon'),
@ -336,6 +363,9 @@ App.prototype.renderNetworkDropdown = function () {
{
closeMenu: () => this.setState({ isNetworkMenuOpen: !isOpen }),
onClick: () => this.props.dispatch(actions.showConfigPage()),
style: {
fontSize: '18px',
},
},
[
h('i.fa.fa-question-circle.fa-lg.menu-icon'),
@ -352,12 +382,17 @@ App.prototype.renderDropdown = function () {
const isOpen = state.isMainMenuOpen
return h(Dropdown, {
useCssTransition: true,
isOpen: isOpen,
zIndex: 11,
onClickOutside: (event) => {
const { classList } = event.target
const isNotToggleElement = !classList.contains('sandwich-expando')
if (isNotToggleElement) {
const classList = event.target.classList
const parentClassList = event.target.parentElement.classList
const isToggleElement = classList.contains('sandwich-expando') ||
parentClassList.contains('sandwich-expando')
if (isOpen && !isToggleElement) {
this.setState({ isMainMenuOpen: false })
}
},
@ -610,7 +645,6 @@ App.prototype.renderCommonRpc = function (rpcList, provider) {
if ((rpc === 'http://localhost:8545') || (rpc === rpcTarget)) {
return null
} else {
return h(
DropdownMenuItem,
{

View File

@ -17,14 +17,14 @@ class AccountDropdowns extends Component {
accountSelectorActive: false,
optionsMenuActive: false,
}
this.accountSelectorToggleClassName = 'fa-angle-down';
this.optionsMenuToggleClassName = 'fa-ellipsis-h';
this.accountSelectorToggleClassName = 'accounts-selector'
this.optionsMenuToggleClassName = 'fa-ellipsis-h'
}
renderAccounts () {
const { identities, selected } = this.props
return Object.keys(identities).map((key) => {
return Object.keys(identities).map((key, index) => {
const identity = identities[key]
const isSelected = identity.address === selected
@ -35,17 +35,24 @@ class AccountDropdowns extends Component {
onClick: () => {
this.props.actions.showAccountDetail(identity.address)
},
style: {
marginTop: index === 0 ? '5px' : '',
fontSize: '24px',
},
},
[
h(
Identicon,
{
address: identity.address,
diameter: 16,
diameter: 32,
style: {
marginLeft: '10px',
},
},
),
h('span', { style: { marginLeft: '10px' } }, identity.name || ''),
h('span', { style: { marginLeft: '10px' } }, isSelected ? h('.check', '✓') : null),
h('span', { style: { marginLeft: '20px', fontSize: '24px' } }, identity.name || ''),
h('span', { style: { marginLeft: '20px', fontSize: '24px' } }, isSelected ? h('.check', '✓') : null),
]
)
})
@ -58,11 +65,17 @@ class AccountDropdowns extends Component {
return h(
Dropdown,
{
useCssTransition: true, // Hardcoded because account selector is temporarily in app-header
style: {
marginLeft: '-125px',
marginLeft: '-238px',
marginTop: '38px',
minWidth: '180px',
overflowY: 'auto',
maxHeight: '300px',
width: '300px',
},
innerStyle: {
padding: '8px 25px',
},
isOpen: accountSelectorActive,
onClickOutside: (event) => {
@ -85,10 +98,13 @@ class AccountDropdowns extends Component {
h(
Identicon,
{
diameter: 16,
style: {
marginLeft: '10px',
},
diameter: 32,
},
),
h('span', { style: { marginLeft: '10px' } }, 'Create Account'),
h('span', { style: { marginLeft: '20px', fontSize: '24px' } }, 'Create Account'),
],
),
h(
@ -101,10 +117,19 @@ class AccountDropdowns extends Component {
h(
Identicon,
{
diameter: 16,
style: {
marginLeft: '10px',
},
diameter: 32,
},
),
h('span', { style: { marginLeft: '10px' } }, 'Import Account'),
h('span', {
style: {
marginLeft: '20px',
fontSize: '24px',
marginBottom: '5px',
},
}, 'Import Account'),
]
),
]
@ -119,7 +144,7 @@ class AccountDropdowns extends Component {
Dropdown,
{
style: {
marginLeft: '-162px',
marginLeft: '-215px',
minWidth: '180px',
},
isOpen: optionsMenuActive,
@ -144,6 +169,18 @@ class AccountDropdowns extends Component {
},
'View account on Etherscan',
),
h(
DropdownMenuItem,
{
closeMenu: () => {},
onClick: () => {
const { selected, identities } = this.props
var identity = identities[selected]
actions.showQrView(selected, identity ? identity.name : '')
},
},
'Show QR Code',
),
h(
DropdownMenuItem,
{
@ -171,7 +208,7 @@ class AccountDropdowns extends Component {
}
render () {
const { style } = this.props
const { style, enableAccountsSelector, enableAccountOptions } = this.props
const { optionsMenuActive, accountSelectorActive } = this.state
return h(
@ -180,10 +217,18 @@ class AccountDropdowns extends Component {
style: style,
},
[
h(
'i.fa.fa-angle-down',
enableAccountsSelector && h(
// 'i.fa.fa-angle-down',
'div.cursor-pointer.color-orange.accounts-selector',
{
style: {},
style: {
// fontSize: '1.8em',
background: 'url(images/switch_acc.svg) white center center no-repeat',
height: '25px',
width: '25px',
transform: 'scale(0.75)',
marginRight: '3px',
},
onClick: (event) => {
event.stopPropagation()
this.setState({
@ -194,10 +239,13 @@ class AccountDropdowns extends Component {
},
this.renderAccountSelector(),
),
h(
enableAccountOptions && h(
'i.fa.fa-ellipsis-h',
{
style: { 'marginLeft': '10px'},
style: {
marginRight: '0.5em',
fontSize: '1.8em',
},
onClick: (event) => {
event.stopPropagation()
this.setState({
@ -213,6 +261,11 @@ class AccountDropdowns extends Component {
}
}
AccountDropdowns.defaultProps = {
enableAccountsSelector: false,
enableAccountOptions: false,
}
AccountDropdowns.propTypes = {
identities: PropTypes.objectOf(PropTypes.object),
selected: PropTypes.string,
@ -226,6 +279,7 @@ const mapDispatchToProps = (dispatch) => {
showAccountDetail: (address) => dispatch(actions.showAccountDetail(address)),
addNewAccount: () => dispatch(actions.addNewAccount()),
showImportPage: () => dispatch(actions.showImportPage()),
showQrView: (selected, identity) => dispatch(actions.showQrView(selected, identity)),
},
}
}

View File

@ -100,7 +100,7 @@ ExportAccountView.prototype.render = function () {
textOverflow: 'ellipsis',
overflow: 'hidden',
webkitUserSelect: 'text',
width: '100%',
maxWidth: '275px',
},
onClick: function (event) {
copyToClipboard(ethUtil.stripHexPrefix(accountDetail.privateKey))

View File

@ -1,14 +1,14 @@
const Component = require('react').Component
const PropTypes = require('react').PropTypes
const h = require('react-hyperscript')
const MenuDroppo = require('menu-droppo')
const MenuDroppo = require('./menu-droppo')
const extend = require('xtend')
const noop = () => {}
class Dropdown extends Component {
render () {
const { isOpen, onClickOutside, style, innerStyle, children } = this.props
const { isOpen, onClickOutside, style, innerStyle, children, useCssTransition } = this.props
const innerStyleDefaults = extend({
borderRadius: '4px',
@ -20,6 +20,7 @@ class Dropdown extends Component {
return h(
MenuDroppo,
{
useCssTransition,
isOpen,
zIndex: 11,
onClickOutside,
@ -43,6 +44,7 @@ class Dropdown extends Component {
Dropdown.defaultProps = {
isOpen: false,
onClick: noop,
useCssTransition: false,
}
Dropdown.propTypes = {
@ -54,7 +56,7 @@ Dropdown.propTypes = {
class DropdownMenuItem extends Component {
render () {
const { onClick, closeMenu, children } = this.props
const { onClick, closeMenu, children, style } = this.props
return h(
'li.dropdown-menu-item',
@ -63,17 +65,17 @@ class DropdownMenuItem extends Component {
onClick()
closeMenu()
},
style: {
style: Object.assign({
listStyle: 'none',
padding: '8px 0px 8px 0px',
fontSize: '12px',
fontSize: '18px',
fontStyle: 'normal',
fontFamily: 'Montserrat Regular',
cursor: 'pointer',
display: 'flex',
justifyContent: 'flex-start',
alignItems: 'center',
},
}, style),
},
children
)

View File

@ -0,0 +1,130 @@
const Component = require('react').Component
const h = require('react-hyperscript')
const inherits = require('util').inherits
const findDOMNode = require('react-dom').findDOMNode
const ReactCSSTransitionGroup = require('react-addons-css-transition-group')
module.exports = MenuDroppoComponent
inherits(MenuDroppoComponent, Component)
function MenuDroppoComponent () {
Component.call(this)
}
MenuDroppoComponent.prototype.render = function () {
const speed = this.props.speed || '300ms'
const useCssTransition = this.props.useCssTransition
const zIndex = ('zIndex' in this.props) ? this.props.zIndex : 0
this.manageListeners()
let style = this.props.style || {}
if (!('position' in style)) {
style.position = 'fixed'
}
style.zIndex = zIndex
return (
h('.menu-droppo-container', {
style,
}, [
h('style', `
.menu-droppo-enter {
transition: transform ${speed} ease-in-out;
transform: translateY(-200%);
}
.menu-droppo-enter.menu-droppo-enter-active {
transition: transform ${speed} ease-in-out;
transform: translateY(0%);
}
.menu-droppo-leave {
transition: transform ${speed} ease-in-out;
transform: translateY(0%);
}
.menu-droppo-leave.menu-droppo-leave-active {
transition: transform ${speed} ease-in-out;
transform: translateY(-200%);
}
`),
useCssTransition
? h(ReactCSSTransitionGroup, {
className: 'css-transition-group',
transitionName: 'menu-droppo',
transitionEnterTimeout: parseInt(speed),
transitionLeaveTimeout: parseInt(speed),
}, this.renderPrimary())
: this.renderPrimary(),
])
)
}
MenuDroppoComponent.prototype.renderPrimary = function () {
const isOpen = this.props.isOpen
if (!isOpen) {
return null
}
const innerStyle = this.props.innerStyle || {}
return (
h('.menu-droppo', {
key: 'menu-droppo-drawer',
style: innerStyle,
},
[ this.props.children ])
)
}
MenuDroppoComponent.prototype.manageListeners = function () {
const isOpen = this.props.isOpen
const onClickOutside = this.props.onClickOutside
if (isOpen) {
this.outsideClickHandler = onClickOutside
} else if (isOpen) {
this.outsideClickHandler = null
}
}
MenuDroppoComponent.prototype.componentDidMount = function () {
if (this && document.body) {
this.globalClickHandler = this.globalClickOccurred.bind(this)
document.body.addEventListener('click', this.globalClickHandler)
var container = findDOMNode(this)
this.container = container
}
}
MenuDroppoComponent.prototype.componentWillUnmount = function () {
if (this && document.body) {
document.body.removeEventListener('click', this.globalClickHandler)
}
}
MenuDroppoComponent.prototype.globalClickOccurred = function (event) {
const target = event.target
const container = findDOMNode(this)
if (target !== container &&
!isDescendant(this.container, event.target) &&
this.outsideClickHandler) {
this.outsideClickHandler(event)
}
}
function isDescendant (parent, child) {
var node = child.parentNode
while (node !== null) {
if (node === parent) {
return true
}
node = node.parentNode
}
return false
}

View File

@ -19,7 +19,11 @@ Notice.prototype.render = function () {
const disabled = state.disclaimerDisabled
return (
h('.flex-column.flex-center.flex-grow', [
h('.flex-column.flex-center.flex-grow', {
style: {
width: '100%',
},
}, [
h('h3.flex-center.text-transform-uppercase.terms-header', {
style: {
background: '#EBEBEB',

View File

@ -4,7 +4,6 @@ const h = require('react-hyperscript')
const inherits = require('util').inherits
const actions = require('../actions')
// slideout menu
const SlideoutMenu = require('react-burger-menu').slide
const WalletView = require('./wallet-view')
const Identicon = require('./identicon')

View File

@ -2,7 +2,6 @@
display: flex;
align-items: center;
font-size: 0.6em;
}
.network-name {

View File

@ -7,24 +7,6 @@ App Sections
debug / dev
*/
// #app-content {
// border: 2px solid green;
// }
// #design-container {
// position: absolute;
// left: 360px;
// top: -42px;
// width: calc(100vw - 360px);
// height: 100vh;
// overflow: scroll;
// }
// #design-container img {
// width: 2000px;
// margin-right: 600px;
// }
/* initialize */
textarea.twelve-word-phrase {

View File

@ -261,10 +261,11 @@ hr.horizontal-line {
.menu-icon {
display: inline-block;
height: 9px;
min-width: 9px;
height: 12px;
min-width: 12px;
margin: 13px;
}
.ether-icon {
background: rgb(0, 163, 68);
border-radius: 20px;
@ -294,7 +295,6 @@ hr.horizontal-line {
color: red;
}
/*
Misc
*/

View File

@ -51,3 +51,38 @@
.app-primary.from-left .main-enter:not(.main-enter-active) {
transform: translateX(-360px);
}
i.fa.fa-question-circle.fa-lg.menu-icon {
font-size: 18px;
}
/*
Hacky breakpoint fix for account + tab sections
Resolves issue from @frankiebee in
https://github.com/MetaMask/metamask-extension/pull/1835
Please remove this when integrating new designs
*/
// This is commented out, because it's not needed in NewUI.
// We will have a new css architecture w/ different breakpoints.
// @media screen and (min-width: 575px) and (max-width: 800px) {
// .account-data-subsection {
// flex: 0 0 auto !important; // reset flex
// margin-left: 10px !important; // create additional horizontal space
// margin-right: 10px !important;
// width: 40%;
// }
// .tabSection {
// flex: 0 0 auto !important;
// margin-left: 10px !important;
// margin-right: 10px !important;
// min-width: 285px;
// width: 49%;
// }
// .name-label {
// width: 80%;
// }
// }

View File

@ -3,7 +3,6 @@ const h = require('react-hyperscript')
const inherits = require('util').inherits
const TxView = require('./components/tx-view')
const WalletView = require('./components/wallet-view')
const SlideoutMenu = require('react-burger-menu').slide
const AccountAndTransactionDetails = require('./account-and-transaction-details')
const HDRestoreVaultScreen = require('./keychains/hd/restore-vault')
const ConfigScreen = require('./config')

View File

@ -26,7 +26,11 @@ UnlockScreen.prototype.render = function () {
const state = this.props
const warning = state.warning
return (
h('.flex-column', [
h('.flex-column', {
style: {
width: 'inherit',
},
}, [
h('.unlock-screen.flex-column.flex-center.flex-grow', [
h(Mascot, {