ScreenHeading.tsx 5.93 KB
Newer Older
Hanwen Cheng's avatar
Hanwen Cheng committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
// 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
18
import React, { ReactElement, ReactNode } from 'react';
import { View, StyleSheet, Text, ViewStyle, TextStyle } from 'react-native';
Hanwen Cheng's avatar
Hanwen Cheng committed
19
20
import AntIcon from 'react-native-vector-icons/AntDesign';
import { Icon } from 'react-native-elements';
21
22

import ButtonIcon from './ButtonIcon';
23
24
import AccountIcon from './AccountIcon';

25
import testIDs from 'e2e/testIDs';
26
27
28
29
30
import { NETWORK_LIST } from 'constants/networkSpecs';
import fontStyles from 'styles/fontStyles';
import fonts from 'styles/fonts';
import colors from 'styles/colors';
import { ButtonListener } from 'types/props';
31

32
const renderSubtitle = (
33
34
35
36
37
38
	subtitle?: string,
	hasSubtitleIcon?: boolean,
	isAlignLeft?: boolean,
	isError?: boolean,
	multiline?: boolean
): ReactNode => {
39
	if (!subtitle || subtitle === '') return;
40
	const subtitleBodyStyle: ViewStyle[] = [baseStyles.subtitleBody],
41
42
43
44
		subtitleTextStyle: TextStyle[] = [
			fontStyles.t_codeS,
			{ color: colors.text.faded }
		];
45
46
47
48
49
50
51
52
53
54
	if (isAlignLeft) {
		subtitleBodyStyle.push({ justifyContent: 'flex-start' });
		subtitleTextStyle.push({ textAlign: 'left' });
	}
	if (isError) {
		subtitleTextStyle.push(baseStyles.t_error);
	}

	return (
		<View style={subtitleBodyStyle}>
55
			{renderSubtitleIcon(hasSubtitleIcon)}
56
57
58
59
60
			<Text
				style={subtitleTextStyle}
				numberOfLines={multiline ? undefined : 1}
				ellipsizeMode="middle"
			>
61
62
				{subtitle}
			</Text>
63
64
65
		</View>
	);
};
66
const renderSubtitleIcon = (hasSubtitleIcon?: boolean): ReactNode => {
67
	if (!hasSubtitleIcon) return;
68
	return <AntIcon name="user" size={10} color={colors.text.faded} />;
69
70
};

71
const renderBack = (onPress?: ButtonListener): ReactNode => {
72
73
74
75
76
77
	if (!onPress) return;
	return (
		<ButtonIcon
			iconName="arrowleft"
			iconType="antdesign"
			onPress={onPress}
78
			testID={testIDs.Main.backButton}
79
			style={StyleSheet.flatten([baseStyles.icon, { left: 0 }])}
80
81
82
83
			iconBgStyle={{ backgroundColor: 'transparent' }}
		/>
	);
};
84
const renderIcon = (iconName?: string, iconType?: string): ReactNode => {
85
86
87
	if (!iconName) return;
	return (
		<View style={[baseStyles.icon, { paddingLeft: 16 }]}>
88
			<Icon name={iconName} type={iconType} color={colors.text.main} />
89
90
91
92
		</View>
	);
};

93
94
95
96
export function LeftScreenHeading({
	title,
	subtitle,
	hasSubtitleIcon,
97
	headMenu,
98
	networkKey
99
100
101
102
}: {
	title: string;
	subtitle?: string;
	hasSubtitleIcon?: boolean;
103
	headMenu?: React.ReactElement;
104
105
106
107
108
109
110
111
112
113
114
	networkKey: string;
}): ReactElement {
	const titleStyle: TextStyle = {
		...fontStyles.h2,
		...baseStyles.t_left,
		...baseStyles.t_normal
	};
	const titleStyleWithSubtitle: TextStyle = {
		...baseStyles.text,
		...baseStyles.t_left
	};
115
116
	return (
		<View style={baseStyles.bodyWithIcon}>
117
118
119
120
121
122
123
124
125
126
127
128
			<View style={{ alignItems: 'center', flexDirection: 'row' }}>
				<AccountIcon
					address={''}
					network={NETWORK_LIST[networkKey]}
					style={baseStyles.networkIcon}
				/>
				<View>
					<Text style={subtitle ? titleStyleWithSubtitle : titleStyle}>
						{title}
					</Text>
					{renderSubtitle(subtitle, hasSubtitleIcon, true, false, false)}
				</View>
129
			</View>
130
			{headMenu}
131
132
133
134
		</View>
	);
}

