Merge pull request #9825 from streetwriters/fix/288

Add form validation in change password screen
This commit is contained in:
Ammar Ahmed
2026-05-11 13:35:45 +05:00
committed by GitHub
4 changed files with 92 additions and 49 deletions

View File

@@ -18,6 +18,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import { strings } from "@notesnook/intl";
import { useThemeColors } from "@notesnook/theme";
import React, { useRef, useState } from "react";
import { View } from "react-native";
import { db } from "../../common/database";
@@ -26,42 +27,44 @@ import { eSendEvent, ToastManager } from "../../services/event-manager";
import Navigation from "../../services/navigation";
import { useUserStore } from "../../stores/use-user-store";
import { eOpenRecoveryKeyDialog } from "../../utils/events";
import { AppFontSize } from "../../utils/size";
import { DefaultAppStyles } from "../../utils/styles";
import { Dialog } from "../dialog";
import AppIcon from "../ui/AppIcon";
import { Button } from "../ui/button";
import Input from "../ui/input";
import FormInput, { createFormRef, validators } from "../ui/input/form-input";
import { Notice } from "../ui/notice";
import Paragraph from "../ui/typography/paragraph";
import { TextInput } from "react-native-gesture-handler";
export const ChangePassword = () => {
const passwordInputRef = useRef<TextInput>(null);
const password = useRef<string>(undefined);
const { colors } = useThemeColors();
const formRef = useRef(
createFormRef({
oldPassword: "",
password: ""
})
);
const oldPasswordInputRef = useRef<TextInput>(null);
const oldPassword = useRef<string>(undefined);
const [error, setError] = useState(false);
const passwordInputRef = useRef<TextInput>(null);
const [loading, setLoading] = useState(false);
const [error, setError] = useState<string>();
const user = useUserStore((state) => state.user);
const changePassword = async () => {
setError(undefined);
formRef.current.clearErrors();
if (!user?.isEmailConfirmed) {
ToastManager.show({
heading: strings.emailNotConfirmed(),
message: strings.emailNotConfirmedDesc(),
type: "error",
context: "local"
});
setError(strings.emailNotConfirmedDesc());
return;
}
if (error || !oldPassword.current || !password.current) {
ToastManager.show({
heading: strings.allFieldsRequired(),
message: strings.allFieldsRequiredDesc(),
type: "error",
context: "local"
});
if (!formRef.current.validate()) {
return;
}
const values = formRef.current.getValues();
setLoading(true);
try {
const result = await BackupService.run(
@@ -74,8 +77,8 @@ export const ChangePassword = () => {
}
const passwordChanged = await db.user.changePassword(
oldPassword.current,
password.current
values.oldPassword,
values.password
);
if (!passwordChanged) {
@@ -91,15 +94,15 @@ export const ChangePassword = () => {
Navigation.goBack();
eSendEvent(eOpenRecoveryKeyDialog);
} catch (e) {
const message = (e as Error).message;
setLoading(false);
ToastManager.show({
heading: strings.passwordChangeFailed(),
message: (e as Error).message,
type: "error",
context: "local"
});
if (/old password/i.test(message)) {
formRef.current.setError("oldPassword", message);
} else {
setError(message);
}
}
setLoading(false);
};
return (
@@ -110,36 +113,61 @@ export const ChangePassword = () => {
}}
>
<Dialog context="change-password-dialog" />
<Input
<FormInput
name="oldPassword"
formRef={formRef}
fwdRef={oldPasswordInputRef}
onChangeText={(value) => {
oldPassword.current = value;
}}
loading={loading}
validators={[validators.required(strings.currentPasswordRequired())]}
returnKeyLabel="Next"
returnKeyType="next"
secureTextEntry
autoComplete="password"
autoCapitalize="none"
autoCorrect={false}
placeholder={strings.oldPassword()}
placeholder={strings.currentPassword()}
onSubmitEditing={() => {
passwordInputRef.current?.focus();
}}
/>
<Input
<FormInput
name="password"
formRef={formRef}
fwdRef={passwordInputRef}
onChangeText={(value) => {
password.current = value;
}}
onErrorCheck={(e) => setError(e)}
loading={loading}
validators={[validators.required(strings.passwordRequired())]}
returnKeyLabel={strings.next()}
returnKeyType="next"
secureTextEntry
validationType="password"
autoComplete="password"
autoCapitalize="none"
autoCorrect={false}
placeholder={strings.newPassword()}
onSubmitEditing={() => {
changePassword();
}}
/>
{error ? (
<Paragraph
numberOfLines={4}
onPress={() => {}}
color={colors.error.accent}
style={{
textAlign: "center",
marginTop: DefaultAppStyles.GAP_VERTICAL
}}
>
<AppIcon
color={colors.error.accent}
name="alert-circle-outline"
size={AppFontSize.sm - 1}
/>{" "}
{error}
</Paragraph>
) : null}
<Notice text={strings.changePasswordNotice()} type="alert" />
<View style={{ height: 10 }} />

View File

@@ -6,6 +6,12 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: @lingui/cli\n"
"Language: en\n"
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: \n"
"Last-Translator: \n"
"Language-Team: \n"
"Plural-Forms: \n"
#: src/strings.ts:2421
msgid " \"Notebook > Notes\""
@@ -1962,10 +1968,15 @@ msgstr "Curate the toolbar that fits your needs and matches your personality."
msgid "Current note"
msgstr "Current note"
#: src/strings.ts:1479
#: src/strings.ts:1485
msgid "Current password"
msgstr "Current password"
#: src/strings.ts:2670
msgid "Current password required"
msgstr "Current password required"
#: src/strings.ts:1229
msgid "Current path: {path}"
msgstr "Current path: {path}"
@@ -4401,10 +4412,6 @@ msgstr "Okay"
msgid "Old - new"
msgstr "Old - new"
#: src/strings.ts:1479
msgid "Old password"
msgstr "Old password"
#: src/strings.ts:1835
msgid "Older version"
msgstr "Older version"

View File

@@ -6,6 +6,12 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: @lingui/cli\n"
"Language: pseudo-LOCALE\n"
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: \n"
"Last-Translator: \n"
"Language-Team: \n"
"Plural-Forms: \n"
#: src/strings.ts:2421
msgid " \"Notebook > Notes\""
@@ -1951,10 +1957,15 @@ msgstr ""
msgid "Current note"
msgstr ""
#: src/strings.ts:1479
#: src/strings.ts:1485
msgid "Current password"
msgstr ""
#: src/strings.ts:2670
msgid "Current password required"
msgstr ""
#: src/strings.ts:1229
msgid "Current path: {path}"
msgstr ""
@@ -4375,10 +4386,6 @@ msgstr ""
msgid "Old - new"
msgstr ""
#: src/strings.ts:1479
msgid "Old password"
msgstr ""
#: src/strings.ts:1835
msgid "Older version"
msgstr ""

View File

@@ -1476,7 +1476,7 @@ $day$: Current day (eg. Monday)`,
someNotesPublished: () => t`Some notes are published`,
unpublishToDelete: () => t`Unpublish notes to delete them`,
filterAttachments: () => t`Filter attachments by filename, type or hash`,
oldPassword: () => t`Old password`,
oldPassword: () => t`Current password`,
newPassword: () => t`New password`,
email: () => t`Email`,
emailInvalid: () => t`Invalid email`,
@@ -2666,5 +2666,6 @@ Use this if changes from other devices are not appearing on this device. This wi
t`Are you sure you want to delete this attachment?`,
attachmentDeleted: () => t`Attachment deleted`,
titleIsRequired: () => t`Title is required`,
nameIsRequired: () => t`Name is required.`
nameIsRequired: () => t`Name is required.`,
currentPasswordRequired: () => t`Current password required`
};