diff --git a/index.js(1) b/index.js(1) index d3cb4b5..3ba107c 100644 --- a/index.js(1) +++ b/index.js(1) @@ -1,57 +1,51 @@ import React from 'react'; import PropTypes from 'prop-types'; -import { - StyleSheet, - View, - Text, - TouchableOpacity, - AppState -} from 'react-native'; +import { StyleSheet, View, Text, TouchableOpacity, AppState } from 'react-native'; import _ from 'lodash'; -import {sprintf} from 'sprintf-js'; +import { sprintf } from 'sprintf-js'; -const DEFAULT_DIGIT_STYLE = {backgroundColor: '#FAB913'}; -const DEFAULT_DIGIT_TXT_STYLE = {color: '#000'}; -const DEFAULT_TIME_LABEL_STYLE = {color: '#000'}; -const DEFAULT_SEPARATOR_STYLE = {color: '#000'}; +const DEFAULT_DIGIT_STYLE = { backgroundColor: '#FAB913' }; +const DEFAULT_DIGIT_TXT_STYLE = { color: '#000' }; +const DEFAULT_TIME_LABEL_STYLE = { color: '#000' }; +const DEFAULT_SEPARATOR_STYLE = { color: '#000' }; const DEFAULT_TIME_TO_SHOW = ['D', 'H', 'M', 'S']; const DEFAULT_TIME_LABELS = { - d: 'Days', - h: 'Hours', - m: 'Minutes', - s: 'Seconds', + d: 'Days', + h: 'Hours', + m: 'Minutes', + s: 'Seconds', }; class CountDown extends React.Component { - _isMounted = false; - static propTypes = { - id: PropTypes.string, - digitStyle: PropTypes.object, - digitTxtStyle: PropTypes.object, - timeLabelStyle: PropTypes.object, - separatorStyle: PropTypes.object, - timeToShow: PropTypes.array, - showSeparator: PropTypes.bool, - size: PropTypes.number, - until: PropTypes.number, - onChange: PropTypes.func, - onPress: PropTypes.func, - onFinish: PropTypes.func, - }; + _isMounted = false; + static propTypes = { + id: PropTypes.string, + digitStyle: PropTypes.object, + digitTxtStyle: PropTypes.object, + timeLabelStyle: PropTypes.object, + separatorStyle: PropTypes.object, + timeToShow: PropTypes.array, + showSeparator: PropTypes.bool, + size: PropTypes.number, + until: PropTypes.number, + onChange: PropTypes.func, + onPress: PropTypes.func, + onFinish: PropTypes.func, + }; - state = { - until: Math.max(this.props.until, 0), - lastUntil: null, - wentBackgroundAt: null, - }; + state = { + until: Math.max(this.props.until, 0), + lastUntil: null, + wentBackgroundAt: null, + }; - constructor(props) { - super(props); - this.timer = setInterval(this.updateTimer, 1000); - } + constructor(props) { + super(props); + this.timer = setInterval(this.updateTimer, 1000); + } - componentDidMount() { + componentDidMount() { this._isMounted = true; AppState.addEventListener('change', this._handleAppStateChange); } @@ -72,8 +66,8 @@ class CountDown extends React.Component { } } } - -_handleAppStateChange = currentAppState => { + + _handleAppStateChange = currentAppState => { const { until, wentBackgroundAt } = this.state; if (currentAppState === 'active' && wentBackgroundAt && this.props.running) { const diff = (Date.now() - wentBackgroundAt) / 1000.0; @@ -91,191 +85,160 @@ _handleAppStateChange = currentAppState => { } }; - getTimeLeft = () => { - const {until} = this.state; - return { - seconds: until % 60, - minutes: parseInt(until / 60, 10) % 60, - hours: parseInt(until / (60 * 60), 10) % 24, - days: parseInt(until / (60 * 60 * 24), 10), - }; - }; - - updateTimer = () => { - // Don't fetch these values here, because their value might be changed - // in another thread - // const {lastUntil, until} = this.state; + getTimeLeft = () => { + const { until } = this.state; + return { + seconds: until % 60, + minutes: parseInt(until / 60, 10) % 60, + hours: parseInt(until / (60 * 60), 10) % 24, + days: parseInt(until / (60 * 60 * 24), 10), + }; + }; - if (this.state.lastUntil === this.state.until || !this.props.running) { - return; - } - if (this.state.until === 1 || (this.state.until === 0 && this.state.lastUntil !== 1)) { - if (this.props.onFinish) { - this.props.onFinish(); - } - if (this.props.onChange) { - this.props.onChange(this.state.until); - } - } + updateTimer = () => { + const { lastUntil, until } = this.state; - if (this.state.until === 0) { - if (this._isMounted) { - this.setState({lastUntil: 0, until: 0}); - } - } else { - if (this.props.onChange) { - this.props.onChange(this.state.until); - } - if (this._isMounted) { - this.setState({ - lastUntil: this.state.until, - until: Math.max(0, this.state.until - 1) - }); - }; - } - }; + if (lastUntil === until || !this.props.running) { + return; + } + if (until === 1 || (until === 0 && lastUntil !== 1)) { + if (this.props.onFinish) { + this.props.onFinish(); + } + if (this.props.onChange) { + this.props.onChange(until); + } + } - renderDigit = (d) => { - const {digitStyle, digitTxtStyle, size} = this.props; - return ( - - - {d} - - - ); - }; + if (until === 0) { + if (this._isMounted) { + this.setState({ lastUntil: 0, until: 0 }); + } + } else { + if (this.props.onChange) { + this.props.onChange(until); + } + if (this._isMounted) { + this.setState({ + lastUntil: until, + until: Math.max(0, until - 1), + }); + } + } + }; - renderLabel = label => { - const {timeLabelStyle, size} = this.props; - if (label) { - return ( - - {label} - - ); - } - }; + renderDigit = d => { + const { digitStyle, digitTxtStyle, size } = this.props; + return ( + + {d} + + ); + }; - renderDoubleDigits = (label, digits) => { - return ( - - - {this.renderDigit(digits)} - - {this.renderLabel(label)} - - ); - }; + renderLabel = label => { + const { timeLabelStyle, size } = this.props; + if (label) { + return {label}; + } + }; - renderSeparator = () => { - const {separatorStyle, size} = this.props; - return ( - - - {':'} - - - ); - }; + renderDoubleDigits = (label, digits) => { + return ( + + {this.renderDigit(digits)} + {this.renderLabel(label)} + + ); + }; - renderCountDown = () => { - const {timeToShow, timeLabels, showSeparator} = this.props; - const {until} = this.state; - const {days, hours, minutes, seconds} = this.getTimeLeft(); - const newTime = sprintf('%02d:%02d:%02d:%02d', days, hours, minutes, seconds).split(':'); - const Component = this.props.onPress ? TouchableOpacity : View; + renderSeparator = () => { + const { separatorStyle, size } = this.props; + return ( + + {':'} + + ); + }; - return ( - - {timeToShow.includes('D') ? this.renderDoubleDigits(timeLabels.d, newTime[0]) : null} - {showSeparator && timeToShow.includes('D') && timeToShow.includes('H') ? this.renderSeparator() : null} - {timeToShow.includes('H') ? this.renderDoubleDigits(timeLabels.h, newTime[1]) : null} - {showSeparator && timeToShow.includes('H') && timeToShow.includes('M') ? this.renderSeparator() : null} - {timeToShow.includes('M') ? this.renderDoubleDigits(timeLabels.m, newTime[2]) : null} - {showSeparator && timeToShow.includes('M') && timeToShow.includes('S') ? this.renderSeparator() : null} - {timeToShow.includes('S') ? this.renderDoubleDigits(timeLabels.s, newTime[3]) : null} - - ); - }; + renderCountDown = () => { + const { timeToShow, timeLabels, showSeparator } = this.props; + const { until } = this.state; + const { days, hours, minutes, seconds } = this.getTimeLeft(); + const newTime = sprintf('%02d:%02d:%02d:%02d', days, hours, minutes, seconds).split(':'); + const Component = this.props.onPress ? TouchableOpacity : View; + + return ( + + {timeToShow.includes('D') ? this.renderDoubleDigits(timeLabels.d, newTime[0]) : null} + {showSeparator && timeToShow.includes('D') && timeToShow.includes('H') + ? this.renderSeparator() + : null} + {timeToShow.includes('H') ? this.renderDoubleDigits(timeLabels.h, newTime[1]) : null} + {showSeparator && timeToShow.includes('H') && timeToShow.includes('M') + ? this.renderSeparator() + : null} + {timeToShow.includes('M') ? this.renderDoubleDigits(timeLabels.m, newTime[2]) : null} + {showSeparator && timeToShow.includes('M') && timeToShow.includes('S') + ? this.renderSeparator() + : null} + {timeToShow.includes('S') ? this.renderDoubleDigits(timeLabels.s, newTime[3]) : null} + + ); + }; - render() { - return ( - - {this.renderCountDown()} - - ); - } + render() { + return {this.renderCountDown()}; + } } CountDown.defaultProps = { - digitStyle: DEFAULT_DIGIT_STYLE, - digitTxtStyle: DEFAULT_DIGIT_TXT_STYLE, - timeLabelStyle: DEFAULT_TIME_LABEL_STYLE, - timeLabels: DEFAULT_TIME_LABELS, - separatorStyle: DEFAULT_SEPARATOR_STYLE, - timeToShow: DEFAULT_TIME_TO_SHOW, - showSeparator: false, - until: 0, - size: 15, - running: true, + digitStyle: DEFAULT_DIGIT_STYLE, + digitTxtStyle: DEFAULT_DIGIT_TXT_STYLE, + timeLabelStyle: DEFAULT_TIME_LABEL_STYLE, + timeLabels: DEFAULT_TIME_LABELS, + separatorStyle: DEFAULT_SEPARATOR_STYLE, + timeToShow: DEFAULT_TIME_TO_SHOW, + showSeparator: false, + until: 0, + size: 15, + running: true, }; const styles = StyleSheet.create({ - timeCont: { - flexDirection: 'row', - justifyContent: 'center', - }, - timeTxt: { - color: 'white', - marginVertical: 2, - backgroundColor: 'transparent', - }, - timeInnerCont: { - flexDirection: 'row', - justifyContent: 'center', - alignItems: 'center', - }, - digitCont: { - borderRadius: 5, - marginHorizontal: 2, - alignItems: 'center', - justifyContent: 'center', - }, - doubleDigitCont: { - justifyContent: 'center', - alignItems: 'center', - }, - digitTxt: { - color: 'white', - fontWeight: 'bold', - fontVariant: ['tabular-nums'] - }, - separatorTxt: { - backgroundColor: 'transparent', - fontWeight: 'bold', - }, + timeCont: { + flexDirection: 'row', + justifyContent: 'center', + }, + timeTxt: { + color: 'white', + marginVertical: 2, + backgroundColor: 'transparent', + }, + timeInnerCont: { + flexDirection: 'row', + justifyContent: 'center', + alignItems: 'center', + }, + digitCont: { + borderRadius: 5, + marginHorizontal: 2, + alignItems: 'center', + justifyContent: 'center', + }, + doubleDigitCont: { + justifyContent: 'center', + alignItems: 'center', + }, + digitTxt: { + color: 'white', + fontWeight: 'bold', + fontVariant: ['tabular-nums'], + }, + separatorTxt: { + backgroundColor: 'transparent', + fontWeight: 'bold', + }, }); - -export default CountDown; -export { CountDown }; +module.exports = CountDown;