diff --git a/test/e2e/helpers.js b/test/e2e/helpers.js index b604a83cdefc..f1769d77593a 100644 --- a/test/e2e/helpers.js +++ b/test/e2e/helpers.js @@ -520,15 +520,11 @@ const onboardingCompleteWalletCreationWithOptOut = async (driver) => { ); await driver.clickElement('[id="basic-configuration-checkbox"]'); await driver.clickElement({ text: 'Turn off', tag: 'button' }); - await driver.clickElement( - '[data-testid="profile-sync-toggle"] .toggle-button', - ); - await driver.clickElement('[data-testid="submit-button"]'); await Promise.all( ( await driver.findClickableElements( - '.toggle-button.toggle-button--on:not([data-testid="basic-functionality-toggle"] .toggle-button):not([data-testid="profile-sync-toggle"] .toggle-button)', + '.toggle-button.toggle-button--on:not([data-testid="basic-functionality-toggle"] .toggle-button)', ) ).map((toggle) => toggle.click()), ); diff --git a/ui/components/multichain/global-menu/global-menu.js b/ui/components/multichain/global-menu/global-menu.js index 7ba0de804919..3841151dd7aa 100644 --- a/ui/components/multichain/global-menu/global-menu.js +++ b/ui/components/multichain/global-menu/global-menu.js @@ -60,6 +60,7 @@ import { ///: BEGIN:ONLY_INCLUDE_IF(snaps) getAnySnapUpdateAvailable, getNotifySnaps, + getUseExternalServices, ///: END:ONLY_INCLUDE_IF } from '../../../selectors'; ///: BEGIN:ONLY_INCLUDE_IF(snaps) @@ -81,6 +82,7 @@ export const GlobalMenu = ({ closeMenu, anchorElement, isOpen }) => { const t = useI18nContext(); const dispatch = useDispatch(); const trackEvent = useContext(MetaMetricsContext); + const basicFunctionality = useSelector(getUseExternalServices); const history = useHistory(); @@ -189,30 +191,31 @@ export const GlobalMenu = ({ closeMenu, anchorElement, isOpen }) => { borderStyle={BorderStyle.none} position={PopoverPosition.BottomEnd} > - <> - handleNotificationsClick()} - > - + handleNotificationsClick()} > - {t('notifications')} - {notificationsCount === 0 && !isMetamaskNotificationFeatureSeen && ( - - )} - - - - - + + {t('notifications')} + {notificationsCount === 0 && + !isMetamaskNotificationFeatureSeen && } + + + + + + )} {account && ( <> void; @@ -31,6 +32,7 @@ export const MetamaskNotificationsProvider: React.FC = ({ children }) => { const isNotificationsEnabled = useSelector( selectIsMetamaskNotificationsEnabled, ); + const basicFunctionality = useSelector(getUseExternalServices); const { listNotifications, notificationsData, isLoading, error } = useListNotifications(); @@ -41,10 +43,10 @@ export const MetamaskNotificationsProvider: React.FC = ({ children }) => { ); useEffect(() => { - if (shouldFetchNotifications) { + if (basicFunctionality && shouldFetchNotifications) { listNotifications(); } - }, [shouldFetchNotifications, listNotifications]); + }, [shouldFetchNotifications, listNotifications, basicFunctionality]); return ( Promise; +export function useSetIsProfileSyncingEnabled(): { + setIsProfileSyncingEnabled: (state: boolean) => Promise; error: string | null; } { const dispatch = useDispatch(); const [error, setError] = useState(null); - const setIsProfileSyncingEnabled = useCallback(async () => { - setError(null); - - try { - await dispatch(setIsProfileSyncingEnabledAction(state)); - } catch (e) { - const errorMessage = - e instanceof Error ? e.message : JSON.stringify(e ?? ''); - setError(errorMessage); - log.error(errorMessage); - throw e; - } - }, [dispatch]); + const setIsProfileSyncingEnabled = useCallback( + async (state: boolean) => { + setError(null); + + try { + await dispatch(setIsProfileSyncingEnabledAction(state)); + } catch (e) { + const errorMessage = + e instanceof Error ? e.message : JSON.stringify(e ?? ''); + setError(errorMessage); + log.error(errorMessage); + } + }, + [dispatch], + ); return { setIsProfileSyncingEnabled, error }; } diff --git a/ui/hooks/metamask-notifications/useSwitchNotifications.test.tsx b/ui/hooks/metamask-notifications/useSwitchNotifications.test.tsx index d0b78f43ced9..b67c2ea80cef 100644 --- a/ui/hooks/metamask-notifications/useSwitchNotifications.test.tsx +++ b/ui/hooks/metamask-notifications/useSwitchNotifications.test.tsx @@ -68,8 +68,8 @@ describe('useSwitchNotifications', () => { ), }); - act(() => { - result.current.onChange(true); + await act(async () => { + await result.current.onChange(true); }); expect(actions.setFeatureAnnouncementsEnabled).toHaveBeenCalledWith(true); @@ -86,8 +86,8 @@ describe('useSwitchNotifications', () => { ), }); - act(() => { - result.current.switchAccountNotifications(['0x123']); + await act(async () => { + await result.current.switchAccountNotifications(['0x123']); }); expect(actions.checkAccountsPresence).toHaveBeenCalledWith(['0x123']); @@ -105,8 +105,8 @@ describe('useSwitchNotifications', () => { }); // Test enabling notifications - act(() => { - result.current.onChange(['0x123'], true); + await act(async () => { + await result.current.onChange(['0x123'], true); }); expect(actions.updateOnChainTriggersByAccount).toHaveBeenCalledWith([ @@ -114,8 +114,8 @@ describe('useSwitchNotifications', () => { ]); // Test disabling notifications - act(() => { - result.current.onChange(['0x123'], false); + await act(async () => { + await result.current.onChange(['0x123'], false); }); expect(actions.deleteOnChainTriggersByAccount).toHaveBeenCalledWith([ diff --git a/ui/pages/onboarding-flow/privacy-settings/privacy-settings.js b/ui/pages/onboarding-flow/privacy-settings/privacy-settings.js index 3f5e0d6dc5ba..30cc64553fcc 100644 --- a/ui/pages/onboarding-flow/privacy-settings/privacy-settings.js +++ b/ui/pages/onboarding-flow/privacy-settings/privacy-settings.js @@ -1,4 +1,4 @@ -import React, { useContext, useState } from 'react'; +import React, { useContext, useState, useEffect } from 'react'; import { useDispatch, useSelector } from 'react-redux'; import { useHistory } from 'react-router-dom'; import { addUrlProtocolPrefix } from '../../../../app/scripts/lib/util'; @@ -65,18 +65,41 @@ import { import IncomingTransactionToggle from '../../../components/app/incoming-trasaction-toggle/incoming-transaction-toggle'; import { Setting } from './setting'; -export default function PrivacySettings() { - const t = useI18nContext(); - const dispatch = useDispatch(); - const history = useHistory(); - +/** + * Profile Syncing Setting props + * + * @param {boolean} basicFunctionalityOnboarding + * @returns props that are used for the profile syncing toggle. + */ +function useProfileSyncingProps(basicFunctionalityOnboarding) { const { setIsProfileSyncingEnabled, error: setIsProfileSyncingEnabledError } = useSetIsProfileSyncingEnabled(); - const { enableProfileSyncing, error: disableProfileSyncingError } = + const { enableProfileSyncing, error: enableProfileSyncingError } = useEnableProfileSyncing(); const profileSyncingError = - setIsProfileSyncingEnabledError || disableProfileSyncingError; + setIsProfileSyncingEnabledError || enableProfileSyncingError; + + const isProfileSyncingEnabled = useSelector(selectIsProfileSyncingEnabled); + + // Effect - toggle profile syncing on/off based on basic functionality toggle + useEffect(() => { + const changeProfileSync = basicFunctionalityOnboarding === true; + setIsProfileSyncingEnabled(changeProfileSync); + }, [basicFunctionalityOnboarding, setIsProfileSyncingEnabled]); + + return { + setIsProfileSyncingEnabled, + enableProfileSyncing, + profileSyncingError, + isProfileSyncingEnabled, + }; +} + +export default function PrivacySettings() { + const t = useI18nContext(); + const dispatch = useDispatch(); + const history = useHistory(); const defaultState = useSelector((state) => state.metamask); const { @@ -91,7 +114,6 @@ export default function PrivacySettings() { useTransactionSimulations, } = defaultState; const petnamesEnabled = useSelector(getPetnamesEnabled); - const isProfileSyncingEnabled = useSelector(selectIsProfileSyncingEnabled); const participateInMetaMetrics = useSelector(selectParticipateInMetaMetrics); const [usePhishingDetection, setUsePhishingDetection] = @@ -124,6 +146,10 @@ export default function PrivacySettings() { getExternalServicesOnboardingToggleState, ); + const profileSyncingProps = useProfileSyncingProps( + externalServicesOnboardingToggleState, + ); + const handleSubmit = () => { dispatch(toggleExternalServices(externalServicesOnboardingToggleState)); dispatch(setUsePhishDetect(usePhishingDetection)); @@ -138,10 +164,16 @@ export default function PrivacySettings() { setUseTransactionSimulations(isTransactionSimulationsEnabled); dispatch(setPetnamesEnabled(turnOnPetnames)); + // Profile Syncing Setup if (externalServicesOnboardingToggleState) { - if (!isProfileSyncingEnabled && participateInMetaMetrics) { + if ( + profileSyncingProps.isProfileSyncingEnabled || + participateInMetaMetrics + ) { dispatch(performSignIn()); } + } else { + profileSyncingProps.setIsProfileSyncingEnabled(false); } if (ipfsURL && !ipfsError) { @@ -160,7 +192,7 @@ export default function PrivacySettings() { }); const eventName = - isProfileSyncingEnabled || participateInMetaMetrics + profileSyncingProps.isProfileSyncingEnabled || participateInMetaMetrics ? MetaMetricsEventName.OnboardingWalletAdvancedSettingsWithAuthenticating : MetaMetricsEventName.OnboardingWalletAdvancedSettingsWithoutAuthenticating; @@ -168,7 +200,7 @@ export default function PrivacySettings() { category: MetaMetricsEventCategory.Onboarding, event: eventName, properties: { - isProfileSyncingEnabled, + isProfileSyncingEnabled: profileSyncingProps.isProfileSyncingEnabled, participateInMetaMetrics, }, }); @@ -177,12 +209,12 @@ export default function PrivacySettings() { }; const handleUseProfileSync = async () => { - if (isProfileSyncingEnabled) { + if (profileSyncingProps.isProfileSyncingEnabled) { dispatch( showModal({ name: 'CONFIRM_TURN_OFF_PROFILE_SYNCING', turnOffProfileSyncing: () => { - setIsProfileSyncingEnabled(false); + profileSyncingProps.setIsProfileSyncingEnabled(false); trackEvent({ category: MetaMetricsEventCategory.Onboarding, event: @@ -195,7 +227,7 @@ export default function PrivacySettings() { }), ); } else { - await enableProfileSyncing(); + profileSyncingProps.setIsProfileSyncingEnabled(true); } }; @@ -260,7 +292,8 @@ export default function PrivacySettings() { , ])} /> - {profileSyncingError && ( + {profileSyncingProps.profileSyncingError && ( { const t = useI18nContext(); @@ -43,6 +44,7 @@ export const Setting = ({ onToggle={(val) => setValue(!val)} offLabel={t('off')} onLabel={t('on')} + disabled={disabled} /> ) : null} @@ -57,4 +59,5 @@ Setting.propTypes = { description: PropTypes.oneOfType([PropTypes.object, PropTypes.string]), showToggle: PropTypes.bool, dataTestId: PropTypes.string, + disabled: PropTypes.bool, }; diff --git a/ui/pages/settings/security-tab/__snapshots__/security-tab.test.js.snap b/ui/pages/settings/security-tab/__snapshots__/security-tab.test.js.snap index 08552fa9d90c..5d0a1853360b 100644 --- a/ui/pages/settings/security-tab/__snapshots__/security-tab.test.js.snap +++ b/ui/pages/settings/security-tab/__snapshots__/security-tab.test.js.snap @@ -241,7 +241,7 @@ exports[`Security Tab should match snapshot 1`] = ` class="settings-page__content-item-col" >