From 28691784bf901c53d76954b9efc5b485f4b0d9fe Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Tue, 29 Oct 2024 12:45:53 +0530 Subject: [PATCH 1/6] Unused CSS --- web/apps/photos/src/styles/global.css | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/web/apps/photos/src/styles/global.css b/web/apps/photos/src/styles/global.css index 66e23828ce..e8cf798bce 100644 --- a/web/apps/photos/src/styles/global.css +++ b/web/apps/photos/src/styles/global.css @@ -125,21 +125,6 @@ body { display: none; } -.carousel-inner { - padding-bottom: 50px !important; -} - -.carousel-indicators li { - width: 10px; - height: 10px; - border-radius: 50%; - margin-right: 12px; -} - -.carousel-indicators .active { - background-color: #51cd7c; -} - div.otp-input input { width: 36px !important; height: 36px; From da6b0c920a6d818e6122b54567f474f0a29940a6 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Tue, 29 Oct 2024 12:54:20 +0530 Subject: [PATCH 2/6] Doc --- web/docs/dependencies.md | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/web/docs/dependencies.md b/web/docs/dependencies.md index 0f5a8a3d1a..1eae21a578 100644 --- a/web/docs/dependencies.md +++ b/web/docs/dependencies.md @@ -191,15 +191,23 @@ For more details, see [translations.md](translations.md). - [chrono-node](https://github.com/wanasit/chrono) is used for parsing natural language queries into dates for showing search results. +- [matrix](https://github.com/mljs/matrix) is mathematical matrix abstraction + by the machine learning code. It is used alongwith + [similarity-transformation](https://github.com/shaileshpandit/similarity-transformation-js) + during face alignment. + +### UI + - [react-top-loading-bar](https://github.com/klendi/react-top-loading-bar) is used for showing a progress indicator for global actions (This shouldn't be used always, it is only meant as a fallback when there isn't an otherwise suitable place for showing a local activity indicator). -- [matrix](https://github.com/mljs/matrix) is mathematical matrix abstraction - by the machine learning code. It is used alongwith - [similarity-transformation](https://github.com/shaileshpandit/similarity-transformation-js) - during face alignment. +- [pure-react-carousel](https://github.com/express-labs/pure-react-carousel) + is used for the feature carousel on the welcome (login / signup) screen. + +- [react-otp-input](https://github.com/devfolioco/react-otp-input) is used to + render a segmented OTP input field. ## Auth app specific From 61936029e812b4f1616c89e20053535079295ccc Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Tue, 29 Oct 2024 18:34:52 +0530 Subject: [PATCH 3/6] Update --- web/apps/photos/package.json | 2 +- .../components/two-factor/VerifyForm.tsx | 35 +++++++++++++++---- web/yarn.lock | 8 ++--- 3 files changed, 34 insertions(+), 11 deletions(-) diff --git a/web/apps/photos/package.json b/web/apps/photos/package.json index b725914b21..303d6cdf2c 100644 --- a/web/apps/photos/package.json +++ b/web/apps/photos/package.json @@ -27,7 +27,7 @@ "piexifjs": "^1.0.6", "pure-react-carousel": "^1.30.1", "react-dropzone": "^14.2", - "react-otp-input": "^2.3.1", + "react-otp-input": "^3.1.1", "react-select": "^5.8.0", "react-top-loading-bar": "^2.3.1", "react-virtualized-auto-sizer": "^1.0", diff --git a/web/packages/accounts/components/two-factor/VerifyForm.tsx b/web/packages/accounts/components/two-factor/VerifyForm.tsx index 3a3d7ac7f3..2881397ef8 100644 --- a/web/packages/accounts/components/two-factor/VerifyForm.tsx +++ b/web/packages/accounts/components/two-factor/VerifyForm.tsx @@ -4,7 +4,7 @@ import { CenteredFlex, VerticallyCentered, } from "@ente/shared/components/Container"; -import { Box, Typography } from "@mui/material"; +import { Box, Typography, styled } from "@mui/material"; import { Formik, type FormikHelpers } from "formik"; import { t } from "i18next"; import { useRef, useState } from "react"; @@ -71,17 +71,21 @@ export default function VerifyTwoFactor(props: Props) { -} + renderInput={(props) => ( + + )} + shouldAutoFocus + // separator={"-"} + // isInputNum + // className={"otp-input"} /> {errors.otp && ( @@ -107,3 +111,22 @@ export default function VerifyTwoFactor(props: Props) { ); } + +const IndividualInput = styled("input")( + ({ theme }) => ` + font-size: 2rem; + padding: 4px 12px; + min-width: 3rem; + margin-inline: 8px; + border: 1px solid ${theme.colors.accent.A700}; + border-radius: 1px; + outline-color: ${theme.colors.accent.A300}; + transition: 0.5s; + + @media (width < 30em) { + font-size: 1rem; + padding: 4px; + min-width: 2rem; + } +`, +); diff --git a/web/yarn.lock b/web/yarn.lock index 411a432aab..a1dc11d308 100644 --- a/web/yarn.lock +++ b/web/yarn.lock @@ -3743,10 +3743,10 @@ react-is@^18.3.1: resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.3.1.tgz#e83557dc12eae63a99e003a46388b1dcbb44db7e" integrity sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg== -react-otp-input@^2.3.1: - version "2.4.0" - resolved "https://registry.yarnpkg.com/react-otp-input/-/react-otp-input-2.4.0.tgz#0f0a3de1d8c8d564e2e4fbe5d6b7b56e29e3a6e6" - integrity sha512-AIgl7u4sS9BTNCxX1xlaS5fPWay/Zml8Ho5LszXZKXrH1C/TiFsTQGmtl13UecQYO3mSF3HUzG2rrDf0sjEFmg== +react-otp-input@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/react-otp-input/-/react-otp-input-3.1.1.tgz#910169629812c40a614e6c175cc2c5f36102bb61" + integrity sha512-bjPavgJ0/Zmf/AYi4onj8FbH93IjeD+e8pWwxIJreDEWsU1ILR5fs8jEJmMGWSBe/yyvPP6X/W6Mk9UkOCkTPw== react-refresh@^0.14.2: version "0.14.2" From d9e6ff2fee14e0a0284a9dee1a45f3c952e54781 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Tue, 29 Oct 2024 19:21:20 +0530 Subject: [PATCH 4/6] Autofocus back to first on error --- web/apps/photos/src/styles/global.css | 19 ------------------ .../components/two-factor/VerifyForm.tsx | 20 +++++++++---------- 2 files changed, 9 insertions(+), 30 deletions(-) diff --git a/web/apps/photos/src/styles/global.css b/web/apps/photos/src/styles/global.css index e8cf798bce..c30221d644 100644 --- a/web/apps/photos/src/styles/global.css +++ b/web/apps/photos/src/styles/global.css @@ -124,22 +124,3 @@ body { .pswp__caption--empty { display: none; } - -div.otp-input input { - width: 36px !important; - height: 36px; - margin: 0 10px; -} - -div.otp-input input::placeholder { - opacity: 0; -} - -div.otp-input input:not(:placeholder-shown), -div.otp-input input:focus { - border: 2px solid #51cd7c; - border-radius: 1px; - -webkit-transition: 0.5s; - transition: 0.5s; - outline: none; -} diff --git a/web/packages/accounts/components/two-factor/VerifyForm.tsx b/web/packages/accounts/components/two-factor/VerifyForm.tsx index 2881397ef8..1561568f35 100644 --- a/web/packages/accounts/components/two-factor/VerifyForm.tsx +++ b/web/packages/accounts/components/two-factor/VerifyForm.tsx @@ -7,7 +7,7 @@ import { import { Box, Typography, styled } from "@mui/material"; import { Formik, type FormikHelpers } from "formik"; import { t } from "i18next"; -import { useRef, useState } from "react"; +import { useState } from "react"; import OtpInput from "react-otp-input"; interface formValues { @@ -25,7 +25,7 @@ export type VerifyTwoFactorCallback = ( export default function VerifyTwoFactor(props: Props) { const [waiting, setWaiting] = useState(false); - const otpInputRef = useRef(null); + const [shouldAutoFocus, setShouldAutoFocus] = useState(true); const markSuccessful = async () => { setWaiting(false); @@ -40,11 +40,13 @@ export default function VerifyTwoFactor(props: Props) { await props.onSubmit(otp, markSuccessful); } catch (e) { resetForm(); - for (let i = 0; i < 6; i++) { - otpInputRef.current?.focusPrevInput(); - } const message = e instanceof Error ? e.message : ""; setFieldError("otp", `${t("generic_error_retry")} ${message}`); + // Workaround (toggling shouldAutoFocus) to reset the focus back to + // the first input field in case of errors. + // https://github.com/devfolioco/react-otp-input/issues/420 + setShouldAutoFocus(false); + setTimeout(() => setShouldAutoFocus(true), 100); } setWaiting(false); }; @@ -71,21 +73,17 @@ export default function VerifyTwoFactor(props: Props) { -} renderInput={(props) => ( )} - shouldAutoFocus - // separator={"-"} - // isInputNum - // className={"otp-input"} /> {errors.otp && ( @@ -123,7 +121,7 @@ const IndividualInput = styled("input")( outline-color: ${theme.colors.accent.A300}; transition: 0.5s; - @media (width < 30em) { + ${theme.breakpoints.down("sm")} { font-size: 1rem; padding: 4px; min-width: 2rem; From d2db27d4eeb02e1116ccfb61508bf69d4553aec0 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Tue, 29 Oct 2024 19:27:33 +0530 Subject: [PATCH 5/6] Style to fit during the login flow --- .../accounts/components/two-factor/VerifyForm.tsx | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/web/packages/accounts/components/two-factor/VerifyForm.tsx b/web/packages/accounts/components/two-factor/VerifyForm.tsx index 1561568f35..765b8aa235 100644 --- a/web/packages/accounts/components/two-factor/VerifyForm.tsx +++ b/web/packages/accounts/components/two-factor/VerifyForm.tsx @@ -112,9 +112,10 @@ export default function VerifyTwoFactor(props: Props) { const IndividualInput = styled("input")( ({ theme }) => ` - font-size: 2rem; - padding: 4px 12px; - min-width: 3rem; + font-size: 1.5rem; + padding: 4px; + width: 40px !important; + aspect-ratio: 1; margin-inline: 8px; border: 1px solid ${theme.colors.accent.A700}; border-radius: 1px; @@ -124,7 +125,7 @@ const IndividualInput = styled("input")( ${theme.breakpoints.down("sm")} { font-size: 1rem; padding: 4px; - min-width: 2rem; + width: 32px !important; } `, ); From 8e5fc76ef1572acbd96049da0fdbbcc43fae99c1 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Tue, 29 Oct 2024 19:29:12 +0530 Subject: [PATCH 6/6] Move dep to correct place --- web/apps/photos/package.json | 1 - web/docs/dependencies.md | 8 ++++---- web/packages/accounts/package.json | 3 ++- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/web/apps/photos/package.json b/web/apps/photos/package.json index 303d6cdf2c..e2b6b828e3 100644 --- a/web/apps/photos/package.json +++ b/web/apps/photos/package.json @@ -27,7 +27,6 @@ "piexifjs": "^1.0.6", "pure-react-carousel": "^1.30.1", "react-dropzone": "^14.2", - "react-otp-input": "^3.1.1", "react-select": "^5.8.0", "react-top-loading-bar": "^2.3.1", "react-virtualized-auto-sizer": "^1.0", diff --git a/web/docs/dependencies.md b/web/docs/dependencies.md index 1eae21a578..5c43b11966 100644 --- a/web/docs/dependencies.md +++ b/web/docs/dependencies.md @@ -132,7 +132,7 @@ with Next.js. For more details, see [translations.md](translations.md). -### Others +### Other UI components - [formik](https://github.com/jaredpalmer/formik) provides an easier to use abstraction for dealing with form state, validation and submission states @@ -140,6 +140,9 @@ For more details, see [translations.md](translations.md). - [react-select](https://react-select.com/) is used for search dropdowns. +- [react-otp-input](https://github.com/devfolioco/react-otp-input) is used to + render a segmented OTP input field for 2FA authentication. + ## Utilities - [comlink](https://github.com/GoogleChromeLabs/comlink) provides a minimal @@ -206,9 +209,6 @@ For more details, see [translations.md](translations.md). - [pure-react-carousel](https://github.com/express-labs/pure-react-carousel) is used for the feature carousel on the welcome (login / signup) screen. -- [react-otp-input](https://github.com/devfolioco/react-otp-input) is used to - render a segmented OTP input field. - ## Auth app specific - [otpauth](https://github.com/hectorm/otpauth) is used for the generation of diff --git a/web/packages/accounts/package.json b/web/packages/accounts/package.json index 574276df1a..c5f7b0b881 100644 --- a/web/packages/accounts/package.json +++ b/web/packages/accounts/package.json @@ -5,6 +5,7 @@ "dependencies": { "@/base": "*", "@ente/eslint-config": "*", - "@ente/shared": "*" + "@ente/shared": "*", + "react-otp-input": "^3.1.1" } }