mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-12-23 01:39:44 +01:00
Adds sidebar component and refactors slide in wallet view sidebar to use it.
This commit is contained in:
parent
4560df6e73
commit
40e0d92f57
@ -123,6 +123,7 @@
|
||||
"modalState": {},
|
||||
"previousModalState": {}
|
||||
},
|
||||
"sidebar": {},
|
||||
"transForward": true,
|
||||
"isLoading": false,
|
||||
"warning": null,
|
||||
|
@ -141,6 +141,7 @@
|
||||
"accountDetail": {
|
||||
"subview": "transactions"
|
||||
},
|
||||
"sidebar": {},
|
||||
"modal": {
|
||||
"modalState": {},
|
||||
"previousModalState": {}
|
||||
|
@ -162,6 +162,7 @@
|
||||
"accountDetail": {
|
||||
"subview": "transactions"
|
||||
},
|
||||
"sidebar": {},
|
||||
"modal": {
|
||||
"modalState": {},
|
||||
"previousModalState": {}
|
||||
|
@ -120,6 +120,7 @@
|
||||
"accountDetail": {
|
||||
"subview": "transactions"
|
||||
},
|
||||
"sidebar": {},
|
||||
"modal": {
|
||||
"modalState": {},
|
||||
"previousModalState": {}
|
||||
|
@ -48,6 +48,7 @@
|
||||
"accountDetail": {
|
||||
"subview": "transactions"
|
||||
},
|
||||
"sidebar": {},
|
||||
"transForward": true,
|
||||
"isLoading": false,
|
||||
"warning": null,
|
||||
|
@ -141,6 +141,7 @@
|
||||
"accountDetail": {
|
||||
"subview": "transactions"
|
||||
},
|
||||
"sidebar": {},
|
||||
"modal": {
|
||||
"modalState": {},
|
||||
"previousModalState": {}
|
||||
|
@ -120,6 +120,7 @@
|
||||
"accountDetail": {
|
||||
"subview": "transactions"
|
||||
},
|
||||
"sidebar": {},
|
||||
"modal": {
|
||||
"modalState": {},
|
||||
"previousModalState": {}
|
||||
|
@ -99,6 +99,7 @@
|
||||
"accountExport": "none",
|
||||
"privateKey": ""
|
||||
},
|
||||
"sidebar": {},
|
||||
"transForward": true,
|
||||
"isLoading": false,
|
||||
"warning": null,
|
||||
|
@ -118,6 +118,7 @@
|
||||
"modalState": {},
|
||||
"previousModalState": {}
|
||||
},
|
||||
"sidebar": {},
|
||||
"transForward": true,
|
||||
"isLoading": false,
|
||||
"warning": null,
|
||||
|
23
package-lock.json
generated
23
package-lock.json
generated
@ -16169,6 +16169,14 @@
|
||||
"resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
|
||||
"integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus="
|
||||
},
|
||||
"json2mq": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/json2mq/-/json2mq-0.2.0.tgz",
|
||||
"integrity": "sha1-tje9O6nqvhIsg+lyBIOusQ0skEo=",
|
||||
"requires": {
|
||||
"string-convert": "^0.2.0"
|
||||
}
|
||||
},
|
||||
"json3": {
|
||||
"version": "3.3.2",
|
||||
"resolved": "https://registry.npmjs.org/json3/-/json3-3.3.2.tgz",
|
||||
@ -25028,6 +25036,16 @@
|
||||
"xtend": "^4.0.1"
|
||||
}
|
||||
},
|
||||
"react-media": {
|
||||
"version": "1.8.0",
|
||||
"resolved": "https://registry.npmjs.org/react-media/-/react-media-1.8.0.tgz",
|
||||
"integrity": "sha512-XcfqkDQj5/hmJod/kXUAZljJyMVkWrBWOkzwynAR8BXOGlbFLGBwezM0jQHtp2BrSymhf14/XrQrb3gGBnGK4g==",
|
||||
"requires": {
|
||||
"invariant": "^2.2.2",
|
||||
"json2mq": "^0.2.0",
|
||||
"prop-types": "^15.5.10"
|
||||
}
|
||||
},
|
||||
"react-modal": {
|
||||
"version": "3.4.4",
|
||||
"resolved": "https://registry.npmjs.org/react-modal/-/react-modal-3.4.4.tgz",
|
||||
@ -27885,6 +27903,11 @@
|
||||
"resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz",
|
||||
"integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM="
|
||||
},
|
||||
"string-convert": {
|
||||
"version": "0.2.1",
|
||||
"resolved": "https://registry.npmjs.org/string-convert/-/string-convert-0.2.1.tgz",
|
||||
"integrity": "sha1-aYLMMEn7tM2F+LJFaLnZvznu/5c="
|
||||
},
|
||||
"string-length": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/string-length/-/string-length-1.0.1.tgz",
|
||||
|
@ -1849,9 +1849,13 @@ function hideModal (payload) {
|
||||
}
|
||||
}
|
||||
|
||||
function showSidebar () {
|
||||
function showSidebar ({ transitionName, type }) {
|
||||
return {
|
||||
type: actions.SIDEBAR_OPEN,
|
||||
value: {
|
||||
transitionName,
|
||||
type,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -15,7 +15,7 @@ const SendTransactionScreen = require('./components/send/send.container')
|
||||
const ConfirmTransaction = require('./components/pages/confirm-transaction')
|
||||
|
||||
// slideout menu
|
||||
const WalletView = require('./components/wallet-view')
|
||||
const Sidebar = require('./components/sidebars').default
|
||||
|
||||
// other views
|
||||
import Home from './components/pages/home'
|
||||
@ -31,7 +31,6 @@ const CreateAccountPage = require('./components/pages/create-account')
|
||||
const NoticeScreen = require('./components/pages/notice')
|
||||
|
||||
const Loading = require('./components/loading-screen')
|
||||
const ReactCSSTransitionGroup = require('react-addons-css-transition-group')
|
||||
const NetworkDropdown = require('./components/dropdowns/network-dropdown')
|
||||
const AccountMenu = require('./components/account-menu')
|
||||
|
||||
@ -105,6 +104,7 @@ class App extends Component {
|
||||
frequentRpcList,
|
||||
currentView,
|
||||
setMouseUserState,
|
||||
sidebar,
|
||||
} = this.props
|
||||
const isLoadingNetwork = network === 'loading' && currentView.name !== 'config'
|
||||
const loadMessage = loadingMessage || isLoadingNetwork ?
|
||||
@ -137,7 +137,12 @@ class App extends Component {
|
||||
h(AppHeader),
|
||||
|
||||
// sidebar
|
||||
this.renderSidebar(),
|
||||
h(Sidebar, {
|
||||
sidebarOpen: sidebar.isOpen,
|
||||
hideSidebar: this.props.hideSidebar,
|
||||
transitionName: sidebar.transitionName,
|
||||
type: sidebar.type,
|
||||
}),
|
||||
|
||||
// network dropdown
|
||||
h(NetworkDropdown, {
|
||||
@ -157,51 +162,6 @@ class App extends Component {
|
||||
)
|
||||
}
|
||||
|
||||
renderSidebar () {
|
||||
return h('div', [
|
||||
h('style', `
|
||||
.sidebar-enter {
|
||||
transition: transform 300ms ease-in-out;
|
||||
transform: translateX(-100%);
|
||||
}
|
||||
.sidebar-enter.sidebar-enter-active {
|
||||
transition: transform 300ms ease-in-out;
|
||||
transform: translateX(0%);
|
||||
}
|
||||
.sidebar-leave {
|
||||
transition: transform 200ms ease-out;
|
||||
transform: translateX(0%);
|
||||
}
|
||||
.sidebar-leave.sidebar-leave-active {
|
||||
transition: transform 200ms ease-out;
|
||||
transform: translateX(-100%);
|
||||
}
|
||||
`),
|
||||
|
||||
h(ReactCSSTransitionGroup, {
|
||||
transitionName: 'sidebar',
|
||||
transitionEnterTimeout: 300,
|
||||
transitionLeaveTimeout: 200,
|
||||
}, [
|
||||
// A second instance of Walletview is used for non-mobile viewports
|
||||
this.props.sidebarOpen ? h(WalletView, {
|
||||
responsiveDisplayClassname: 'sidebar',
|
||||
style: {},
|
||||
}) : undefined,
|
||||
|
||||
]),
|
||||
|
||||
// overlay
|
||||
// TODO: add onClick for overlay to close sidebar
|
||||
this.props.sidebarOpen ? h('div.sidebar-overlay', {
|
||||
style: {},
|
||||
onClick: () => {
|
||||
this.props.hideSidebar()
|
||||
},
|
||||
}, []) : undefined,
|
||||
])
|
||||
}
|
||||
|
||||
toggleMetamaskActive () {
|
||||
if (!this.props.isUnlocked) {
|
||||
// currently inactive: redirect to password box
|
||||
@ -270,7 +230,7 @@ App.propTypes = {
|
||||
provider: PropTypes.object,
|
||||
frequentRpcList: PropTypes.array,
|
||||
currentView: PropTypes.object,
|
||||
sidebarOpen: PropTypes.bool,
|
||||
sidebar: PropTypes.object,
|
||||
alertOpen: PropTypes.bool,
|
||||
hideSidebar: PropTypes.func,
|
||||
isMascara: PropTypes.bool,
|
||||
@ -306,7 +266,7 @@ function mapStateToProps (state) {
|
||||
const { appState, metamask } = state
|
||||
const {
|
||||
networkDropdownOpen,
|
||||
sidebarOpen,
|
||||
sidebar,
|
||||
alertOpen,
|
||||
alertMessage,
|
||||
isLoading,
|
||||
@ -333,7 +293,7 @@ function mapStateToProps (state) {
|
||||
return {
|
||||
// state from plugin
|
||||
networkDropdownOpen,
|
||||
sidebarOpen,
|
||||
sidebar,
|
||||
alertOpen,
|
||||
alertMessage,
|
||||
isLoading,
|
||||
|
@ -459,7 +459,7 @@ const mapDispatchToProps = (dispatch) => {
|
||||
function mapStateToProps (state) {
|
||||
return {
|
||||
keyrings: state.metamask.keyrings,
|
||||
sidebarOpen: state.appState.sidebarOpen,
|
||||
sidebarOpen: state.appState.sidebar.isOpen,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -33,3 +33,7 @@
|
||||
@import './transaction-list-item/index';
|
||||
|
||||
@import './transaction-status/index';
|
||||
|
||||
@import './app-header/index';
|
||||
|
||||
@import './sidebars/index';
|
||||
|
@ -3,17 +3,22 @@ import MenuBar from './menu-bar.component'
|
||||
import { showSidebar, hideSidebar } from '../../actions'
|
||||
|
||||
const mapStateToProps = state => {
|
||||
const { appState: { sidebarOpen, isMascara } } = state
|
||||
const { appState: { sidebar: { isOpen }, isMascara } } = state
|
||||
|
||||
return {
|
||||
sidebarOpen,
|
||||
sidebarOpen: isOpen,
|
||||
isMascara,
|
||||
}
|
||||
}
|
||||
|
||||
const mapDispatchToProps = dispatch => {
|
||||
return {
|
||||
showSidebar: () => dispatch(showSidebar()),
|
||||
showSidebar: () => {
|
||||
dispatch(showSidebar({
|
||||
transitionName: 'sidebar-right',
|
||||
type: 'wallet-view',
|
||||
}))
|
||||
},
|
||||
hideSidebar: () => dispatch(hideSidebar()),
|
||||
}
|
||||
}
|
||||
|
1
ui/app/components/sidebars/index.js
Normal file
1
ui/app/components/sidebars/index.js
Normal file
@ -0,0 +1 @@
|
||||
export { default } from './sidebar.component'
|
74
ui/app/components/sidebars/index.scss
Normal file
74
ui/app/components/sidebars/index.scss
Normal file
@ -0,0 +1,74 @@
|
||||
.sidebar-right-enter {
|
||||
transition: transform 300ms ease-in-out;
|
||||
transform: translateX(-100%);
|
||||
}
|
||||
|
||||
.sidebar-right-enter.sidebar-right-enter-active {
|
||||
transition: transform 300ms ease-in-out;
|
||||
transform: translateX(0%);
|
||||
}
|
||||
|
||||
.sidebar-right-leave {
|
||||
transition: transform 200ms ease-out;
|
||||
transform: translateX(0%);
|
||||
}
|
||||
|
||||
.sidebar-right-leave.sidebar-right-leave-active {
|
||||
transition: transform 200ms ease-out;
|
||||
transform: translateX(-100%);
|
||||
}
|
||||
|
||||
.sidebar-left-enter {
|
||||
transition: transform 300ms ease-in-out;
|
||||
transform: translateX(100%);
|
||||
}
|
||||
|
||||
.sidebar-left-enter.sidebar-left-enter-active {
|
||||
transition: transform 300ms ease-in-out;
|
||||
transform: translateX(0%);
|
||||
}
|
||||
|
||||
.sidebar-left-leave {
|
||||
transition: transform 200ms ease-out;
|
||||
transform: translateX(0%);
|
||||
}
|
||||
|
||||
.sidebar-left-leave.sidebar-left-leave-active {
|
||||
transition: transform 200ms ease-out;
|
||||
transform: translateX(100%);
|
||||
}
|
||||
|
||||
.sidebar-left {
|
||||
flex: 1 0 230px;
|
||||
background: rgb(250, 250, 250);
|
||||
z-index: $sidebar-z-index;
|
||||
position: fixed;
|
||||
left: 15%;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
will-change: transform;
|
||||
overflow-y: auto;
|
||||
box-shadow: rgba(0, 0, 0, .15) 2px 2px 4px;
|
||||
width: 85%;
|
||||
height: 100%;
|
||||
|
||||
@media screen and (min-width: 769px) {
|
||||
width: 408px;
|
||||
left: calc(100% - 408px);
|
||||
}
|
||||
}
|
||||
|
||||
.sidebar-overlay {
|
||||
z-index: $sidebar-overlay-z-index;
|
||||
position: fixed;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
background-color: rgba(0, 0, 0, .3);
|
||||
}
|
49
ui/app/components/sidebars/sidebar.component.js
Normal file
49
ui/app/components/sidebars/sidebar.component.js
Normal file
@ -0,0 +1,49 @@
|
||||
import React, { Component } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import ReactCSSTransitionGroup from 'react-addons-css-transition-group'
|
||||
import WalletView from '../wallet-view'
|
||||
import { WALLET_VIEW_SIDEBAR } from './sidebar.constants'
|
||||
|
||||
export default class Sidebar extends Component {
|
||||
|
||||
static propTypes = {
|
||||
sidebarOpen: PropTypes.bool,
|
||||
hideSidebar: PropTypes.func,
|
||||
transitionName: PropTypes.string,
|
||||
type: PropTypes.string,
|
||||
};
|
||||
|
||||
renderOverlay () {
|
||||
return <div className="sidebar-overlay" onClick={() => this.props.hideSidebar()} />
|
||||
}
|
||||
|
||||
renderSidebarContent () {
|
||||
const { type } = this.props
|
||||
|
||||
switch (type) {
|
||||
case WALLET_VIEW_SIDEBAR:
|
||||
return <WalletView responsiveDisplayClassname={'sidebar-right' } />
|
||||
default:
|
||||
return null
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
render () {
|
||||
const { transitionName, sidebarOpen } = this.props
|
||||
|
||||
return (
|
||||
<div>
|
||||
<ReactCSSTransitionGroup
|
||||
transitionName={transitionName}
|
||||
transitionEnterTimeout={300}
|
||||
transitionLeaveTimeout={200}
|
||||
>
|
||||
{ sidebarOpen ? this.renderSidebarContent() : null }
|
||||
</ReactCSSTransitionGroup>
|
||||
{ sidebarOpen ? this.renderOverlay() : null }
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
}
|
1
ui/app/components/sidebars/sidebar.constants.js
Normal file
1
ui/app/components/sidebars/sidebar.constants.js
Normal file
@ -0,0 +1 @@
|
||||
export const WALLET_VIEW_SIDEBAR = 'wallet-view'
|
88
ui/app/components/sidebars/tests/sidebars-component.test.js
Normal file
88
ui/app/components/sidebars/tests/sidebars-component.test.js
Normal file
@ -0,0 +1,88 @@
|
||||
import React from 'react'
|
||||
import assert from 'assert'
|
||||
import { shallow } from 'enzyme'
|
||||
import sinon from 'sinon'
|
||||
import ReactCSSTransitionGroup from 'react-addons-css-transition-group'
|
||||
import Sidebar from '../sidebar.component.js'
|
||||
|
||||
import WalletView from '../../wallet-view'
|
||||
|
||||
const propsMethodSpies = {
|
||||
hideSidebar: sinon.spy(),
|
||||
}
|
||||
|
||||
describe('Sidebar Component', function () {
|
||||
let wrapper
|
||||
|
||||
beforeEach(() => {
|
||||
wrapper = shallow(<Sidebar
|
||||
sidebarOpen={false}
|
||||
hideSidebar={propsMethodSpies.hideSidebar}
|
||||
transitionName={'someTransition'}
|
||||
type={'wallet-view'}
|
||||
/>)
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
propsMethodSpies.hideSidebar.resetHistory()
|
||||
})
|
||||
|
||||
describe('renderOverlay', () => {
|
||||
let renderOverlay
|
||||
|
||||
beforeEach(() => {
|
||||
renderOverlay = shallow(wrapper.instance().renderOverlay())
|
||||
})
|
||||
|
||||
it('should render a overlay element', () => {
|
||||
assert(renderOverlay.hasClass('sidebar-overlay'))
|
||||
})
|
||||
|
||||
it('should pass the correct onClick function to the element', () => {
|
||||
assert.equal(propsMethodSpies.hideSidebar.callCount, 0)
|
||||
renderOverlay.props().onClick()
|
||||
assert.equal(propsMethodSpies.hideSidebar.callCount, 1)
|
||||
})
|
||||
})
|
||||
|
||||
describe('renderSidebarContent', () => {
|
||||
let renderSidebarContent
|
||||
|
||||
beforeEach(() => {
|
||||
wrapper.setProps({ type: 'wallet-view' })
|
||||
renderSidebarContent = wrapper.instance().renderSidebarContent()
|
||||
})
|
||||
|
||||
it('should render sidebar content with the correct props', () => {
|
||||
wrapper.setProps({ type: 'wallet-view' })
|
||||
renderSidebarContent = wrapper.instance().renderSidebarContent()
|
||||
assert.equal(renderSidebarContent.props.responsiveDisplayClassname, 'sidebar-right')
|
||||
})
|
||||
|
||||
it('should not render with an unrecognized type', () => {
|
||||
wrapper.setProps({ type: 'foobar' })
|
||||
renderSidebarContent = wrapper.instance().renderSidebarContent()
|
||||
assert.equal(renderSidebarContent, undefined)
|
||||
})
|
||||
})
|
||||
|
||||
describe('render', () => {
|
||||
it('should render a div with one child', () => {
|
||||
assert(wrapper.is('div'))
|
||||
assert.equal(wrapper.children().length, 1)
|
||||
})
|
||||
|
||||
it('should render the ReactCSSTransitionGroup without any children', () => {
|
||||
assert(wrapper.children().at(0).is(ReactCSSTransitionGroup))
|
||||
assert.equal(wrapper.children().at(0).children().length, 0)
|
||||
})
|
||||
|
||||
it('should render sidebar content and the overlay if sidebarOpen is true', () => {
|
||||
wrapper.setProps({ sidebarOpen: true })
|
||||
assert.equal(wrapper.children().length, 2)
|
||||
assert(wrapper.children().at(1).hasClass('sidebar-overlay'))
|
||||
assert.equal(wrapper.children().at(0).children().length, 1)
|
||||
assert(wrapper.children().at(0).children().at(0).is(WalletView))
|
||||
})
|
||||
})
|
||||
})
|
@ -18,7 +18,7 @@ function mapStateToProps (state) {
|
||||
userAddress: selectors.getSelectedAddress(state),
|
||||
contractExchangeRates: state.metamask.contractExchangeRates,
|
||||
conversionRate: state.metamask.conversionRate,
|
||||
sidebarOpen: state.appState.sidebarOpen,
|
||||
sidebarOpen: state.appState.sidebar.isOpen,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -34,7 +34,7 @@ function mapStateToProps (state) {
|
||||
|
||||
return {
|
||||
network: state.metamask.network,
|
||||
sidebarOpen: state.appState.sidebarOpen,
|
||||
sidebarOpen: state.appState.sidebar.isOpen,
|
||||
identities: state.metamask.identities,
|
||||
accounts: state.metamask.accounts,
|
||||
tokens: state.metamask.tokens,
|
||||
|
@ -148,7 +148,7 @@ $wallet-view-bg: $alabaster;
|
||||
}
|
||||
}
|
||||
|
||||
.wallet-view.sidebar {
|
||||
.wallet-view.sidebar-right {
|
||||
flex: 1 0 230px;
|
||||
background: rgb(250, 250, 250);
|
||||
z-index: $sidebar-z-index;
|
||||
@ -166,20 +166,6 @@ $wallet-view-bg: $alabaster;
|
||||
height: calc(100% - 56px);
|
||||
}
|
||||
|
||||
.sidebar-overlay {
|
||||
z-index: $sidebar-overlay-z-index;
|
||||
position: fixed;
|
||||
// top: 41px;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
background-color: rgba(0, 0, 0, .3);
|
||||
}
|
||||
|
||||
// main-container media queries
|
||||
|
||||
@media screen and (min-width: 576px) {
|
||||
|
@ -48,7 +48,11 @@ function reduceApp (state, action) {
|
||||
name: null,
|
||||
},
|
||||
},
|
||||
sidebarOpen: false,
|
||||
sidebar: {
|
||||
isOpen: false,
|
||||
transitionName: '',
|
||||
type: '',
|
||||
},
|
||||
alertOpen: false,
|
||||
alertMessage: null,
|
||||
qrCodeData: null,
|
||||
@ -88,12 +92,18 @@ function reduceApp (state, action) {
|
||||
// sidebar methods
|
||||
case actions.SIDEBAR_OPEN:
|
||||
return extend(appState, {
|
||||
sidebarOpen: true,
|
||||
sidebar: {
|
||||
...action.value,
|
||||
isOpen: true,
|
||||
},
|
||||
})
|
||||
|
||||
case actions.SIDEBAR_CLOSE:
|
||||
return extend(appState, {
|
||||
sidebarOpen: false,
|
||||
sidebar: {
|
||||
...appState.sidebar,
|
||||
isOpen: false,
|
||||
},
|
||||
})
|
||||
|
||||
// alert methods
|
||||
|
Loading…
Reference in New Issue
Block a user