1
0
mirror of https://github.com/kremalicious/metamask-extension.git synced 2024-11-30 16:18:07 +01:00
metamask-extension/ui/pages/swaps/countdown-timer/countdown-timer.js

123 lines
3.7 KiB
JavaScript
Raw Normal View History

import React, { useState, useEffect, useContext, useRef } from 'react';
import { useSelector } from 'react-redux';
import PropTypes from 'prop-types';
import classnames from 'classnames';
import { Duration } from 'luxon';
import { I18nContext } from '../../../contexts/i18n';
import InfoTooltip from '../../../components/ui/info-tooltip';
import { getSwapsQuoteRefreshTime } from '../../../ducks/swaps/swaps';
import { SECOND } from '../../../../shared/constants/time';
import TimerIcon from './timer-icon';
2020-10-06 20:28:38 +02:00
// Return the mm:ss start time of the countdown timer.
// If time has elapsed between `timeStarted` the time current time,
// then that elapsed time will be subtracted from the timer before
// rendering
2020-11-03 00:41:28 +01:00
function getNewTimer(currentTime, timeStarted, timeBaseStart) {
const timeAlreadyElapsed = currentTime - timeStarted;
return timeBaseStart - timeAlreadyElapsed;
2020-10-06 20:28:38 +02:00
}
2020-11-03 00:41:28 +01:00
function decreaseTimerByOne(timer) {
return Math.max(timer - SECOND, 0);
2020-10-06 20:28:38 +02:00
}
2020-11-03 00:41:28 +01:00
function timeBelowWarningTime(timer, warningTime) {
const [warningTimeMinutes, warningTimeSeconds] = warningTime.split(':');
2020-11-03 00:41:28 +01:00
return (
timer <=
(Number(warningTimeMinutes) * 60 + Number(warningTimeSeconds)) * SECOND
);
2020-10-06 20:28:38 +02:00
}
2020-11-03 00:41:28 +01:00
export default function CountdownTimer({
2020-10-06 20:28:38 +02:00
timeStarted,
timeOnly,
timerBase,
2020-10-06 20:28:38 +02:00
warningTime,
labelKey,
infoTooltipLabelKey,
}) {
const t = useContext(I18nContext);
const intervalRef = useRef();
const initialTimeStartedRef = useRef();
2020-10-06 20:28:38 +02:00
const swapsQuoteRefreshTime = useSelector(getSwapsQuoteRefreshTime);
const timerStart = Number(timerBase) || swapsQuoteRefreshTime;
const [currentTime, setCurrentTime] = useState(() => Date.now());
2020-11-03 00:41:28 +01:00
const [timer, setTimer] = useState(() =>
getNewTimer(currentTime, timeStarted, timerStart),
);
2020-10-06 20:28:38 +02:00
useEffect(() => {
if (intervalRef.current === undefined) {
intervalRef.current = setInterval(() => {
setTimer(decreaseTimerByOne);
}, SECOND);
2020-10-06 20:28:38 +02:00
}
2020-11-03 00:41:28 +01:00
return function cleanup() {
clearInterval(intervalRef.current);
};
}, []);
2020-10-06 20:28:38 +02:00
// Reset the timer that timer has hit '0:00' and the timeStarted prop has changed
useEffect(() => {
if (!initialTimeStartedRef.current) {
initialTimeStartedRef.current = timeStarted || Date.now();
2020-10-06 20:28:38 +02:00
}
if (timer === 0 && timeStarted !== initialTimeStartedRef.current) {
initialTimeStartedRef.current = timeStarted;
const newCurrentTime = Date.now();
setCurrentTime(newCurrentTime);
setTimer(getNewTimer(newCurrentTime, timeStarted, timerStart));
2020-10-06 20:28:38 +02:00
clearInterval(intervalRef.current);
2020-10-06 20:28:38 +02:00
intervalRef.current = setInterval(() => {
setTimer(decreaseTimerByOne);
}, SECOND);
2020-10-06 20:28:38 +02:00
}
}, [timeStarted, timer, timerStart]);
2020-10-06 20:28:38 +02:00
const formattedTimer = Duration.fromMillis(timer).toFormat('m:ss');
let time;
2020-10-06 20:28:38 +02:00
if (timeOnly) {
time = <div className="countdown-timer__time">{formattedTimer}</div>;
2020-10-06 20:28:38 +02:00
} else if (labelKey) {
2020-11-03 00:41:28 +01:00
time = t(labelKey, [
<div key="countdown-time-1" className="countdown-timer__time">
{formattedTimer}
</div>,
]);
2020-10-06 20:28:38 +02:00
}
return (
<div className="countdown-timer">
<div
Increase Jest unit test coverage for the Swaps feature to ~25% (#10900) * Swaps: Show a network name dynamically in a tooltip * Replace “Ethereum” with “$1”, change “Test” to “Testnet” * Replace 이더리움 with $1 * Translate network names, use ‘Ethereum’ by default if a translation is not available yet * Reorder messages to resolve ESLint issues * Add a snapshot test for the FeeCard component, increase Jest threshold * Enable snapshot testing into external .snap files in ESLint * Add the “networkNameEthereum” key in ko/messages.json, remove default “Ethereum” value * Throw an error if chain ID is not supported by the Swaps feature * Use string literals when calling the `t` fn, * Watch Jest tests silently (no React warnings in terminal, only errors) * Add @testing-library/jest-dom, import it before running Jest tests * Add snapshot testing of Swaps’ React components for happy paths, increase minimum threshold for Jest * Add the test/jest folder for Jest setup and shared functions, use it in Swaps Jest tests * Fix ESLint issues, update linting config * Enable ESLint for .snap files (Jest snapshots), throw an error if a snapshot is bigger than 50 lines * Don’t run lint:fix for .snap files * Move `createProps` outside of `describe` blocks, move store creation inside tests * Use translations instead of keys, update a rendering function to load translations * Make sure all Jest snapshots are shorter than 50 lines (default limit) * Add / update props for Swaps tests * Fix React warnings when running tests for Swaps
2021-04-21 21:34:35 +02:00
data-testid="countdown-timer__timer-container"
2020-10-06 20:28:38 +02:00
className={classnames('countdown-timer__timer-container', {
2020-11-03 00:41:28 +01:00
'countdown-timer__timer-container--warning':
warningTime && timeBelowWarningTime(timer, warningTime),
2020-10-06 20:28:38 +02:00
})}
>
<TimerIcon />
2020-10-06 20:28:38 +02:00
{time}
</div>
2020-11-03 00:41:28 +01:00
{!timeOnly && infoTooltipLabelKey ? (
<InfoTooltip position="bottom" contentText={t(infoTooltipLabelKey)} />
) : null}
2020-10-06 20:28:38 +02:00
</div>
);
2020-10-06 20:28:38 +02:00
}
CountdownTimer.propTypes = {
timeStarted: PropTypes.number,
timeOnly: PropTypes.bool,
timerBase: PropTypes.number,
warningTime: PropTypes.string,
labelKey: PropTypes.string,
infoTooltipLabelKey: PropTypes.string,
};