Files
element-call/src/settings/ProfileSettingsTab.tsx

118 lines
3.4 KiB
TypeScript
Raw Normal View History

2022-05-04 17:09:48 +01:00
/*
Copyright 2022-2024 New Vector Ltd.
2022-05-04 17:09:48 +01:00
SPDX-License-Identifier: AGPL-3.0-only
Please see LICENSE in the repository root for full details.
2022-05-04 17:09:48 +01:00
*/
import { FC, useCallback, useEffect, useMemo, useRef } from "react";
2022-08-12 16:46:53 -04:00
import { MatrixClient } from "matrix-js-sdk/src/client";
2022-10-10 09:19:10 -04:00
import { useTranslation } from "react-i18next";
import { logger } from "matrix-js-sdk/src/logger";
2022-06-06 22:33:13 +02:00
import { useProfile } from "../profile/useProfile";
2022-01-05 17:27:01 -08:00
import { FieldRow, InputField, ErrorMessage } from "../input/Input";
2022-02-18 16:02:27 -08:00
import { AvatarInputField } from "../input/AvatarInputField";
import styles from "./ProfileSettingsTab.module.css";
2021-12-13 14:54:44 -08:00
2022-06-06 22:33:13 +02:00
interface Props {
client: MatrixClient;
}
export const ProfileSettingsTab: FC<Props> = ({ client }) => {
2022-10-10 09:19:10 -04:00
const { t } = useTranslation();
2023-05-22 14:33:20 -04:00
const { error, displayName, avatarUrl, saveProfile } = useProfile(client);
const userId = useMemo(() => client.getUserId(), [client]);
2022-02-18 16:02:27 -08:00
2023-05-22 14:33:20 -04:00
const formRef = useRef<HTMLFormElement | null>(null);
const formChanged = useRef(false);
const onFormChange = useCallback(() => {
formChanged.current = true;
2022-02-18 16:02:27 -08:00
}, []);
2021-12-13 14:54:44 -08:00
2023-05-22 14:33:20 -04:00
const removeAvatar = useRef(false);
const onRemoveAvatar = useCallback(() => {
removeAvatar.current = true;
formChanged.current = true;
}, []);
2021-12-13 14:54:44 -08:00
2023-05-22 14:33:20 -04:00
useEffect(() => {
const form = formRef.current!;
2023-05-22 15:44:39 -04:00
// Auto-save when the user dismisses this component
2024-06-04 11:20:25 -04:00
return (): void => {
2023-05-22 14:33:20 -04:00
if (formChanged.current) {
const data = new FormData(form);
const displayNameDataEntry = data.get("displayName");
const avatar = data.get("avatar");
2022-06-11 15:14:00 +02:00
2023-05-22 14:33:20 -04:00
const avatarSize =
typeof avatar == "string" ? avatar.length : (avatar?.size ?? 0);
2023-05-22 14:33:20 -04:00
const displayName =
typeof displayNameDataEntry == "string"
? displayNameDataEntry
: (displayNameDataEntry?.name ?? null);
2022-06-11 15:14:00 +02:00
if (!displayName) {
return;
}
2023-05-22 14:33:20 -04:00
saveProfile({
displayName,
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
2023-05-22 14:33:20 -04:00
avatar: avatar && avatarSize > 0 ? avatar : undefined,
removeAvatar: removeAvatar.current && (!avatar || avatarSize === 0),
}).catch((e) => {
logger.error("Failed to save profile", e);
2023-05-22 14:33:20 -04:00
});
}
};
}, [saveProfile]);
2021-12-13 14:54:44 -08:00
return (
2023-05-22 14:33:20 -04:00
<form onChange={onFormChange} ref={formRef} className={styles.content}>
<FieldRow className={styles.avatarFieldRow}>
{userId && displayName && (
<AvatarInputField
id="avatar"
name="avatar"
label={t("common.avatar")}
avatarUrl={avatarUrl}
userId={userId}
displayName={displayName}
onRemoveAvatar={onRemoveAvatar}
/>
)}
</FieldRow>
<FieldRow>
<InputField
id="userId"
name="userId"
label={t("common.username")}
type="text"
disabled
2023-05-22 14:33:20 -04:00
value={client.getUserId()!}
/>
</FieldRow>
<FieldRow>
<InputField
id="displayName"
name="displayName"
label={t("common.display_name")}
type="text"
required
autoComplete="off"
placeholder={t("common.display_name")}
2023-05-22 14:33:20 -04:00
defaultValue={displayName}
data-testid="profile_displayname"
/>
</FieldRow>
{error && (
<FieldRow>
<ErrorMessage error={error} />
</FieldRow>
)}
</form>
2021-12-13 14:54:44 -08:00
);
};