From 457420400bcd05ecc7a4ded2544d61620a4f761a Mon Sep 17 00:00:00 2001 From: escapedcat Date: Sun, 11 Aug 2024 17:19:08 +0800 Subject: [PATCH 1/5] fix(settings): refactor change password and add form-handling to modal --- src/components/CapsLockWarning.tsx | 8 +- src/components/ConfirmModal.tsx | 42 +++++--- src/hooks/use-caps-lock.ts | 10 +- src/pages/Settings/ChangePwModal.tsx | 149 +++++++++++++++------------ src/pages/Settings/index.tsx | 14 +-- 5 files changed, 121 insertions(+), 102 deletions(-) diff --git a/src/components/CapsLockWarning.tsx b/src/components/CapsLockWarning.tsx index d6ba6164..0f4c0814 100644 --- a/src/components/CapsLockWarning.tsx +++ b/src/components/CapsLockWarning.tsx @@ -1,13 +1,15 @@ +import { Alert } from "@/components/Alert"; import { ExclamationTriangleIcon } from "@heroicons/react/24/outline"; import { useTranslation } from "react-i18next"; const CapsLockWarning = () => { const { t } = useTranslation(); return ( -

- + + +   {t("login.caps_lock")} -

+ ); }; diff --git a/src/components/ConfirmModal.tsx b/src/components/ConfirmModal.tsx index a0998468..5af6e4a5 100644 --- a/src/components/ConfirmModal.tsx +++ b/src/components/ConfirmModal.tsx @@ -13,9 +13,10 @@ import { useTranslation } from "react-i18next"; export type Props = { headline: string; body?: ReactNode; - onConfirm: () => void; + onConfirm?: () => void; disclosure: UseDisclosureReturn; isLoading?: boolean; + isFormModal?: ReactNode; }; export const ConfirmModal = ({ @@ -24,6 +25,7 @@ export const ConfirmModal = ({ onConfirm, disclosure, isLoading, + isFormModal, }: Props) => { const { t } = useTranslation(); const { isOpen, onOpenChange, onClose } = disclosure; @@ -38,21 +40,31 @@ export const ConfirmModal = ({ {headline} - {!!body && {body}} + {!!isFormModal ? ( + isFormModal + ) : ( + <> + {!!body && {body}} - - - - + + + + + + )} )} diff --git a/src/hooks/use-caps-lock.ts b/src/hooks/use-caps-lock.ts index 3866e784..f3334765 100644 --- a/src/hooks/use-caps-lock.ts +++ b/src/hooks/use-caps-lock.ts @@ -1,24 +1,24 @@ import { KeyboardEvent, useState } from "react"; const useCapsLock = () => { - const [isCapsLockOn, setIsCapsLockOn] = useState(false); + const [isCapsLockEnabled, setIsCapsLockEnabled] = useState(false); const onKeyDown = (event: KeyboardEvent) => { if (event.getModifierState("CapsLock")) { - setIsCapsLockOn(true); + setIsCapsLockEnabled(true); } }; const onKeyUp = (event: KeyboardEvent) => { - if (isCapsLockOn) { + if (isCapsLockEnabled) { if (!event.getModifierState("CapsLock")) { - setIsCapsLockOn(false); + setIsCapsLockEnabled(false); } } }; return { - isCapsLockOn, + isCapsLockEnabled, keyHandlers: { onKeyDown, onKeyUp, diff --git a/src/pages/Settings/ChangePwModal.tsx b/src/pages/Settings/ChangePwModal.tsx index d89f0344..d30065c4 100644 --- a/src/pages/Settings/ChangePwModal.tsx +++ b/src/pages/Settings/ChangePwModal.tsx @@ -1,14 +1,13 @@ -import ButtonWithSpinner from "@/components/ButtonWithSpinner/ButtonWithSpinner"; +import ActionBox from "./ActionBox"; +import { Button } from "@/components/Button"; import CapsLockWarning from "@/components/CapsLockWarning"; -import InputField from "@/components/InputField"; +import ConfirmModal from "@/components/ConfirmModal"; import useCapsLock from "@/hooks/use-caps-lock"; -import ModalDialog from "@/layouts/ModalDialog"; -import { MODAL_ROOT } from "@/utils"; import { checkError } from "@/utils/checkError"; import { instance } from "@/utils/interceptor"; -import { ArrowPathIcon, XMarkIcon } from "@heroicons/react/24/outline"; -import { ChangeEvent, FC, useState } from "react"; -import { createPortal } from "react-dom"; +import { Input, useDisclosure } from "@nextui-org/react"; +import { ModalFooter, ModalBody } from "@nextui-org/react"; +import { type FC, useState } from "react"; import { useForm } from "react-hook-form"; import { useTranslation } from "react-i18next"; import { toast } from "react-toastify"; @@ -23,18 +22,20 @@ interface IFormInputs { const ChangePwModal: FC = ({ onClose }) => { const { t } = useTranslation(); - const [oldPassword, setOldPassword] = useState(""); - const [newPassword, setNewPassword] = useState(""); const [isLoading, setIsLoading] = useState(false); - const { isCapsLockOn, keyHandlers } = useCapsLock(); + const confirmModal = useDisclosure(); - const changePwHandler = () => { + const { isCapsLockEnabled, keyHandlers } = useCapsLock(); + + const changePwHandler = (data: IFormInputs) => { setIsLoading(true); + const params = { type: "a", - old_password: oldPassword, - new_password: newPassword, + old_password: data.oldPassword, + new_password: data.newPassword, }; + instance .post("/system/change-password", {}, { params }) .then(() => { @@ -46,34 +47,35 @@ const ChangePwModal: FC = ({ onClose }) => { }) .finally(() => { setIsLoading(false); + reset(); }); }; - const onChangeOldPw = (event: ChangeEvent) => { - setOldPassword(event.target.value); - }; - - const onChangeNewPw = (event: ChangeEvent) => { - setNewPassword(event.target.value); - }; - const { register, handleSubmit, + reset, formState: { errors, isValid }, } = useForm({ mode: "onChange", }); - return createPortal( - -

{t("settings.change_pw_a")}

-
-
- ( + + + {isCapsLockEnabled && } + +
+ = ({ onClose }) => { value: 8, message: t("setup.password_error_length"), }, - onChange: onChangeOldPw, })} - type="password" - value={oldPassword} - label={t("settings.old_pw")} - errorMessage={errors.oldPassword} {...keyHandlers} /> -
-
- = ({ onClose }) => { value: 8, message: t("setup.password_error_length"), }, - onChange: onChangeNewPw, })} - type="password" - value={newPassword} - label={t("settings.new_pw")} - errorMessage={errors.newPassword} {...keyHandlers} /> - {isCapsLockOn && } -
-
- - } - > - {t("settings.change_pw_a")} - -
-
-
, - MODAL_ROOT, + + + + + + + + + ); + + return ( + <> + } + /> + + confirmModal.onOpen()} + showChild={false} + /> + ); }; diff --git a/src/pages/Settings/index.tsx b/src/pages/Settings/index.tsx index da129cf8..d493c393 100644 --- a/src/pages/Settings/index.tsx +++ b/src/pages/Settings/index.tsx @@ -1,4 +1,3 @@ -import ActionBox from "./ActionBox"; import ChangePwModal from "./ChangePwModal"; import DebugLogBox from "./DebugLogBox"; import I18nBox from "./I18nBox"; @@ -6,14 +5,12 @@ import RebootModal from "./RebootModal"; import ShutdownModal from "./ShutdownModal"; import VersionBox from "./VersionBox"; import { enableGutter } from "@/utils"; -import { FC, useEffect, useState } from "react"; +import { FC, useEffect } from "react"; import { useTranslation } from "react-i18next"; const Settings: FC = () => { const { t } = useTranslation(); - const [showPwModal, setShowPwModal] = useState(false); - useEffect(() => { enableGutter(); }, []); @@ -21,14 +18,7 @@ const Settings: FC = () => { return (
- setShowPwModal(true)} - showChild={showPwModal} - > - setShowPwModal(false)} /> - + From 9095acea5739411caac23db199516347fcaaf930 Mon Sep 17 00:00:00 2001 From: escapedcat Date: Sun, 11 Aug 2024 17:22:26 +0800 Subject: [PATCH 2/5] fix(settings): cleanup --- src/pages/Settings/ChangePwModal.tsx | 7 ++----- src/pages/Settings/index.tsx | 3 --- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/src/pages/Settings/ChangePwModal.tsx b/src/pages/Settings/ChangePwModal.tsx index d30065c4..f95a6fd4 100644 --- a/src/pages/Settings/ChangePwModal.tsx +++ b/src/pages/Settings/ChangePwModal.tsx @@ -12,15 +12,12 @@ import { useForm } from "react-hook-form"; import { useTranslation } from "react-i18next"; import { toast } from "react-toastify"; -export type Props = { - onClose: () => void; -}; interface IFormInputs { oldPassword: string; newPassword: string; } -const ChangePwModal: FC = ({ onClose }) => { +const ChangePwModal: FC = () => { const { t } = useTranslation(); const [isLoading, setIsLoading] = useState(false); const confirmModal = useDisclosure(); @@ -40,7 +37,7 @@ const ChangePwModal: FC = ({ onClose }) => { .post("/system/change-password", {}, { params }) .then(() => { toast.success(t("settings.pass_a_changed")); - onClose(); + confirmModal.onClose(); }) .catch((err) => { toast.error(checkError(err)); diff --git a/src/pages/Settings/index.tsx b/src/pages/Settings/index.tsx index d493c393..85dbc1f9 100644 --- a/src/pages/Settings/index.tsx +++ b/src/pages/Settings/index.tsx @@ -6,11 +6,8 @@ import ShutdownModal from "./ShutdownModal"; import VersionBox from "./VersionBox"; import { enableGutter } from "@/utils"; import { FC, useEffect } from "react"; -import { useTranslation } from "react-i18next"; const Settings: FC = () => { - const { t } = useTranslation(); - useEffect(() => { enableGutter(); }, []); From 016cb4918bffa1f28f06154abd083ace6173da79 Mon Sep 17 00:00:00 2001 From: escapedcat Date: Sun, 11 Aug 2024 18:14:07 +0800 Subject: [PATCH 3/5] fix(settings): avoid re-rendering the form --- src/pages/Settings/ChangePwModal.tsx | 155 ++++++++++++++------------- 1 file changed, 78 insertions(+), 77 deletions(-) diff --git a/src/pages/Settings/ChangePwModal.tsx b/src/pages/Settings/ChangePwModal.tsx index f95a6fd4..29bbf61d 100644 --- a/src/pages/Settings/ChangePwModal.tsx +++ b/src/pages/Settings/ChangePwModal.tsx @@ -57,89 +57,90 @@ const ChangePwModal: FC = () => { mode: "onChange", }); - const Form = () => ( -
- - {isCapsLockEnabled && } - -
- - - -
-
- - - - - -
- ); - return ( <> } + isFormModal={ +
+ + {isCapsLockEnabled && } + +
+ + + +
+
+ + + + + +
+ } /> Date: Sun, 11 Aug 2024 22:13:58 +0800 Subject: [PATCH 4/5] fix(home): unlock modal caps alert usage --- src/pages/Home/UnlockModal.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pages/Home/UnlockModal.tsx b/src/pages/Home/UnlockModal.tsx index 7f7faeb3..50734016 100644 --- a/src/pages/Home/UnlockModal.tsx +++ b/src/pages/Home/UnlockModal.tsx @@ -29,7 +29,7 @@ export default function UnlockModal({ onClose }: Props) { const { setWalletLocked } = useContext(AppContext); const [isLoading, setIsLoading] = useState(false); const [passwordWrong, setPasswordWrong] = useState(false); - const { isCapsLockOn, keyHandlers } = useCapsLock(); + const { isCapsLockEnabled, keyHandlers } = useCapsLock(); const { register, @@ -81,7 +81,7 @@ export default function UnlockModal({ onClose }: Props) { disabled={isLoading} {...keyHandlers} /> - {isCapsLockOn && } + {isCapsLockEnabled && } Date: Sun, 18 Aug 2024 15:17:52 +0800 Subject: [PATCH 5/5] refactor(settings): apply suggestion and directly use prop --- src/components/ConfirmModal.tsx | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/components/ConfirmModal.tsx b/src/components/ConfirmModal.tsx index 5af6e4a5..f911fff8 100644 --- a/src/components/ConfirmModal.tsx +++ b/src/components/ConfirmModal.tsx @@ -40,9 +40,7 @@ export const ConfirmModal = ({ {headline} - {!!isFormModal ? ( - isFormModal - ) : ( + {isFormModal || ( <> {!!body && {body}}