PathDetails.tsx 5.96 KB
Newer Older
1
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
Hanwen Cheng's avatar
Hanwen Cheng committed
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// This file is part of Parity.

// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// Parity is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with Parity.  If not, see <http://www.gnu.org/licenses/>.

17
import { StackNavigationProp } from '@react-navigation/stack';
Hanwen Cheng's avatar
Hanwen Cheng committed
18
import React from 'react';
19
import { ScrollView, StyleSheet, View } from 'react-native';
20

21
import QRScannerAndDerivationTab from 'components/QRScannerAndDerivationTab';
22
import { SafeAreaViewContainer } from 'components/SafeAreaContainer';
23
24
import { defaultNetworkKey, UnknownNetworkKeys } from 'constants/networkSpecs';
import testIDs from 'e2e/testIDs';
25
// TODO use typescript 3.8's type import, Wait for prettier update.
26
27
import { AccountsStoreStateWithIdentity } from 'types/identityTypes';
import { NavigationAccountIdentityProps } from 'types/props';
28
import { RootStackParamList } from 'types/routes';
29
import { withAccountStore, withCurrentIdentity } from 'utils/HOC';
30
31
32
33
34
import PathCard from 'components/PathCard';
import PopupMenu from 'components/PopupMenu';
import { LeftScreenHeading } from 'components/ScreenHeading';
import colors from 'styles/colors';
import QrView from 'components/QrView';
Hanwen Cheng's avatar
Hanwen Cheng committed
35
import {
36
	getAddressWithPath,
37
	getNetworkKey,
38
	getPathName,
39
	getPathsWithSubstrateNetworkKey,
40
	isSubstrateHardDerivedPath,
Hanwen Cheng's avatar
Hanwen Cheng committed
41
	isSubstratePath
42
43
} from 'utils/identitiesUtils';
import { alertDeleteAccount, alertPathDeletionError } from 'utils/alertUtils';
44
import { navigateToPathsList, useUnlockSeed } from 'utils/navigationHelpers';
45
import { generateAccountId } from 'utils/account';
46
import { UnknownAccountWarning } from 'components/Warnings';
47
import { useSeedRef } from 'utils/seedRefHooks';
Hanwen Cheng's avatar
Hanwen Cheng committed
48

49
interface Props {
50
51
	path: string;
	networkKey: string;
52
53
54
	navigation:
		| StackNavigationProp<RootStackParamList, 'PathDetails'>
		| StackNavigationProp<RootStackParamList, 'PathsList'>;
55
	accounts: AccountsStoreStateWithIdentity;
56
57
58
59
60
61
62
63
}

export function PathDetailsView({
	accounts,
	navigation,
	path,
	networkKey
}: Props): React.ReactElement {
Hanwen Cheng's avatar
Hanwen Cheng committed
64
	const { currentIdentity } = accounts.state;
65
66
	const address = getAddressWithPath(path, currentIdentity);
	const accountName = getPathName(path, currentIdentity);
67
	const { isSeedRefValid } = useSeedRef(currentIdentity.encryptedSeed);
68
69
70
	const { unlockWithoutPassword, unlockWithPassword } = useUnlockSeed(
		isSeedRefValid
	);
71
	if (!address) return <View />;
72
73
	const isUnknownNetwork = networkKey === UnknownNetworkKeys.UNKNOWN;
	const formattedNetworkKey = isUnknownNetwork ? defaultNetworkKey : networkKey;
74
75
	const accountId = generateAccountId({
		address,
76
		networkKey: formattedNetworkKey
77
	});
Hanwen Cheng's avatar
Hanwen Cheng committed
78

79
80
81
82
83
84
	const onTapDeriveButton = (): Promise<void> =>
		unlockWithoutPassword({
			name: 'PathDerivation',
			params: { parentPath: path }
		});

85
	const onOptionSelect = async (value: string): Promise<void> => {
86
87
88
		switch (value) {
			case 'PathDelete':
				alertDeleteAccount('this account', async () => {
89
90
					try {
						await accounts.deletePath(path);
91
92
						if (isSubstratePath(path)) {
							const listedPaths = getPathsWithSubstrateNetworkKey(
93
								accounts.state.currentIdentity,
94
								networkKey
95
96
97
							);
							const hasOtherPaths = listedPaths.length > 0;
							hasOtherPaths
98
								? navigateToPathsList(navigation, networkKey)
99
								: navigation.navigate('Main');
100
						} else {
101
							navigation.navigate('Main');
102
						}
103
104
					} catch (err) {
						alertPathDeletionError(err);
105
106
107
					}
				});
				break;
108
			case 'PathExport': {
109
110
				const pathMeta = currentIdentity.meta.get(path)!;
				if (pathMeta.hasPassword) {
111
112
113
114
115
116
117
					await unlockWithPassword(password => ({
						name: 'PathSecret',
						params: {
							password,
							path
						}
					}));
118
				} else {
119
					await unlockWithoutPassword({ name: 'PathSecret', params: { path } });
120
121
122
				}
				break;
			}
123
124
125
			case 'PathManagement':
				navigation.navigate('PathManagement', { path });
				break;
Hanwen Cheng's avatar
Hanwen Cheng committed
126
127
128
129
		}
	};

	return (
130
131
132
133
134
135
136
137
138
139
140
141
		<SafeAreaViewContainer>
			<ScrollView testID={testIDs.PathDetail.screen} bounces={false}>
				<LeftScreenHeading
					title="Public Address"
					networkKey={formattedNetworkKey}
					headMenu={
						<PopupMenu
							testID={testIDs.PathDetail.popupMenuButton}
							onSelect={onOptionSelect}
							menuTriggerIconName={'more-vert'}
							menuItems={[
								{ text: 'Edit', value: 'PathManagement' },
142
143
144
145
								{
									hide: !isSubstrateHardDerivedPath(path),
									testID: testIDs.PathDetail.exportButton,
									text: 'Export Account',
146
									value: 'PathExport'
147
								},
148
149
150
151
152
153
154
155
156
157
158
159
160
161
								{
									testID: testIDs.PathDetail.deleteButton,
									text: 'Delete',
									textStyle: styles.deleteText,
									value: 'PathDelete'
								}
							]}
						/>
					}
				/>
				<PathCard identity={currentIdentity} path={path} />
				<QrView data={`${accountId}:${accountName}`} />
				{isUnknownNetwork && <UnknownAccountWarning isPath />}
			</ScrollView>
162
163
164
165
166
167
168
			{isSubstratePath(path) && (
				<QRScannerAndDerivationTab
					derivationTestID={testIDs.PathDetail.deriveButton}
					title="Derive New Account"
					onPress={onTapDeriveButton}
				/>
			)}
169
		</SafeAreaViewContainer>
Hanwen Cheng's avatar
Hanwen Cheng committed
170
171
172
	);
}

173
174
function PathDetails({
	accounts,
175
176
	navigation,
	route
177
}: NavigationAccountIdentityProps<'PathDetails'>): React.ReactElement {
178
	const path = route.params.path;
179
	const networkKey = getNetworkKey(path, accounts.state.currentIdentity);
Hanwen Cheng's avatar
Hanwen Cheng committed
180
181
182
183
184
185
186
187
188
189
190
191
	return (
		<PathDetailsView
			accounts={accounts}
			navigation={navigation}
			path={path}
			networkKey={networkKey}
		/>
	);
}

const styles = StyleSheet.create({
	deleteText: {
192
		color: colors.signal.error
Hanwen Cheng's avatar
Hanwen Cheng committed
193
194
195
	}
});

196
export default withAccountStore(withCurrentIdentity(PathDetails));