import { ObservableStore } from '@metamask/obs-store' import { TOGGLEABLE_ALERT_TYPES, WEB3_SHIM_USAGE_ALERT_STATES, } from '../../../shared/constants/alerts' /** * @typedef {Object} AlertControllerInitState * @property {Object} alertEnabledness - A map of alerts IDs to booleans, where * `true` indicates that the alert is enabled and shown, and `false` the opposite. * @property {Object} unconnectedAccountAlertShownOrigins - A map of origin * strings to booleans indicating whether the "switch to connected" alert has * been shown (`true`) or otherwise (`false`). */ /** * @typedef {Object} AlertControllerOptions * @property {AlertControllerInitState} initState - The initial controller state */ const defaultState = { alertEnabledness: TOGGLEABLE_ALERT_TYPES.reduce( (alertEnabledness, alertType) => { alertEnabledness[alertType] = true return alertEnabledness }, {}, ), unconnectedAccountAlertShownOrigins: {}, web3ShimUsageOrigins: {}, } /** * Controller responsible for maintaining alert-related state. */ export default class AlertController { /** * @constructor * @param {AlertControllerOptions} [opts] - Controller configuration parameters */ constructor(opts = {}) { const { initState = {}, preferencesStore } = opts const state = { ...defaultState, alertEnabledness: { ...defaultState.alertEnabledness, ...initState.alertEnabledness, }, } this.store = new ObservableStore(state) this.selectedAddress = preferencesStore.getState().selectedAddress preferencesStore.subscribe(({ selectedAddress }) => { const currentState = this.store.getState() if ( currentState.unconnectedAccountAlertShownOrigins && this.selectedAddress !== selectedAddress ) { this.selectedAddress = selectedAddress this.store.updateState({ unconnectedAccountAlertShownOrigins: {} }) } }) } setAlertEnabledness(alertId, enabledness) { let { alertEnabledness } = this.store.getState() alertEnabledness = { ...alertEnabledness } alertEnabledness[alertId] = enabledness this.store.updateState({ alertEnabledness }) } /** * Sets the "switch to connected" alert as shown for the given origin * @param {string} origin - The origin the alert has been shown for */ setUnconnectedAccountAlertShown(origin) { let { unconnectedAccountAlertShownOrigins } = this.store.getState() unconnectedAccountAlertShownOrigins = { ...unconnectedAccountAlertShownOrigins, } unconnectedAccountAlertShownOrigins[origin] = true this.store.updateState({ unconnectedAccountAlertShownOrigins }) } /** * Gets the web3 shim usage state for the given origin. * * @param {string} origin - The origin to get the web3 shim usage state for. * @returns {undefined | 1 | 2} The web3 shim usage state for the given * origin, or undefined. */ getWeb3ShimUsageState(origin) { return this.store.getState().web3ShimUsageOrigins[origin] } /** * Sets the web3 shim usage state for the given origin to RECORDED. * * @param {string} origin - The origin the that used the web3 shim. */ setWeb3ShimUsageRecorded(origin) { this._setWeb3ShimUsageState(origin, WEB3_SHIM_USAGE_ALERT_STATES.RECORDED) } /** * Sets the web3 shim usage state for the given origin to DISMISSED. * * @param {string} origin - The origin that the web3 shim notification was * dismissed for. */ setWeb3ShimUsageAlertDismissed(origin) { this._setWeb3ShimUsageState(origin, WEB3_SHIM_USAGE_ALERT_STATES.DISMISSED) } /** * @private * @param {string} origin - The origin to set the state for. * @param {number} value - The state value to set. */ _setWeb3ShimUsageState(origin, value) { let { web3ShimUsageOrigins } = this.store.getState() web3ShimUsageOrigins = { ...web3ShimUsageOrigins, } web3ShimUsageOrigins[origin] = value this.store.updateState({ web3ShimUsageOrigins }) } }