diff --git a/src/input/Input.tsx b/src/input/Input.tsx index afecd6a..95d3fc5 100644 --- a/src/input/Input.tsx +++ b/src/input/Input.tsx @@ -72,6 +72,7 @@ interface InputFieldProps { autoCorrect?: string; autoCapitalize?: string; value?: string; + defaultValue?: string; placeholder?: string; defaultChecked?: boolean; onChange?: (event: ChangeEvent) => void; diff --git a/src/settings/ProfileSettingsTab.tsx b/src/settings/ProfileSettingsTab.tsx index 7e32568..023a7cd 100644 --- a/src/settings/ProfileSettingsTab.tsx +++ b/src/settings/ProfileSettingsTab.tsx @@ -14,11 +14,10 @@ See the License for the specific language governing permissions and limitations under the License. */ -import React, { ChangeEvent, useCallback, useState } from "react"; +import React, { useCallback, useEffect, useRef } from "react"; import { MatrixClient } from "matrix-js-sdk/src/client"; import { useTranslation } from "react-i18next"; -import { Button } from "../button"; import { useProfile } from "../profile/useProfile"; import { FieldRow, InputField, ErrorMessage } from "../input/Input"; import { AvatarInputField } from "../input/AvatarInputField"; @@ -29,52 +28,47 @@ interface Props { } export function ProfileSettingsTab({ client }: Props) { const { t } = useTranslation(); - const { - error, - loading, - displayName: initialDisplayName, - avatarUrl, - saveProfile, - } = useProfile(client); - const [displayName, setDisplayName] = useState(initialDisplayName || ""); - const [removeAvatar, setRemoveAvatar] = useState(false); + const { error, displayName, avatarUrl, saveProfile } = useProfile(client); - const onRemoveAvatar = useCallback(() => { - setRemoveAvatar(true); + const formRef = useRef(null); + + const formChanged = useRef(false); + const onFormChange = useCallback(() => { + formChanged.current = true; }, []); - const onChangeDisplayName = useCallback( - (e: ChangeEvent) => { - setDisplayName(e.target.value); - }, - [setDisplayName] - ); + const removeAvatar = useRef(false); + const onRemoveAvatar = useCallback(() => { + removeAvatar.current = true; + formChanged.current = true; + }, []); - const onSubmit = useCallback( - (e) => { - e.preventDefault(); - const data = new FormData(e.target); - const displayNameDataEntry = data.get("displayName"); - const avatar: File | string = data.get("avatar"); + useEffect(() => { + const form = formRef.current!; + return () => { + if (formChanged.current) { + const data = new FormData(form); + const displayNameDataEntry = data.get("displayName"); + const avatar = data.get("avatar"); - const avatarSize = - typeof avatar == "string" ? avatar.length : avatar.size; - const displayName = - typeof displayNameDataEntry == "string" - ? displayNameDataEntry - : displayNameDataEntry.name; + const avatarSize = + typeof avatar == "string" ? avatar.length : avatar?.size ?? 0; + const displayName = + typeof displayNameDataEntry == "string" + ? displayNameDataEntry + : displayNameDataEntry?.name ?? null; - saveProfile({ - displayName, - avatar: avatar && avatarSize > 0 ? avatar : undefined, - removeAvatar: removeAvatar && (!avatar || avatarSize === 0), - }); - }, - [saveProfile, removeAvatar] - ); + saveProfile({ + displayName, + avatar: avatar && avatarSize > 0 ? avatar : undefined, + removeAvatar: removeAvatar.current && (!avatar || avatarSize === 0), + }); + } + }; + }, [saveProfile]); return ( -
+ @@ -104,8 +98,7 @@ export function ProfileSettingsTab({ client }: Props) { required autoComplete="off" placeholder={t("Display name")} - value={displayName} - onChange={onChangeDisplayName} + defaultValue={displayName} data-testid="profile_displayname" /> @@ -114,11 +107,6 @@ export function ProfileSettingsTab({ client }: Props) { )} - - - ); } diff --git a/src/settings/useMediaHandler.tsx b/src/settings/useMediaHandler.tsx index bf62eeb..0d84996 100644 --- a/src/settings/useMediaHandler.tsx +++ b/src/settings/useMediaHandler.tsx @@ -25,8 +25,8 @@ import React, { ReactNode, useRef, } from "react"; -import { useClient } from "../ClientContext"; +import { useClient } from "../ClientContext"; import { getNamedDevices } from "../media-utils"; export interface MediaHandlerContextInterface {