Make the profile form autosave
This commit is contained in:
parent
85380c8142
commit
ae40dea7ec
3 changed files with 38 additions and 49 deletions
|
@ -72,6 +72,7 @@ interface InputFieldProps {
|
|||
autoCorrect?: string;
|
||||
autoCapitalize?: string;
|
||||
value?: string;
|
||||
defaultValue?: string;
|
||||
placeholder?: string;
|
||||
defaultChecked?: boolean;
|
||||
onChange?: (event: ChangeEvent) => void;
|
||||
|
|
|
@ -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<HTMLFormElement | null>(null);
|
||||
|
||||
const formChanged = useRef(false);
|
||||
const onFormChange = useCallback(() => {
|
||||
formChanged.current = true;
|
||||
}, []);
|
||||
|
||||
const onChangeDisplayName = useCallback(
|
||||
(e: ChangeEvent<HTMLInputElement>) => {
|
||||
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);
|
||||
useEffect(() => {
|
||||
const form = formRef.current!;
|
||||
return () => {
|
||||
if (formChanged.current) {
|
||||
const data = new FormData(form);
|
||||
const displayNameDataEntry = data.get("displayName");
|
||||
const avatar: File | string = data.get("avatar");
|
||||
const avatar = data.get("avatar");
|
||||
|
||||
const avatarSize =
|
||||
typeof avatar == "string" ? avatar.length : avatar.size;
|
||||
typeof avatar == "string" ? avatar.length : avatar?.size ?? 0;
|
||||
const displayName =
|
||||
typeof displayNameDataEntry == "string"
|
||||
? displayNameDataEntry
|
||||
: displayNameDataEntry.name;
|
||||
: displayNameDataEntry?.name ?? null;
|
||||
|
||||
saveProfile({
|
||||
displayName,
|
||||
avatar: avatar && avatarSize > 0 ? avatar : undefined,
|
||||
removeAvatar: removeAvatar && (!avatar || avatarSize === 0),
|
||||
removeAvatar: removeAvatar.current && (!avatar || avatarSize === 0),
|
||||
});
|
||||
},
|
||||
[saveProfile, removeAvatar]
|
||||
);
|
||||
}
|
||||
};
|
||||
}, [saveProfile]);
|
||||
|
||||
return (
|
||||
<form onSubmit={onSubmit} className={styles.content}>
|
||||
<form onChange={onFormChange} ref={formRef} className={styles.content}>
|
||||
<FieldRow className={styles.avatarFieldRow}>
|
||||
<AvatarInputField
|
||||
id="avatar"
|
||||
|
@ -92,7 +86,7 @@ export function ProfileSettingsTab({ client }: Props) {
|
|||
label={t("Username")}
|
||||
type="text"
|
||||
disabled
|
||||
value={client.getUserId()}
|
||||
value={client.getUserId()!}
|
||||
/>
|
||||
</FieldRow>
|
||||
<FieldRow>
|
||||
|
@ -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"
|
||||
/>
|
||||
</FieldRow>
|
||||
|
@ -114,11 +107,6 @@ export function ProfileSettingsTab({ client }: Props) {
|
|||
<ErrorMessage error={error} />
|
||||
</FieldRow>
|
||||
)}
|
||||
<FieldRow rightAlign>
|
||||
<Button type="submit" disabled={loading}>
|
||||
{loading ? t("Saving…") : t("Save")}
|
||||
</Button>
|
||||
</FieldRow>
|
||||
</form>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in a new issue