diff --git a/app/_locales/en/messages.json b/app/_locales/en/messages.json index 18821dfe1..f947c9e5c 100644 --- a/app/_locales/en/messages.json +++ b/app/_locales/en/messages.json @@ -2,6 +2,9 @@ "migrateSai": { "message": "A message from Maker: The new Multi-Collateral Dai token has been released. Your old tokens are now called Sai. Please upgrade your Sai tokens to the new Dai." }, + "migrateSaiInfo": { + "message": "To dismiss this notification you can migrate your tokens or hide SAI from the token list." + }, "migrate": { "message": "Migrate" }, diff --git a/app/scripts/controllers/app-state.js b/app/scripts/controllers/app-state.js index 9533fd458..8d67874ad 100644 --- a/app/scripts/controllers/app-state.js +++ b/app/scripts/controllers/app-state.js @@ -13,6 +13,7 @@ class AppStateController { this.onInactiveTimeout = onInactiveTimeout || (() => {}) this.store = new ObservableStore(extend({ timeoutMinutes: 0, + mkrMigrationReminderTimestamp: null, }, initState)) this.timer = null @@ -23,6 +24,12 @@ class AppStateController { this._setInactiveTimeout(preferences.autoLogoutTimeLimit) } + setMkrMigrationReminderTimestamp (timestamp) { + this.store.updateState({ + mkrMigrationReminderTimestamp: timestamp, + }) + } + /** * Sets the last active time to the current time * @return {void} diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 1c607a4c6..14caf0706 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -508,6 +508,7 @@ module.exports = class MetamaskController extends EventEmitter { // AppStateController setLastActiveTime: nodeify(this.appStateController.setLastActiveTime, this.appStateController), + setMkrMigrationReminderTimestamp: nodeify(this.appStateController.setMkrMigrationReminderTimestamp, this.appStateController), // EnsController tryReverseResolveAddress: nodeify(this.ensController.reverseResolveAddress, this.ensController), diff --git a/ui/app/components/app/dai-migration-component/dai-migration-notification.component.js b/ui/app/components/app/dai-migration-component/dai-migration-notification.component.js index eebe4296a..d26358df7 100644 --- a/ui/app/components/app/dai-migration-component/dai-migration-notification.component.js +++ b/ui/app/components/app/dai-migration-component/dai-migration-notification.component.js @@ -1,3 +1,4 @@ +import { DateTime } from 'luxon' import React, { PureComponent } from 'react' import PropTypes from 'prop-types' import HomeNotification from '../home-notification' @@ -8,18 +9,37 @@ export default class DaiV1MigrationNotification extends PureComponent { } static defaultProps = { + mkrMigrationReminderTimestamp: null, string: '', symbol: '', } static propTypes = { + setMkrMigrationReminderTimestamp: PropTypes.func.isRequired, + mkrMigrationReminderTimestamp: PropTypes.string, string: PropTypes.string, symbol: PropTypes.string, } + remindMeLater = () => { + const nextWeek = DateTime.utc().plus({ + days: 7, + }) + this.props.setMkrMigrationReminderTimestamp(nextWeek.toString()) + } + render () { const { t } = this.context - const { string: balanceString, symbol } = this.props + const { mkrMigrationReminderTimestamp, string: balanceString, symbol } = this.props + + if (mkrMigrationReminderTimestamp) { + const reminderDateTime = DateTime.fromISO(mkrMigrationReminderTimestamp, { + zone: 'UTC', + }) + if (reminderDateTime > DateTime.utc()) { + return null + } + } if (!balanceString || !symbol) { return null @@ -31,15 +51,27 @@ export default class DaiV1MigrationNotification extends PureComponent { return ( + {t('migrateSai')} +   + { + window.open('https://blog.makerdao.com/multi-collateral-dai-is-live/', '_blank', 'noopener') + }} + > + {t('learnMore')}. + + + )} acceptText={t('migrate')} onAccept={() => { window.open('https://migrate.makerdao.com', '_blank', 'noopener') }} - ignoreText={t('learnMore')} - onIgnore={() => { - window.open('https://blog.makerdao.com/multi-collateral-dai-is-live/', '_blank', 'noopener') - }} + ignoreText={t('remindMeLater')} + onIgnore={this.remindMeLater} + infoText={t('migrateSaiInfo')} /> ) } diff --git a/ui/app/components/app/dai-migration-component/dai-migration-notification.container.js b/ui/app/components/app/dai-migration-component/dai-migration-notification.container.js index 1ea1d2fe4..175083bce 100644 --- a/ui/app/components/app/dai-migration-component/dai-migration-notification.container.js +++ b/ui/app/components/app/dai-migration-component/dai-migration-notification.container.js @@ -3,18 +3,32 @@ import { compose } from 'recompose' import DaiMigrationNotification from './dai-migration-notification.component' import withTokenTracker from '../../../helpers/higher-order-components/with-token-tracker' import { getSelectedAddress, getDaiV1Token } from '../../../selectors/selectors' +import { setMkrMigrationReminderTimestamp } from '../../../store/actions' const mapStateToProps = (state) => { + const { + metamask: { + mkrMigrationReminderTimestamp, + }, + } = state + const userAddress = getSelectedAddress(state) const oldDai = getDaiV1Token(state) return { + mkrMigrationReminderTimestamp, userAddress, token: oldDai, } } +const mapDispatchToProps = (dispatch) => { + return { + setMkrMigrationReminderTimestamp: (t) => dispatch(setMkrMigrationReminderTimestamp(t)), + } +} + export default compose( - connect(mapStateToProps), + connect(mapStateToProps, mapDispatchToProps), withTokenTracker, )(DaiMigrationNotification) diff --git a/ui/app/components/app/home-notification/home-notification.component.js b/ui/app/components/app/home-notification/home-notification.component.js index cc86ef6d8..d3d0a0961 100644 --- a/ui/app/components/app/home-notification/home-notification.component.js +++ b/ui/app/components/app/home-notification/home-notification.component.js @@ -17,12 +17,12 @@ export default class HomeNotification extends PureComponent { } static propTypes = { - acceptText: PropTypes.string.isRequired, + acceptText: PropTypes.node.isRequired, onAccept: PropTypes.func, - ignoreText: PropTypes.string, + ignoreText: PropTypes.node, onIgnore: PropTypes.func, - descriptionText: PropTypes.string.isRequired, - infoText: PropTypes.string, + descriptionText: PropTypes.node.isRequired, + infoText: PropTypes.node, classNames: PropTypes.array, } diff --git a/ui/app/store/actions.js b/ui/app/store/actions.js index f76024590..2642e89e9 100644 --- a/ui/app/store/actions.js +++ b/ui/app/store/actions.js @@ -367,6 +367,7 @@ var actions = { // AppStateController-related actions SET_LAST_ACTIVE_TIME: 'SET_LAST_ACTIVE_TIME', setLastActiveTime, + setMkrMigrationReminderTimestamp, getContractMethodData, loadingMethoDataStarted, @@ -2755,6 +2756,16 @@ function setLastActiveTime () { } } +function setMkrMigrationReminderTimestamp (timestamp) { + return (dispatch) => { + background.setMkrMigrationReminderTimestamp(timestamp, (err) => { + if (err) { + return dispatch(actions.displayWarning(err.message)) + } + }) + } +} + function loadingMethoDataStarted () { return { type: actions.LOADING_METHOD_DATA_STARTED,