aboutsummaryrefslogtreecommitdiffstats
path: root/ui
diff options
context:
space:
mode:
Diffstat (limited to 'ui')
-rw-r--r--ui/app/accounts/import/index.js15
-rw-r--r--ui/app/actions.js6
-rw-r--r--ui/app/add-token.js26
-rw-r--r--ui/app/app.js26
-rw-r--r--ui/app/components/dropdowns/components/account-dropdowns.js18
-rw-r--r--ui/app/components/dropdowns/network-dropdown.js8
-rw-r--r--ui/app/components/modals/deposit-ether-modal.js5
-rw-r--r--ui/app/components/modals/modal.js12
-rw-r--r--ui/app/components/shapeshift-form.js19
-rw-r--r--ui/app/css/itcss/components/account-menu.scss5
-rw-r--r--ui/app/css/itcss/components/header.scss7
-rw-r--r--ui/app/css/itcss/components/modal.scss4
-rw-r--r--ui/app/css/itcss/components/new-account.scss10
-rw-r--r--ui/app/css/itcss/settings/variables.scss4
-rw-r--r--ui/app/reducers/app.js4
-rw-r--r--ui/app/reducers/metamask.js7
-rw-r--r--ui/app/send-v2.js15
-rw-r--r--ui/app/unlock.js4
18 files changed, 134 insertions, 61 deletions
diff --git a/ui/app/accounts/import/index.js b/ui/app/accounts/import/index.js
index 71eb9ae23..adb52db74 100644
--- a/ui/app/accounts/import/index.js
+++ b/ui/app/accounts/import/index.js
@@ -35,6 +35,21 @@ AccountImportSubview.prototype.render = function () {
return (
h('div.new-account-import-form', [
+ h('.new-account-import-disclaimer', [
+ h('span', 'Imported accounts will not be associated with your originally created MetaMask account seedphrase. Learn more about imported accounts '),
+ h('span', {
+ style: {
+ cursor: 'pointer',
+ textDecoration: 'underline',
+ },
+ onClick: () => {
+ global.platform.openWindow({
+ url: 'https://metamask.helpscoutdocs.com/article/17-what-are-loose-accounts',
+ })
+ },
+ }, 'here'),
+ ]),
+
h('div.new-account-import-form__select-section', [
h('div.new-account-import-form__select-label', 'Select Type'),
diff --git a/ui/app/actions.js b/ui/app/actions.js
index 9606841ae..3e26f333b 100644
--- a/ui/app/actions.js
+++ b/ui/app/actions.js
@@ -860,15 +860,16 @@ function markPasswordForgotten () {
function unMarkPasswordForgotten () {
return (dispatch) => {
return background.unMarkPasswordForgotten(() => {
- dispatch(actions.forgotPassword())
+ dispatch(actions.forgotPassword(false))
forceUpdateMetamaskState(dispatch)
})
}
}
-function forgotPassword () {
+function forgotPassword (forgotPasswordState = true) {
return {
type: actions.FORGOT_PASSWORD,
+ value: forgotPasswordState,
}
}
@@ -1504,6 +1505,7 @@ function pairUpdate (coin) {
dispatch(actions.hideWarning())
shapeShiftRequest('marketinfo', {pair: `${coin.toLowerCase()}_eth`}, (mktResponse) => {
dispatch(actions.hideSubLoadingIndication())
+ if (mktResponse.error) return dispatch(actions.displayWarning(mktResponse.error))
dispatch({
type: actions.PAIR_UPDATE,
value: {
diff --git a/ui/app/add-token.js b/ui/app/add-token.js
index 230ab35fe..51c577987 100644
--- a/ui/app/add-token.js
+++ b/ui/app/add-token.js
@@ -52,13 +52,16 @@ function AddTokenScreen () {
isShowingConfirmation: false,
customAddress: '',
customSymbol: '',
- customDecimals: 0,
+ customDecimals: '',
searchQuery: '',
isCollapsed: true,
selectedTokens: {},
errors: {},
+ autoFilled: false,
}
this.tokenAddressDidChange = this.tokenAddressDidChange.bind(this)
+ this.tokenSymbolDidChange = this.tokenSymbolDidChange.bind(this)
+ this.tokenDecimalsDidChange = this.tokenDecimalsDidChange.bind(this)
this.onNext = this.onNext.bind(this)
Component.call(this)
}
@@ -103,6 +106,16 @@ AddTokenScreen.prototype.tokenAddressDidChange = function (e) {
}
}
+AddTokenScreen.prototype.tokenSymbolDidChange = function (e) {
+ const customSymbol = e.target.value.trim()
+ this.setState({ customSymbol })
+}
+
+AddTokenScreen.prototype.tokenDecimalsDidChange = function (e) {
+ const customDecimals = e.target.value.trim()
+ this.setState({ customDecimals })
+}
+
AddTokenScreen.prototype.checkExistingAddresses = function (address) {
if (!address) return false
const tokensList = this.props.tokens
@@ -125,7 +138,7 @@ AddTokenScreen.prototype.validate = function () {
errors.customAddress = 'Address is invalid. '
}
- const validDecimals = customDecimals >= 0 && customDecimals < 36
+ const validDecimals = customDecimals !== null && customDecimals >= 0 && customDecimals < 36
if (!validDecimals) {
errors.customDecimals = 'Decimals must be at least 0, and not over 36.'
}
@@ -166,12 +179,13 @@ AddTokenScreen.prototype.attemptToAutoFillTokenParams = async function (address)
this.setState({
customSymbol: symbol,
customDecimals: decimals.toString(),
+ autoFilled: true,
})
}
}
AddTokenScreen.prototype.renderCustomForm = function () {
- const { customAddress, customSymbol, customDecimals, errors } = this.state
+ const { autoFilled, customAddress, customSymbol, customDecimals, errors } = this.state
return !this.state.isCollapsed && (
h('div.add-token__add-custom-form', [
@@ -196,8 +210,9 @@ AddTokenScreen.prototype.renderCustomForm = function () {
h('div.add-token__add-custom-label', 'Token Symbol'),
h('input.add-token__add-custom-input', {
type: 'text',
+ onChange: this.tokenSymbolDidChange,
value: customSymbol,
- disabled: true,
+ disabled: autoFilled,
}),
h('div.add-token__add-custom-error-message', errors.customSymbol),
]),
@@ -209,8 +224,9 @@ AddTokenScreen.prototype.renderCustomForm = function () {
h('div.add-token__add-custom-label', 'Decimals of Precision'),
h('input.add-token__add-custom-input', {
type: 'number',
+ onChange: this.tokenDecimalsDidChange,
value: customDecimals,
- disabled: true,
+ disabled: autoFilled,
}),
h('div.add-token__add-custom-error-message', errors.customDecimals),
]),
diff --git a/ui/app/app.js b/ui/app/app.js
index 5d37b9bdf..4e6da24c3 100644
--- a/ui/app/app.js
+++ b/ui/app/app.js
@@ -89,6 +89,8 @@ function mapStateToProps (state) {
currentCurrency: state.metamask.currentCurrency,
isMouseUser: state.appState.isMouseUser,
betaUI: state.metamask.featureFlags.betaUI,
+ isRevealingSeedWords: state.metamask.isRevealingSeedWords,
+ Qr: state.appState.Qr,
// state needed to get account dropdown temporarily rendering from app bar
identities,
@@ -286,10 +288,10 @@ App.prototype.renderAppBar = function () {
}),
// metamask name
- h('h1', 'MetaMask'),
-
- h('div.beta-label', 'BETA'),
-
+ h('.flex-row', [
+ h('h1', 'MetaMask'),
+ h('div.beta-label', 'BETA'),
+ ]),
]),
h('div.header__right-actions', [
@@ -362,9 +364,17 @@ App.prototype.renderBackButton = function (style, justArrow = false) {
App.prototype.renderPrimary = function () {
log.debug('rendering primary')
var props = this.props
- const {isMascara, isOnboarding, betaUI} = props
+ const {
+ isMascara,
+ isOnboarding,
+ betaUI,
+ isRevealingSeedWords,
+ Qr,
+ } = props
+ const isMascaraOnboarding = isMascara && isOnboarding
+ const isBetaUIOnboarding = betaUI && isOnboarding && !props.isPopup && !isRevealingSeedWords
- if ((isMascara || betaUI) && isOnboarding && !props.isPopup) {
+ if (isMascaraOnboarding || isBetaUIOnboarding) {
return h(MascaraFirstTime)
}
@@ -388,7 +398,7 @@ App.prototype.renderPrimary = function () {
if (props.isInitialized && props.forgottenPassword) {
log.debug('rendering restore vault screen')
return h(HDRestoreVaultScreen, {key: 'HDRestoreVaultScreen'})
- } else if (!props.isInitialized && !props.isUnlocked) {
+ } else if (!props.isInitialized && !props.isUnlocked && !isRevealingSeedWords) {
log.debug('rendering menu screen')
return props.isPopup
? h(OldUIInitializeMenuScreen, {key: 'menuScreenInit'})
@@ -500,7 +510,7 @@ App.prototype.renderPrimary = function () {
width: '285px',
},
}, [
- h(QrView, {key: 'qr'}),
+ h(QrView, {key: 'qr', Qr}),
]),
])
diff --git a/ui/app/components/dropdowns/components/account-dropdowns.js b/ui/app/components/dropdowns/components/account-dropdowns.js
index fa9ffc632..40918cc53 100644
--- a/ui/app/components/dropdowns/components/account-dropdowns.js
+++ b/ui/app/components/dropdowns/components/account-dropdowns.js
@@ -134,22 +134,6 @@ class AccountDropdowns extends Component {
]),
]),
-// =======
-// },
-// ),
-// this.indicateIfLoose(keyring),
-// h('span', {
-// style: {
-// marginLeft: '20px',
-// fontSize: '24px',
-// maxWidth: '145px',
-// whiteSpace: 'nowrap',
-// overflow: 'hidden',
-// textOverflow: 'ellipsis',
-// },
-// }, identity.name || ''),
-// h('span', { style: { marginLeft: '20px', fontSize: '24px' } }, isSelected ? h('.check', '✓') : null),
-// >>>>>>> master:ui/app/components/account-dropdowns.js
]
)
})
@@ -159,7 +143,7 @@ class AccountDropdowns extends Component {
try { // Sometimes keyrings aren't loaded yet:
const type = keyring.type
const isLoose = type !== 'HD Key Tree'
- return isLoose ? h('.keyring-label', 'LOOSE') : null
+ return isLoose ? h('.keyring-label', 'IMPORTED') : null
} catch (e) { return }
}
diff --git a/ui/app/components/dropdowns/network-dropdown.js b/ui/app/components/dropdowns/network-dropdown.js
index 9be5cc5d1..ff10c0758 100644
--- a/ui/app/components/dropdowns/network-dropdown.js
+++ b/ui/app/components/dropdowns/network-dropdown.js
@@ -114,7 +114,7 @@ NetworkDropdown.prototype.render = function () {
[
providerType === 'mainnet' ? h('i.fa.fa-check') : h('.network-check__transparent', '✓'),
h(NetworkDropdownIcon, {
- backgroundColor: '#038789', // $blue-lagoon
+ backgroundColor: '#29B6AF', // $java
isSelected: providerType === 'mainnet',
}),
h('span.network-name-item', {
@@ -136,7 +136,7 @@ NetworkDropdown.prototype.render = function () {
[
providerType === 'ropsten' ? h('i.fa.fa-check') : h('.network-check__transparent', '✓'),
h(NetworkDropdownIcon, {
- backgroundColor: '#e91550', // $crimson
+ backgroundColor: '#ff4a8d', // $wild-strawberry
isSelected: providerType === 'ropsten',
}),
h('span.network-name-item', {
@@ -158,7 +158,7 @@ NetworkDropdown.prototype.render = function () {
[
providerType === 'kovan' ? h('i.fa.fa-check') : h('.network-check__transparent', '✓'),
h(NetworkDropdownIcon, {
- backgroundColor: '#690496', // $purple
+ backgroundColor: '#7057ff', // $cornflower-blue
isSelected: providerType === 'kovan',
}),
h('span.network-name-item', {
@@ -180,7 +180,7 @@ NetworkDropdown.prototype.render = function () {
[
providerType === 'rinkeby' ? h('i.fa.fa-check') : h('.network-check__transparent', '✓'),
h(NetworkDropdownIcon, {
- backgroundColor: '#ebb33f', // $tulip-tree
+ backgroundColor: '#f6c343', // $saffron
isSelected: providerType === 'rinkeby',
}),
h('span.network-name-item', {
diff --git a/ui/app/components/modals/deposit-ether-modal.js b/ui/app/components/modals/deposit-ether-modal.js
index 532d66653..7547dbcf5 100644
--- a/ui/app/components/modals/deposit-ether-modal.js
+++ b/ui/app/components/modals/deposit-ether-modal.js
@@ -33,6 +33,9 @@ function mapDispatchToProps (dispatch) {
hideModal: () => {
dispatch(actions.hideModal())
},
+ hideWarning: () => {
+ dispatch(actions.hideWarning())
+ },
showAccountDetailModal: () => {
dispatch(actions.showModal({ name: 'ACCOUNT_DETAILS' }))
},
@@ -119,6 +122,7 @@ DepositEtherModal.prototype.render = function () {
h('div.deposit-ether-modal__header__close', {
onClick: () => {
this.setState({ buyingWithShapeshift: false })
+ this.props.hideWarning()
this.props.hideModal()
},
}),
@@ -179,6 +183,7 @@ DepositEtherModal.prototype.render = function () {
}
DepositEtherModal.prototype.goToAccountDetailsModal = function () {
+ this.props.hideWarning()
this.props.hideModal()
this.props.showAccountDetailModal()
}
diff --git a/ui/app/components/modals/modal.js b/ui/app/components/modals/modal.js
index 97fe38292..8e9e58985 100644
--- a/ui/app/components/modals/modal.js
+++ b/ui/app/components/modals/modal.js
@@ -79,6 +79,7 @@ const MODALS = {
contents: [
h(DepositEtherModal, {}, []),
],
+ onHide: (props) => props.hideWarning(),
mobileModalStyle: {
width: '100%',
height: '100%',
@@ -286,6 +287,10 @@ function mapDispatchToProps (dispatch) {
hideModal: () => {
dispatch(actions.hideModal())
},
+ hideWarning: () => {
+ dispatch(actions.hideWarning())
+ },
+
}
}
@@ -308,7 +313,12 @@ Modal.prototype.render = function () {
{
className: 'modal',
keyboard: false,
- onHide: () => { this.onHide() },
+ onHide: () => {
+ if (modal.onHide) {
+ modal.onHide(this.props)
+ }
+ this.onHide()
+ },
ref: (ref) => {
this.modalRef = ref
},
diff --git a/ui/app/components/shapeshift-form.js b/ui/app/components/shapeshift-form.js
index 2270b8236..87eb1588a 100644
--- a/ui/app/components/shapeshift-form.js
+++ b/ui/app/components/shapeshift-form.js
@@ -14,11 +14,13 @@ function mapStateToProps (state) {
tokenExchangeRates,
selectedAddress,
} = state.metamask
+ const { warning } = state.appState
return {
coinOptions,
tokenExchangeRates,
selectedAddress,
+ warning,
}
}
@@ -51,8 +53,7 @@ ShapeshiftForm.prototype.componentWillMount = function () {
this.props.shapeShiftSubview()
}
-ShapeshiftForm.prototype.onCoinChange = function (e) {
- const coin = e.target.value
+ShapeshiftForm.prototype.onCoinChange = function (coin) {
this.setState({
depositCoin: coin,
errorMessage: '',
@@ -133,7 +134,7 @@ ShapeshiftForm.prototype.renderMarketInfo = function () {
}
ShapeshiftForm.prototype.renderQrCode = function () {
- const { depositAddress, isLoading } = this.state
+ const { depositAddress, isLoading, depositCoin } = this.state
const qrImage = qrcode(4, 'M')
qrImage.addData(depositAddress)
qrImage.make()
@@ -141,7 +142,7 @@ ShapeshiftForm.prototype.renderQrCode = function () {
return h('div.shapeshift-form', {}, [
h('div.shapeshift-form__deposit-instruction', [
- 'Deposit your BTC to the address below:',
+ `Deposit your ${depositCoin.toUpperCase()} to the address below:`,
]),
h('div', depositAddress),
@@ -164,7 +165,7 @@ ShapeshiftForm.prototype.renderQrCode = function () {
ShapeshiftForm.prototype.render = function () {
- const { coinOptions, btnClass } = this.props
+ const { coinOptions, btnClass, warning } = this.props
const { depositCoin, errorMessage, showQrCode, depositAddress } = this.state
const coinPair = `${depositCoin}_eth`
const { tokenExchangeRates } = this.props
@@ -182,7 +183,7 @@ ShapeshiftForm.prototype.render = function () {
h(SimpleDropdown, {
selectedOption: this.state.depositCoin,
- onSelect: this.onCoinChange,
+ onSelect: (coin) => this.onCoinChange(coin),
options: Object.entries(coinOptions).map(([coin]) => ({
value: coin.toLowerCase(),
displayValue: coin,
@@ -207,7 +208,9 @@ ShapeshiftForm.prototype.render = function () {
]),
- h('div', {
+ warning && h('div.shapeshift-form__address-input-label', warning),
+
+ !warning && h('div', {
className: classnames('shapeshift-form__address-input-wrapper', {
'shapeshift-form__address-input-wrapper--error': errorMessage,
}),
@@ -228,7 +231,7 @@ ShapeshiftForm.prototype.render = function () {
h('divshapeshift-form__address-input-error-message', [errorMessage]),
]),
- this.renderMarketInfo(),
+ !warning && this.renderMarketInfo(),
]),
diff --git a/ui/app/css/itcss/components/account-menu.scss b/ui/app/css/itcss/components/account-menu.scss
index 8ad7481c7..4752741aa 100644
--- a/ui/app/css/itcss/components/account-menu.scss
+++ b/ui/app/css/itcss/components/account-menu.scss
@@ -66,8 +66,9 @@
.keyring-label {
margin-top: 5px;
- background-color: $black;
- color: $dusty-gray;
+ background-color: $dusty-gray;
+ color: $black;
+ font-weight: normal;
}
}
diff --git a/ui/app/css/itcss/components/header.scss b/ui/app/css/itcss/components/header.scss
index d91ab3c48..eeed9ee06 100644
--- a/ui/app/css/itcss/components/header.scss
+++ b/ui/app/css/itcss/components/header.scss
@@ -80,11 +80,10 @@
font-family: Roboto;
text-transform: uppercase;
font-weight: 500;
- font-size: 0.8rem;
- padding-left: 9px;
+ font-size: .8rem;
color: $buttercup;
- align-self: flex-start;
- margin-top: 10px;
+ margin-left: 5px;
+ line-height: initial;
@media screen and (max-width: 575px) {
display: none;
diff --git a/ui/app/css/itcss/components/modal.scss b/ui/app/css/itcss/components/modal.scss
index 919e1793b..53e3bff00 100644
--- a/ui/app/css/itcss/components/modal.scss
+++ b/ui/app/css/itcss/components/modal.scss
@@ -787,6 +787,10 @@
width: auto;
flex: 1;
}
+
+ @media screen and (max-width: 575px) {
+ width: auto;
+ }
}
}
diff --git a/ui/app/css/itcss/components/new-account.scss b/ui/app/css/itcss/components/new-account.scss
index 81f919df3..c6c254ede 100644
--- a/ui/app/css/itcss/components/new-account.scss
+++ b/ui/app/css/itcss/components/new-account.scss
@@ -54,6 +54,16 @@
}
+.new-account-import-disclaimer {
+ width: 120%;
+ background-color: #F4F9FC;
+ display: inline-block;
+ align-items: center;
+ padding: 20px 30px 20px;
+ font-size: 12px;
+ line-height: 1.5;
+}
+
.new-account-import-form {
display: flex;
flex-flow: column;
diff --git a/ui/app/css/itcss/settings/variables.scss b/ui/app/css/itcss/settings/variables.scss
index 4c0972527..d96c1ae43 100644
--- a/ui/app/css/itcss/settings/variables.scss
+++ b/ui/app/css/itcss/settings/variables.scss
@@ -46,6 +46,10 @@ $manatee: #93949d;
$spindle: #c7ddec;
$mid-gray: #5b5d67;
$cape-cod: #38393a;
+$java: #29b6af;
+$wild-strawberry: #ff4a8d;
+$cornflower-blue: #7057ff;
+$saffron: #f6c343;
/*
Z-Indicies
diff --git a/ui/app/reducers/app.js b/ui/app/reducers/app.js
index 02f024f7c..4dda839a2 100644
--- a/ui/app/reducers/app.js
+++ b/ui/app/reducers/app.js
@@ -140,10 +140,10 @@ function reduceApp (state, action) {
case actions.FORGOT_PASSWORD:
return extend(appState, {
currentView: {
- name: 'restoreVault',
+ name: action.value ? 'restoreVault' : 'accountDetail',
},
transForward: false,
- forgottenPassword: true,
+ forgottenPassword: action.value,
})
case actions.SHOW_INIT_MENU:
diff --git a/ui/app/reducers/metamask.js b/ui/app/reducers/metamask.js
index beeba948d..cddcd0c1f 100644
--- a/ui/app/reducers/metamask.js
+++ b/ui/app/reducers/metamask.js
@@ -43,12 +43,15 @@ function reduceMetamask (state, action) {
useBlockie: false,
featureFlags: {},
networkEndpointType: OLD_UI_NETWORK_TYPE,
+ isRevealingSeedWords: false,
}, state.metamask)
switch (action.type) {
case actions.SHOW_ACCOUNTS_PAGE:
- newState = extend(metamaskState)
+ newState = extend(metamaskState, {
+ isRevealingSeedWords: false,
+ })
delete newState.seedWords
return newState
@@ -124,10 +127,12 @@ function reduceMetamask (state, action) {
},
})
+
case actions.SHOW_NEW_VAULT_SEED:
return extend(metamaskState, {
isUnlocked: true,
isInitialized: false,
+ isRevealingSeedWords: true,
seedWords: action.value,
})
diff --git a/ui/app/send-v2.js b/ui/app/send-v2.js
index 1d67150e3..fc1df1f51 100644
--- a/ui/app/send-v2.js
+++ b/ui/app/send-v2.js
@@ -361,8 +361,9 @@ SendTransactionScreen.prototype.validateAmount = function (value) {
})
}
+ const verifyTokenBalance = selectedToken && tokenBalance !== null
let sufficientTokens
- if (selectedToken) {
+ if (verifyTokenBalance) {
sufficientTokens = isTokenBalanceSufficient({
tokenBalance,
amount,
@@ -377,7 +378,7 @@ SendTransactionScreen.prototype.validateAmount = function (value) {
if (conversionRate && !sufficientBalance) {
amountError = 'Insufficient funds.'
- } else if (selectedToken && !sufficientTokens) {
+ } else if (verifyTokenBalance && !sufficientTokens) {
amountError = 'Insufficient tokens.'
} else if (amountLessThanZero) {
amountError = 'Can not send negative amounts of ETH.'
@@ -396,14 +397,15 @@ SendTransactionScreen.prototype.renderAmountRow = function () {
amount,
setMaxModeTo,
maxModeOn,
+ gasTotal,
} = this.props
return h('div.send-v2__form-row', [
- h('div.send-v2__form-label', [
+ h('div.send-v2__form-label', [
'Amount:',
this.renderErrorMessage('amount'),
- !errors.amount && h('div.send-v2__amount-max', {
+ !errors.amount && gasTotal && h('div.send-v2__amount-max', {
onClick: (event) => {
event.preventDefault()
setMaxModeTo(true)
@@ -491,9 +493,12 @@ SendTransactionScreen.prototype.renderFooter = function () {
goHome,
clearSend,
gasTotal,
+ tokenBalance,
+ selectedToken,
errors: { amount: amountError, to: toError },
} = this.props
+ const missingTokenBalance = selectedToken && !tokenBalance
const noErrors = !amountError && toError === null
return h('div.page-container__footer', [
@@ -504,7 +509,7 @@ SendTransactionScreen.prototype.renderFooter = function () {
},
}, 'Cancel'),
h('button.btn-clear.page-container__footer-button', {
- disabled: !noErrors || !gasTotal,
+ disabled: !noErrors || !gasTotal || missingTokenBalance,
onClick: event => this.onSubmit(event),
}, 'Next'),
])
diff --git a/ui/app/unlock.js b/ui/app/unlock.js
index 13c3f1274..cafe3a859 100644
--- a/ui/app/unlock.js
+++ b/ui/app/unlock.js
@@ -71,7 +71,7 @@ UnlockScreen.prototype.render = function () {
style: {
margin: 10,
},
- }, 'Unlock'),
+ }, 'Log In'),
]),
h('.flex-row.flex-center.flex-grow', [
@@ -104,7 +104,7 @@ UnlockScreen.prototype.render = function () {
},
}, 'Use classic interface'),
]),
-
+
])
)
}