diff --git a/e2e/identityManipulation.spec.js b/e2e/identityManipulation.spec.js index fc8f292244..4fd427704e 100644 --- a/e2e/identityManipulation.spec.js +++ b/e2e/identityManipulation.spec.js @@ -114,12 +114,6 @@ describe('Load test', async () => { await testSetUpDefaultPath(); }); - it('starts with a root account', async () => { - await testTap(PathsList.rootButton); - await expect(element(by.text('Root'))).toExist(); - await tapBack(); - }); - it('is able to create custom path', async () => { await tapBack(); await testTap(testIDs.AccountNetworkChooser.addNewNetworkButton); diff --git a/e2e/testIDs.js b/e2e/testIDs.js index e40ba22c17..424ffe359f 100644 --- a/e2e/testIDs.js +++ b/e2e/testIDs.js @@ -74,7 +74,6 @@ const testIDs = { PathsList: { deriveButton: 'path_list_derive_button', pathCard: 'path_list_path_card', - rootButton: 'path_list_root_button', scanButton: 'path_list_scan_button', screen: 'path_list_screen' }, diff --git a/specs/util/identitiesUtils.spec.js b/specs/util/identitiesUtils.spec.js index cb09b6b23a..9cec36a8b1 100644 --- a/specs/util/identitiesUtils.spec.js +++ b/specs/util/identitiesUtils.spec.js @@ -87,7 +87,7 @@ const raw = [ }, { address: 'addressRoot', - expectName: '', + expectName: 'Identity root', name: '', path: '' }, @@ -162,19 +162,23 @@ describe('IdentitiesUtils', () => { const groupResult = groupPaths(kusamaPaths); expect(groupResult).toEqual([ { - paths: [paths[0]], + paths: ['//kusama'], + title: 'Kusama root' + }, + { + paths: ['//kusama//default'], title: '//default' }, { - paths: [paths[2]], + paths: ['//kusama/softKey1'], title: '/softKey1' }, { - paths: [paths[4]], + paths: ['//kusama//staking/1'], title: '//staking' }, { - paths: [paths[1], paths[3]], + paths: ['//kusama//funding/1', '//kusama//funding/2'], title: '//funding' } ]); @@ -192,8 +196,8 @@ describe('IdentitiesUtils', () => { const groupResult = groupPaths(unKnownPaths); expect(groupResult).toEqual([ { - paths: ['//polkadot//default'], - title: '//polkadot' + paths: [''], + title: 'Identity root' }, { paths: ['//custom'], @@ -203,6 +207,10 @@ describe('IdentitiesUtils', () => { paths: ['/polkadot/1'], title: '/polkadot' }, + { + paths: ['//polkadot//default'], + title: '//polkadot' + }, { paths: ['/kusama', '/kusama/1'], title: '/kusama' diff --git a/src/components/CompatibleCard.js b/src/components/CompatibleCard.js index 17b83e42dd..0bed99e91d 100644 --- a/src/components/CompatibleCard.js +++ b/src/components/CompatibleCard.js @@ -20,8 +20,6 @@ import PropTypes from 'prop-types'; import AccountCard from './AccountCard'; import PathCard from './PathCard'; import React from 'react'; -import { getIdentityName } from '../util/identitiesUtils'; -import { defaultNetworkKey } from '../constants'; const CompatibleCard = ({ account, accountsStore, titlePrefix }) => account.isLegacy === true || account.isLegacy === undefined ? ( @@ -30,12 +28,6 @@ const CompatibleCard = ({ account, accountsStore, titlePrefix }) => address={account.address} networkKey={account.networkKey || ''} /> - ) : account.path === '' ? ( - ) : ( { iconName="arrowleft" iconType="antdesign" onPress={onPress} - style={[baseStyles.icon, { left: 0, top: -8 }]} + style={[baseStyles.icon, { left: 0 }]} iconBgStyle={{ backgroundColor: 'transparent' }} /> ); @@ -91,12 +89,21 @@ const renderIcon = (iconName, iconType) => { ); }; -export function PathCardHeading({ title, networkKey }) { +export function LeftScreenHeading({ + title, + subtitle, + hasSubtitleIcon, + networkKey +}) { const titleStyle = composeStyle( fontStyles.h2, baseStyles.t_left, baseStyles.t_normal ); + const titleStyleWithSubtitle = composeStyle( + baseStyles.text, + baseStyles.t_left + ); return ( - {title} + + {title} + + {renderSubtitle(subtitle, hasSubtitleIcon, true, false, false)} ); } -export function PathListHeading({ +export function IdentityHeading({ title, subtitle, hasSubtitleIcon, - testID, - networkKey, - onPress + onPressBack }) { return ( - - - - {title} - {renderSubtitle(subtitle, hasSubtitleIcon, true, false, false)} - - - ); -} - -export function IdentityHeading({ onPress, title, subtitle, hasSubtitleIcon }) { - return ( - - - - - {title} - - - - {renderSubtitle(subtitle, hasSubtitleIcon, true, false, false)} + + + + {title} + - + {onPressBack && renderBack(onPressBack)} + {renderSubtitle(subtitle, hasSubtitleIcon, true, false, false)} + ); } @@ -167,7 +148,7 @@ export default class ScreenHeading extends React.PureComponent { static propTypes = { onPress: PropTypes.func, subtitle: PropTypes.string, - title: PropTypes.string + title: PropTypes.string.isRequired }; render() { const { @@ -176,7 +157,6 @@ export default class ScreenHeading extends React.PureComponent { subtitleL, hasSubtitleIcon, error, - onPress, iconName, iconType } = this.props; @@ -185,7 +165,6 @@ export default class ScreenHeading extends React.PureComponent { {title} {renderSubtitle(subtitle, hasSubtitleIcon, subtitleL, error, true)} - {renderBack(onPress)} {renderIcon(iconName, iconType)} ); @@ -203,7 +182,9 @@ const baseStyles = StyleSheet.create({ marginBottom: 16 }, bodyWithIdentity: { + flexDirection: 'column', height: 42, + justifyContent: 'center', paddingLeft: 72, paddingRight: 32 }, @@ -241,10 +222,5 @@ const baseStyles = StyleSheet.create({ text: { ...fontStyles.h1, textAlign: 'center' - }, - touchable: { - flex: 1, - flexDirection: 'column', - justifyContent: 'center' } }); diff --git a/src/constants.js b/src/constants.js index 45c904f875..a1fd90b295 100644 --- a/src/constants.js +++ b/src/constants.js @@ -60,7 +60,7 @@ const unknownNetworkBase = { prefix: 2, protocol: NetworkProtocols.UNKNOWN, secondaryColor: colors.card_bgSolid, - title: 'Unknown network' + title: 'Custom network' } }; diff --git a/src/screens/AccountNetworkChooser.js b/src/screens/AccountNetworkChooser.js index 738bd1c8e4..e91245c95e 100644 --- a/src/screens/AccountNetworkChooser.js +++ b/src/screens/AccountNetworkChooser.js @@ -26,12 +26,10 @@ import { NETWORK_LIST, UnknownNetworkKeys, SubstrateNetworkKeys, - NetworkProtocols, - defaultNetworkKey + NetworkProtocols } from '../constants'; import { navigateToPathsList, - navigateToRootPath, navigateToSubstrateRoot, unlockSeedPhrase } from '../util/navigationHelpers'; @@ -142,7 +140,7 @@ function AccountNetworkChooser({ navigation, accounts }) { `//${pathId}`, seedPhrase, networkKey, - 'Root' + `${networkParams.title} root` ); onDerivationFinished(derivationSucceed, networkKey, true); }; @@ -192,41 +190,14 @@ function AccountNetworkChooser({ navigation, accounts }) { return ; } else if (shouldShowMoreNetworks) { return ( - setShouldShowMoreNetworks(false)} + onPressBack={() => setShouldShowMoreNetworks(false)} /> ); } else { const identityName = getIdentityName(currentIdentity, identities); - const rootAccount = currentIdentity.meta.get(''); - const rootAddress = rootAccount ? rootAccount.address : ''; - const onRootKeyPress = async () => { - if (rootAccount == null) { - const seedPhrase = await unlockSeedPhrase(navigation); - const derivationSucceed = await accounts.deriveNewPath( - '', - seedPhrase, - defaultNetworkKey, - '' - ); - if (!derivationSucceed) { - return alertPathDerivationError(); - } else { - navigateToRootPath(navigation); - } - } else { - navigation.navigate('PathDetails', { path: '' }); - } - }; - return ( - - ); + return ; } }; diff --git a/src/screens/PathDetails.js b/src/screens/PathDetails.js index c36b8c9f28..78a8dc95f7 100644 --- a/src/screens/PathDetails.js +++ b/src/screens/PathDetails.js @@ -22,12 +22,11 @@ import { withNavigation } from 'react-navigation'; import { ScrollView, StyleSheet, View } from 'react-native'; import PathCard from '../components/PathCard'; import PopupMenu from '../components/PopupMenu'; -import { PathCardHeading } from '../components/ScreenHeading'; +import { LeftScreenHeading } from '../components/ScreenHeading'; import colors from '../colors'; import QrView from '../components/QrView'; import { getAddressWithPath, - getIdentityName, getNetworkKeyByPath, getPathName, getPathsWithSubstrateNetwork, @@ -54,7 +53,6 @@ export function PathDetailsView({ accounts, navigation, path, networkKey }) { }); const isUnknownNetwork = networkKey === UnknownNetworkKeys.UNKNOWN; //TODO enable user to select networkKey. - const isRootPath = path === ''; const formattedNetworkKey = isUnknownNetwork ? defaultNetworkKey : networkKey; const onOptionSelect = value => { @@ -67,7 +65,7 @@ export function PathDetailsView({ accounts, navigation, path, networkKey }) { const listedPaths = getPathsWithSubstrateNetwork(paths, networkKey); const hasOtherPaths = listedPaths.length > 0; if (deleteSucceed) { - isSubstratePath(path) && !isRootPath && hasOtherPaths + isSubstratePath(path) && hasOtherPaths ? navigateToPathsList(navigation, networkKey) : navigation.navigate('AccountNetworkChooser'); } else { @@ -86,7 +84,7 @@ export function PathDetailsView({ accounts, navigation, path, networkKey }) { return ( - @@ -96,7 +94,7 @@ export function PathDetailsView({ accounts, navigation, path, networkKey }) { onSelect={onOptionSelect} menuTriggerIconName={'more-vert'} menuItems={[ - { hide: isUnknownNetwork, text: 'Edit', value: 'PathManagement' }, + { text: 'Edit', value: 'PathManagement' }, { text: 'Derive Account', value: 'PathDerivation' }, { testID: testIDs.PathDetail.deleteButton, @@ -111,11 +109,7 @@ export function PathDetailsView({ accounts, navigation, path, networkKey }) { {isUnknownNetwork ? ( <> diff --git a/src/screens/PathsList.js b/src/screens/PathsList.js index 44f118ff79..31dc931047 100644 --- a/src/screens/PathsList.js +++ b/src/screens/PathsList.js @@ -28,7 +28,6 @@ import { withAccountStore } from '../util/HOC'; import { withNavigation } from 'react-navigation'; import { getPathsWithSubstrateNetwork, - getRootPathMeta, groupPaths, removeSlash } from '../util/identitiesUtils'; @@ -40,15 +39,7 @@ import testIDs from '../../e2e/testIDs'; import Separator from '../components/Separator'; import fontStyles from '../fontStyles'; import colors from '../colors'; -import { PathListHeading } from '../components/ScreenHeading'; -import { - alertDeriveRootPath, - alertPathDerivationError -} from '../util/alertUtils'; -import { - navigateToPathDetails, - unlockSeedPhrase -} from '../util/navigationHelpers'; +import { LeftScreenHeading } from '../components/ScreenHeading'; function PathsList({ accounts, navigation }) { const networkKey = navigation.getParam( @@ -83,29 +74,6 @@ function PathsList({ accounts, navigation }) { const { navigate } = navigation; const rootPath = `//${networkParams.pathId}`; - const onClickRootPath = () => { - if (isUnknownNetworkPath) return; - const rootPathMeta = getRootPathMeta(currentIdentity, networkKey); - if (rootPathMeta) { - navigate('PathDetails', { path: rootPath }); - } else { - alertDeriveRootPath(async () => { - const seedPhrase = await unlockSeedPhrase(navigation); - const derivationSucceed = await accounts.deriveNewPath( - rootPath, - seedPhrase, - networkKey, - '' - ); - if (derivationSucceed) { - navigateToPathDetails(navigation, networkKey, rootPath); - } else { - alertPathDerivationError(); - } - }); - } - }; - const renderSinglePath = pathsGroup => { const path = pathsGroup.paths[0]; return ( @@ -176,10 +144,8 @@ function PathsList({ accounts, navigation }) { : `//${networkParams.pathId}`; return ( - - navigation.navigate('PathDerivation', { parentPath: rootPath }) - } - /> - )} + + navigation.navigate('PathDerivation', { + parentPath: isUnknownNetworkPath ? '' : rootPath + }) + } + /> ); diff --git a/src/stores/AccountsStore.js b/src/stores/AccountsStore.js index fb5637023d..9ec09e943f 100644 --- a/src/stores/AccountsStore.js +++ b/src/stores/AccountsStore.js @@ -360,8 +360,6 @@ export default class AccountsStore extends Container { //TODO encrypt seedPhrase with password in the future version, // current encryption with only seedPhrase is compatible. updatedIdentity.encryptedSeed = await encryptData(seedPhrase, pin); - //TODO now hard coded to polkadot canary prefix which is 2, future enable user to change that. - await this._addPathToIdentity('', seedPhrase, updatedIdentity, 'Root', 2); const newIdentities = this.state.identities.concat(updatedIdentity); this.setState({ currentIdentity: updatedIdentity, diff --git a/src/util/alertUtils.js b/src/util/alertUtils.js index 052d546403..ab2935dc02 100644 --- a/src/util/alertUtils.js +++ b/src/util/alertUtils.js @@ -81,13 +81,6 @@ This identity can only be recovered with its associated recovery phrase.`, ); }; -export const alertDeriveRootPath = onDeriveRootPath => - Alert.alert( - 'Create Root Path', - 'By confirm you are about to create the root account for this network', - buildAlertButtons(onDeriveRootPath, 'Confirm') - ); - export const alertCopyBackupPhrase = seedPhrase => Alert.alert( 'Write this recovery phrase on paper', diff --git a/src/util/identitiesUtils.js b/src/util/identitiesUtils.js index 5cc2b5bc0d..a6db1777ea 100644 --- a/src/util/identitiesUtils.js +++ b/src/util/identitiesUtils.js @@ -149,15 +149,6 @@ export const getAddressWithPath = (path, identity) => { : address; }; -export const getRootPathMeta = (identity, networkKey) => { - const rootPathId = `//${NETWORK_LIST[networkKey].pathId}`; - if (identity.meta.has(rootPathId)) { - return identity.meta.get(rootPathId); - } else { - return null; - } -}; - export const unlockIdentitySeed = async (pin, identity) => { const { encryptedSeed } = identity; const seed = await decryptData(encryptedSeed, pin); @@ -168,7 +159,6 @@ export const unlockIdentitySeed = async (pin, identity) => { export const getExistedNetworkKeys = identity => { const pathsList = Array.from(identity.addresses.values()); const networkKeysSet = pathsList.reduce((networksSet, path) => { - if (path === '') return networksSet; let networkKey; if (isSubstratePath(path)) { networkKey = getNetworkKeyByPath(path); @@ -199,9 +189,8 @@ export const getPathName = (path, lookUpIdentity) => { ) { return lookUpIdentity.meta.get(path).name; } - if (!isSubstratePath(path)) { - return 'No name'; - } + if (!isSubstratePath(path)) return 'No name'; + if (path === '') return 'Identity root'; return extractSubPathName(path); }; @@ -226,25 +215,35 @@ export const groupPaths = paths => { const groupedPaths = paths.reduce((groupedPath, path) => { if (path === '') { + groupedPath.push({ paths: [''], title: 'Identity root' }); return groupedPath; } + const rootPath = path.match(pathsRegex.firstPath)[0]; - const isUnknownRootPath = Object.values(NETWORK_LIST).every( - v => `//${v.pathId}` !== rootPath + const networkParams = Object.values(NETWORK_LIST).find( + v => `//${v.pathId}` === rootPath ); - if (isUnknownRootPath) { + if (networkParams === undefined) { insertPathIntoGroup(path, path, groupedPath); return groupedPath; } const isRootPath = path === rootPath; - if (isRootPath) return groupedPath; + if (isRootPath) { + groupedPath.push({ paths: [path], title: `${networkParams.title} root` }); + return groupedPath; + } const subPath = path.slice(rootPath.length); insertPathIntoGroup(subPath, path, groupedPath); return groupedPath; }, []); - return groupedPaths.sort((a, b) => a.paths.length - b.paths.length); + return groupedPaths.sort((a, b) => { + if (a.paths.length === 1 && b.paths.length === 1) { + return a.paths[0].length - b.paths[0].length; + } + return a.paths.length - b.paths.length; + }); }; diff --git a/src/util/navigationHelpers.js b/src/util/navigationHelpers.js index 5af5db0e2d..92b6178bb3 100644 --- a/src/util/navigationHelpers.js +++ b/src/util/navigationHelpers.js @@ -142,9 +142,6 @@ export const navigateToSignedMessage = navigation => export const navigateToSignedTx = navigation => resetNavigationWithNetworkChooser(navigation, 'SignedTx', { isNew: true }); -export const navigateToRootPath = navigation => - resetNavigationWithNetworkChooser(navigation, 'PathDetails', { path: '' }); - export const navigateToPathsList = (navigation, networkKey) => resetNavigationWithNetworkChooser(navigation, 'PathsList', { networkKey });