mirror of
https://github.com/quantum5/totp.git
synced 2025-04-24 21:52:04 -04:00
Add countdown progress bar
This commit is contained in:
parent
5243c3aa8b
commit
8e02568a43
15
src/App.tsx
15
src/App.tsx
|
@ -21,6 +21,7 @@ function App() {
|
||||||
const [state, setState] = React.useState(() => parseState() || defaults);
|
const [state, setState] = React.useState(() => parseState() || defaults);
|
||||||
const {secret, step, digits, algorithm} = state;
|
const {secret, step, digits, algorithm} = state;
|
||||||
const [offset, setOffset] = React.useState(0);
|
const [offset, setOffset] = React.useState(0);
|
||||||
|
const [remaining, setRemaining] = React.useState(0);
|
||||||
|
|
||||||
const [validSecret, decoded] = React.useMemo(() => {
|
const [validSecret, decoded] = React.useMemo(() => {
|
||||||
try {
|
try {
|
||||||
|
@ -43,11 +44,16 @@ function App() {
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
if (!validStep) return;
|
if (!validStep) return;
|
||||||
const now = Date.now();
|
const now = Date.now();
|
||||||
const nextOffset = Math.floor(now / (1000 * step)) + 1;
|
const nextUpdate = Math.floor(now / 1000) * 1000 + 1000;
|
||||||
const nextUpdate = nextOffset * step * 1000;
|
const timer = setTimeout(() => {
|
||||||
const timer = setTimeout(() => setOffset(nextOffset), nextUpdate - now);
|
const now = Date.now();
|
||||||
|
const offset = Math.floor(now / (1000 * step));
|
||||||
|
const nextUpdate = (offset + 1) * step * 1000;
|
||||||
|
setRemaining((nextUpdate - now) / 1000);
|
||||||
|
setOffset(offset);
|
||||||
|
}, nextUpdate - now);
|
||||||
return () => clearTimeout(timer);
|
return () => clearTimeout(timer);
|
||||||
}, [validStep, offset, step]);
|
}, [validStep, step, offset, remaining]);
|
||||||
|
|
||||||
const showAdvanced = React.useCallback(() => {
|
const showAdvanced = React.useCallback(() => {
|
||||||
setAdvanced(true);
|
setAdvanced(true);
|
||||||
|
@ -102,6 +108,7 @@ function App() {
|
||||||
<div className="totp-settings">
|
<div className="totp-settings">
|
||||||
<TextInput label="Secret key" value={secret} onChange={setSecret}
|
<TextInput label="Secret key" value={secret} onChange={setSecret}
|
||||||
error={!validSecret && 'Secret must be a valid base32-encoded string'}/>
|
error={!validSecret && 'Secret must be a valid base32-encoded string'}/>
|
||||||
|
<progress class="totp-tick" value={validStep ? remaining : 0} max={validStep ? step : 0}/>
|
||||||
{advanced ?
|
{advanced ?
|
||||||
<ActionLink onClick={hideAdvanced}>Hide advanced options</ActionLink> :
|
<ActionLink onClick={hideAdvanced}>Hide advanced options</ActionLink> :
|
||||||
<ActionLink onClick={showAdvanced}>Show advanced options</ActionLink>}
|
<ActionLink onClick={showAdvanced}>Show advanced options</ActionLink>}
|
||||||
|
|
|
@ -109,6 +109,11 @@ nav.navbar {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
progress.totp-tick {
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
@include media-breakpoint-down(sm) {
|
@include media-breakpoint-down(sm) {
|
||||||
.totp-code {
|
.totp-code {
|
||||||
&.totp-far {
|
&.totp-far {
|
||||||
|
|
Loading…
Reference in a new issue