135
export function IdentityHeading({
136
137
	title,
	subtitle,
138
	hasSubtitleIcon,
139
	onPressBack
140
141
142
143
144
145
}: {
	title: string;
	subtitle?: string;
	hasSubtitleIcon?: boolean;
	onPressBack?: ButtonListener;
}): ReactElement {
146
	return (
147
148
149
150
151
152
153
154
155
		<View style={baseStyles.bodyWithIdentity}>
			<View style={baseStyles.identityName}>
				<Text
					style={[baseStyles.text, baseStyles.t_left]}
					numberOfLines={1}
					ellipsizeMode="middle"
				>
					{title}
				</Text>
156
			</View>
157
158
159
			{onPressBack && renderBack(onPressBack)}
			{renderSubtitle(subtitle, hasSubtitleIcon, true, false, false)}
		</View>
160
161
	);
}
Hanwen Cheng's avatar
Hanwen Cheng committed
162

163
164
165
166
export default class ScreenHeading extends React.PureComponent<{
	subtitle?: string;
	subtitleL?: boolean;
	hasSubtitleIcon?: boolean;
167
	headMenu?: React.ReactElement;
168
169
170
171
172
173
174
	title: string;
	onPress?: ButtonListener;
	error?: boolean;
	iconName?: string;
	iconType?: string;
}> {
	render(): ReactElement {
Hanwen Cheng's avatar
Hanwen Cheng committed
175
176
177
178
		const {
			title,
			subtitle,
			subtitleL,
179
			hasSubtitleIcon,
180
			headMenu,
Hanwen Cheng's avatar
Hanwen Cheng committed
181
182
183
184
185
186
			error,
			iconName,
			iconType
		} = this.props;

		return (
187
			<View style={{ ...baseStyles.body, flexDirection: 'row' }}>
188
				{renderIcon(iconName, iconType)}
189
190
191
192
				<View style={baseStyles.titles}>
					<Text style={baseStyles.text}>{title}</Text>
					{renderSubtitle(subtitle, hasSubtitleIcon, subtitleL, error, true)}
				</View>
193
				{headMenu}
Hanwen Cheng's avatar
Hanwen Cheng committed
194
195
196
197
198
			</View>
		);
	}
}

199
const baseStyles = StyleSheet.create({
Hanwen Cheng's avatar
Hanwen Cheng committed
200
201
202
203
	body: {
		marginBottom: 16,
		paddingHorizontal: 16
	},
204
205
206
	bodyWithIcon: {
		alignItems: 'center',
		flexDirection: 'row',
207
208
209
		justifyContent: 'space-between',
		marginBottom: 16,
		paddingRight: 16
Hanwen Cheng's avatar
Hanwen Cheng committed
210
	},
211
	bodyWithIdentity: {
212
		flexDirection: 'column',
213
		height: 42,
214
		justifyContent: 'center',
215
216
217
		paddingLeft: 72,
		paddingRight: 32
	},
Hanwen Cheng's avatar
Hanwen Cheng committed
218
219
220
221
	icon: {
		marginLeft: 5,
		position: 'absolute'
	},
222
	identityName: {
223
		alignItems: 'center',
224
225
226
		flexDirection: 'row'
	},
	linkIcon: {
227
		marginLeft: 10
228
	},
229
230
231
	// menu: {
	// 	alignSelf: 'flex-end'
	// },
232
233
234
235
	networkIcon: {
		paddingHorizontal: 16
	},
	subtitleBody: {
Hanwen Cheng's avatar
Hanwen Cheng committed
236
237
238
239
240
241
242
243
		alignItems: 'center',
		flexDirection: 'row',
		justifyContent: 'center'
	},
	t_center: {
		textAlign: 'center'
	},
	t_error: {
244
		color: colors.signal.error
Hanwen Cheng's avatar
Hanwen Cheng committed
245
246
247
248
249
250
	},
	t_left: {
		textAlign: 'left'
	},
	t_normal: {
		fontFamily: fonts.roboto
251
252
253
254
	},
	text: {
		...fontStyles.h1,
		textAlign: 'center'
255
256
257
258
	},
	titles: {
		alignItems: 'center',
		flex: 1
Hanwen Cheng's avatar
Hanwen Cheng committed
259
	}
260
});