Skip to content

Commit

Permalink
refactor: routes.component.js and creation of ToastMaster (#27735)
Browse files Browse the repository at this point in the history
## **Description**

This PR is part of the larger effort to add `React.lazy` to routes.

I would be very surprised if I did not break functionality somewhere, as
this was a large and tough refactor. It needs some good QA, and Harika
has been doing some testing that has passed.

Summary of what I did:
- Pulled all Toast-related logic out of routes.component.js and into the
new ToastMaster
- Pulled everything else I could pull out into routes-helpers.js
- Moved things out of the general selectors.js and actions.ts into
toast-master-selectors.ts
- Simplification of some Pointless Thunks™

For later PRs:
- Convert routes.component.js to TypeScript
- Convert routes.component.js to Hooks
- Convert routes.component.js to react-router v6
- Eliminate routes.container.js

[![Open in GitHub
Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/27735?quickstart=1)

## **Related issues**

Progresses: MetaMask/MetaMask-planning#2898

## **Manual testing steps**

Test all the Routes and all the Toasts

## **Screenshots/Recordings**
### **Before**
### **After**
## **Pre-merge author checklist**

- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask
Extension Coding
Standards](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I’ve included tests if applicable
- [x] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I’ve applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.
  • Loading branch information
HowardBraham authored Oct 22, 2024
1 parent eb77786 commit a1a62aa
Show file tree
Hide file tree
Showing 12 changed files with 934 additions and 867 deletions.
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import React from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { BannerAlert } from '../../../../component-library';
import { useI18nContext } from '../../../../../hooks/useI18nContext';
import { getOpenSeaEnabled } from '../../../../../selectors';
import {
detectNfts,
setOpenSeaEnabled,
setShowNftDetectionEnablementToast,
setUseNftDetection,
} from '../../../../../store/actions';
import { getOpenSeaEnabled } from '../../../../../selectors';
import { BannerAlert } from '../../../../component-library';
import { setShowNftDetectionEnablementToast } from '../../../toast-master/utils';

export default function NFTsDetectionNoticeNFTsTab() {
const t = useI18nContext();
Expand Down
108 changes: 108 additions & 0 deletions ui/components/app/toast-master/selectors.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
import { InternalAccount, isEvmAccountType } from '@metamask/keyring-api';
import { getAlertEnabledness } from '../../../ducks/metamask/metamask';
import { PRIVACY_POLICY_DATE } from '../../../helpers/constants/privacy-policy';
import {
SURVEY_DATE,
SURVEY_END_TIME,
SURVEY_START_TIME,
} from '../../../helpers/constants/survey';
import { getPermittedAccountsForCurrentTab } from '../../../selectors';
import { MetaMaskReduxState } from '../../../store/store';
import { getIsPrivacyToastRecent } from './utils';

// TODO: get this into one of the larger definitions of state type
type State = Omit<MetaMaskReduxState, 'appState'> & {
appState: {
showNftDetectionEnablementToast?: boolean;
};
metamask: {
newPrivacyPolicyToastClickedOrClosed?: boolean;
newPrivacyPolicyToastShownDate?: number;
onboardingDate?: number;
showNftDetectionEnablementToast?: boolean;
surveyLinkLastClickedOrClosed?: number;
switchedNetworkNeverShowMessage?: boolean;
};
};

/**
* Determines if the survey toast should be shown based on the current time, survey start and end times, and whether the survey link was last clicked or closed.
*
* @param state - The application state containing the necessary survey data.
* @returns True if the current time is between the survey start and end times and the survey link was not last clicked or closed. False otherwise.
*/
export function selectShowSurveyToast(state: State): boolean {
if (state.metamask?.surveyLinkLastClickedOrClosed) {
return false;
}

const startTime = new Date(`${SURVEY_DATE} ${SURVEY_START_TIME}`).getTime();
const endTime = new Date(`${SURVEY_DATE} ${SURVEY_END_TIME}`).getTime();
const now = Date.now();

return now > startTime && now < endTime;
}

/**
* Determines if the privacy policy toast should be shown based on the current date and whether the new privacy policy toast was clicked or closed.
*
* @param state - The application state containing the privacy policy data.
* @returns Boolean is True if the toast should be shown, and the number is the date the toast was last shown.
*/
export function selectShowPrivacyPolicyToast(state: State): {
showPrivacyPolicyToast: boolean;
newPrivacyPolicyToastShownDate?: number;
} {
const {
newPrivacyPolicyToastClickedOrClosed,
newPrivacyPolicyToastShownDate,
onboardingDate,
} = state.metamask || {};
const newPrivacyPolicyDate = new Date(PRIVACY_POLICY_DATE);
const currentDate = new Date(Date.now());

const showPrivacyPolicyToast =
!newPrivacyPolicyToastClickedOrClosed &&
currentDate >= newPrivacyPolicyDate &&
getIsPrivacyToastRecent(newPrivacyPolicyToastShownDate) &&
// users who onboarded before the privacy policy date should see the notice
// and
// old users who don't have onboardingDate set should see the notice
(!onboardingDate || onboardingDate < newPrivacyPolicyDate.valueOf());

return { showPrivacyPolicyToast, newPrivacyPolicyToastShownDate };
}

export function selectNftDetectionEnablementToast(state: State): boolean {
return Boolean(state.appState?.showNftDetectionEnablementToast);
}

// If there is more than one connected account to activeTabOrigin,
// *BUT* the current account is not one of them, show the banner
export function selectShowConnectAccountToast(
state: State,
account: InternalAccount,
): boolean {
const allowShowAccountSetting = getAlertEnabledness(state).unconnectedAccount;
const connectedAccounts = getPermittedAccountsForCurrentTab(state);
const isEvmAccount = isEvmAccountType(account?.type);

return (
allowShowAccountSetting &&
account &&
state.activeTab?.origin &&
isEvmAccount &&
connectedAccounts.length > 0 &&
!connectedAccounts.some((address) => address === account.address)
);
}

/**
* Retrieves user preference to never see the "Switched Network" toast
*
* @param state - Redux state object.
* @returns Boolean preference value
*/
export function selectSwitchedNetworkNeverShowMessage(state: State): boolean {
return Boolean(state.metamask.switchedNetworkNeverShowMessage);
}
Loading

0 comments on commit a1a62aa

Please sign in to comment.