@momo-kits/avatar 0.0.33-beta → 0.0.33
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 +150 -35
- package/Avatar.web.js +132 -69
- package/package.json +5 -12
- package/publish.sh +1 -1
- package/babel.config.js +0 -3
package/Avatar.js
CHANGED
|
@@ -2,13 +2,19 @@
|
|
|
2
2
|
import PropTypes from 'prop-types';
|
|
3
3
|
import React, { Component } from 'react';
|
|
4
4
|
import {
|
|
5
|
-
View, StyleSheet, TouchableOpacity
|
|
5
|
+
View, StyleSheet, TouchableOpacity, Dimensions, Platform
|
|
6
6
|
} from 'react-native';
|
|
7
7
|
import { get, isEqual } from 'lodash';
|
|
8
8
|
import {
|
|
9
|
-
ValueUtil, Colors, Text, IconSource, Image
|
|
9
|
+
ValueUtil, Colors, Text, IconSource, Image, ScaleSize
|
|
10
10
|
} from '@momo-kits/core';
|
|
11
11
|
|
|
12
|
+
export const AvatarQuality = {
|
|
13
|
+
low: 'low',
|
|
14
|
+
medium: 'medium',
|
|
15
|
+
high: 'high',
|
|
16
|
+
};
|
|
17
|
+
|
|
12
18
|
export const AvatarSize = {
|
|
13
19
|
tiny: 'tiny',
|
|
14
20
|
small: 'small',
|
|
@@ -29,6 +35,29 @@ export const AvatarSize = {
|
|
|
29
35
|
size96: 'size96'
|
|
30
36
|
};
|
|
31
37
|
|
|
38
|
+
const COLORS = [
|
|
39
|
+
'#3683f3',
|
|
40
|
+
'#ea63af',
|
|
41
|
+
'#f94889',
|
|
42
|
+
'#82b6da',
|
|
43
|
+
'#2fc093',
|
|
44
|
+
'#7b4a41',
|
|
45
|
+
'#ff97bc',
|
|
46
|
+
'#4130d7',
|
|
47
|
+
'#c3c3c3',
|
|
48
|
+
'#f7ae2f',
|
|
49
|
+
'#b04595',
|
|
50
|
+
'#57b748',
|
|
51
|
+
'#ff8900',
|
|
52
|
+
'#7841bf',
|
|
53
|
+
'#be3f3e',
|
|
54
|
+
'#c51515',
|
|
55
|
+
'#8e6472',
|
|
56
|
+
'#fed27d',
|
|
57
|
+
'#ff6f5d',
|
|
58
|
+
'#05b8ae',
|
|
59
|
+
];
|
|
60
|
+
|
|
32
61
|
export const SubIconType = {
|
|
33
62
|
momo: 'momo',
|
|
34
63
|
online: 'online',
|
|
@@ -76,7 +105,7 @@ const styles = StyleSheet.create({
|
|
|
76
105
|
}
|
|
77
106
|
});
|
|
78
107
|
|
|
79
|
-
const subIconSize =
|
|
108
|
+
const subIconSize = (width) => ({
|
|
80
109
|
tiny: {
|
|
81
110
|
width: 8,
|
|
82
111
|
height: 8,
|
|
@@ -176,7 +205,7 @@ const subIconSize = StyleSheet.create({
|
|
|
176
205
|
}
|
|
177
206
|
});
|
|
178
207
|
|
|
179
|
-
const avatarSize =
|
|
208
|
+
const avatarSize = (width) => ({
|
|
180
209
|
tiny: {
|
|
181
210
|
width: 16,
|
|
182
211
|
height: 16,
|
|
@@ -264,32 +293,59 @@ const avatarSize = StyleSheet.create({
|
|
|
264
293
|
}
|
|
265
294
|
});
|
|
266
295
|
|
|
267
|
-
const shortName =
|
|
296
|
+
const shortName = (width) => ({
|
|
268
297
|
tiny: {
|
|
269
|
-
fontSize: 5
|
|
298
|
+
fontSize: ScaleSize(5, width)
|
|
270
299
|
},
|
|
271
300
|
small: {
|
|
272
|
-
fontSize: 11
|
|
301
|
+
fontSize: ScaleSize(11, width)
|
|
273
302
|
},
|
|
274
303
|
medium: {
|
|
275
|
-
fontSize: 15
|
|
304
|
+
fontSize: ScaleSize(15, width)
|
|
305
|
+
},
|
|
306
|
+
middle: {
|
|
307
|
+
fontSize: ScaleSize(16, width)
|
|
276
308
|
},
|
|
277
309
|
large: {
|
|
278
|
-
fontSize: 20
|
|
310
|
+
fontSize: ScaleSize(20, width)
|
|
279
311
|
},
|
|
280
312
|
giant: {
|
|
281
|
-
fontSize: 25
|
|
313
|
+
fontSize: ScaleSize(25, width)
|
|
282
314
|
}
|
|
283
315
|
});
|
|
284
316
|
|
|
285
317
|
export default class Avatar extends Component {
|
|
286
318
|
constructor(props) {
|
|
287
319
|
super(props);
|
|
320
|
+
this.color = this.getAvatarColor(props.name);
|
|
288
321
|
this.state = {
|
|
289
322
|
hideSource: false,
|
|
290
323
|
ownUpdate: false,
|
|
291
|
-
source: props.source
|
|
324
|
+
source: props.source,
|
|
325
|
+
dimensions: {}
|
|
292
326
|
};
|
|
327
|
+
this.imageSource = '';
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
componentDidMount() {
|
|
331
|
+
const { scaleSize } = this.props;
|
|
332
|
+
if (scaleSize) {
|
|
333
|
+
this.subscription = Dimensions.addEventListener(
|
|
334
|
+
'change',
|
|
335
|
+
({ window }) => {
|
|
336
|
+
if(window?.height > 0 && window?.width > 0 && Platform.OS === 'android') {
|
|
337
|
+
this.setState({ dimensions: window });
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
);
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
componentWillUnmount() {
|
|
345
|
+
const { scaleSize } = this.props;
|
|
346
|
+
if (scaleSize) {
|
|
347
|
+
this.subscription?.remove?.();
|
|
348
|
+
}
|
|
293
349
|
}
|
|
294
350
|
|
|
295
351
|
static getDerivedStateFromProps(nextProps, prevState) {
|
|
@@ -315,12 +371,24 @@ export default class Avatar extends Component {
|
|
|
315
371
|
return alphabet.join('');
|
|
316
372
|
}
|
|
317
373
|
|
|
318
|
-
|
|
374
|
+
hashUrl(url) {
|
|
375
|
+
let hash = 0;
|
|
376
|
+
let char;
|
|
377
|
+
if (url?.length === 0) return hash;
|
|
378
|
+
for (let i = 0; i < url?.length; i++) {
|
|
379
|
+
char = url?.charCodeAt(i);
|
|
380
|
+
hash = ((hash << 5) - hash) + char;
|
|
381
|
+
hash &= hash; // Convert to 32bit integer
|
|
382
|
+
}
|
|
383
|
+
return hash;
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
renderShortName = (name, avatarStyle, size, color,) => {
|
|
319
387
|
if (name) {
|
|
320
388
|
const shortedName = this.getContactShortName(name);
|
|
321
389
|
const shortNameStyle = this.mapShortNameStyle(size);
|
|
322
390
|
return (
|
|
323
|
-
<View style={[styles.shortNameView, avatarStyle]}>
|
|
391
|
+
<View style={[styles.shortNameView, avatarStyle, { backgroundColor: color }]}>
|
|
324
392
|
<Text.H4 style={[styles.shortNameText, shortNameStyle]}>{shortedName}</Text.H4>
|
|
325
393
|
</View>
|
|
326
394
|
);
|
|
@@ -334,49 +402,70 @@ export default class Avatar extends Component {
|
|
|
334
402
|
}
|
|
335
403
|
|
|
336
404
|
isValidImageUrl = (source) => {
|
|
337
|
-
const validSource = source &&
|
|
405
|
+
const validSource = source && source.uri && this.isUrl(source.uri);
|
|
338
406
|
return validSource;
|
|
339
407
|
}
|
|
340
408
|
|
|
409
|
+
mapAvatarQuality = (url, quality) => {
|
|
410
|
+
if (!quality || quality === AvatarQuality.medium) {
|
|
411
|
+
return url;
|
|
412
|
+
}
|
|
413
|
+
if (quality === AvatarQuality.low) {
|
|
414
|
+
return url.replace('.png', '_s64.png');
|
|
415
|
+
}
|
|
416
|
+
if (quality === AvatarQuality.high) {
|
|
417
|
+
return url.replace('.png', '_s512.png');
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
return url;
|
|
421
|
+
}
|
|
422
|
+
|
|
341
423
|
mapStyleFromSize = (size) => {
|
|
342
|
-
const
|
|
424
|
+
const { dimensions } = this.state;
|
|
425
|
+
const avatarStyle = avatarSize(dimensions?.width > 0 ? dimensions?.width : null).small;
|
|
343
426
|
if (typeof size === 'object') return size;
|
|
344
|
-
if (avatarSize[size]) return avatarSize[size];
|
|
427
|
+
if (avatarSize(dimensions?.width > 0 ? dimensions?.width : null)[size]) return avatarSize(dimensions?.width > 0 ? dimensions?.width : null)[size];
|
|
345
428
|
return avatarStyle;
|
|
346
429
|
}
|
|
347
430
|
|
|
348
431
|
mapShortNameStyle = (size) => {
|
|
349
432
|
let shortNameStyle = {};
|
|
433
|
+
const { dimensions } = this.state;
|
|
350
434
|
switch (size) {
|
|
351
435
|
case AvatarSize.tiny: {
|
|
352
|
-
shortNameStyle = shortName.tiny;
|
|
436
|
+
shortNameStyle = shortName(dimensions?.width > 0 ? dimensions?.width : null).tiny;
|
|
353
437
|
break;
|
|
354
438
|
}
|
|
355
439
|
case AvatarSize.small: {
|
|
356
|
-
shortNameStyle = shortName.small;
|
|
440
|
+
shortNameStyle = shortName(dimensions?.width > 0 ? dimensions?.width : null).small;
|
|
357
441
|
break;
|
|
358
442
|
}
|
|
359
443
|
case AvatarSize.medium: {
|
|
360
|
-
shortNameStyle = shortName.medium;
|
|
444
|
+
shortNameStyle = shortName(dimensions?.width > 0 ? dimensions?.width : null).medium;
|
|
445
|
+
break;
|
|
446
|
+
}
|
|
447
|
+
case AvatarSize.size48: {
|
|
448
|
+
shortNameStyle = shortName(dimensions?.width || null).middle;
|
|
361
449
|
break;
|
|
362
450
|
}
|
|
363
451
|
case AvatarSize.large: {
|
|
364
|
-
shortNameStyle = shortName.large;
|
|
452
|
+
shortNameStyle = shortName(dimensions?.width > 0 ? dimensions?.width : null).large;
|
|
365
453
|
break;
|
|
366
454
|
}
|
|
367
455
|
case AvatarSize.giant: {
|
|
368
|
-
shortNameStyle = shortName.giant;
|
|
456
|
+
shortNameStyle = shortName(dimensions?.width > 0 ? dimensions?.width : null).giant;
|
|
369
457
|
break;
|
|
370
458
|
}
|
|
371
459
|
default:
|
|
372
|
-
shortNameStyle = shortName.small;
|
|
460
|
+
shortNameStyle = shortName(dimensions?.width > 0 ? dimensions?.width : null).small;
|
|
373
461
|
}
|
|
374
462
|
return shortNameStyle;
|
|
375
463
|
}
|
|
376
464
|
|
|
377
465
|
mapSubIconSize = (size) => {
|
|
378
|
-
const
|
|
379
|
-
|
|
466
|
+
const { dimensions } = this.state;
|
|
467
|
+
const subIconStyle = subIconSize(dimensions?.width > 0 ? dimensions?.width : null).small;
|
|
468
|
+
if (subIconSize(dimensions?.width > 0 ? dimensions?.width : null)[size]) return subIconSize(dimensions?.width > 0 ? dimensions?.width : null)[size];
|
|
380
469
|
return subIconStyle;
|
|
381
470
|
}
|
|
382
471
|
|
|
@@ -393,8 +482,11 @@ export default class Avatar extends Component {
|
|
|
393
482
|
};
|
|
394
483
|
}
|
|
395
484
|
|
|
396
|
-
onLoadSourceError = () => {
|
|
397
|
-
this.
|
|
485
|
+
onLoadSourceError = (imageSource) => {
|
|
486
|
+
if(this.imageSource?.uri !== imageSource?.uri){
|
|
487
|
+
this.imageSource = imageSource;
|
|
488
|
+
this.setState({ hideSource: true, ownUpdate: true });
|
|
489
|
+
}
|
|
398
490
|
}
|
|
399
491
|
|
|
400
492
|
renderSubIcon = () => {
|
|
@@ -426,6 +518,15 @@ export default class Avatar extends Component {
|
|
|
426
518
|
);
|
|
427
519
|
}
|
|
428
520
|
|
|
521
|
+
getAvatarColor(name) {
|
|
522
|
+
const shortName = this.getContactShortName(name)
|
|
523
|
+
if (!shortName) return "#d5d6d6"
|
|
524
|
+
const firstLetter = shortName[0].charCodeAt(0)
|
|
525
|
+
let colorIndex = Number(firstLetter) % 26
|
|
526
|
+
if (colorIndex > 19) colorIndex = 25 - colorIndex
|
|
527
|
+
return COLORS[colorIndex]
|
|
528
|
+
}
|
|
529
|
+
|
|
429
530
|
onPress = () => {
|
|
430
531
|
const { onPress } = this.props;
|
|
431
532
|
if (onPress && typeof onPress === 'function') onPress();
|
|
@@ -433,23 +534,34 @@ export default class Avatar extends Component {
|
|
|
433
534
|
|
|
434
535
|
render() {
|
|
435
536
|
const {
|
|
436
|
-
size, source, name, resizeMode, style, onPress, isShowLoading, loading, cached, extraPropsImage
|
|
537
|
+
size, source, name, resizeMode, style, onPress, isShowLoading, loading, cached, extraPropsImage, quality
|
|
437
538
|
} = this.props;
|
|
438
539
|
const { hideSource } = this.state;
|
|
439
540
|
const avatarStyle = this.mapStyleFromSize(size);
|
|
440
541
|
const containerSize = this.extractSize(avatarStyle);
|
|
441
542
|
const imageSource = ValueUtil.getImageSource(source);
|
|
442
543
|
const showName = typeof imageSource === 'object' && Object.keys(imageSource).length === 0 && typeof imageSource !== 'number';
|
|
544
|
+
// add priority high for avatar
|
|
545
|
+
if (imageSource?.uri) {
|
|
546
|
+
imageSource.priority = 'high';
|
|
547
|
+
imageSource.uri = this.mapAvatarQuality(imageSource.uri, quality);
|
|
548
|
+
// if doest not have time query, set default cache time to 1 day
|
|
549
|
+
if (!imageSource.uri?.includes('?') && cached) {
|
|
550
|
+
const midnight = new Date().setHours(0, 0, 0, 0);
|
|
551
|
+
imageSource.uri = `${imageSource.uri}?time=${midnight}`;
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
|
|
443
555
|
const inner = (
|
|
444
556
|
<View style={[styles.container, containerSize, style]}>
|
|
445
|
-
{(showName || hideSource) ? this.renderShortName(name, avatarStyle, size) : <View />}
|
|
557
|
+
{(showName || hideSource) ? this.renderShortName(name, avatarStyle, size, this.color) : <View />}
|
|
446
558
|
{this.isValidImageUrl(imageSource) && !hideSource
|
|
447
559
|
? (
|
|
448
560
|
<Image
|
|
449
561
|
cached={cached}
|
|
450
562
|
loading={loading || isShowLoading}
|
|
451
563
|
source={imageSource}
|
|
452
|
-
onError={this.onLoadSourceError}
|
|
564
|
+
onError={() => this.onLoadSourceError(imageSource)}
|
|
453
565
|
style={avatarStyle}
|
|
454
566
|
resizeMode={resizeMode}
|
|
455
567
|
{...extraPropsImage}
|
|
@@ -472,10 +584,8 @@ export default class Avatar extends Component {
|
|
|
472
584
|
Avatar.propTypes = {
|
|
473
585
|
name: PropTypes.string,
|
|
474
586
|
resizeMode: PropTypes.string,
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
width: PropTypes.number, height: PropTypes.number, borderRadius: PropTypes.number
|
|
478
|
-
})]),
|
|
587
|
+
quality: PropTypes.oneOf(['low', 'medium', 'high']),
|
|
588
|
+
size: PropTypes.any,
|
|
479
589
|
source: PropTypes.oneOfType([PropTypes.shape({ uri: PropTypes.string }), PropTypes.number, PropTypes.string]),
|
|
480
590
|
subIcon: PropTypes.oneOf(['momo', 'online', 'key', 'none']),
|
|
481
591
|
subIconSource: PropTypes.oneOfType([PropTypes.shape({ uri: PropTypes.string }), PropTypes.number, PropTypes.string]),
|
|
@@ -483,10 +593,15 @@ Avatar.propTypes = {
|
|
|
483
593
|
onPress: PropTypes.func,
|
|
484
594
|
loading: PropTypes.bool,
|
|
485
595
|
cached: PropTypes.bool,
|
|
486
|
-
|
|
596
|
+
scaleSize: PropTypes.bool,
|
|
597
|
+
extraPropsImage: PropTypes.object,
|
|
598
|
+
number: PropTypes.string
|
|
487
599
|
};
|
|
488
600
|
|
|
489
601
|
Avatar.defaultProps = {
|
|
490
602
|
resizeMode: 'cover',
|
|
491
|
-
cached: true
|
|
603
|
+
cached: true,
|
|
604
|
+
scaleSize: false,
|
|
605
|
+
quality: 'medium',
|
|
606
|
+
size: 'small'
|
|
492
607
|
};
|
package/Avatar.web.js
CHANGED
|
@@ -2,14 +2,43 @@
|
|
|
2
2
|
import PropTypes from 'prop-types';
|
|
3
3
|
import React, { Component } from 'react';
|
|
4
4
|
import {
|
|
5
|
-
View, StyleSheet, TouchableOpacity, Image
|
|
5
|
+
View, StyleSheet, TouchableOpacity, Image, Dimensions
|
|
6
6
|
} from 'react-native';
|
|
7
7
|
import { get, isEqual } from 'lodash';
|
|
8
|
-
import
|
|
9
|
-
import Colors from '../../colors';
|
|
10
|
-
import { Icons } from '../../icons';
|
|
11
|
-
import Text from '
|
|
12
|
-
import {
|
|
8
|
+
import ValueUtil from '../../core/utils/ValueUtil';
|
|
9
|
+
import Colors from '../../core/colors';
|
|
10
|
+
import { Icons as IconSource } from '../../core/icons';
|
|
11
|
+
import Text from '../../core/components/typography';
|
|
12
|
+
import { RFValueHorizontal as ScaleSize } from '../../core/components/typography/reponsiveSize';
|
|
13
|
+
|
|
14
|
+
export const AvatarQuality = {
|
|
15
|
+
low: 'low',
|
|
16
|
+
medium: 'medium',
|
|
17
|
+
high: 'high',
|
|
18
|
+
};
|
|
19
|
+
|
|
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
|
+
];
|
|
13
42
|
|
|
14
43
|
export const AvatarSize = {
|
|
15
44
|
tiny: 'tiny',
|
|
@@ -78,7 +107,7 @@ const styles = StyleSheet.create({
|
|
|
78
107
|
}
|
|
79
108
|
});
|
|
80
109
|
|
|
81
|
-
const subIconSize =
|
|
110
|
+
const subIconSize = (width) => ({
|
|
82
111
|
tiny: {
|
|
83
112
|
width: 8,
|
|
84
113
|
height: 8,
|
|
@@ -178,7 +207,7 @@ const subIconSize = StyleSheet.create({
|
|
|
178
207
|
}
|
|
179
208
|
});
|
|
180
209
|
|
|
181
|
-
const avatarSize =
|
|
210
|
+
const avatarSize = (width) => ({
|
|
182
211
|
tiny: {
|
|
183
212
|
width: 16,
|
|
184
213
|
height: 16,
|
|
@@ -266,34 +295,57 @@ const avatarSize = StyleSheet.create({
|
|
|
266
295
|
}
|
|
267
296
|
});
|
|
268
297
|
|
|
269
|
-
const shortName =
|
|
298
|
+
const shortName = (width) => ({
|
|
270
299
|
tiny: {
|
|
271
|
-
fontSize: 5
|
|
300
|
+
fontSize: ScaleSize(5, width)
|
|
272
301
|
},
|
|
273
302
|
small: {
|
|
274
|
-
fontSize: 11
|
|
303
|
+
fontSize: ScaleSize(11, width)
|
|
275
304
|
},
|
|
276
305
|
medium: {
|
|
277
|
-
fontSize: 15
|
|
306
|
+
fontSize: ScaleSize(15, width)
|
|
278
307
|
},
|
|
279
308
|
large: {
|
|
280
|
-
fontSize: 20
|
|
309
|
+
fontSize: ScaleSize(20, width)
|
|
281
310
|
},
|
|
282
311
|
giant: {
|
|
283
|
-
fontSize: 25
|
|
312
|
+
fontSize: ScaleSize(25, width)
|
|
284
313
|
}
|
|
285
314
|
});
|
|
286
315
|
|
|
287
316
|
export default class Avatar extends Component {
|
|
288
317
|
constructor(props) {
|
|
289
318
|
super(props);
|
|
319
|
+
this.color = this.getAvatarColor(props.name);
|
|
290
320
|
this.state = {
|
|
291
321
|
hideSource: false,
|
|
292
322
|
ownUpdate: false,
|
|
293
|
-
source: props.source
|
|
323
|
+
source: props.source,
|
|
324
|
+
dimensions: {}
|
|
294
325
|
};
|
|
295
326
|
}
|
|
296
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
|
+
}
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
componentWillUnmount() {
|
|
343
|
+
const { scaleSize } = this.props;
|
|
344
|
+
if (scaleSize) {
|
|
345
|
+
this.subscription?.remove?.();
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
|
|
297
349
|
static getDerivedStateFromProps(nextProps, prevState) {
|
|
298
350
|
if (prevState.ownUpdate) {
|
|
299
351
|
return {
|
|
@@ -336,49 +388,66 @@ export default class Avatar extends Component {
|
|
|
336
388
|
}
|
|
337
389
|
|
|
338
390
|
isValidImageUrl = (source) => {
|
|
339
|
-
const validSource = source &&
|
|
391
|
+
const validSource = source && source.uri && this.isUrl(source.uri);
|
|
340
392
|
return validSource;
|
|
341
393
|
}
|
|
342
394
|
|
|
395
|
+
mapAvatarQuality = (url, quality) => {
|
|
396
|
+
if (!quality || quality === AvatarQuality.medium) {
|
|
397
|
+
return url;
|
|
398
|
+
}
|
|
399
|
+
if (quality === AvatarQuality.low) {
|
|
400
|
+
return url.replace('.png', '_s64.png');
|
|
401
|
+
}
|
|
402
|
+
if (quality === AvatarQuality.high) {
|
|
403
|
+
return url.replace('.png', '_s512.png');
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
return url;
|
|
407
|
+
}
|
|
408
|
+
|
|
343
409
|
mapStyleFromSize = (size) => {
|
|
344
|
-
const
|
|
410
|
+
const { dimensions } = this.state;
|
|
411
|
+
const avatarStyle = avatarSize(dimensions?.width || null).small;
|
|
345
412
|
if (typeof size === 'object') return size;
|
|
346
|
-
if (avatarSize[size]) return avatarSize[size];
|
|
413
|
+
if (avatarSize(dimensions?.width || null)[size]) return avatarSize(dimensions?.width || null)[size];
|
|
347
414
|
return avatarStyle;
|
|
348
415
|
}
|
|
349
416
|
|
|
350
417
|
mapShortNameStyle = (size) => {
|
|
351
418
|
let shortNameStyle = {};
|
|
419
|
+
const { dimensions } = this.state;
|
|
352
420
|
switch (size) {
|
|
353
421
|
case AvatarSize.tiny: {
|
|
354
|
-
shortNameStyle = shortName.tiny;
|
|
422
|
+
shortNameStyle = shortName(dimensions?.width || null).tiny;
|
|
355
423
|
break;
|
|
356
424
|
}
|
|
357
425
|
case AvatarSize.small: {
|
|
358
|
-
shortNameStyle = shortName.small;
|
|
426
|
+
shortNameStyle = shortName(dimensions?.width || null).small;
|
|
359
427
|
break;
|
|
360
428
|
}
|
|
361
429
|
case AvatarSize.medium: {
|
|
362
|
-
shortNameStyle = shortName.medium;
|
|
430
|
+
shortNameStyle = shortName(dimensions?.width || null).medium;
|
|
363
431
|
break;
|
|
364
432
|
}
|
|
365
433
|
case AvatarSize.large: {
|
|
366
|
-
shortNameStyle = shortName.large;
|
|
434
|
+
shortNameStyle = shortName(dimensions?.width || null).large;
|
|
367
435
|
break;
|
|
368
436
|
}
|
|
369
437
|
case AvatarSize.giant: {
|
|
370
|
-
shortNameStyle = shortName.giant;
|
|
438
|
+
shortNameStyle = shortName(dimensions?.width || null).giant;
|
|
371
439
|
break;
|
|
372
440
|
}
|
|
373
441
|
default:
|
|
374
|
-
shortNameStyle = shortName.small;
|
|
442
|
+
shortNameStyle = shortName(dimensions?.width || null).small;
|
|
375
443
|
}
|
|
376
444
|
return shortNameStyle;
|
|
377
445
|
}
|
|
378
446
|
|
|
379
447
|
mapSubIconSize = (size) => {
|
|
380
|
-
const
|
|
381
|
-
|
|
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];
|
|
382
451
|
return subIconStyle;
|
|
383
452
|
}
|
|
384
453
|
|
|
@@ -391,10 +460,20 @@ export default class Avatar extends Component {
|
|
|
391
460
|
height: containerWidth,
|
|
392
461
|
borderRadius: containerWidth / 2,
|
|
393
462
|
borderWidth,
|
|
394
|
-
borderColor:
|
|
463
|
+
borderColor: Colors.black_01
|
|
395
464
|
};
|
|
396
465
|
}
|
|
397
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
|
+
}
|
|
475
|
+
|
|
476
|
+
|
|
398
477
|
onLoadSourceError = () => {
|
|
399
478
|
this.setState({ hideSource: true, ownUpdate: true });
|
|
400
479
|
}
|
|
@@ -403,14 +482,14 @@ export default class Avatar extends Component {
|
|
|
403
482
|
const { subIcon, size, subIconSource } = this.props;
|
|
404
483
|
if ((!subIcon || subIcon === SubIconType.none) && !subIconSource) return <View />;
|
|
405
484
|
const subIconSizeStyle = this.mapSubIconSize(size);
|
|
406
|
-
const iconSource =
|
|
485
|
+
const iconSource = ValueUtil.getImageSource(subIconSource);
|
|
407
486
|
return (
|
|
408
487
|
<View style={styles.subIcon}>
|
|
409
488
|
{subIcon === SubIconType.momo
|
|
410
489
|
? (
|
|
411
490
|
<Image
|
|
412
491
|
style={[styles.subIconImage, subIconSizeStyle]}
|
|
413
|
-
source={
|
|
492
|
+
source={IconSource.ic_round_momo_tiny}
|
|
414
493
|
/>
|
|
415
494
|
)
|
|
416
495
|
: <View />}
|
|
@@ -435,16 +514,27 @@ export default class Avatar extends Component {
|
|
|
435
514
|
|
|
436
515
|
render() {
|
|
437
516
|
const {
|
|
438
|
-
size, source, name, resizeMode, style, onPress, isShowLoading, loading, cached, extraPropsImage
|
|
517
|
+
size, source, name, resizeMode, style, onPress, isShowLoading, loading, cached, extraPropsImage, quality
|
|
439
518
|
} = this.props;
|
|
440
519
|
const { hideSource } = this.state;
|
|
441
520
|
const avatarStyle = this.mapStyleFromSize(size);
|
|
442
521
|
const containerSize = this.extractSize(avatarStyle);
|
|
443
|
-
const imageSource =
|
|
522
|
+
const imageSource = ValueUtil.getImageSource(source);
|
|
444
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
|
+
}
|
|
534
|
+
|
|
445
535
|
const inner = (
|
|
446
|
-
<View style={[styles.container,
|
|
447
|
-
{(showName || hideSource) ? this.renderShortName(name, avatarStyle, size) :
|
|
536
|
+
<View style={[styles.container, containerSize, style]}>
|
|
537
|
+
{(showName || hideSource) ? this.renderShortName(name, avatarStyle, size) : <View />}
|
|
448
538
|
{this.isValidImageUrl(imageSource) && !hideSource
|
|
449
539
|
? (
|
|
450
540
|
<Image
|
|
@@ -472,54 +562,27 @@ export default class Avatar extends Component {
|
|
|
472
562
|
}
|
|
473
563
|
|
|
474
564
|
Avatar.propTypes = {
|
|
475
|
-
/**
|
|
476
|
-
* The default name when image load fail.
|
|
477
|
-
*/
|
|
478
565
|
name: PropTypes.string,
|
|
479
|
-
/**
|
|
480
|
-
* How resize should the avatar be?
|
|
481
|
-
*/
|
|
482
566
|
resizeMode: PropTypes.string,
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
* What source Avatar to use?
|
|
489
|
-
*/
|
|
567
|
+
quality: PropTypes.oneOf(['low', 'medium', 'high']),
|
|
568
|
+
size: PropTypes.oneOf(['tiny', 'small', 'medium', 'large', 'giant', 'size8', 'size24', 'size36', 'size44', 'size48', 'size52', 'size56', 'size64', 'size72', 'size80', 'size88', 'size96',
|
|
569
|
+
PropTypes.shape({
|
|
570
|
+
width: PropTypes.number, height: PropTypes.number, borderRadius: PropTypes.number
|
|
571
|
+
})]),
|
|
490
572
|
source: PropTypes.oneOfType([PropTypes.shape({ uri: PropTypes.string }), PropTypes.number, PropTypes.string]),
|
|
491
|
-
/**
|
|
492
|
-
* What subIcon Avatar to use?
|
|
493
|
-
*/
|
|
494
573
|
subIcon: PropTypes.oneOf(['momo', 'online', 'key', 'none']),
|
|
495
|
-
/**
|
|
496
|
-
* What custom subIcon Avatar to use?
|
|
497
|
-
*/
|
|
498
574
|
subIconSource: PropTypes.oneOfType([PropTypes.shape({ uri: PropTypes.string }), PropTypes.number, PropTypes.string]),
|
|
499
|
-
/**
|
|
500
|
-
* What custom style Avatar to use?
|
|
501
|
-
*/
|
|
502
575
|
style: PropTypes.oneOfType([PropTypes.array, PropTypes.object]),
|
|
503
|
-
/**
|
|
504
|
-
* Optional click handler.
|
|
505
|
-
*/
|
|
506
576
|
onPress: PropTypes.func,
|
|
507
|
-
/**
|
|
508
|
-
* Optional loading handler.
|
|
509
|
-
*/
|
|
510
577
|
loading: PropTypes.bool,
|
|
511
|
-
/**
|
|
512
|
-
* Optional cached handler.
|
|
513
|
-
*/
|
|
514
578
|
cached: PropTypes.bool,
|
|
515
|
-
|
|
516
|
-
* Optional extra prop of Image.
|
|
517
|
-
*/
|
|
579
|
+
scaleSize: PropTypes.bool,
|
|
518
580
|
extraPropsImage: PropTypes.object
|
|
519
581
|
};
|
|
520
582
|
|
|
521
583
|
Avatar.defaultProps = {
|
|
522
584
|
resizeMode: 'cover',
|
|
523
|
-
|
|
524
|
-
|
|
585
|
+
cached: true,
|
|
586
|
+
scaleSize: false,
|
|
587
|
+
quality: 'medium',
|
|
525
588
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@momo-kits/avatar",
|
|
3
|
-
"version": "0.0.33
|
|
3
|
+
"version": "0.0.33",
|
|
4
4
|
"private": false,
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"dependencies": {},
|
|
@@ -8,16 +8,9 @@
|
|
|
8
8
|
"react-native": ">=0.55",
|
|
9
9
|
"prop-types": "^15.7.2",
|
|
10
10
|
"react": "16.9.0",
|
|
11
|
-
"
|
|
12
|
-
"
|
|
11
|
+
"@momo-kits/core": ">=0.0.5-beta",
|
|
12
|
+
"lodash": "^4.17.15"
|
|
13
13
|
},
|
|
14
|
-
"devDependencies": {
|
|
15
|
-
|
|
16
|
-
"@babel/core": "^7.12.9",
|
|
17
|
-
"@babel/runtime": "^7.12.5"
|
|
18
|
-
},
|
|
19
|
-
"license": "MoMo",
|
|
20
|
-
"jest": {
|
|
21
|
-
"preset": "react-native"
|
|
22
|
-
}
|
|
14
|
+
"devDependencies": {},
|
|
15
|
+
"license": "MoMo"
|
|
23
16
|
}
|
package/publish.sh
CHANGED
|
@@ -26,4 +26,4 @@ cd ..
|
|
|
26
26
|
rm -rf dist
|
|
27
27
|
|
|
28
28
|
|
|
29
|
-
|
|
29
|
+
curl -X POST -H 'Content-Type: application/json' 'https://chat.googleapis.com/v1/spaces/AAAAbP8987c/messages?key=AIzaSyDdI0hCZtE6vySjMm-WEfRq3CPzqKqqsHI&token=UGSFRvk_oYb9uGsAgs31bVvMm6jDkmD8zihGm3eyaQA%3D&threadKey=JoaXTEYaNNkl' -d '{"text": "@momo-kits/avatar new version release: '*"$VERSION"*' https://www.npmjs.com/package/@momo-kits/avatar"}'
|
package/babel.config.js
DELETED