You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

StatelessAvatar.js 4.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. // @flow
  2. import React from 'react';
  3. import { Image, Text, View } from 'react-native';
  4. import { Icon } from '../../../icons';
  5. import { type StyleType } from '../../../styles';
  6. import AbstractStatelessAvatar, { type Props as AbstractProps } from '../AbstractStatelessAvatar';
  7. import styles from './styles';
  8. const DEFAULT_AVATAR = require('../../../../../../images/avatar.png');
  9. type Props = AbstractProps & {
  10. /**
  11. * One of the expected status strings (e.g. 'available') to render a badge on the avatar, if necessary.
  12. */
  13. status?: ?string,
  14. /**
  15. * External style passed to the component.
  16. */
  17. style?: StyleType
  18. };
  19. /**
  20. * Implements a stateless avatar component that renders an avatar purely from what gets passed through
  21. * props.
  22. */
  23. export default class StatelessAvatar extends AbstractStatelessAvatar<Props> {
  24. /**
  25. * Instantiates a new {@code Component}.
  26. *
  27. * @inheritdoc
  28. */
  29. constructor(props: Props) {
  30. super(props);
  31. this._onAvatarLoadError = this._onAvatarLoadError.bind(this);
  32. }
  33. /**
  34. * Implements {@code Component#render}.
  35. *
  36. * @inheritdoc
  37. */
  38. render() {
  39. const { initials, size, style, url } = this.props;
  40. let avatar;
  41. if (this._isIcon(url)) {
  42. avatar = this._renderIconAvatar(url);
  43. } else if (url) {
  44. avatar = this._renderURLAvatar();
  45. } else if (initials) {
  46. avatar = this._renderInitialsAvatar();
  47. } else {
  48. avatar = this._renderDefaultAvatar();
  49. }
  50. return (
  51. <View>
  52. <View
  53. style = { [
  54. styles.avatarContainer(size),
  55. style
  56. ] }>
  57. { avatar }
  58. </View>
  59. { this._renderAvatarStatus() }
  60. </View>
  61. );
  62. }
  63. _isIcon: (?string | ?Object) => boolean;
  64. /**
  65. * Renders a badge representing the avatar status.
  66. *
  67. * @returns {React$Elementaa}
  68. */
  69. _renderAvatarStatus() {
  70. const { size, status } = this.props;
  71. if (!status) {
  72. return null;
  73. }
  74. return (
  75. <View style = { styles.badgeContainer }>
  76. <View style = { styles.badge(size, status) } />
  77. </View>
  78. );
  79. }
  80. /**
  81. * Renders the default avatar.
  82. *
  83. * @returns {React$Element<*>}
  84. */
  85. _renderDefaultAvatar() {
  86. const { size } = this.props;
  87. return (
  88. <Image
  89. source = { DEFAULT_AVATAR }
  90. style = { [
  91. styles.avatarContent(size),
  92. styles.staticAvatar
  93. ] } />
  94. );
  95. }
  96. /**
  97. * Renders the icon avatar.
  98. *
  99. * @param {Object} icon - The icon component to render.
  100. * @returns {React$Element<*>}
  101. */
  102. _renderIconAvatar(icon) {
  103. const { color, size } = this.props;
  104. return (
  105. <View
  106. style = { [
  107. styles.initialsContainer,
  108. {
  109. backgroundColor: color
  110. }
  111. ] }>
  112. <Icon
  113. src = { icon }
  114. style = { styles.initialsText(size) } />
  115. </View>
  116. );
  117. }
  118. /**
  119. * Renders the initials-based avatar.
  120. *
  121. * @returns {React$Element<*>}
  122. */
  123. _renderInitialsAvatar() {
  124. const { color, initials, size } = this.props;
  125. return (
  126. <View
  127. style = { [
  128. styles.initialsContainer,
  129. {
  130. backgroundColor: color
  131. }
  132. ] }>
  133. <Text style = { styles.initialsText(size) }> { initials } </Text>
  134. </View>
  135. );
  136. }
  137. /**
  138. * Renders the url-based avatar.
  139. *
  140. * @returns {React$Element<*>}
  141. */
  142. _renderURLAvatar() {
  143. const { onAvatarLoadError, size, url } = this.props;
  144. return (
  145. <Image
  146. defaultSource = { DEFAULT_AVATAR }
  147. onError = { onAvatarLoadError }
  148. resizeMode = 'cover'
  149. source = {{ uri: url }}
  150. style = { styles.avatarContent(size) } />
  151. );
  152. }
  153. _onAvatarLoadError: () => void;
  154. /**
  155. * Handles avatar load errors.
  156. *
  157. * @returns {void}
  158. */
  159. _onAvatarLoadError() {
  160. const { onAvatarLoadError, onAvatarLoadErrorParams = {} } = this.props;
  161. if (onAvatarLoadError) {
  162. onAvatarLoadError({
  163. ...onAvatarLoadErrorParams,
  164. dontRetry: true
  165. });
  166. }
  167. }
  168. }