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

Use createContext for metametrics context (preserve legacy context) (#8540)

This commit is contained in:
Brad Decker 2020-05-08 11:41:43 -05:00 committed by GitHub
parent abf2294bf3
commit c0489163b5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 148 additions and 136 deletions

View File

@ -0,0 +1,131 @@
import React, { Component, createContext, useEffect, useCallback, useState } from 'react'
import { useSelector } from 'react-redux'
import PropTypes from 'prop-types'
import { useHistory } from 'react-router-dom'
import { captureException } from '@sentry/browser'
import {
getCurrentNetworkId,
getSelectedAsset,
getAccountType,
getNumberOfAccounts,
getNumberOfTokens,
} from '../selectors/selectors'
import {
txDataSelector,
} from '../selectors/confirm-transaction'
import { getEnvironmentType } from '../../../app/scripts/lib/util'
import {
sendMetaMetricsEvent,
sendCountIsTrackable,
} from '../helpers/utils/metametrics.util'
export const MetaMetricsContext = createContext(() => {
captureException(
Error(`MetaMetrics context function was called from a react node that is not a descendant of a MetaMetrics context provider`)
)
})
export function MetaMetricsProvider ({ children }) {
const txData = useSelector(txDataSelector) || {}
const network = useSelector(getCurrentNetworkId)
const environmentType = getEnvironmentType()
const activeCurrency = useSelector(getSelectedAsset)
const accountType = useSelector(getAccountType)
const confirmTransactionOrigin = txData.origin
const metaMetricsId = useSelector((state) => state.metamask.metaMetricsId)
const participateInMetaMetrics = useSelector((state) => state.metamask.participateInMetaMetrics)
const metaMetricsSendCount = useSelector((state) => state.metamask.metaMetricsSendCount)
const numberOfTokens = useSelector(getNumberOfTokens)
const numberOfAccounts = useSelector(getNumberOfAccounts)
const history = useHistory()
const [state, setState] = useState(() => ({
currentPath: window.location.href,
previousPath: '',
}))
const { previousPath, currentPath } = state
useEffect(() => {
const unlisten = history.listen(() => setState((prevState) => ({
currentPath: window.location.href,
previousPath: prevState.currentPath,
})))
// remove this listener if the component is no longer mounted
return unlisten
}, [history])
const metricsEvent = useCallback((config = {}, overrides = {}) => {
const { eventOpts = {} } = config
const { name = '' } = eventOpts
const { pathname: overRidePathName = '' } = overrides
const isSendFlow = Boolean(name.match(/^send|^confirm/) || overRidePathName.match(/send|confirm/))
if (participateInMetaMetrics || config.isOptIn) {
return sendMetaMetricsEvent({
network,
environmentType,
activeCurrency,
accountType,
confirmTransactionOrigin,
metaMetricsId,
numberOfTokens,
numberOfAccounts,
version: global.platform.getVersion(),
...config,
previousPath,
currentPath,
excludeMetaMetricsId: isSendFlow && !sendCountIsTrackable(metaMetricsSendCount + 1),
...overrides,
})
}
}, [
network,
environmentType,
activeCurrency,
accountType,
confirmTransactionOrigin,
participateInMetaMetrics,
previousPath,
metaMetricsId,
numberOfTokens,
numberOfAccounts,
currentPath,
metaMetricsSendCount,
])
return (
<MetaMetricsContext.Provider value={metricsEvent}>
{children}
</MetaMetricsContext.Provider>
)
}
MetaMetricsProvider.propTypes = { children: PropTypes.node }
export class LegacyMetaMetricsProvider extends Component {
static propTypes = {
children: PropTypes.node,
}
static defaultProps = {
children: undefined,
}
static contextType = MetaMetricsContext
static childContextTypes = {
metricsEvent: PropTypes.func,
}
getChildContext () {
return {
metricsEvent: this.context,
}
}
render () {
return this.props.children
}
}

View File

@ -1,130 +0,0 @@
import { Component } from 'react'
import { connect } from 'react-redux'
import PropTypes from 'prop-types'
import { withRouter } from 'react-router-dom'
import { compose } from 'redux'
import {
getCurrentNetworkId,
getSelectedAsset,
getAccountType,
getNumberOfAccounts,
getNumberOfTokens,
txDataSelector,
} from '../../../selectors'
import { getEnvironmentType } from '../../../../../app/scripts/lib/util'
import {
sendMetaMetricsEvent,
sendCountIsTrackable,
} from '../../utils/metametrics.util'
class MetaMetricsProvider extends Component {
static propTypes = {
accountType: PropTypes.string.isRequired,
activeCurrency: PropTypes.string.isRequired,
children: PropTypes.object.isRequired,
confirmTransactionOrigin: PropTypes.string,
environmentType: PropTypes.string.isRequired,
history: PropTypes.object.isRequired,
metaMetricsId: PropTypes.string,
metaMetricsSendCount: PropTypes.number.isRequired,
network: PropTypes.string.isRequired,
numberOfTokens: PropTypes.number,
numberOfAccounts: PropTypes.number,
participateInMetaMetrics: PropTypes.bool,
version: PropTypes.string,
}
static childContextTypes = {
metricsEvent: PropTypes.func,
}
constructor (props) {
super(props)
props.history.listen(() => {
this.setState((prevState) => ({
previousPath: prevState.currentPath,
currentPath: window.location.href,
}))
})
}
state = {
previousPath: '',
currentPath: window.location.href,
}
getChildContext () {
const {
network,
environmentType,
activeCurrency,
accountType,
confirmTransactionOrigin,
metaMetricsId,
participateInMetaMetrics,
metaMetricsSendCount,
numberOfTokens,
numberOfAccounts,
version,
} = this.props
const { previousPath, currentPath } = this.state
return {
metricsEvent: (config = {}, overrides = {}) => {
const { eventOpts = {} } = config
const { name = '' } = eventOpts
const { pathname: overRidePathName = '' } = overrides
const isSendFlow = Boolean(name.match(/^send|^confirm/) || overRidePathName.match(/send|confirm/))
if (participateInMetaMetrics || config.isOptIn) {
return sendMetaMetricsEvent({
network,
environmentType,
activeCurrency,
accountType,
confirmTransactionOrigin,
metaMetricsId,
numberOfTokens,
numberOfAccounts,
version,
...config,
previousPath,
currentPath,
excludeMetaMetricsId: isSendFlow && !sendCountIsTrackable(metaMetricsSendCount + 1),
...overrides,
})
}
},
}
}
render () {
return this.props.children
}
}
const mapStateToProps = (state) => {
const txData = txDataSelector(state) || {}
return {
network: getCurrentNetworkId(state),
environmentType: getEnvironmentType(),
activeCurrency: getSelectedAsset(state),
accountType: getAccountType(state),
confirmTransactionOrigin: txData.origin,
metaMetricsId: state.metamask.metaMetricsId,
participateInMetaMetrics: state.metamask.participateInMetaMetrics,
metaMetricsSendCount: state.metamask.metaMetricsSendCount,
numberOfTokens: getNumberOfTokens(state),
numberOfAccounts: getNumberOfAccounts(state),
version: global.platform.getVersion(),
}
}
export default compose(
withRouter,
connect(mapStateToProps)
)(MetaMetricsProvider)

View File

@ -0,0 +1,9 @@
import { useContext, useCallback } from 'react'
import { MetaMetricsContext } from '../contexts/metametrics'
export function useMetricEvent (config = {}, overrides = {}) {
const metricsEvent = useContext(MetaMetricsContext)
const trackEvent = useCallback(() => metricsEvent(config, overrides), [config, overrides])
return trackEvent
}

View File

@ -6,7 +6,7 @@ import * as Sentry from '@sentry/browser'
import ErrorPage from './error' import ErrorPage from './error'
import Routes from './routes' import Routes from './routes'
import { I18nProvider, LegacyI18nProvider } from '../contexts/i18n' import { I18nProvider, LegacyI18nProvider } from '../contexts/i18n'
import MetaMetricsProvider from '../helpers/higher-order-components/metametrics/metametrics.provider' import { MetaMetricsProvider, LegacyMetaMetricsProvider } from '../contexts/metametrics'
class Index extends PureComponent { class Index extends PureComponent {
state = {} state = {}
@ -42,11 +42,13 @@ class Index extends PureComponent {
<Provider store={store}> <Provider store={store}>
<HashRouter hashType="noslash"> <HashRouter hashType="noslash">
<MetaMetricsProvider> <MetaMetricsProvider>
<I18nProvider> <LegacyMetaMetricsProvider>
<LegacyI18nProvider> <I18nProvider>
<Routes /> <LegacyI18nProvider>
</LegacyI18nProvider> <Routes />
</I18nProvider> </LegacyI18nProvider>
</I18nProvider>
</LegacyMetaMetricsProvider>
</MetaMetricsProvider> </MetaMetricsProvider>
</HashRouter> </HashRouter>
</Provider> </Provider>