198 lines
4.7 KiB
JavaScript
198 lines
4.7 KiB
JavaScript
// @flow
|
|
|
|
import React from 'react';
|
|
import { Image, Text, View } from 'react-native';
|
|
|
|
import { Icon } from '../../../icons';
|
|
import { type StyleType } from '../../../styles';
|
|
import AbstractStatelessAvatar, { type IProps as AbstractProps } from '../AbstractStatelessAvatar';
|
|
|
|
import styles from './styles';
|
|
|
|
const DEFAULT_AVATAR = require('../../../../../../images/avatar.png');
|
|
|
|
type Props = AbstractProps & {
|
|
|
|
/**
|
|
* One of the expected status strings (e.g. 'available') to render a badge on the avatar, if necessary.
|
|
*/
|
|
status?: ?string,
|
|
|
|
/**
|
|
* External style passed to the component.
|
|
*/
|
|
style?: StyleType
|
|
};
|
|
|
|
/**
|
|
* Implements a stateless avatar component that renders an avatar purely from what gets passed through
|
|
* props.
|
|
*/
|
|
export default class StatelessAvatar extends AbstractStatelessAvatar<Props> {
|
|
|
|
/**
|
|
* Instantiates a new {@code Component}.
|
|
*
|
|
* @inheritdoc
|
|
*/
|
|
constructor(props: Props) {
|
|
super(props);
|
|
|
|
this._onAvatarLoadError = this._onAvatarLoadError.bind(this);
|
|
}
|
|
|
|
/**
|
|
* Implements {@code Component#render}.
|
|
*
|
|
* @inheritdoc
|
|
*/
|
|
render() {
|
|
const { initials, size, style, url } = this.props;
|
|
|
|
let avatar;
|
|
|
|
if (this._isIcon(url)) {
|
|
avatar = this._renderIconAvatar(url);
|
|
} else if (url) {
|
|
avatar = this._renderURLAvatar();
|
|
} else if (initials) {
|
|
avatar = this._renderInitialsAvatar();
|
|
} else {
|
|
avatar = this._renderDefaultAvatar();
|
|
}
|
|
|
|
return (
|
|
<View>
|
|
<View
|
|
style = { [
|
|
styles.avatarContainer(size),
|
|
style
|
|
] }>
|
|
{ avatar }
|
|
</View>
|
|
{ this._renderAvatarStatus() }
|
|
</View>
|
|
);
|
|
}
|
|
|
|
_isIcon: (?string | ?Object) => boolean;
|
|
|
|
/**
|
|
* Renders a badge representing the avatar status.
|
|
*
|
|
* @returns {React$Elementaa}
|
|
*/
|
|
_renderAvatarStatus() {
|
|
const { size, status } = this.props;
|
|
|
|
if (!status) {
|
|
return null;
|
|
}
|
|
|
|
return (
|
|
<View style = { styles.badgeContainer }>
|
|
<View style = { styles.badge(size, status) } />
|
|
</View>
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Renders the default avatar.
|
|
*
|
|
* @returns {React$Element<*>}
|
|
*/
|
|
_renderDefaultAvatar() {
|
|
const { size } = this.props;
|
|
|
|
return (
|
|
<Image
|
|
source = { DEFAULT_AVATAR }
|
|
style = { [
|
|
styles.avatarContent(size),
|
|
styles.staticAvatar
|
|
] } />
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Renders the icon avatar.
|
|
*
|
|
* @param {Object} icon - The icon component to render.
|
|
* @returns {React$Element<*>}
|
|
*/
|
|
_renderIconAvatar(icon) {
|
|
const { color, size } = this.props;
|
|
|
|
return (
|
|
<View
|
|
style = { [
|
|
styles.initialsContainer,
|
|
{
|
|
backgroundColor: color
|
|
}
|
|
] }>
|
|
<Icon
|
|
src = { icon }
|
|
style = { styles.initialsText(size) } />
|
|
</View>
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Renders the initials-based avatar.
|
|
*
|
|
* @returns {React$Element<*>}
|
|
*/
|
|
_renderInitialsAvatar() {
|
|
const { color, initials, size } = this.props;
|
|
|
|
return (
|
|
<View
|
|
style = { [
|
|
styles.initialsContainer,
|
|
{
|
|
backgroundColor: color
|
|
}
|
|
] }>
|
|
<Text style = { styles.initialsText(size) }> { initials } </Text>
|
|
</View>
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Renders the url-based avatar.
|
|
*
|
|
* @returns {React$Element<*>}
|
|
*/
|
|
_renderURLAvatar() {
|
|
const { onAvatarLoadError, size, url } = this.props;
|
|
|
|
return (
|
|
<Image
|
|
defaultSource = { DEFAULT_AVATAR }
|
|
onError = { onAvatarLoadError }
|
|
resizeMode = 'cover'
|
|
source = {{ uri: url }}
|
|
style = { styles.avatarContent(size) } />
|
|
);
|
|
}
|
|
|
|
_onAvatarLoadError: () => void;
|
|
|
|
/**
|
|
* Handles avatar load errors.
|
|
*
|
|
* @returns {void}
|
|
*/
|
|
_onAvatarLoadError() {
|
|
const { onAvatarLoadError, onAvatarLoadErrorParams = {} } = this.props;
|
|
|
|
if (onAvatarLoadError) {
|
|
onAvatarLoadError({
|
|
...onAvatarLoadErrorParams,
|
|
dontRetry: true
|
|
});
|
|
}
|
|
}
|
|
}
|