Fix no-negated-condition issues (#9222)

See [`no-negated-condition`](https://eslint.org/docs/rules/no-negated-condition) for more information.

This change enables `no-negated-condition` and fixes the issues raised by the rule.
feature/default_network_editable
Whymarrh Whitby 4 years ago committed by GitHub
parent c11888f287
commit 884775cf71
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      .eslintrc.js
  2. 6
      app/scripts/controllers/transactions/index.js
  3. 2
      app/scripts/controllers/transactions/tx-state-manager.js
  4. 6
      app/scripts/lib/freezeGlobals.js
  5. 14
      app/scripts/lib/util.js
  6. 9
      app/scripts/metamask-controller.js
  7. 8
      development/metamaskbot-build-announce.js
  8. 10
      development/sentry-publish.js
  9. 5
      test/unit/app/nodeify-test.js
  10. 34
      ui/app/components/app/confirm-page-container/confirm-page-container-header/confirm-page-container-header.component.js
  11. 6
      ui/app/components/app/connected-accounts-list/connected-accounts-list.component.js
  12. 6
      ui/app/components/app/gas-customization/gas-modal-page-container/advanced-tab-content/advanced-tab-content.component.js
  13. 6
      ui/app/components/app/gas-customization/gas-modal-page-container/basic-tab-content/basic-tab-content.component.js
  14. 8
      ui/app/components/app/gas-customization/gas-price-button-group/gas-price-button-group.component.js
  15. 10
      ui/app/components/app/info-box/info-box.component.js
  16. 11
      ui/app/components/app/modal/modal.component.js
  17. 2
      ui/app/components/app/modals/edit-approval-permission/edit-approval-permission.component.js
  18. 8
      ui/app/components/app/modals/qr-scanner/qr-scanner.component.js
  19. 19
      ui/app/components/app/transaction-breakdown/transaction-breakdown.component.js
  20. 6
      ui/app/components/app/transaction-list-item/transaction-list-item.component.js
  21. 9
      ui/app/ducks/gas/gas.duck.js
  22. 8
      ui/app/helpers/utils/metametrics.util.js
  23. 6
      ui/app/hooks/tests/useTokenData.test.js
  24. 8
      ui/app/pages/confirm-decrypt-message/confirm-decrypt-message.component.js
  25. 4
      ui/app/pages/first-time-flow/metametrics-opt-in/metametrics-opt-in.component.js
  26. 6
      ui/app/pages/first-time-flow/onboarding-initiator-util.js
  27. 6
      ui/app/pages/first-time-flow/seed-phrase/confirm-seed-phrase/confirm-seed-phrase.component.js
  28. 6
      ui/app/pages/first-time-flow/seed-phrase/seed-phrase.component.js
  29. 12
      ui/app/pages/mobile-sync/mobile-sync.component.js
  30. 16
      ui/app/pages/permissions-connect/permissions-connect.component.js
  31. 8
      ui/app/pages/routes/routes.component.js
  32. 2
      ui/app/pages/send/send-content/add-recipient/ens-input.component.js
  33. 8
      ui/app/pages/send/send-content/send-amount-row/amount-max-button/amount-max-button.component.js
  34. 6
      ui/app/pages/send/send.container.js
  35. 6
      ui/app/selectors/permissions.js

@ -57,6 +57,7 @@ module.exports = {
'no-eq-null': 'error',
'no-global-assign': 'error',
'no-loop-func': 'error',
'no-negated-condition': 'error',
'no-nested-ternary': 'error',
'no-plusplus': ['error', { 'allowForLoopAfterthoughts': true }],
'no-process-exit': 'error',

@ -560,9 +560,9 @@ export default class TransactionController extends EventEmitter {
// It seems that sometimes the numerical values being returned from
// this.query.getTransactionReceipt are BN instances and not strings.
const gasUsed = typeof txReceipt.gasUsed !== 'string'
? txReceipt.gasUsed.toString(16)
: txReceipt.gasUsed
const gasUsed = typeof txReceipt.gasUsed === 'string'
? txReceipt.gasUsed
: txReceipt.gasUsed.toString(16)
txMeta.txReceipt = {
...txReceipt,

@ -424,7 +424,7 @@ export default class TransactionStateManager extends EventEmitter {
@param {erroObject} err - error object
*/
setTxStatusFailed (txId, err) {
const error = !err ? new Error('Internal metamask failure') : err
const error = err || new Error('Internal metamask failure')
const txMeta = this.getTx(txId)
txMeta.err = {

@ -30,11 +30,11 @@ function freeze (target, key, value, enumerable = true) {
configurable: false, writable: false,
}
if (value !== undefined) {
if (value === undefined) {
target[key] = deepFreeze(target[key])
} else {
opts.value = deepFreeze(value)
opts.enumerable = enumerable
} else {
target[key] = deepFreeze(target[key])
}
Object.defineProperty(target, key, opts)

@ -55,19 +55,19 @@ const getEnvironmentType = (url = window.location.href) => getEnvironmentTypeMem
*/
const getPlatform = (_) => {
const ua = window.navigator.userAgent
if (ua.search('Firefox') !== -1) {
return PLATFORM_FIREFOX
} else {
if (ua.search('Firefox') === -1) {
if (window && window.chrome && window.chrome.ipcRenderer) {
return PLATFORM_BRAVE
} else if (ua.search('Edge') !== -1) {
}
if (ua.search('Edge') !== -1) {
return PLATFORM_EDGE
} else if (ua.search('OPR') !== -1) {
}
if (ua.search('OPR') !== -1) {
return PLATFORM_OPERA
} else {
return PLATFORM_CHROME
}
return PLATFORM_CHROME
}
return PLATFORM_FIREFOX
}
/**

@ -710,15 +710,16 @@ export default class MetamaskController extends EventEmitter {
Object.keys(accountTokens).forEach((address) => {
const checksummedAddress = ethUtil.toChecksumAddress(address)
filteredAccountTokens[checksummedAddress] = {}
Object.keys(accountTokens[address]).forEach(
(networkType) => (filteredAccountTokens[checksummedAddress][networkType] = networkType !== 'mainnet' ?
accountTokens[address][networkType] :
Object.keys(accountTokens[address]).forEach((networkType) => {
filteredAccountTokens[checksummedAddress][networkType] = networkType === 'mainnet'
? (
accountTokens[address][networkType].filter(({ address }) => {
const tokenAddress = ethUtil.toChecksumAddress(address)
return contractMap[tokenAddress] ? contractMap[tokenAddress].erc20 : true
})
),
)
: accountTokens[address][networkType]
})
})
const preferences = {

@ -81,10 +81,7 @@ async function start () {
const summaryPlatform = 'chrome'
const summaryPage = 'home'
let commentBody
if (!benchmarkResults[summaryPlatform]) {
console.log(`No results for ${summaryPlatform} found; skipping benchmark`)
commentBody = artifactsBody
} else {
if (benchmarkResults[summaryPlatform]) {
try {
const summaryPageLoad = Math.round(parseFloat(benchmarkResults[summaryPlatform][summaryPage].average.load))
const summaryPageLoadMarginOfError = Math.round(parseFloat(benchmarkResults[summaryPlatform][summaryPage].marginOfError.load))
@ -147,6 +144,9 @@ async function start () {
console.error(`Error constructing benchmark results: '${error}'`)
commentBody = artifactsBody
}
} else {
console.log(`No results for ${summaryPlatform} found; skipping benchmark`)
commentBody = artifactsBody
}
const JSON_PAYLOAD = JSON.stringify({ body: commentBody })

@ -25,12 +25,14 @@ async function start () {
// check if version has artifacts or not
const versionHasArtifacts = versionAlreadyExists && await checkIfVersionHasArtifacts()
if (!versionHasArtifacts) {
// upload sentry source and sourcemaps
await exec(`./development/sentry-upload-artifacts.sh --release ${VERSION}`)
} else {
if (versionHasArtifacts) {
console.log(`Version "${VERSION}" already has artifacts on Sentry, skipping sourcemap upload`)
return
}
// upload sentry source and sourcemaps
await exec(`./development/sentry-upload-artifacts.sh --release ${VERSION}`)
}
async function checkIfAuthWorks () {

@ -16,9 +16,10 @@ describe('nodeify', function () {
if (!err) {
assert.equal(res, 'barbaz')
done()
} else {
done(new Error(err.toString()))
return
}
done(new Error(err.toString()))
})
})

@ -30,8 +30,22 @@ export default function ConfirmPageContainerHeader ({
return (
<div className="confirm-page-container-header">
<div className="confirm-page-container-header__row">
{ !showAccountInHeader
{ showAccountInHeader
? (
<div className="confirm-page-container-header__address-container">
<div className="confirm-page-container-header__address-identicon">
<Identicon
address={accountAddress}
diameter={24}
/>
</div>
<div className="confirm-page-container-header__address">
{ shortenAddress(accountAddress) }
</div>
<AccountMismatchWarning address={accountAddress} />
</div>
)
: (
<div
className="confirm-page-container-header__back-button-container"
style={{
@ -49,24 +63,6 @@ export default function ConfirmPageContainerHeader ({
</span>
</div>
)
: null
}
{ showAccountInHeader
? (
<div className="confirm-page-container-header__address-container">
<div className="confirm-page-container-header__address-identicon">
<Identicon
address={accountAddress}
diameter={24}
/>
</div>
<div className="confirm-page-container-header__address">
{ shortenAddress(accountAddress) }
</div>
<AccountMismatchWarning address={accountAddress} />
</div>
)
: null
}
{ !isFullScreen && <NetworkDisplay /> }
</div>

@ -149,9 +149,9 @@ export default class ConnectedAccountsList extends PureComponent {
: null
}
action={
address !== selectedAddress
? this.renderListItemAction(address)
: null
address === selectedAddress
? null
: this.renderListItemAction(address)
}
/>
)

@ -86,9 +86,9 @@ export default class AdvancedTabContent extends Component {
? (
<div>
<div className="advanced-tab__fee-chart__title">{ t('liveGasPricePredictions') }</div>
{!gasEstimatesLoading
? <GasPriceChart {...gasChartProps} updateCustomGasPrice={this.onGasChartUpdate} />
: <Loading />
{gasEstimatesLoading
? <Loading />
: <GasPriceChart {...gasChartProps} updateCustomGasPrice={this.onGasChartUpdate} />
}
<div className="advanced-tab__fee-chart__speed-buttons">
<span>{ t('slower') }</span>

@ -20,15 +20,15 @@ export default class BasicTabContent extends Component {
<div className="basic-tab-content">
<div className="basic-tab-content__title">{ t('estimatedProcessingTimes') }</div>
<div className="basic-tab-content__blurb">{ t('selectAHigherGasFee') }</div>
{!gasPriceButtonGroupProps.loading
? (
{gasPriceButtonGroupProps.loading
? <Loading />
: (
<GasPriceButtonGroup
className="gas-price-button-group--alt"
showCheck
{...gasPriceButtonGroupProps}
/>
)
: <Loading />
}
<div className="basic-tab-content__footer-blurb">{ t('acceleratingATransaction') }</div>
</div>

@ -89,18 +89,18 @@ export default class GasPriceButtonGroup extends Component {
} = this.props
return (
!buttonDataLoading
? (
buttonDataLoading
? <div className={`${buttonPropsAndFlags.className}__loading-container`}>{this.context.t('loading')}</div>
: (
<ButtonGroup
className={buttonPropsAndFlags.className}
defaultActiveButtonIndex={defaultActiveButtonIndex}
newActiveButtonIndex={newActiveButtonIndex}
noButtonActiveByDefault={noButtonActiveByDefault}
>
{ gasButtonInfo.map((obj, index) => this.renderButton(obj, buttonPropsAndFlags, index)) }
{gasButtonInfo.map((obj, index) => this.renderButton(obj, buttonPropsAndFlags, index))}
</ButtonGroup>
)
: <div className={`${buttonPropsAndFlags.className}__loading-container`}>{ this.context.t('loading') }</div>
)
}
}

@ -29,17 +29,17 @@ export default class InfoBox extends Component {
render () {
const { title, description } = this.props
return !this.state.isShowing
? null
: (
return this.state.isShowing
? (
<div className="info-box">
<div
className="info-box__close"
onClick={() => this.handleClose()}
/>
<div className="info-box__title">{ title }</div>
<div className="info-box__description">{ description }</div>
<div className="info-box__title">{title}</div>
<div className="info-box__description">{description}</div>
</div>
)
: null
}
}

@ -63,8 +63,10 @@ export default class Modal extends PureComponent {
<div className={classnames('modal-container__content', contentClass)}>
{ children }
</div>
{ !hideFooter
? (
{
hideFooter
? null
: (
<div className="modal-container__footer">
{
onCancel && (
@ -73,7 +75,7 @@ export default class Modal extends PureComponent {
onClick={onCancel}
className="modal-container__footer-button"
>
{ cancelText }
{cancelText}
</Button>
)
}
@ -83,11 +85,10 @@ export default class Modal extends PureComponent {
disabled={submitDisabled}
className="modal-container__footer-button"
>
{ submitText }
{submitText}
</Button>
</div>
)
: null
}
</div>
)

@ -204,7 +204,7 @@ export default class EditApprovalPermission extends PureComponent {
return (
<Modal
onSubmit={() => {
setCustomAmount(!selectedOptionIsUnlimited ? customSpendLimit : '')
setCustomAmount(selectedOptionIsUnlimited ? '' : customSpendLimit)
hideModal()
}}
submitText={t('save')}

@ -117,11 +117,11 @@ export default class QrScanner extends Component {
const result = this.parseContent(content.text)
if (!this.mounted) {
return
} else if (result.type !== 'unknown') {
} else if (result.type === 'unknown') {
this.setState({ error: new Error(this.context.t('unknownQrCode')) })
} else {
this.props.qrCodeDetected(result)
this.stopAndClose()
} else {
this.setState({ error: new Error(this.context.t('unknownQrCode')) })
}
} catch (error) {
if (!this.mounted) {
@ -248,7 +248,7 @@ export default class QrScanner extends Component {
display: ready === READY_STATE.READY ? 'block' : 'none',
}}
/>
{ ready !== READY_STATE.READY ? <Spinner color="#F7C06C" /> : null}
{ready === READY_STATE.READY ? null : <Spinner color="#F7C06C" />}
</div>
</div>
<div className="qr-scanner__status">

@ -37,13 +37,14 @@ export default class TransactionBreakdown extends PureComponent {
{ t('transaction') }
</div>
<TransactionBreakdownRow title="Nonce">
{typeof nonce !== 'undefined'
? (
{typeof nonce === 'undefined'
? null
: (
<HexToDecimal
className="transaction-breakdown__value"
value={nonce}
/>
) : null
)
}
</TransactionBreakdownRow>
<TransactionBreakdownRow title={t('amount')}>
@ -57,14 +58,14 @@ export default class TransactionBreakdown extends PureComponent {
title={`${t('gasLimit')} (${t('units')})`}
className="transaction-breakdown__row-title"
>
{typeof gas !== 'undefined'
? (
{typeof gas === 'undefined'
? '?'
: (
<HexToDecimal
className="transaction-breakdown__value"
value={gas}
/>
)
: '?'
}
</TransactionBreakdownRow>
{
@ -81,8 +82,9 @@ export default class TransactionBreakdown extends PureComponent {
)
}
<TransactionBreakdownRow title={t('gasPrice')}>
{typeof gasPrice !== 'undefined'
? (
{typeof gasPrice === 'undefined'
? '?'
: (
<CurrencyDisplay
className="transaction-breakdown__value"
data-testid="transaction-breakdown__gas-price"
@ -92,7 +94,6 @@ export default class TransactionBreakdown extends PureComponent {
hideLabel
/>
)
: '?'
}
</TransactionBreakdownRow>
<TransactionBreakdownRow title={t('total')}>

@ -86,13 +86,15 @@ export default function TransactionListItem ({ transactionGroup, isEarliestNonce
return null
}
return !cancelEnabled ? (
return cancelEnabled
? cancelButton
: (
<Tooltip title={t('notEnoughGas')}>
<div>
{cancelButton}
</div>
</Tooltip>
) : cancelButton
)
}, [isPending, t, isUnapproved, cancelEnabled, cancelTransaction, hasCancelled])

@ -399,7 +399,7 @@ export function fetchGasEstimates (blockTime) {
const next = arr[i + 1]
if (!next) {
return [{ expectedWait, gasprice }]
} else {
}
const supplementalPrice = getRandomArbitrary(gasprice, next.gasprice)
const supplementalTime = extrapolateY({
higherY: next.expectedWait,
@ -421,7 +421,6 @@ export function fetchGasEstimates (blockTime) {
{ expectedWait: supplementalTime, gasprice: supplementalPrice },
{ expectedWait: supplementalTime2, gasprice: supplementalPrice2 },
]
}
}))
const withOutliersRemoved = inliersByIQR(withSupplementalTimeEstimates.slice(0).reverse(), 'expectedWait').reverse()
const timeMappedToSeconds = withOutliersRemoved.map(({ expectedWait, gasprice }) => {
@ -453,11 +452,11 @@ export function fetchGasEstimates (blockTime) {
export function setCustomGasPriceForRetry (newPrice) {
return (dispatch) => {
if (newPrice !== '0x0') {
dispatch(setCustomGasPrice(newPrice))
} else {
if (newPrice === '0x0') {
const { fast } = loadLocalStorageData('BASIC_PRICE_ESTIMATES')
dispatch(setCustomGasPrice(decGWEIToHexWEI(fast)))
} else {
dispatch(setCustomGasPrice(newPrice))
}
}
}

@ -157,7 +157,10 @@ function composeUrl (config) {
const urlref = previousPath && composeUrlRefParamAddition(previousPath, confirmTransactionOrigin)
const dimensions = !pageOpts.hideDimensions ? composeCustomDimensionParamAddition({
const dimensions = pageOpts.hideDimensions
? ''
: (
composeCustomDimensionParamAddition({
network,
environmentType,
activeCurrency,
@ -165,7 +168,8 @@ function composeUrl (config) {
version,
numberOfTokens: (customVariables && customVariables.numberOfTokens) || numberOfTokens,
numberOfAccounts: (customVariables && customVariables.numberOfAccounts) || numberOfAccounts,
}) : ''
})
)
const url = currentPath ? `&url=${encodeURIComponent(`${METAMETRICS_TRACKING_URL}${currentPath}`)}` : ''
const _id = metaMetricsId && !excludeMetaMetricsId ? `&_id=${metaMetricsId.slice(2, 18)}` : ''
const rand = `&rand=${String(Math.random()).slice(2)}`

@ -65,9 +65,9 @@ const tests = [
describe('useTokenData', function () {
tests.forEach((test) => {
const testTitle = test.tokenData !== null
? `should return properly decoded data with _value ${test.tokenData.params[1].value}`
: `should return null when no data provided`
const testTitle = test.tokenData === null
? `should return null when no data provided`
: `should return properly decoded data with _value ${test.tokenData.params[1].value}`
it(testTitle, function () {
const { result } = renderHook(() => useTokenData(test.data))
assert.deepEqual(result.current, test.tokenData)

@ -220,7 +220,7 @@ export default class ConfirmDecryptMessage extends Component {
className="request-decrypt-message__message-text"
>
{ !hasDecrypted && !hasError ? txData.msgParams.data : rawMessage }
{ !hasError ? '' : errorMessage }
{ hasError ? errorMessage : '' }
</div>
<div
className={classnames({
@ -236,10 +236,10 @@ export default class ConfirmDecryptMessage extends Component {
})}
onClick={(event) => {
decryptMessageInline(txData, event).then((result) => {
if (!result.error) {
this.setState({ hasDecrypted: true, rawMessage: result.rawData })
} else {
if (result.error) {
this.setState({ hasError: true, errorMessage: this.context.t('decryptInlineError', [result.error]) })
} else {
this.setState({ hasDecrypted: true, rawMessage: result.rawData })
}
})
}}

@ -88,7 +88,7 @@ export default class MetaMetricsOptIn extends Component {
onCancel={() => {
setParticipateInMetaMetrics(false)
.then(() => {
const promise = participateInMetaMetrics !== false
const promise = participateInMetaMetrics === true
? metricsEvent({
eventOpts: {
category: 'Onboarding',
@ -110,7 +110,7 @@ export default class MetaMetricsOptIn extends Component {
onSubmit={() => {
setParticipateInMetaMetrics(true)
.then(([_, metaMetricsId]) => {
const promise = participateInMetaMetrics !== true
const promise = participateInMetaMetrics === false
? metricsEvent({
eventOpts: {
category: 'Onboarding',

@ -16,12 +16,12 @@ const returnToOnboardingInitiatorTab = async (onboardingInitiator) => {
})
}))
if (!tab) {
if (tab) {
window.close()
} else {
// this case can happen if the tab was closed since being checked with `extension.tabs.get`
log.warn(`Setting current tab to onboarding initiator has failed; falling back to redirect`)
window.location.assign(onboardingInitiator.location)
} else {
window.close()
}
}

@ -173,10 +173,10 @@ export default class ConfirmSeedPhrase extends PureComponent {
className="confirm-seed-phrase__seed-word--sorted"
selected={isSelected}
onClick={() => {
if (!isSelected) {
this.handleSelectSeedWord(index)
} else {
if (isSelected) {
this.handleDeselectSeedWord(index)
} else {
this.handleSelectSeedWord(index)
}
}}
word={word}

@ -30,10 +30,10 @@ export default class SeedPhrase extends PureComponent {
if (!seedPhrase) {
verifySeedPhrase()
.then((verifiedSeedPhrase) => {
if (!verifiedSeedPhrase) {
history.push(DEFAULT_ROUTE)
} else {
if (verifiedSeedPhrase) {
this.setState({ verifiedSeedPhrase })
} else {
history.push(DEFAULT_ROUTE)
}
})
}

@ -194,10 +194,10 @@ export default class MobileSyncPage extends Component {
storeInHistory: false,
},
(status, response) => {
if (!status.error) {
resolve()
} else {
if (status.error) {
reject(response)
} else {
resolve()
}
})
})
@ -253,10 +253,10 @@ export default class MobileSyncPage extends Component {
storeInHistory: false,
},
(status, response) => {
if (!status.error) {
resolve()
} else {
if (status.error) {
reject(response)
} else {
resolve()
}
},
)

@ -162,26 +162,24 @@ export default class PermissionConnect extends Component {
const { redirecting } = this.state
const { page } = this.props
const { t } = this.context
return !redirecting
? (
<div
className="permissions-connect__top-bar"
>
{ page === '2'
return redirecting
? null
: (
<div className="permissions-connect__top-bar">
{page === '2'
? (
<div className="permissions-connect__back" onClick={() => this.goBack()}>
<i className="fas fa-chevron-left" />
{ t('back') }
{t('back')}
</div>
)
: null
}
<div className="permissions-connect__page-count">
{ t('xOfY', [ page, '2' ]) }
{t('xOfY', [page, '2'])}
</div>
</div>
)
: null
}
render () {

@ -265,16 +265,16 @@ export default class Routes extends Component {
}
toggleMetamaskActive () {
if (!this.props.isUnlocked) {
if (this.props.isUnlocked) {
// currently active: deactivate
this.props.lockMetaMask()
} else {
// currently inactive: redirect to password box
const passwordBox = document.querySelector('input[type=password]')
if (!passwordBox) {
return
}
passwordBox.focus()
} else {
// currently active: deactivate
this.props.lockMetaMask()
}
}

@ -122,7 +122,7 @@ export default class EnsInput extends Component {
if (!networkHasEnsSupport && !isValidAddress(input) && !isValidAddressHead(input)) {
updateEnsResolution('')
updateEnsResolutionError(!networkHasEnsSupport ? 'Network does not support ENS' : '')
updateEnsResolutionError(networkHasEnsSupport ? '' : 'Network does not support ENS')
return
}

@ -51,12 +51,12 @@ export default class AmountMaxButton extends Component {
name: 'Clicked "Amount Max"',
},
})
if (!maxModeOn) {
setMaxModeTo(true)
this.setMaxAmount()
} else {
if (maxModeOn) {
setMaxModeTo(false)
clearMaxAmount()
} else {
setMaxModeTo(true)
this.setMaxAmount()
}
}

@ -90,9 +90,9 @@ function mapDispatchToProps (dispatch) {
value,
data,
}) => {
!editingTransactionId
? dispatch(updateGasData({ gasPrice, selectedAddress, sendToken, blockGasLimit, to, value, data }))
: dispatch(setGasTotal(calcGasTotal(gasLimit, gasPrice)))
editingTransactionId
? dispatch(setGasTotal(calcGasTotal(gasLimit, gasPrice)))
: dispatch(updateGasData({ gasPrice, selectedAddress, sendToken, blockGasLimit, to, value, data }))
},
updateSendTokenBalance: ({ sendToken, tokenContract, address }) => {
dispatch(updateSendTokenBalance({

@ -261,10 +261,10 @@ export function getPermissionsMetadataHostCounts (state) {
const metadata = getPermissionDomainsMetadata(state)
return Object.values(metadata).reduce((counts, { host }) => {
if (host) {
if (!counts[host]) {
counts[host] = 1
} else {
if (counts[host]) {
counts[host] += 1
} else {
counts[host] = 1
}
}
return counts

Loading…
Cancel
Save