@momo-kits/avatar 0.0.34-beta → 0.0.34

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
@@ -1 +1,607 @@
1
- var _interopRequireDefault=require("@babel/runtime/helpers/interopRequireDefault");Object.defineProperty(exports,"__esModule",{value:true});exports.default=exports.SubIconType=exports.AvatarSize=void 0;var _extends2=_interopRequireDefault(require("@babel/runtime/helpers/extends"));var _classCallCheck2=_interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));var _createClass2=_interopRequireDefault(require("@babel/runtime/helpers/createClass"));var _inherits2=_interopRequireDefault(require("@babel/runtime/helpers/inherits"));var _possibleConstructorReturn2=_interopRequireDefault(require("@babel/runtime/helpers/possibleConstructorReturn"));var _getPrototypeOf2=_interopRequireDefault(require("@babel/runtime/helpers/getPrototypeOf"));var _propTypes=_interopRequireDefault(require("prop-types"));var _react=_interopRequireWildcard(require("react"));var _reactNative=require("react-native");var _lodash=require("lodash");var _core=require("@momo-kits/core");var _jsxFileName="/Users/trinh.ho2/momo-folk/kits/src/libs/avatar/dist/Avatar.js";function _getRequireWildcardCache(nodeInterop){if(typeof WeakMap!=="function")return null;var cacheBabelInterop=new WeakMap();var cacheNodeInterop=new WeakMap();return(_getRequireWildcardCache=function _getRequireWildcardCache(nodeInterop){return nodeInterop?cacheNodeInterop:cacheBabelInterop;})(nodeInterop);}function _interopRequireWildcard(obj,nodeInterop){if(!nodeInterop&&obj&&obj.__esModule){return obj;}if(obj===null||typeof obj!=="object"&&typeof obj!=="function"){return{default:obj};}var cache=_getRequireWildcardCache(nodeInterop);if(cache&&cache.has(obj)){return cache.get(obj);}var newObj={};var hasPropertyDescriptor=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var key in obj){if(key!=="default"&&Object.prototype.hasOwnProperty.call(obj,key)){var desc=hasPropertyDescriptor?Object.getOwnPropertyDescriptor(obj,key):null;if(desc&&(desc.get||desc.set)){Object.defineProperty(newObj,key,desc);}else{newObj[key]=obj[key];}}}newObj.default=obj;if(cache){cache.set(obj,newObj);}return newObj;}function _createSuper(Derived){var hasNativeReflectConstruct=_isNativeReflectConstruct();return function _createSuperInternal(){var Super=(0,_getPrototypeOf2.default)(Derived),result;if(hasNativeReflectConstruct){var NewTarget=(0,_getPrototypeOf2.default)(this).constructor;result=Reflect.construct(Super,arguments,NewTarget);}else{result=Super.apply(this,arguments);}return(0,_possibleConstructorReturn2.default)(this,result);};}function _isNativeReflectConstruct(){if(typeof Reflect==="undefined"||!Reflect.construct)return false;if(Reflect.construct.sham)return false;if(typeof Proxy==="function")return true;try{Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){}));return true;}catch(e){return false;}}var AvatarSize={tiny:'tiny',small:'small',medium:'medium',large:'large',giant:'giant',size8:'size8',size24:'size24',size36:'size36',size44:'size44',size48:'size48',size52:'size52',size56:'size56',size64:'size64',size72:'size72',size80:'size80',size88:'size88',size96:'size96'};exports.AvatarSize=AvatarSize;var SubIconType={momo:'momo',online:'online',key:'key',none:'none'};exports.SubIconType=SubIconType;var styles=_reactNative.StyleSheet.create({container:{justifyContent:'center',alignItems:'center'},shortNameView:{justifyContent:'center',alignItems:'center',backgroundColor:_core.Colors.very_light_pink_four,width:'100%',height:'100%'},shortNameText:{color:'#f6f6f6'},absolute:{position:'absolute',top:0,left:0,right:0,bottom:0},subIcon:{position:'absolute',bottom:0,right:0},subIconImage:{width:22,height:22},subIconImageOnline:{backgroundColor:_core.Colors.kiwi_green,borderColor:'white',borderWidth:1}});var subIconSize=_reactNative.StyleSheet.create({tiny:{width:8,height:8,borderRadius:4},small:{width:10,height:10,borderRadius:5},medium:{width:12,height:12,borderRadius:6},large:{width:16,height:16,borderRadius:8},size8:{width:8,height:8,borderRadius:4},size24:{width:10,height:10,borderRadius:5},size36:{width:10,height:10,borderRadius:5},size44:{width:14,height:14,borderRadius:7},size48:{width:14,height:14,borderRadius:7},size52:{width:16,height:16,borderRadius:8},size56:{width:16,height:16,borderRadius:8},size64:{width:16,height:16,borderRadius:8,top:-2,left:-2},size72:{width:18,height:18,borderRadius:9,top:-3,left:-3},size80:{width:18,height:18,borderRadius:9,top:-3,left:-3},size88:{width:18,height:18,borderRadius:9,top:-4,left:-4},size96:{width:20,height:20,borderRadius:10,top:-4,left:-4},giant:{top:-5,left:-5,width:24,height:24,borderRadius:12}});var avatarSize=_reactNative.StyleSheet.create({tiny:{width:16,height:16,borderRadius:8},small:{width:32,height:32,borderRadius:16},medium:{width:40,height:40,borderRadius:20},large:{width:60,height:60,borderRadius:30},giant:{width:120,height:120,borderRadius:60},size8:{width:8,height:8,borderRadius:4},size24:{width:24,height:24,borderRadius:12},size36:{width:36,height:36,borderRadius:18},size44:{width:44,height:44,borderRadius:22},size48:{width:48,height:48,borderRadius:24},size52:{width:52,height:52,borderRadius:26},size56:{width:56,height:56,borderRadius:28},size64:{width:64,height:64,borderRadius:32},size72:{width:72,height:72,borderRadius:36},size80:{width:80,height:80,borderRadius:40},size88:{width:88,height:88,borderRadius:44},size96:{width:96,height:96,borderRadius:48}});var shortName=_reactNative.StyleSheet.create({tiny:{fontSize:5},small:{fontSize:11},medium:{fontSize:15},large:{fontSize:20},giant:{fontSize:25}});var Avatar=function(_Component){(0,_inherits2.default)(Avatar,_Component);var _super=_createSuper(Avatar);function Avatar(props){var _this;(0,_classCallCheck2.default)(this,Avatar);_this=_super.call(this,props);_this.getContactShortName=function(name){if(!name)return'';var shortNameList=name.split(' ',2);var alphabet=[];shortNameList.forEach(function(n){if(n&&n.length>0){alphabet.push(n[0].toString().toUpperCase());}});return alphabet.join('');};_this.renderShortName=function(name,avatarStyle,size){if(name){var shortedName=_this.getContactShortName(name);var shortNameStyle=_this.mapShortNameStyle(size);return _react.default.createElement(_reactNative.View,{style:[styles.shortNameView,avatarStyle],__source:{fileName:_jsxFileName,lineNumber:323,columnNumber:17}},_react.default.createElement(_core.Text.H4,{style:[styles.shortNameText,shortNameStyle],__source:{fileName:_jsxFileName,lineNumber:324,columnNumber:21}},shortedName));}return _react.default.createElement(_reactNative.View,{__source:{fileName:_jsxFileName,lineNumber:328,columnNumber:16}});};_this.isValidImageUrl=function(source){var validSource=source&&(source.uri&&_this.isUrl(source.uri)||typeof source==='number');return validSource;};_this.mapStyleFromSize=function(size){var avatarStyle=avatarSize.small;if(typeof size==='object')return size;if(avatarSize[size])return avatarSize[size];return avatarStyle;};_this.mapShortNameStyle=function(size){var shortNameStyle={};switch(size){case AvatarSize.tiny:{shortNameStyle=shortName.tiny;break;}case AvatarSize.small:{shortNameStyle=shortName.small;break;}case AvatarSize.medium:{shortNameStyle=shortName.medium;break;}case AvatarSize.large:{shortNameStyle=shortName.large;break;}case AvatarSize.giant:{shortNameStyle=shortName.giant;break;}default:shortNameStyle=shortName.small;}return shortNameStyle;};_this.mapSubIconSize=function(size){var subIconStyle=subIconSize.small;if(subIconSize[size])return subIconSize[size];return subIconStyle;};_this.extractSize=function(avatarStyle){var style=_this.props.style;var borderWidth=(0,_lodash.get)(style,'borderWidth',1);var containerWidth=Math.round(avatarStyle.width+2+borderWidth);return{width:containerWidth,height:containerWidth,borderRadius:containerWidth/2,borderWidth:borderWidth,borderColor:_core.Colors.black_01};};_this.onLoadSourceError=function(){_this.setState({hideSource:true,ownUpdate:true});};_this.renderSubIcon=function(){var _this$props=_this.props,subIcon=_this$props.subIcon,size=_this$props.size,subIconSource=_this$props.subIconSource;if((!subIcon||subIcon===SubIconType.none)&&!subIconSource)return _react.default.createElement(_reactNative.View,{__source:{fileName:_jsxFileName,lineNumber:402,columnNumber:82}});var subIconSizeStyle=_this.mapSubIconSize(size);var iconSource=_core.ValueUtil.getImageSource(subIconSource);return _react.default.createElement(_reactNative.View,{style:styles.subIcon,__source:{fileName:_jsxFileName,lineNumber:406,columnNumber:13}},subIcon===SubIconType.momo?_react.default.createElement(_core.Image,{style:[styles.subIconImage,subIconSizeStyle],source:_core.IconSource.ic_round_momo_tiny,__source:{fileName:_jsxFileName,lineNumber:409,columnNumber:25}}):_react.default.createElement(_reactNative.View,{__source:{fileName:_jsxFileName,lineNumber:414,columnNumber:23}}),subIcon===SubIconType.online?_react.default.createElement(_reactNative.View,{style:[styles.subIconImageOnline,subIconSizeStyle],__source:{fileName:_jsxFileName,lineNumber:416,columnNumber:23}}):_react.default.createElement(_reactNative.View,{__source:{fileName:_jsxFileName,lineNumber:416,columnNumber:88}}),iconSource&&subIconSource&&!subIcon?_react.default.createElement(_core.Image,{style:[styles.subIconImage,subIconSizeStyle],source:iconSource,__source:{fileName:_jsxFileName,lineNumber:419,columnNumber:21}}):_react.default.createElement(_reactNative.View,{__source:{fileName:_jsxFileName,lineNumber:424,columnNumber:23}}));};_this.onPress=function(){var onPress=_this.props.onPress;if(onPress&&typeof onPress==='function')onPress();};_this.state={hideSource:false,ownUpdate:false,source:props.source};return _this;}(0,_createClass2.default)(Avatar,[{key:"isUrl",value:function isUrl(url){var expression=/(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-/]))?/gi;return expression.test(url);}},{key:"render",value:function render(){var _this$props2=this.props,size=_this$props2.size,source=_this$props2.source,name=_this$props2.name,resizeMode=_this$props2.resizeMode,style=_this$props2.style,onPress=_this$props2.onPress,isShowLoading=_this$props2.isShowLoading,loading=_this$props2.loading,cached=_this$props2.cached,extraPropsImage=_this$props2.extraPropsImage;var hideSource=this.state.hideSource;var avatarStyle=this.mapStyleFromSize(size);var containerSize=this.extractSize(avatarStyle);var imageSource=_core.ValueUtil.getImageSource(source);var showName=typeof imageSource==='object'&&Object.keys(imageSource).length===0&&typeof imageSource!=='number';var inner=_react.default.createElement(_reactNative.View,{style:[styles.container,containerSize,style],__source:{fileName:_jsxFileName,lineNumber:444,columnNumber:13}},showName||hideSource?this.renderShortName(name,avatarStyle,size):_react.default.createElement(_reactNative.View,{__source:{fileName:_jsxFileName,lineNumber:445,columnNumber:93}}),this.isValidImageUrl(imageSource)&&!hideSource?_react.default.createElement(_core.Image,(0,_extends2.default)({cached:cached,loading:loading||isShowLoading,source:imageSource,onError:this.onLoadSourceError,style:avatarStyle,resizeMode:resizeMode},extraPropsImage,{__source:{fileName:_jsxFileName,lineNumber:448,columnNumber:25}})):_react.default.createElement(_reactNative.View,{__source:{fileName:_jsxFileName,lineNumber:457,columnNumber:25}}),this.renderSubIcon());if(onPress){return _react.default.createElement(_reactNative.TouchableOpacity,{activeOpacity:onPress?0.5:1,onPress:this.onPress,__source:{fileName:_jsxFileName,lineNumber:463,columnNumber:17}},inner);}return inner;}}],[{key:"getDerivedStateFromProps",value:function getDerivedStateFromProps(nextProps,prevState){if(prevState.ownUpdate){return{ownUpdate:false};}if(!(0,_lodash.isEqual)(nextProps.source,prevState.source)){return{source:nextProps.source,hideSource:false};}return null;}}]);return Avatar;}(_react.Component);exports.default=Avatar;Avatar.propTypes={name:_propTypes.default.string,resizeMode:_propTypes.default.string,size:_propTypes.default.oneOf(['tiny','small','medium','large','giant','size8','size24','size36','size44','size48','size52','size56','size64','size72','size80','size88','size96',_propTypes.default.shape({width:_propTypes.default.number,height:_propTypes.default.number,borderRadius:_propTypes.default.number})]),source:_propTypes.default.oneOfType([_propTypes.default.shape({uri:_propTypes.default.string}),_propTypes.default.number,_propTypes.default.string]),subIcon:_propTypes.default.oneOf(['momo','online','key','none']),subIconSource:_propTypes.default.oneOfType([_propTypes.default.shape({uri:_propTypes.default.string}),_propTypes.default.number,_propTypes.default.string]),style:_propTypes.default.oneOfType([_propTypes.default.array,_propTypes.default.object]),onPress:_propTypes.default.func,loading:_propTypes.default.bool,cached:_propTypes.default.bool,extraPropsImage:_propTypes.default.object};Avatar.defaultProps={resizeMode:'cover',cached:true};
1
+ /* eslint-disable indent */
2
+ import PropTypes from 'prop-types';
3
+ import React, { Component } from 'react';
4
+ import {
5
+ View, StyleSheet, TouchableOpacity, Dimensions, Platform
6
+ } from 'react-native';
7
+ import { get, isEqual } from 'lodash';
8
+ import {
9
+ ValueUtil, Colors, Text, IconSource, Image, ScaleSize
10
+ } from '@momo-kits/core';
11
+
12
+ export const AvatarQuality = {
13
+ low: 'low',
14
+ medium: 'medium',
15
+ high: 'high',
16
+ };
17
+
18
+ export const AvatarSize = {
19
+ tiny: 'tiny',
20
+ small: 'small',
21
+ medium: 'medium',
22
+ large: 'large',
23
+ giant: 'giant',
24
+ size8: 'size8',
25
+ size24: 'size24',
26
+ size36: 'size36',
27
+ size44: 'size44',
28
+ size48: 'size48',
29
+ size52: 'size52',
30
+ size56: 'size56',
31
+ size64: 'size64',
32
+ size72: 'size72',
33
+ size80: 'size80',
34
+ size88: 'size88',
35
+ size96: 'size96'
36
+ };
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
+
61
+ export const SubIconType = {
62
+ momo: 'momo',
63
+ online: 'online',
64
+ key: 'key',
65
+ none: 'none'
66
+ };
67
+
68
+ const styles = StyleSheet.create({
69
+ container: {
70
+ justifyContent: 'center',
71
+ alignItems: 'center'
72
+ },
73
+ shortNameView: {
74
+ justifyContent: 'center',
75
+ alignItems: 'center',
76
+
77
+ backgroundColor: Colors.very_light_pink_four,
78
+ width: '100%',
79
+ height: '100%'
80
+ },
81
+ shortNameText: {
82
+ // fontSize: 17,
83
+ color: '#f6f6f6'
84
+ },
85
+ absolute: {
86
+ position: 'absolute',
87
+ top: 0,
88
+ left: 0,
89
+ right: 0,
90
+ bottom: 0
91
+ },
92
+ subIcon: {
93
+ position: 'absolute',
94
+ bottom: 0,
95
+ right: 0
96
+ },
97
+ subIconImage: {
98
+ width: 22,
99
+ height: 22
100
+ },
101
+ subIconImageOnline: {
102
+ backgroundColor: Colors.kiwi_green,
103
+ borderColor: 'white',
104
+ borderWidth: 1
105
+ }
106
+ });
107
+
108
+ const subIconSize = (width) => ({
109
+ tiny: {
110
+ width: 8,
111
+ height: 8,
112
+ borderRadius: 4
113
+ },
114
+ small: {
115
+ width: 10,
116
+ height: 10,
117
+ borderRadius: 5
118
+ },
119
+ medium: {
120
+ width: 12,
121
+ height: 12,
122
+ borderRadius: 6
123
+ },
124
+ large: {
125
+ width: 16,
126
+ height: 16,
127
+ borderRadius: 8
128
+ },
129
+ size8: {
130
+ width: 8,
131
+ height: 8,
132
+ borderRadius: 4
133
+ },
134
+ size24: {
135
+ width: 10,
136
+ height: 10,
137
+ borderRadius: 5
138
+ },
139
+ size36: {
140
+ width: 10,
141
+ height: 10,
142
+ borderRadius: 5
143
+ },
144
+ size44: {
145
+ width: 14,
146
+ height: 14,
147
+ borderRadius: 7
148
+ },
149
+ size48: {
150
+ width: 14,
151
+ height: 14,
152
+ borderRadius: 7
153
+ },
154
+ size52: {
155
+ width: 16,
156
+ height: 16,
157
+ borderRadius: 8
158
+ },
159
+ size56: {
160
+ width: 16,
161
+ height: 16,
162
+ borderRadius: 8
163
+ },
164
+ size64: {
165
+ width: 16,
166
+ height: 16,
167
+ borderRadius: 8,
168
+ top: -2,
169
+ left: -2,
170
+ },
171
+ size72: {
172
+ width: 18,
173
+ height: 18,
174
+ borderRadius: 9,
175
+ top: -3,
176
+ left: -3,
177
+ },
178
+ size80: {
179
+ width: 18,
180
+ height: 18,
181
+ borderRadius: 9,
182
+ top: -3,
183
+ left: -3,
184
+ },
185
+ size88: {
186
+ width: 18,
187
+ height: 18,
188
+ borderRadius: 9,
189
+ top: -4,
190
+ left: -4,
191
+ },
192
+ size96: {
193
+ width: 20,
194
+ height: 20,
195
+ borderRadius: 10,
196
+ top: -4,
197
+ left: -4,
198
+ },
199
+ giant: {
200
+ top: -5,
201
+ left: -5,
202
+ width: 24,
203
+ height: 24,
204
+ borderRadius: 12
205
+ }
206
+ });
207
+
208
+ const avatarSize = (width) => ({
209
+ tiny: {
210
+ width: 16,
211
+ height: 16,
212
+ borderRadius: 8
213
+ },
214
+ small: {
215
+ width: 32,
216
+ height: 32,
217
+ borderRadius: 16
218
+ },
219
+ medium: {
220
+ width: 40,
221
+ height: 40,
222
+ borderRadius: 20
223
+ },
224
+ large: {
225
+ width: 60,
226
+ height: 60,
227
+ borderRadius: 30
228
+ },
229
+ giant: {
230
+ width: 120,
231
+ height: 120,
232
+ borderRadius: 60
233
+ },
234
+ size8: {
235
+ width: 8,
236
+ height: 8,
237
+ borderRadius: 4
238
+ },
239
+ size24: {
240
+ width: 24,
241
+ height: 24,
242
+ borderRadius: 12
243
+ },
244
+ size36: {
245
+ width: 36,
246
+ height: 36,
247
+ borderRadius: 18
248
+ },
249
+ size44: {
250
+ width: 44,
251
+ height: 44,
252
+ borderRadius: 22
253
+ },
254
+ size48: {
255
+ width: 48,
256
+ height: 48,
257
+ borderRadius: 24
258
+ },
259
+ size52: {
260
+ width: 52,
261
+ height: 52,
262
+ borderRadius: 26
263
+ },
264
+ size56: {
265
+ width: 56,
266
+ height: 56,
267
+ borderRadius: 28
268
+ },
269
+ size64: {
270
+ width: 64,
271
+ height: 64,
272
+ borderRadius: 32
273
+ },
274
+ size72: {
275
+ width: 72,
276
+ height: 72,
277
+ borderRadius: 36
278
+ },
279
+ size80: {
280
+ width: 80,
281
+ height: 80,
282
+ borderRadius: 40
283
+ },
284
+ size88: {
285
+ width: 88,
286
+ height: 88,
287
+ borderRadius: 44
288
+ },
289
+ size96: {
290
+ width: 96,
291
+ height: 96,
292
+ borderRadius: 48
293
+ }
294
+ });
295
+
296
+ const shortName = (width) => ({
297
+ tiny: {
298
+ fontSize: ScaleSize(5, width)
299
+ },
300
+ small: {
301
+ fontSize: ScaleSize(11, width)
302
+ },
303
+ medium: {
304
+ fontSize: ScaleSize(15, width)
305
+ },
306
+ middle: {
307
+ fontSize: ScaleSize(16, width)
308
+ },
309
+ large: {
310
+ fontSize: ScaleSize(20, width)
311
+ },
312
+ giant: {
313
+ fontSize: ScaleSize(25, width)
314
+ }
315
+ });
316
+
317
+ export default class Avatar extends Component {
318
+ constructor(props) {
319
+ super(props);
320
+ this.color = this.getAvatarColor(props.name);
321
+ this.state = {
322
+ hideSource: false,
323
+ ownUpdate: false,
324
+ source: props.source,
325
+ dimensions: {}
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
+ }
349
+ }
350
+
351
+ static getDerivedStateFromProps(nextProps, prevState) {
352
+ if (prevState.ownUpdate) {
353
+ return {
354
+ ownUpdate: false,
355
+ };
356
+ } if (!isEqual(nextProps.source, prevState.source)) {
357
+ return { source: nextProps.source, hideSource: false };
358
+ }
359
+ return null;
360
+ }
361
+
362
+ getContactShortName = (name) => {
363
+ if (!name) return '';
364
+ const shortNameList = name.split(' ', 2);
365
+ const alphabet = [];
366
+ shortNameList.forEach((n) => {
367
+ if (n && n.length > 0) {
368
+ alphabet.push(n[0].toString().toUpperCase());
369
+ }
370
+ });
371
+ return alphabet.join('');
372
+ }
373
+
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,) => {
387
+ if (name) {
388
+ const shortedName = this.getContactShortName(name);
389
+ const shortNameStyle = this.mapShortNameStyle(size);
390
+ return (
391
+ <View style={[styles.shortNameView, avatarStyle, { backgroundColor: color }]}>
392
+ <Text.H4 style={[styles.shortNameText, shortNameStyle]}>{shortedName}</Text.H4>
393
+ </View>
394
+ );
395
+ }
396
+ return <View />;
397
+ }
398
+
399
+ isUrl(url) {
400
+ const expression = /(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-/]))?/gi;
401
+ return expression.test(url);
402
+ }
403
+
404
+ isValidImageUrl = (source) => {
405
+ const validSource = source && source.uri && this.isUrl(source.uri);
406
+ return validSource;
407
+ }
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
+
423
+ mapStyleFromSize = (size) => {
424
+ const { dimensions } = this.state;
425
+ const avatarStyle = avatarSize(dimensions?.width > 0 ? dimensions?.width : null).small;
426
+ if (typeof size === 'object') return size;
427
+ if (avatarSize(dimensions?.width > 0 ? dimensions?.width : null)[size]) return avatarSize(dimensions?.width > 0 ? dimensions?.width : null)[size];
428
+ return avatarStyle;
429
+ }
430
+
431
+ mapShortNameStyle = (size) => {
432
+ let shortNameStyle = {};
433
+ const { dimensions } = this.state;
434
+ switch (size) {
435
+ case AvatarSize.tiny: {
436
+ shortNameStyle = shortName(dimensions?.width > 0 ? dimensions?.width : null).tiny;
437
+ break;
438
+ }
439
+ case AvatarSize.small: {
440
+ shortNameStyle = shortName(dimensions?.width > 0 ? dimensions?.width : null).small;
441
+ break;
442
+ }
443
+ case AvatarSize.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;
449
+ break;
450
+ }
451
+ case AvatarSize.large: {
452
+ shortNameStyle = shortName(dimensions?.width > 0 ? dimensions?.width : null).large;
453
+ break;
454
+ }
455
+ case AvatarSize.giant: {
456
+ shortNameStyle = shortName(dimensions?.width > 0 ? dimensions?.width : null).giant;
457
+ break;
458
+ }
459
+ default:
460
+ shortNameStyle = shortName(dimensions?.width > 0 ? dimensions?.width : null).small;
461
+ }
462
+ return shortNameStyle;
463
+ }
464
+
465
+ mapSubIconSize = (size) => {
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];
469
+ return subIconStyle;
470
+ }
471
+
472
+ extractSize = (avatarStyle) => {
473
+ const { style } = this.props;
474
+ const borderWidth = get(style, 'borderWidth', 1);
475
+ const containerWidth = Math.round(avatarStyle.width + 2 + borderWidth);
476
+ return {
477
+ width: containerWidth,
478
+ height: containerWidth,
479
+ borderRadius: containerWidth / 2,
480
+ borderWidth,
481
+ borderColor: Colors.black_01
482
+ };
483
+ }
484
+
485
+ onLoadSourceError = (imageSource) => {
486
+ if(this.imageSource?.uri !== imageSource?.uri){
487
+ this.imageSource = imageSource;
488
+ this.setState({ hideSource: true, ownUpdate: true });
489
+ }
490
+ }
491
+
492
+ renderSubIcon = () => {
493
+ const { subIcon, size, subIconSource } = this.props;
494
+ if ((!subIcon || subIcon === SubIconType.none) && !subIconSource) return <View />;
495
+ const subIconSizeStyle = this.mapSubIconSize(size);
496
+ const iconSource = ValueUtil.getImageSource(subIconSource);
497
+ return (
498
+ <View style={styles.subIcon}>
499
+ {subIcon === SubIconType.momo
500
+ ? (
501
+ <Image
502
+ style={[styles.subIconImage, subIconSizeStyle]}
503
+ source={IconSource.ic_round_momo_tiny}
504
+ />
505
+ )
506
+ : <View />}
507
+ {subIcon === SubIconType.online
508
+ ? <View style={[styles.subIconImageOnline, subIconSizeStyle]} /> : <View />}
509
+
510
+ {iconSource && subIconSource && !subIcon ? (
511
+ <Image
512
+ style={[styles.subIconImage, subIconSizeStyle]}
513
+ source={iconSource}
514
+ />
515
+ )
516
+ : <View />}
517
+ </View>
518
+ );
519
+ }
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
+
530
+ onPress = () => {
531
+ const { onPress } = this.props;
532
+ if (onPress && typeof onPress === 'function') onPress();
533
+ }
534
+
535
+ render() {
536
+ const {
537
+ size, source, name, resizeMode, style, onPress, isShowLoading, loading, cached, extraPropsImage, quality
538
+ } = this.props;
539
+ const { hideSource } = this.state;
540
+ const avatarStyle = this.mapStyleFromSize(size);
541
+ const containerSize = this.extractSize(avatarStyle);
542
+ const imageSource = ValueUtil.getImageSource(source);
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
+
555
+ const inner = (
556
+ <View style={[styles.container, containerSize, style]}>
557
+ {(showName || hideSource) ? this.renderShortName(name, avatarStyle, size, this.color) : <View />}
558
+ {this.isValidImageUrl(imageSource) && !hideSource
559
+ ? (
560
+ <Image
561
+ cached={cached}
562
+ loading={loading || isShowLoading}
563
+ source={imageSource}
564
+ onError={() => this.onLoadSourceError(imageSource)}
565
+ style={avatarStyle}
566
+ resizeMode={resizeMode}
567
+ {...extraPropsImage}
568
+ />
569
+ ) : <View />}
570
+ {this.renderSubIcon()}
571
+ </View>
572
+ );
573
+ if (onPress) {
574
+ return (
575
+ <TouchableOpacity activeOpacity={onPress ? 0.5 : 1} onPress={this.onPress}>
576
+ {inner}
577
+ </TouchableOpacity>
578
+ );
579
+ }
580
+ return inner;
581
+ }
582
+ }
583
+
584
+ Avatar.propTypes = {
585
+ name: PropTypes.string,
586
+ resizeMode: PropTypes.string,
587
+ quality: PropTypes.oneOf(['low', 'medium', 'high']),
588
+ size: PropTypes.any,
589
+ source: PropTypes.oneOfType([PropTypes.shape({ uri: PropTypes.string }), PropTypes.number, PropTypes.string]),
590
+ subIcon: PropTypes.oneOf(['momo', 'online', 'key', 'none']),
591
+ subIconSource: PropTypes.oneOfType([PropTypes.shape({ uri: PropTypes.string }), PropTypes.number, PropTypes.string]),
592
+ style: PropTypes.oneOfType([PropTypes.array, PropTypes.object]),
593
+ onPress: PropTypes.func,
594
+ loading: PropTypes.bool,
595
+ cached: PropTypes.bool,
596
+ scaleSize: PropTypes.bool,
597
+ extraPropsImage: PropTypes.object,
598
+ number: PropTypes.string
599
+ };
600
+
601
+ Avatar.defaultProps = {
602
+ resizeMode: 'cover',
603
+ cached: true,
604
+ scaleSize: false,
605
+ quality: 'medium',
606
+ size: 'small'
607
+ };
package/Avatar.web.js CHANGED
@@ -1 +1,588 @@
1
- var _interopRequireDefault=require("@babel/runtime/helpers/interopRequireDefault");Object.defineProperty(exports,"__esModule",{value:true});exports.default=exports.SubIconType=exports.AvatarSize=void 0;var _extends2=_interopRequireDefault(require("@babel/runtime/helpers/extends"));var _classCallCheck2=_interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));var _createClass2=_interopRequireDefault(require("@babel/runtime/helpers/createClass"));var _inherits2=_interopRequireDefault(require("@babel/runtime/helpers/inherits"));var _possibleConstructorReturn2=_interopRequireDefault(require("@babel/runtime/helpers/possibleConstructorReturn"));var _getPrototypeOf2=_interopRequireDefault(require("@babel/runtime/helpers/getPrototypeOf"));var _propTypes=_interopRequireDefault(require("prop-types"));var _react=_interopRequireWildcard(require("react"));var _reactNative=require("react-native");var _lodash=require("lodash");var _ValueUtil=_interopRequireDefault(require("../../utils/ValueUtil"));var _colors=_interopRequireDefault(require("../../colors"));var _icons=require("../../icons");var _typography=_interopRequireDefault(require("../typography"));var _colorCore=require("../../colors/colorCore");var _jsxFileName="/Users/trinh.ho2/momo-folk/kits/src/libs/avatar/dist/Avatar.web.js";function _getRequireWildcardCache(nodeInterop){if(typeof WeakMap!=="function")return null;var cacheBabelInterop=new WeakMap();var cacheNodeInterop=new WeakMap();return(_getRequireWildcardCache=function _getRequireWildcardCache(nodeInterop){return nodeInterop?cacheNodeInterop:cacheBabelInterop;})(nodeInterop);}function _interopRequireWildcard(obj,nodeInterop){if(!nodeInterop&&obj&&obj.__esModule){return obj;}if(obj===null||typeof obj!=="object"&&typeof obj!=="function"){return{default:obj};}var cache=_getRequireWildcardCache(nodeInterop);if(cache&&cache.has(obj)){return cache.get(obj);}var newObj={};var hasPropertyDescriptor=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var key in obj){if(key!=="default"&&Object.prototype.hasOwnProperty.call(obj,key)){var desc=hasPropertyDescriptor?Object.getOwnPropertyDescriptor(obj,key):null;if(desc&&(desc.get||desc.set)){Object.defineProperty(newObj,key,desc);}else{newObj[key]=obj[key];}}}newObj.default=obj;if(cache){cache.set(obj,newObj);}return newObj;}function _createSuper(Derived){var hasNativeReflectConstruct=_isNativeReflectConstruct();return function _createSuperInternal(){var Super=(0,_getPrototypeOf2.default)(Derived),result;if(hasNativeReflectConstruct){var NewTarget=(0,_getPrototypeOf2.default)(this).constructor;result=Reflect.construct(Super,arguments,NewTarget);}else{result=Super.apply(this,arguments);}return(0,_possibleConstructorReturn2.default)(this,result);};}function _isNativeReflectConstruct(){if(typeof Reflect==="undefined"||!Reflect.construct)return false;if(Reflect.construct.sham)return false;if(typeof Proxy==="function")return true;try{Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){}));return true;}catch(e){return false;}}var AvatarSize={tiny:'tiny',small:'small',medium:'medium',large:'large',giant:'giant',size8:'size8',size24:'size24',size36:'size36',size44:'size44',size48:'size48',size52:'size52',size56:'size56',size64:'size64',size72:'size72',size80:'size80',size88:'size88',size96:'size96'};exports.AvatarSize=AvatarSize;var SubIconType={momo:'momo',online:'online',key:'key',none:'none'};exports.SubIconType=SubIconType;var styles=_reactNative.StyleSheet.create({container:{justifyContent:'center',alignItems:'center'},shortNameView:{justifyContent:'center',alignItems:'center',backgroundColor:_colors.default.very_light_pink_four,width:'100%',height:'100%'},shortNameText:{color:'#f6f6f6'},absolute:{position:'absolute',top:0,left:0,right:0,bottom:0},subIcon:{position:'absolute',bottom:0,right:0},subIconImage:{width:22,height:22},subIconImageOnline:{backgroundColor:_colors.default.kiwi_green,borderColor:'white',borderWidth:1}});var subIconSize=_reactNative.StyleSheet.create({tiny:{width:8,height:8,borderRadius:4},small:{width:10,height:10,borderRadius:5},medium:{width:12,height:12,borderRadius:6},large:{width:16,height:16,borderRadius:8},size8:{width:8,height:8,borderRadius:4},size24:{width:10,height:10,borderRadius:5},size36:{width:10,height:10,borderRadius:5},size44:{width:14,height:14,borderRadius:7},size48:{width:14,height:14,borderRadius:7},size52:{width:16,height:16,borderRadius:8},size56:{width:16,height:16,borderRadius:8},size64:{width:16,height:16,borderRadius:8,top:-2,left:-2},size72:{width:18,height:18,borderRadius:9,top:-3,left:-3},size80:{width:18,height:18,borderRadius:9,top:-3,left:-3},size88:{width:18,height:18,borderRadius:9,top:-4,left:-4},size96:{width:20,height:20,borderRadius:10,top:-4,left:-4},giant:{top:-5,left:-5,width:24,height:24,borderRadius:12}});var avatarSize=_reactNative.StyleSheet.create({tiny:{width:16,height:16,borderRadius:8},small:{width:32,height:32,borderRadius:16},medium:{width:40,height:40,borderRadius:20},large:{width:60,height:60,borderRadius:30},giant:{width:120,height:120,borderRadius:60},size8:{width:8,height:8,borderRadius:4},size24:{width:24,height:24,borderRadius:12},size36:{width:36,height:36,borderRadius:18},size44:{width:44,height:44,borderRadius:22},size48:{width:48,height:48,borderRadius:24},size52:{width:52,height:52,borderRadius:26},size56:{width:56,height:56,borderRadius:28},size64:{width:64,height:64,borderRadius:32},size72:{width:72,height:72,borderRadius:36},size80:{width:80,height:80,borderRadius:40},size88:{width:88,height:88,borderRadius:44},size96:{width:96,height:96,borderRadius:48}});var shortName=_reactNative.StyleSheet.create({tiny:{fontSize:5},small:{fontSize:11},medium:{fontSize:15},large:{fontSize:20},giant:{fontSize:25}});var Avatar=function(_Component){(0,_inherits2.default)(Avatar,_Component);var _super=_createSuper(Avatar);function Avatar(props){var _this;(0,_classCallCheck2.default)(this,Avatar);_this=_super.call(this,props);_this.getContactShortName=function(name){if(!name)return'';var shortNameList=name.split(' ',2);var alphabet=[];shortNameList.forEach(function(n){if(n&&n.length>0){alphabet.push(n[0].toString().toUpperCase());}});return alphabet.join('');};_this.renderShortName=function(name,avatarStyle,size){if(name){var shortedName=_this.getContactShortName(name);var shortNameStyle=_this.mapShortNameStyle(size);return _react.default.createElement(_reactNative.View,{style:[styles.shortNameView,avatarStyle],__source:{fileName:_jsxFileName,lineNumber:325,columnNumber:17}},_react.default.createElement(_typography.default.H4,{style:[styles.shortNameText,shortNameStyle],__source:{fileName:_jsxFileName,lineNumber:326,columnNumber:21}},shortedName));}return _react.default.createElement(_reactNative.View,{__source:{fileName:_jsxFileName,lineNumber:330,columnNumber:16}});};_this.isValidImageUrl=function(source){var validSource=source&&(source.uri&&_this.isUrl(source.uri)||typeof source==='number');return validSource;};_this.mapStyleFromSize=function(size){var avatarStyle=avatarSize.small;if(typeof size==='object')return size;if(avatarSize[size])return avatarSize[size];return avatarStyle;};_this.mapShortNameStyle=function(size){var shortNameStyle={};switch(size){case AvatarSize.tiny:{shortNameStyle=shortName.tiny;break;}case AvatarSize.small:{shortNameStyle=shortName.small;break;}case AvatarSize.medium:{shortNameStyle=shortName.medium;break;}case AvatarSize.large:{shortNameStyle=shortName.large;break;}case AvatarSize.giant:{shortNameStyle=shortName.giant;break;}default:shortNameStyle=shortName.small;}return shortNameStyle;};_this.mapSubIconSize=function(size){var subIconStyle=subIconSize.small;if(subIconSize[size])return subIconSize[size];return subIconStyle;};_this.extractSize=function(avatarStyle){var style=_this.props.style;var borderWidth=(0,_lodash.get)(style,'borderWidth',1);var containerWidth=Math.round(avatarStyle.width+2+borderWidth);return{width:containerWidth,height:containerWidth,borderRadius:containerWidth/2,borderWidth:borderWidth,borderColor:_colorCore.ColorCore.black_01};};_this.onLoadSourceError=function(){_this.setState({hideSource:true,ownUpdate:true});};_this.renderSubIcon=function(){var _this$props=_this.props,subIcon=_this$props.subIcon,size=_this$props.size,subIconSource=_this$props.subIconSource;if((!subIcon||subIcon===SubIconType.none)&&!subIconSource)return _react.default.createElement(_reactNative.View,{__source:{fileName:_jsxFileName,lineNumber:404,columnNumber:82}});var subIconSizeStyle=_this.mapSubIconSize(size);var iconSource=_ValueUtil.default.getImageSource(subIconSource);return _react.default.createElement(_reactNative.View,{style:styles.subIcon,__source:{fileName:_jsxFileName,lineNumber:408,columnNumber:13}},subIcon===SubIconType.momo?_react.default.createElement(_reactNative.Image,{style:[styles.subIconImage,subIconSizeStyle],source:_icons.Icons.ic_round_momo_tiny,__source:{fileName:_jsxFileName,lineNumber:411,columnNumber:25}}):_react.default.createElement(_reactNative.View,{__source:{fileName:_jsxFileName,lineNumber:416,columnNumber:23}}),subIcon===SubIconType.online?_react.default.createElement(_reactNative.View,{style:[styles.subIconImageOnline,subIconSizeStyle],__source:{fileName:_jsxFileName,lineNumber:418,columnNumber:23}}):_react.default.createElement(_reactNative.View,{__source:{fileName:_jsxFileName,lineNumber:418,columnNumber:88}}),iconSource&&subIconSource&&!subIcon?_react.default.createElement(_reactNative.Image,{style:[styles.subIconImage,subIconSizeStyle],source:iconSource,__source:{fileName:_jsxFileName,lineNumber:421,columnNumber:21}}):_react.default.createElement(_reactNative.View,{__source:{fileName:_jsxFileName,lineNumber:426,columnNumber:23}}));};_this.onPress=function(){var onPress=_this.props.onPress;if(onPress&&typeof onPress==='function')onPress();};_this.state={hideSource:false,ownUpdate:false,source:props.source};return _this;}(0,_createClass2.default)(Avatar,[{key:"isUrl",value:function isUrl(url){var expression=/(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-/]))?/gi;return expression.test(url);}},{key:"render",value:function render(){var _this$props2=this.props,size=_this$props2.size,source=_this$props2.source,name=_this$props2.name,resizeMode=_this$props2.resizeMode,style=_this$props2.style,onPress=_this$props2.onPress,isShowLoading=_this$props2.isShowLoading,loading=_this$props2.loading,cached=_this$props2.cached,extraPropsImage=_this$props2.extraPropsImage;var hideSource=this.state.hideSource;var avatarStyle=this.mapStyleFromSize(size);var containerSize=this.extractSize(avatarStyle);var imageSource=_ValueUtil.default.getImageSource(source);var showName=typeof imageSource==='object'&&Object.keys(imageSource).length===0&&typeof imageSource!=='number';var inner=_react.default.createElement(_reactNative.View,{style:[styles.container,avatarStyle,style],__source:{fileName:_jsxFileName,lineNumber:446,columnNumber:13}},showName||hideSource?this.renderShortName(name,avatarStyle,size):null,this.isValidImageUrl(imageSource)&&!hideSource?_react.default.createElement(_reactNative.Image,(0,_extends2.default)({cached:cached,loading:loading||isShowLoading,source:imageSource,onError:this.onLoadSourceError,style:avatarStyle,resizeMode:resizeMode},extraPropsImage,{__source:{fileName:_jsxFileName,lineNumber:450,columnNumber:25}})):_react.default.createElement(_reactNative.View,{__source:{fileName:_jsxFileName,lineNumber:459,columnNumber:25}}),this.renderSubIcon());if(onPress){return _react.default.createElement(_reactNative.TouchableOpacity,{activeOpacity:onPress?0.5:1,onPress:this.onPress,__source:{fileName:_jsxFileName,lineNumber:465,columnNumber:17}},inner);}return inner;}}],[{key:"getDerivedStateFromProps",value:function getDerivedStateFromProps(nextProps,prevState){if(prevState.ownUpdate){return{ownUpdate:false};}if(!(0,_lodash.isEqual)(nextProps.source,prevState.source)){return{source:nextProps.source,hideSource:false};}return null;}}]);return Avatar;}(_react.Component);exports.default=Avatar;Avatar.propTypes={name:_propTypes.default.string,resizeMode:_propTypes.default.string,size:_propTypes.default.oneOf(['tiny','small','medium','large','giant','size8','size24','size36','size44','size48','size52','size56','size64','size72','size80','size88','size96']),source:_propTypes.default.oneOfType([_propTypes.default.shape({uri:_propTypes.default.string}),_propTypes.default.number,_propTypes.default.string]),subIcon:_propTypes.default.oneOf(['momo','online','key','none']),subIconSource:_propTypes.default.oneOfType([_propTypes.default.shape({uri:_propTypes.default.string}),_propTypes.default.number,_propTypes.default.string]),style:_propTypes.default.oneOfType([_propTypes.default.array,_propTypes.default.object]),onPress:_propTypes.default.func,loading:_propTypes.default.bool,cached:_propTypes.default.bool,extraPropsImage:_propTypes.default.object};Avatar.defaultProps={resizeMode:'cover',size:'medium',cached:true};
1
+ /* eslint-disable indent */
2
+ import PropTypes from 'prop-types';
3
+ import React, { Component } from 'react';
4
+ import {
5
+ View, StyleSheet, TouchableOpacity, Image, Dimensions
6
+ } from 'react-native';
7
+ import { get, isEqual } from 'lodash';
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
+ ];
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
+ const styles = StyleSheet.create({
71
+ container: {
72
+ justifyContent: 'center',
73
+ alignItems: 'center'
74
+ },
75
+ shortNameView: {
76
+ justifyContent: 'center',
77
+ alignItems: 'center',
78
+
79
+ backgroundColor: Colors.very_light_pink_four,
80
+ width: '100%',
81
+ height: '100%'
82
+ },
83
+ shortNameText: {
84
+ // fontSize: 17,
85
+ color: '#f6f6f6'
86
+ },
87
+ absolute: {
88
+ position: 'absolute',
89
+ top: 0,
90
+ left: 0,
91
+ right: 0,
92
+ bottom: 0
93
+ },
94
+ subIcon: {
95
+ position: 'absolute',
96
+ bottom: 0,
97
+ right: 0
98
+ },
99
+ subIconImage: {
100
+ width: 22,
101
+ height: 22
102
+ },
103
+ subIconImageOnline: {
104
+ backgroundColor: Colors.kiwi_green,
105
+ 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
130
+ },
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
+ });
209
+
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
+ }
340
+ }
341
+
342
+ componentWillUnmount() {
343
+ const { scaleSize } = this.props;
344
+ if (scaleSize) {
345
+ this.subscription?.remove?.();
346
+ }
347
+ }
348
+
349
+ static getDerivedStateFromProps(nextProps, prevState) {
350
+ if (prevState.ownUpdate) {
351
+ return {
352
+ ownUpdate: false,
353
+ };
354
+ } if (!isEqual(nextProps.source, prevState.source)) {
355
+ return { source: nextProps.source, hideSource: false };
356
+ }
357
+ return null;
358
+ }
359
+
360
+ getContactShortName = (name) => {
361
+ if (!name) return '';
362
+ const shortNameList = name.split(' ', 2);
363
+ const alphabet = [];
364
+ shortNameList.forEach((n) => {
365
+ if (n && n.length > 0) {
366
+ alphabet.push(n[0].toString().toUpperCase());
367
+ }
368
+ });
369
+ 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;
387
+ return expression.test(url);
388
+ }
389
+
390
+ isValidImageUrl = (source) => {
391
+ const validSource = source && source.uri && this.isUrl(source.uri);
392
+ return validSource;
393
+ }
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
+
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
+ }
475
+
476
+
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
+ ? (
490
+ <Image
491
+ style={[styles.subIconImage, subIconSizeStyle]}
492
+ source={IconSource.ic_round_momo_tiny}
493
+ />
494
+ )
495
+ : <View />}
496
+ {subIcon === SubIconType.online
497
+ ? <View style={[styles.subIconImageOnline, subIconSizeStyle]} /> : <View />}
498
+
499
+ {iconSource && subIconSource && !subIcon ? (
500
+ <Image
501
+ style={[styles.subIconImage, subIconSizeStyle]}
502
+ source={iconSource}
503
+ />
504
+ )
505
+ : <View />}
506
+ </View>
507
+ );
508
+ }
509
+
510
+ onPress = () => {
511
+ const { onPress } = this.props;
512
+ 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
+ }
534
+
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) {
554
+ return (
555
+ <TouchableOpacity activeOpacity={onPress ? 0.5 : 1} onPress={this.onPress}>
556
+ {inner}
557
+ </TouchableOpacity>
558
+ );
559
+ }
560
+ return inner;
561
+ }
562
+ }
563
+
564
+ Avatar.propTypes = {
565
+ name: PropTypes.string,
566
+ resizeMode: PropTypes.string,
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
+ })]),
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]),
575
+ style: PropTypes.oneOfType([PropTypes.array, PropTypes.object]),
576
+ onPress: PropTypes.func,
577
+ loading: PropTypes.bool,
578
+ cached: PropTypes.bool,
579
+ scaleSize: PropTypes.bool,
580
+ extraPropsImage: PropTypes.object
581
+ };
582
+
583
+ Avatar.defaultProps = {
584
+ resizeMode: 'cover',
585
+ cached: true,
586
+ scaleSize: false,
587
+ quality: 'medium',
588
+ };
package/index.js CHANGED
@@ -1 +1,3 @@
1
- var _interopRequireDefault=require("@babel/runtime/helpers/interopRequireDefault");Object.defineProperty(exports,"__esModule",{value:true});exports.default=void 0;var _Avatar=_interopRequireDefault(require("./Avatar"));var _default=_Avatar.default;exports.default=_default;
1
+ import Avatar from './Avatar';
2
+
3
+ export default Avatar;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@momo-kits/avatar",
3
- "version": "0.0.34-beta",
3
+ "version": "0.0.34",
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
- "lodash": "^4.17.15",
12
- "@momo-kits/core": ">=0.0.5-beta"
11
+ "@momo-kits/core": ">=0.0.5-beta",
12
+ "lodash": "^4.17.15"
13
13
  },
14
- "devDependencies": {
15
- "metro-react-native-babel-preset": "^0.64.0",
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
@@ -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
@@ -26,4 +26,4 @@ cd ..
26
26
  rm -rf dist
27
27
 
28
28
 
29
- echo '{"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"}'
package/babel.config.js DELETED
@@ -1 +0,0 @@
1
- module.exports={presets:['module:metro-react-native-babel-preset']};