@momo-kits/avatar 0.0.1-beta → 0.0.1

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 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
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',
@@ -76,7 +82,7 @@ const styles = StyleSheet.create({
76
82
  }
77
83
  });
78
84
 
79
- const subIconSize = StyleSheet.create({
85
+ const subIconSize = (width) => ({
80
86
  tiny: {
81
87
  width: 8,
82
88
  height: 8,
@@ -176,7 +182,7 @@ const subIconSize = StyleSheet.create({
176
182
  }
177
183
  });
178
184
 
179
- const avatarSize = StyleSheet.create({
185
+ const avatarSize = (width) => ({
180
186
  tiny: {
181
187
  width: 16,
182
188
  height: 16,
@@ -264,21 +270,21 @@ const avatarSize = StyleSheet.create({
264
270
  }
265
271
  });
266
272
 
267
- const shortName = StyleSheet.create({
273
+ const shortName = (width) => ({
268
274
  tiny: {
269
- fontSize: 5
275
+ fontSize: ScaleSize(5, width)
270
276
  },
271
277
  small: {
272
- fontSize: 11
278
+ fontSize: ScaleSize(11, width)
273
279
  },
274
280
  medium: {
275
- fontSize: 15
281
+ fontSize: ScaleSize(15, width)
276
282
  },
277
283
  large: {
278
- fontSize: 20
284
+ fontSize: ScaleSize(20, width)
279
285
  },
280
286
  giant: {
281
- fontSize: 25
287
+ fontSize: ScaleSize(25, width)
282
288
  }
283
289
  });
284
290
 
@@ -288,8 +294,29 @@ export default class Avatar extends Component {
288
294
  this.state = {
289
295
  hideSource: false,
290
296
  ownUpdate: false,
291
- source: props.source
297
+ source: props.source,
298
+ dimensions: {}
292
299
  };
300
+ this.imageSource = '';
301
+ }
302
+
303
+ componentDidMount() {
304
+ const { scaleSize } = this.props;
305
+ if (scaleSize) {
306
+ this.subscription = Dimensions.addEventListener(
307
+ 'change',
308
+ ({ window }) => {
309
+ this.setState({ dimensions: window });
310
+ }
311
+ );
312
+ }
313
+ }
314
+
315
+ componentWillUnmount() {
316
+ const { scaleSize } = this.props;
317
+ if (scaleSize) {
318
+ this.subscription?.remove?.();
319
+ }
293
320
  }
294
321
 
295
322
  static getDerivedStateFromProps(nextProps, prevState) {
@@ -334,49 +361,66 @@ export default class Avatar extends Component {
334
361
  }
335
362
 
336
363
  isValidImageUrl = (source) => {
337
- const validSource = source && (((source.uri && this.isUrl(source.uri)) || (typeof source === 'number')));
364
+ const validSource = source && source.uri && this.isUrl(source.uri);
338
365
  return validSource;
339
366
  }
340
367
 
368
+ mapAvatarQuality = (url, quality) => {
369
+ if (!quality || quality === AvatarQuality.medium) {
370
+ return url;
371
+ }
372
+ if (quality === AvatarQuality.low) {
373
+ return url.replace('.png', '_s64.png');
374
+ }
375
+ if (quality === AvatarQuality.high) {
376
+ return url.replace('.png', '_s512.png');
377
+ }
378
+
379
+ return url;
380
+ }
381
+
341
382
  mapStyleFromSize = (size) => {
342
- const avatarStyle = avatarSize.small;
383
+ const { dimensions } = this.state;
384
+ const avatarStyle = avatarSize(dimensions?.width || null).small;
343
385
  if (typeof size === 'object') return size;
344
- if (avatarSize[size]) return avatarSize[size];
386
+ if (avatarSize(dimensions?.width || null)[size]) return avatarSize(dimensions?.width || null)[size];
345
387
  return avatarStyle;
346
388
  }
347
389
 
348
390
  mapShortNameStyle = (size) => {
349
391
  let shortNameStyle = {};
392
+ const { dimensions } = this.state;
350
393
  switch (size) {
351
394
  case AvatarSize.tiny: {
352
- shortNameStyle = shortName.tiny;
395
+ shortNameStyle = shortName(dimensions?.width || null).tiny;
353
396
  break;
354
397
  }
355
398
  case AvatarSize.small: {
356
- shortNameStyle = shortName.small;
399
+ shortNameStyle = shortName(dimensions?.width || null).small;
357
400
  break;
358
401
  }
359
402
  case AvatarSize.medium: {
360
- shortNameStyle = shortName.medium;
403
+ shortNameStyle = shortName(dimensions?.width || null).medium;
361
404
  break;
362
405
  }
363
406
  case AvatarSize.large: {
364
- shortNameStyle = shortName.large;
407
+ shortNameStyle = shortName(dimensions?.width || null).large;
365
408
  break;
366
409
  }
367
410
  case AvatarSize.giant: {
368
- shortNameStyle = shortName.giant;
411
+ shortNameStyle = shortName(dimensions?.width || null).giant;
369
412
  break;
370
413
  }
371
414
  default:
372
- shortNameStyle = shortName.small;
415
+ shortNameStyle = shortName(dimensions?.width || null).small;
373
416
  }
374
417
  return shortNameStyle;
375
418
  }
376
419
 
377
420
  mapSubIconSize = (size) => {
378
- const subIconStyle = subIconSize.small;
379
- if (subIconSize[size]) return subIconSize[size];
421
+ const { dimensions } = this.state;
422
+ const subIconStyle = subIconSize(dimensions?.width || null).small;
423
+ if (subIconSize(dimensions?.width || null)[size]) return subIconSize(dimensions?.width || null)[size];
380
424
  return subIconStyle;
381
425
  }
382
426
 
@@ -393,8 +437,11 @@ export default class Avatar extends Component {
393
437
  };
394
438
  }
395
439
 
396
- onLoadSourceError = () => {
397
- this.setState({ hideSource: true, ownUpdate: true });
440
+ onLoadSourceError = (imageSource) => {
441
+ if(this.imageSource?.uri !== imageSource?.uri){
442
+ this.imageSource = imageSource;
443
+ this.setState({ hideSource: true, ownUpdate: true });
444
+ }
398
445
  }
399
446
 
400
447
  renderSubIcon = () => {
@@ -433,13 +480,24 @@ export default class Avatar extends Component {
433
480
 
434
481
  render() {
435
482
  const {
436
- size, source, name, resizeMode, style, onPress, isShowLoading, loading, cached, extraPropsImage
483
+ size, source, name, resizeMode, style, onPress, isShowLoading, loading, cached, extraPropsImage, quality
437
484
  } = this.props;
438
485
  const { hideSource } = this.state;
439
486
  const avatarStyle = this.mapStyleFromSize(size);
440
487
  const containerSize = this.extractSize(avatarStyle);
441
488
  const imageSource = ValueUtil.getImageSource(source);
442
489
  const showName = typeof imageSource === 'object' && Object.keys(imageSource).length === 0 && typeof imageSource !== 'number';
490
+ // add priority high for avatar
491
+ if (imageSource?.uri) {
492
+ imageSource.priority = 'high';
493
+ imageSource.uri = this.mapAvatarQuality(imageSource.uri, quality);
494
+ // if doest not have time query, set default cache time to 1 day
495
+ if (!imageSource.uri?.includes('?') && cached) {
496
+ const midnight = new Date().setHours(0, 0, 0, 0);
497
+ imageSource.uri = `${imageSource.uri}?time=${midnight}`;
498
+ }
499
+ }
500
+
443
501
  const inner = (
444
502
  <View style={[styles.container, containerSize, style]}>
445
503
  {(showName || hideSource) ? this.renderShortName(name, avatarStyle, size) : <View />}
@@ -449,7 +507,7 @@ export default class Avatar extends Component {
449
507
  cached={cached}
450
508
  loading={loading || isShowLoading}
451
509
  source={imageSource}
452
- onError={this.onLoadSourceError}
510
+ onError={() => this.onLoadSourceError(imageSource)}
453
511
  style={avatarStyle}
454
512
  resizeMode={resizeMode}
455
513
  {...extraPropsImage}
@@ -472,6 +530,7 @@ export default class Avatar extends Component {
472
530
  Avatar.propTypes = {
473
531
  name: PropTypes.string,
474
532
  resizeMode: PropTypes.string,
533
+ quality: PropTypes.oneOf(['low', 'medium', 'high']),
475
534
  size: PropTypes.oneOf(['tiny', 'small', 'medium', 'large', 'giant', 'size8', 'size24', 'size36', 'size44', 'size48', 'size52', 'size56', 'size64', 'size72', 'size80', 'size88', 'size96',
476
535
  PropTypes.shape({
477
536
  width: PropTypes.number, height: PropTypes.number, borderRadius: PropTypes.number
@@ -483,10 +542,13 @@ Avatar.propTypes = {
483
542
  onPress: PropTypes.func,
484
543
  loading: PropTypes.bool,
485
544
  cached: PropTypes.bool,
545
+ scaleSize: PropTypes.bool,
486
546
  extraPropsImage: PropTypes.object
487
547
  };
488
548
 
489
549
  Avatar.defaultProps = {
490
550
  resizeMode: 'cover',
491
- cached: true
551
+ cached: true,
552
+ scaleSize: false,
553
+ quality: 'medium',
492
554
  };
package/Avatar.web.js CHANGED
@@ -2,14 +2,20 @@
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 ValueUtils from '../../utils/ValueUtil';
9
- import Colors from '../../colors';
10
- import { Icons } from '../../icons';
11
- import Text from '../typography';
12
- import { ColorCore } from '../../colors/colorCore';
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
+ };
13
19
 
14
20
  export const AvatarSize = {
15
21
  tiny: 'tiny',
@@ -78,7 +84,7 @@ const styles = StyleSheet.create({
78
84
  }
79
85
  });
80
86
 
81
- const subIconSize = StyleSheet.create({
87
+ const subIconSize = (width) => ({
82
88
  tiny: {
83
89
  width: 8,
84
90
  height: 8,
@@ -178,7 +184,7 @@ const subIconSize = StyleSheet.create({
178
184
  }
179
185
  });
180
186
 
181
- const avatarSize = StyleSheet.create({
187
+ const avatarSize = (width) => ({
182
188
  tiny: {
183
189
  width: 16,
184
190
  height: 16,
@@ -266,21 +272,21 @@ const avatarSize = StyleSheet.create({
266
272
  }
267
273
  });
268
274
 
269
- const shortName = StyleSheet.create({
275
+ const shortName = (width) => ({
270
276
  tiny: {
271
- fontSize: 5
277
+ fontSize: ScaleSize(5, width)
272
278
  },
273
279
  small: {
274
- fontSize: 11
280
+ fontSize: ScaleSize(11, width)
275
281
  },
276
282
  medium: {
277
- fontSize: 15
283
+ fontSize: ScaleSize(15, width)
278
284
  },
279
285
  large: {
280
- fontSize: 20
286
+ fontSize: ScaleSize(20, width)
281
287
  },
282
288
  giant: {
283
- fontSize: 25
289
+ fontSize: ScaleSize(25, width)
284
290
  }
285
291
  });
286
292
 
@@ -290,10 +296,30 @@ export default class Avatar extends Component {
290
296
  this.state = {
291
297
  hideSource: false,
292
298
  ownUpdate: false,
293
- source: props.source
299
+ source: props.source,
300
+ dimensions: {}
294
301
  };
295
302
  }
296
303
 
304
+ componentDidMount() {
305
+ const { scaleSize } = this.props;
306
+ if (scaleSize) {
307
+ this.subscription = Dimensions.addEventListener(
308
+ 'change',
309
+ ({ window }) => {
310
+ this.setState({ dimensions: window });
311
+ }
312
+ );
313
+ }
314
+ }
315
+
316
+ componentWillUnmount() {
317
+ const { scaleSize } = this.props;
318
+ if (scaleSize) {
319
+ this.subscription?.remove?.();
320
+ }
321
+ }
322
+
297
323
  static getDerivedStateFromProps(nextProps, prevState) {
298
324
  if (prevState.ownUpdate) {
299
325
  return {
@@ -336,49 +362,66 @@ export default class Avatar extends Component {
336
362
  }
337
363
 
338
364
  isValidImageUrl = (source) => {
339
- const validSource = source && (((source.uri && this.isUrl(source.uri)) || (typeof source === 'number')));
365
+ const validSource = source && source.uri && this.isUrl(source.uri);
340
366
  return validSource;
341
367
  }
342
368
 
369
+ mapAvatarQuality = (url, quality) => {
370
+ if (!quality || quality === AvatarQuality.medium) {
371
+ return url;
372
+ }
373
+ if (quality === AvatarQuality.low) {
374
+ return url.replace('.png', '_s64.png');
375
+ }
376
+ if (quality === AvatarQuality.high) {
377
+ return url.replace('.png', '_s512.png');
378
+ }
379
+
380
+ return url;
381
+ }
382
+
343
383
  mapStyleFromSize = (size) => {
344
- const avatarStyle = avatarSize.small;
384
+ const { dimensions } = this.state;
385
+ const avatarStyle = avatarSize(dimensions?.width || null).small;
345
386
  if (typeof size === 'object') return size;
346
- if (avatarSize[size]) return avatarSize[size];
387
+ if (avatarSize(dimensions?.width || null)[size]) return avatarSize(dimensions?.width || null)[size];
347
388
  return avatarStyle;
348
389
  }
349
390
 
350
391
  mapShortNameStyle = (size) => {
351
392
  let shortNameStyle = {};
393
+ const { dimensions } = this.state;
352
394
  switch (size) {
353
395
  case AvatarSize.tiny: {
354
- shortNameStyle = shortName.tiny;
396
+ shortNameStyle = shortName(dimensions?.width || null).tiny;
355
397
  break;
356
398
  }
357
399
  case AvatarSize.small: {
358
- shortNameStyle = shortName.small;
400
+ shortNameStyle = shortName(dimensions?.width || null).small;
359
401
  break;
360
402
  }
361
403
  case AvatarSize.medium: {
362
- shortNameStyle = shortName.medium;
404
+ shortNameStyle = shortName(dimensions?.width || null).medium;
363
405
  break;
364
406
  }
365
407
  case AvatarSize.large: {
366
- shortNameStyle = shortName.large;
408
+ shortNameStyle = shortName(dimensions?.width || null).large;
367
409
  break;
368
410
  }
369
411
  case AvatarSize.giant: {
370
- shortNameStyle = shortName.giant;
412
+ shortNameStyle = shortName(dimensions?.width || null).giant;
371
413
  break;
372
414
  }
373
415
  default:
374
- shortNameStyle = shortName.small;
416
+ shortNameStyle = shortName(dimensions?.width || null).small;
375
417
  }
376
418
  return shortNameStyle;
377
419
  }
378
420
 
379
421
  mapSubIconSize = (size) => {
380
- const subIconStyle = subIconSize.small;
381
- if (subIconSize[size]) return subIconSize[size];
422
+ const { dimensions } = this.state;
423
+ const subIconStyle = subIconSize(dimensions?.width || null).small;
424
+ if (subIconSize(dimensions?.width || null)[size]) return subIconSize(dimensions?.width || null)[size];
382
425
  return subIconStyle;
383
426
  }
384
427
 
@@ -391,7 +434,7 @@ export default class Avatar extends Component {
391
434
  height: containerWidth,
392
435
  borderRadius: containerWidth / 2,
393
436
  borderWidth,
394
- borderColor: ColorCore.black_01
437
+ borderColor: Colors.black_01
395
438
  };
396
439
  }
397
440
 
@@ -403,14 +446,14 @@ export default class Avatar extends Component {
403
446
  const { subIcon, size, subIconSource } = this.props;
404
447
  if ((!subIcon || subIcon === SubIconType.none) && !subIconSource) return <View />;
405
448
  const subIconSizeStyle = this.mapSubIconSize(size);
406
- const iconSource = ValueUtils.getImageSource(subIconSource);
449
+ const iconSource = ValueUtil.getImageSource(subIconSource);
407
450
  return (
408
451
  <View style={styles.subIcon}>
409
452
  {subIcon === SubIconType.momo
410
453
  ? (
411
454
  <Image
412
455
  style={[styles.subIconImage, subIconSizeStyle]}
413
- source={Icons.ic_round_momo_tiny}
456
+ source={IconSource.ic_round_momo_tiny}
414
457
  />
415
458
  )
416
459
  : <View />}
@@ -435,16 +478,27 @@ export default class Avatar extends Component {
435
478
 
436
479
  render() {
437
480
  const {
438
- size, source, name, resizeMode, style, onPress, isShowLoading, loading, cached, extraPropsImage
481
+ size, source, name, resizeMode, style, onPress, isShowLoading, loading, cached, extraPropsImage, quality
439
482
  } = this.props;
440
483
  const { hideSource } = this.state;
441
484
  const avatarStyle = this.mapStyleFromSize(size);
442
485
  const containerSize = this.extractSize(avatarStyle);
443
- const imageSource = ValueUtils.getImageSource(source);
486
+ const imageSource = ValueUtil.getImageSource(source);
444
487
  const showName = typeof imageSource === 'object' && Object.keys(imageSource).length === 0 && typeof imageSource !== 'number';
488
+ // add priority high for avatar
489
+ if (imageSource?.uri) {
490
+ imageSource.priority = 'high';
491
+ imageSource.uri = this.mapAvatarQuality(imageSource.uri, quality);
492
+ // if doest not have time query, set default cache time to 1 day
493
+ if (!imageSource.uri?.includes('?') && cached) {
494
+ const midnight = new Date().setHours(0, 0, 0, 0);
495
+ imageSource.uri = `${imageSource.uri}?time=${midnight}`;
496
+ }
497
+ }
498
+
445
499
  const inner = (
446
- <View style={[styles.container, avatarStyle, style]}>
447
- {(showName || hideSource) ? this.renderShortName(name, avatarStyle, size) : null}
500
+ <View style={[styles.container, containerSize, style]}>
501
+ {(showName || hideSource) ? this.renderShortName(name, avatarStyle, size) : <View />}
448
502
  {this.isValidImageUrl(imageSource) && !hideSource
449
503
  ? (
450
504
  <Image
@@ -472,54 +526,27 @@ export default class Avatar extends Component {
472
526
  }
473
527
 
474
528
  Avatar.propTypes = {
475
- /**
476
- * The default name when image load fail.
477
- */
478
529
  name: PropTypes.string,
479
- /**
480
- * How resize should the avatar be?
481
- */
482
530
  resizeMode: PropTypes.string,
483
- /**
484
- * How large should the avatar be?
485
- */
486
- size: PropTypes.oneOf(['tiny', 'small', 'medium', 'large', 'giant', 'size8', 'size24', 'size36', 'size44', 'size48', 'size52', 'size56', 'size64', 'size72', 'size80', 'size88', 'size96']),
487
- /**
488
- * What source Avatar to use?
489
- */
531
+ quality: PropTypes.oneOf(['low', 'medium', 'high']),
532
+ size: PropTypes.oneOf(['tiny', 'small', 'medium', 'large', 'giant', 'size8', 'size24', 'size36', 'size44', 'size48', 'size52', 'size56', 'size64', 'size72', 'size80', 'size88', 'size96',
533
+ PropTypes.shape({
534
+ width: PropTypes.number, height: PropTypes.number, borderRadius: PropTypes.number
535
+ })]),
490
536
  source: PropTypes.oneOfType([PropTypes.shape({ uri: PropTypes.string }), PropTypes.number, PropTypes.string]),
491
- /**
492
- * What subIcon Avatar to use?
493
- */
494
537
  subIcon: PropTypes.oneOf(['momo', 'online', 'key', 'none']),
495
- /**
496
- * What custom subIcon Avatar to use?
497
- */
498
538
  subIconSource: PropTypes.oneOfType([PropTypes.shape({ uri: PropTypes.string }), PropTypes.number, PropTypes.string]),
499
- /**
500
- * What custom style Avatar to use?
501
- */
502
539
  style: PropTypes.oneOfType([PropTypes.array, PropTypes.object]),
503
- /**
504
- * Optional click handler.
505
- */
506
540
  onPress: PropTypes.func,
507
- /**
508
- * Optional loading handler.
509
- */
510
541
  loading: PropTypes.bool,
511
- /**
512
- * Optional cached handler.
513
- */
514
542
  cached: PropTypes.bool,
515
- /**
516
- * Optional extra prop of Image.
517
- */
543
+ scaleSize: PropTypes.bool,
518
544
  extraPropsImage: PropTypes.object
519
545
  };
520
546
 
521
547
  Avatar.defaultProps = {
522
548
  resizeMode: 'cover',
523
- size: 'medium',
524
- cached: true
549
+ cached: true,
550
+ scaleSize: false,
551
+ quality: 'medium',
525
552
  };
package/package.json CHANGED
@@ -1,17 +1,16 @@
1
1
  {
2
- "name": "@momo-kits/avatar",
3
- "version": "0.0.1-beta",
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
- "lodash": "^4.17.15",
12
- "@momo-kits/core": ">=0.0.5-beta"
13
- },
14
- "devDependencies": {},
15
- "license": "MoMo"
16
- }
17
-
2
+ "name": "@momo-kits/avatar",
3
+ "version": "0.0.1",
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
+ }
package/publish.sh CHANGED
@@ -12,7 +12,7 @@ echo VERSION: $VERSION
12
12
  rsync -r --verbose --exclude '*.mdx' --exclude '*Demo.js' --exclude 'props-type.js' --exclude 'prop-types.js' --exclude 'web.js' ./* dist
13
13
 
14
14
  # #babel component to dist
15
- babel ./dist -d dist --copy-files
15
+ #babel ./dist -d dist --copy-files
16
16
 
17
17
  #copy option
18
18
  #cp -r ./src/ dist