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/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/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 @@
+
+
\ No newline at end of file
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;
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/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/src/view/seed-mobile.js b/src/view/seed-mobile.js
new file mode 100644
index 000000000..856db739b
--- /dev/null
+++ b/src/view/seed-mobile.js
@@ -0,0 +1,131 @@
+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 { 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';
+
+//
+// Seed (Mobile) View
+//
+
+const styles = StyleSheet.create({
+ backBtn: {
+ alignSelf: 'flex-start',
+ marginTop: 5,
+ },
+ content: {
+ justifyContent: 'center',
+ backgroundColor: color.blackDark,
+ },
+ pagination: {
+ marginBottom: 10,
+ },
+});
+
+const SeedView = ({ store, wallet }) => (
+
+
+ wallet.initPrevSeedPage()}
+ />
+
+
+
+
+
+
+
+ {`${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',
+ maxWidth: 350,
+ 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: 8,
+ 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);
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', () => (
))
diff --git a/test/unit/action/wallet.spec.js b/test/unit/action/wallet.spec.js
index 2cda55e0b..a9079b836 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', () => {
+ 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', () => {
+ 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;