@momo-kits/avatar 0.0.61-beta → 0.0.61-beta.3
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 +298 -116
- package/Avatar.web.js +73 -4
- package/package.json +14 -14
- package/publish.sh +2 -2
package/Avatar.js
CHANGED
|
@@ -2,13 +2,28 @@
|
|
|
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
|
+
Dimensions,
|
|
9
|
+
Platform,
|
|
6
10
|
} from 'react-native';
|
|
7
11
|
import { get, isEqual } from 'lodash';
|
|
8
12
|
import {
|
|
9
|
-
|
|
13
|
+
ValueUtil,
|
|
14
|
+
Colors,
|
|
15
|
+
Text,
|
|
16
|
+
IconSource,
|
|
17
|
+
Image,
|
|
18
|
+
ScaleSize,
|
|
10
19
|
} from '@momo-kits/core';
|
|
11
20
|
|
|
21
|
+
export const AvatarQuality = {
|
|
22
|
+
low: 'low',
|
|
23
|
+
medium: 'medium',
|
|
24
|
+
high: 'high',
|
|
25
|
+
};
|
|
26
|
+
|
|
12
27
|
export const AvatarSize = {
|
|
13
28
|
tiny: 'tiny',
|
|
14
29
|
small: 'small',
|
|
@@ -26,20 +41,43 @@ export const AvatarSize = {
|
|
|
26
41
|
size72: 'size72',
|
|
27
42
|
size80: 'size80',
|
|
28
43
|
size88: 'size88',
|
|
29
|
-
size96: 'size96'
|
|
44
|
+
size96: 'size96',
|
|
30
45
|
};
|
|
31
46
|
|
|
47
|
+
const COLORS = [
|
|
48
|
+
'#3683f3',
|
|
49
|
+
'#ea63af',
|
|
50
|
+
'#f94889',
|
|
51
|
+
'#82b6da',
|
|
52
|
+
'#2fc093',
|
|
53
|
+
'#7b4a41',
|
|
54
|
+
'#ff97bc',
|
|
55
|
+
'#4130d7',
|
|
56
|
+
'#c3c3c3',
|
|
57
|
+
'#f7ae2f',
|
|
58
|
+
'#b04595',
|
|
59
|
+
'#57b748',
|
|
60
|
+
'#ff8900',
|
|
61
|
+
'#7841bf',
|
|
62
|
+
'#be3f3e',
|
|
63
|
+
'#c51515',
|
|
64
|
+
'#8e6472',
|
|
65
|
+
'#fed27d',
|
|
66
|
+
'#ff6f5d',
|
|
67
|
+
'#05b8ae',
|
|
68
|
+
];
|
|
69
|
+
|
|
32
70
|
export const SubIconType = {
|
|
33
71
|
momo: 'momo',
|
|
34
72
|
online: 'online',
|
|
35
73
|
key: 'key',
|
|
36
|
-
none: 'none'
|
|
74
|
+
none: 'none',
|
|
37
75
|
};
|
|
38
76
|
|
|
39
77
|
const styles = StyleSheet.create({
|
|
40
78
|
container: {
|
|
41
79
|
justifyContent: 'center',
|
|
42
|
-
alignItems: 'center'
|
|
80
|
+
alignItems: 'center',
|
|
43
81
|
},
|
|
44
82
|
shortNameView: {
|
|
45
83
|
justifyContent: 'center',
|
|
@@ -47,90 +85,93 @@ const styles = StyleSheet.create({
|
|
|
47
85
|
|
|
48
86
|
backgroundColor: Colors.very_light_pink_four,
|
|
49
87
|
width: '100%',
|
|
50
|
-
height: '100%'
|
|
88
|
+
height: '100%',
|
|
51
89
|
},
|
|
52
90
|
shortNameText: {
|
|
53
91
|
// fontSize: 17,
|
|
54
|
-
color:
|
|
92
|
+
color: Colors.pink_03,
|
|
93
|
+
},
|
|
94
|
+
shortNameTextCustom: {
|
|
95
|
+
color: '#f6f6f6',
|
|
55
96
|
},
|
|
56
97
|
absolute: {
|
|
57
98
|
position: 'absolute',
|
|
58
99
|
top: 0,
|
|
59
100
|
left: 0,
|
|
60
101
|
right: 0,
|
|
61
|
-
bottom: 0
|
|
102
|
+
bottom: 0,
|
|
62
103
|
},
|
|
63
104
|
subIcon: {
|
|
64
105
|
position: 'absolute',
|
|
65
106
|
bottom: 0,
|
|
66
|
-
right: 0
|
|
107
|
+
right: 0,
|
|
67
108
|
},
|
|
68
109
|
subIconImage: {
|
|
69
110
|
width: 22,
|
|
70
|
-
height: 22
|
|
111
|
+
height: 22,
|
|
71
112
|
},
|
|
72
113
|
subIconImageOnline: {
|
|
73
114
|
backgroundColor: Colors.kiwi_green,
|
|
74
115
|
borderColor: 'white',
|
|
75
|
-
borderWidth: 1
|
|
76
|
-
}
|
|
116
|
+
borderWidth: 1,
|
|
117
|
+
},
|
|
77
118
|
});
|
|
78
119
|
|
|
79
120
|
const subIconSize = (width) => ({
|
|
80
121
|
tiny: {
|
|
81
122
|
width: 8,
|
|
82
123
|
height: 8,
|
|
83
|
-
borderRadius: 4
|
|
124
|
+
borderRadius: 4,
|
|
84
125
|
},
|
|
85
126
|
small: {
|
|
86
127
|
width: 10,
|
|
87
128
|
height: 10,
|
|
88
|
-
borderRadius: 5
|
|
129
|
+
borderRadius: 5,
|
|
89
130
|
},
|
|
90
131
|
medium: {
|
|
91
132
|
width: 12,
|
|
92
133
|
height: 12,
|
|
93
|
-
borderRadius: 6
|
|
134
|
+
borderRadius: 6,
|
|
94
135
|
},
|
|
95
136
|
large: {
|
|
96
137
|
width: 16,
|
|
97
138
|
height: 16,
|
|
98
|
-
borderRadius: 8
|
|
139
|
+
borderRadius: 8,
|
|
99
140
|
},
|
|
100
141
|
size8: {
|
|
101
142
|
width: 8,
|
|
102
143
|
height: 8,
|
|
103
|
-
borderRadius: 4
|
|
144
|
+
borderRadius: 4,
|
|
104
145
|
},
|
|
105
146
|
size24: {
|
|
106
147
|
width: 10,
|
|
107
148
|
height: 10,
|
|
108
|
-
borderRadius: 5
|
|
149
|
+
borderRadius: 5,
|
|
109
150
|
},
|
|
110
151
|
size36: {
|
|
111
152
|
width: 10,
|
|
112
153
|
height: 10,
|
|
113
|
-
borderRadius: 5
|
|
154
|
+
borderRadius: 5,
|
|
114
155
|
},
|
|
115
156
|
size44: {
|
|
116
157
|
width: 14,
|
|
117
158
|
height: 14,
|
|
118
|
-
borderRadius: 7
|
|
159
|
+
borderRadius: 7,
|
|
119
160
|
},
|
|
120
161
|
size48: {
|
|
121
162
|
width: 14,
|
|
122
163
|
height: 14,
|
|
123
|
-
borderRadius: 7
|
|
164
|
+
borderRadius: 7,
|
|
124
165
|
},
|
|
125
166
|
size52: {
|
|
126
167
|
width: 16,
|
|
127
168
|
height: 16,
|
|
128
|
-
borderRadius: 8
|
|
169
|
+
borderRadius: 8,
|
|
129
170
|
},
|
|
130
171
|
size56: {
|
|
131
172
|
width: 16,
|
|
132
173
|
height: 16,
|
|
133
|
-
borderRadius: 8
|
|
174
|
+
borderRadius: 8,
|
|
134
175
|
},
|
|
135
176
|
size64: {
|
|
136
177
|
width: 16,
|
|
@@ -172,125 +213,132 @@ const subIconSize = (width) => ({
|
|
|
172
213
|
left: -5,
|
|
173
214
|
width: 24,
|
|
174
215
|
height: 24,
|
|
175
|
-
borderRadius: 12
|
|
176
|
-
}
|
|
216
|
+
borderRadius: 12,
|
|
217
|
+
},
|
|
177
218
|
});
|
|
178
219
|
|
|
179
220
|
const avatarSize = (width) => ({
|
|
180
221
|
tiny: {
|
|
181
222
|
width: 16,
|
|
182
223
|
height: 16,
|
|
183
|
-
borderRadius: 8
|
|
224
|
+
borderRadius: 8,
|
|
184
225
|
},
|
|
185
226
|
small: {
|
|
186
227
|
width: 32,
|
|
187
228
|
height: 32,
|
|
188
|
-
borderRadius: 16
|
|
229
|
+
borderRadius: 16,
|
|
189
230
|
},
|
|
190
231
|
medium: {
|
|
191
232
|
width: 40,
|
|
192
233
|
height: 40,
|
|
193
|
-
borderRadius: 20
|
|
234
|
+
borderRadius: 20,
|
|
194
235
|
},
|
|
195
236
|
large: {
|
|
196
237
|
width: 60,
|
|
197
238
|
height: 60,
|
|
198
|
-
borderRadius: 30
|
|
239
|
+
borderRadius: 30,
|
|
199
240
|
},
|
|
200
241
|
giant: {
|
|
201
242
|
width: 120,
|
|
202
243
|
height: 120,
|
|
203
|
-
borderRadius: 60
|
|
244
|
+
borderRadius: 60,
|
|
204
245
|
},
|
|
205
246
|
size8: {
|
|
206
247
|
width: 8,
|
|
207
248
|
height: 8,
|
|
208
|
-
borderRadius: 4
|
|
249
|
+
borderRadius: 4,
|
|
209
250
|
},
|
|
210
251
|
size24: {
|
|
211
252
|
width: 24,
|
|
212
253
|
height: 24,
|
|
213
|
-
borderRadius: 12
|
|
254
|
+
borderRadius: 12,
|
|
214
255
|
},
|
|
215
256
|
size36: {
|
|
216
257
|
width: 36,
|
|
217
258
|
height: 36,
|
|
218
|
-
borderRadius: 18
|
|
259
|
+
borderRadius: 18,
|
|
219
260
|
},
|
|
220
261
|
size44: {
|
|
221
262
|
width: 44,
|
|
222
263
|
height: 44,
|
|
223
|
-
borderRadius: 22
|
|
264
|
+
borderRadius: 22,
|
|
224
265
|
},
|
|
225
266
|
size48: {
|
|
226
267
|
width: 48,
|
|
227
268
|
height: 48,
|
|
228
|
-
borderRadius: 24
|
|
269
|
+
borderRadius: 24,
|
|
229
270
|
},
|
|
230
271
|
size52: {
|
|
231
272
|
width: 52,
|
|
232
273
|
height: 52,
|
|
233
|
-
borderRadius: 26
|
|
274
|
+
borderRadius: 26,
|
|
234
275
|
},
|
|
235
276
|
size56: {
|
|
236
277
|
width: 56,
|
|
237
278
|
height: 56,
|
|
238
|
-
borderRadius: 28
|
|
279
|
+
borderRadius: 28,
|
|
239
280
|
},
|
|
240
281
|
size64: {
|
|
241
282
|
width: 64,
|
|
242
283
|
height: 64,
|
|
243
|
-
borderRadius: 32
|
|
284
|
+
borderRadius: 32,
|
|
244
285
|
},
|
|
245
286
|
size72: {
|
|
246
287
|
width: 72,
|
|
247
288
|
height: 72,
|
|
248
|
-
borderRadius: 36
|
|
289
|
+
borderRadius: 36,
|
|
249
290
|
},
|
|
250
291
|
size80: {
|
|
251
292
|
width: 80,
|
|
252
293
|
height: 80,
|
|
253
|
-
borderRadius: 40
|
|
294
|
+
borderRadius: 40,
|
|
254
295
|
},
|
|
255
296
|
size88: {
|
|
256
297
|
width: 88,
|
|
257
298
|
height: 88,
|
|
258
|
-
borderRadius: 44
|
|
299
|
+
borderRadius: 44,
|
|
259
300
|
},
|
|
260
301
|
size96: {
|
|
261
302
|
width: 96,
|
|
262
303
|
height: 96,
|
|
263
|
-
borderRadius: 48
|
|
264
|
-
}
|
|
304
|
+
borderRadius: 48,
|
|
305
|
+
},
|
|
265
306
|
});
|
|
266
307
|
|
|
267
308
|
const shortName = (width) => ({
|
|
268
309
|
tiny: {
|
|
269
|
-
fontSize: ScaleSize(5, width)
|
|
310
|
+
fontSize: ScaleSize(5, width),
|
|
270
311
|
},
|
|
271
312
|
small: {
|
|
272
|
-
fontSize: ScaleSize(11, width)
|
|
313
|
+
fontSize: ScaleSize(11, width),
|
|
273
314
|
},
|
|
274
315
|
medium: {
|
|
275
|
-
fontSize: ScaleSize(15, width)
|
|
316
|
+
fontSize: ScaleSize(15, width),
|
|
317
|
+
},
|
|
318
|
+
middle: {
|
|
319
|
+
fontSize: ScaleSize(16, width),
|
|
276
320
|
},
|
|
277
321
|
large: {
|
|
278
|
-
fontSize: ScaleSize(20, width)
|
|
322
|
+
fontSize: ScaleSize(20, width),
|
|
279
323
|
},
|
|
280
324
|
giant: {
|
|
281
|
-
fontSize: ScaleSize(25, width)
|
|
282
|
-
}
|
|
325
|
+
fontSize: ScaleSize(25, width),
|
|
326
|
+
},
|
|
283
327
|
});
|
|
284
328
|
|
|
285
329
|
export default class Avatar extends Component {
|
|
286
330
|
constructor(props) {
|
|
287
331
|
super(props);
|
|
332
|
+
this.color = props.custom
|
|
333
|
+
? this.getAvatarColor(props.name)
|
|
334
|
+
: Colors.pink_10;
|
|
288
335
|
this.state = {
|
|
289
336
|
hideSource: false,
|
|
290
337
|
ownUpdate: false,
|
|
291
338
|
source: props.source,
|
|
292
|
-
dimensions: {}
|
|
339
|
+
dimensions: {},
|
|
293
340
|
};
|
|
341
|
+
this.imageSource = '';
|
|
294
342
|
}
|
|
295
343
|
|
|
296
344
|
componentDidMount() {
|
|
@@ -299,8 +347,14 @@ export default class Avatar extends Component {
|
|
|
299
347
|
this.subscription = Dimensions.addEventListener(
|
|
300
348
|
'change',
|
|
301
349
|
({ window }) => {
|
|
302
|
-
|
|
303
|
-
|
|
350
|
+
if (
|
|
351
|
+
window?.height > 0 &&
|
|
352
|
+
window?.width > 0 &&
|
|
353
|
+
Platform.OS === 'android'
|
|
354
|
+
) {
|
|
355
|
+
this.setState({ dimensions: window });
|
|
356
|
+
}
|
|
357
|
+
},
|
|
304
358
|
);
|
|
305
359
|
}
|
|
306
360
|
}
|
|
@@ -317,7 +371,8 @@ export default class Avatar extends Component {
|
|
|
317
371
|
return {
|
|
318
372
|
ownUpdate: false,
|
|
319
373
|
};
|
|
320
|
-
}
|
|
374
|
+
}
|
|
375
|
+
if (!isEqual(nextProps.source, prevState.source)) {
|
|
321
376
|
return { source: nextProps.source, hideSource: false };
|
|
322
377
|
}
|
|
323
378
|
return null;
|
|
@@ -333,75 +388,141 @@ export default class Avatar extends Component {
|
|
|
333
388
|
}
|
|
334
389
|
});
|
|
335
390
|
return alphabet.join('');
|
|
391
|
+
};
|
|
392
|
+
|
|
393
|
+
hashUrl(url) {
|
|
394
|
+
let hash = 0;
|
|
395
|
+
let char;
|
|
396
|
+
if (url?.length === 0) return hash;
|
|
397
|
+
for (let i = 0; i < url?.length; i++) {
|
|
398
|
+
char = url?.charCodeAt(i);
|
|
399
|
+
hash = (hash << 5) - hash + char;
|
|
400
|
+
hash &= hash; // Convert to 32bit integer
|
|
401
|
+
}
|
|
402
|
+
return hash;
|
|
336
403
|
}
|
|
337
404
|
|
|
338
|
-
renderShortName = (name, avatarStyle, size) => {
|
|
405
|
+
renderShortName = (name, avatarStyle, size, color) => {
|
|
339
406
|
if (name) {
|
|
340
407
|
const shortedName = this.getContactShortName(name);
|
|
341
408
|
const shortNameStyle = this.mapShortNameStyle(size);
|
|
342
409
|
return (
|
|
343
|
-
<View
|
|
344
|
-
|
|
410
|
+
<View
|
|
411
|
+
style={[
|
|
412
|
+
styles.shortNameView,
|
|
413
|
+
avatarStyle,
|
|
414
|
+
{ backgroundColor: color },
|
|
415
|
+
]}>
|
|
416
|
+
<Text.H4
|
|
417
|
+
style={[
|
|
418
|
+
this.props.custom
|
|
419
|
+
? styles.shortNameTextCustom
|
|
420
|
+
: styles.shortNameText,
|
|
421
|
+
shortNameStyle,
|
|
422
|
+
]}>
|
|
423
|
+
{shortedName}
|
|
424
|
+
</Text.H4>
|
|
345
425
|
</View>
|
|
346
426
|
);
|
|
347
427
|
}
|
|
348
428
|
return <View />;
|
|
349
|
-
}
|
|
429
|
+
};
|
|
350
430
|
|
|
351
431
|
isUrl(url) {
|
|
352
|
-
const expression =
|
|
432
|
+
const expression =
|
|
433
|
+
/(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-/]))?/gi;
|
|
353
434
|
return expression.test(url);
|
|
354
435
|
}
|
|
355
436
|
|
|
356
437
|
isValidImageUrl = (source) => {
|
|
357
|
-
const validSource = source &&
|
|
438
|
+
const validSource = source && source.uri && this.isUrl(source.uri);
|
|
358
439
|
return validSource;
|
|
359
|
-
}
|
|
440
|
+
};
|
|
441
|
+
|
|
442
|
+
mapAvatarQuality = (url, quality) => {
|
|
443
|
+
if (!quality || quality === AvatarQuality.medium) {
|
|
444
|
+
return url;
|
|
445
|
+
}
|
|
446
|
+
if (quality === AvatarQuality.low) {
|
|
447
|
+
return url.replace('.png', '_s64.png');
|
|
448
|
+
}
|
|
449
|
+
if (quality === AvatarQuality.high) {
|
|
450
|
+
return url.replace('.png', '_s512.png');
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
return url;
|
|
454
|
+
};
|
|
360
455
|
|
|
361
456
|
mapStyleFromSize = (size) => {
|
|
362
457
|
const { dimensions } = this.state;
|
|
363
|
-
const avatarStyle = avatarSize(
|
|
458
|
+
const avatarStyle = avatarSize(
|
|
459
|
+
dimensions?.width > 0 ? dimensions?.width : null,
|
|
460
|
+
).small;
|
|
364
461
|
if (typeof size === 'object') return size;
|
|
365
|
-
if (avatarSize(dimensions?.width
|
|
462
|
+
if (avatarSize(dimensions?.width > 0 ? dimensions?.width : null)[size])
|
|
463
|
+
return avatarSize(dimensions?.width > 0 ? dimensions?.width : null)[
|
|
464
|
+
size
|
|
465
|
+
];
|
|
366
466
|
return avatarStyle;
|
|
367
|
-
}
|
|
467
|
+
};
|
|
368
468
|
|
|
369
469
|
mapShortNameStyle = (size) => {
|
|
370
470
|
let shortNameStyle = {};
|
|
371
471
|
const { dimensions } = this.state;
|
|
372
472
|
switch (size) {
|
|
373
473
|
case AvatarSize.tiny: {
|
|
374
|
-
shortNameStyle = shortName(
|
|
474
|
+
shortNameStyle = shortName(
|
|
475
|
+
dimensions?.width > 0 ? dimensions?.width : null,
|
|
476
|
+
).tiny;
|
|
375
477
|
break;
|
|
376
478
|
}
|
|
377
479
|
case AvatarSize.small: {
|
|
378
|
-
shortNameStyle = shortName(
|
|
480
|
+
shortNameStyle = shortName(
|
|
481
|
+
dimensions?.width > 0 ? dimensions?.width : null,
|
|
482
|
+
).small;
|
|
379
483
|
break;
|
|
380
484
|
}
|
|
381
485
|
case AvatarSize.medium: {
|
|
382
|
-
shortNameStyle = shortName(
|
|
486
|
+
shortNameStyle = shortName(
|
|
487
|
+
dimensions?.width > 0 ? dimensions?.width : null,
|
|
488
|
+
).medium;
|
|
489
|
+
break;
|
|
490
|
+
}
|
|
491
|
+
case AvatarSize.size48: {
|
|
492
|
+
shortNameStyle = shortName(dimensions?.width || null).middle;
|
|
383
493
|
break;
|
|
384
494
|
}
|
|
385
495
|
case AvatarSize.large: {
|
|
386
|
-
shortNameStyle = shortName(
|
|
496
|
+
shortNameStyle = shortName(
|
|
497
|
+
dimensions?.width > 0 ? dimensions?.width : null,
|
|
498
|
+
).large;
|
|
387
499
|
break;
|
|
388
500
|
}
|
|
389
501
|
case AvatarSize.giant: {
|
|
390
|
-
shortNameStyle = shortName(
|
|
502
|
+
shortNameStyle = shortName(
|
|
503
|
+
dimensions?.width > 0 ? dimensions?.width : null,
|
|
504
|
+
).giant;
|
|
391
505
|
break;
|
|
392
506
|
}
|
|
393
507
|
default:
|
|
394
|
-
shortNameStyle = shortName(
|
|
508
|
+
shortNameStyle = shortName(
|
|
509
|
+
dimensions?.width > 0 ? dimensions?.width : null,
|
|
510
|
+
).small;
|
|
395
511
|
}
|
|
396
512
|
return shortNameStyle;
|
|
397
|
-
}
|
|
513
|
+
};
|
|
398
514
|
|
|
399
515
|
mapSubIconSize = (size) => {
|
|
400
516
|
const { dimensions } = this.state;
|
|
401
|
-
const subIconStyle = subIconSize(
|
|
402
|
-
|
|
517
|
+
const subIconStyle = subIconSize(
|
|
518
|
+
dimensions?.width > 0 ? dimensions?.width : null,
|
|
519
|
+
).small;
|
|
520
|
+
if (subIconSize(dimensions?.width > 0 ? dimensions?.width : null)[size])
|
|
521
|
+
return subIconSize(
|
|
522
|
+
dimensions?.width > 0 ? dimensions?.width : null,
|
|
523
|
+
)[size];
|
|
403
524
|
return subIconStyle;
|
|
404
|
-
}
|
|
525
|
+
};
|
|
405
526
|
|
|
406
527
|
extractSize = (avatarStyle) => {
|
|
407
528
|
const { style } = this.props;
|
|
@@ -412,78 +533,128 @@ export default class Avatar extends Component {
|
|
|
412
533
|
height: containerWidth,
|
|
413
534
|
borderRadius: containerWidth / 2,
|
|
414
535
|
borderWidth,
|
|
415
|
-
borderColor: Colors.black_01
|
|
536
|
+
borderColor: Colors.black_01,
|
|
416
537
|
};
|
|
417
|
-
}
|
|
538
|
+
};
|
|
418
539
|
|
|
419
|
-
onLoadSourceError = () => {
|
|
420
|
-
this.
|
|
421
|
-
|
|
540
|
+
onLoadSourceError = (imageSource) => {
|
|
541
|
+
if (this.imageSource?.uri !== imageSource?.uri) {
|
|
542
|
+
this.imageSource = imageSource;
|
|
543
|
+
this.setState({ hideSource: true, ownUpdate: true });
|
|
544
|
+
}
|
|
545
|
+
};
|
|
422
546
|
|
|
423
547
|
renderSubIcon = () => {
|
|
424
548
|
const { subIcon, size, subIconSource } = this.props;
|
|
425
|
-
if ((!subIcon || subIcon === SubIconType.none) && !subIconSource)
|
|
549
|
+
if ((!subIcon || subIcon === SubIconType.none) && !subIconSource)
|
|
550
|
+
return <View />;
|
|
426
551
|
const subIconSizeStyle = this.mapSubIconSize(size);
|
|
427
552
|
const iconSource = ValueUtil.getImageSource(subIconSource);
|
|
428
553
|
return (
|
|
429
554
|
<View style={styles.subIcon}>
|
|
430
|
-
{subIcon === SubIconType.momo
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
{subIcon === SubIconType.online
|
|
439
|
-
|
|
555
|
+
{subIcon === SubIconType.momo ? (
|
|
556
|
+
<Image
|
|
557
|
+
style={[styles.subIconImage, subIconSizeStyle]}
|
|
558
|
+
source={IconSource.ic_round_momo_tiny}
|
|
559
|
+
/>
|
|
560
|
+
) : (
|
|
561
|
+
<View />
|
|
562
|
+
)}
|
|
563
|
+
{subIcon === SubIconType.online ? (
|
|
564
|
+
<View
|
|
565
|
+
style={[styles.subIconImageOnline, subIconSizeStyle]}
|
|
566
|
+
/>
|
|
567
|
+
) : (
|
|
568
|
+
<View />
|
|
569
|
+
)}
|
|
440
570
|
|
|
441
571
|
{iconSource && subIconSource && !subIcon ? (
|
|
442
572
|
<Image
|
|
443
573
|
style={[styles.subIconImage, subIconSizeStyle]}
|
|
444
574
|
source={iconSource}
|
|
445
575
|
/>
|
|
446
|
-
)
|
|
447
|
-
|
|
576
|
+
) : (
|
|
577
|
+
<View />
|
|
578
|
+
)}
|
|
448
579
|
</View>
|
|
449
580
|
);
|
|
581
|
+
};
|
|
582
|
+
|
|
583
|
+
getAvatarColor(name) {
|
|
584
|
+
const shortName = this.getContactShortName(name);
|
|
585
|
+
if (!shortName) return '#d5d6d6';
|
|
586
|
+
const firstLetter = shortName[0].charCodeAt(0);
|
|
587
|
+
let colorIndex = Number(firstLetter) % 26;
|
|
588
|
+
if (colorIndex > 19) colorIndex = 25 - colorIndex;
|
|
589
|
+
return COLORS[colorIndex];
|
|
450
590
|
}
|
|
451
591
|
|
|
452
592
|
onPress = () => {
|
|
453
593
|
const { onPress } = this.props;
|
|
454
594
|
if (onPress && typeof onPress === 'function') onPress();
|
|
455
|
-
}
|
|
595
|
+
};
|
|
456
596
|
|
|
457
597
|
render() {
|
|
458
598
|
const {
|
|
459
|
-
size,
|
|
599
|
+
size,
|
|
600
|
+
source,
|
|
601
|
+
name,
|
|
602
|
+
resizeMode,
|
|
603
|
+
style,
|
|
604
|
+
onPress,
|
|
605
|
+
isShowLoading,
|
|
606
|
+
loading,
|
|
607
|
+
cached,
|
|
608
|
+
extraPropsImage,
|
|
609
|
+
quality,
|
|
460
610
|
} = this.props;
|
|
461
611
|
const { hideSource } = this.state;
|
|
462
612
|
const avatarStyle = this.mapStyleFromSize(size);
|
|
463
613
|
const containerSize = this.extractSize(avatarStyle);
|
|
464
614
|
const imageSource = ValueUtil.getImageSource(source);
|
|
465
|
-
const showName =
|
|
615
|
+
const showName =
|
|
616
|
+
typeof imageSource === 'object' &&
|
|
617
|
+
Object.keys(imageSource).length === 0 &&
|
|
618
|
+
typeof imageSource !== 'number';
|
|
619
|
+
// add priority high for avatar
|
|
620
|
+
if (imageSource?.uri) {
|
|
621
|
+
imageSource.priority = 'high';
|
|
622
|
+
imageSource.uri = this.mapAvatarQuality(imageSource.uri, quality);
|
|
623
|
+
// if doest not have time query, set default cache time to 1 day
|
|
624
|
+
if (!imageSource.uri?.includes('?') && cached) {
|
|
625
|
+
const midnight = new Date().setHours(0, 0, 0, 0);
|
|
626
|
+
imageSource.uri = `${imageSource.uri}?time=${midnight}`;
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
|
|
466
630
|
const inner = (
|
|
467
631
|
<View style={[styles.container, containerSize, style]}>
|
|
468
|
-
{
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
632
|
+
{showName || hideSource ? (
|
|
633
|
+
this.renderShortName(name, avatarStyle, size, this.color)
|
|
634
|
+
) : (
|
|
635
|
+
<View />
|
|
636
|
+
)}
|
|
637
|
+
{this.isValidImageUrl(imageSource) && !hideSource ? (
|
|
638
|
+
<Image
|
|
639
|
+
cached={cached}
|
|
640
|
+
loading={loading || isShowLoading}
|
|
641
|
+
source={imageSource}
|
|
642
|
+
onError={() => this.onLoadSourceError(imageSource)}
|
|
643
|
+
style={avatarStyle}
|
|
644
|
+
resizeMode={resizeMode}
|
|
645
|
+
{...extraPropsImage}
|
|
646
|
+
/>
|
|
647
|
+
) : (
|
|
648
|
+
<View />
|
|
649
|
+
)}
|
|
481
650
|
{this.renderSubIcon()}
|
|
482
651
|
</View>
|
|
483
652
|
);
|
|
484
653
|
if (onPress) {
|
|
485
654
|
return (
|
|
486
|
-
<TouchableOpacity
|
|
655
|
+
<TouchableOpacity
|
|
656
|
+
activeOpacity={onPress ? 0.5 : 1}
|
|
657
|
+
onPress={this.onPress}>
|
|
487
658
|
{inner}
|
|
488
659
|
</TouchableOpacity>
|
|
489
660
|
);
|
|
@@ -495,23 +666,34 @@ export default class Avatar extends Component {
|
|
|
495
666
|
Avatar.propTypes = {
|
|
496
667
|
name: PropTypes.string,
|
|
497
668
|
resizeMode: PropTypes.string,
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
})
|
|
502
|
-
|
|
669
|
+
quality: PropTypes.oneOf(['low', 'medium', 'high']),
|
|
670
|
+
size: PropTypes.any,
|
|
671
|
+
source: PropTypes.oneOfType([
|
|
672
|
+
PropTypes.shape({ uri: PropTypes.string }),
|
|
673
|
+
PropTypes.number,
|
|
674
|
+
PropTypes.string,
|
|
675
|
+
]),
|
|
503
676
|
subIcon: PropTypes.oneOf(['momo', 'online', 'key', 'none']),
|
|
504
|
-
subIconSource: PropTypes.oneOfType([
|
|
677
|
+
subIconSource: PropTypes.oneOfType([
|
|
678
|
+
PropTypes.shape({ uri: PropTypes.string }),
|
|
679
|
+
PropTypes.number,
|
|
680
|
+
PropTypes.string,
|
|
681
|
+
]),
|
|
505
682
|
style: PropTypes.oneOfType([PropTypes.array, PropTypes.object]),
|
|
506
683
|
onPress: PropTypes.func,
|
|
507
684
|
loading: PropTypes.bool,
|
|
508
685
|
cached: PropTypes.bool,
|
|
509
686
|
scaleSize: PropTypes.bool,
|
|
510
|
-
extraPropsImage: PropTypes.object
|
|
687
|
+
extraPropsImage: PropTypes.object,
|
|
688
|
+
number: PropTypes.string,
|
|
689
|
+
custom: PropTypes.bool,
|
|
511
690
|
};
|
|
512
691
|
|
|
513
692
|
Avatar.defaultProps = {
|
|
514
693
|
resizeMode: 'cover',
|
|
515
694
|
cached: true,
|
|
516
|
-
scaleSize: false
|
|
695
|
+
scaleSize: false,
|
|
696
|
+
quality: 'medium',
|
|
697
|
+
size: 'small',
|
|
698
|
+
custom: false,
|
|
517
699
|
};
|
package/Avatar.web.js
CHANGED
|
@@ -11,6 +11,35 @@ import { Icons as IconSource } from '../../core/icons';
|
|
|
11
11
|
import Text from '../../core/components/typography';
|
|
12
12
|
import { RFValueHorizontal as ScaleSize } from '../../core/components/typography/reponsiveSize';
|
|
13
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
|
+
];
|
|
42
|
+
|
|
14
43
|
export const AvatarSize = {
|
|
15
44
|
tiny: 'tiny',
|
|
16
45
|
small: 'small',
|
|
@@ -287,6 +316,7 @@ const shortName = (width) => ({
|
|
|
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,
|
|
@@ -301,7 +331,9 @@ export default class Avatar extends Component {
|
|
|
301
331
|
this.subscription = Dimensions.addEventListener(
|
|
302
332
|
'change',
|
|
303
333
|
({ window }) => {
|
|
304
|
-
|
|
334
|
+
if(window?.height > 0 && window?.width > 0) {
|
|
335
|
+
this.setState({ dimensions: window });
|
|
336
|
+
}
|
|
305
337
|
}
|
|
306
338
|
);
|
|
307
339
|
}
|
|
@@ -356,10 +388,24 @@ export default class Avatar extends Component {
|
|
|
356
388
|
}
|
|
357
389
|
|
|
358
390
|
isValidImageUrl = (source) => {
|
|
359
|
-
const validSource = source &&
|
|
391
|
+
const validSource = source && source.uri && this.isUrl(source.uri);
|
|
360
392
|
return validSource;
|
|
361
393
|
}
|
|
362
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
|
+
|
|
363
409
|
mapStyleFromSize = (size) => {
|
|
364
410
|
const { dimensions } = this.state;
|
|
365
411
|
const avatarStyle = avatarSize(dimensions?.width || null).small;
|
|
@@ -418,6 +464,16 @@ export default class Avatar extends Component {
|
|
|
418
464
|
};
|
|
419
465
|
}
|
|
420
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
|
+
|
|
421
477
|
onLoadSourceError = () => {
|
|
422
478
|
this.setState({ hideSource: true, ownUpdate: true });
|
|
423
479
|
}
|
|
@@ -458,13 +514,24 @@ export default class Avatar extends Component {
|
|
|
458
514
|
|
|
459
515
|
render() {
|
|
460
516
|
const {
|
|
461
|
-
size, source, name, resizeMode, style, onPress, isShowLoading, loading, cached, extraPropsImage
|
|
517
|
+
size, source, name, resizeMode, style, onPress, isShowLoading, loading, cached, extraPropsImage, quality
|
|
462
518
|
} = this.props;
|
|
463
519
|
const { hideSource } = this.state;
|
|
464
520
|
const avatarStyle = this.mapStyleFromSize(size);
|
|
465
521
|
const containerSize = this.extractSize(avatarStyle);
|
|
466
522
|
const imageSource = ValueUtil.getImageSource(source);
|
|
467
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
|
+
|
|
468
535
|
const inner = (
|
|
469
536
|
<View style={[styles.container, containerSize, style]}>
|
|
470
537
|
{(showName || hideSource) ? this.renderShortName(name, avatarStyle, size) : <View />}
|
|
@@ -497,6 +564,7 @@ export default class Avatar extends Component {
|
|
|
497
564
|
Avatar.propTypes = {
|
|
498
565
|
name: PropTypes.string,
|
|
499
566
|
resizeMode: PropTypes.string,
|
|
567
|
+
quality: PropTypes.oneOf(['low', 'medium', 'high']),
|
|
500
568
|
size: PropTypes.oneOf(['tiny', 'small', 'medium', 'large', 'giant', 'size8', 'size24', 'size36', 'size44', 'size48', 'size52', 'size56', 'size64', 'size72', 'size80', 'size88', 'size96',
|
|
501
569
|
PropTypes.shape({
|
|
502
570
|
width: PropTypes.number, height: PropTypes.number, borderRadius: PropTypes.number
|
|
@@ -515,5 +583,6 @@ Avatar.propTypes = {
|
|
|
515
583
|
Avatar.defaultProps = {
|
|
516
584
|
resizeMode: 'cover',
|
|
517
585
|
cached: true,
|
|
518
|
-
scaleSize: false
|
|
586
|
+
scaleSize: false,
|
|
587
|
+
quality: 'medium',
|
|
519
588
|
};
|
package/package.json
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
2
|
+
"name": "@momo-kits/avatar",
|
|
3
|
+
"version": "0.0.61-beta.3",
|
|
4
|
+
"private": false,
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"dependencies": {},
|
|
7
|
+
"peerDependencies": {
|
|
8
|
+
"react-native": ">=0.55",
|
|
9
|
+
"prop-types": "^15.7.2",
|
|
10
|
+
"react": "16.9.0",
|
|
11
|
+
"@momo-kits/core": ">=0.0.5-beta",
|
|
12
|
+
"lodash": "^4.17.15"
|
|
13
|
+
},
|
|
14
|
+
"devDependencies": {},
|
|
15
|
+
"license": "MoMo"
|
|
16
16
|
}
|
package/publish.sh
CHANGED
|
@@ -21,9 +21,9 @@ rsync -r --verbose --exclude '*.mdx' --exclude '*Demo.js' --exclude 'props-type
|
|
|
21
21
|
#npm login
|
|
22
22
|
#publish dist to npm
|
|
23
23
|
cd dist
|
|
24
|
-
npm publish --access=public
|
|
24
|
+
npm publish --tag beta --access=public
|
|
25
25
|
cd ..
|
|
26
26
|
rm -rf dist
|
|
27
27
|
|
|
28
28
|
|
|
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"}'
|
|
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"}'
|