diff --git a/web/apps/auth/src/pages/auth.tsx b/web/apps/auth/src/pages/auth.tsx index a76b687fc3..c5c328a425 100644 --- a/web/apps/auth/src/pages/auth.tsx +++ b/web/apps/auth/src/pages/auth.tsx @@ -122,7 +122,7 @@ const AuthenticatorCodesPage = () => { ) : ( filteredCodes.map((code) => ( - + )) )} @@ -162,159 +162,13 @@ const AuthNavbar: React.FC = () => { ); }; -const AuthFooter: React.FC = () => { - return ( -
-

{t("AUTH_DOWNLOAD_MOBILE_APP")}

- - - -
- ); -}; - -const TOTPDisplay = ({ issuer, account, code, nextCode, period }) => { - return ( -
- -
-
-

- {issuer} -

-

- {account} -

-

- {code} -

-
-
-
-

- {t("AUTH_NEXT")} -

-

- {nextCode} -

-
-
-
- ); -}; - -function BadCodeInfo({ codeInfo, codeErr }) { - const [showRawData, setShowRawData] = useState(false); - - return ( -
-
{codeInfo.title}
-
{codeErr}
-
- {showRawData ? ( -
setShowRawData(false)}> - {codeInfo.rawData ?? "no raw data"} -
- ) : ( -
setShowRawData(true)}>Show rawData
- )} -
-
- ); -} - -interface OTPDisplayProps { +interface CodeDisplay { codeInfo: Code; } -const OTPDisplay: React.FC = ({ codeInfo }) => { - const [code, setCode] = useState(""); - const [nextCode, setNextCode] = useState(""); +const CodeDisplay: React.FC = ({ codeInfo }) => { + const [otp, setOTP] = useState(""); + const [nextOTP, setNextOTP] = useState(""); const [codeErr, setCodeErr] = useState(""); const [hasCopied, setHasCopied] = useState(false); @@ -328,8 +182,8 @@ const OTPDisplay: React.FC = ({ codeInfo }) => { period: codeInfo.period ?? Code.defaultPeriod, digits: codeInfo.digits, }); - setCode(totp.generate()); - setNextCode( + setOTP(totp.generate()); + setNextOTP( totp.generate({ timestamp: currentTime + codeInfo.period * 1000, }), @@ -340,8 +194,8 @@ const OTPDisplay: React.FC = ({ codeInfo }) => { counter: 0, algorithm: codeInfo.algorithm, }); - setCode(hotp.generate()); - setNextCode(hotp.generate({ counter: 1 })); + setOTP(hotp.generate()); + setNextOTP(hotp.generate({ counter: 1 })); } } catch (err) { setCodeErr(err.message); @@ -349,7 +203,7 @@ const OTPDisplay: React.FC = ({ codeInfo }) => { }; const copyCode = () => { - navigator.clipboard.writeText(code); + navigator.clipboard.writeText(otp); setHasCopied(true); setTimeout(() => { setHasCopied(false); @@ -392,13 +246,7 @@ const OTPDisplay: React.FC = ({ codeInfo }) => { copyCode(); }} > - + = ({ codeInfo }) => { ); }; +interface OTPDisplayProps { + code: Code; + otp: string; + nextOTP: string; +} + +const OTPDisplay: React.FC = ({ code, otp, nextOTP }) => { + return ( +
+ +
+
+

+ {code.issuer} +

+

+ {code.account} +

+

+ {otp} +

+
+
+
+

+ {t("AUTH_NEXT")} +

+

+ {nextOTP} +

+
+
+
+ ); +}; + interface TimerProgressProps { period: number; } const TimerProgress: React.FC = ({ period }) => { const [progress, setProgress] = useState(0); - const [ticker, setTicker] = useState(null); const microSecondsInPeriod = period * 1000000; - const startTicker = () => { + useEffect(() => { + const updateTimeRemaining = () => { + const timeRemaining = + microSecondsInPeriod - + ((new Date().getTime() * 1000) % microSecondsInPeriod); + setProgress(timeRemaining / microSecondsInPeriod); + }; + const ticker = setInterval(() => { updateTimeRemaining(); }, 10); - setTicker(ticker); - }; - const updateTimeRemaining = () => { - const timeRemaining = - microSecondsInPeriod - - ((new Date().getTime() * 1000) % microSecondsInPeriod); - setProgress(timeRemaining / microSecondsInPeriod); - }; - - useEffect(() => { - startTicker(); return () => clearInterval(ticker); }, []); @@ -452,3 +406,44 @@ const TimerProgress: React.FC = ({ period }) => { /> ); }; + +function BadCodeInfo({ codeInfo, codeErr }) { + const [showRawData, setShowRawData] = useState(false); + + return ( +
+
{codeInfo.title}
+
{codeErr}
+
+ {showRawData ? ( +
setShowRawData(false)}> + {codeInfo.rawData ?? "no raw data"} +
+ ) : ( +
setShowRawData(true)}>Show rawData
+ )} +
+
+ ); +} + +const AuthFooter: React.FC = () => { + return ( +
+

{t("AUTH_DOWNLOAD_MOBILE_APP")}

+ + + +
+ ); +};