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.native.js 4.1KB

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