aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDan J Miller <danjm.com@gmail.com>2019-02-27 22:46:41 +0800
committerWhymarrh Whitby <whymarrh.whitby@gmail.com>2019-02-27 22:46:41 +0800
commitcb2698d20eae273d372d03e11fa765a91c330c17 (patch)
treef23b852b074dad770bfd970799220b63c40459b7
parenta2320c76fef084b7ec01839ab9c17b474839b3c0 (diff)
downloadtangerine-wallet-browser-cb2698d20eae273d372d03e11fa765a91c330c17.tar
tangerine-wallet-browser-cb2698d20eae273d372d03e11fa765a91c330c17.tar.gz
tangerine-wallet-browser-cb2698d20eae273d372d03e11fa765a91c330c17.tar.bz2
tangerine-wallet-browser-cb2698d20eae273d372d03e11fa765a91c330c17.tar.lz
tangerine-wallet-browser-cb2698d20eae273d372d03e11fa765a91c330c17.tar.xz
tangerine-wallet-browser-cb2698d20eae273d372d03e11fa765a91c330c17.tar.zst
tangerine-wallet-browser-cb2698d20eae273d372d03e11fa765a91c330c17.zip
First time flow updates (#6192)
* Action select step of onboarding flow added. * Update navigation on create and import password screens. * Adds terms of service checkbox to create and import account screens. * Add security warning to jazzicon intro step * Update and streamline unique image to confirm seed steps of first time flow. * UI touch ups to welcome screen. * UI touch up on select action page * Fix first time import flow. * Add end of flow screen to first time flow * Replace unique image screen with updated fishing warning screen. * Update e2e tests for onboarding flow changes. * Add required translations to onboarding flow. * Update design of select action screen to emphasize create new wallet option. * Clean up onboarding flow code. * Remove notice related code from first-time-flow directory. * Use updater function argument in new-account.component
-rw-r--r--app/_locales/en/messages.json65
-rw-r--r--app/images/download-alt.svg5
-rw-r--r--app/images/sleuth.svg1
-rw-r--r--app/images/thin-plus.svg4
-rw-r--r--test/e2e/beta/from-import-beta-ui.spec.js52
-rw-r--r--test/e2e/beta/metamask-beta-responsive-ui.spec.js215
-rw-r--r--test/e2e/beta/metamask-beta-ui.spec.js56
-rw-r--r--ui/app/components/pages/first-time-flow/create-password/create-password.component.js29
-rw-r--r--ui/app/components/pages/first-time-flow/create-password/import-with-seed-phrase/import-with-seed-phrase.component.js37
-rw-r--r--ui/app/components/pages/first-time-flow/create-password/new-account/new-account.component.js46
-rw-r--r--ui/app/components/pages/first-time-flow/create-password/unique-image/unique-image.component.js37
-rw-r--r--ui/app/components/pages/first-time-flow/end-of-flow/end-of-flow.component.js70
-rw-r--r--ui/app/components/pages/first-time-flow/end-of-flow/end-of-flow.container.js11
-rw-r--r--ui/app/components/pages/first-time-flow/end-of-flow/index.js1
-rw-r--r--ui/app/components/pages/first-time-flow/end-of-flow/index.scss47
-rw-r--r--ui/app/components/pages/first-time-flow/first-time-flow-switch/first-time-flow-switch.component.js7
-rw-r--r--ui/app/components/pages/first-time-flow/first-time-flow-switch/first-time-flow-switch.container.js2
-rw-r--r--ui/app/components/pages/first-time-flow/first-time-flow.component.js33
-rw-r--r--ui/app/components/pages/first-time-flow/first-time-flow.container.js3
-rw-r--r--ui/app/components/pages/first-time-flow/index.scss59
-rw-r--r--ui/app/components/pages/first-time-flow/notices/index.js1
-rw-r--r--ui/app/components/pages/first-time-flow/notices/notices.component.js124
-rw-r--r--ui/app/components/pages/first-time-flow/notices/notices.container.js27
-rw-r--r--ui/app/components/pages/first-time-flow/seed-phrase/confirm-seed-phrase/confirm-seed-phrase.component.js29
-rw-r--r--ui/app/components/pages/first-time-flow/seed-phrase/confirm-seed-phrase/confirm-seed-phrase.container.js12
-rw-r--r--ui/app/components/pages/first-time-flow/seed-phrase/confirm-seed-phrase/index.js2
-rw-r--r--ui/app/components/pages/first-time-flow/seed-phrase/confirm-seed-phrase/index.scss4
-rw-r--r--ui/app/components/pages/first-time-flow/seed-phrase/index.js2
-rw-r--r--ui/app/components/pages/first-time-flow/seed-phrase/index.scss6
-rw-r--r--ui/app/components/pages/first-time-flow/seed-phrase/reveal-seed-phrase/index.scss4
-rw-r--r--ui/app/components/pages/first-time-flow/seed-phrase/reveal-seed-phrase/reveal-seed-phrase.component.js18
-rw-r--r--ui/app/components/pages/first-time-flow/seed-phrase/seed-phrase.component.js17
-rw-r--r--ui/app/components/pages/first-time-flow/seed-phrase/seed-phrase.container.js12
-rw-r--r--ui/app/components/pages/first-time-flow/select-action/index.js1
-rw-r--r--ui/app/components/pages/first-time-flow/select-action/index.scss87
-rw-r--r--ui/app/components/pages/first-time-flow/select-action/select-action.component.js104
-rw-r--r--ui/app/components/pages/first-time-flow/select-action/select-action.container.js0
-rw-r--r--ui/app/components/pages/first-time-flow/welcome/index.scss31
-rw-r--r--ui/app/components/pages/first-time-flow/welcome/welcome.component.js16
-rw-r--r--ui/app/components/pages/home/home.component.js10
-rw-r--r--ui/app/routes.js4
41 files changed, 763 insertions, 528 deletions
diff --git a/app/_locales/en/messages.json b/app/_locales/en/messages.json
index 2d0098a24..d4860bbfb 100644
--- a/app/_locales/en/messages.json
+++ b/app/_locales/en/messages.json
@@ -92,6 +92,15 @@
"advanced": {
"message": "Advanced"
},
+ "agreeTermsOfService": {
+ "message": "I agree to the Terms of Service"
+ },
+ "allDone": {
+ "message": "All Done"
+ },
+ "alreadyHaveSeedPhrase": {
+ "message": "No, I already have a seed phrase"
+ },
"amount": {
"message": "Amount"
},
@@ -239,6 +248,9 @@
"confirmTransaction": {
"message": "Confirm Transaction"
},
+ "congratulations": {
+ "message": "Congratulations"
+ },
"connectHardwareWallet": {
"message": "Connect Hardware Wallet"
},
@@ -326,6 +338,9 @@
"createAccount": {
"message": "Create Account"
},
+ "createAWallet": {
+ "message": "Create a Wallet"
+ },
"createDen": {
"message": "Create"
},
@@ -448,6 +463,24 @@
"encryptNewDen": {
"message": "Encrypt your new DEN"
},
+ "endOfFlowMessage1": {
+ "message": "You passed the test - keep your seedphrase safe, it's your responsibility!"
+ },
+ "endOfFlowMessage2": {
+ "message": "Tips on storing it safely"
+ },
+ "endOfFlowMessage3": {
+ "message": "Save a backup in multiple places"
+ },
+ "endOfFlowMessage4": {
+ "message": "Never tell anyone"
+ },
+ "endOfFlowMessage5": {
+ "message": "If you need to back your seed phrase again, you can find it in Settings -> Security."
+ },
+ "endOfFlowMessage6": {
+ "message": "MetaMask cannot recover your seedphrase. Learn more."
+ },
"ensNameNotFound": {
"message": "ENS name not found"
},
@@ -581,10 +614,16 @@
"getHelp": {
"message": "Get Help."
},
+ "getStarted": {
+ "message": "Get Started"
+ },
"greaterThanMin": {
"message": "must be greater than or equal to $1.",
"description": "helper for inputting hex as decimal input"
},
+ "happyToSeeYou": {
+ "message": "We’re happy to see you."
+ },
"hardware": {
"message": "hardware"
},
@@ -647,6 +686,9 @@
"importDen": {
"message": "Import Existing DEN"
},
+ "importWallet": {
+ "message": "Import Wallet"
+ },
"imported": {
"message": "Imported",
"description": "status showing that an account has been fully loaded into the keyring"
@@ -731,6 +773,9 @@
"message": "must be less than or equal to $1.",
"description": "helper for inputting hex as decimal input"
},
+ "letsGoSetUp": {
+ "message": "Yes, let’s get set up!"
+ },
"likeToAddTokens": {
"message": "Would you like to add these tokens?"
},
@@ -777,7 +822,7 @@
"message": "Message"
},
"metamaskDescription": {
- "message": "MetaMask is a secure identity vault for Ethereum."
+ "message": "Connecting you to Ethereum and the Decentralized Web."
},
"metamaskSeedWords": {
"message": "MetaMask Seed Words"
@@ -848,6 +893,21 @@
"newNetwork": {
"message": "New Network"
},
+ "newToMetaMask": {
+ "message": "New to MetaMask?"
+ },
+ "noAlreadyHaveSeed": {
+ "message": "No, I already have a seed phrase"
+ },
+ "protectYourKeys": {
+ "message": "Protect Your Keys!"
+ },
+ "protectYourKeysMessage1": {
+ "message": "Be careful with your seed phrase — there have been reports of websites that attempt to imitate MetaMask. MetaMask will never ask for your seed phrase!"
+ },
+ "protectYourKeysMessage2": {
+ "message": "Keep your phrase safe. If you see something fishy, or you’re uncertain about a website, email support@metamask.io"
+ },
"rpcURL": {
"message": "New RPC URL"
},
@@ -1609,6 +1669,9 @@
"yourUniqueAccountImageDescription2": {
"message": "You’ll see this image everytime you need to confirm a transaction."
},
+ "yourUniqueAccountImageDescription3": {
+ "message": "MetaMask will never ask for your seed phrase!"
+ },
"zeroGasPriceOnSpeedUpError": {
"message":"Zero gas price on speed up"
}
diff --git a/app/images/download-alt.svg b/app/images/download-alt.svg
new file mode 100644
index 000000000..11c54fd66
--- /dev/null
+++ b/app/images/download-alt.svg
@@ -0,0 +1,5 @@
+<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
+<rect x="40" y="40" width="40" height="4.57143" rx="2.28571" transform="rotate(-180 40 40)" fill="#979797"/>
+<rect x="22.5641" y="21.7144" width="4.10256" height="21.7143" rx="2.05128" transform="rotate(-180 22.5641 21.7144)" fill="#979797"/>
+<path d="M20.5 30L7.07661 12L33.9234 12L20.5 30Z" fill="#979797"/>
+</svg>
diff --git a/app/images/sleuth.svg b/app/images/sleuth.svg
new file mode 100644
index 000000000..f4ac8c787
--- /dev/null
+++ b/app/images/sleuth.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#66757F" d="M33 36v-1c0-3.313-2.687-6-6-6H9c-3.313 0-6 2.687-6 6v1h30z"/><path fill="#EF9645" d="M12 27.482C13.672 29.057 15.746 30 18 30s4.327-.944 6-2.518V26H12v1.482z"/><path fill="#66757F" d="M26.75 20.435c1.188.208 2.619.129 2.416.917-.479 1.854-2.604 1.167-2.979 1.188-.375.02.563-2.105.563-2.105z"/><path fill="#292F33" d="M27.062 20.645c1.875.25 2.541.416 1.166.958-.772.305-2.243 4.803-3.331 4.118-1.087-.685 2.165-5.076 2.165-5.076z"/><path fill="#66757F" d="M9.255 20.435c-1.188.208-2.619.129-2.416.917.479 1.854 2.604 1.167 2.979 1.188.375.02-.563-2.105-.563-2.105z"/><path fill="#292F33" d="M8.943 20.645c-1.875.25-2.541.416-1.166.958.772.305 2.243 4.803 3.331 4.118 1.088-.685-2.165-5.076-2.165-5.076z"/><path fill="#FFAC33" d="M8.055 11.031c-1.953 0-2.305 3.164-.664 3.594 0 0-1.367 3.32 1.953 3.32-.547-1.68-1.562-4.414-.781-6.406m19.38-.508c1.953 0 2.305 3.164.664 3.594 0 0 1.367 3.32-1.953 3.32.547-1.68 1.562-4.414.781-6.406"/><ellipse fill="#FFDC5D" cx="18" cy="15.5" rx="10" ry="12.5"/><path fill="#662113" d="M14 17c-.552 0-1-.448-1-1v-1c0-.552.448-1 1-1s1 .448 1 1v1c0 .552-.448 1-1 1zm8 0c-.553 0-1-.448-1-1v-1c0-.552.447-1 1-1s1 .448 1 1v1c0 .552-.447 1-1 1z"/><path fill="#C1694F" d="M19 20.5c0 .276-.224.5-.5.5h-1c-.276 0-.5-.224-.5-.5s.224-.5.5-.5h1c.276 0 .5.224.5.5z"/><path fill-rule="evenodd" clip-rule="evenodd" fill="#292F33" d="M7.657 14.788c.148.147.888.591 1.036 1.034.148.443.445 2.954 1.333 3.693.916.762 4.37.478 5.032.149 1.48-.738 1.662-2.798 1.924-3.842.148-.591 1.036-.591 1.036-.591s.888 0 1.036.591c.262 1.044.444 3.104 1.924 3.841.662.33 4.116.614 5.034-.147.887-.739 1.183-3.25 1.331-3.694.146-.443.888-.886 1.035-1.034.148-.148.148-.739 0-.887-.296-.295-3.788-.559-7.548-.148-.75.082-1.035.295-2.812.295-1.776 0-2.062-.214-2.812-.295-3.759-.411-7.252-.148-7.548.148-.149.148-.149.74-.001.887z"/><path fill="#66757F" d="M7.858 8.395S9.217-.506 13.79.023c3.512.406 4.89.825 7.833.097 1.947-.482 4.065 1.136 5.342 4.379.816 2.068 1.224 4.041 1.224 4.041s3.938-.385 4.165 1.732c.228 2.117-4.354 4.716-15.889 4.716C10 14.987 3.33 12.63 3.013 10.657c-.317-1.973 4.845-2.262 4.845-2.262z"/><path fill="#292F33" d="M8.125 7.15s-.27 1.104-.406 1.871c-.136.768.226 1.296 2.705 1.824 3.287.7 10.679.692 15.058-.383 1.759-.432 2.886-.72 2.751-1.583-.167-1.068-.196-1.066-.541-2.208 0 0-1.477.502-3.427.96-2.66.624-9.964.911-13.481.144-1.874-.41-2.659-.625-2.659-.625zm-.136 13.953c-.354.145 2.921 1.378 7.48 1.458 4.771.084 6.234.39 5.146 1.459-1.146 1.125-.852 2.894-.771 3.418.081.524 2.047 1.916 2.208 2.56.161.645-1.229 5.961-1.229 5.961l-8.729-.252c-2.565-8.844-2.883-8.501-4.105-13.604-.241-1.008 0-1 0-1z"/><path fill="#66757F" d="M6.989 21.144c-.354.146 2.921 1.378 7.48 1.458 4.771.084 6.234.39 5.146 1.459-1.146 1.125-.664 2.894-.583 3.418.081.524 1.859 1.916 2.021 2.561.16.644-1.231 5.96-1.231 5.96l-8.729-.252c-2.565-8.844-2.883-8.501-4.105-13.604-.24-1.008.001-1 .001-1z"/><path fill="#292F33" d="M28.052 21.103c.354.145-2.921 1.378-7.479 1.458-4.771.084-6.234.39-5.146 1.459 1.146 1.125 2.976 2.892 2.896 3.416-.081.524-4.172 1.918-4.333 2.562-.161.645 1.229 5.961 1.229 5.961l8.729-.252c2.565-8.844 2.883-8.501 4.104-13.604.241-1.008 0-1 0-1z"/><path fill="#66757F" d="M28.958 21.103c.354.145-2.921 1.378-7.479 1.458-4.771.084-6.234.39-5.146 1.459 1.146 1.125 2.977 2.892 2.896 3.416-.081.524-4.172 1.918-4.333 2.562-.161.645 1.229 5.961 1.229 5.961l8.657.01c2.565-8.844 2.955-8.763 4.177-13.866.24-1.008-.001-1-.001-1z"/></svg>
diff --git a/app/images/thin-plus.svg b/app/images/thin-plus.svg
new file mode 100644
index 000000000..f46c72a4a
--- /dev/null
+++ b/app/images/thin-plus.svg
@@ -0,0 +1,4 @@
+<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
+<rect y="18" width="40" height="4" rx="2" fill="#979797"/>
+<rect x="18" width="4" height="40" rx="2" fill="#979797"/>
+</svg>
diff --git a/test/e2e/beta/from-import-beta-ui.spec.js b/test/e2e/beta/from-import-beta-ui.spec.js
index d4a380584..ad3e8b1fe 100644
--- a/test/e2e/beta/from-import-beta-ui.spec.js
+++ b/test/e2e/beta/from-import-beta-ui.spec.js
@@ -65,13 +65,16 @@ describe('Using MetaMask with an existing account', function () {
beforeEach(async function () {
await driver.executeScript(
+ 'window.origFetch = window.fetch.bind(window);' +
'window.fetch = ' +
'(...args) => { ' +
'if (args[0] === "https://ethgasstation.info/json/ethgasAPI.json") { return ' +
'Promise.resolve({ json: () => Promise.resolve(JSON.parse(\'' + fetchMockResponses.ethGasBasic + '\')) }); } else if ' +
'(args[0] === "https://ethgasstation.info/json/predictTable.json") { return ' +
- 'Promise.resolve({ json: () => Promise.resolve(JSON.parse(\'' + fetchMockResponses.ethGasPredictTable + '\')) }); } ' +
- 'return window.fetch(...args); }'
+ 'Promise.resolve({ json: () => Promise.resolve(JSON.parse(\'' + fetchMockResponses.ethGasPredictTable + '\')) }); } else if ' +
+ '(args[0] === "https://dev.blockscale.net/api/gasexpress.json") { return ' +
+ 'Promise.resolve({ json: () => Promise.resolve(JSON.parse(\'' + fetchMockResponses.gasExpress + '\')) }); } ' +
+ 'return window.origFetch(...args); }'
)
})
@@ -95,16 +98,19 @@ describe('Using MetaMask with an existing account', function () {
describe('First time flow starting from an existing seed phrase', () => {
it('clicks the continue button on the welcome screen', async () => {
- const welcomeScreenBtn = await findElement(driver, By.css('.welcome-page .first-time-flow__button'))
+ await findElement(driver, By.css('.welcome-page__header'))
+ const welcomeScreenBtn = await findElement(driver, By.css('.first-time-flow__button'))
welcomeScreenBtn.click()
await delay(largeDelayMs)
})
- it('imports a seed phrase', async () => {
- const [seedPhrase] = await findElements(driver, By.xpath(`//a[contains(text(), 'Import with seed phrase')]`))
- await seedPhrase.click()
- await delay(regularDelayMs)
+ it('clicks the "Import Wallet" option', async () => {
+ const customRpcButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Import Wallet')]`))
+ customRpcButton.click()
+ await delay(largeDelayMs)
+ })
+ it('imports a seed phrase', async () => {
const [seedTextArea] = await findElements(driver, By.css('textarea.first-time-flow__textarea'))
await seedTextArea.sendKeys(testSeedPhrase)
await delay(regularDelayMs)
@@ -114,39 +120,25 @@ describe('Using MetaMask with an existing account', function () {
const [confirmPassword] = await findElements(driver, By.id('confirm-password'))
confirmPassword.sendKeys('correct horse battery staple')
+ const tosCheckBox = await findElement(driver, By.css('.first-time-flow__checkbox'))
+ await tosCheckBox.click()
+
const [importButton] = await findElements(driver, By.xpath(`//button[contains(text(), 'Import')]`))
await importButton.click()
await delay(regularDelayMs)
})
- it('clicks through the ToS', async () => {
- // terms of use
- await findElement(driver, By.css('.first-time-flow__markdown'))
- const canClickThrough = await driver.findElement(By.css('button.first-time-flow__button')).isEnabled()
- assert.equal(canClickThrough, false, 'disabled continue button')
- const bottomOfTos = await findElement(driver, By.linkText('Attributions'))
- await driver.executeScript('arguments[0].scrollIntoView(true)', bottomOfTos)
- await delay(regularDelayMs)
- const acceptTos = await findElement(driver, By.css('button.first-time-flow__button'))
- driver.wait(until.elementIsEnabled(acceptTos))
- await acceptTos.click()
- await delay(regularDelayMs)
- })
-
- it('clicks through the privacy notice', async () => {
- // privacy notice
+ it('clicks through the security warning screen', async () => {
+ await findElement(driver, By.xpath(`//div[contains(text(), 'Protect Your Keys!')]`))
const nextScreen = await findElement(driver, By.css('button.first-time-flow__button'))
await nextScreen.click()
await delay(regularDelayMs)
})
- it('clicks through the phishing notice', async () => {
- // phishing notice
- const noticeElement = await driver.findElement(By.css('.first-time-flow__markdown'))
- await driver.executeScript('arguments[0].scrollTop = arguments[0].scrollHeight', noticeElement)
- await delay(regularDelayMs)
- const nextScreen = await findElement(driver, By.css('button.first-time-flow__button'))
- await nextScreen.click()
+ it('clicks through the success screen', async () => {
+ await findElement(driver, By.xpath(`//div[contains(text(), 'Congratulations')]`))
+ const doneButton = await findElement(driver, By.css('button.first-time-flow__button'))
+ await doneButton.click()
await delay(regularDelayMs)
})
})
diff --git a/test/e2e/beta/metamask-beta-responsive-ui.spec.js b/test/e2e/beta/metamask-beta-responsive-ui.spec.js
index 099ed944e..781811d6d 100644
--- a/test/e2e/beta/metamask-beta-responsive-ui.spec.js
+++ b/test/e2e/beta/metamask-beta-responsive-ui.spec.js
@@ -80,134 +80,111 @@ describe('MetaMask', function () {
})
describe('Going through the first time flow', () => {
- it('clicks the continue button on the welcome screen', async () => {
- const welcomeScreenBtn = await findElement(driver, By.css('.welcome-page .first-time-flow__button'))
- welcomeScreenBtn.click()
- await delay(largeDelayMs)
- })
-
- it('accepts a secure password', async () => {
- const passwordBox = await findElement(driver, By.css('.first-time-flow__form #create-password'))
- const passwordBoxConfirm = await findElement(driver, By.css('.first-time-flow__form #confirm-password'))
- const button = await findElement(driver, By.css('.first-time-flow__form button'))
-
- await passwordBox.sendKeys('correct horse battery staple')
- await passwordBoxConfirm.sendKeys('correct horse battery staple')
- await button.click()
- await delay(regularDelayMs)
- })
-
- it('clicks through the unique image screen', async () => {
- await findElement(driver, By.css('.first-time-flow__unique-image'))
- const nextScreen = await findElement(driver, By.css('button.first-time-flow__button'))
- await nextScreen.click()
- await delay(regularDelayMs)
- })
-
- it('clicks through the ToS', async () => {
- // terms of use
- await findElement(driver, By.css('.first-time-flow__markdown'))
- const canClickThrough = await driver.findElement(By.css('button.first-time-flow__button')).isEnabled()
- assert.equal(canClickThrough, false, 'disabled continue button')
- const bottomOfTos = await findElement(driver, By.linkText('Attributions'))
- await driver.executeScript('arguments[0].scrollIntoView(true)', bottomOfTos)
- await delay(regularDelayMs)
- const acceptTos = await findElement(driver, By.css('button.first-time-flow__button'))
- driver.wait(until.elementIsEnabled(acceptTos))
- await acceptTos.click()
- await delay(regularDelayMs)
- })
-
- it('clicks through the privacy notice', async () => {
- // privacy notice
- const nextScreen = await findElement(driver, By.css('button.first-time-flow__button'))
- await nextScreen.click()
- await delay(regularDelayMs)
- })
-
- it('clicks through the phishing notice', async () => {
- // phishing notice
- const noticeElement = await driver.findElement(By.css('.first-time-flow__markdown'))
- await driver.executeScript('arguments[0].scrollTop = arguments[0].scrollHeight', noticeElement)
- await delay(regularDelayMs)
- const nextScreen = await findElement(driver, By.css('button.first-time-flow__button'))
- await nextScreen.click()
- await delay(regularDelayMs)
- })
-
- let seedPhrase
-
- it('reveals the seed phrase', async () => {
- const byRevealButton = By.css('.reveal-seed-phrase__secret-blocker .reveal-seed-phrase__reveal-button')
- await driver.wait(until.elementLocated(byRevealButton, 10000))
- const revealSeedPhraseButton = await findElement(driver, byRevealButton, 10000)
- await revealSeedPhraseButton.click()
- await delay(regularDelayMs)
-
- seedPhrase = await driver.findElement(By.css('.reveal-seed-phrase__secret-words')).getText()
- assert.equal(seedPhrase.split(' ').length, 12)
- await delay(regularDelayMs)
-
- const nextScreen = await findElement(driver, By.css('button.first-time-flow__button'))
- await nextScreen.click()
- await delay(regularDelayMs)
- })
-
- async function clickWordAndWait (word) {
- const xpath = `//div[contains(@class, 'confirm-seed-phrase__seed-word--shuffled') and not(contains(@class, 'confirm-seed-phrase__seed-word--selected')) and contains(text(), '${word}')]`
- const word0 = await findElement(driver, By.xpath(xpath), 10000)
-
- await word0.click()
- await delay(tinyDelayMs)
- }
+ it('clicks the continue button on the welcome screen', async () => {
+ await findElement(driver, By.css('.welcome-page__header'))
+ const welcomeScreenBtn = await findElement(driver, By.css('.first-time-flow__button'))
+ welcomeScreenBtn.click()
+ await delay(largeDelayMs)
+ })
- async function retypeSeedPhrase (words, wasReloaded, count = 0) {
- try {
- if (wasReloaded) {
- const byRevealButton = By.css('.reveal-seed-phrase__secret-blocker .reveal-seed-phrase__reveal-button')
- await driver.wait(until.elementLocated(byRevealButton, 10000))
- const revealSeedPhraseButton = await findElement(driver, byRevealButton, 10000)
- await revealSeedPhraseButton.click()
- await delay(regularDelayMs)
-
- const nextScreen = await findElement(driver, By.css('button.first-time-flow__button'))
- await nextScreen.click()
- await delay(regularDelayMs)
- }
+ it('clicks the "Create New Wallet" option', async () => {
+ const customRpcButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Create a Wallet')]`))
+ customRpcButton.click()
+ await delay(largeDelayMs)
+ })
+
+ it('accepts a secure password', async () => {
+ const passwordBox = await findElement(driver, By.css('.first-time-flow__form #create-password'))
+ const passwordBoxConfirm = await findElement(driver, By.css('.first-time-flow__form #confirm-password'))
+ const button = await findElement(driver, By.css('.first-time-flow__form button'))
+
+ await passwordBox.sendKeys('correct horse battery staple')
+ await passwordBoxConfirm.sendKeys('correct horse battery staple')
+
+ const tosCheckBox = await findElement(driver, By.css('.first-time-flow__checkbox'))
+ await tosCheckBox.click()
+
+ await button.click()
+ await delay(regularDelayMs)
+ })
+
+ it('clicks through the security warning screen', async () => {
+ await findElement(driver, By.xpath(`//div[contains(text(), 'Protect Your Keys!')]`))
+ const nextScreen = await findElement(driver, By.css('button.first-time-flow__button'))
+ await nextScreen.click()
+ await delay(regularDelayMs)
+ })
+
+ let seedPhrase
+
+ it('reveals the seed phrase', async () => {
+ const byRevealButton = By.css('.reveal-seed-phrase__secret-blocker .reveal-seed-phrase__reveal-button')
+ await driver.wait(until.elementLocated(byRevealButton, 10000))
+ const revealSeedPhraseButton = await findElement(driver, byRevealButton, 10000)
+ await revealSeedPhraseButton.click()
+ await delay(regularDelayMs)
+
+ seedPhrase = await driver.findElement(By.css('.reveal-seed-phrase__secret-words')).getText()
+ assert.equal(seedPhrase.split(' ').length, 12)
+ await delay(regularDelayMs)
+
+ const nextScreen = await findElement(driver, By.css('button.first-time-flow__button'))
+ await nextScreen.click()
+ await delay(regularDelayMs)
+ })
+
+ async function clickWordAndWait (word) {
+ const xpath = `//div[contains(@class, 'confirm-seed-phrase__seed-word--shuffled') and not(contains(@class, 'confirm-seed-phrase__seed-word--selected')) and contains(text(), '${word}')]`
+ const word0 = await findElement(driver, By.xpath(xpath), 10000)
+
+ await word0.click()
+ await delay(tinyDelayMs)
+ }
- for (let i = 0; i < 12; i++) {
- await clickWordAndWait(words[i])
- }
- } catch (e) {
- if (count > 2) {
- throw e
- } else {
- await loadExtension(driver, extensionId)
- await retypeSeedPhrase(words, true, count + 1)
+ async function retypeSeedPhrase (words, wasReloaded, count = 0) {
+ try {
+ if (wasReloaded) {
+ const byRevealButton = By.css('.reveal-seed-phrase__secret-blocker .reveal-seed-phrase__reveal-button')
+ await driver.wait(until.elementLocated(byRevealButton, 10000))
+ const revealSeedPhraseButton = await findElement(driver, byRevealButton, 10000)
+ await revealSeedPhraseButton.click()
+ await delay(regularDelayMs)
+
+ const nextScreen = await findElement(driver, By.css('button.first-time-flow__button'))
+ await nextScreen.click()
+ await delay(regularDelayMs)
+ }
+
+ for (let i = 0; i < 12; i++) {
+ await clickWordAndWait(words[i])
+ }
+ } catch (e) {
+ if (count > 2) {
+ throw e
+ } else {
+ await loadExtension(driver, extensionId)
+ await retypeSeedPhrase(words, true, count + 1)
+ }
}
}
- }
- it('can retype the seed phrase', async () => {
- const words = seedPhrase.split(' ')
+ it('can retype the seed phrase', async () => {
+ const words = seedPhrase.split(' ')
- await retypeSeedPhrase(words)
- await delay(regularDelayMs)
+ await retypeSeedPhrase(words)
- const confirm = await findElement(driver, By.xpath(`//button[contains(text(), 'Confirm')]`))
- await confirm.click()
- await delay(regularDelayMs)
- })
+ const confirm = await findElement(driver, By.xpath(`//button[contains(text(), 'Confirm')]`))
+ await confirm.click()
+ await delay(regularDelayMs)
+ })
- it('clicks through the deposit modal', async () => {
- const byBuyModal = By.css('span .modal')
- const buyModal = await driver.wait(until.elementLocated(byBuyModal))
- const closeModal = await findElement(driver, By.css('.page-container__header-close'))
- await closeModal.click()
- await driver.wait(until.stalenessOf(buyModal))
- await delay(regularDelayMs)
+ it('clicks through the success screen', async () => {
+ await findElement(driver, By.xpath(`//div[contains(text(), 'Congratulations')]`))
+ const doneButton = await findElement(driver, By.css('button.first-time-flow__button'))
+ await doneButton.click()
+ await delay(regularDelayMs)
+ })
})
- })
describe('Show account information', () => {
it('show account details dropdown menu', async () => {
diff --git a/test/e2e/beta/metamask-beta-ui.spec.js b/test/e2e/beta/metamask-beta-ui.spec.js
index 798cce372..26aa50a43 100644
--- a/test/e2e/beta/metamask-beta-ui.spec.js
+++ b/test/e2e/beta/metamask-beta-ui.spec.js
@@ -102,11 +102,18 @@ describe('MetaMask', function () {
describe('Going through the first time flow', () => {
it('clicks the continue button on the welcome screen', async () => {
- const welcomeScreenBtn = await findElement(driver, By.css('.welcome-page .first-time-flow__button'))
+ await findElement(driver, By.css('.welcome-page__header'))
+ const welcomeScreenBtn = await findElement(driver, By.css('.first-time-flow__button'))
welcomeScreenBtn.click()
await delay(largeDelayMs)
})
+ it('clicks the "Create New Wallet" option', async () => {
+ const customRpcButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Create a Wallet')]`))
+ customRpcButton.click()
+ await delay(largeDelayMs)
+ })
+
it('accepts a secure password', async () => {
const passwordBox = await findElement(driver, By.css('.first-time-flow__form #create-password'))
const passwordBoxConfirm = await findElement(driver, By.css('.first-time-flow__form #confirm-password'))
@@ -114,43 +121,16 @@ describe('MetaMask', function () {
await passwordBox.sendKeys('correct horse battery staple')
await passwordBoxConfirm.sendKeys('correct horse battery staple')
- await button.click()
- await delay(regularDelayMs)
- })
-
- it('clicks through the unique image screen', async () => {
- await findElement(driver, By.css('.first-time-flow__unique-image'))
- const nextScreen = await findElement(driver, By.css('button.first-time-flow__button'))
- await nextScreen.click()
- await delay(regularDelayMs)
- })
- it('clicks through the ToS', async () => {
- // terms of use
- await findElement(driver, By.css('.first-time-flow__markdown'))
- const canClickThrough = await driver.findElement(By.css('button.first-time-flow__button')).isEnabled()
- assert.equal(canClickThrough, false, 'disabled continue button')
- const bottomOfTos = await findElement(driver, By.linkText('Attributions'))
- await driver.executeScript('arguments[0].scrollIntoView(true)', bottomOfTos)
- await delay(regularDelayMs)
- const acceptTos = await findElement(driver, By.css('button.first-time-flow__button'))
- driver.wait(until.elementIsEnabled(acceptTos))
- await acceptTos.click()
- await delay(regularDelayMs)
- })
+ const tosCheckBox = await findElement(driver, By.css('.first-time-flow__checkbox'))
+ await tosCheckBox.click()
- it('clicks through the privacy notice', async () => {
- // privacy notice
- const nextScreen = await findElement(driver, By.css('button.first-time-flow__button'))
- await nextScreen.click()
+ await button.click()
await delay(regularDelayMs)
})
- it('clicks through the phishing notice', async () => {
- // phishing notice
- const noticeElement = await driver.findElement(By.css('.first-time-flow__markdown'))
- await driver.executeScript('arguments[0].scrollTop = arguments[0].scrollHeight', noticeElement)
- await delay(regularDelayMs)
+ it('clicks through the security warning screen', async () => {
+ await findElement(driver, By.xpath(`//div[contains(text(), 'Protect Your Keys!')]`))
const nextScreen = await findElement(driver, By.css('button.first-time-flow__button'))
await nextScreen.click()
await delay(regularDelayMs)
@@ -219,12 +199,10 @@ describe('MetaMask', function () {
await delay(regularDelayMs)
})
- it('clicks through the deposit modal', async () => {
- const byBuyModal = By.css('span .modal')
- const buyModal = await driver.wait(until.elementLocated(byBuyModal))
- const closeModal = await findElement(driver, By.css('.page-container__header-close'))
- await closeModal.click()
- await driver.wait(until.stalenessOf(buyModal))
+ it('clicks through the success screen', async () => {
+ await findElement(driver, By.xpath(`//div[contains(text(), 'Congratulations')]`))
+ const doneButton = await findElement(driver, By.css('button.first-time-flow__button'))
+ await doneButton.click()
await delay(regularDelayMs)
})
})
diff --git a/ui/app/components/pages/first-time-flow/create-password/create-password.component.js b/ui/app/components/pages/first-time-flow/create-password/create-password.component.js
index 69b1e549f..7cca82ca6 100644
--- a/ui/app/components/pages/first-time-flow/create-password/create-password.component.js
+++ b/ui/app/components/pages/first-time-flow/create-password/create-password.component.js
@@ -8,13 +8,13 @@ import {
INITIALIZE_CREATE_PASSWORD_ROUTE,
INITIALIZE_IMPORT_WITH_SEED_PHRASE_ROUTE,
INITIALIZE_UNIQUE_IMAGE_ROUTE,
- INITIALIZE_NOTICE_ROUTE,
} from '../../../../routes'
export default class CreatePassword extends PureComponent {
static propTypes = {
history: PropTypes.object,
isInitialized: PropTypes.bool,
+ isImportedKeyring: PropTypes.bool,
onCreateNewAccount: PropTypes.func,
onCreateNewAccountFromSeed: PropTypes.func,
}
@@ -23,17 +23,38 @@ export default class CreatePassword extends PureComponent {
const { isInitialized, history } = this.props
if (isInitialized) {
- history.push(INITIALIZE_NOTICE_ROUTE)
+ history.push(INITIALIZE_UNIQUE_IMAGE_ROUTE)
}
}
render () {
- const { onCreateNewAccount, onCreateNewAccountFromSeed } = this.props
+ const { onCreateNewAccount, onCreateNewAccountFromSeed, isImportedKeyring } = this.props
return (
<div className="first-time-flow__wrapper">
+ <div className="app-header__logo-container">
+ <img
+ className="app-header__metafox-logo app-header__metafox-logo--horizontal"
+ src="/images/logo/metamask-logo-horizontal.svg"
+ height={30}
+ />
+ <img
+ className="app-header__metafox-logo app-header__metafox-logo--icon"
+ src="/images/logo/metamask-fox.svg"
+ height={42}
+ width={42}
+ />
+ </div>
<Switch>
- <Route exact path={INITIALIZE_UNIQUE_IMAGE_ROUTE} component={UniqueImage} />
+ <Route exact
+ path={INITIALIZE_UNIQUE_IMAGE_ROUTE}
+ render={props => (
+ <UniqueImage
+ { ...props }
+ isImportedKeyring={isImportedKeyring}
+ />
+ )}
+ />
<Route
exact
path={INITIALIZE_IMPORT_WITH_SEED_PHRASE_ROUTE}
diff --git a/ui/app/components/pages/first-time-flow/create-password/import-with-seed-phrase/import-with-seed-phrase.component.js b/ui/app/components/pages/first-time-flow/create-password/import-with-seed-phrase/import-with-seed-phrase.component.js
index 6f8ab031a..2e99147bb 100644
--- a/ui/app/components/pages/first-time-flow/create-password/import-with-seed-phrase/import-with-seed-phrase.component.js
+++ b/ui/app/components/pages/first-time-flow/create-password/import-with-seed-phrase/import-with-seed-phrase.component.js
@@ -3,10 +3,9 @@ import React, { PureComponent } from 'react'
import PropTypes from 'prop-types'
import TextField from '../../../../text-field'
import Button from '../../../../button'
-import Breadcrumbs from '../../../../breadcrumbs'
import {
- INITIALIZE_CREATE_PASSWORD_ROUTE,
- INITIALIZE_NOTICE_ROUTE,
+ INITIALIZE_SELECT_ACTION_ROUTE,
+ INITIALIZE_UNIQUE_IMAGE_ROUTE,
} from '../../../../../routes'
export default class ImportWithSeedPhrase extends PureComponent {
@@ -26,6 +25,7 @@ export default class ImportWithSeedPhrase extends PureComponent {
seedPhraseError: '',
passwordError: '',
confirmPasswordError: '',
+ termsChecked: false,
}
parseSeedPhrase = (seedPhrase) => {
@@ -104,7 +104,7 @@ export default class ImportWithSeedPhrase extends PureComponent {
try {
await onSubmit(password, seedPhrase)
- history.push(INITIALIZE_NOTICE_ROUTE)
+ history.push(INITIALIZE_UNIQUE_IMAGE_ROUTE)
} catch (error) {
this.setState({ seedPhraseError: error.message })
}
@@ -131,20 +131,26 @@ export default class ImportWithSeedPhrase extends PureComponent {
return !passwordError && !confirmPasswordError && !seedPhraseError
}
+ toggleTermsCheck = () => {
+ this.setState((prevState) => ({
+ termsChecked: !prevState.termsChecked,
+ }))
+ }
+
render () {
const { t } = this.context
- const { seedPhraseError, passwordError, confirmPasswordError } = this.state
+ const { seedPhraseError, passwordError, confirmPasswordError, termsChecked } = this.state
return (
<form
className="first-time-flow__form"
onSubmit={this.handleImport}
>
- <div>
+ <div className="first-time-flow__create-back">
<a
onClick={e => {
e.preventDefault()
- this.props.history.push(INITIALIZE_CREATE_PASSWORD_ROUTE)
+ this.props.history.push(INITIALIZE_SELECT_ACTION_ROUTE)
}}
href="#"
>
@@ -197,19 +203,22 @@ export default class ImportWithSeedPhrase extends PureComponent {
margin="normal"
largeLabel
/>
+ <div className="first-time-flow__checkbox-container" onClick={this.toggleTermsCheck}>
+ <div className="first-time-flow__checkbox">
+ {termsChecked ? <i className="fa fa-check fa-2x" /> : null}
+ </div>
+ <span className="first-time-flow__checkbox-label">
+ { t('agreeTermsOfService') }
+ </span>
+ </div>
<Button
- type="first-time"
+ type="confirm"
className="first-time-flow__button"
- disabled={!this.isValid()}
+ disabled={!this.isValid() || !termsChecked}
onClick={this.handleImport}
>
{ t('import') }
</Button>
- <Breadcrumbs
- className="first-time-flow__breadcrumbs"
- total={2}
- currentIndex={0}
- />
</form>
)
}
diff --git a/ui/app/components/pages/first-time-flow/create-password/new-account/new-account.component.js b/ui/app/components/pages/first-time-flow/create-password/new-account/new-account.component.js
index 54f8c1a70..b82cba0c5 100644
--- a/ui/app/components/pages/first-time-flow/create-password/new-account/new-account.component.js
+++ b/ui/app/components/pages/first-time-flow/create-password/new-account/new-account.component.js
@@ -1,10 +1,10 @@
import React, { PureComponent } from 'react'
import PropTypes from 'prop-types'
-import Breadcrumbs from '../../../../breadcrumbs'
import Button from '../../../../button'
import {
INITIALIZE_UNIQUE_IMAGE_ROUTE,
INITIALIZE_IMPORT_WITH_SEED_PHRASE_ROUTE,
+ INITIALIZE_SELECT_ACTION_ROUTE,
} from '../../../../../routes'
import TextField from '../../../../text-field'
@@ -23,6 +23,7 @@ export default class NewAccount extends PureComponent {
confirmPassword: '',
passwordError: '',
confirmPasswordError: '',
+ termsChecked: false,
}
isValid () {
@@ -111,12 +112,29 @@ export default class NewAccount extends PureComponent {
history.push(INITIALIZE_IMPORT_WITH_SEED_PHRASE_ROUTE)
}
+ toggleTermsCheck = () => {
+ this.setState((prevState) => ({
+ termsChecked: !prevState.termsChecked,
+ }))
+ }
+
render () {
const { t } = this.context
- const { password, confirmPassword, passwordError, confirmPasswordError } = this.state
+ const { password, confirmPassword, passwordError, confirmPasswordError, termsChecked } = this.state
return (
<div>
+ <div className="first-time-flow__create-back">
+ <a
+ onClick={e => {
+ e.preventDefault()
+ this.props.history.push(INITIALIZE_SELECT_ACTION_ROUTE)
+ }}
+ href="#"
+ >
+ {`< Back`}
+ </a>
+ </div>
<div className="first-time-flow__header">
{ t('createPassword') }
</div>
@@ -151,27 +169,23 @@ export default class NewAccount extends PureComponent {
fullWidth
largeLabel
/>
+ <div className="first-time-flow__checkbox-container" onClick={this.toggleTermsCheck}>
+ <div className="first-time-flow__checkbox">
+ {termsChecked ? <i className="fa fa-check fa-2x" /> : null}
+ </div>
+ <span className="first-time-flow__checkbox-label">
+ I agree to the Terms Of Service
+ </span>
+ </div>
<Button
- type="first-time"
+ type="confirm"
className="first-time-flow__button"
- disabled={!this.isValid()}
+ disabled={!this.isValid() || !termsChecked}
onClick={this.handleCreate}
>
{ t('create') }
</Button>
</form>
- <a
- href=""
- className="first-time-flow__link create-password__import-link"
- onClick={this.handleImportWithSeedPhrase}
- >
- { t('importWithSeedPhrase') }
- </a>
- <Breadcrumbs
- className="first-time-flow__breadcrumbs"
- total={3}
- currentIndex={0}
- />
</div>
)
}
diff --git a/ui/app/components/pages/first-time-flow/create-password/unique-image/unique-image.component.js b/ui/app/components/pages/first-time-flow/create-password/unique-image/unique-image.component.js
index 41a566f0a..fa76074f5 100644
--- a/ui/app/components/pages/first-time-flow/create-password/unique-image/unique-image.component.js
+++ b/ui/app/components/pages/first-time-flow/create-password/unique-image/unique-image.component.js
@@ -1,9 +1,7 @@
import React, { PureComponent } from 'react'
import PropTypes from 'prop-types'
-import Identicon from '../../../../identicon'
-import Breadcrumbs from '../../../../breadcrumbs'
import Button from '../../../../button'
-import { INITIALIZE_NOTICE_ROUTE } from '../../../../../routes'
+import { INITIALIZE_SEED_PHRASE_ROUTE, INITIALIZE_END_OF_FLOW_ROUTE } from '../../../../../routes'
export default class UniqueImageScreen extends PureComponent {
static contextTypes = {
@@ -11,42 +9,43 @@ export default class UniqueImageScreen extends PureComponent {
}
static propTypes = {
- address: PropTypes.string,
history: PropTypes.object,
+ isImportedKeyring: PropTypes.bool,
}
render () {
const { t } = this.context
- const { address, history } = this.props
+ const { history, isImportedKeyring } = this.props
return (
<div>
- <Identicon
- className="first-time-flow__unique-image"
- address={address}
- diameter={70}
+ <img
+ src="/images/sleuth.svg"
+ height={42}
+ width={42}
/>
<div className="first-time-flow__header">
- { t('yourUniqueAccountImage') }
+ { t('protectYourKeys') }
</div>
<div className="first-time-flow__text-block">
- { t('yourUniqueAccountImageDescription1') }
+ { t('protectYourKeysMessage1') }
</div>
<div className="first-time-flow__text-block">
- { t('yourUniqueAccountImageDescription2') }
+ { t('protectYourKeysMessage2') }
</div>
<Button
- type="first-time"
+ type="confirm"
className="first-time-flow__button"
- onClick={() => history.push(INITIALIZE_NOTICE_ROUTE)}
+ onClick={() => {
+ if (isImportedKeyring) {
+ history.push(INITIALIZE_END_OF_FLOW_ROUTE)
+ } else {
+ history.push(INITIALIZE_SEED_PHRASE_ROUTE)
+ }
+ }}
>
{ t('next') }
</Button>
- <Breadcrumbs
- className="first-time-flow__breadcrumbs"
- total={3}
- currentIndex={0}
- />
</div>
)
}
diff --git a/ui/app/components/pages/first-time-flow/end-of-flow/end-of-flow.component.js b/ui/app/components/pages/first-time-flow/end-of-flow/end-of-flow.component.js
new file mode 100644
index 000000000..2ca5fd8ec
--- /dev/null
+++ b/ui/app/components/pages/first-time-flow/end-of-flow/end-of-flow.component.js
@@ -0,0 +1,70 @@
+import React, { PureComponent } from 'react'
+import PropTypes from 'prop-types'
+import Button from '../../../button'
+import { DEFAULT_ROUTE } from '../../../../routes'
+
+export default class EndOfFlowScreen extends PureComponent {
+ static contextTypes = {
+ t: PropTypes.func,
+ }
+
+ static propTypes = {
+ history: PropTypes.object,
+ completeOnboarding: PropTypes.func,
+ }
+
+ render () {
+ const { t } = this.context
+ const { history, completeOnboarding } = this.props
+
+ return (
+ <div className="end-of-flow">
+ <div className="app-header__logo-container">
+ <img
+ className="app-header__metafox-logo app-header__metafox-logo--horizontal"
+ src="/images/logo/metamask-logo-horizontal.svg"
+ height={30}
+ />
+ <img
+ className="app-header__metafox-logo app-header__metafox-logo--icon"
+ src="/images/logo/metamask-fox.svg"
+ height={42}
+ width={42}
+ />
+ </div>
+ <div className="end-of-flow__emoji">🎉</div>
+ <div className="first-time-flow__header">
+ { t('congratulations') }
+ </div>
+ <div className="first-time-flow__text-block end-of-flow__text-1">
+ { t('endOfFlowMessage1') }
+ </div>
+ <div className="first-time-flow__text-block end-of-flow__text-2">
+ { t('endOfFlowMessage2') }
+ </div>
+ <div className="first-time-flow__text-block end-of-flow__text-3">
+ { '• ' + t('endOfFlowMessage3') }
+ </div>
+ <div className="first-time-flow__text-block end-of-flow__text-4">
+ { '• ' + t('endOfFlowMessage4') }
+ </div>
+ <div className="first-time-flow__text-block end-of-flow__text-3">
+ { t('endOfFlowMessage5') }
+ </div>
+ <div className="first-time-flow__text-block end-of-flow__text-3">
+ { '*' + t('endOfFlowMessage6') }
+ </div>
+ <Button
+ type="confirm"
+ className="first-time-flow__button"
+ onClick={async () => {
+ await completeOnboarding()
+ history.push(DEFAULT_ROUTE)
+ }}
+ >
+ { 'All Done' }
+ </Button>
+ </div>
+ )
+ }
+}
diff --git a/ui/app/components/pages/first-time-flow/end-of-flow/end-of-flow.container.js b/ui/app/components/pages/first-time-flow/end-of-flow/end-of-flow.container.js
new file mode 100644
index 000000000..ffe2c0efb
--- /dev/null
+++ b/ui/app/components/pages/first-time-flow/end-of-flow/end-of-flow.container.js
@@ -0,0 +1,11 @@
+import { connect } from 'react-redux'
+import EndOfFlow from './end-of-flow.component'
+import { setCompletedOnboarding } from '../../../../actions'
+
+const mapDispatchToProps = dispatch => {
+ return {
+ completeOnboarding: () => dispatch(setCompletedOnboarding()),
+ }
+}
+
+export default connect(null, mapDispatchToProps)(EndOfFlow)
diff --git a/ui/app/components/pages/first-time-flow/end-of-flow/index.js b/ui/app/components/pages/first-time-flow/end-of-flow/index.js
new file mode 100644
index 000000000..b0643d155
--- /dev/null
+++ b/ui/app/components/pages/first-time-flow/end-of-flow/index.js
@@ -0,0 +1 @@
+export { default } from './end-of-flow.container'
diff --git a/ui/app/components/pages/first-time-flow/end-of-flow/index.scss b/ui/app/components/pages/first-time-flow/end-of-flow/index.scss
new file mode 100644
index 000000000..5f5cc5991
--- /dev/null
+++ b/ui/app/components/pages/first-time-flow/end-of-flow/index.scss
@@ -0,0 +1,47 @@
+.end-of-flow {
+ color: black;
+ font-family: Roboto;
+ font-style: normal;
+
+ .app-header__logo-container {
+ width: 742px;
+ margin-top: 3%;
+
+ @media screen and (max-width: $break-small) {
+ width: 100%;
+ }
+ }
+
+ &__text-1, &__text-3 {
+ font-weight: normal;
+ font-size: 16px;
+ margin-top: 18px;
+ }
+
+ &__text-2 {
+ font-weight: bold;
+ font-size: 16px;
+ margin-top: 26px;
+ }
+
+ &__text-3 {
+ margin-top: 26px;
+ }
+
+ &__text-3 {
+ margin-top: 2px;
+ }
+
+ button {
+ width: 207px;
+ }
+
+ &__start-over-button {
+ width: 744px;
+ }
+
+ &__emoji {
+ font-size: 80px;
+ margin-top: 70px;
+ }
+} \ No newline at end of file
diff --git a/ui/app/components/pages/first-time-flow/first-time-flow-switch/first-time-flow-switch.component.js b/ui/app/components/pages/first-time-flow/first-time-flow-switch/first-time-flow-switch.component.js
index 9e8bce2c8..43f792e06 100644
--- a/ui/app/components/pages/first-time-flow/first-time-flow-switch/first-time-flow-switch.component.js
+++ b/ui/app/components/pages/first-time-flow/first-time-flow-switch/first-time-flow-switch.component.js
@@ -5,7 +5,6 @@ import {
DEFAULT_ROUTE,
LOCK_ROUTE,
INITIALIZE_WELCOME_ROUTE,
- INITIALIZE_NOTICE_ROUTE,
INITIALIZE_UNLOCK_ROUTE,
INITIALIZE_SEED_PHRASE_ROUTE,
} from '../../../../routes'
@@ -15,7 +14,6 @@ export default class FirstTimeFlowSwitch extends PureComponent {
completedOnboarding: PropTypes.bool,
isInitialized: PropTypes.bool,
isUnlocked: PropTypes.bool,
- noActiveNotices: PropTypes.bool,
seedPhrase: PropTypes.string,
}
@@ -24,7 +22,6 @@ export default class FirstTimeFlowSwitch extends PureComponent {
completedOnboarding,
isInitialized,
isUnlocked,
- noActiveNotices,
seedPhrase,
} = this.props
@@ -44,10 +41,6 @@ export default class FirstTimeFlowSwitch extends PureComponent {
return <Redirect to={{ pathname: INITIALIZE_UNLOCK_ROUTE }} />
}
- if (!noActiveNotices) {
- return <Redirect to={{ pathname: INITIALIZE_NOTICE_ROUTE }} />
- }
-
if (seedPhrase) {
return <Redirect to={{ pathname: INITIALIZE_SEED_PHRASE_ROUTE }} />
}
diff --git a/ui/app/components/pages/first-time-flow/first-time-flow-switch/first-time-flow-switch.container.js b/ui/app/components/pages/first-time-flow/first-time-flow-switch/first-time-flow-switch.container.js
index 8b7a74880..e44c216c0 100644
--- a/ui/app/components/pages/first-time-flow/first-time-flow-switch/first-time-flow-switch.container.js
+++ b/ui/app/components/pages/first-time-flow/first-time-flow-switch/first-time-flow-switch.container.js
@@ -6,14 +6,12 @@ const mapStateToProps = ({ metamask }) => {
completedOnboarding,
isInitialized,
isUnlocked,
- noActiveNotices,
} = metamask
return {
completedOnboarding,
isInitialized,
isUnlocked,
- noActiveNotices,
}
}
diff --git a/ui/app/components/pages/first-time-flow/first-time-flow.component.js b/ui/app/components/pages/first-time-flow/first-time-flow.component.js
index cde077803..82308dda2 100644
--- a/ui/app/components/pages/first-time-flow/first-time-flow.component.js
+++ b/ui/app/components/pages/first-time-flow/first-time-flow.component.js
@@ -3,17 +3,19 @@ import PropTypes from 'prop-types'
import { Switch, Route } from 'react-router-dom'
import FirstTimeFlowSwitch from './first-time-flow-switch'
import Welcome from './welcome'
+import SelectAction from './select-action'
+import EndOfFlow from './end-of-flow'
import Unlock from '../unlock-page'
import CreatePassword from './create-password'
-import Notices from './notices'
import SeedPhrase from './seed-phrase'
import {
DEFAULT_ROUTE,
INITIALIZE_WELCOME_ROUTE,
INITIALIZE_CREATE_PASSWORD_ROUTE,
- INITIALIZE_NOTICE_ROUTE,
INITIALIZE_SEED_PHRASE_ROUTE,
INITIALIZE_UNLOCK_ROUTE,
+ INITIALIZE_SELECT_ACTION_ROUTE,
+ INITIALIZE_END_OF_FLOW_ROUTE,
} from '../../../routes'
export default class FirstTimeFlow extends PureComponent {
@@ -24,7 +26,6 @@ export default class FirstTimeFlow extends PureComponent {
history: PropTypes.object,
isInitialized: PropTypes.bool,
isUnlocked: PropTypes.bool,
- noActiveNotices: PropTypes.bool,
unlockAccount: PropTypes.func,
}
@@ -70,14 +71,12 @@ export default class FirstTimeFlow extends PureComponent {
}
handleUnlock = async password => {
- const { unlockAccount, history, noActiveNotices } = this.props
+ const { unlockAccount, history } = this.props
try {
const seedPhrase = await unlockAccount(password)
this.setState({ seedPhrase }, () => {
- noActiveNotices
- ? history.push(INITIALIZE_SEED_PHRASE_ROUTE)
- : history.push(INITIALIZE_NOTICE_ROUTE)
+ history.push(INITIALIZE_SEED_PHRASE_ROUTE)
})
} catch (error) {
throw new Error(error.message)
@@ -100,26 +99,21 @@ export default class FirstTimeFlow extends PureComponent {
)}
/>
<Route
- exact
- path={INITIALIZE_NOTICE_ROUTE}
- render={props => (
- <Notices
- { ...props }
- isImportedKeyring={isImportedKeyring}
- />
- )}
- />
- <Route
path={INITIALIZE_CREATE_PASSWORD_ROUTE}
render={props => (
<CreatePassword
{ ...props }
+ isImportedKeyring={isImportedKeyring}
onCreateNewAccount={this.handleCreateNewAccount}
onCreateNewAccountFromSeed={this.handleImportWithSeedPhrase}
/>
)}
/>
<Route
+ path={INITIALIZE_SELECT_ACTION_ROUTE}
+ component={SelectAction}
+ />
+ <Route
path={INITIALIZE_UNLOCK_ROUTE}
render={props => (
<Unlock
@@ -130,6 +124,11 @@ export default class FirstTimeFlow extends PureComponent {
/>
<Route
exact
+ path={INITIALIZE_END_OF_FLOW_ROUTE}
+ component={EndOfFlow}
+ />
+ <Route
+ exact
path={INITIALIZE_WELCOME_ROUTE}
component={Welcome}
/>
diff --git a/ui/app/components/pages/first-time-flow/first-time-flow.container.js b/ui/app/components/pages/first-time-flow/first-time-flow.container.js
index 782eddb74..1419dd59f 100644
--- a/ui/app/components/pages/first-time-flow/first-time-flow.container.js
+++ b/ui/app/components/pages/first-time-flow/first-time-flow.container.js
@@ -7,13 +7,12 @@ import {
} from '../../../actions'
const mapStateToProps = state => {
- const { metamask: { completedOnboarding, isInitialized, isUnlocked, noActiveNotices } } = state
+ const { metamask: { completedOnboarding, isInitialized, isUnlocked } } = state
return {
completedOnboarding,
isInitialized,
isUnlocked,
- noActiveNotices,
}
}
diff --git a/ui/app/components/pages/first-time-flow/index.scss b/ui/app/components/pages/first-time-flow/index.scss
index e3aca0694..e14d57f58 100644
--- a/ui/app/components/pages/first-time-flow/index.scss
+++ b/ui/app/components/pages/first-time-flow/index.scss
@@ -1,18 +1,28 @@
@import './welcome/index';
+@import './select-action/index';
+
@import './seed-phrase/index';
+@import './end-of-flow/index';
+
.first-time-flow {
width: 100%;
background-color: $white;
+ display: flex;
+ justify-content: center;
&__wrapper {
@media screen and (min-width: $break-large) {
- padding: 60px 275px 0 275px;
+ max-width: 742px;
+ display: flex;
+ flex-direction: column;
+ width: 100%;
+ margin-top: 2%;
}
- @media screen and (max-width: 1100px) {
- padding: 36px;
+ .app-header__metafox-logo {
+ margin-bottom: 40px;
}
}
@@ -21,9 +31,14 @@
flex-direction: column;
}
+ &__create-back {
+ margin-bottom: 16px;
+ }
+
&__header {
font-size: 2.5rem;
margin-bottom: 24px;
+ color: black;
}
&__subheader {
@@ -86,6 +101,7 @@
&__text-block {
margin-bottom: 24px;
+ color: black;
@media screen and (max-width: $break-small) {
margin-bottom: 16px;
@@ -95,5 +111,42 @@
&__button {
margin: 35px 0 14px;
+ width: 140px;
+ height: 44px;
+ }
+
+ &__checkbox-container {
+ display: flex;
+ align-items: center;
+ margin-top: 24px;
+ }
+
+ &__checkbox {
+ background: #FFFFFF;
+ border: 1px solid #CDCDCD;
+ box-sizing: border-box;
+ height: 34px;
+ width: 34px;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+
+ &:hover {
+ border: 1.5px solid #2f9ae0;
+ }
+
+ .fa-check {
+ color: #2f9ae0
+ }
+ }
+
+ &__checkbox-label {
+ font-family: Roboto;
+ font-style: normal;
+ font-weight: normal;
+ line-height: normal;
+ font-size: 18px;
+ color: #939090;
+ margin-left: 18px;
}
}
diff --git a/ui/app/components/pages/first-time-flow/notices/index.js b/ui/app/components/pages/first-time-flow/notices/index.js
deleted file mode 100644
index 024daaa68..000000000
--- a/ui/app/components/pages/first-time-flow/notices/index.js
+++ /dev/null
@@ -1 +0,0 @@
-export { default } from './notices.container'
diff --git a/ui/app/components/pages/first-time-flow/notices/notices.component.js b/ui/app/components/pages/first-time-flow/notices/notices.component.js
deleted file mode 100644
index fefaedd6f..000000000
--- a/ui/app/components/pages/first-time-flow/notices/notices.component.js
+++ /dev/null
@@ -1,124 +0,0 @@
-import React, { PureComponent } from 'react'
-import PropTypes from 'prop-types'
-import Markdown from 'react-markdown'
-import debounce from 'lodash.debounce'
-import Button from '../../../button'
-import Identicon from '../../../identicon'
-import Breadcrumbs from '../../../breadcrumbs'
-import { DEFAULT_ROUTE, INITIALIZE_SEED_PHRASE_ROUTE } from '../../../../routes'
-
-export default class Notices extends PureComponent {
- static contextTypes = {
- t: PropTypes.func,
- }
-
- static propTypes = {
- address: PropTypes.string.isRequired,
- completeOnboarding: PropTypes.func,
- history: PropTypes.object,
- isImportedKeyring: PropTypes.bool,
- markNoticeRead: PropTypes.func,
- nextUnreadNotice: PropTypes.shape({
- title: PropTypes.string,
- date: PropTypes.string,
- body: PropTypes.string,
- }),
- noActiveNotices: PropTypes.bool,
- }
-
- static defaultProps = {
- nextUnreadNotice: {},
- }
-
- state = {
- atBottom: false,
- }
-
- componentDidMount () {
- const { noActiveNotices, history } = this.props
-
- if (noActiveNotices) {
- history.push(INITIALIZE_SEED_PHRASE_ROUTE)
- }
-
- this.onScroll()
- }
-
- acceptTerms = async () => {
- const {
- completeOnboarding,
- history,
- isImportedKeyring,
- markNoticeRead,
- nextUnreadNotice,
- } = this.props
-
- const hasActiveNotices = await markNoticeRead(nextUnreadNotice)
-
- if (!hasActiveNotices) {
- if (isImportedKeyring) {
- await completeOnboarding()
- history.push(DEFAULT_ROUTE)
- } else {
- history.push(INITIALIZE_SEED_PHRASE_ROUTE)
- }
- } else {
- this.setState({ atBottom: false }, () => this.onScroll())
- }
- }
-
- onScroll = debounce(() => {
- if (this.state.atBottom) {
- return
- }
-
- const target = document.querySelector('.first-time-flow__markdown')
-
- if (target) {
- const { scrollTop, offsetHeight, scrollHeight } = target
- const atBottom = scrollTop + offsetHeight >= scrollHeight
-
- this.setState({ atBottom })
- }
- }, 25)
-
- render () {
- const { t } = this.context
- const { isImportedKeyring, address, nextUnreadNotice: { title, body } } = this.props
- const { atBottom } = this.state
-
- return (
- <div
- className="first-time-flow__wrapper"
- onScroll={this.onScroll}
- >
- <Identicon
- className="first-time-flow__unique-image"
- address={address}
- diameter={70}
- />
- <div className="first-time-flow__header">
- { title }
- </div>
- <Markdown
- className="first-time-flow__markdown"
- source={body}
- skipHtml
- />
- <Button
- type="first-time"
- className="first-time-flow__button"
- onClick={atBottom && this.acceptTerms}
- disabled={!atBottom}
- >
- { t('accept') }
- </Button>
- <Breadcrumbs
- className="first-time-flow__breadcrumbs"
- total={isImportedKeyring ? 2 : 3}
- currentIndex={1}
- />
- </div>
- )
- }
-}
diff --git a/ui/app/components/pages/first-time-flow/notices/notices.container.js b/ui/app/components/pages/first-time-flow/notices/notices.container.js
deleted file mode 100644
index c65c5b7de..000000000
--- a/ui/app/components/pages/first-time-flow/notices/notices.container.js
+++ /dev/null
@@ -1,27 +0,0 @@
-import { connect } from 'react-redux'
-import { withRouter } from 'react-router-dom'
-import { compose } from 'recompose'
-import { markNoticeRead, setCompletedOnboarding } from '../../../../actions'
-import Notices from './notices.component'
-
-const mapStateToProps = ({ metamask }) => {
- const { selectedAddress, nextUnreadNotice, noActiveNotices } = metamask
-
- return {
- address: selectedAddress,
- nextUnreadNotice,
- noActiveNotices,
- }
-}
-
-const mapDispatchToProps = dispatch => {
- return {
- markNoticeRead: notice => dispatch(markNoticeRead(notice)),
- completeOnboarding: () => dispatch(setCompletedOnboarding()),
- }
-}
-
-export default compose(
- withRouter,
- connect(mapStateToProps, mapDispatchToProps)
-)(Notices)
diff --git a/ui/app/components/pages/first-time-flow/seed-phrase/confirm-seed-phrase/confirm-seed-phrase.component.js b/ui/app/components/pages/first-time-flow/seed-phrase/confirm-seed-phrase/confirm-seed-phrase.component.js
index bc0f73a27..b5c4bf463 100644
--- a/ui/app/components/pages/first-time-flow/seed-phrase/confirm-seed-phrase/confirm-seed-phrase.component.js
+++ b/ui/app/components/pages/first-time-flow/seed-phrase/confirm-seed-phrase/confirm-seed-phrase.component.js
@@ -2,10 +2,8 @@ import React, { PureComponent } from 'react'
import PropTypes from 'prop-types'
import classnames from 'classnames'
import shuffle from 'lodash.shuffle'
-import Identicon from '../../../../identicon'
import Button from '../../../../button'
-import Breadcrumbs from '../../../../breadcrumbs'
-import { DEFAULT_ROUTE, INITIALIZE_SEED_PHRASE_ROUTE } from '../../../../../routes'
+import { INITIALIZE_END_OF_FLOW_ROUTE, INITIALIZE_SEED_PHRASE_ROUTE } from '../../../../../routes'
import { exportAsFile } from '../../../../../../app/util'
import { selectSeedWord, deselectSeedWord } from './confirm-seed-phrase.state'
@@ -19,11 +17,8 @@ export default class ConfirmSeedPhrase extends PureComponent {
}
static propTypes = {
- address: PropTypes.string,
- completeOnboarding: PropTypes.func,
history: PropTypes.object,
onSubmit: PropTypes.func,
- openBuyEtherModal: PropTypes.func,
seedPhrase: PropTypes.string,
}
@@ -45,16 +40,14 @@ export default class ConfirmSeedPhrase extends PureComponent {
}
handleSubmit = async () => {
- const { completeOnboarding, history, openBuyEtherModal } = this.props
+ const { history } = this.props
if (!this.isValid()) {
return
}
try {
- await completeOnboarding()
- history.push(DEFAULT_ROUTE)
- openBuyEtherModal()
+ history.push(INITIALIZE_END_OF_FLOW_ROUTE)
} catch (error) {
console.error(error.message)
}
@@ -76,11 +69,11 @@ export default class ConfirmSeedPhrase extends PureComponent {
render () {
const { t } = this.context
- const { address, history } = this.props
+ const { history } = this.props
const { selectedSeedWords, shuffledSeedWords, selectedSeedWordsHash } = this.state
return (
- <div>
+ <div className="confirm-seed-phrase">
<div className="confirm-seed-phrase__back-button">
<a
onClick={e => {
@@ -92,11 +85,6 @@ export default class ConfirmSeedPhrase extends PureComponent {
{`< Back`}
</a>
</div>
- <Identicon
- className="first-time-flow__unique-image"
- address={address}
- diameter={70}
- />
<div className="first-time-flow__header">
{ t('confirmSecretBackupPhrase') }
</div>
@@ -143,18 +131,13 @@ export default class ConfirmSeedPhrase extends PureComponent {
}
</div>
<Button
- type="first-time"
+ type="confirm"
className="first-time-flow__button"
onClick={this.handleSubmit}
disabled={!this.isValid()}
>
{ t('confirm') }
</Button>
- <Breadcrumbs
- className="first-time-flow__breadcrumbs"
- total={3}
- currentIndex={2}
- />
</div>
)
}
diff --git a/ui/app/components/pages/first-time-flow/seed-phrase/confirm-seed-phrase/confirm-seed-phrase.container.js b/ui/app/components/pages/first-time-flow/seed-phrase/confirm-seed-phrase/confirm-seed-phrase.container.js
deleted file mode 100644
index 5fa2bec1e..000000000
--- a/ui/app/components/pages/first-time-flow/seed-phrase/confirm-seed-phrase/confirm-seed-phrase.container.js
+++ /dev/null
@@ -1,12 +0,0 @@
-import { connect } from 'react-redux'
-import ConfirmSeedPhrase from './confirm-seed-phrase.component'
-import { setCompletedOnboarding, showModal } from '../../../../../actions'
-
-const mapDispatchToProps = dispatch => {
- return {
- completeOnboarding: () => dispatch(setCompletedOnboarding()),
- openBuyEtherModal: () => dispatch(showModal({ name: 'DEPOSIT_ETHER'})),
- }
-}
-
-export default connect(null, mapDispatchToProps)(ConfirmSeedPhrase)
diff --git a/ui/app/components/pages/first-time-flow/seed-phrase/confirm-seed-phrase/index.js b/ui/app/components/pages/first-time-flow/seed-phrase/confirm-seed-phrase/index.js
index beb53b383..c7b511503 100644
--- a/ui/app/components/pages/first-time-flow/seed-phrase/confirm-seed-phrase/index.js
+++ b/ui/app/components/pages/first-time-flow/seed-phrase/confirm-seed-phrase/index.js
@@ -1 +1 @@
-export { default } from './confirm-seed-phrase.container'
+export { default } from './confirm-seed-phrase.component'
diff --git a/ui/app/components/pages/first-time-flow/seed-phrase/confirm-seed-phrase/index.scss b/ui/app/components/pages/first-time-flow/seed-phrase/confirm-seed-phrase/index.scss
index e0444571f..93137618c 100644
--- a/ui/app/components/pages/first-time-flow/seed-phrase/confirm-seed-phrase/index.scss
+++ b/ui/app/components/pages/first-time-flow/seed-phrase/confirm-seed-phrase/index.scss
@@ -41,4 +41,8 @@
padding: 6px 18px;
}
}
+
+ button {
+ margin-top: 0xp;
+ }
}
diff --git a/ui/app/components/pages/first-time-flow/seed-phrase/index.js b/ui/app/components/pages/first-time-flow/seed-phrase/index.js
index 7355bfb2c..185b3f089 100644
--- a/ui/app/components/pages/first-time-flow/seed-phrase/index.js
+++ b/ui/app/components/pages/first-time-flow/seed-phrase/index.js
@@ -1 +1 @@
-export { default } from './seed-phrase.container'
+export { default } from './seed-phrase.component'
diff --git a/ui/app/components/pages/first-time-flow/seed-phrase/index.scss b/ui/app/components/pages/first-time-flow/seed-phrase/index.scss
index 88b28950c..e4fd7be4f 100644
--- a/ui/app/components/pages/first-time-flow/seed-phrase/index.scss
+++ b/ui/app/components/pages/first-time-flow/seed-phrase/index.scss
@@ -26,11 +26,15 @@
min-width: 0;
@media screen and (min-width: $break-large) {
- margin-left: 48px;
+ margin-left: 81px;
}
@media screen and (max-width: $break-small) {
margin-top: 24px;
}
+
+ .first-time-flow__text-block {
+ color: #5A5A5A;
+ }
}
}
diff --git a/ui/app/components/pages/first-time-flow/seed-phrase/reveal-seed-phrase/index.scss b/ui/app/components/pages/first-time-flow/seed-phrase/reveal-seed-phrase/index.scss
index 568359d31..8a47447ed 100644
--- a/ui/app/components/pages/first-time-flow/seed-phrase/reveal-seed-phrase/index.scss
+++ b/ui/app/components/pages/first-time-flow/seed-phrase/reveal-seed-phrase/index.scss
@@ -50,4 +50,8 @@
cursor: pointer;
font-weight: 500;
}
+
+ button {
+ margin-top: 0xp;
+ }
}
diff --git a/ui/app/components/pages/first-time-flow/seed-phrase/reveal-seed-phrase/reveal-seed-phrase.component.js b/ui/app/components/pages/first-time-flow/seed-phrase/reveal-seed-phrase/reveal-seed-phrase.component.js
index bb822d1d5..732ce14af 100644
--- a/ui/app/components/pages/first-time-flow/seed-phrase/reveal-seed-phrase/reveal-seed-phrase.component.js
+++ b/ui/app/components/pages/first-time-flow/seed-phrase/reveal-seed-phrase/reveal-seed-phrase.component.js
@@ -1,10 +1,8 @@
import React, { PureComponent } from 'react'
import PropTypes from 'prop-types'
import classnames from 'classnames'
-import Identicon from '../../../../identicon'
import LockIcon from '../../../../lock-icon'
import Button from '../../../../button'
-import Breadcrumbs from '../../../../breadcrumbs'
import { INITIALIZE_CONFIRM_SEED_PHRASE_ROUTE } from '../../../../../routes'
import { exportAsFile } from '../../../../../../app/util'
@@ -14,7 +12,6 @@ export default class RevealSeedPhrase extends PureComponent {
}
static propTypes = {
- address: PropTypes.string,
history: PropTypes.object,
seedPhrase: PropTypes.string,
}
@@ -75,16 +72,10 @@ export default class RevealSeedPhrase extends PureComponent {
render () {
const { t } = this.context
- const { address } = this.props
const { isShowingSeedPhrase } = this.state
return (
- <div>
- <Identicon
- className="first-time-flow__unique-image"
- address={address}
- diameter={70}
- />
+ <div className="reveal-seed-phrase">
<div className="seed-phrase__sections">
<div className="seed-phrase__main">
<div className="first-time-flow__header">
@@ -121,18 +112,13 @@ export default class RevealSeedPhrase extends PureComponent {
</div>
</div>
<Button
- type="first-time"
+ type="confirm"
className="first-time-flow__button"
onClick={this.handleNext}
disabled={!isShowingSeedPhrase}
>
{ t('next') }
</Button>
- <Breadcrumbs
- className="first-time-flow__breadcrumbs"
- total={3}
- currentIndex={2}
- />
</div>
)
}
diff --git a/ui/app/components/pages/first-time-flow/seed-phrase/seed-phrase.component.js b/ui/app/components/pages/first-time-flow/seed-phrase/seed-phrase.component.js
index 5f5b8a0b2..9eec89cdd 100644
--- a/ui/app/components/pages/first-time-flow/seed-phrase/seed-phrase.component.js
+++ b/ui/app/components/pages/first-time-flow/seed-phrase/seed-phrase.component.js
@@ -25,10 +25,23 @@ export default class SeedPhrase extends PureComponent {
}
render () {
- const { address, seedPhrase } = this.props
+ const { seedPhrase } = this.props
return (
<div className="first-time-flow__wrapper">
+ <div className="app-header__logo-container">
+ <img
+ className="app-header__metafox-logo app-header__metafox-logo--horizontal"
+ src="/images/logo/metamask-logo-horizontal.svg"
+ height={30}
+ />
+ <img
+ className="app-header__metafox-logo app-header__metafox-logo--icon"
+ src="/images/logo/metamask-fox.svg"
+ height={42}
+ width={42}
+ />
+ </div>
<Switch>
<Route
exact
@@ -36,7 +49,6 @@ export default class SeedPhrase extends PureComponent {
render={props => (
<ConfirmSeedPhrase
{ ...props }
- address={address}
seedPhrase={seedPhrase}
/>
)}
@@ -47,7 +59,6 @@ export default class SeedPhrase extends PureComponent {
render={props => (
<RevealSeedPhrase
{ ...props }
- address={address}
seedPhrase={seedPhrase}
/>
)}
diff --git a/ui/app/components/pages/first-time-flow/seed-phrase/seed-phrase.container.js b/ui/app/components/pages/first-time-flow/seed-phrase/seed-phrase.container.js
deleted file mode 100644
index 4df024ffc..000000000
--- a/ui/app/components/pages/first-time-flow/seed-phrase/seed-phrase.container.js
+++ /dev/null
@@ -1,12 +0,0 @@
-import { connect } from 'react-redux'
-import SeedPhrase from './seed-phrase.component'
-
-const mapStateToProps = state => {
- const { metamask: { selectedAddress } } = state
-
- return {
- address: selectedAddress,
- }
-}
-
-export default connect(mapStateToProps)(SeedPhrase)
diff --git a/ui/app/components/pages/first-time-flow/select-action/index.js b/ui/app/components/pages/first-time-flow/select-action/index.js
new file mode 100644
index 000000000..3aa968834
--- /dev/null
+++ b/ui/app/components/pages/first-time-flow/select-action/index.js
@@ -0,0 +1 @@
+export { default } from './select-action.component'
diff --git a/ui/app/components/pages/first-time-flow/select-action/index.scss b/ui/app/components/pages/first-time-flow/select-action/index.scss
new file mode 100644
index 000000000..b9585eb3b
--- /dev/null
+++ b/ui/app/components/pages/first-time-flow/select-action/index.scss
@@ -0,0 +1,87 @@
+.select-action {
+ .app-header__logo-container {
+ width: 742px;
+ margin-top: 3%;
+ }
+
+ &__body {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ }
+
+ &__body-header {
+ font-family: Roboto;
+ font-style: normal;
+ font-weight: normal;
+ line-height: 39px;
+ font-size: 28px;
+ text-align: center;
+ margin-top: 65px;
+ color: black;
+ }
+
+ &__select-buttons {
+ display: flex;
+ flex-direction: row;
+ margin-top: 40px;
+ }
+
+ &__select-button {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: space-evenly;
+ width: 269px;
+ height: 278px;
+
+ border: 1px solid #D8D8D8;
+ box-sizing: border-box;
+ border-radius: 10px;
+ margin-left: 22px;
+
+ .first-time-flow__button {
+ max-width: 221px;
+ height: 44px;
+ }
+ }
+
+ &__button-symbol {
+ color: #C4C4C4;
+ margin-top: 41px;
+ }
+
+ &__button-content {
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ height: 144px;
+ }
+
+ &__button-text-big {
+ font-family: Roboto;
+ font-style: normal;
+ font-weight: normal;
+ line-height: 28px;
+ font-size: 20px;
+ color: #000000;
+ margin-top: 12px;
+ text-align: center;
+ }
+
+ &__button-text-small {
+ font-family: Roboto;
+ font-style: normal;
+ font-weight: normal;
+ line-height: 20px;
+ font-size: 14px;
+ color: #7A7A7B;
+ margin-top: 10px;
+ }
+
+ button {
+ font-weight: 500;
+ width: 221px;
+ }
+} \ No newline at end of file
diff --git a/ui/app/components/pages/first-time-flow/select-action/select-action.component.js b/ui/app/components/pages/first-time-flow/select-action/select-action.component.js
new file mode 100644
index 000000000..385efe02a
--- /dev/null
+++ b/ui/app/components/pages/first-time-flow/select-action/select-action.component.js
@@ -0,0 +1,104 @@
+import React, { PureComponent } from 'react'
+import PropTypes from 'prop-types'
+import Button from '../../../button'
+import {
+ INITIALIZE_CREATE_PASSWORD_ROUTE,
+ INITIALIZE_IMPORT_WITH_SEED_PHRASE_ROUTE,
+ INITIALIZE_UNIQUE_IMAGE_ROUTE,
+} from '../../../../routes'
+
+export default class SelectAction extends PureComponent {
+ static propTypes = {
+ history: PropTypes.object,
+ isInitialized: PropTypes.bool,
+ }
+
+ static contextTypes = {
+ t: PropTypes.func,
+ }
+
+ componentDidMount () {
+ const { history, isInitialized } = this.props
+
+ if (isInitialized) {
+ history.push(INITIALIZE_UNIQUE_IMAGE_ROUTE)
+ }
+ }
+
+ handleCreate = () => {
+ this.props.history.push(INITIALIZE_CREATE_PASSWORD_ROUTE)
+ }
+
+ handleImport = () => {
+ this.props.history.push(INITIALIZE_IMPORT_WITH_SEED_PHRASE_ROUTE)
+ }
+
+ render () {
+ const { t } = this.context
+
+ return (
+ <div className="select-action">
+ <div className="app-header__logo-container">
+ <img
+ className="app-header__metafox-logo app-header__metafox-logo--horizontal"
+ src="/images/logo/metamask-logo-horizontal.svg"
+ height={30}
+ />
+ <img
+ className="app-header__metafox-logo app-header__metafox-logo--icon"
+ src="/images/logo/metamask-fox.svg"
+ height={42}
+ width={42}
+ />
+ </div>
+
+ <div className="select-action__wrapper">
+
+
+ <div className="select-action__body">
+ <div className="select-action__body-header">
+ { t('newToMetaMask') }
+ </div>
+ <div className="select-action__select-buttons">
+ <div className="select-action__select-button">
+ <div className="select-action__button-content">
+ <div className="select-action__button-symbol">
+ <img src="/images/download-alt.svg" />
+ </div>
+ <div className="select-action__button-text-big">
+ { t('noAlreadyHaveSeed') }
+ </div>
+ </div>
+ <Button
+ type="primary"
+ className="first-time-flow__button"
+ onClick={this.handleImport}
+ >
+ { t('importWallet') }
+ </Button>
+ </div>
+ <div className="select-action__select-button">
+ <div className="select-action__button-content">
+ <div className="select-action__button-symbol">
+ <img src="/images/thin-plus.svg" />
+ </div>
+ <div className="select-action__button-text-big">
+ { t('letsGoSetUp') }
+ </div>
+ </div>
+ <Button
+ type="confirm"
+ className="first-time-flow__button"
+ onClick={this.handleCreate}
+ >
+ { t('createAWallet') }
+ </Button>
+ </div>
+ </div>
+ </div>
+
+ </div>
+ </div>
+ )
+ }
+}
diff --git a/ui/app/components/pages/first-time-flow/select-action/select-action.container.js b/ui/app/components/pages/first-time-flow/select-action/select-action.container.js
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/ui/app/components/pages/first-time-flow/select-action/select-action.container.js
diff --git a/ui/app/components/pages/first-time-flow/welcome/index.scss b/ui/app/components/pages/first-time-flow/welcome/index.scss
index 7527ceb35..3b5071480 100644
--- a/ui/app/components/pages/first-time-flow/welcome/index.scss
+++ b/ui/app/components/pages/first-time-flow/welcome/index.scss
@@ -1,43 +1,42 @@
.welcome-page {
display: flex;
flex-direction: column;
- justify-content: center;
+ justify-content: flex-start;
align-items: center;
- width: 400px;
+ max-width: 442px;
padding: 0 18px;
+ color: black;
&__wrapper {
display: flex;
flex-direction: row;
justify-content: center;
- align-items: center;
+ align-items: flex-start;
height: 100%;
+ margin-top: 110px;
}
&__header {
- font-size: 1.5rem;
- margin-bottom: 14px;
+ font-size: 28px;
+ margin-bottom: 22px;
+ margin-top: 50px;
}
&__description {
text-align: center;
+ div {
+ font-size: 16px;
+ }
+
@media screen and (max-width: 575px) {
font-size: .9rem;
}
}
- &__button {
- height: 54px;
- width: 198px;
- font-family: Roboto;
- box-shadow: 0 2px 4px 0 rgba(0, 0, 0, .14);
- color: $white;
- font-size: 1.25rem;
+ .first-time-flow__button {
+ width: 184px;
font-weight: 500;
- text-transform: uppercase;
- margin: 35px 0 14px;
- transition: 200ms ease-in-out;
- background-color: rgba(247, 134, 28, .9);
+ margin-top: 44px;
}
}
diff --git a/ui/app/components/pages/first-time-flow/welcome/welcome.component.js b/ui/app/components/pages/first-time-flow/welcome/welcome.component.js
index f28a8210d..08eb86939 100644
--- a/ui/app/components/pages/first-time-flow/welcome/welcome.component.js
+++ b/ui/app/components/pages/first-time-flow/welcome/welcome.component.js
@@ -3,7 +3,7 @@ import React, { PureComponent } from 'react'
import PropTypes from 'prop-types'
import Mascot from '../../../mascot'
import Button from '../../../button'
-import { INITIALIZE_CREATE_PASSWORD_ROUTE, INITIALIZE_NOTICE_ROUTE } from '../../../../routes'
+import { INITIALIZE_SELECT_ACTION_ROUTE, INITIALIZE_UNIQUE_IMAGE_ROUTE } from '../../../../routes'
export default class Welcome extends PureComponent {
static propTypes = {
@@ -25,12 +25,12 @@ export default class Welcome extends PureComponent {
const { history, isInitialized } = this.props
if (isInitialized) {
- history.push(INITIALIZE_NOTICE_ROUTE)
+ history.push(INITIALIZE_UNIQUE_IMAGE_ROUTE)
}
}
handleContinue = () => {
- this.props.history.push(INITIALIZE_CREATE_PASSWORD_ROUTE)
+ this.props.history.push(INITIALIZE_SELECT_ACTION_ROUTE)
}
render () {
@@ -41,22 +41,22 @@ export default class Welcome extends PureComponent {
<div className="welcome-page">
<Mascot
animationEventEmitter={this.animationEventEmitter}
- width="225"
- height="225"
+ width="125"
+ height="125"
/>
<div className="welcome-page__header">
{ t('welcome') }
</div>
<div className="welcome-page__description">
<div>{ t('metamaskDescription') }</div>
- <div>{ t('holdEther') }</div>
+ <div>{ t('happyToSeeYou') }</div>
</div>
<Button
- type="first-time"
+ type="confirm"
className="first-time-flow__button"
onClick={this.handleContinue}
>
- { t('continue') }
+ { t('getStarted') }
</Button>
</div>
</div>
diff --git a/ui/app/components/pages/home/home.component.js b/ui/app/components/pages/home/home.component.js
index 469c760a6..953d43aba 100644
--- a/ui/app/components/pages/home/home.component.js
+++ b/ui/app/components/pages/home/home.component.js
@@ -10,15 +10,12 @@ import {
INITIALIZE_SEED_PHRASE_ROUTE,
RESTORE_VAULT_ROUTE,
CONFIRM_TRANSACTION_ROUTE,
- NOTICE_ROUTE,
CONFIRM_ADD_SUGGESTED_TOKEN_ROUTE,
} from '../../../routes'
export default class Home extends PureComponent {
static propTypes = {
history: PropTypes.object,
- noActiveNotices: PropTypes.bool,
- lostAccounts: PropTypes.array,
forgottenPassword: PropTypes.bool,
seedWords: PropTypes.string,
suggestedTokens: PropTypes.object,
@@ -45,18 +42,11 @@ export default class Home extends PureComponent {
render () {
const {
- noActiveNotices,
- lostAccounts,
forgottenPassword,
seedWords,
providerRequests,
} = this.props
- // notices
- if (!noActiveNotices || (lostAccounts && lostAccounts.length > 0)) {
- return <Redirect to={{ pathname: NOTICE_ROUTE }} />
- }
-
// seed words
if (seedWords) {
return <Redirect to={{ pathname: INITIALIZE_SEED_PHRASE_ROUTE }}/>
diff --git a/ui/app/routes.js b/ui/app/routes.js
index 2f4863547..7c4e805ab 100644
--- a/ui/app/routes.js
+++ b/ui/app/routes.js
@@ -25,7 +25,9 @@ const INITIALIZE_IMPORT_ACCOUNT_ROUTE = '/initialize/create-password/import-acco
const INITIALIZE_IMPORT_WITH_SEED_PHRASE_ROUTE = '/initialize/create-password/import-with-seed-phrase'
const INITIALIZE_UNIQUE_IMAGE_ROUTE = '/initialize/create-password/unique-image'
const INITIALIZE_NOTICE_ROUTE = '/initialize/notice'
+const INITIALIZE_SELECT_ACTION_ROUTE = '/initialize/select-action'
const INITIALIZE_SEED_PHRASE_ROUTE = '/initialize/seed-phrase'
+const INITIALIZE_END_OF_FLOW_ROUTE = '/initialize/end-of-flow'
const INITIALIZE_CONFIRM_SEED_PHRASE_ROUTE = '/initialize/seed-phrase/confirm'
const CONFIRM_TRANSACTION_ROUTE = '/confirm-transaction'
@@ -64,8 +66,10 @@ module.exports = {
INITIALIZE_IMPORT_WITH_SEED_PHRASE_ROUTE,
INITIALIZE_UNIQUE_IMAGE_ROUTE,
INITIALIZE_NOTICE_ROUTE,
+ INITIALIZE_SELECT_ACTION_ROUTE,
INITIALIZE_SEED_PHRASE_ROUTE,
INITIALIZE_CONFIRM_SEED_PHRASE_ROUTE,
+ INITIALIZE_END_OF_FLOW_ROUTE,
CONFIRM_TRANSACTION_ROUTE,
CONFIRM_SEND_ETHER_PATH,
CONFIRM_SEND_TOKEN_PATH,