mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-12-23 09:52:26 +01:00
b73f543b23
* Add 'What's New' notification popup * Move selectors from shared/notifications into ui/ directory * Use keys for localized message in whats new notifications objects, to ensure notifications will be translated. * Remove unused swaps intro popup locale messages * Fix keys of whats new notification locales * Remove notifications messages and descriptions from comment in shared/notifications * Move notifcationActionFunctions to shared/notifications and make it stateless * Get notification data from constants instead of state in whats-new-popup * Code cleanup * Fix build quote reference to swapsEthToken, broken during rebase * Rename notificationFilters to notificationToExclude to clarify its purpose * Documentation for getSortedNotificationsToShow * Move notification action functions from shared/ to whats-new-popup.js * Stop setting swapsWelcomeMessageHasBeenShown to state in app-state controller * Update e2e tests for whats new popup changes * Updating migration files * Addressing feedback part 1 * Addressing feedback part 2 * Remove unnecessary div in whats-new-popup * Change getNotificationsToExclude to getNotificationsToInclude for use in the getSortedNotificationsToShow selector * Delete intro-popup directory and test files * Lint fix * Add notifiction state to address-entry fixture * Use two separate functions for rendering first and subsequent notifications in the whats-new-popup * Ensure that string literals are passed to t for whats new popup text * Update import-ui fixtures to include notificaiton controller state * Remove unnecessary, accidental change confirm-approve * Remove swaps notification in favour of mobile swaps as first notifcation and TBD 3rd notification * Update whats-new-popup to use intersection observer api to detect if notification has been seen * Add notifications to send-edit and threebox e2e test fixtures * Update ui/app/selectors/selectors.js Co-authored-by: Mark Stacey <markjstacey@gmail.com> * Update ui/app/selectors/selectors.js Co-authored-by: Mark Stacey <markjstacey@gmail.com> * Clean up locale code for whats-new-popup notifications * Disconnect observers in whats-new-popup when their callback is first called * Add test case for migration 58 for when the AppStateController does not exist * Rename popover components containerRef to popoverWrapRef * Fix messages.json * Update notification messages and images * Rename popoverWrapRef -> popoverRef in whats-new-popup and popover.component * Only create one observer, and only after images have loaded, in whats-new-popup * Set width and height on whats-new-popup image, instead of setting state on img load * Update ui/app/components/app/whats-new-popup/whats-new-popup.js Co-authored-by: Mark Stacey <markjstacey@gmail.com> * Code clean up in whats new popup re: notification rendering and action functions * Code cleanup in render notification functions of whats-new-popup * Update ui/app/components/app/whats-new-popup/whats-new-popup.js Co-authored-by: Mark Stacey <markjstacey@gmail.com> * lint fix * Update and localize notification dates * Clean up date code in shred/notifications/index.js Co-authored-by: ryanml <ryanlanese@gmail.com> Co-authored-by: Mark Stacey <markjstacey@gmail.com>
162 lines
4.1 KiB
JavaScript
162 lines
4.1 KiB
JavaScript
import EventEmitter from 'events';
|
|
import { ObservableStore } from '@metamask/obs-store';
|
|
import { METAMASK_CONTROLLER_EVENTS } from '../metamask-controller';
|
|
|
|
export default class AppStateController extends EventEmitter {
|
|
/**
|
|
* @constructor
|
|
* @param {Object} opts
|
|
*/
|
|
constructor(opts = {}) {
|
|
const {
|
|
addUnlockListener,
|
|
isUnlocked,
|
|
initState,
|
|
onInactiveTimeout,
|
|
showUnlockRequest,
|
|
preferencesStore,
|
|
} = opts;
|
|
super();
|
|
|
|
this.onInactiveTimeout = onInactiveTimeout || (() => undefined);
|
|
this.store = new ObservableStore({
|
|
timeoutMinutes: 0,
|
|
connectedStatusPopoverHasBeenShown: true,
|
|
defaultHomeActiveTabName: null,
|
|
...initState,
|
|
});
|
|
this.timer = null;
|
|
|
|
this.isUnlocked = isUnlocked;
|
|
this.waitingForUnlock = [];
|
|
addUnlockListener(this.handleUnlock.bind(this));
|
|
|
|
this._showUnlockRequest = showUnlockRequest;
|
|
|
|
preferencesStore.subscribe(({ preferences }) => {
|
|
const currentState = this.store.getState();
|
|
if (currentState.timeoutMinutes !== preferences.autoLockTimeLimit) {
|
|
this._setInactiveTimeout(preferences.autoLockTimeLimit);
|
|
}
|
|
});
|
|
|
|
const { preferences } = preferencesStore.getState();
|
|
this._setInactiveTimeout(preferences.autoLockTimeLimit);
|
|
}
|
|
|
|
/**
|
|
* Get a Promise that resolves when the extension is unlocked.
|
|
* This Promise will never reject.
|
|
*
|
|
* @param {boolean} shouldShowUnlockRequest - Whether the extension notification
|
|
* popup should be opened.
|
|
* @returns {Promise<void>} A promise that resolves when the extension is
|
|
* unlocked, or immediately if the extension is already unlocked.
|
|
*/
|
|
getUnlockPromise(shouldShowUnlockRequest) {
|
|
return new Promise((resolve) => {
|
|
if (this.isUnlocked()) {
|
|
resolve();
|
|
} else {
|
|
this.waitForUnlock(resolve, shouldShowUnlockRequest);
|
|
}
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Adds a Promise's resolve function to the waitingForUnlock queue.
|
|
* Also opens the extension popup if specified.
|
|
*
|
|
* @param {Promise.resolve} resolve - A Promise's resolve function that will
|
|
* be called when the extension is unlocked.
|
|
* @param {boolean} shouldShowUnlockRequest - Whether the extension notification
|
|
* popup should be opened.
|
|
*/
|
|
waitForUnlock(resolve, shouldShowUnlockRequest) {
|
|
this.waitingForUnlock.push({ resolve });
|
|
this.emit(METAMASK_CONTROLLER_EVENTS.UPDATE_BADGE);
|
|
if (shouldShowUnlockRequest) {
|
|
this._showUnlockRequest();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Drains the waitingForUnlock queue, resolving all the related Promises.
|
|
*/
|
|
handleUnlock() {
|
|
if (this.waitingForUnlock.length > 0) {
|
|
while (this.waitingForUnlock.length > 0) {
|
|
this.waitingForUnlock.shift().resolve();
|
|
}
|
|
this.emit(METAMASK_CONTROLLER_EVENTS.UPDATE_BADGE);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Sets the default home tab
|
|
* @param {string} [defaultHomeActiveTabName] - the tab name
|
|
*/
|
|
setDefaultHomeActiveTabName(defaultHomeActiveTabName) {
|
|
this.store.updateState({
|
|
defaultHomeActiveTabName,
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Record that the user has seen the connected status info popover
|
|
*/
|
|
setConnectedStatusPopoverHasBeenShown() {
|
|
this.store.updateState({
|
|
connectedStatusPopoverHasBeenShown: true,
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Sets the last active time to the current time
|
|
* @returns {void}
|
|
*/
|
|
setLastActiveTime() {
|
|
this._resetTimer();
|
|
}
|
|
|
|
/**
|
|
* Sets the inactive timeout for the app
|
|
* @param {number} timeoutMinutes - the inactive timeout in minutes
|
|
* @returns {void}
|
|
* @private
|
|
*/
|
|
_setInactiveTimeout(timeoutMinutes) {
|
|
this.store.updateState({
|
|
timeoutMinutes,
|
|
});
|
|
|
|
this._resetTimer();
|
|
}
|
|
|
|
/**
|
|
* Resets the internal inactive timer
|
|
*
|
|
* If the {@code timeoutMinutes} state is falsy (i.e., zero) then a new
|
|
* timer will not be created.
|
|
*
|
|
* @returns {void}
|
|
* @private
|
|
*/
|
|
_resetTimer() {
|
|
const { timeoutMinutes } = this.store.getState();
|
|
|
|
if (this.timer) {
|
|
clearTimeout(this.timer);
|
|
}
|
|
|
|
if (!timeoutMinutes) {
|
|
return;
|
|
}
|
|
|
|
this.timer = setTimeout(
|
|
() => this.onInactiveTimeout(),
|
|
timeoutMinutes * 60 * 1000,
|
|
);
|
|
}
|
|
}
|