diff --git a/app/component-library/components/Navigation/TabBar/TabBar.tsx b/app/component-library/components/Navigation/TabBar/TabBar.tsx index ba51d756b88..c9658dab766 100644 --- a/app/component-library/components/Navigation/TabBar/TabBar.tsx +++ b/app/component-library/components/Navigation/TabBar/TabBar.tsx @@ -34,13 +34,12 @@ const TabBar = ({ state, descriptors, navigation }: TabBarProps) => { * Current onboarding wizard step */ const wizardStep = useSelector((reduxState: any) => reduxState.wizard.step); - /** * Return current step of onboarding wizard if not step 5 nor 0 */ const renderOnboardingWizard = useCallback( () => - [4, 5].includes(wizardStep) && ( + [4, 5, 6].includes(wizardStep) && ( ), [navigation, wizardStep], diff --git a/app/components/UI/Navbar/index.js b/app/components/UI/Navbar/index.js index 3a6578f622f..d9e53a1f99f 100644 --- a/app/components/UI/Navbar/index.js +++ b/app/components/UI/Navbar/index.js @@ -90,13 +90,15 @@ const styles = StyleSheet.create({ paddingVertical: Device.isAndroid() ? 14 : 8, }, infoButton: { + paddingRight: Device.isAndroid() ? 0 : 18, + marginTop: 5, }, disabled: { opacity: 0.3, }, leftButtonContainer: { - marginRight: Device.isAndroid() ? 22 : 12, + marginRight: 12, flexDirection: 'row', alignItems: 'flex-end', }, diff --git a/app/components/UI/OnboardingWizard/Coachmark/__snapshots__/index.test.tsx.snap b/app/components/UI/OnboardingWizard/Coachmark/__snapshots__/index.test.tsx.snap index c1844d8a260..9d504f204a5 100644 --- a/app/components/UI/OnboardingWizard/Coachmark/__snapshots__/index.test.tsx.snap +++ b/app/components/UI/OnboardingWizard/Coachmark/__snapshots__/index.test.tsx.snap @@ -159,7 +159,7 @@ exports[`Coachmark should render correctly 1`] = ` } > 1 - /5 + /6 {currentStep !== 0 && ( - {currentStep}/5 + {currentStep}/6 )} diff --git a/app/components/UI/OnboardingWizard/Step1/index.js b/app/components/UI/OnboardingWizard/Step1/index.js index cc3ee2ab591..f711969658a 100644 --- a/app/components/UI/OnboardingWizard/Step1/index.js +++ b/app/components/UI/OnboardingWizard/Step1/index.js @@ -29,7 +29,7 @@ const styles = StyleSheet.create({ position: 'absolute', left: 0, right: 0, - bottom: Device.isIphoneX() ? 80 : Device.isIos() ? 40 : 60, + bottom: Device.isIphoneX() ? 80 : Device.isIos() ? 40 : 64, }, }); diff --git a/app/components/UI/OnboardingWizard/Step2/index.js b/app/components/UI/OnboardingWizard/Step2/index.js index 3bce98fe7d9..2e4f0a8ba6f 100644 --- a/app/components/UI/OnboardingWizard/Step2/index.js +++ b/app/components/UI/OnboardingWizard/Step2/index.js @@ -1,19 +1,20 @@ -import React, { PureComponent } from 'react'; +import React, { useCallback, useEffect, useState } from 'react'; import PropTypes from 'prop-types'; import { connect } from 'react-redux'; import { Platform, StyleSheet, Text, View } from 'react-native'; -import Coachmark from '../Coachmark'; import setOnboardingWizardStep from '../../../../actions/wizard'; import { strings } from '../../../../../locales/i18n'; +import Coachmark from '../Coachmark'; + import onboardingStyles from './../styles'; import { MetaMetricsEvents, ONBOARDING_WIZARD_STEP_DESCRIPTION, } from '../../../../core/Analytics'; -import { mockTheme, ThemeContext } from '../../../../util/theme'; +import { useTheme } from '../../../../util/theme'; import generateTestId from '../../../../../wdio/utils/generateTestId'; import { ONBOARDING_WIZARD_SECOND_STEP_CONTENT_ID } from '../../../../../wdio/screen-objects/testIDs/Components/OnboardingWizard.testIds'; -import { withMetricsAwareness } from '../../../../components/hooks/useMetrics'; +import { useMetrics } from '../../../hooks/useMetrics'; const styles = StyleSheet.create({ main: { @@ -27,95 +28,59 @@ const styles = StyleSheet.create({ }, }); -class Step2 extends PureComponent { - static propTypes = { - /** - * Dispatch set onboarding wizard step - */ - setOnboardingWizardStep: PropTypes.func, - /** - * Coachmark ref to get position - */ - coachmarkRef: PropTypes.object, - /** - * Callback called when closing step - */ - onClose: PropTypes.func, - /** - * Metrics injected by withMetricsAwareness HOC - */ - metrics: PropTypes.object, - }; - - state = { - coachmarkTop: 0, - }; +const Step2 = ({ setOnboardingWizardStep, coachmarkRef, onClose }) => { + const { colors } = useTheme(); + const { trackEvent } = useMetrics(); - componentDidMount = () => { - this.getPosition(this.props.coachmarkRef.yourAccountRef); - }; + const [coachmarkTop, setCoachmarkTop] = useState(0); - /** - * If component ref defined, calculate its position and position coachmark accordingly - */ - getPosition = (ref) => { - ref && - ref.current && - ref.current.measure((fx, fy, width, height, px, py) => { - this.setState({ - coachmarkTop: py + height, - }); - }); - }; + const handleLayout = useCallback(() => { + const yourAccRef = coachmarkRef.yourAccountRef?.current; + if (!yourAccRef) return; - /** - * Dispatches 'setOnboardingWizardStep' with next step - */ - onNext = () => { - const { setOnboardingWizardStep } = this.props; - setOnboardingWizardStep && setOnboardingWizardStep(3); - this.props.metrics.trackEvent( - MetaMetricsEvents.ONBOARDING_TOUR_STEP_COMPLETED, - { - tutorial_step_count: 2, - tutorial_step_name: ONBOARDING_WIZARD_STEP_DESCRIPTION[2], + yourAccRef.measure( + ( + accActionsFx, + accActionsFy, + accActionsWidth, + accActionsHeight, + accActionsPageX, + accActionsPageY, + ) => { + const top = accActionsHeight + accActionsPageY; + setCoachmarkTop(top); }, ); + }, [coachmarkRef.yourAccountRef]); + + useEffect(() => { + handleLayout(); + }, [handleLayout]); + + const onNext = () => { + setOnboardingWizardStep && setOnboardingWizardStep(3); + trackEvent(MetaMetricsEvents.ONBOARDING_TOUR_STEP_COMPLETED, { + tutorial_step_count: 2, + tutorial_step_name: ONBOARDING_WIZARD_STEP_DESCRIPTION[2], + }); }; - /** - * Dispatches 'setOnboardingWizardStep' with back step - */ - onBack = () => { - const { setOnboardingWizardStep } = this.props; + const onBack = () => { setOnboardingWizardStep && setOnboardingWizardStep(1); - this.props.metrics.trackEvent( - MetaMetricsEvents.ONBOARDING_TOUR_STEP_REVISITED, - { - tutorial_step_count: 2, - tutorial_step_name: ONBOARDING_WIZARD_STEP_DESCRIPTION[2], - }, - ); + trackEvent(MetaMetricsEvents.ONBOARDING_TOUR_STEP_REVISITED, { + tutorial_step_count: 2, + tutorial_step_name: ONBOARDING_WIZARD_STEP_DESCRIPTION[2], + }); }; - getOnboardingStyles = () => { - const colors = this.context.colors || mockTheme.colors; - return onboardingStyles(colors); - }; + const getOnboardingStyles = () => onboardingStyles(colors); - /** - * Calls props 'onClose' - */ - onClose = () => { - const { onClose } = this.props; + const onCloseStep = () => { onClose && onClose(false); }; - /** - * Returns content for this step - */ - content = () => { - const dynamicOnboardingStyles = this.getOnboardingStyles(); + const content = () => { + const dynamicOnboardingStyles = getOnboardingStyles(); return ( @@ -132,36 +97,38 @@ class Step2 extends PureComponent { ); }; - render() { - return ( - - - - + return ( + + + - ); - } -} + + ); +}; + +Step2.propTypes = { + setOnboardingWizardStep: PropTypes.func, + coachmarkRef: PropTypes.object, + onClose: PropTypes.func, +}; const mapDispatchToProps = (dispatch) => ({ setOnboardingWizardStep: (step) => dispatch(setOnboardingWizardStep(step)), }); -Step2.contextType = ThemeContext; - -export default connect(null, mapDispatchToProps)(withMetricsAwareness(Step2)); +export default connect(null, mapDispatchToProps)(Step2); diff --git a/app/components/UI/OnboardingWizard/Step3/index.js b/app/components/UI/OnboardingWizard/Step3/index.js index 700ed3d9be0..6b1327e0d41 100644 --- a/app/components/UI/OnboardingWizard/Step3/index.js +++ b/app/components/UI/OnboardingWizard/Step3/index.js @@ -1,7 +1,7 @@ import React, { useCallback, useEffect, useState } from 'react'; import PropTypes from 'prop-types'; import { connect } from 'react-redux'; -import { Dimensions, Platform, StyleSheet, Text, View } from 'react-native'; +import { Platform, StyleSheet, Text, View } from 'react-native'; import Coachmark from '../Coachmark'; import setOnboardingWizardStep from '../../../../actions/wizard'; import { strings } from '../../../../../locales/i18n'; @@ -27,6 +27,9 @@ const styles = StyleSheet.create({ }, coachmarkContainer: { position: 'absolute', + left: 0, + right: 0, + marginHorizontal: 16, }, }); @@ -35,8 +38,6 @@ const Step3 = ({ setOnboardingWizardStep, coachmarkRef, onClose }) => { const { trackEvent } = useMetrics(); const [coachmarkTop, setCoachmarkTop] = useState(0); - const [coachmarkLeft, setCoachmarkLeft] = useState(0); - const [coachmarkRight, setCoachmarkRight] = useState(0); const handleLayout = useCallback(() => { const accActionsRef = coachmarkRef.accountActionsRef?.current; @@ -52,11 +53,7 @@ const Step3 = ({ setOnboardingWizardStep, coachmarkRef, onClose }) => { accActionsPageY, ) => { const top = accActionsHeight + accActionsPageY; - const right = - Dimensions.get('window').width - (accActionsPageX + accActionsWidth); setCoachmarkTop(top); - setCoachmarkLeft(accActionsPageX); - setCoachmarkRight(right); }, ); }, [coachmarkRef.accountActionsRef]); @@ -109,8 +106,6 @@ const Step3 = ({ setOnboardingWizardStep, coachmarkRef, onClose }) => { styles.coachmarkContainer, { top: coachmarkTop, - left: coachmarkLeft, - right: coachmarkRight, }, ]} > diff --git a/app/components/UI/OnboardingWizard/Step4/__snapshots__/index.test.tsx.snap b/app/components/UI/OnboardingWizard/Step4/__snapshots__/index.test.tsx.snap index b4e2d1c97bb..c074699512a 100644 --- a/app/components/UI/OnboardingWizard/Step4/__snapshots__/index.test.tsx.snap +++ b/app/components/UI/OnboardingWizard/Step4/__snapshots__/index.test.tsx.snap @@ -32,6 +32,8 @@ exports[`Step4 should render correctly 1`] = ` } } > - + `; diff --git a/app/components/UI/OnboardingWizard/Step4/index.js b/app/components/UI/OnboardingWizard/Step4/index.js index 2973c67361f..5abe521348d 100644 --- a/app/components/UI/OnboardingWizard/Step4/index.js +++ b/app/components/UI/OnboardingWizard/Step4/index.js @@ -1,11 +1,14 @@ import React, { useCallback, useEffect, useState } from 'react'; import PropTypes from 'prop-types'; import { connect } from 'react-redux'; -import { Dimensions, Platform, StyleSheet, Text, View } from 'react-native'; -import Coachmark from '../Coachmark'; +import { Platform, StyleSheet, Text, View } from 'react-native'; import setOnboardingWizardStep from '../../../../actions/wizard'; import { strings } from '../../../../../locales/i18n'; -import onboardingStyles from './../styles'; +import Coachmark from '../Coachmark'; + +import Device from '../../../../util/device'; + +import onboardingStyles from '../styles'; import { MetaMetricsEvents, ONBOARDING_WIZARD_STEP_DESCRIPTION, @@ -13,7 +16,8 @@ import { import { useTheme } from '../../../../util/theme'; import generateTestId from '../../../../../wdio/utils/generateTestId'; import { ONBOARDING_WIZARD_FOURTH_STEP_CONTENT_ID } from '../../../../../wdio/screen-objects/testIDs/Components/OnboardingWizard.testIds'; -import { useMetrics } from '../../../../components/hooks/useMetrics'; + +import { useMetrics } from '../../../hooks/useMetrics'; const styles = StyleSheet.create({ main: { @@ -23,32 +27,25 @@ const styles = StyleSheet.create({ position: 'absolute', left: 0, right: 0, + marginHorizontal: 16, }, - coachmark: { marginHorizontal: 16 }, }); -const Step4 = (props) => { - const { setOnboardingWizardStep, onClose } = props; - const { trackEvent } = useMetrics(); +const Step4 = ({ setOnboardingWizardStep, onClose }) => { const { colors } = useTheme(); - const dynamicOnboardingStyles = onboardingStyles(colors); - const [coachmarkBottom, setCoachmarkBottom] = useState(); - - const getCoachmarkPosition = useCallback(() => { - props?.coachmarkRef?.current?.measure( - (x, y, width, heigh, pageX, pageY) => { - setCoachmarkBottom(Dimensions.get('window').height - pageY); - }, - ); - }, [props?.coachmarkRef]); + const { trackEvent } = useMetrics(); + + const [coachmarkTop, setCoachmarkTop] = useState(0); + + const handleLayout = useCallback(() => { + const top = Device.isIphoneX() ? 80 : Device.isIos() ? 64 : 60; + setCoachmarkTop(top); + }, []); useEffect(() => { - getCoachmarkPosition(); - }, [getCoachmarkPosition]); + handleLayout(); + }, [handleLayout]); - /** - * Dispatches 'setOnboardingWizardStep' with next step - */ const onNext = () => { setOnboardingWizardStep && setOnboardingWizardStep(5); trackEvent(MetaMetricsEvents.ONBOARDING_TOUR_STEP_COMPLETED, { @@ -57,9 +54,6 @@ const Step4 = (props) => { }); }; - /** - * Dispatches 'setOnboardingWizardStep' with back step - */ const onBack = () => { setOnboardingWizardStep && setOnboardingWizardStep(3); trackEvent(MetaMetricsEvents.ONBOARDING_TOUR_STEP_REVISITED, { @@ -68,26 +62,29 @@ const Step4 = (props) => { }); }; - /** - * Calls props 'onClose' - */ - const handleOnClose = () => { + const getOnboardingStyles = () => onboardingStyles(colors); + + const onCloseStep = () => { onClose && onClose(false); }; - /** - * Returns content for this step - */ - const content = () => ( - - - {strings('onboarding_wizard_new.step4.content1')} - - - ); + const content = () => { + const dynamicOnboardingStyles = getOnboardingStyles(); + + return ( + + + {strings('onboarding_wizard_new.step4.content1')} + + + ); + }; return ( @@ -95,7 +92,7 @@ const Step4 = (props) => { style={[ styles.coachmarkContainer, { - bottom: coachmarkBottom, + top: coachmarkTop, }, ]} > @@ -104,33 +101,22 @@ const Step4 = (props) => { content={content()} onNext={onNext} onBack={onBack} - style={styles.coachmark} - bottomIndicatorPosition={'bottomCenter'} + topIndicatorPosition={'topRight'} currentStep={3} - onClose={handleOnClose} + onClose={onCloseStep} /> ); }; -const mapDispatchToProps = (dispatch) => ({ - setOnboardingWizardStep: (step) => dispatch(setOnboardingWizardStep(step)), -}); - Step4.propTypes = { - /** - * Dispatch set onboarding wizard step - */ setOnboardingWizardStep: PropTypes.func, - /** - * Callback called when closing step - */ onClose: PropTypes.func, - /** - * coachmark ref to get position - */ - coachmarkRef: PropTypes.object, }; +const mapDispatchToProps = (dispatch) => ({ + setOnboardingWizardStep: (step) => dispatch(setOnboardingWizardStep(step)), +}); + export default connect(null, mapDispatchToProps)(Step4); diff --git a/app/components/UI/OnboardingWizard/Step4/index.test.tsx b/app/components/UI/OnboardingWizard/Step4/index.test.tsx index 5d484d0ba58..3aa4a51e59b 100644 --- a/app/components/UI/OnboardingWizard/Step4/index.test.tsx +++ b/app/components/UI/OnboardingWizard/Step4/index.test.tsx @@ -1,17 +1,23 @@ import React from 'react'; +import Step4 from '.'; import { shallow } from 'enzyme'; -import Step4 from './'; import configureMockStore from 'redux-mock-store'; import { Provider } from 'react-redux'; +import initialBackgroundState from '../../../../util/test/initial-background-state.json'; const mockStore = configureMockStore(); -const store = mockStore({}); +const initialState = { + engine: { + backgroundState: initialBackgroundState, + }, +}; +const store = mockStore(initialState); describe('Step4', () => { it('should render correctly', () => { const wrapper = shallow( - + , ); expect(wrapper).toMatchSnapshot(); diff --git a/app/components/UI/OnboardingWizard/Step5/index.js b/app/components/UI/OnboardingWizard/Step5/index.js index 9f2450dd66b..2cba5e8eeff 100644 --- a/app/components/UI/OnboardingWizard/Step5/index.js +++ b/app/components/UI/OnboardingWizard/Step5/index.js @@ -2,51 +2,55 @@ import React, { useCallback, useEffect, useState } from 'react'; import PropTypes from 'prop-types'; import { connect } from 'react-redux'; import { Dimensions, Platform, StyleSheet, Text, View } from 'react-native'; -import { colors as importedColors } from '../../../../styles/common'; import Coachmark from '../Coachmark'; import setOnboardingWizardStep from '../../../../actions/wizard'; import { strings } from '../../../../../locales/i18n'; -import onboardingStyles from './../styles'; +import onboardingStyles from '../styles'; import { MetaMetricsEvents, ONBOARDING_WIZARD_STEP_DESCRIPTION, } from '../../../../core/Analytics'; import { useTheme } from '../../../../util/theme'; -import { createBrowserNavDetails } from '../../../Views/Browser'; import generateTestId from '../../../../../wdio/utils/generateTestId'; import { ONBOARDING_WIZARD_FIFTH_STEP_CONTENT_ID } from '../../../../../wdio/screen-objects/testIDs/Components/OnboardingWizard.testIds'; -import { useMetrics } from '../../../../components/hooks/useMetrics'; +import { useMetrics } from '../../../hooks/useMetrics'; -const WIDTH = Dimensions.get('window').width; const styles = StyleSheet.create({ main: { flex: 1, - backgroundColor: importedColors.transparent, - marginLeft: 16, - }, - some: { - width: WIDTH - 32, }, coachmarkContainer: { position: 'absolute', left: 0, right: 0, + marginHorizontal: 16, }, }); const Step5 = (props) => { - const { navigation, setOnboardingWizardStep, onClose } = props; + const { setOnboardingWizardStep, onClose } = props; const { trackEvent } = useMetrics(); const { colors } = useTheme(); const dynamicOnboardingStyles = onboardingStyles(colors); - const [coachmarkBottom, setCoachmarkBottom] = useState(); + const [coachmarkBottom, setCoachmarkBottom] = useState(50); + + const getCoachmarkPosition = useCallback(() => { + props?.coachmarkRef?.current?.measure( + (x, y, width, heigh, pageX, pageY) => { + setCoachmarkBottom(Dimensions.get('window').height - pageY); + }, + ); + }, [props?.coachmarkRef]); + + useEffect(() => { + getCoachmarkPosition(); + }, [getCoachmarkPosition]); /** * Dispatches 'setOnboardingWizardStep' with next step */ const onNext = () => { setOnboardingWizardStep && setOnboardingWizardStep(6); - navigation && navigation.navigate(...createBrowserNavDetails()); trackEvent(MetaMetricsEvents.ONBOARDING_TOUR_STEP_COMPLETED, { tutorial_step_count: 5, tutorial_step_name: ONBOARDING_WIZARD_STEP_DESCRIPTION[5], @@ -54,13 +58,10 @@ const Step5 = (props) => { }; /** - * Dispatches 'setOnboardingWizardStep' with next step + * Dispatches 'setOnboardingWizardStep' with back step */ const onBack = () => { - navigation && navigation.navigate('WalletView'); - setTimeout(() => { - setOnboardingWizardStep && setOnboardingWizardStep(4); - }, 1); + setOnboardingWizardStep && setOnboardingWizardStep(4); trackEvent(MetaMetricsEvents.ONBOARDING_TOUR_STEP_REVISITED, { tutorial_step_count: 5, tutorial_step_name: ONBOARDING_WIZARD_STEP_DESCRIPTION[5], @@ -88,30 +89,23 @@ const Step5 = (props) => { ); - const getCoachmarkPosition = useCallback(() => { - props?.coachmarkRef?.current?.measure( - (x, y, width, heigh, pageX, pageY) => { - setCoachmarkBottom(Dimensions.get('window').height - pageY); - }, - ); - }, [props?.coachmarkRef]); - - useEffect(() => { - getCoachmarkPosition(); - }, [getCoachmarkPosition]); - return ( - + @@ -124,10 +118,6 @@ const mapDispatchToProps = (dispatch) => ({ }); Step5.propTypes = { - /** - * Object that represents the navigator - */ - navigation: PropTypes.object, /** * Dispatch set onboarding wizard step */ @@ -137,7 +127,7 @@ Step5.propTypes = { */ onClose: PropTypes.func, /** - * ref + * coachmark ref to get position */ coachmarkRef: PropTypes.object, }; diff --git a/app/components/UI/OnboardingWizard/Step6/index.js b/app/components/UI/OnboardingWizard/Step6/index.js index 4a7fbf3c413..6acd9e7da2b 100644 --- a/app/components/UI/OnboardingWizard/Step6/index.js +++ b/app/components/UI/OnboardingWizard/Step6/index.js @@ -1,65 +1,59 @@ -import React, { useEffect, useState } from 'react'; +import React from 'react'; import PropTypes from 'prop-types'; import { connect } from 'react-redux'; import { Platform, StyleSheet, Text, View } from 'react-native'; +import Device from '../../../../util/device'; import Coachmark from '../Coachmark'; import setOnboardingWizardStep from '../../../../actions/wizard'; import { strings } from '../../../../../locales/i18n'; -import onboardingStyles from './../styles'; -import Device from '../../../../util/device'; +import { createBrowserNavDetails } from '../../../Views/Browser'; + +import onboardingStyles from '../styles'; import { MetaMetricsEvents, ONBOARDING_WIZARD_STEP_DESCRIPTION, } from '../../../../core/Analytics'; import { useTheme } from '../../../../util/theme'; -import Routes from '../../../../constants/navigation/Routes'; import generateTestId from '../../../../../wdio/utils/generateTestId'; import { ONBOARDING_WIZARD_SIXTH_STEP_CONTENT_ID } from '../../../../../wdio/screen-objects/testIDs/Components/OnboardingWizard.testIds'; -import { useMetrics } from '../../../../components/hooks/useMetrics'; +import { useMetrics } from '../../../hooks/useMetrics'; const styles = StyleSheet.create({ main: { flex: 1, }, coachmarkContainer: { - flex: 1, position: 'absolute', + alignSelf: 'center', left: 0, right: 0, marginHorizontal: 16, + bottom: Device.isIphoneX() ? 80 : Device.isIos() ? 40 : 64, }, }); const Step6 = (props) => { const { setOnboardingWizardStep, onClose, navigation } = props; const { trackEvent } = useMetrics(); - - const [ready, setReady] = useState(false); - const [coachmarkTop, setCoachmarkTop] = useState(0); const { colors } = useTheme(); const dynamicOnboardingStyles = onboardingStyles(colors); /** - * If component ref defined, calculate its position and position coachmark accordingly + * Dispatches 'setOnboardingWizardStep' with next step */ - const getPosition = () => { - const position = Device.isAndroid() ? 280 : Device.isIphoneX() ? 320 : 280; - setCoachmarkTop(position); - setReady(true); + const onNext = () => { + setOnboardingWizardStep && setOnboardingWizardStep(7); + navigation && navigation.navigate(...createBrowserNavDetails()); + trackEvent(MetaMetricsEvents.ONBOARDING_TOUR_STEP_COMPLETED, { + tutorial_step_count: 6, + tutorial_step_name: ONBOARDING_WIZARD_STEP_DESCRIPTION[6], + }); }; - useEffect(() => { - // As we're changing the view on this step, we have to make sure Browser is rendered - setTimeout(() => { - getPosition(); - }, 1200); - }, []); - /** - * Dispatches 'setOnboardingWizardStep' with back step + * Dispatches 'setOnboardingWizardStep' with next step */ const onBack = () => { - navigation?.navigate?.(Routes.WALLET.HOME); setOnboardingWizardStep && setOnboardingWizardStep(5); trackEvent(MetaMetricsEvents.ONBOARDING_TOUR_STEP_REVISITED, { tutorial_step_count: 6, @@ -68,9 +62,9 @@ const Step6 = (props) => { }; /** - * Calls props onClose + * Calls props 'onClose' */ - const triggerOnClose = () => { + const handleOnClose = () => { onClose && onClose(false); }; @@ -88,19 +82,18 @@ const Step6 = (props) => { ); - if (!ready) return null; - return ( - + @@ -121,7 +114,7 @@ Step6.propTypes = { */ setOnboardingWizardStep: PropTypes.func, /** - * Callback to call when closing + * Callback called when closing step */ onClose: PropTypes.func, }; diff --git a/app/components/UI/OnboardingWizard/Step6/index.test.tsx b/app/components/UI/OnboardingWizard/Step6/index.test.tsx index 07ea0ad77e8..a097d7067f2 100644 --- a/app/components/UI/OnboardingWizard/Step6/index.test.tsx +++ b/app/components/UI/OnboardingWizard/Step6/index.test.tsx @@ -1,6 +1,6 @@ import React from 'react'; import { shallow } from 'enzyme'; -import Step6 from './'; +import Step6 from '.'; import configureMockStore from 'redux-mock-store'; import { Provider } from 'react-redux'; diff --git a/app/components/UI/OnboardingWizard/Step7/__snapshots__/index.test.tsx.snap b/app/components/UI/OnboardingWizard/Step7/__snapshots__/index.test.tsx.snap new file mode 100644 index 00000000000..f08de91d1ff --- /dev/null +++ b/app/components/UI/OnboardingWizard/Step7/__snapshots__/index.test.tsx.snap @@ -0,0 +1,274 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Step7 should render correctly 1`] = ` + + + + + + + + + + + + + Using the browser + + + + + + + + Search for sites by keyword or enter a URL. Have fun out there! + + + + + + 6 + /6 + + + + + Got it + + + + + + + +`; diff --git a/app/components/UI/OnboardingWizard/Step7/index.js b/app/components/UI/OnboardingWizard/Step7/index.js new file mode 100644 index 00000000000..60e910e0c82 --- /dev/null +++ b/app/components/UI/OnboardingWizard/Step7/index.js @@ -0,0 +1,130 @@ +import React, { useEffect, useState } from 'react'; +import PropTypes from 'prop-types'; +import { connect } from 'react-redux'; +import { Platform, StyleSheet, Text, View } from 'react-native'; +import Coachmark from '../Coachmark'; +import setOnboardingWizardStep from '../../../../actions/wizard'; +import { strings } from '../../../../../locales/i18n'; +import onboardingStyles from '../styles'; +import Routes from '../../../../constants/navigation/Routes'; + +import Device from '../../../../util/device'; +import { + MetaMetricsEvents, + ONBOARDING_WIZARD_STEP_DESCRIPTION, +} from '../../../../core/Analytics'; +import { useTheme } from '../../../../util/theme'; + +import generateTestId from '../../../../../wdio/utils/generateTestId'; +import { ONBOARDING_WIZARD_SEVENTH_STEP_CONTENT_ID } from '../../../../../wdio/screen-objects/testIDs/Components/OnboardingWizard.testIds'; +import { useMetrics } from '../../../hooks/useMetrics'; + +const styles = StyleSheet.create({ + main: { + flex: 1, + }, + coachmarkContainer: { + position: 'absolute', + left: 0, + right: 0, + marginHorizontal: 16, + }, +}); + +const Step7 = (props) => { + const { setOnboardingWizardStep, onClose, navigation } = props; + const { trackEvent } = useMetrics(); + + const [ready, setReady] = useState(false); + const [coachmarkTop, setCoachmarkTop] = useState(0); + const { colors } = useTheme(); + const dynamicOnboardingStyles = onboardingStyles(colors); + + /** + * If component ref defined, calculate its position and position coachmark accordingly + */ + const getPosition = () => { + const position = Device.isAndroid() ? 280 : Device.isIphoneX() ? 320 : 280; + setCoachmarkTop(position); + setReady(true); + }; + + useEffect(() => { + getPosition(); + }, []); + + /** + * Dispatches 'setOnboardingWizardStep' with back step + */ + const onBack = () => { + navigation?.navigate?.(Routes.WALLET.HOME); + setTimeout(() => { + setOnboardingWizardStep && setOnboardingWizardStep(6); + }, 1); + trackEvent(MetaMetricsEvents.ONBOARDING_TOUR_STEP_REVISITED, { + tutorial_step_count: 7, + tutorial_step_name: ONBOARDING_WIZARD_STEP_DESCRIPTION[7], + }); + }; + + /** + * Calls props onClose + */ + const triggerOnClose = () => { + navigation?.navigate?.(Routes.WALLET.HOME); + onClose && onClose(false); + }; + + /** + * Returns content for this step + */ + const content = () => ( + + + {strings('onboarding_wizard_new.step7.content1')} + + + ); + + if (!ready) return null; + + return ( + + + + + + ); +}; + +const mapDispatchToProps = (dispatch) => ({ + setOnboardingWizardStep: (step) => dispatch(setOnboardingWizardStep(step)), +}); + +Step7.propTypes = { + /** + * Object that represents the navigator + */ + navigation: PropTypes.object, + /** + * Dispatch set onboarding wizard step + */ + setOnboardingWizardStep: PropTypes.func, + /** + * Callback to call when closing + */ + onClose: PropTypes.func, +}; + +export default connect(null, mapDispatchToProps)(Step7); diff --git a/app/components/UI/OnboardingWizard/Step7/index.test.tsx b/app/components/UI/OnboardingWizard/Step7/index.test.tsx new file mode 100644 index 00000000000..0789f092857 --- /dev/null +++ b/app/components/UI/OnboardingWizard/Step7/index.test.tsx @@ -0,0 +1,10 @@ +import React from 'react'; +import renderWithProvider from '../../../../util/test/renderWithProvider'; +import Step7 from '.'; + +describe('Step7', () => { + it('should render correctly', () => { + const container = renderWithProvider(); + expect(container).toMatchSnapshot(); + }); +}); diff --git a/app/components/UI/OnboardingWizard/index.js b/app/components/UI/OnboardingWizard/index.js index 97dcd2a8442..fbbbb76e794 100644 --- a/app/components/UI/OnboardingWizard/index.js +++ b/app/components/UI/OnboardingWizard/index.js @@ -1,17 +1,20 @@ import React, { useContext } from 'react'; import PropTypes from 'prop-types'; import { View, StyleSheet } from 'react-native'; -import { colors as importedColors } from '../../../styles/common'; import { connect } from 'react-redux'; +import DefaultPreference from 'react-native-default-preference'; +import Modal from 'react-native-modal'; +import { colors as importedColors } from '../../../styles/common'; + import Step1 from './Step1'; import Step2 from './Step2'; import Step3 from './Step3'; import Step4 from './Step4'; import Step5 from './Step5'; import Step6 from './Step6'; +import Step7 from './Step7'; import setOnboardingWizardStep from '../../../actions/wizard'; -import DefaultPreference from 'react-native-default-preference'; -import Modal from 'react-native-modal'; +import Routes from '../../../constants/navigation/Routes'; import { ONBOARDING_WIZARD, EXPLORED } from '../../../constants/storage'; import { MetaMetricsEvents, @@ -79,6 +82,8 @@ const OnboardingWizard = (props) => { const theme = useTheme(); const { trackEvent } = useMetrics(); const styles = createStyles(theme); + // eslint-disable-next-line no-console + console.log('OnboardingWizard', step); /** * Close onboarding wizard setting step to 0 and closing drawer @@ -121,6 +126,7 @@ const OnboardingWizard = (props) => { /> ), 6: , + 7: , }; return steps[step]; }; @@ -128,13 +134,13 @@ const OnboardingWizard = (props) => { const getBackButtonBehavior = () => { if (step === 1) { return closeOnboardingWizard(); - } else if (step === 5) { - setOnboardingWizardStep(4); - navigation.navigate('WalletView'); - drawerRef?.current?.dismissDrawer?.(); } else if (step === 6) { - drawerRef?.current?.showDrawer?.(); setOnboardingWizardStep(5); + navigation.navigate(Routes.WALLET.HOME); + drawerRef?.current?.dismissDrawer?.(); + } else if (step === 7) { + drawerRef?.current?.showDrawer?.(); + setOnboardingWizardStep(6); } return setOnboardingWizardStep(step - 1); }; diff --git a/app/components/Views/BrowserTab/index.js b/app/components/Views/BrowserTab/index.js index 61fc1c71bbc..2b5cdd8bf4b 100644 --- a/app/components/Views/BrowserTab/index.js +++ b/app/components/Views/BrowserTab/index.js @@ -1420,7 +1420,7 @@ export const BrowserTab = (props) => { */ const renderOnboardingWizard = () => { const { wizardStep } = props; - if ([6].includes(wizardStep)) { + if ([7].includes(wizardStep)) { if (!wizardScrollAdjusted.current) { setTimeout(() => { reload(); diff --git a/app/components/Views/Wallet/index.tsx b/app/components/Views/Wallet/index.tsx index be6a137d57e..ad8ad348703 100644 --- a/app/components/Views/Wallet/index.tsx +++ b/app/components/Views/Wallet/index.tsx @@ -378,7 +378,7 @@ const Wallet = ({ navigation }: any) => { */ const renderOnboardingWizard = useCallback( () => - [1, 2, 3].includes(wizardStep) && ( + [1, 2, 3, 4, 5, 6].includes(wizardStep) && ( { await TestHelpers.delay(3000); await OnboardingWizardModal.isVisible(); await OnboardingWizardModal.tapTakeTourButton(); + // Ensure step 1 is shown correctly await OnboardingWizardModal.isYourAccountsTutorialStepVisible(); await OnboardingWizardModal.tapGotItButton(); - // Ensure step 3 is shown correctly + // Ensure step 2 is shown correctly await OnboardingWizardModal.isEditAccountNameTutorialStepVisible(); - // await WalletView.editAccountName(ACCOUNT); await OnboardingWizardModal.tapGotItButton(); await WalletView.isAccountNameCorrect(ACCOUNT); + // Ensure step 3 is shown correctly + await OnboardingWizardModal.isNotificationsTutorialStepVisible(); + await OnboardingWizardModal.tapGotItButton(); // Ensure step 4 is shown correctly await OnboardingWizardModal.isMainNavigationTutorialStepVisible(); await OnboardingWizardModal.tapGotItButton(); @@ -105,7 +108,7 @@ describe(SmokeCore('Start Exploring'), () => { await OnboardingWizardModal.tapGotItButton(); await OnboardingWizardModal.isExploreTheBrowserTutorialStepVisible(); await OnboardingWizardModal.tapGotItButton(); - // Ensure step 6 is shown correctly + // Ensure step 7 is shown correctly await OnboardingWizardModal.isBrowserSearchStepTutorialVisible(); await OnboardingWizardModal.tapGotItButton(); // Check that we are on the Browser page diff --git a/wdio/screen-objects/Modals/OnboardingWizardModal.js b/wdio/screen-objects/Modals/OnboardingWizardModal.js index 42588ee0a9d..83baed7a930 100644 --- a/wdio/screen-objects/Modals/OnboardingWizardModal.js +++ b/wdio/screen-objects/Modals/OnboardingWizardModal.js @@ -9,6 +9,7 @@ import { ONBOARDING_WIZARD_STEP_1_NO_THANKS_ID, ONBOARDING_WIZARD_STEP_1_TAKE_THE_TOUR_ID, ONBOARDING_WIZARD_THIRD_STEP_CONTENT_ID, + ONBOARDING_WIZARD_SEVENTH_STEP_CONTENT_ID, } from '../testIDs/Components/OnboardingWizard.testIds'; import Selectors from '../../helpers/Selectors'; @@ -67,6 +68,12 @@ class OnboardingWizardModal { ); } + get step7Description() { + return Selectors.getElementByPlatform( + ONBOARDING_WIZARD_SEVENTH_STEP_CONTENT_ID, + ); + } + get onBoardingWizardGotItButton() { return Selectors.getElementByPlatform(ONBOARDING_WIZARD_NEXT_GOT_IT_BUTTON); } @@ -107,6 +114,10 @@ class OnboardingWizardModal { await expect(await this.step6Description).toBeDisplayed(); } + async isStep7ContentDisplayed() { + await expect(await this.step7Description).toBeDisplayed(); + } + async tapGotItButton() { await Gestures.tap(this.onBoardingWizardGotItButton); } diff --git a/wdio/screen-objects/testIDs/Components/OnboardingWizard.testIds.js b/wdio/screen-objects/testIDs/Components/OnboardingWizard.testIds.js index ea2ae8d309f..cde48e52b14 100644 --- a/wdio/screen-objects/testIDs/Components/OnboardingWizard.testIds.js +++ b/wdio/screen-objects/testIDs/Components/OnboardingWizard.testIds.js @@ -29,3 +29,6 @@ export const ONBOARDING_WIZARD_FIFTH_STEP_CONTENT_ID = export const ONBOARDING_WIZARD_SIXTH_STEP_CONTENT_ID = 'onboarding-wizard-step6-content'; + + export const ONBOARDING_WIZARD_SEVENTH_STEP_CONTENT_ID = + 'onboarding-wizard-step7-content';