您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

StatelessAvatar.tsx 4.8KB

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