import * as React from 'react'; import classNames from 'classnames'; import { getInitials } from '../util/getInitials'; import { LocalizerType } from '../types/Util'; import { ColorType } from '../types/Colors'; export type Props = { avatarPath?: string; color?: ColorType; conversationType: 'group' | 'direct'; noteToSelf?: boolean; title: string; name?: string; phoneNumber?: string; profileName?: string; size: 28 | 32 | 52 | 80 | 112; onClick?: () => unknown; // Matches Popper's RefHandler type innerRef?: React.Ref; i18n: LocalizerType; } & Pick, 'className'>; interface State { imageBroken: boolean; lastAvatarPath?: string; } export class Avatar extends React.Component { public handleImageErrorBound: () => void; public constructor(props: Props) { super(props); this.handleImageErrorBound = this.handleImageError.bind(this); this.state = { lastAvatarPath: props.avatarPath, imageBroken: false, }; } public static getDerivedStateFromProps(props: Props, state: State): State { if (props.avatarPath !== state.lastAvatarPath) { return { ...state, lastAvatarPath: props.avatarPath, imageBroken: false, }; } return state; } 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, title } = this.props; const { imageBroken } = this.state; if (!avatarPath || imageBroken) { return null; } return ( {i18n('contactAvatarAlt', ); } public renderNoImage() { const { conversationType, name, noteToSelf, profileName, size, } = this.props; const initials = getInitials(name || profileName); const isGroup = conversationType === 'group'; if (noteToSelf) { return (
); } if (!isGroup && initials) { return (
{initials}
); } return (
); } public render() { const { avatarPath, color, innerRef, noteToSelf, onClick, size, className, } = this.props; const { imageBroken } = this.state; const hasImage = !noteToSelf && avatarPath && !imageBroken; if (![28, 32, 52, 80, 112].includes(size)) { throw new Error(`Size ${size} is not supported!`); } let contents; if (onClick) { contents = ( ); } else { contents = hasImage ? this.renderImage() : this.renderNoImage(); } return (
{contents}
); } }