diff --git a/src/components/auth/AuthMasterPasswordPopover.tsx b/src/components/auth/AuthMasterPasswordPopover.tsx index 6fd3eab..26c0054 100644 --- a/src/components/auth/AuthMasterPasswordPopover.tsx +++ b/src/components/auth/AuthMasterPasswordPopover.tsx @@ -1,12 +1,11 @@ // Copyright (c) 2020-2021 Drew Lemmy // This file is part of KristWeb 2 under AGPL-3.0. // Full details: https://github.com/tmpim/KristWeb2/blob/master/LICENSE.txt -import { useState, useRef, FC } from "react"; +import { useState, useRef, useCallback, FC, Ref } from "react"; import { Popover, Button, Input, Form } from "antd"; import { TooltipPlacement } from "antd/lib/tooltip"; -import { useTranslation } from "react-i18next"; -import { translateError } from "@utils/i18n"; +import { useTFns, translateError } from "@utils/i18n"; import { FakeUsernameInput } from "./FakeUsernameInput"; import { getMasterPasswordInput } from "./MasterPasswordInput"; @@ -23,64 +22,99 @@ placement?: TooltipPlacement; } -export const AuthMasterPasswordPopover: FC = ({ encrypt, onSubmit, placement, children }) => { - const { salt, tester } = useMasterPassword(); +export const AuthMasterPasswordPopover: FC = ({ + encrypt, + onSubmit, + placement, + children +}) => { + const { tStr } = useTFns("masterPassword."); - const { t } = useTranslation(); - const [form] = Form.useForm(); - const [passwordError, setPasswordError] = useState(); const inputRef = useRef(null); - async function onFinish(values: FormValues) { - try { - await authMasterPassword(salt, tester, values.masterPassword); - onSubmit(); - } catch (err) { - setPasswordError(translateError(t, err, "masterPassword.errorUnknown")); - } - } + const onVisibleChange = useCallback(() => + setTimeout(() => inputRef.current?.focus(), 20), [inputRef]); return { - if (visible) setTimeout(() => { if (inputRef.current) inputRef.current.focus(); }, 20); - }} - content={<> -

{t(encrypt ? "masterPassword.popoverDescriptionEncrypt" : "masterPassword.popoverDescription")}

- -
- - - {/* Password input */} - - {getMasterPasswordInput({ inputRef, placeholder: t("masterPassword.passwordPlaceholder"), autoFocus: true })} - - - - - } + onVisibleChange={onVisibleChange} + content={() => } > {children}
; }; + +interface AuthFormProps { + encrypt?: boolean; + onSubmit: () => void; + inputRef: Ref; +} + +function AuthForm({ + encrypt, + onSubmit, + inputRef +}: AuthFormProps): JSX.Element { + const { t, tStr, tKey } = useTFns("masterPassword."); + + const { salt, tester } = useMasterPassword(); + + const [form] = Form.useForm(); + const [passwordError, setPasswordError] = useState(); + + const onFinish = useCallback(async function(values: FormValues) { + try { + await authMasterPassword(salt, tester, values.masterPassword); + onSubmit(); + } catch (err) { + setPasswordError(translateError(t, err, tKey("errorUnknown"))); + } + }, [t, tKey, onSubmit, salt, tester]); + + return <> +

{tStr(encrypt ? "popoverDescriptionEncrypt" : "popoverDescription")}

+ +
+ + + {/* Password input */} + + {getMasterPasswordInput({ + inputRef, + placeholder: t("masterPassword.passwordPlaceholder"), + autoFocus: true + })} + + + {/* Submit button */} + + + ; +} diff --git a/src/utils/i18n/fns.ts b/src/utils/i18n/fns.ts index 856eb9c..5573908 100644 --- a/src/utils/i18n/fns.ts +++ b/src/utils/i18n/fns.ts @@ -1,6 +1,7 @@ // Copyright (c) 2020-2021 Drew Lemmy // This file is part of KristWeb 2 under AGPL-3.0. // Full details: https://github.com/tmpim/KristWeb2/blob/master/LICENSE.txt +import { useCallback } from "react"; import { i18n } from "i18next"; import { useTranslation, TFunction } from "react-i18next"; import { TranslatedError } from "./errors"; @@ -17,9 +18,9 @@ } export function useTranslationFns(prefix?: string): TFns { const { t, i18n } = useTranslation(); - const tKey = (key: string) => prefix + key; - const tStr = (key: string) => t(tKey(key)); - const tErr = (key: string) => new TranslatedError(tKey(key)); + const tKey = useCallback((key: string) => prefix + key, [prefix]); + const tStr = useCallback((key: string) => t(tKey(key)), [t, tKey]); + const tErr = useCallback((key: string) => new TranslatedError(tKey(key)), [tKey]); return { t, tKey, tStr, tErr, i18n }; }