Establish onboarding-flow wrapper/router base and feature flag env variable (#12247)

* establish onboarding-flow wrapper/router base and feature flag env variable

* small cleanup

* addressing feedback
feature/default_network_editable
Alex Donesky 3 years ago committed by GitHub
parent 730605353a
commit 9355fb21c7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      development/build/scripts.js
  2. 15
      ui/ducks/metamask/metamask.js
  3. 28
      ui/helpers/constants/routes.js
  4. 22
      ui/helpers/higher-order-components/authenticated/authenticated.component.js
  5. 10
      ui/helpers/higher-order-components/initialized/initialized.component.js
  6. 18
      ui/pages/onboarding-flow/index.scss
  7. 41
      ui/pages/onboarding-flow/onboarding-flow-switch/onboarding-flow-switch.js
  8. 109
      ui/pages/onboarding-flow/onboarding-flow.js
  9. 1
      ui/pages/pages.scss
  10. 8
      ui/pages/routes/routes.component.js
  11. 10
      ui/selectors/first-time-flow.js

@ -27,6 +27,7 @@ const bifyModuleGroups = require('bify-module-groups');
const metamaskrc = require('rc')('metamask', {
INFURA_PROJECT_ID: process.env.INFURA_PROJECT_ID,
ONBOARDING_V2: process.env.ONBOARDING_V2,
SEGMENT_HOST: process.env.SEGMENT_HOST,
SEGMENT_WRITE_KEY: process.env.SEGMENT_WRITE_KEY,
SEGMENT_LEGACY_WRITE_KEY: process.env.SEGMENT_LEGACY_WRITE_KEY,
@ -612,6 +613,7 @@ function getEnvironmentVariables({ buildType, devMode, testing }) {
? process.env.SEGMENT_PROD_LEGACY_WRITE_KEY
: metamaskrc.SEGMENT_LEGACY_WRITE_KEY,
SWAPS_USE_DEV_APIS: process.env.SWAPS_USE_DEV_APIS === '1',
ONBOARDING_V2: metamaskrc.ONBOARDING_V2 === '1',
};
}

@ -325,3 +325,18 @@ export function getIsGasEstimatesLoading(state) {
return isGasEstimatesLoading;
}
export function getCompletedOnboarding(state) {
return state.metamask.completedOnboarding;
}
export function getIsInitialized(state) {
return state.metamask.isInitialized;
}
export function getIsUnlocked(state) {
return state.metamask.isUnlocked;
}
export function getSeedPhraseBackedUp(state) {
return state.metamask.seedPhraseBackedUp;
}

@ -52,6 +52,21 @@ const INITIALIZE_END_OF_FLOW_ROUTE = '/initialize/end-of-flow';
const INITIALIZE_CONFIRM_SEED_PHRASE_ROUTE = '/initialize/seed-phrase/confirm';
const INITIALIZE_METAMETRICS_OPT_IN_ROUTE = '/initialize/metametrics-opt-in';
const ONBOARDING_ROUTE = '/onboarding';
const ONBOARDING_REVIEW_SRP_ROUTE = '/onboarding/review-srp';
const ONBOARDING_CONFIRM_SRP_ROUTE = '/onboarding/confirm-srp';
const ONBOARDING_CREATE_PASSWORD_ROUTE = '/onboarding/create-password';
const ONBOARDING_COMPLETION_ROUTE = '/onboarding/completion';
const ONBOARDING_UNLOCK_ROUTE = '/onboarding/unlock';
const ONBOARDING_GET_STARTED_ROUTE = '/onboarding/get-started';
const ONBOARDING_HELP_US_IMPROVE_ROUTE = '/onboarding/help-us-improve';
const ONBOARDING_IMPORT_WITH_SRP_ROUTE =
'/onboarding/create-password/import-with-sre';
const ONBOARDING_IMPORT_MOBILE_ROUTE = '/onboarding/create-password';
const ONBOARDING_SECURE_YOUR_WALLET_ROUTE = '/onboarding/secure-your-wallet';
const ONBOARDING_PRIVACY_SETTINGS_ROUTE = '/onboarding/privacy-settings';
const ONBOARDING_PIN_EXTENSION_ROUTE = '/onboarding/pin-extension';
const CONFIRM_TRANSACTION_ROUTE = '/confirm-transaction';
const CONFIRM_SEND_ETHER_PATH = '/send-ether';
const CONFIRM_SEND_TOKEN_PATH = '/send-token';
@ -199,4 +214,17 @@ export {
AWAITING_SIGNATURES_ROUTE,
SWAPS_ERROR_ROUTE,
SWAPS_MAINTENANCE_ROUTE,
ONBOARDING_ROUTE,
ONBOARDING_GET_STARTED_ROUTE,
ONBOARDING_HELP_US_IMPROVE_ROUTE,
ONBOARDING_CREATE_PASSWORD_ROUTE,
ONBOARDING_IMPORT_WITH_SRP_ROUTE,
ONBOARDING_IMPORT_MOBILE_ROUTE,
ONBOARDING_SECURE_YOUR_WALLET_ROUTE,
ONBOARDING_REVIEW_SRP_ROUTE,
ONBOARDING_CONFIRM_SRP_ROUTE,
ONBOARDING_PRIVACY_SETTINGS_ROUTE,
ONBOARDING_COMPLETION_ROUTE,
ONBOARDING_UNLOCK_ROUTE,
ONBOARDING_PIN_EXTENSION_ROUTE,
};

@ -1,16 +1,32 @@
import React from 'react';
import PropTypes from 'prop-types';
import { Redirect, Route } from 'react-router-dom';
import { UNLOCK_ROUTE, INITIALIZE_ROUTE } from '../../constants/routes';
import {
UNLOCK_ROUTE,
INITIALIZE_ROUTE,
ONBOARDING_ROUTE,
} from '../../constants/routes';
export default function Authenticated(props) {
const { isUnlocked, completedOnboarding } = props;
switch (true) {
// For ONBOARDING_V2 dev purposes,
// Remove when ONBOARDING_V2 dev complete
case process.env.ONBOARDING_V2 === true:
return <Redirect to={{ pathname: ONBOARDING_ROUTE }} />;
case isUnlocked && completedOnboarding:
return <Route {...props} />;
case !completedOnboarding:
return <Redirect to={{ pathname: INITIALIZE_ROUTE }} />;
return (
<Redirect
to={{
pathname: process.env.ONBOARDING_V2
? ONBOARDING_ROUTE
: INITIALIZE_ROUTE,
}}
/>
);
default:
return <Redirect to={{ pathname: UNLOCK_ROUTE }} />;
}

@ -1,13 +1,19 @@
import React from 'react';
import PropTypes from 'prop-types';
import { Redirect, Route } from 'react-router-dom';
import { INITIALIZE_ROUTE } from '../../constants/routes';
import { INITIALIZE_ROUTE, ONBOARDING_ROUTE } from '../../constants/routes';
export default function Initialized(props) {
return props.completedOnboarding ? (
<Route {...props} />
) : (
<Redirect to={{ pathname: INITIALIZE_ROUTE }} />
<Redirect
to={{
pathname: process.env.ONBOARDING_V2
? ONBOARDING_ROUTE
: INITIALIZE_ROUTE,
}}
/>
);
}

@ -0,0 +1,18 @@
@import 'recovery-phrase/index';
@import 'new-account/index';
.onboarding-flow {
width: 100%;
background-color: $white;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
&__wrapper {
margin-top: 40px;
padding: 32px;
border: 1px solid $Grey-100;
border-radius: 20px;
}
}

@ -0,0 +1,41 @@
import React from 'react';
import { useSelector } from 'react-redux';
import { Redirect } from 'react-router-dom';
import {
DEFAULT_ROUTE,
ONBOARDING_COMPLETION_ROUTE,
ONBOARDING_GET_STARTED_ROUTE,
ONBOARDING_UNLOCK_ROUTE,
LOCK_ROUTE,
} from '../../../helpers/constants/routes';
import {
getCompletedOnboarding,
getIsInitialized,
getIsUnlocked,
getSeedPhraseBackedUp,
} from '../../../ducks/metamask/metamask';
export default function OnboardingFlowSwitch() {
const completedOnboarding = useSelector(getCompletedOnboarding);
const isInitialized = useSelector(getIsInitialized);
const seedPhraseBackedUp = useSelector(getSeedPhraseBackedUp);
const isUnlocked = useSelector(getIsUnlocked);
if (completedOnboarding) {
return <Redirect to={{ pathname: DEFAULT_ROUTE }} />;
}
if (seedPhraseBackedUp !== null) {
return <Redirect to={{ pathname: ONBOARDING_COMPLETION_ROUTE }} />;
}
if (isUnlocked) {
return <Redirect to={{ pathname: LOCK_ROUTE }} />;
}
if (!isInitialized) {
return <Redirect to={{ pathname: ONBOARDING_GET_STARTED_ROUTE }} />;
}
return <Redirect to={{ pathname: ONBOARDING_UNLOCK_ROUTE }} />;
}

@ -0,0 +1,109 @@
import React, { useEffect, useState } from 'react';
import { Switch, Route, useHistory } from 'react-router-dom';
import { useDispatch, useSelector } from 'react-redux';
import Unlock from '../unlock-page';
import {
ONBOARDING_CREATE_PASSWORD_ROUTE,
ONBOARDING_REVIEW_SRP_ROUTE,
ONBOARDING_CONFIRM_SRP_ROUTE,
ONBOARDING_UNLOCK_ROUTE,
DEFAULT_ROUTE,
} from '../../helpers/constants/routes';
import {
getCompletedOnboarding,
getIsInitialized,
getIsUnlocked,
getSeedPhraseBackedUp,
} from '../../ducks/metamask/metamask';
import {
createNewVaultAndGetSeedPhrase,
unlockAndGetSeedPhrase,
} from '../../store/actions';
import { getFirstTimeFlowTypeRoute } from '../../selectors';
import OnboardingFlowSwitch from './onboarding-flow-switch/onboarding-flow-switch';
import NewAccount from './new-account/new-account';
import ReviewRecoveryPhrase from './recovery-phrase/review-recovery-phrase';
import ConfirmRecoveryPhrase from './recovery-phrase/confirm-recovery-phrase';
export default function OnboardingFlow() {
const [seedPhrase, setSeedPhrase] = useState('');
const dispatch = useDispatch();
const history = useHistory();
const isInitialized = useSelector(getIsInitialized);
const isUnlocked = useSelector(getIsUnlocked);
const completedOnboarding = useSelector(getCompletedOnboarding);
const seedPhraseBackedUp = useSelector(getSeedPhraseBackedUp);
const nextRoute = useSelector(getFirstTimeFlowTypeRoute);
useEffect(() => {
// For ONBOARDING_V2 dev purposes,
// Remove when ONBOARDING_V2 dev complete
if (process.env.ONBOARDING_V2) {
history.push(ONBOARDING_CREATE_PASSWORD_ROUTE);
return;
}
if (completedOnboarding && seedPhraseBackedUp) {
history.push(DEFAULT_ROUTE);
return;
}
if (isInitialized && !isUnlocked) {
history.push(ONBOARDING_UNLOCK_ROUTE);
}
}, [
history,
completedOnboarding,
isInitialized,
isUnlocked,
seedPhraseBackedUp,
]);
const handleCreateNewAccount = async (password) => {
const newSeedPhrase = await dispatch(
createNewVaultAndGetSeedPhrase(password),
);
setSeedPhrase(newSeedPhrase);
};
const handleUnlock = async (password) => {
const retreivedSeedPhrase = await dispatch(
unlockAndGetSeedPhrase(password),
);
setSeedPhrase(retreivedSeedPhrase);
history.push(nextRoute);
};
return (
<div className="onboarding-flow">
<div className="onboarding-flow__wrapper">
<Switch>
<Route
path={ONBOARDING_CREATE_PASSWORD_ROUTE}
render={(routeProps) => (
<NewAccount
{...routeProps}
createNewAccount={handleCreateNewAccount}
/>
)}
/>
<Route
path={ONBOARDING_REVIEW_SRP_ROUTE}
render={() => <ReviewRecoveryPhrase seedPhrase={seedPhrase} />}
/>
<Route
path={ONBOARDING_CONFIRM_SRP_ROUTE}
render={() => <ConfirmRecoveryPhrase seedPhrase={seedPhrase} />}
/>
<Route
path={ONBOARDING_UNLOCK_ROUTE}
render={(routeProps) => (
<Unlock {...routeProps} onSubmit={handleUnlock} />
)}
/>
<Route exact path="*" component={OnboardingFlowSwitch} />
</Switch>
</div>
</div>
);
}

@ -19,3 +19,4 @@
@import 'settings/index';
@import 'swaps/index';
@import 'unlock-page/index';
@import 'onboarding-flow/index';

@ -53,6 +53,7 @@ import {
BUILD_QUOTE_ROUTE,
CONFIRMATION_V_NEXT_ROUTE,
CONFIRM_IMPORT_TOKEN_ROUTE,
ONBOARDING_ROUTE,
} from '../../helpers/constants/routes';
import {
@ -62,6 +63,7 @@ import {
import { getEnvironmentType } from '../../../app/scripts/lib/util';
import { isBeta } from '../../helpers/utils/build-types';
import ConfirmationPage from '../confirmation';
import OnboardingFlow from '../onboarding-flow/onboarding-flow';
export default class Routes extends Component {
static propTypes = {
@ -114,9 +116,11 @@ export default class Routes extends Component {
renderRoutes() {
const { autoLockTimeLimit, setLastActiveTime } = this.props;
const routes = (
<Switch>
{process.env.ONBOARDING_V2 && (
<Route path={ONBOARDING_ROUTE} component={OnboardingFlow} />
)}
<Route path={LOCK_ROUTE} component={Lock} exact />
<Route path={INITIALIZE_ROUTE} component={FirstTimeFlow} />
<Initialized path={UNLOCK_ROUTE} component={UnlockPage} exact />
@ -225,7 +229,7 @@ export default class Routes extends Component {
const isInitializing = Boolean(
matchPath(location.pathname, {
path: INITIALIZE_ROUTE,
path: process.env.ONBOARDING_V2 ? ONBOARDING_ROUTE : INITIALIZE_ROUTE,
exact: false,
}),
);

@ -2,6 +2,8 @@ import {
INITIALIZE_CREATE_PASSWORD_ROUTE,
INITIALIZE_IMPORT_WITH_SEED_PHRASE_ROUTE,
DEFAULT_ROUTE,
ONBOARDING_CREATE_PASSWORD_ROUTE,
ONBOARDING_IMPORT_WITH_SRP_ROUTE,
} from '../helpers/constants/routes';
export function getFirstTimeFlowTypeRoute(state) {
@ -9,9 +11,13 @@ export function getFirstTimeFlowTypeRoute(state) {
let nextRoute;
if (firstTimeFlowType === 'create') {
nextRoute = INITIALIZE_CREATE_PASSWORD_ROUTE;
nextRoute = process.env.ONBOARDING_V2
? ONBOARDING_CREATE_PASSWORD_ROUTE
: INITIALIZE_CREATE_PASSWORD_ROUTE;
} else if (firstTimeFlowType === 'import') {
nextRoute = INITIALIZE_IMPORT_WITH_SEED_PHRASE_ROUTE;
nextRoute = process.env.ONBOARDING_V2
? ONBOARDING_IMPORT_WITH_SRP_ROUTE
: INITIALIZE_IMPORT_WITH_SEED_PHRASE_ROUTE;
} else {
nextRoute = DEFAULT_ROUTE;
}

Loading…
Cancel
Save