From db6296cfd91ad8a7e5bc41975900f5d727873529 Mon Sep 17 00:00:00 2001 From: Valentine Wallace Date: Thu, 29 Nov 2018 22:40:57 +0000 Subject: [PATCH 1/7] Add actions for mobile seed view pagination/navigation. --- src/action/wallet.js | 30 ++++++++++++++++++++++++++- src/store.js | 1 + test/unit/action/wallet.spec.js | 36 ++++++++++++++++++++++++++++++++- 3 files changed, 65 insertions(+), 2 deletions(-) diff --git a/src/action/wallet.js b/src/action/wallet.js index af2617957..44ae414cf 100644 --- a/src/action/wallet.js +++ b/src/action/wallet.js @@ -274,13 +274,41 @@ class WalletAction { } /** - * Initialize the seed flow by navigating to the proper next view. + * Initialize the seed flow by navigating to the proper next view and + * resetting the current seed index. * @return {undefined} */ initSeed() { + this._store.wallet.seedIndex = 0; this._nav.goSeedIntro ? this._nav.goSeedIntro() : this._nav.goSeed(); } + /** + * Initialize the next seed view by setting a new seedIndex or, if all seed + * words have been displayed, navigating to the mobile seed verify view. + * @return {undefined} + */ + initNextSeedPage() { + if (this._store.wallet.seedIndex < 16) { + this._store.wallet.seedIndex += 8; + } else { + this.initSeedVerify(); + } + } + + /** + * Initialize the previous seed view by setting a new seedIndex or, if on the + * first seed page, navigating to the select seed view. + * @return {undefined} + */ + initPrevSeedPage() { + if (this._store.wallet.seedIndex >= 8) { + this._store.wallet.seedIndex -= 8; + } else { + this._nav.goSelectSeed(); + } + } + /** * Initialize the restore wallet view by resetting input values and then * navigating to the view. diff --git a/src/store.js b/src/store.js index 4a838840f..498beebbd 100644 --- a/src/store.js +++ b/src/store.js @@ -47,6 +47,7 @@ export class Store { newPassword: '', passwordVerify: '', seedVerify: ['', '', ''], + seedIndex: 0, restoring: false, restoreIndex: 0, restoreSeed: Array(24).fill(''), diff --git a/test/unit/action/wallet.spec.js b/test/unit/action/wallet.spec.js index 2cda55e0b..44113abd5 100644 --- a/test/unit/action/wallet.spec.js +++ b/test/unit/action/wallet.spec.js @@ -310,8 +310,10 @@ describe('Action Wallet Unit Tests', () => { }); describe('initSeed()', () => { - it('should navigate to seed view', () => { + it('should clear attributes and navigate to view', () => { + store.wallet.seedIndex = 42; wallet.initSeed(); + expect(store.wallet.seedIndex, 'to equal', 0); expect(nav.goSeed, 'was called once'); }); @@ -323,6 +325,38 @@ describe('Action Wallet Unit Tests', () => { }); }); + describe('initPrevSeedPage()', () => { + it('should navigate to select seed if seedIndex < 8', () => { + store.wallet.seedIndex = 7; + wallet.initPrevSeedPage(); + expect(nav.goSelectSeed, 'was called once'); + expect(store.wallet.seedIndex, 'to equal', 7); + }); + + it('should decrement seedIndex if greater than 7', async () => { + store.wallet.seedIndex = 8; + wallet.initPrevSeedPage(); + expect(nav.goSelectSeed, 'was not called'); + expect(store.wallet.seedIndex, 'to equal', 0); + }); + }); + + describe('initNextSeedPage()', () => { + it('should init seed verify if seedIndex > 16', () => { + store.wallet.seedIndex = 16; + wallet.initNextSeedPage(); + expect(nav.goSeedVerify, 'was called'); + expect(store.wallet.seedIndex, 'to equal', 16); + }); + + it('should increment seedIndex if less than 16', async () => { + store.wallet.seedIndex = 8; + wallet.initNextSeedPage(); + expect(nav.goSeedVerify, 'was not called'); + expect(store.wallet.seedIndex, 'to equal', 16); + }); + }); + describe('initRestoreWallet()', () => { it('should clear attributes and navigate to view', () => { store.wallet.restoreIndex = 42; From 7ab0ff333955fb9fbc16545acbb89fe6983e9247 Mon Sep 17 00:00:00 2001 From: Valentine Wallace Date: Thu, 29 Nov 2018 22:44:07 +0000 Subject: [PATCH 2/7] Add screen for Seed (Mobile). --- src/view/seed-mobile.js | 145 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 145 insertions(+) create mode 100644 src/view/seed-mobile.js diff --git a/src/view/seed-mobile.js b/src/view/seed-mobile.js new file mode 100644 index 000000000..fd3d659c6 --- /dev/null +++ b/src/view/seed-mobile.js @@ -0,0 +1,145 @@ +import React from 'react'; +import { View, StyleSheet } from 'react-native'; +import { observer } from 'mobx-react'; +import PropTypes from 'prop-types'; +import MainContent from '../component/main-content'; +import { Text } from '../component/text'; +import { Background } from '../component/background'; +import { Header } from '../component/header'; +import { Button, BackButton, GlasButton } from '../component/button'; +import LightningBoltIcon from '../asset/icon/lightning-bolt'; +import { color, font } from '../component/style'; + +// +// Seed (Mobile) View +// + +const styles = StyleSheet.create({ + header: { + height: 150, + }, + title: { + alignItems: 'center', + }, + titleTxt: { + width: 200, + marginTop: 10, + textAlign: 'center', + fontSize: 15, + letterSpacing: 2, + }, + background: { + flex: 1, + justifyContent: 'space-between', + backgroundColor: color.blackDark, + }, + seed: { + flex: 1, + justifyContent: 'center', + alignItems: 'center', + }, + pagination: { + paddingBottom: 10, + }, +}); + +const SeedView = ({ store, wallet }) => ( + +
+ wallet.initPrevSeedPage()} /> + + + + Write down each word and store it in a safe place. + + +
+ + + + + {`${store.wallet.seedIndex + 8} of 24`} + + + wallet.initNextSeedPage()}>Next + +
+); + +SeedView.propTypes = { + store: PropTypes.object.isRequired, + wallet: PropTypes.object.isRequired, +}; + +// +// Word List +// + +const listStyles = StyleSheet.create({ + wrapper: { + justifyContent: 'center', + margin: 20, + }, + words: { + flexDirection: 'row', + flexWrap: 'wrap', + justifyContent: 'center', + }, +}); + +const WordList = ({ seedMnemonic, startingIndex }) => ( + + + {seedMnemonic.map((word, i) => ( + + ))} + + +); + +WordList.propTypes = { + seedMnemonic: PropTypes.array.isRequired, + startingIndex: PropTypes.number, +}; + +// +// Word +// + +const wordStyles = StyleSheet.create({ + wrapper: { + justifyContent: 'center', + height: 45, + width: 115, + margin: 10, + borderWidth: 1, + borderColor: color.seedBorder, + backgroundColor: color.seedBackground, + }, + word: { + fontSize: font.sizeS * 1.2, + paddingLeft: 10, + }, +}); + +const Word = ({ word, index }) => ( + + + {index}. {word} + + +); + +Word.propTypes = { + word: PropTypes.string.isRequired, + index: PropTypes.number.isRequired, +}; + +export default observer(SeedView); From 226bd7f297985199e1aec1887747478c7628e0f1 Mon Sep 17 00:00:00 2001 From: Valentine Wallace Date: Thu, 29 Nov 2018 22:51:04 +0000 Subject: [PATCH 3/7] Wire up navigation for Seed (Mobile). --- src/action/index-mobile.js | 26 ++++++++++++++++++++++++++ src/view/main-mobile.js | 8 +++++--- stories/screen-story.js | 6 +++--- 3 files changed, 34 insertions(+), 6 deletions(-) diff --git a/src/action/index-mobile.js b/src/action/index-mobile.js index 64302027f..8e277d656 100644 --- a/src/action/index-mobile.js +++ b/src/action/index-mobile.js @@ -208,6 +208,32 @@ store.selectedTransaction = (store.computedTransactions || []).find( tx => tx.type === 'bitcoin' ); store.selectedChannel = store.computedChannels && store.computedChannels[0]; +store.seedMnemonic = [ + 'empower', + 'neglect', + 'experience', + 'elevator', + 'entropy', + 'future', + 'trust', + 'swift', + 'pluck', + 'easy', + 'kite', + 'measure', + 'engage', + 'settle', + 'dog', + 'manager', + 'tool', + 'fan', + 'neglect', + 'conduct', + 'blouse', + 'stone', + 'quit', + 'cashew', +]; store.logs = [ '[14:00:24.995] [info] Using lnd in path lnd', 'Checking for update', diff --git a/src/view/main-mobile.js b/src/view/main-mobile.js index e2a675945..1b78f355a 100644 --- a/src/view/main-mobile.js +++ b/src/view/main-mobile.js @@ -10,6 +10,7 @@ import WelcomeView from './welcome'; import LoaderView from './loader'; import SelectSeedView from './select-seed'; import SeedIntroView from './seed-intro-mobile'; +import SeedView from './seed-mobile'; import SetPinView from './set-pin-mobile'; import SetPinConfirmView from './set-pin-confirm-mobile'; import SeedSuccessView from './seed-success-mobile'; @@ -59,9 +60,9 @@ const Welcome = () => ; const Loader = () => ; -const SelectSeed = () => ( - -); +const SelectSeed = () => ; + +const Seed = () => ; const SeedIntro = () => ; @@ -167,6 +168,7 @@ const MainStack = createStackNavigator( Loader, SelectSeed, SeedIntro, + Seed, SetPassword, SetPasswordConfirm, SeedSuccess, diff --git a/stories/screen-story.js b/stories/screen-story.js index 225ba3cfb..93a0f3109 100644 --- a/stories/screen-story.js +++ b/stories/screen-story.js @@ -63,6 +63,7 @@ import SeedIntro from '../src/view/seed-intro-mobile'; import SeedSuccess from '../src/view/seed-success'; import SeedSuccessMobile from '../src/view/seed-success-mobile'; import Seed from '../src/view/seed'; +import SeedMobile from '../src/view/seed-mobile'; import SeedVerify from '../src/view/seed-verify'; import SetPassword from '../src/view/set-password'; import SetPinMobile from '../src/view/set-pin-mobile'; @@ -118,11 +119,10 @@ sinon.stub(auth, '_generateWalletPassword'); storiesOf('Screens', module) .add('Welcome', () => ) .add('Loader - First Time', () => ) - .add('Select Seed', () => ( - - )) + .add('Select Seed', () => ) .add('Seed Intro (Mobile)', () => ) .add('Seed', () => ) + .add('Seed (Mobile)', () => ) .add('Seed Verify', () => ( )) From 48bb55e62976f3d9648888382b2cda1f62aeac9c Mon Sep 17 00:00:00 2001 From: Tankred Hase Date: Thu, 10 Jan 2019 19:01:45 +0700 Subject: [PATCH 4/7] Add seed svg --- src/asset/icon/seed.js | 34 ++++++++++++++++++++++++++++++++++ src/asset/icon/seed.svg | 31 +++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+) create mode 100644 src/asset/icon/seed.js create mode 100644 src/asset/icon/seed.svg diff --git a/src/asset/icon/seed.js b/src/asset/icon/seed.js new file mode 100644 index 000000000..252f3d62b --- /dev/null +++ b/src/asset/icon/seed.js @@ -0,0 +1,34 @@ +import React from 'react'; +import Svg, { Defs, Path, G, Use } from '../../component/svg'; + +// SVGR has dropped some elements not supported by react-native-svg: filter, feOffset, feGaussianBlur, feColorMatrix +const SvgSeed = props => ( + + + + + + + + + + + + +); + +export default SvgSeed; diff --git a/src/asset/icon/seed.svg b/src/asset/icon/seed.svg new file mode 100644 index 000000000..b67503947 --- /dev/null +++ b/src/asset/icon/seed.svg @@ -0,0 +1,31 @@ + + + + Group + Created with Sketch. + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file From 1a7ec72077186476738c8c9fcaf2cdfce574b416 Mon Sep 17 00:00:00 2001 From: Tankred Hase Date: Thu, 10 Jan 2019 19:15:45 +0700 Subject: [PATCH 5/7] Implement large title header component --- src/component/header.js | 47 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 45 insertions(+), 2 deletions(-) diff --git a/src/component/header.js b/src/component/header.js index 864affbda..71684a4de 100644 --- a/src/component/header.js +++ b/src/component/header.js @@ -3,7 +3,7 @@ import { View, StyleSheet } from 'react-native'; import PropTypes from 'prop-types'; import { createStyles, maxWidth } from './media-query'; import Text from './text'; -import { color, breakWidth } from './style'; +import { color, font, breakWidth } from './style'; // // Header @@ -11,7 +11,7 @@ import { color, breakWidth } from './style'; const baseStyles = { header: { - height: 75, + minHeight: 75, flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', @@ -107,4 +107,47 @@ Title.propTypes = { children: PropTypes.node, }; +// +// Large Title +// + +const largeTitleStyles = StyleSheet.create({ + titleWrapper: { + alignItems: 'center', + paddingTop: 15, + paddingBottom: 15, + }, + title: { + maxWidth: 200, + textAlign: 'center', + fontSize: font.sizeSub, + lineHeight: font.lineHeightSub, + letterSpacing: 1, + }, + titleIcon: { + marginTop: 10, + }, +}); + +export const LargeTitle = ({ title = '', style, children }) => ( + + {children} + + {title} + + +); + +LargeTitle.propTypes = { + title: PropTypes.string, + style: Text.propTypes.style, + children: PropTypes.node, +}; + export default Header; From ca7d7f69cc4d6abb8ee3d2239c286dd3c77817d8 Mon Sep 17 00:00:00 2001 From: Tankred Hase Date: Thu, 10 Jan 2019 19:16:03 +0700 Subject: [PATCH 6/7] Refactor seed-mobile view --- src/view/seed-mobile.js | 86 +++++++++++++++++------------------------ 1 file changed, 36 insertions(+), 50 deletions(-) diff --git a/src/view/seed-mobile.js b/src/view/seed-mobile.js index fd3d659c6..856db739b 100644 --- a/src/view/seed-mobile.js +++ b/src/view/seed-mobile.js @@ -4,10 +4,10 @@ import { observer } from 'mobx-react'; import PropTypes from 'prop-types'; import MainContent from '../component/main-content'; import { Text } from '../component/text'; -import { Background } from '../component/background'; -import { Header } from '../component/header'; -import { Button, BackButton, GlasButton } from '../component/button'; -import LightningBoltIcon from '../asset/icon/lightning-bolt'; +import { SplitBackground } from '../component/background'; +import { Header, LargeTitle } from '../component/header'; +import { Button, BackButton, SmallGlasButton } from '../component/button'; +import SeedIcon from '../asset/icon/seed'; import { color, font } from '../component/style'; // @@ -15,62 +15,47 @@ import { color, font } from '../component/style'; // const styles = StyleSheet.create({ - header: { - height: 150, + backBtn: { + alignSelf: 'flex-start', + marginTop: 5, }, - title: { - alignItems: 'center', - }, - titleTxt: { - width: 200, - marginTop: 10, - textAlign: 'center', - fontSize: 15, - letterSpacing: 2, - }, - background: { - flex: 1, - justifyContent: 'space-between', - backgroundColor: color.blackDark, - }, - seed: { - flex: 1, + content: { justifyContent: 'center', - alignItems: 'center', + backgroundColor: color.blackDark, }, pagination: { - paddingBottom: 10, + marginBottom: 10, }, }); const SeedView = ({ store, wallet }) => ( - -
- wallet.initPrevSeedPage()} /> - - - - Write down each word and store it in a safe place. - - + +
+ wallet.initPrevSeedPage()} + /> + + +
- - - - - {`${store.wallet.seedIndex + 8} of 24`} - - - wallet.initNextSeedPage()}>Next + + + + {`${store.wallet.seedIndex + 8} of 24`} + - + wallet.initNextSeedPage()}> + Next + +
); SeedView.propTypes = { @@ -85,6 +70,7 @@ SeedView.propTypes = { const listStyles = StyleSheet.create({ wrapper: { justifyContent: 'center', + maxWidth: 350, margin: 20, }, words: { @@ -118,7 +104,7 @@ const wordStyles = StyleSheet.create({ justifyContent: 'center', height: 45, width: 115, - margin: 10, + margin: 8, borderWidth: 1, borderColor: color.seedBorder, backgroundColor: color.seedBackground, From f5080b77c50a1e857ec9a292ac63d685c6dc8114 Mon Sep 17 00:00:00 2001 From: Valentine Wallace Date: Fri, 11 Jan 2019 22:05:43 +0000 Subject: [PATCH 7/7] Remove unnecessary async in seed unit tests. --- test/unit/action/wallet.spec.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/unit/action/wallet.spec.js b/test/unit/action/wallet.spec.js index 44113abd5..a9079b836 100644 --- a/test/unit/action/wallet.spec.js +++ b/test/unit/action/wallet.spec.js @@ -333,7 +333,7 @@ describe('Action Wallet Unit Tests', () => { expect(store.wallet.seedIndex, 'to equal', 7); }); - it('should decrement seedIndex if greater than 7', async () => { + it('should decrement seedIndex if greater than 7', () => { store.wallet.seedIndex = 8; wallet.initPrevSeedPage(); expect(nav.goSelectSeed, 'was not called'); @@ -349,7 +349,7 @@ describe('Action Wallet Unit Tests', () => { expect(store.wallet.seedIndex, 'to equal', 16); }); - it('should increment seedIndex if less than 16', async () => { + it('should increment seedIndex if less than 16', () => { store.wallet.seedIndex = 8; wallet.initNextSeedPage(); expect(nav.goSeedVerify, 'was not called');