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 }); } }