You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
	
	
		
			119 lines
		
	
	
		
			2.6 KiB
		
	
	
	
		
			TypeScript
		
	
		
		
			
		
	
	
			119 lines
		
	
	
		
			2.6 KiB
		
	
	
	
		
			TypeScript
		
	
| 
											7 years ago
										 | import React from 'react'; | ||
|  | import classNames from 'classnames'; | ||
|  | 
 | ||
|  | import { getInitials } from '../util/getInitials'; | ||
|  | import { Localizer } from '../types/Util'; | ||
|  | 
 | ||
|  | interface Props { | ||
|  |   avatarPath?: string; | ||
|  |   color?: string; | ||
|  |   conversationType: 'group' | 'direct'; | ||
|  |   i18n: Localizer; | ||
|  |   name?: string; | ||
|  |   phoneNumber?: string; | ||
|  |   profileName?: string; | ||
|  |   size: number; | ||
|  | } | ||
|  | 
 | ||
|  | interface State { | ||
|  |   imageBroken: boolean; | ||
|  | } | ||
|  | 
 | ||
|  | export class Avatar extends React.Component<Props, State> { | ||
|  |   public handleImageErrorBound: () => void; | ||
|  | 
 | ||
|  |   public constructor(props: Props) { | ||
|  |     super(props); | ||
|  | 
 | ||
|  |     this.handleImageErrorBound = this.handleImageError.bind(this); | ||
|  | 
 | ||
|  |     this.state = { | ||
|  |       imageBroken: false, | ||
|  |     }; | ||
|  |   } | ||
|  | 
 | ||
|  |   public handleImageError() { | ||
|  |     // tslint:disable-next-line no-console
 | ||
|  |     console.log('Avatar: Image failed to load; failing over to placeholder'); | ||
|  |     this.setState({ | ||
|  |       imageBroken: true, | ||
|  |     }); | ||
|  |   } | ||
|  | 
 | ||
|  |   public renderImage() { | ||
|  |     const { avatarPath, i18n, name, phoneNumber, profileName } = this.props; | ||
|  |     const { imageBroken } = this.state; | ||
|  |     const hasImage = avatarPath && !imageBroken; | ||
|  | 
 | ||
|  |     if (!hasImage) { | ||
|  |       return null; | ||
|  |     } | ||
|  | 
 | ||
|  |     const title = `${name || phoneNumber}${ | ||
|  |       !name && profileName ? ` ~${profileName}` : '' | ||
|  |     }`;
 | ||
|  | 
 | ||
|  |     return ( | ||
|  |       <img | ||
|  |         onError={this.handleImageErrorBound} | ||
|  |         alt={i18n('contactAvatarAlt', [title])} | ||
|  |         src={avatarPath} | ||
|  |       /> | ||
|  |     ); | ||
|  |   } | ||
|  | 
 | ||
|  |   public renderNoImage() { | ||
|  |     const { conversationType, name, size } = this.props; | ||
|  | 
 | ||
|  |     const initials = getInitials(name); | ||
|  |     const isGroup = conversationType === 'group'; | ||
|  | 
 | ||
|  |     if (!isGroup && initials) { | ||
|  |       return ( | ||
|  |         <div | ||
|  |           className={classNames( | ||
|  |             'module-avatar__label', | ||
|  |             `module-avatar__label--${size}` | ||
|  |           )} | ||
|  |         > | ||
|  |           {initials} | ||
|  |         </div> | ||
|  |       ); | ||
|  |     } | ||
|  | 
 | ||
|  |     return ( | ||
|  |       <div | ||
|  |         className={classNames( | ||
|  |           'module-avatar__icon', | ||
|  |           `module-avatar__icon--${conversationType}`, | ||
|  |           `module-avatar__icon--${size}` | ||
|  |         )} | ||
|  |       /> | ||
|  |     ); | ||
|  |   } | ||
|  | 
 | ||
|  |   public render() { | ||
|  |     const { avatarPath, color, size } = this.props; | ||
|  |     const { imageBroken } = this.state; | ||
|  | 
 | ||
|  |     const hasImage = avatarPath && !imageBroken; | ||
|  | 
 | ||
|  |     if (size !== 28 && size !== 36 && size !== 48 && size !== 80) { | ||
|  |       throw new Error(`Size ${size} is not supported!`); | ||
|  |     } | ||
|  | 
 | ||
|  |     return ( | ||
|  |       <div | ||
|  |         className={classNames( | ||
|  |           'module-avatar', | ||
|  |           `module-avatar--${size}`, | ||
|  |           hasImage ? 'module-avatar--with-image' : 'module-avatar--no-image', | ||
|  |           !hasImage ? `module-avatar--${color}` : null | ||
|  |         )} | ||
|  |       > | ||
|  |         {hasImage ? this.renderImage() : this.renderNoImage()} | ||
|  |       </div> | ||
|  |     ); | ||
|  |   } | ||
|  | } |