Skip to content

Commit

Permalink
Implement web3 shim usage notification
Browse files Browse the repository at this point in the history
  • Loading branch information
rekmarks committed Dec 10, 2020
1 parent 4538126 commit d555463
Show file tree
Hide file tree
Showing 9 changed files with 148 additions and 30 deletions.
9 changes: 6 additions & 3 deletions app/_locales/en/messages.json
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,9 @@
"bytes": {
"message": "Bytes"
},
"canToggleInSettings": {
"message": "You can re-enable this notification in Settings -> Alerts."
},
"cancel": {
"message": "Cancel"
},
Expand Down Expand Up @@ -2101,9 +2104,9 @@
"walletSeed": {
"message": "Seed phrase"
},
"web3UsageNotification": {
"message": "We noticed that the site at $1 attempted to use window.web3.",
"description": "$1 is a URL."
"web3ShimUsageNotification": {
"message": "We noticed that the current website tried to use the removed window.web3 API. If the site appears to be broken, please click $1 for more information.",
"description": "$1 is a clickable link."
},
"welcome": {
"message": "Welcome to MetaMask"
Expand Down
6 changes: 3 additions & 3 deletions app/scripts/controllers/alert.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import {
*/

const defaultState = {
alertEnabledness: Object.keys(TOGGLEABLE_ALERT_TYPES).reduce(
alertEnabledness: TOGGLEABLE_ALERT_TYPES.reduce(
(alertEnabledness, alertType) => {
alertEnabledness[alertType] = true
return alertEnabledness
Expand All @@ -39,7 +39,7 @@ export default class AlertController {
* @param {AlertControllerOptions} [opts] - Controller configuration parameters
*/
constructor(opts = {}) {
const { initState, preferencesStore } = opts
const { initState = {}, preferencesStore } = opts
const state = {
alertEnabledness: {
...defaultState.alertEnabledness,
Expand Down Expand Up @@ -111,7 +111,7 @@ export default class AlertController {
* @param {string} origin - The origin that the web3 shim notification was
* dismissed for.
*/
setWeb3ShimUsageDismissed(origin) {
setWeb3ShimUsageAlertDismissed(origin) {
this._setWeb3ShimUsageState(origin, WEB3_SHIM_USAGE_ALERT_STATES.DISMISSED)
}

Expand Down
2 changes: 1 addition & 1 deletion app/scripts/metamask-controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -707,7 +707,7 @@ export default class MetamaskController extends EventEmitter {
setUnconnectedAccountAlertShown: alertController.setUnconnectedAccountAlertShown.bind(
alertController,
),
setWeb3ShimUsageDismissed: alertController.setWeb3ShimUsageDismissed.bind(
setWeb3ShimUsageAlertDismissed: alertController.setWeb3ShimUsageAlertDismissed.bind(
alertController,
),

Expand Down
Original file line number Diff line number Diff line change
@@ -1,22 +1,41 @@
import React from 'react'
import React, { useState } from 'react'
import classnames from 'classnames'
import PropTypes from 'prop-types'
import Button from '../../ui/button'
import Checkbox from '../../ui/check-box'
import Tooltip from '../../ui/tooltip'

const HomeNotification = ({
acceptText,
checkboxText,
checkboxTooltipText,
classNames = [],
descriptionText,
ignoreText,
infoText,
onAccept,
onIgnore,
}) => {
const [checkboxState, setCheckBoxState] = useState(false)

const checkboxElement = checkboxText && (
<Checkbox
id="homeNotification_checkbox"
checked={checkboxState}
className="home-notification__checkbox"
onClick={() => setCheckBoxState((checked) => !checked)}
/>
)

return (
<div className={classnames('home-notification', ...classNames)}>
<div className="home-notification__content">
<div className="home-notification__content-container">
<img
className="home-notification__icon"
alt=""
src="images/icons/connect.svg"
/>
<div className="home-notification__text">{descriptionText}</div>
</div>
{infoText ? (
Expand All @@ -43,18 +62,43 @@ const HomeNotification = ({
<Button
type="secondary"
className="home-notification__ignore-button"
onClick={onIgnore}
// Some onIgnore handlers use the checkboxState to determine whether
// to disable the notification
onClick={() => onIgnore(checkboxState)}
>
{ignoreText}
</Button>
) : null}
{checkboxText ? (
<div className="home-notification__checkbox-wrapper">
{checkboxTooltipText ? (
<Tooltip
position="top"
title={checkboxTooltipText}
wrapperClassName="home-notification__checkbox-label-tooltip"
>
{checkboxElement}
</Tooltip>
) : (
checkboxElement
)}
<label
className="home-notification__checkbox-label"
htmlFor="homeNotification_checkbox"
>
{checkboxText}
</label>
</div>
) : null}
</div>
</div>
)
}

HomeNotification.propTypes = {
acceptText: PropTypes.node,
checkboxText: PropTypes.node,
checkboxTooltipText: PropTypes.node,
classNames: PropTypes.array,
descriptionText: PropTypes.node.isRequired,
ignoreText: PropTypes.node,
Expand Down
36 changes: 36 additions & 0 deletions ui/app/components/app/home-notification/index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,46 @@
color: $white;
}

&__text-link {
@include H7;

color: $primary-blue;
cursor: pointer;
}

.fa-info-circle {
color: #6a737d;
}

& &__checkbox-wrapper {
display: flex;
flex-direction: row;
align-items: center;

@media screen and (max-width: 575px) {
width: 160px;
}
}

& &__checkbox {
width: 12px;
height: 12px;
font-size: 15px;
cursor: pointer;
}

& &__checkbox-label {
@include H7;

color: $white;
margin-left: 10px;
margin-top: 1px;
user-select: none;
-moz-user-select: none;
-webkit-user-select: none;
cursor: pointer;
}

& &__ignore-button {
border-color: #6a737d;
box-sizing: border-box;
Expand Down
40 changes: 29 additions & 11 deletions ui/app/pages/home/home.component.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ export default class Home extends PureComponent {
suggestedTokens: PropTypes.object,
unconfirmedTransactionsCount: PropTypes.number,
shouldShowSeedPhraseReminder: PropTypes.bool.isRequired,
shouldShowWeb3ShimUsageNotification: PropTypes.bool.isRequired,
isPopup: PropTypes.bool,
isNotification: PropTypes.bool.isRequired,
threeBoxSynced: PropTypes.bool,
Expand All @@ -67,6 +66,10 @@ export default class Home extends PureComponent {
swapsFetchParams: PropTypes.object,
swapsEnabled: PropTypes.bool,
isMainnet: PropTypes.bool,
shouldShowWeb3ShimUsageNotification: PropTypes.bool.isRequired,
setWeb3ShimUsageAlertDismissed: PropTypes.func.isRequired,
originOfCurrentTab: PropTypes.string,
disableWeb3ShimUsageAlert: PropTypes.func.isRequired,
}

state = {
Expand Down Expand Up @@ -155,30 +158,45 @@ export default class Home extends PureComponent {
const {
history,
shouldShowSeedPhraseReminder,
shouldShowWeb3ShimUsageNotification,
isPopup,
selectedAddress,
restoreFromThreeBox,
turnThreeBoxSyncingOn,
setShowRestorePromptToFalse,
showRestorePrompt,
threeBoxLastUpdated,
shouldShowWeb3ShimUsageNotification,
setWeb3ShimUsageAlertDismissed,
originOfCurrentTab,
disableWeb3ShimUsageAlert,
} = this.props

return (
<MultipleNotifications>
{shouldShowWeb3ShimUsageNotification ? (
<HomeNotification
descriptionText={t('web3UsageNotification', ['foobar.com'])}
acceptText={t('dismiss')}
onAccept={() => {
console.log('Dismiss!')
descriptionText={t('web3ShimUsageNotification', [
<span
key="web3ShimUsageNotificationLink"
className="home-notification__text-link"
onClick={() =>
// TODO: update this
global.platform.openTab({ url: 'https://metamask.io' })
}
>
{t('here')}
</span>,
])}
ignoreText={t('dismiss')}
onIgnore={(disable) => {
setWeb3ShimUsageAlertDismissed(originOfCurrentTab)
if (disable) {
disableWeb3ShimUsageAlert()
}
}}
// onIgnore={() => {
// console.log('Ignore!')
// }}
// infoText={t('backupApprovalInfo')} // the icon thingy
key="home-web3UsageNotification"
checkboxText={t('dontShowThisAgain')}
checkboxTooltipText={t('canToggleInSettings')}
key="home-web3ShimUsageNotification"
/>
) : null}
{shouldShowSeedPhraseReminder ? (
Expand Down
21 changes: 17 additions & 4 deletions ui/app/pages/home/home.container.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ import {
getCurrentEthBalance,
getFirstPermissionRequest,
getIsMainnet,
getOriginOfCurrentTab,
getTotalUnapprovedCount,
getWeb3ShimUsageStateForCurrentTab,
getWeb3ShimUsageStateForOrigin,
unconfirmedTransactionsCountSelector,
} from '../../selectors'

Expand All @@ -19,6 +20,8 @@ import {
setConnectedStatusPopoverHasBeenShown,
setDefaultHomeActiveTabName,
setSwapsWelcomeMessageHasBeenShown,
setWeb3ShimUsageAlertDismissed,
setAlertEnabledness,
} from '../../store/actions'
import { setThreeBoxLastUpdated } from '../../ducks/app/app'
import { getWeb3ShimUsageAlertEnabledness } from '../../ducks/metamask/metamask'
Expand All @@ -31,7 +34,10 @@ import {
ENVIRONMENT_TYPE_NOTIFICATION,
ENVIRONMENT_TYPE_POPUP,
} from '../../../../app/scripts/lib/enums'
import { WEB3_SHIM_USAGE_ALERT_STATES } from '../../../../shared/constants/alerts'
import {
ALERT_TYPES,
WEB3_SHIM_USAGE_ALERT_STATES,
} from '../../../../shared/constants/alerts'
import Home from './home.component'

const mapStateToProps = (state) => {
Expand Down Expand Up @@ -62,11 +68,12 @@ const mapStateToProps = (state) => {
? firstPermissionsRequest.metadata.id
: null

const originOfCurrentTab = getOriginOfCurrentTab(state)
const shouldShowWeb3ShimUsageNotification =
isPopup &&
getWeb3ShimUsageAlertEnabledness(state) &&
activeTabHasPermissions(state) &&
getWeb3ShimUsageStateForCurrentTab(state) ===
getWeb3ShimUsageStateForOrigin(state, originOfCurrentTab) ===
WEB3_SHIM_USAGE_ALERT_STATES.RECORDED

return {
Expand All @@ -77,7 +84,6 @@ const mapStateToProps = (state) => {
shouldShowSeedPhraseReminder:
seedPhraseBackedUp === false &&
(parseInt(accountBalance, 16) > 0 || tokens.length > 0),
shouldShowWeb3ShimUsageNotification,
isPopup,
isNotification,
threeBoxSynced,
Expand All @@ -93,6 +99,8 @@ const mapStateToProps = (state) => {
swapsFetchParams: swapsState.fetchParams,
showAwaitingSwapScreen: swapsState.routeState === 'awaiting',
isMainnet: getIsMainnet(state),
originOfCurrentTab,
shouldShowWeb3ShimUsageNotification,
}
}

Expand All @@ -115,6 +123,11 @@ const mapDispatchToProps = (dispatch) => ({
onTabClick: (name) => dispatch(setDefaultHomeActiveTabName(name)),
setSwapsWelcomeMessageHasBeenShown: () =>
dispatch(setSwapsWelcomeMessageHasBeenShown()),
setWeb3ShimUsageAlertDismissed: (origin) =>
dispatch(setWeb3ShimUsageAlertDismissed(origin)),
disableWeb3ShimUsageAlert: () => {
dispatch(setAlertEnabledness(ALERT_TYPES.web3ShimUsage, false))
},
})

export default compose(
Expand Down
4 changes: 2 additions & 2 deletions ui/app/selectors/selectors.js
Original file line number Diff line number Diff line change
Expand Up @@ -357,6 +357,6 @@ export function getUSDConversionRate(state) {
return state.metamask.usdConversionRate
}

export function getWeb3ShimUsageStateForCurrentTab(state) {
return state.metamask.web3ShimUsageOrigins[getOriginOfCurrentTab(state)]
export function getWeb3ShimUsageStateForOrigin(state, origin) {
return state.metamask.web3ShimUsageOrigins[origin]
}
12 changes: 8 additions & 4 deletions ui/app/store/actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -2487,12 +2487,16 @@ export function setAlertEnabledness(alertId, enabledness) {
}
}

export async function setUnconnectedAccountAlertShown(origin) {
await promisifiedBackground.setUnconnectedAccountAlertShown(origin)
export function setUnconnectedAccountAlertShown(origin) {
return async () => {
await promisifiedBackground.setUnconnectedAccountAlertShown(origin)
}
}

export async function setWeb3ShimUsageDismissed(origin) {
await promisifiedBackground.setWeb3ShimUsageDismissed(origin)
export function setWeb3ShimUsageAlertDismissed(origin) {
return async () => {
await promisifiedBackground.setWeb3ShimUsageAlertDismissed(origin)
}
}

export function loadingMethodDataStarted() {
Expand Down

0 comments on commit d555463

Please sign in to comment.