@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.
Files changed (3) hide show
  1. package/Avatar.js +67 -66
  2. package/Avatar.web.js +308 -483
  3. 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
- export const AvatarQuality = {
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: 16,
122
- height: 16,
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(8),
142
+ fontSize: ScaleSize(10),
158
143
  lineHeight: 16,
159
144
  };
160
145
  case 'small':
161
146
  return {
162
- fontSize: ScaleSize(14),
163
- lineHeight: 20,
147
+ fontSize: ScaleSize(15),
148
+ lineHeight: 22,
164
149
  };
165
150
  case 'medium':
166
151
  return {
167
- fontSize: ScaleSize(18),
152
+ fontSize: ScaleSize(15),
168
153
  lineHeight: 22,
169
154
  };
170
155
  case 'large':
171
156
  return {
172
- fontSize: ScaleSize(25),
157
+ fontSize: ScaleSize(15),
158
+ lineHeight: 22,
173
159
  };
174
160
  case 'giant':
175
161
  return {
176
- fontSize: ScaleSize(32),
162
+ fontSize: ScaleSize(15),
163
+ lineHeight: 22,
177
164
  };
178
165
  default:
179
166
  return {
180
- fontSize: ScaleSize(18),
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 = ValueUtil.getImageSource(source);
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
- const validSource = source && source.uri && isUrl(source.uri);
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 = (imageSource) => {
247
- if (this.imageSource?.uri !== imageSource?.uri) {
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 style={styles.subIcon}>
258
- <Image
259
- source={subIcon}
260
- style={[
261
- {
262
- width: iconWidth,
263
- height: iconHeight,
264
- borderRadius: iconRadius,
265
- bottom: iconWidth / 2 - 2,
266
- right: iconWidth / 2 - 2,
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 style={styles.topIcon}>
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
- style={{ fontSize, lineHeight, color: Colors.pink_03 }}>
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={!!onPress ? 0.5 : 1}
358
- style={[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
- subIconSource: PropTypes.oneOfType([
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, StyleSheet, TouchableOpacity, Image, Dimensions
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
- export const AvatarQuality = {
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
- backgroundColor: Colors.very_light_pink_four,
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: '#f6f6f6'
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 avatarSize = (width) => ({
211
- tiny: {
212
- width: 16,
213
- height: 16,
214
- borderRadius: 8
215
- },
216
- small: {
217
- width: 32,
218
- height: 32,
219
- borderRadius: 16
220
- },
221
- medium: {
222
- width: 40,
223
- height: 40,
224
- borderRadius: 20
225
- },
226
- large: {
227
- width: 60,
228
- height: 60,
229
- borderRadius: 30
230
- },
231
- giant: {
232
- width: 120,
233
- height: 120,
234
- borderRadius: 60
235
- },
236
- size8: {
237
- width: 8,
238
- height: 8,
239
- borderRadius: 4
240
- },
241
- size24: {
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
- componentWillUnmount() {
343
- const { scaleSize } = this.props;
344
- if (scaleSize) {
345
- this.subscription?.remove?.();
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
- static getDerivedStateFromProps(nextProps, prevState) {
350
- if (prevState.ownUpdate) {
143
+ const shortName = (size) => {
144
+ switch (size) {
145
+ case 'tiny':
351
146
  return {
352
- ownUpdate: false,
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
- getContactShortName = (name) => {
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
- renderShortName = (name, avatarStyle, size) => {
373
- if (name) {
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
- const validSource = source && source.uri && this.isUrl(source.uri);
392
- return validSource;
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
- onLoadSourceError = () => {
478
- this.setState({ hideSource: true, ownUpdate: true });
479
- }
480
-
481
- renderSubIcon = () => {
482
- const { subIcon, size, subIconSource } = this.props;
483
- if ((!subIcon || subIcon === SubIconType.none) && !subIconSource) return <View />;
484
- const subIconSizeStyle = this.mapSubIconSize(size);
485
- const iconSource = ValueUtil.getImageSource(subIconSource);
486
- return (
487
- <View style={styles.subIcon}>
488
- {subIcon === SubIconType.momo
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
- style={[styles.subIconImage, subIconSizeStyle]}
492
- source={IconSource.ic_round_momo_tiny}
260
+ source={subIcon}
261
+ style={[
262
+ {
263
+ width: iconWidth,
264
+ height: iconHeight,
265
+ borderRadius: iconRadius,
266
+ },
267
+ ]}
493
268
  />
494
- )
495
- : <View />}
496
- {subIcon === SubIconType.online
497
- ? <View style={[styles.subIconImageOnline, subIconSizeStyle]} /> : <View />}
269
+ ) : (
270
+ subIcon()
271
+ )}
272
+ </View>
273
+ );
274
+ }
275
+ };
498
276
 
499
- {iconSource && subIconSource && !subIcon ? (
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
- style={[styles.subIconImage, subIconSizeStyle]}
502
- source={iconSource}
293
+ source={topIcon}
294
+ style={[
295
+ {
296
+ width: iconWidth,
297
+ height: iconHeight,
298
+ borderRadius: iconRadius,
299
+ },
300
+ ]}
503
301
  />
504
- )
505
- : <View />}
506
- </View>
507
- );
508
- }
302
+ </View>
303
+ );
304
+ }
305
+ };
509
306
 
510
- onPress = () => {
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
- const inner = (
536
- <View style={[styles.container, containerSize, style]}>
537
- {(showName || hideSource) ? this.renderShortName(name, avatarStyle, size) : <View />}
538
- {this.isValidImageUrl(imageSource) && !hideSource
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
- <TouchableOpacity activeOpacity={onPress ? 0.5 : 1} onPress={this.onPress}>
556
- {inner}
557
- </TouchableOpacity>
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 inner;
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', '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
- })]),
572
- source: PropTypes.oneOfType([PropTypes.shape({ uri: PropTypes.string }), PropTypes.number, PropTypes.string]),
573
- subIcon: PropTypes.oneOf(['momo', 'online', 'key', 'none']),
574
- subIconSource: PropTypes.oneOfType([PropTypes.shape({ uri: PropTypes.string }), PropTypes.number, PropTypes.string]),
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
- cached: PropTypes.bool,
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
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@momo-kits/avatar",
3
- "version": "0.0.61-alpha.10",
3
+ "version": "0.0.61-alpha.12",
4
4
  "private": false,
5
5
  "main": "index.js",
6
6
  "dependencies": {},