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.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. // @flow
  2. import React from 'react';
  3. import { translate } from '../../../../base/i18n';
  4. import { Icon } from '../../../icons';
  5. import AbstractStatelessAvatar, { type Props as AbstractProps } from '../AbstractStatelessAvatar';
  6. type Props = AbstractProps & {
  7. /**
  8. * External class name passed through props.
  9. */
  10. className?: string,
  11. /**
  12. * The default avatar URL if we want to override the app bundled one (e.g. AlwaysOnTop)
  13. */
  14. defaultAvatar?: string,
  15. /**
  16. * ID of the component to be rendered.
  17. */
  18. id?: string,
  19. /**
  20. * One of the expected status strings (e.g. 'available') to render a badge on the avatar, if necessary.
  21. */
  22. status?: ?string,
  23. /**
  24. * TestId of the element, if any.
  25. */
  26. testId?: string,
  27. /**
  28. * Invoked to obtain translated strings.
  29. */
  30. t: Function
  31. };
  32. /**
  33. * Implements a stateless avatar component that renders an avatar purely from what gets passed through
  34. * props.
  35. */
  36. class StatelessAvatar extends AbstractStatelessAvatar<Props> {
  37. /**
  38. * Implements {@code Component#render}.
  39. *
  40. * @inheritdoc
  41. */
  42. render() {
  43. const { initials, url } = this.props;
  44. if (this._isIcon(url)) {
  45. return (
  46. <div
  47. className = { `${this._getAvatarClassName()} ${this._getBadgeClassName()}` }
  48. data-testid = { this.props.testId }
  49. id = { this.props.id }
  50. style = { this._getAvatarStyle(this.props.color) }>
  51. <Icon
  52. size = '50%'
  53. src = { url } />
  54. </div>
  55. );
  56. }
  57. if (url) {
  58. return (
  59. <div className = { this._getBadgeClassName() }>
  60. <img
  61. alt = { this.props.t('profile.avatar') }
  62. className = { this._getAvatarClassName() }
  63. data-testid = { this.props.testId }
  64. id = { this.props.id }
  65. onError = { this.props.onAvatarLoadError }
  66. src = { url }
  67. style = { this._getAvatarStyle() } />
  68. </div>
  69. );
  70. }
  71. if (initials) {
  72. return (
  73. <div
  74. className = { `${this._getAvatarClassName()} ${this._getBadgeClassName()}` }
  75. data-testid = { this.props.testId }
  76. id = { this.props.id }
  77. style = { this._getAvatarStyle(this.props.color) }>
  78. <svg
  79. className = 'avatar-svg'
  80. viewBox = '0 0 100 100'
  81. xmlns = 'http://www.w3.org/2000/svg'
  82. xmlnsXlink = 'http://www.w3.org/1999/xlink'>
  83. <text
  84. dominantBaseline = 'central'
  85. fill = 'rgba(255,255,255,1)'
  86. fontSize = '40pt'
  87. textAnchor = 'middle'
  88. x = '50'
  89. y = '50'>
  90. { initials }
  91. </text>
  92. </svg>
  93. </div>
  94. );
  95. }
  96. // default avatar
  97. return (
  98. <div className = { this._getBadgeClassName() }>
  99. <img
  100. alt = { this.props.t('profile.avatar') }
  101. className = { this._getAvatarClassName('defaultAvatar') }
  102. data-testid = { this.props.testId }
  103. id = { this.props.id }
  104. src = { this.props.defaultAvatar || 'images/avatar.png' }
  105. style = { this._getAvatarStyle() } />
  106. </div>
  107. );
  108. }
  109. /**
  110. * Constructs a style object to be used on the avatars.
  111. *
  112. * @param {string?} color - The desired background color.
  113. * @returns {Object}
  114. */
  115. _getAvatarStyle(color) {
  116. const { size } = this.props;
  117. return {
  118. backgroundColor: color || undefined,
  119. fontSize: size ? size * 0.5 : '180%',
  120. height: size || '100%',
  121. width: size || '100%'
  122. };
  123. }
  124. /**
  125. * Constructs a list of class names required for the avatar component.
  126. *
  127. * @param {string} additional - Any additional class to add.
  128. * @returns {string}
  129. */
  130. _getAvatarClassName(additional) {
  131. return `avatar ${additional || ''} ${this.props.className || ''}`;
  132. }
  133. /**
  134. * Generates a class name to render a badge on the avatar, if necessary.
  135. *
  136. * @returns {string}
  137. */
  138. _getBadgeClassName() {
  139. const { status } = this.props;
  140. if (status) {
  141. return `avatar-badge avatar-badge-${status}`;
  142. }
  143. return '';
  144. }
  145. _isIcon: (?string | ?Object) => boolean
  146. }
  147. export default translate(StatelessAvatar);