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.

Label.tsx 4.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. import React, { Component } from 'react';
  2. import { Animated, Text, ViewStyle } from 'react-native';
  3. import Icon from '../../../icons/components/Icon';
  4. import { StyleType, combineStyles } from '../../../styles/functions.native';
  5. import styles from './styles';
  6. /**
  7. * Const for status string 'in progress'.
  8. */
  9. const STATUS_IN_PROGRESS = 'in_progress';
  10. /**
  11. * Const for status string 'off'.
  12. */
  13. const STATUS_OFF = 'off';
  14. interface IProps {
  15. /**
  16. * An SVG icon to be rendered as the content of the label.
  17. */
  18. icon?: Function;
  19. /**
  20. * Color for the icon.
  21. */
  22. iconColor?: string;
  23. /**
  24. * Status of the label. This prop adds some additional styles based on its
  25. * value. E.g. If status = off, it will render the label symbolising that
  26. * the thing it displays (e.g. Recording) is off.
  27. */
  28. status?: 'in_progress' | 'off' | 'on';
  29. /**
  30. * Style of the label.
  31. */
  32. style?: StyleType;
  33. /**
  34. * String or component that will be rendered as the label itself.
  35. */
  36. text?: string;
  37. /**
  38. * Custom styles for the text.
  39. */
  40. textStyle?: StyleType;
  41. }
  42. type State = {
  43. /**
  44. * An animation object handling the opacity changes of the in progress
  45. * label.
  46. */
  47. pulseAnimation: Animated.Value;
  48. };
  49. /**
  50. * Renders a circular indicator to be used for status icons, such as recording
  51. * on, audio-only conference, video quality and similar.
  52. */
  53. export default class Label extends Component<IProps, State> {
  54. /**
  55. * A reference to the started animation of this label.
  56. */
  57. animationReference: Animated.CompositeAnimation;
  58. /**
  59. * Instantiates a new instance of {@code Label}.
  60. *
  61. * @inheritdoc
  62. */
  63. constructor(props: IProps) {
  64. super(props);
  65. this.state = {
  66. pulseAnimation: new Animated.Value(0)
  67. };
  68. }
  69. /**
  70. * Implements {@code Component#componentDidMount}.
  71. *
  72. * @inheritdoc
  73. */
  74. componentDidMount() {
  75. this._maybeToggleAnimation({}, this.props);
  76. }
  77. /**
  78. * Implements {@code Component#componentDidUpdate}.
  79. *
  80. * @inheritdoc
  81. */
  82. componentDidUpdate(prevProps: IProps) {
  83. this._maybeToggleAnimation(prevProps, this.props);
  84. }
  85. /**
  86. * Implements React {@link Component}'s render.
  87. *
  88. * @inheritdoc
  89. */
  90. render() {
  91. const { icon, text, status, style, iconColor, textStyle } = this.props;
  92. let extraStyle = null;
  93. switch (status) {
  94. case STATUS_IN_PROGRESS:
  95. extraStyle = {
  96. opacity: this.state.pulseAnimation
  97. };
  98. break;
  99. case STATUS_OFF:
  100. extraStyle = styles.labelOff;
  101. break;
  102. }
  103. return (
  104. <Animated.View
  105. style = { [
  106. combineStyles(styles.labelContainer, style ?? {}),
  107. extraStyle as ViewStyle
  108. ] }>
  109. { icon && <Icon
  110. color = { iconColor }
  111. size = '18'
  112. src = { icon } /> }
  113. { text && <Text style = { [ styles.labelText, textStyle ] }>
  114. { text }
  115. </Text>}
  116. </Animated.View>
  117. );
  118. }
  119. /**
  120. * Checks if the animation has to be started or stopped and acts
  121. * accordingly.
  122. *
  123. * @param {IProps} oldProps - The previous values of the Props.
  124. * @param {IProps} newProps - The new values of the Props.
  125. * @returns {void}
  126. */
  127. _maybeToggleAnimation(oldProps: Partial<IProps>, newProps: IProps) {
  128. const { status: oldStatus } = oldProps;
  129. const { status: newStatus } = newProps;
  130. const { pulseAnimation } = this.state;
  131. if (newStatus === STATUS_IN_PROGRESS
  132. && oldStatus !== STATUS_IN_PROGRESS) {
  133. // Animation must be started
  134. this.animationReference = Animated.loop(Animated.sequence([
  135. Animated.timing(pulseAnimation, {
  136. delay: 500,
  137. toValue: 1,
  138. useNativeDriver: true
  139. }),
  140. Animated.timing(pulseAnimation, {
  141. toValue: 0.3,
  142. useNativeDriver: true
  143. })
  144. ]));
  145. this.animationReference.start();
  146. } else if (this.animationReference
  147. && newStatus !== STATUS_IN_PROGRESS
  148. && oldStatus === STATUS_IN_PROGRESS) {
  149. // Animation must be stopped
  150. this.animationReference.stop();
  151. }
  152. }
  153. }