@momo-kits/avatar 0.0.61-alpha.10 → 0.0.61-alpha.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Avatar.js +67 -66
- package/Avatar.web.js +308 -483
- package/package.json +1 -1
package/Avatar.js
CHANGED
|
@@ -8,30 +8,15 @@ import {
|
|
|
8
8
|
ValueUtil,
|
|
9
9
|
} from '@momo-kits/core-v2';
|
|
10
10
|
import PropTypes from 'prop-types';
|
|
11
|
-
import React from 'react';
|
|
11
|
+
import React, { useState } from 'react';
|
|
12
12
|
import { StyleSheet, TouchableOpacity, View } from 'react-native';
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
const AvatarQuality = {
|
|
15
15
|
low: 'low',
|
|
16
16
|
medium: 'medium',
|
|
17
17
|
high: 'high',
|
|
18
18
|
};
|
|
19
19
|
|
|
20
|
-
export const AvatarSize = {
|
|
21
|
-
tiny: 'tiny',
|
|
22
|
-
small: 'small',
|
|
23
|
-
medium: 'medium',
|
|
24
|
-
large: 'large',
|
|
25
|
-
giant: 'giant',
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
export const SubIconType = {
|
|
29
|
-
momo: 'momo',
|
|
30
|
-
online: 'online',
|
|
31
|
-
key: 'key',
|
|
32
|
-
none: 'none',
|
|
33
|
-
};
|
|
34
|
-
|
|
35
20
|
const styles = StyleSheet.create({
|
|
36
21
|
container: {
|
|
37
22
|
justifyContent: 'center',
|
|
@@ -118,8 +103,8 @@ const avatarSize = (size) => {
|
|
|
118
103
|
switch (size) {
|
|
119
104
|
case 'tiny':
|
|
120
105
|
return {
|
|
121
|
-
width:
|
|
122
|
-
height:
|
|
106
|
+
width: 24,
|
|
107
|
+
height: 24,
|
|
123
108
|
};
|
|
124
109
|
case 'small': {
|
|
125
110
|
return {
|
|
@@ -154,30 +139,32 @@ const shortName = (size) => {
|
|
|
154
139
|
switch (size) {
|
|
155
140
|
case 'tiny':
|
|
156
141
|
return {
|
|
157
|
-
fontSize: ScaleSize(
|
|
142
|
+
fontSize: ScaleSize(10),
|
|
158
143
|
lineHeight: 16,
|
|
159
144
|
};
|
|
160
145
|
case 'small':
|
|
161
146
|
return {
|
|
162
|
-
fontSize: ScaleSize(
|
|
163
|
-
lineHeight:
|
|
147
|
+
fontSize: ScaleSize(15),
|
|
148
|
+
lineHeight: 22,
|
|
164
149
|
};
|
|
165
150
|
case 'medium':
|
|
166
151
|
return {
|
|
167
|
-
fontSize: ScaleSize(
|
|
152
|
+
fontSize: ScaleSize(15),
|
|
168
153
|
lineHeight: 22,
|
|
169
154
|
};
|
|
170
155
|
case 'large':
|
|
171
156
|
return {
|
|
172
|
-
fontSize: ScaleSize(
|
|
157
|
+
fontSize: ScaleSize(15),
|
|
158
|
+
lineHeight: 22,
|
|
173
159
|
};
|
|
174
160
|
case 'giant':
|
|
175
161
|
return {
|
|
176
|
-
fontSize: ScaleSize(
|
|
162
|
+
fontSize: ScaleSize(15),
|
|
163
|
+
lineHeight: 22,
|
|
177
164
|
};
|
|
178
165
|
default:
|
|
179
166
|
return {
|
|
180
|
-
fontSize: ScaleSize(
|
|
167
|
+
fontSize: ScaleSize(15),
|
|
181
168
|
lineHeight: 22,
|
|
182
169
|
};
|
|
183
170
|
}
|
|
@@ -205,8 +192,9 @@ const Avatar = ({
|
|
|
205
192
|
borderRadius: iconRadius,
|
|
206
193
|
} = subIconSize(size);
|
|
207
194
|
|
|
208
|
-
const imageSource =
|
|
209
|
-
|
|
195
|
+
const [imageSource, setImageSource] = useState(
|
|
196
|
+
ValueUtil.getImageSource(source),
|
|
197
|
+
);
|
|
210
198
|
const getContactShortName = (name) => {
|
|
211
199
|
if (!name) return '';
|
|
212
200
|
const shortNameList = name.split(' ', 2);
|
|
@@ -225,8 +213,7 @@ const Avatar = ({
|
|
|
225
213
|
};
|
|
226
214
|
|
|
227
215
|
const isValidImageUrl = (source) => {
|
|
228
|
-
|
|
229
|
-
return validSource;
|
|
216
|
+
return source && source.uri && isUrl(source.uri);
|
|
230
217
|
};
|
|
231
218
|
|
|
232
219
|
const mapAvatarQuality = (url, quality) => {
|
|
@@ -243,30 +230,40 @@ const Avatar = ({
|
|
|
243
230
|
return url;
|
|
244
231
|
};
|
|
245
232
|
|
|
246
|
-
const onLoadSourceError = (
|
|
247
|
-
|
|
248
|
-
this.imageSource = imageSource;
|
|
249
|
-
this.setState({ hideSource: true, ownUpdate: true });
|
|
250
|
-
}
|
|
233
|
+
const onLoadSourceError = (source) => {
|
|
234
|
+
setImageSource(source);
|
|
251
235
|
};
|
|
252
236
|
|
|
253
237
|
const renderSubIcon = () => {
|
|
254
238
|
// const subIconSizeStyle = this.mapSubIconSize(size);
|
|
255
239
|
if (subIcon && shape === 'circle' && size !== 'tiny') {
|
|
256
240
|
return (
|
|
257
|
-
<View
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
241
|
+
<View
|
|
242
|
+
style={[
|
|
243
|
+
styles.subIcon,
|
|
244
|
+
size === 'large' && {
|
|
245
|
+
bottom: 2,
|
|
246
|
+
right: 2,
|
|
247
|
+
},
|
|
248
|
+
size === 'giant' && {
|
|
249
|
+
bottom: 4,
|
|
250
|
+
right: 4,
|
|
251
|
+
},
|
|
252
|
+
]}>
|
|
253
|
+
{typeof subIcon === 'string' ? (
|
|
254
|
+
<Image
|
|
255
|
+
source={subIcon}
|
|
256
|
+
style={[
|
|
257
|
+
{
|
|
258
|
+
width: iconWidth,
|
|
259
|
+
height: iconHeight,
|
|
260
|
+
borderRadius: iconRadius,
|
|
261
|
+
},
|
|
262
|
+
]}
|
|
263
|
+
/>
|
|
264
|
+
) : (
|
|
265
|
+
subIcon()
|
|
266
|
+
)}
|
|
270
267
|
</View>
|
|
271
268
|
);
|
|
272
269
|
}
|
|
@@ -275,7 +272,18 @@ const Avatar = ({
|
|
|
275
272
|
const renderTopIcon = () => {
|
|
276
273
|
if (topIcon && shape === 'circle' && size !== 'tiny') {
|
|
277
274
|
return (
|
|
278
|
-
<View
|
|
275
|
+
<View
|
|
276
|
+
style={[
|
|
277
|
+
styles.topIcon,
|
|
278
|
+
size === 'large' && {
|
|
279
|
+
top: 2,
|
|
280
|
+
right: 2,
|
|
281
|
+
},
|
|
282
|
+
size === 'giant' && {
|
|
283
|
+
top: 4,
|
|
284
|
+
right: 4,
|
|
285
|
+
},
|
|
286
|
+
]}>
|
|
279
287
|
<Image
|
|
280
288
|
source={topIcon}
|
|
281
289
|
style={[
|
|
@@ -283,8 +291,6 @@ const Avatar = ({
|
|
|
283
291
|
width: iconWidth,
|
|
284
292
|
height: iconHeight,
|
|
285
293
|
borderRadius: iconRadius,
|
|
286
|
-
top: iconWidth / 2 - 2,
|
|
287
|
-
right: iconWidth / 2 - 2,
|
|
288
294
|
},
|
|
289
295
|
]}
|
|
290
296
|
/>
|
|
@@ -313,7 +319,12 @@ const Avatar = ({
|
|
|
313
319
|
styles.shortNameView,
|
|
314
320
|
]}>
|
|
315
321
|
<Text
|
|
316
|
-
|
|
322
|
+
weight="regular"
|
|
323
|
+
style={{
|
|
324
|
+
fontSize,
|
|
325
|
+
lineHeight,
|
|
326
|
+
color: Colors.pink_03,
|
|
327
|
+
}}>
|
|
317
328
|
{shortedName}
|
|
318
329
|
</Text>
|
|
319
330
|
</View>
|
|
@@ -354,8 +365,8 @@ const Avatar = ({
|
|
|
354
365
|
|
|
355
366
|
return (
|
|
356
367
|
<TouchableOpacity
|
|
357
|
-
activeOpacity={
|
|
358
|
-
style={
|
|
368
|
+
activeOpacity={onPress ? 0.5 : 1}
|
|
369
|
+
style={style}
|
|
359
370
|
onPress={onPressIcon}>
|
|
360
371
|
<View
|
|
361
372
|
style={{
|
|
@@ -380,28 +391,18 @@ Avatar.propTypes = {
|
|
|
380
391
|
PropTypes.number,
|
|
381
392
|
PropTypes.string,
|
|
382
393
|
]),
|
|
383
|
-
subIcon: PropTypes.string,
|
|
394
|
+
subIcon: PropTypes.oneOfType([PropTypes.string, PropTypes.func]),
|
|
384
395
|
topIcon: PropTypes.string,
|
|
385
|
-
|
|
386
|
-
PropTypes.shape({ uri: PropTypes.string }),
|
|
387
|
-
PropTypes.number,
|
|
388
|
-
PropTypes.string,
|
|
389
|
-
]),
|
|
396
|
+
|
|
390
397
|
style: PropTypes.oneOfType([PropTypes.array, PropTypes.object]),
|
|
391
398
|
onPress: PropTypes.func,
|
|
392
399
|
loading: PropTypes.bool,
|
|
393
|
-
extraPropsImage: PropTypes.object,
|
|
394
|
-
custom: PropTypes.bool,
|
|
395
400
|
shape: PropTypes.oneOf(['circle', 'square']),
|
|
396
401
|
};
|
|
397
402
|
|
|
398
403
|
Avatar.defaultProps = {
|
|
399
|
-
resizeMode: 'cover',
|
|
400
|
-
cached: true,
|
|
401
|
-
scaleSize: false,
|
|
402
404
|
quality: 'medium',
|
|
403
405
|
size: 'small',
|
|
404
|
-
custom: false,
|
|
405
406
|
shape: 'circle',
|
|
406
407
|
name: '',
|
|
407
408
|
};
|
package/Avatar.web.js
CHANGED
|
@@ -2,7 +2,11 @@
|
|
|
2
2
|
import PropTypes from 'prop-types';
|
|
3
3
|
import React, { Component } from 'react';
|
|
4
4
|
import {
|
|
5
|
-
View,
|
|
5
|
+
View,
|
|
6
|
+
StyleSheet,
|
|
7
|
+
TouchableOpacity,
|
|
8
|
+
Image,
|
|
9
|
+
Dimensions,
|
|
6
10
|
} from 'react-native';
|
|
7
11
|
import { get, isEqual } from 'lodash';
|
|
8
12
|
import ValueUtil from '../../core/utils/ValueUtil';
|
|
@@ -10,354 +14,193 @@ import Colors from '../../core/colors';
|
|
|
10
14
|
import { Icons as IconSource } from '../../core/icons';
|
|
11
15
|
import Text from '../../core/components/typography';
|
|
12
16
|
import { RFValueHorizontal as ScaleSize } from '../../core/components/typography/reponsiveSize';
|
|
17
|
+
import { Radius } from '@momo-kits/core-v2';
|
|
13
18
|
|
|
14
|
-
|
|
19
|
+
const AvatarQuality = {
|
|
15
20
|
low: 'low',
|
|
16
21
|
medium: 'medium',
|
|
17
22
|
high: 'high',
|
|
18
23
|
};
|
|
19
24
|
|
|
20
|
-
const COLORS = [
|
|
21
|
-
'#3683f3',
|
|
22
|
-
'#ea63af',
|
|
23
|
-
'#f94889',
|
|
24
|
-
'#82b6da',
|
|
25
|
-
'#2fc093',
|
|
26
|
-
'#7b4a41',
|
|
27
|
-
'#ff97bc',
|
|
28
|
-
'#4130d7',
|
|
29
|
-
'#c3c3c3',
|
|
30
|
-
'#f7ae2f',
|
|
31
|
-
'#b04595',
|
|
32
|
-
'#57b748',
|
|
33
|
-
'#ff8900',
|
|
34
|
-
'#7841bf',
|
|
35
|
-
'#be3f3e',
|
|
36
|
-
'#c51515',
|
|
37
|
-
'#8e6472',
|
|
38
|
-
'#fed27d',
|
|
39
|
-
'#ff6f5d',
|
|
40
|
-
'#05b8ae',
|
|
41
|
-
];
|
|
42
|
-
|
|
43
|
-
export const AvatarSize = {
|
|
44
|
-
tiny: 'tiny',
|
|
45
|
-
small: 'small',
|
|
46
|
-
medium: 'medium',
|
|
47
|
-
large: 'large',
|
|
48
|
-
giant: 'giant',
|
|
49
|
-
size8: 'size8',
|
|
50
|
-
size24: 'size24',
|
|
51
|
-
size36: 'size36',
|
|
52
|
-
size44: 'size44',
|
|
53
|
-
size48: 'size48',
|
|
54
|
-
size52: 'size52',
|
|
55
|
-
size56: 'size56',
|
|
56
|
-
size64: 'size64',
|
|
57
|
-
size72: 'size72',
|
|
58
|
-
size80: 'size80',
|
|
59
|
-
size88: 'size88',
|
|
60
|
-
size96: 'size96'
|
|
61
|
-
};
|
|
62
|
-
|
|
63
|
-
export const SubIconType = {
|
|
64
|
-
momo: 'momo',
|
|
65
|
-
online: 'online',
|
|
66
|
-
key: 'key',
|
|
67
|
-
none: 'none'
|
|
68
|
-
};
|
|
69
|
-
|
|
70
25
|
const styles = StyleSheet.create({
|
|
71
26
|
container: {
|
|
72
27
|
justifyContent: 'center',
|
|
73
|
-
alignItems: 'center'
|
|
28
|
+
alignItems: 'center',
|
|
74
29
|
},
|
|
75
30
|
shortNameView: {
|
|
31
|
+
backgroundColor: Colors.pink_09,
|
|
76
32
|
justifyContent: 'center',
|
|
77
33
|
alignItems: 'center',
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
width: '100%',
|
|
81
|
-
height: '100%'
|
|
34
|
+
borderWidth: 1,
|
|
35
|
+
borderColor: Colors.black_04,
|
|
82
36
|
},
|
|
83
37
|
shortNameText: {
|
|
84
38
|
// fontSize: 17,
|
|
85
|
-
color:
|
|
39
|
+
color: Colors.pink_03,
|
|
40
|
+
},
|
|
41
|
+
shortNameTextCustom: {
|
|
42
|
+
color: '#f6f6f6',
|
|
86
43
|
},
|
|
87
44
|
absolute: {
|
|
88
45
|
position: 'absolute',
|
|
89
46
|
top: 0,
|
|
90
47
|
left: 0,
|
|
91
48
|
right: 0,
|
|
92
|
-
bottom: 0
|
|
49
|
+
bottom: 0,
|
|
93
50
|
},
|
|
94
51
|
subIcon: {
|
|
95
52
|
position: 'absolute',
|
|
96
53
|
bottom: 0,
|
|
97
|
-
right: 0
|
|
54
|
+
right: 0,
|
|
55
|
+
},
|
|
56
|
+
topIcon: {
|
|
57
|
+
position: 'absolute',
|
|
58
|
+
top: 0,
|
|
59
|
+
right: 0,
|
|
98
60
|
},
|
|
99
61
|
subIconImage: {
|
|
100
62
|
width: 22,
|
|
101
|
-
height: 22
|
|
63
|
+
height: 22,
|
|
102
64
|
},
|
|
103
65
|
subIconImageOnline: {
|
|
104
66
|
backgroundColor: Colors.kiwi_green,
|
|
105
67
|
borderColor: 'white',
|
|
106
|
-
borderWidth: 1
|
|
107
|
-
}
|
|
108
|
-
});
|
|
109
|
-
|
|
110
|
-
const subIconSize = (width) => ({
|
|
111
|
-
tiny: {
|
|
112
|
-
width: 8,
|
|
113
|
-
height: 8,
|
|
114
|
-
borderRadius: 4
|
|
115
|
-
},
|
|
116
|
-
small: {
|
|
117
|
-
width: 10,
|
|
118
|
-
height: 10,
|
|
119
|
-
borderRadius: 5
|
|
120
|
-
},
|
|
121
|
-
medium: {
|
|
122
|
-
width: 12,
|
|
123
|
-
height: 12,
|
|
124
|
-
borderRadius: 6
|
|
125
|
-
},
|
|
126
|
-
large: {
|
|
127
|
-
width: 16,
|
|
128
|
-
height: 16,
|
|
129
|
-
borderRadius: 8
|
|
68
|
+
borderWidth: 1,
|
|
130
69
|
},
|
|
131
|
-
size8: {
|
|
132
|
-
width: 8,
|
|
133
|
-
height: 8,
|
|
134
|
-
borderRadius: 4
|
|
135
|
-
},
|
|
136
|
-
size24: {
|
|
137
|
-
width: 10,
|
|
138
|
-
height: 10,
|
|
139
|
-
borderRadius: 5
|
|
140
|
-
},
|
|
141
|
-
size36: {
|
|
142
|
-
width: 10,
|
|
143
|
-
height: 10,
|
|
144
|
-
borderRadius: 5
|
|
145
|
-
},
|
|
146
|
-
size44: {
|
|
147
|
-
width: 14,
|
|
148
|
-
height: 14,
|
|
149
|
-
borderRadius: 7
|
|
150
|
-
},
|
|
151
|
-
size48: {
|
|
152
|
-
width: 14,
|
|
153
|
-
height: 14,
|
|
154
|
-
borderRadius: 7
|
|
155
|
-
},
|
|
156
|
-
size52: {
|
|
157
|
-
width: 16,
|
|
158
|
-
height: 16,
|
|
159
|
-
borderRadius: 8
|
|
160
|
-
},
|
|
161
|
-
size56: {
|
|
162
|
-
width: 16,
|
|
163
|
-
height: 16,
|
|
164
|
-
borderRadius: 8
|
|
165
|
-
},
|
|
166
|
-
size64: {
|
|
167
|
-
width: 16,
|
|
168
|
-
height: 16,
|
|
169
|
-
borderRadius: 8,
|
|
170
|
-
top: -2,
|
|
171
|
-
left: -2,
|
|
172
|
-
},
|
|
173
|
-
size72: {
|
|
174
|
-
width: 18,
|
|
175
|
-
height: 18,
|
|
176
|
-
borderRadius: 9,
|
|
177
|
-
top: -3,
|
|
178
|
-
left: -3,
|
|
179
|
-
},
|
|
180
|
-
size80: {
|
|
181
|
-
width: 18,
|
|
182
|
-
height: 18,
|
|
183
|
-
borderRadius: 9,
|
|
184
|
-
top: -3,
|
|
185
|
-
left: -3,
|
|
186
|
-
},
|
|
187
|
-
size88: {
|
|
188
|
-
width: 18,
|
|
189
|
-
height: 18,
|
|
190
|
-
borderRadius: 9,
|
|
191
|
-
top: -4,
|
|
192
|
-
left: -4,
|
|
193
|
-
},
|
|
194
|
-
size96: {
|
|
195
|
-
width: 20,
|
|
196
|
-
height: 20,
|
|
197
|
-
borderRadius: 10,
|
|
198
|
-
top: -4,
|
|
199
|
-
left: -4,
|
|
200
|
-
},
|
|
201
|
-
giant: {
|
|
202
|
-
top: -5,
|
|
203
|
-
left: -5,
|
|
204
|
-
width: 24,
|
|
205
|
-
height: 24,
|
|
206
|
-
borderRadius: 12
|
|
207
|
-
}
|
|
208
70
|
});
|
|
209
71
|
|
|
210
|
-
const
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
width: 24,
|
|
243
|
-
height: 24,
|
|
244
|
-
borderRadius: 12
|
|
245
|
-
},
|
|
246
|
-
size36: {
|
|
247
|
-
width: 36,
|
|
248
|
-
height: 36,
|
|
249
|
-
borderRadius: 18
|
|
250
|
-
},
|
|
251
|
-
size44: {
|
|
252
|
-
width: 44,
|
|
253
|
-
height: 44,
|
|
254
|
-
borderRadius: 22
|
|
255
|
-
},
|
|
256
|
-
size48: {
|
|
257
|
-
width: 48,
|
|
258
|
-
height: 48,
|
|
259
|
-
borderRadius: 24
|
|
260
|
-
},
|
|
261
|
-
size52: {
|
|
262
|
-
width: 52,
|
|
263
|
-
height: 52,
|
|
264
|
-
borderRadius: 26
|
|
265
|
-
},
|
|
266
|
-
size56: {
|
|
267
|
-
width: 56,
|
|
268
|
-
height: 56,
|
|
269
|
-
borderRadius: 28
|
|
270
|
-
},
|
|
271
|
-
size64: {
|
|
272
|
-
width: 64,
|
|
273
|
-
height: 64,
|
|
274
|
-
borderRadius: 32
|
|
275
|
-
},
|
|
276
|
-
size72: {
|
|
277
|
-
width: 72,
|
|
278
|
-
height: 72,
|
|
279
|
-
borderRadius: 36
|
|
280
|
-
},
|
|
281
|
-
size80: {
|
|
282
|
-
width: 80,
|
|
283
|
-
height: 80,
|
|
284
|
-
borderRadius: 40
|
|
285
|
-
},
|
|
286
|
-
size88: {
|
|
287
|
-
width: 88,
|
|
288
|
-
height: 88,
|
|
289
|
-
borderRadius: 44
|
|
290
|
-
},
|
|
291
|
-
size96: {
|
|
292
|
-
width: 96,
|
|
293
|
-
height: 96,
|
|
294
|
-
borderRadius: 48
|
|
295
|
-
}
|
|
296
|
-
});
|
|
297
|
-
|
|
298
|
-
const shortName = (width) => ({
|
|
299
|
-
tiny: {
|
|
300
|
-
fontSize: ScaleSize(5, width)
|
|
301
|
-
},
|
|
302
|
-
small: {
|
|
303
|
-
fontSize: ScaleSize(11, width)
|
|
304
|
-
},
|
|
305
|
-
medium: {
|
|
306
|
-
fontSize: ScaleSize(15, width)
|
|
307
|
-
},
|
|
308
|
-
large: {
|
|
309
|
-
fontSize: ScaleSize(20, width)
|
|
310
|
-
},
|
|
311
|
-
giant: {
|
|
312
|
-
fontSize: ScaleSize(25, width)
|
|
313
|
-
}
|
|
314
|
-
});
|
|
315
|
-
|
|
316
|
-
export default class Avatar extends Component {
|
|
317
|
-
constructor(props) {
|
|
318
|
-
super(props);
|
|
319
|
-
this.color = this.getAvatarColor(props.name);
|
|
320
|
-
this.state = {
|
|
321
|
-
hideSource: false,
|
|
322
|
-
ownUpdate: false,
|
|
323
|
-
source: props.source,
|
|
324
|
-
dimensions: {}
|
|
325
|
-
};
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
componentDidMount() {
|
|
329
|
-
const { scaleSize } = this.props;
|
|
330
|
-
if (scaleSize) {
|
|
331
|
-
this.subscription = Dimensions.addEventListener(
|
|
332
|
-
'change',
|
|
333
|
-
({ window }) => {
|
|
334
|
-
if(window?.height > 0 && window?.width > 0) {
|
|
335
|
-
this.setState({ dimensions: window });
|
|
336
|
-
}
|
|
337
|
-
}
|
|
338
|
-
);
|
|
339
|
-
}
|
|
72
|
+
const subIconSize = (size) => {
|
|
73
|
+
switch (size) {
|
|
74
|
+
case 'giant':
|
|
75
|
+
return {
|
|
76
|
+
width: 12,
|
|
77
|
+
height: 12,
|
|
78
|
+
borderRadius: 6,
|
|
79
|
+
};
|
|
80
|
+
case 'small':
|
|
81
|
+
return {
|
|
82
|
+
width: 8,
|
|
83
|
+
height: 8,
|
|
84
|
+
borderRadius: 4,
|
|
85
|
+
};
|
|
86
|
+
case 'medium':
|
|
87
|
+
return {
|
|
88
|
+
width: 12,
|
|
89
|
+
height: 12,
|
|
90
|
+
borderRadius: 6,
|
|
91
|
+
};
|
|
92
|
+
case 'large':
|
|
93
|
+
return {
|
|
94
|
+
width: 12,
|
|
95
|
+
height: 12,
|
|
96
|
+
borderRadius: 6,
|
|
97
|
+
};
|
|
98
|
+
default:
|
|
99
|
+
return {
|
|
100
|
+
width: 12,
|
|
101
|
+
height: 12,
|
|
102
|
+
borderRadius: 6,
|
|
103
|
+
};
|
|
340
104
|
}
|
|
105
|
+
};
|
|
341
106
|
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
107
|
+
const avatarSize = (size) => {
|
|
108
|
+
switch (size) {
|
|
109
|
+
case 'tiny':
|
|
110
|
+
return {
|
|
111
|
+
width: 24,
|
|
112
|
+
height: 24,
|
|
113
|
+
};
|
|
114
|
+
case 'small': {
|
|
115
|
+
return {
|
|
116
|
+
width: 32,
|
|
117
|
+
height: 32,
|
|
118
|
+
};
|
|
346
119
|
}
|
|
120
|
+
case 'medium':
|
|
121
|
+
return {
|
|
122
|
+
width: 40,
|
|
123
|
+
height: 40,
|
|
124
|
+
};
|
|
125
|
+
case 'large':
|
|
126
|
+
return {
|
|
127
|
+
width: 56,
|
|
128
|
+
height: 56,
|
|
129
|
+
};
|
|
130
|
+
case 'giant':
|
|
131
|
+
return {
|
|
132
|
+
width: 72,
|
|
133
|
+
height: 72,
|
|
134
|
+
};
|
|
135
|
+
default:
|
|
136
|
+
return {
|
|
137
|
+
width: 40,
|
|
138
|
+
height: 40,
|
|
139
|
+
};
|
|
347
140
|
}
|
|
141
|
+
};
|
|
348
142
|
|
|
349
|
-
|
|
350
|
-
|
|
143
|
+
const shortName = (size) => {
|
|
144
|
+
switch (size) {
|
|
145
|
+
case 'tiny':
|
|
351
146
|
return {
|
|
352
|
-
|
|
147
|
+
fontSize: ScaleSize(10),
|
|
148
|
+
lineHeight: 16,
|
|
149
|
+
};
|
|
150
|
+
case 'small':
|
|
151
|
+
return {
|
|
152
|
+
fontSize: ScaleSize(15),
|
|
153
|
+
lineHeight: 22,
|
|
154
|
+
};
|
|
155
|
+
case 'medium':
|
|
156
|
+
return {
|
|
157
|
+
fontSize: ScaleSize(15),
|
|
158
|
+
lineHeight: 22,
|
|
159
|
+
};
|
|
160
|
+
case 'large':
|
|
161
|
+
return {
|
|
162
|
+
fontSize: ScaleSize(15),
|
|
163
|
+
lineHeight: 22,
|
|
164
|
+
};
|
|
165
|
+
case 'giant':
|
|
166
|
+
return {
|
|
167
|
+
fontSize: ScaleSize(15),
|
|
168
|
+
lineHeight: 22,
|
|
169
|
+
};
|
|
170
|
+
default:
|
|
171
|
+
return {
|
|
172
|
+
fontSize: ScaleSize(15),
|
|
173
|
+
lineHeight: 22,
|
|
353
174
|
};
|
|
354
|
-
} if (!isEqual(nextProps.source, prevState.source)) {
|
|
355
|
-
return { source: nextProps.source, hideSource: false };
|
|
356
|
-
}
|
|
357
|
-
return null;
|
|
358
175
|
}
|
|
176
|
+
};
|
|
359
177
|
|
|
360
|
-
|
|
178
|
+
const Avatar = ({
|
|
179
|
+
resizeMode,
|
|
180
|
+
cached,
|
|
181
|
+
quality,
|
|
182
|
+
size,
|
|
183
|
+
shape,
|
|
184
|
+
name,
|
|
185
|
+
source,
|
|
186
|
+
onPress,
|
|
187
|
+
style,
|
|
188
|
+
subIcon,
|
|
189
|
+
topIcon,
|
|
190
|
+
loading,
|
|
191
|
+
}) => {
|
|
192
|
+
const { width, height } = avatarSize(size);
|
|
193
|
+
const { fontSize, lineHeight } = shortName(size);
|
|
194
|
+
const {
|
|
195
|
+
width: iconWidth,
|
|
196
|
+
height: iconHeight,
|
|
197
|
+
borderRadius: iconRadius,
|
|
198
|
+
} = subIconSize(size);
|
|
199
|
+
|
|
200
|
+
const [imageSource, setImageSource] = useState(
|
|
201
|
+
ValueUtil.getImageSource(source),
|
|
202
|
+
);
|
|
203
|
+
const getContactShortName = (name) => {
|
|
361
204
|
if (!name) return '';
|
|
362
205
|
const shortNameList = name.split(' ', 2);
|
|
363
206
|
const alphabet = [];
|
|
@@ -367,32 +210,18 @@ export default class Avatar extends Component {
|
|
|
367
210
|
}
|
|
368
211
|
});
|
|
369
212
|
return alphabet.join('');
|
|
370
|
-
}
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
const shortedName = this.getContactShortName(name);
|
|
375
|
-
const shortNameStyle = this.mapShortNameStyle(size);
|
|
376
|
-
return (
|
|
377
|
-
<View style={[styles.shortNameView, avatarStyle]}>
|
|
378
|
-
<Text.H4 style={[styles.shortNameText, shortNameStyle]}>{shortedName}</Text.H4>
|
|
379
|
-
</View>
|
|
380
|
-
);
|
|
381
|
-
}
|
|
382
|
-
return <View />;
|
|
383
|
-
}
|
|
384
|
-
|
|
385
|
-
isUrl(url) {
|
|
386
|
-
const expression = /(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-/]))?/gi;
|
|
213
|
+
};
|
|
214
|
+
const isUrl = (url) => {
|
|
215
|
+
const expression =
|
|
216
|
+
/(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-/]))?/gi;
|
|
387
217
|
return expression.test(url);
|
|
388
|
-
}
|
|
218
|
+
};
|
|
389
219
|
|
|
390
|
-
isValidImageUrl = (source) => {
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
}
|
|
220
|
+
const isValidImageUrl = (source) => {
|
|
221
|
+
return source && source.uri && isUrl(source.uri);
|
|
222
|
+
};
|
|
394
223
|
|
|
395
|
-
mapAvatarQuality = (url, quality) => {
|
|
224
|
+
const mapAvatarQuality = (url, quality) => {
|
|
396
225
|
if (!quality || quality === AvatarQuality.medium) {
|
|
397
226
|
return url;
|
|
398
227
|
}
|
|
@@ -404,185 +233,181 @@ export default class Avatar extends Component {
|
|
|
404
233
|
}
|
|
405
234
|
|
|
406
235
|
return url;
|
|
407
|
-
}
|
|
408
|
-
|
|
409
|
-
mapStyleFromSize = (size) => {
|
|
410
|
-
const { dimensions } = this.state;
|
|
411
|
-
const avatarStyle = avatarSize(dimensions?.width || null).small;
|
|
412
|
-
if (typeof size === 'object') return size;
|
|
413
|
-
if (avatarSize(dimensions?.width || null)[size]) return avatarSize(dimensions?.width || null)[size];
|
|
414
|
-
return avatarStyle;
|
|
415
|
-
}
|
|
416
|
-
|
|
417
|
-
mapShortNameStyle = (size) => {
|
|
418
|
-
let shortNameStyle = {};
|
|
419
|
-
const { dimensions } = this.state;
|
|
420
|
-
switch (size) {
|
|
421
|
-
case AvatarSize.tiny: {
|
|
422
|
-
shortNameStyle = shortName(dimensions?.width || null).tiny;
|
|
423
|
-
break;
|
|
424
|
-
}
|
|
425
|
-
case AvatarSize.small: {
|
|
426
|
-
shortNameStyle = shortName(dimensions?.width || null).small;
|
|
427
|
-
break;
|
|
428
|
-
}
|
|
429
|
-
case AvatarSize.medium: {
|
|
430
|
-
shortNameStyle = shortName(dimensions?.width || null).medium;
|
|
431
|
-
break;
|
|
432
|
-
}
|
|
433
|
-
case AvatarSize.large: {
|
|
434
|
-
shortNameStyle = shortName(dimensions?.width || null).large;
|
|
435
|
-
break;
|
|
436
|
-
}
|
|
437
|
-
case AvatarSize.giant: {
|
|
438
|
-
shortNameStyle = shortName(dimensions?.width || null).giant;
|
|
439
|
-
break;
|
|
440
|
-
}
|
|
441
|
-
default:
|
|
442
|
-
shortNameStyle = shortName(dimensions?.width || null).small;
|
|
443
|
-
}
|
|
444
|
-
return shortNameStyle;
|
|
445
|
-
}
|
|
446
|
-
|
|
447
|
-
mapSubIconSize = (size) => {
|
|
448
|
-
const { dimensions } = this.state;
|
|
449
|
-
const subIconStyle = subIconSize(dimensions?.width || null).small;
|
|
450
|
-
if (subIconSize(dimensions?.width || null)[size]) return subIconSize(dimensions?.width || null)[size];
|
|
451
|
-
return subIconStyle;
|
|
452
|
-
}
|
|
453
|
-
|
|
454
|
-
extractSize = (avatarStyle) => {
|
|
455
|
-
const { style } = this.props;
|
|
456
|
-
const borderWidth = get(style, 'borderWidth', 1);
|
|
457
|
-
const containerWidth = Math.round(avatarStyle.width + 2 + borderWidth);
|
|
458
|
-
return {
|
|
459
|
-
width: containerWidth,
|
|
460
|
-
height: containerWidth,
|
|
461
|
-
borderRadius: containerWidth / 2,
|
|
462
|
-
borderWidth,
|
|
463
|
-
borderColor: Colors.black_01
|
|
464
|
-
};
|
|
465
|
-
}
|
|
466
|
-
|
|
467
|
-
getAvatarColor(name) {
|
|
468
|
-
const shortName = this.getContactShortName(name)
|
|
469
|
-
if (!shortName) return "#d5d6d6"
|
|
470
|
-
const firstLetter = shortName[0].charCodeAt(0)
|
|
471
|
-
let colorIndex = Number(firstLetter) % 26
|
|
472
|
-
if (colorIndex > 19) colorIndex = 25 - colorIndex
|
|
473
|
-
return COLORS[colorIndex]
|
|
474
|
-
}
|
|
236
|
+
};
|
|
475
237
|
|
|
238
|
+
const onLoadSourceError = (source) => {
|
|
239
|
+
setImageSource(source);
|
|
240
|
+
};
|
|
476
241
|
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
242
|
+
const renderSubIcon = () => {
|
|
243
|
+
// const subIconSizeStyle = this.mapSubIconSize(size);
|
|
244
|
+
if (subIcon && shape === 'circle' && size !== 'tiny') {
|
|
245
|
+
return (
|
|
246
|
+
<View
|
|
247
|
+
style={[
|
|
248
|
+
styles.subIcon,
|
|
249
|
+
size === 'large' && {
|
|
250
|
+
bottom: 2,
|
|
251
|
+
right: 2,
|
|
252
|
+
},
|
|
253
|
+
size === 'giant' && {
|
|
254
|
+
bottom: 4,
|
|
255
|
+
right: 4,
|
|
256
|
+
},
|
|
257
|
+
]}>
|
|
258
|
+
{typeof subIcon === 'string' ? (
|
|
490
259
|
<Image
|
|
491
|
-
|
|
492
|
-
|
|
260
|
+
source={subIcon}
|
|
261
|
+
style={[
|
|
262
|
+
{
|
|
263
|
+
width: iconWidth,
|
|
264
|
+
height: iconHeight,
|
|
265
|
+
borderRadius: iconRadius,
|
|
266
|
+
},
|
|
267
|
+
]}
|
|
493
268
|
/>
|
|
494
|
-
)
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
269
|
+
) : (
|
|
270
|
+
subIcon()
|
|
271
|
+
)}
|
|
272
|
+
</View>
|
|
273
|
+
);
|
|
274
|
+
}
|
|
275
|
+
};
|
|
498
276
|
|
|
499
|
-
|
|
277
|
+
const renderTopIcon = () => {
|
|
278
|
+
if (topIcon && shape === 'circle' && size !== 'tiny') {
|
|
279
|
+
return (
|
|
280
|
+
<View
|
|
281
|
+
style={[
|
|
282
|
+
styles.topIcon,
|
|
283
|
+
size === 'large' && {
|
|
284
|
+
top: 2,
|
|
285
|
+
right: 2,
|
|
286
|
+
},
|
|
287
|
+
size === 'giant' && {
|
|
288
|
+
top: 4,
|
|
289
|
+
right: 4,
|
|
290
|
+
},
|
|
291
|
+
]}>
|
|
500
292
|
<Image
|
|
501
|
-
|
|
502
|
-
|
|
293
|
+
source={topIcon}
|
|
294
|
+
style={[
|
|
295
|
+
{
|
|
296
|
+
width: iconWidth,
|
|
297
|
+
height: iconHeight,
|
|
298
|
+
borderRadius: iconRadius,
|
|
299
|
+
},
|
|
300
|
+
]}
|
|
503
301
|
/>
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
}
|
|
302
|
+
</View>
|
|
303
|
+
);
|
|
304
|
+
}
|
|
305
|
+
};
|
|
509
306
|
|
|
510
|
-
|
|
511
|
-
const { onPress } = this.props;
|
|
307
|
+
const onPressIcon = () => {
|
|
512
308
|
if (onPress && typeof onPress === 'function') onPress();
|
|
513
|
-
}
|
|
514
|
-
|
|
515
|
-
render() {
|
|
516
|
-
const {
|
|
517
|
-
size, source, name, resizeMode, style, onPress, isShowLoading, loading, cached, extraPropsImage, quality
|
|
518
|
-
} = this.props;
|
|
519
|
-
const { hideSource } = this.state;
|
|
520
|
-
const avatarStyle = this.mapStyleFromSize(size);
|
|
521
|
-
const containerSize = this.extractSize(avatarStyle);
|
|
522
|
-
const imageSource = ValueUtil.getImageSource(source);
|
|
523
|
-
const showName = typeof imageSource === 'object' && Object.keys(imageSource).length === 0 && typeof imageSource !== 'number';
|
|
524
|
-
// add priority high for avatar
|
|
525
|
-
if (imageSource?.uri) {
|
|
526
|
-
imageSource.priority = 'high';
|
|
527
|
-
imageSource.uri = this.mapAvatarQuality(imageSource.uri, quality);
|
|
528
|
-
// if doest not have time query, set default cache time to 1 day
|
|
529
|
-
if (!imageSource.uri?.includes('?') && cached) {
|
|
530
|
-
const midnight = new Date().setHours(0, 0, 0, 0);
|
|
531
|
-
imageSource.uri = `${imageSource.uri}?time=${midnight}`;
|
|
532
|
-
}
|
|
533
|
-
}
|
|
309
|
+
};
|
|
534
310
|
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
? (
|
|
540
|
-
<Image
|
|
541
|
-
cached={cached}
|
|
542
|
-
loading={loading || isShowLoading}
|
|
543
|
-
source={imageSource}
|
|
544
|
-
onError={this.onLoadSourceError}
|
|
545
|
-
style={avatarStyle}
|
|
546
|
-
resizeMode={resizeMode}
|
|
547
|
-
{...extraPropsImage}
|
|
548
|
-
/>
|
|
549
|
-
) : <View />}
|
|
550
|
-
{this.renderSubIcon()}
|
|
551
|
-
</View>
|
|
552
|
-
);
|
|
553
|
-
if (onPress) {
|
|
311
|
+
const renderShortName = () => {
|
|
312
|
+
if (name) {
|
|
313
|
+
const shortedName = getContactShortName(name);
|
|
314
|
+
// const shortNameStyle = mapShortNameStyle(size);
|
|
554
315
|
return (
|
|
555
|
-
<
|
|
556
|
-
{
|
|
557
|
-
|
|
316
|
+
<View
|
|
317
|
+
style={[
|
|
318
|
+
{
|
|
319
|
+
width,
|
|
320
|
+
height,
|
|
321
|
+
borderRadius:
|
|
322
|
+
shape === 'circle' ? width / 2 : Radius.XS,
|
|
323
|
+
},
|
|
324
|
+
styles.shortNameView,
|
|
325
|
+
]}>
|
|
326
|
+
<Text
|
|
327
|
+
weight="regular"
|
|
328
|
+
style={{
|
|
329
|
+
fontSize,
|
|
330
|
+
lineHeight,
|
|
331
|
+
color: Colors.pink_03,
|
|
332
|
+
}}>
|
|
333
|
+
{shortedName}
|
|
334
|
+
</Text>
|
|
335
|
+
</View>
|
|
558
336
|
);
|
|
559
337
|
}
|
|
560
|
-
return
|
|
338
|
+
return <View />;
|
|
339
|
+
};
|
|
340
|
+
|
|
341
|
+
if (imageSource?.uri) {
|
|
342
|
+
imageSource.priority = 'high';
|
|
343
|
+
imageSource.uri = mapAvatarQuality(imageSource.uri, quality);
|
|
344
|
+
// if doest not have time query, set default cache time to 1 day
|
|
345
|
+
if (!imageSource.uri?.includes('?') && cached) {
|
|
346
|
+
const midnight = new Date().setHours(0, 0, 0, 0);
|
|
347
|
+
imageSource.uri = `${imageSource.uri}?time=${midnight}`;
|
|
348
|
+
}
|
|
561
349
|
}
|
|
562
|
-
|
|
350
|
+
|
|
351
|
+
const renderImage = () => {
|
|
352
|
+
return (
|
|
353
|
+
<Image
|
|
354
|
+
cached={cached}
|
|
355
|
+
resizeMode={resizeMode}
|
|
356
|
+
onLoadSourceError={() => onLoadSourceError(source)}
|
|
357
|
+
source={source}
|
|
358
|
+
loading={loading}
|
|
359
|
+
style={[
|
|
360
|
+
{
|
|
361
|
+
width,
|
|
362
|
+
height,
|
|
363
|
+
borderRadius:
|
|
364
|
+
shape === 'circle' ? width / 2 : Radius.XS,
|
|
365
|
+
},
|
|
366
|
+
]}
|
|
367
|
+
/>
|
|
368
|
+
);
|
|
369
|
+
};
|
|
370
|
+
|
|
371
|
+
return (
|
|
372
|
+
<TouchableOpacity
|
|
373
|
+
activeOpacity={onPress ? 0.5 : 1}
|
|
374
|
+
style={style}
|
|
375
|
+
onPress={onPressIcon}>
|
|
376
|
+
<View
|
|
377
|
+
style={{
|
|
378
|
+
alignSelf: 'baseline',
|
|
379
|
+
}}>
|
|
380
|
+
{!!imageSource && isValidImageUrl(imageSource)
|
|
381
|
+
? renderImage()
|
|
382
|
+
: renderShortName()}
|
|
383
|
+
{renderTopIcon()}
|
|
384
|
+
{renderSubIcon()}
|
|
385
|
+
</View>
|
|
386
|
+
</TouchableOpacity>
|
|
387
|
+
);
|
|
388
|
+
};
|
|
563
389
|
|
|
564
390
|
Avatar.propTypes = {
|
|
565
391
|
name: PropTypes.string,
|
|
566
|
-
resizeMode: PropTypes.string,
|
|
567
392
|
quality: PropTypes.oneOf(['low', 'medium', 'high']),
|
|
568
|
-
size: PropTypes.oneOf(['tiny', 'small', 'medium', 'large', 'giant',
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
393
|
+
size: PropTypes.oneOf(['tiny', 'small', 'medium', 'large', 'giant']),
|
|
394
|
+
source: PropTypes.oneOfType([
|
|
395
|
+
PropTypes.shape({ uri: PropTypes.string }),
|
|
396
|
+
PropTypes.number,
|
|
397
|
+
PropTypes.string,
|
|
398
|
+
]),
|
|
399
|
+
subIcon: PropTypes.oneOfType([PropTypes.string, PropTypes.func]),
|
|
400
|
+
topIcon: PropTypes.string,
|
|
401
|
+
|
|
575
402
|
style: PropTypes.oneOfType([PropTypes.array, PropTypes.object]),
|
|
576
403
|
onPress: PropTypes.func,
|
|
577
404
|
loading: PropTypes.bool,
|
|
578
|
-
|
|
579
|
-
scaleSize: PropTypes.bool,
|
|
580
|
-
extraPropsImage: PropTypes.object
|
|
405
|
+
shape: PropTypes.oneOf(['circle', 'square']),
|
|
581
406
|
};
|
|
582
407
|
|
|
583
408
|
Avatar.defaultProps = {
|
|
584
|
-
resizeMode: 'cover',
|
|
585
|
-
cached: true,
|
|
586
|
-
scaleSize: false,
|
|
587
409
|
quality: 'medium',
|
|
410
|
+
size: 'small',
|
|
411
|
+
shape: 'circle',
|
|
412
|
+
name: '',
|
|
588
413
|
};
|