mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-11-22 01:47:00 +01:00
Implement Flask onboarding UI (#12745)
* Added Flask Experimental Area warning to OnboardingV2 * Added first time flow Flask Experimental Area warning * Made both onboarding flows use one Experimental Area component * Fix comments in React divs * Fix unreachable code * Fix build lint problems * Changes after code review * Added guards around route constants imports * Code Review changes * Update ui/components/app/flask/experimental-area/index.scss Co-authored-by: George Marshall <george.marshall@consensys.net> * Code review changes * Fix lint * Update ui/components/app/flask/experimental-area/index.scss Co-authored-by: George Marshall <george.marshall@consensys.net> * Update ui/components/app/flask/experimental-area/index.scss Co-authored-by: George Marshall <george.marshall@consensys.net> * Update ui/components/app/flask/experimental-area/index.scss Co-authored-by: George Marshall <george.marshall@consensys.net> * Update ui/components/app/flask/experimental-area/index.scss Co-authored-by: George Marshall <george.marshall@consensys.net> * Update ui/components/app/flask/experimental-area/index.scss Co-authored-by: George Marshall <george.marshall@consensys.net> * fix lint Co-authored-by: George Marshall <george.marshall@consensys.net>
This commit is contained in:
parent
7a92e22111
commit
70386726f6
@ -1056,6 +1056,21 @@
|
||||
"message": "File import not working? Click here!",
|
||||
"description": "Helps user import their account from a JSON file"
|
||||
},
|
||||
"flaskExperimentalText1": {
|
||||
"message": "Using Flask can greatly increase your risk of fund loss:"
|
||||
},
|
||||
"flaskExperimentalText2": {
|
||||
"message": "if you use it to install non-trustworthy Snaps"
|
||||
},
|
||||
"flaskExperimentalText3": {
|
||||
"message": "if you do not review confirmations before approving changes"
|
||||
},
|
||||
"flaskExperimentalText4": {
|
||||
"message": "if you interact with unfamiliar smart contracts"
|
||||
},
|
||||
"flaskExperimentalText5": {
|
||||
"message": "Using Flask gives you much greater discretion in using the power of MetaMask, and that discretion is yours. Do you accept these risks as well as extra responsibility for your wallet's safety?"
|
||||
},
|
||||
"followUsOnTwitter": {
|
||||
"message": "Follow us on Twitter"
|
||||
},
|
||||
@ -3217,6 +3232,9 @@
|
||||
"usedByClients": {
|
||||
"message": "Used by a variety of different clients"
|
||||
},
|
||||
"userAccepts": {
|
||||
"message": "I accept"
|
||||
},
|
||||
"userName": {
|
||||
"message": "Username"
|
||||
},
|
||||
|
@ -29,7 +29,8 @@
|
||||
},
|
||||
"eslint-module-utils": {
|
||||
"packages": {
|
||||
"eslint-import-resolver-node": true
|
||||
"eslint-import-resolver-node": true,
|
||||
"@babel/eslint-parser": true
|
||||
}
|
||||
},
|
||||
"node-sass": {
|
||||
|
@ -53,6 +53,7 @@
|
||||
@import 'wallet-overview/index';
|
||||
@import 'whats-new-popup/index';
|
||||
@import 'loading-network-screen/index';
|
||||
@import 'flask/experimental-area/index';
|
||||
@import 'advanced-gas-fee-popover/index';
|
||||
@import 'advanced-gas-fee-popover/advanced-gas-fee-inputs/index';
|
||||
@import 'advanced-gas-fee-popover/advanced-gas-fee-inputs/base-fee-input/index';
|
||||
|
@ -0,0 +1,97 @@
|
||||
import React, { useContext } from 'react';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import PropTypes from 'prop-types';
|
||||
import { I18nContext } from '../../../../contexts/i18n';
|
||||
import Button from '../../../ui/button';
|
||||
|
||||
function lineBreaksToBr(source) {
|
||||
return source.split('\n').map((value) => {
|
||||
return (
|
||||
<>
|
||||
{value}
|
||||
<br />
|
||||
</>
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
const METAMASK_LOGO = lineBreaksToBr(`MMm*mmMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMmm*mMM
|
||||
MM*./***mMMMMMMMMMMMMMMMMMMMMMMMMMMm***/.*MM
|
||||
MM/...///*mMMMMMMMMMMMMMMMMMMMMMMm*///.../MM
|
||||
Mm.....//../*mMMMMMMMMMMMMMMMMm*/..//.....mM
|
||||
M*....../*....*mMMMMMMMMMMMMm*....*/......*M
|
||||
M/........*.....*//////////*...../......../M
|
||||
m..........*/...//........//.../*..........m
|
||||
M/..........//.../......../...//........../M
|
||||
M/.........../*/./.......//./*/.........../M
|
||||
M*.............////......////.............*M
|
||||
Mm...............**......**...............mM
|
||||
Mm/...............*/..../*.............../mM
|
||||
MM/............../*/..../*/............../MM
|
||||
Mm..............//./...././/..............mM
|
||||
MM*............*/../..../../*............*MM
|
||||
MM/........../*..../..../....*/........../MM
|
||||
MMm.........//...../..../.....//.........mMM
|
||||
MMm......//**....../..../......**//......mMM
|
||||
MMM/..////.*......./..../......././///../MMM
|
||||
MMMm*//..../......./..../......./....//*mMMM
|
||||
MMMm......*////////*....*////////*......mMMM
|
||||
MMM*......*////////*....*////////*......*MMM
|
||||
MMM/....../*......./..../.......*/....../MMM
|
||||
MMm........**/./m*./..../.**/..**........mMM
|
||||
MM*........//*mMMM///..///mMMm*//........*MM
|
||||
MM/........././*mM*//..//*Mm*/./........./MM
|
||||
Mm..........//.../**/../**/...//..........mM
|
||||
M*...........*..../*/../*/..../...........*M
|
||||
M*///////////*/.../m/../m/.../*///////////*M
|
||||
M*.........../*/...m/../m.../*/...........*M
|
||||
Mm.........../..//.*....*./*../...........mM
|
||||
MM/........../...//******//.../........../MM
|
||||
MM*........../....*MMMMMM*..../..........*MM
|
||||
MMm........../....*MMMMMM*..../..........mMM
|
||||
MMm/........//....*MMMMMM*....//......../mMM
|
||||
MMM/....../*mm*...*mmmmmm*...*mm*/....../MMM
|
||||
MMM*../*mmMMMMMm///......//*mMMMMMmm*/..*MMM
|
||||
MMMm*mMMMMMMMMMMm**......**mMMMMMMMMMMm*mMMM
|
||||
MMMMMMMMMMMMMMMMMm/....../mMMMMMMMMMMMMMMMMM
|
||||
MMMMMMMMMMMMMMMMMMmmmmmmmmMMMMMMMMMMMMMMMMMM`);
|
||||
|
||||
/* eslint-disable no-irregular-whitespace */
|
||||
const EXPERIMENTAL_AREA = lineBreaksToBr(`█▄█ █▀█ █░█ ▀ █▀█ █▀▀ █▀▀ █▄░█ ▀█▀ █▀▀ █▀█ █ █▄░█ █▀▀ ▄▀█ █▄░█
|
||||
░█░ █▄█ █▄█ ░ █▀▄ ██▄ ██▄ █░▀█ ░█░ ██▄ █▀▄ █ █░▀█ █▄█ █▀█ █░▀█
|
||||
|
||||
█▀▀ ▀▄▀ █▀█ █▀▀ █▀█ █ █▀▄▀█ █▀▀ █▄░█ ▀█▀ ▄▀█ █░░ ▄▀█ █▀█ █▀▀ ▄▀█
|
||||
██▄ █░█ █▀▀ ██▄ █▀▄ █ █░▀░█ ██▄ █░▀█ ░█░ █▀█ █▄▄ █▀█ █▀▄ ██▄ █▀█`);
|
||||
/* eslint-enable no-irregular-whitespace */
|
||||
|
||||
export default function ExperimentalArea({ redirectTo }) {
|
||||
const t = useContext(I18nContext);
|
||||
const history = useHistory();
|
||||
|
||||
const onClick = () => {
|
||||
history.push(redirectTo);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="experimental-area">
|
||||
<div className="logo">{METAMASK_LOGO}</div>
|
||||
<div className="experimental-text">{EXPERIMENTAL_AREA}</div>
|
||||
<div className="text">
|
||||
{t('flaskExperimentalText1')}
|
||||
<ul>
|
||||
<li>{t('flaskExperimentalText2')}</li>
|
||||
<li>{t('flaskExperimentalText3')}</li>
|
||||
<li>{t('flaskExperimentalText4')}</li>
|
||||
</ul>
|
||||
{t('flaskExperimentalText5')}
|
||||
</div>
|
||||
<Button type="primary" onClick={onClick}>
|
||||
{t('userAccepts')}
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
ExperimentalArea.propTypes = {
|
||||
redirectTo: PropTypes.string,
|
||||
};
|
@ -0,0 +1,13 @@
|
||||
import React from 'react';
|
||||
|
||||
import ExperimentalArea from '.';
|
||||
|
||||
export default {
|
||||
title: 'Components/App/Flask/ExperimentalArea',
|
||||
id: __filename,
|
||||
component: ExperimentalArea,
|
||||
};
|
||||
|
||||
export const DefaultStory = () => <ExperimentalArea />;
|
||||
|
||||
DefaultStory.storyName = 'Default';
|
1
ui/components/app/flask/experimental-area/index.js
Normal file
1
ui/components/app/flask/experimental-area/index.js
Normal file
@ -0,0 +1 @@
|
||||
export { default } from './experimental-area';
|
54
ui/components/app/flask/experimental-area/index.scss
Normal file
54
ui/components/app/flask/experimental-area/index.scss
Normal file
@ -0,0 +1,54 @@
|
||||
.experimental-area {
|
||||
color: $flask-purple;
|
||||
margin: auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
.logo {
|
||||
padding: 16px 8px 0;
|
||||
line-height: 0.625em;
|
||||
font-family: monospace;
|
||||
font-size: $font-size-h8;
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
|
||||
.experimental-text {
|
||||
padding: 16px 8px 0;
|
||||
font-family: monospace;
|
||||
font-size: $font-size-h5;
|
||||
margin: auto;
|
||||
line-height: 0.875em;
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
|
||||
.text {
|
||||
@include H5;
|
||||
|
||||
padding: 16px;
|
||||
max-width: 670px;
|
||||
}
|
||||
|
||||
ul {
|
||||
padding: 16px 0;
|
||||
}
|
||||
|
||||
li {
|
||||
list-style-type: disc;
|
||||
padding-left: 8px;
|
||||
list-style-position: inside;
|
||||
margin-bottom: 8px;
|
||||
|
||||
&:nth-last-child(1) {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
button {
|
||||
background-color: $flask-purple !important;
|
||||
border: 0 !important;
|
||||
color: $ui-1;
|
||||
width: 200px;
|
||||
}
|
||||
}
|
@ -1,6 +1,5 @@
|
||||
// These are the colors of the MetaMask design system
|
||||
// Only design system colors should be added, no superfluous variables
|
||||
// See https://bit.ly/32mnoja (link to figma design system)
|
||||
$Blue-000: #eaf6ff;
|
||||
$Blue-100: #a7d9fe;
|
||||
$Blue-200: #75c4fd;
|
||||
@ -112,6 +111,8 @@ $rinkeby: #f6c343;
|
||||
$goerli: #3099f2;
|
||||
$localhost: #29b6af;
|
||||
|
||||
$flask-purple: #8b45b6;
|
||||
|
||||
$color-map: (
|
||||
'ui-1': $ui-1,
|
||||
'ui-2': $ui-2,
|
||||
@ -143,4 +144,5 @@ $color-map: (
|
||||
'goerli': $goerli,
|
||||
'localhost': $localhost,
|
||||
'transparent': transparent,
|
||||
'flask-purple': $flask-purple
|
||||
);
|
||||
|
@ -70,6 +70,11 @@ const ONBOARDING_PIN_EXTENSION_ROUTE = '/onboarding/pin-extension';
|
||||
const ONBOARDING_WELCOME_ROUTE = '/onboarding/welcome';
|
||||
const ONBOARDING_METAMETRICS = '/onboarding/metametrics';
|
||||
|
||||
///: BEGIN:ONLY_INCLUDE_IN(flask)
|
||||
const INITIALIZE_EXPERIMENTAL_AREA = '/initialize/experimental-area';
|
||||
const ONBOARDING_EXPERIMENTAL_AREA = '/onboarding/experimental-area';
|
||||
///: END:ONLY_INCLUDE_IN
|
||||
|
||||
const CONFIRM_TRANSACTION_ROUTE = '/confirm-transaction';
|
||||
const CONFIRM_SEND_ETHER_PATH = '/send-ether';
|
||||
const CONFIRM_SEND_TOKEN_PATH = '/send-token';
|
||||
@ -234,4 +239,8 @@ export {
|
||||
ONBOARDING_PIN_EXTENSION_ROUTE,
|
||||
ONBOARDING_WELCOME_ROUTE,
|
||||
ONBOARDING_METAMETRICS,
|
||||
///: BEGIN:ONLY_INCLUDE_IN(flask)
|
||||
INITIALIZE_EXPERIMENTAL_AREA,
|
||||
ONBOARDING_EXPERIMENTAL_AREA,
|
||||
///: END:ONLY_INCLUDE_IN
|
||||
};
|
||||
|
@ -5,8 +5,13 @@ import {
|
||||
DEFAULT_ROUTE,
|
||||
LOCK_ROUTE,
|
||||
INITIALIZE_END_OF_FLOW_ROUTE,
|
||||
INITIALIZE_WELCOME_ROUTE,
|
||||
INITIALIZE_UNLOCK_ROUTE,
|
||||
///: BEGIN:ONLY_INCLUDE_IN(flask)
|
||||
INITIALIZE_EXPERIMENTAL_AREA,
|
||||
///: END:ONLY_INCLUDE_IN
|
||||
///: BEGIN:ONLY_INCLUDE_IN(main,beta)
|
||||
INITIALIZE_WELCOME_ROUTE,
|
||||
///: END:ONLY_INCLUDE_IN
|
||||
} from '../../../helpers/constants/routes';
|
||||
|
||||
export default class FirstTimeFlowSwitch extends PureComponent {
|
||||
@ -38,7 +43,16 @@ export default class FirstTimeFlowSwitch extends PureComponent {
|
||||
}
|
||||
|
||||
if (!isInitialized) {
|
||||
return <Redirect to={{ pathname: INITIALIZE_WELCOME_ROUTE }} />;
|
||||
/* eslint-disable prefer-const */
|
||||
let redirect;
|
||||
///: BEGIN:ONLY_INCLUDE_IN(flask)
|
||||
redirect = <Redirect to={{ pathname: INITIALIZE_EXPERIMENTAL_AREA }} />;
|
||||
///: END:ONLY_INCLUDE_IN
|
||||
///: BEGIN:ONLY_INCLUDE_IN(main,beta)
|
||||
redirect = <Redirect to={{ pathname: INITIALIZE_WELCOME_ROUTE }} />;
|
||||
///: END:ONLY_INCLUDE_IN
|
||||
/* eslint-enable prefer-const */
|
||||
return redirect;
|
||||
}
|
||||
|
||||
return <Redirect to={{ pathname: INITIALIZE_UNLOCK_ROUTE }} />;
|
||||
|
@ -13,7 +13,13 @@ import {
|
||||
INITIALIZE_METAMETRICS_OPT_IN_ROUTE,
|
||||
INITIALIZE_BACKUP_SEED_PHRASE_ROUTE,
|
||||
INITIALIZE_SEED_PHRASE_INTRO_ROUTE,
|
||||
///: BEGIN:ONLY_INCLUDE_IN(flask)
|
||||
INITIALIZE_EXPERIMENTAL_AREA,
|
||||
///: END:ONLY_INCLUDE_IN
|
||||
} from '../../helpers/constants/routes';
|
||||
///: BEGIN:ONLY_INCLUDE_IN(flask)
|
||||
import ExperimentalArea from '../../components/app/flask/experimental-area';
|
||||
///: END:ONLY_INCLUDE_IN
|
||||
import FirstTimeFlowSwitch from './first-time-flow-switch';
|
||||
import Welcome from './welcome';
|
||||
import SelectAction from './select-action';
|
||||
@ -162,6 +168,22 @@ export default class FirstTimeFlow extends PureComponent {
|
||||
component={EndOfFlow}
|
||||
/>
|
||||
<Route exact path={INITIALIZE_WELCOME_ROUTE} component={Welcome} />
|
||||
{
|
||||
///: BEGIN:ONLY_INCLUDE_IN(flask)
|
||||
}
|
||||
<Route
|
||||
exact
|
||||
path={INITIALIZE_EXPERIMENTAL_AREA}
|
||||
render={(routeProps) => (
|
||||
<ExperimentalArea
|
||||
{...routeProps}
|
||||
redirectTo={INITIALIZE_SELECT_ACTION_ROUTE}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
{
|
||||
///: END:ONLY_INCLUDE_IN
|
||||
}
|
||||
<Route
|
||||
exact
|
||||
path={INITIALIZE_METAMETRICS_OPT_IN_ROUTE}
|
||||
|
@ -6,7 +6,12 @@ import {
|
||||
ONBOARDING_COMPLETION_ROUTE,
|
||||
ONBOARDING_UNLOCK_ROUTE,
|
||||
LOCK_ROUTE,
|
||||
ONBOARDING_WELCOME_ROUTE,
|
||||
///: BEGIN:ONLY_INCLUDE_IN(flask)
|
||||
ONBOARDING_EXPERIMENTAL_AREA, // eslint-disable-line no-unused-vars
|
||||
///: END:ONLY_INCLUDE_IN
|
||||
///: BEGIN:ONLY_INCLUDE_IN(main,beta)
|
||||
ONBOARDING_WELCOME_ROUTE, // eslint-disable-line no-unused-vars
|
||||
///: END:ONLY_INCLUDE_IN
|
||||
} from '../../../helpers/constants/routes';
|
||||
import {
|
||||
getCompletedOnboarding,
|
||||
@ -16,6 +21,7 @@ import {
|
||||
} from '../../../ducks/metamask/metamask';
|
||||
|
||||
export default function OnboardingFlowSwitch() {
|
||||
/* eslint-disable prefer-const */
|
||||
const completedOnboarding = useSelector(getCompletedOnboarding);
|
||||
const isInitialized = useSelector(getIsInitialized);
|
||||
const seedPhraseBackedUp = useSelector(getSeedPhraseBackedUp);
|
||||
@ -34,7 +40,16 @@ export default function OnboardingFlowSwitch() {
|
||||
}
|
||||
|
||||
if (!isInitialized) {
|
||||
return <Redirect to={{ pathname: ONBOARDING_WELCOME_ROUTE }} />;
|
||||
let redirect;
|
||||
/* eslint-disable prefer-const */
|
||||
///: BEGIN:ONLY_INCLUDE_IN(flask)
|
||||
redirect = <Redirect to={{ pathname: ONBOARDING_EXPERIMENTAL_AREA }} />;
|
||||
///: END:ONLY_INCLUDE_IN
|
||||
///: BEGIN:ONLY_INCLUDE_IN(main,beta)
|
||||
redirect = <Redirect to={{ pathname: ONBOARDING_WELCOME_ROUTE }} />;
|
||||
///: END:ONLY_INCLUDE_IN
|
||||
/* eslint-enable prefer-const */
|
||||
return redirect;
|
||||
}
|
||||
|
||||
return <Redirect to={{ pathname: ONBOARDING_UNLOCK_ROUTE }} />;
|
||||
|
@ -3,6 +3,9 @@ import { Switch, Route, useHistory, useLocation } from 'react-router-dom';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
import Unlock from '../unlock-page';
|
||||
import {
|
||||
///: BEGIN:ONLY_INCLUDE_IN(flask)
|
||||
ONBOARDING_EXPERIMENTAL_AREA,
|
||||
///: END:ONLY_INCLUDE_IN
|
||||
ONBOARDING_CREATE_PASSWORD_ROUTE,
|
||||
ONBOARDING_REVIEW_SRP_ROUTE,
|
||||
ONBOARDING_CONFIRM_SRP_ROUTE,
|
||||
@ -30,6 +33,9 @@ import {
|
||||
import { getFirstTimeFlowTypeRoute } from '../../selectors';
|
||||
import Button from '../../components/ui/button';
|
||||
import { useI18nContext } from '../../hooks/useI18nContext';
|
||||
///: BEGIN:ONLY_INCLUDE_IN(flask)
|
||||
import ExperimentalArea from '../../components/app/flask/experimental-area';
|
||||
///: END:ONLY_INCLUDE_IN
|
||||
import OnboardingFlowSwitch from './onboarding-flow-switch/onboarding-flow-switch';
|
||||
import CreatePassword from './create-password/create-password';
|
||||
import ReviewRecoveryPhrase from './recovery-phrase/review-recovery-phrase';
|
||||
@ -161,6 +167,21 @@ export default function OnboardingFlow() {
|
||||
path={ONBOARDING_METAMETRICS}
|
||||
component={MetaMetricsComponent}
|
||||
/>
|
||||
{
|
||||
///: BEGIN:ONLY_INCLUDE_IN(flask)
|
||||
}
|
||||
<Route
|
||||
path={ONBOARDING_EXPERIMENTAL_AREA}
|
||||
render={(routeProps) => (
|
||||
<ExperimentalArea
|
||||
{...routeProps}
|
||||
redirectTo={ONBOARDING_WELCOME_ROUTE}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
{
|
||||
///: END:ONLY_INCLUDE_IN
|
||||
}
|
||||
<Route exact path="*" component={OnboardingFlowSwitch} />
|
||||
</Switch>
|
||||
</div>
|
||||
|
Loading…
Reference in New Issue
Block a user