173 lines
4.3 KiB
JavaScript
173 lines
4.3 KiB
JavaScript
// @flow
|
|
import React from 'react';
|
|
import { Animated, Text } from 'react-native';
|
|
|
|
import Icon from '../../icons/components/Icon';
|
|
import { combineStyles, type StyleType } from '../../styles';
|
|
|
|
import AbstractLabel, {
|
|
type Props as AbstractProps
|
|
} from './AbstractLabel';
|
|
import styles from './styles';
|
|
|
|
/**
|
|
* Const for status string 'in progress'.
|
|
*/
|
|
const STATUS_IN_PROGRESS = 'in_progress';
|
|
|
|
/**
|
|
* Const for status string 'off'.
|
|
*/
|
|
const STATUS_OFF = 'off';
|
|
|
|
type Props = AbstractProps & {
|
|
|
|
/**
|
|
* Color for the icon.
|
|
*/
|
|
iconColor?: ?string,
|
|
|
|
/**
|
|
* Status of the label. This prop adds some additional styles based on its
|
|
* value. E.g. If status = off, it will render the label symbolising that
|
|
* the thing it displays (e.g. Recording) is off.
|
|
*/
|
|
status: ('in_progress' | 'off' | 'on'),
|
|
|
|
/**
|
|
* Style of the label.
|
|
*/
|
|
style?: ?StyleType,
|
|
|
|
/**
|
|
* Custom styles for the text.
|
|
*/
|
|
textStyle?: ?StyleType
|
|
};
|
|
|
|
type State = {
|
|
|
|
/**
|
|
* An animation object handling the opacity changes of the in progress
|
|
* label.
|
|
*/
|
|
pulseAnimation: Object
|
|
}
|
|
|
|
/**
|
|
* Renders a circular indicator to be used for status icons, such as recording
|
|
* on, audio-only conference, video quality and similar.
|
|
*/
|
|
export default class Label extends AbstractLabel<Props, State> {
|
|
/**
|
|
* A reference to the started animation of this label.
|
|
*/
|
|
animationReference: Object;
|
|
|
|
/**
|
|
* Instantiates a new instance of {@code Label}.
|
|
*
|
|
* @inheritdoc
|
|
*/
|
|
constructor(props: Props) {
|
|
super(props);
|
|
|
|
this.state = {
|
|
pulseAnimation: new Animated.Value(0)
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Implements {@code Component#componentDidMount}.
|
|
*
|
|
* @inheritdoc
|
|
*/
|
|
componentDidMount() {
|
|
this._maybeToggleAnimation({}, this.props);
|
|
}
|
|
|
|
/**
|
|
* Implements {@code Component#componentDidUpdate}.
|
|
*
|
|
* @inheritdoc
|
|
*/
|
|
componentDidUpdate(prevProps: Props) {
|
|
this._maybeToggleAnimation(prevProps, this.props);
|
|
}
|
|
|
|
/**
|
|
* Implements React {@link Component}'s render.
|
|
*
|
|
* @inheritdoc
|
|
*/
|
|
render() {
|
|
const { icon, text, status, style, iconColor, textStyle } = this.props;
|
|
|
|
let extraStyle = null;
|
|
|
|
switch (status) {
|
|
case STATUS_IN_PROGRESS:
|
|
extraStyle = {
|
|
opacity: this.state.pulseAnimation
|
|
};
|
|
break;
|
|
case STATUS_OFF:
|
|
extraStyle = styles.labelOff;
|
|
break;
|
|
}
|
|
|
|
return (
|
|
<Animated.View
|
|
style = { [
|
|
combineStyles(styles.labelContainer, style),
|
|
extraStyle
|
|
] }>
|
|
{ icon && <Icon
|
|
color = { iconColor }
|
|
size = '18'
|
|
src = { icon } /> }
|
|
{ text && <Text style = { [ styles.labelText, textStyle ] }>
|
|
{ text }
|
|
</Text>}
|
|
</Animated.View>
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Checks if the animation has to be started or stopped and acts
|
|
* accordingly.
|
|
*
|
|
* @param {Props} oldProps - The previous values of the Props.
|
|
* @param {Props} newProps - The new values of the Props.
|
|
* @returns {void}
|
|
*/
|
|
_maybeToggleAnimation(oldProps, newProps) {
|
|
const { status: oldStatus } = oldProps;
|
|
const { status: newStatus } = newProps;
|
|
const { pulseAnimation } = this.state;
|
|
|
|
if (newStatus === STATUS_IN_PROGRESS
|
|
&& oldStatus !== STATUS_IN_PROGRESS) {
|
|
// Animation must be started
|
|
this.animationReference = Animated.loop(Animated.sequence([
|
|
Animated.timing(pulseAnimation, {
|
|
delay: 500,
|
|
toValue: 1,
|
|
useNativeDriver: true
|
|
}),
|
|
Animated.timing(pulseAnimation, {
|
|
toValue: 0.3,
|
|
useNativeDriver: true
|
|
})
|
|
]));
|
|
|
|
this.animationReference.start();
|
|
} else if (this.animationReference
|
|
&& newStatus !== STATUS_IN_PROGRESS
|
|
&& oldStatus === STATUS_IN_PROGRESS) {
|
|
// Animation must be stopped
|
|
this.animationReference.stop();
|
|
}
|
|
}
|
|
}
|