diff --git a/index.js b/index.js
index b546b82..4333fb3 100644
--- a/index.js
+++ b/index.js
@@ -1,274 +1,377 @@
-import React from 'react';
-import PropTypes from 'prop-types';
+import React from "react";
+import PropTypes from "prop-types";
import {
- StyleSheet,
- View,
- Text,
- TouchableOpacity,
- AppState
-} from 'react-native';
-import _ from 'lodash';
-import {sprintf} from 'sprintf-js';
+ StyleSheet,
+ View,
+ Text,
+ TouchableOpacity,
+ AppState,
+} from "react-native";
+import _ from "lodash";
+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_TIME_TO_SHOW = ['D', 'H', 'M', 'S'];
+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 {
- 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,
- };
-
- constructor(props) {
- super(props);
- this.timer = setInterval(this.updateTimer, 1000);
- }
+ static propTypes = {
+ id: PropTypes.string,
+ digitStyle: PropTypes.object,
+ digitTxtStyle: PropTypes.object,
+ timeLabelStyle: PropTypes.object,
+ doubleDigitslStyle: PropTypes.object,
+ separatorStyle: PropTypes.object,
+ timeToHiddenWhenEqualToZero: PropTypes.object,
+ timeToShow: PropTypes.array,
+ showSeparator: PropTypes.bool,
+ size: PropTypes.number,
+ until: PropTypes.number,
+ onChange: PropTypes.func,
+ onPress: PropTypes.func,
+ onFinish: PropTypes.func,
+ };
- componentDidMount() {
- AppState.addEventListener('change', this._handleAppStateChange);
- }
+ state = {
+ until: Math.max(this.props.until, 0),
+ lastUntil: null,
+ wentBackgroundAt: null,
+ };
- componentWillUnmount() {
- clearInterval(this.timer);
- AppState.removeEventListener('change', this._handleAppStateChange);
- }
+ constructor(props) {
+ super(props);
+ this.timer = setInterval(this.updateTimer, 1000);
+ this.myListener = null;
+ }
- componentDidUpdate(prevProps, prevState) {
- if (this.props.until !== prevProps.until || this.props.id !== prevProps.id) {
- this.setState({
- lastUntil: prevState.until,
- until: Math.max(prevProps.until, 0)
- });
+ componentDidMount() {
+ this.myListener = AppState.addEventListener(
+ "change",
+ this._handleAppStateChange
+ );
}
- }
- // componentWillReceiveProps(nextProps) {
- // if (this.props.until !== nextProps.until || this.props.id !== nextProps.id) {
- // this.setState({
- // lastUntil: this.state.until,
- // until: Math.max(nextProps.until, 0)
- // });
- // }
- // }
- _handleAppStateChange = currentAppState => {
- const {until, wentBackgroundAt} = this.state;
- if (currentAppState === 'active' && wentBackgroundAt && this.props.running) {
- const diff = (Date.now() - wentBackgroundAt) / 1000.0;
- this.setState({
- lastUntil: until,
- until: Math.max(0, until - diff)
- });
+ componentWillUnmount() {
+ clearInterval(this.timer);
+ this.myListener && this.myListener.remove();
}
- if (currentAppState === 'background') {
- this.setState({wentBackgroundAt: Date.now()});
+
+ componentDidUpdate(prevProps, prevState) {
+ if (
+ this.props.until !== prevProps.until ||
+ this.props.id !== prevProps.id
+ ) {
+ this.setState({
+ lastUntil: prevState.until,
+ until: Math.max(prevProps.until, 0),
+ });
+ }
}
- }
+ // componentWillReceiveProps(nextProps) {
+ // if (this.props.until !== nextProps.until || this.props.id !== nextProps.id) {
+ // this.setState({
+ // lastUntil: this.state.until,
+ // until: Math.max(nextProps.until, 0)
+ // });
+ // }
+ // }
- 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),
+ _handleAppStateChange = (currentAppState) => {
+ const { until, wentBackgroundAt } = this.state;
+ if (
+ currentAppState === "active" &&
+ wentBackgroundAt &&
+ this.props.running
+ ) {
+ const diff = (Date.now() - wentBackgroundAt) / 1000.0;
+ this.setState({
+ lastUntil: until,
+ until: Math.max(0, until - diff),
+ });
+ }
+ if (currentAppState === "background") {
+ this.setState({ wentBackgroundAt: Date.now() });
+ }
};
- };
- 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 = () => {
+ // Don't fetch these values here, because their value might be changed
+ // in another thread
+ // const {lastUntil, until} = this.state;
- if (this.state.until === 0) {
- this.setState({lastUntil: 0, until: 0});
- } else {
- if (this.props.onChange) {
- this.props.onChange(this.state.until);
- }
- this.setState({
- lastUntil: this.state.until,
- until: Math.max(0, this.state.until - 1)
- });
- }
- };
+ 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);
+ }
+ }
- renderDigit = (d) => {
- const {digitStyle, digitTxtStyle, size} = this.props;
- return (
-
-
- {d}
-
-
- );
- };
+ if (this.state.until === 0) {
+ this.setState({ lastUntil: 0, until: 0 });
+ } else {
+ if (this.props.onChange) {
+ this.props.onChange(this.state.until);
+ }
+ this.setState({
+ lastUntil: this.state.until,
+ until: Math.max(0, this.state.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}
+
+ );
+ }
+ };
+
+ // Kiểm tra xem co hiển thị timeType (days, hours, minutes, seconds) hay không ?
+ checkTimeToHideen = (digits, timeType, newTime) => {
+ const { timeToHiddenWhenEqualToZero } = this.props;
- renderSeparator = () => {
- const {separatorStyle, size} = this.props;
- return (
-
-
- {':'}
-
-
- );
- };
+ // nếu không có timeToHiddenWhenEqualToZero khỏi cần check
+ if (!timeToHiddenWhenEqualToZero) return false;
+ const days = Number(newTime[0]),
+ hours = Number(newTime[1]),
+ minutes = Number(newTime[2]);
- 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;
+ const objectTime = {
+ D:
+ timeToHiddenWhenEqualToZero?.includes(timeType) &&
+ Number(digits) === 0,
+ H:
+ timeToHiddenWhenEqualToZero?.includes(timeType) &&
+ Number(digits) === 0 &&
+ days === 0, // kiểm tra xem days === 0 thì giờ là lớn nhất có thể ẩn 00:30:30:30
+ M:
+ timeToHiddenWhenEqualToZero?.includes(timeType) &&
+ Number(digits) === 0 &&
+ days === 0 &&
+ hours === 0, // kiểm tra xem days === 0 và hours === 0 thì phút là lớn nhất có thể ẩn 00:00:30:30
+ S:
+ timeToHiddenWhenEqualToZero?.includes(timeType) &&
+ Number(digits) === 0 &&
+ days === 0 &&
+ hours === 0 &&
+ minutes === 0, // kiểm tra xem days === 0 và hours === 0 và minutes === 0 thì giây là lớn nhất có thể ẩn 00:00:00:30
+ };
+ return objectTime[timeType] || false;
+ };
- 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}
-
- );
- };
+ renderDoubleDigits = (label, digits, timeType, newTime) => {
+ const { doubleDigitslStyle } = this.props;
- render() {
- return (
-
- {this.renderCountDown()}
-
- );
- }
+ if (!this.checkTimeToHideen(digits, timeType, newTime)) {
+ return (
+
+
+ {this.renderDigit(digits)}
+
+ {this.renderLabel(label)}
+
+ );
+ }
+ return ;
+ };
+
+ renderSeparator = (digits, timeType, newTime) => {
+ const { separatorStyle, size } = this.props;
+
+ if (!this.checkTimeToHideen(digits, timeType, newTime)) {
+ return (
+
+
+ {":"}
+
+
+ );
+ }
+ return ;
+ };
+
+ renderCountDown = () => {
+ const { timeToShow, timeLabels, showSeparator } = this.props;
+ 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],
+ "D",
+ newTime
+ )
+ : null}
+ {showSeparator &&
+ timeToShow.includes("D") &&
+ timeToShow.includes("H")
+ ? this.renderSeparator(newTime[0], "D", newTime)
+ : null}
+ {timeToShow.includes("H")
+ ? this.renderDoubleDigits(
+ timeLabels.h,
+ newTime[1],
+ "H",
+ newTime
+ )
+ : null}
+ {showSeparator &&
+ timeToShow.includes("H") &&
+ timeToShow.includes("M")
+ ? this.renderSeparator(newTime[1], "H", newTime)
+ : null}
+ {timeToShow.includes("M")
+ ? this.renderDoubleDigits(
+ timeLabels.m,
+ newTime[2],
+ "M",
+ newTime
+ )
+ : null}
+ {showSeparator &&
+ timeToShow.includes("M") &&
+ timeToShow.includes("S")
+ ? this.renderSeparator(newTime[2], "M", newTime)
+ : null}
+ {timeToShow.includes("S")
+ ? this.renderDoubleDigits(
+ timeLabels.s,
+ newTime[3],
+ "S",
+ newTime
+ )
+ : null}
+
+ );
+ };
+
+ 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;