2022-05-04 17:09:48 +01:00
|
|
|
/*
|
2024-09-06 10:22:13 +02:00
|
|
|
Copyright 2022-2024 New Vector Ltd.
|
2022-05-04 17:09:48 +01:00
|
|
|
|
2025-02-18 17:59:58 +00:00
|
|
|
SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
2024-09-06 10:22:13 +02:00
|
|
|
Please see LICENSE in the repository root for full details.
|
2022-05-04 17:09:48 +01:00
|
|
|
*/
|
|
|
|
|
|
2025-03-13 16:58:14 +01:00
|
|
|
import {
|
|
|
|
|
type MatrixEvent,
|
|
|
|
|
type User,
|
2025-03-13 18:36:01 +01:00
|
|
|
type MatrixClient,
|
2025-03-13 16:58:14 +01:00
|
|
|
UserEvent,
|
|
|
|
|
type FileType,
|
|
|
|
|
} from "matrix-js-sdk";
|
2022-01-05 17:19:03 -08:00
|
|
|
import { useState, useCallback, useEffect } from "react";
|
2025-03-13 13:58:43 +01:00
|
|
|
import { logger } from "matrix-js-sdk/lib/logger";
|
2022-01-05 17:19:03 -08:00
|
|
|
|
2022-06-11 15:14:00 +02:00
|
|
|
interface ProfileLoadState {
|
2023-06-30 16:43:28 +01:00
|
|
|
success: boolean;
|
|
|
|
|
loading: boolean;
|
|
|
|
|
displayName?: string;
|
|
|
|
|
avatarUrl?: string;
|
2022-06-11 15:14:00 +02:00
|
|
|
error?: Error;
|
2022-06-06 22:33:13 +02:00
|
|
|
}
|
2022-06-11 15:14:00 +02:00
|
|
|
|
|
|
|
|
type ProfileSaveCallback = ({
|
|
|
|
|
displayName,
|
|
|
|
|
avatar,
|
|
|
|
|
removeAvatar,
|
|
|
|
|
}: {
|
|
|
|
|
displayName: string;
|
|
|
|
|
avatar: FileType;
|
|
|
|
|
removeAvatar: boolean;
|
|
|
|
|
}) => Promise<void>;
|
|
|
|
|
|
2023-09-22 18:05:13 -04:00
|
|
|
interface UseProfile extends ProfileLoadState {
|
|
|
|
|
saveProfile: ProfileSaveCallback;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function useProfile(client: MatrixClient | undefined): UseProfile {
|
2023-06-30 16:43:28 +01:00
|
|
|
const [{ success, loading, displayName, avatarUrl, error }, setState] =
|
2022-06-11 15:14:00 +02:00
|
|
|
useState<ProfileLoadState>(() => {
|
2023-06-30 16:43:28 +01:00
|
|
|
let user: User | undefined = undefined;
|
|
|
|
|
if (client) {
|
|
|
|
|
user = client.getUser(client.getUserId()!) ?? undefined;
|
|
|
|
|
}
|
2022-01-05 17:19:03 -08:00
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
success: false,
|
|
|
|
|
loading: false,
|
2022-02-23 16:41:12 -08:00
|
|
|
displayName: user?.rawDisplayName,
|
2022-05-18 19:00:59 -04:00
|
|
|
avatarUrl: user?.avatarUrl,
|
2023-06-30 16:43:28 +01:00
|
|
|
error: undefined,
|
2022-01-05 17:19:03 -08:00
|
|
|
};
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
2022-06-11 15:14:00 +02:00
|
|
|
const onChangeUser = (
|
2023-06-30 16:43:28 +01:00
|
|
|
_event: MatrixEvent | undefined,
|
2023-10-11 10:42:04 -04:00
|
|
|
{ displayName, avatarUrl }: User,
|
2023-09-22 18:05:13 -04:00
|
|
|
): void => {
|
2022-01-05 17:19:03 -08:00
|
|
|
setState({
|
|
|
|
|
success: false,
|
|
|
|
|
loading: false,
|
|
|
|
|
displayName,
|
2022-05-18 19:00:59 -04:00
|
|
|
avatarUrl,
|
2023-06-30 16:43:28 +01:00
|
|
|
error: undefined,
|
2022-01-05 17:19:03 -08:00
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
2023-06-30 16:43:28 +01:00
|
|
|
let user: User | null;
|
2022-01-05 17:19:03 -08:00
|
|
|
if (client) {
|
2023-06-30 16:43:28 +01:00
|
|
|
const userId = client.getUserId()!;
|
2022-01-05 17:19:03 -08:00
|
|
|
user = client.getUser(userId);
|
2023-06-30 16:43:28 +01:00
|
|
|
user?.on(UserEvent.DisplayName, onChangeUser);
|
|
|
|
|
user?.on(UserEvent.AvatarUrl, onChangeUser);
|
2022-01-05 17:19:03 -08:00
|
|
|
}
|
|
|
|
|
|
2024-06-04 11:20:25 -04:00
|
|
|
return (): void => {
|
2022-01-05 17:19:03 -08:00
|
|
|
if (user) {
|
2022-06-11 15:14:00 +02:00
|
|
|
user.removeListener(UserEvent.DisplayName, onChangeUser);
|
|
|
|
|
user.removeListener(UserEvent.AvatarUrl, onChangeUser);
|
2022-01-05 17:19:03 -08:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
}, [client]);
|
|
|
|
|
|
2022-06-11 15:14:00 +02:00
|
|
|
const saveProfile = useCallback<ProfileSaveCallback>(
|
2022-02-18 16:02:27 -08:00
|
|
|
async ({ displayName, avatar, removeAvatar }) => {
|
2022-01-05 17:19:03 -08:00
|
|
|
if (client) {
|
|
|
|
|
setState((prev) => ({
|
|
|
|
|
...prev,
|
|
|
|
|
loading: true,
|
2023-06-30 16:43:28 +01:00
|
|
|
error: undefined,
|
2022-01-05 17:19:03 -08:00
|
|
|
success: false,
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
await client.setDisplayName(displayName);
|
|
|
|
|
|
2022-06-06 22:33:13 +02:00
|
|
|
let mxcAvatarUrl: string;
|
2022-01-05 17:19:03 -08:00
|
|
|
|
2022-02-18 16:02:27 -08:00
|
|
|
if (removeAvatar) {
|
|
|
|
|
await client.setAvatarUrl("");
|
|
|
|
|
} else if (avatar) {
|
2023-10-11 10:42:04 -04:00
|
|
|
({ content_uri: mxcAvatarUrl } =
|
|
|
|
|
await client.uploadContent(avatar));
|
2022-01-05 17:19:03 -08:00
|
|
|
await client.setAvatarUrl(mxcAvatarUrl);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
setState((prev) => ({
|
|
|
|
|
...prev,
|
|
|
|
|
displayName,
|
2023-06-30 16:43:28 +01:00
|
|
|
avatarUrl: removeAvatar
|
|
|
|
|
? undefined
|
2024-07-17 10:07:26 +02:00
|
|
|
: (mxcAvatarUrl ?? prev.avatarUrl),
|
2022-01-05 17:19:03 -08:00
|
|
|
loading: false,
|
|
|
|
|
success: true,
|
|
|
|
|
}));
|
2022-06-11 15:14:00 +02:00
|
|
|
} catch (error: unknown) {
|
2022-01-05 17:19:03 -08:00
|
|
|
setState((prev) => ({
|
|
|
|
|
...prev,
|
|
|
|
|
loading: false,
|
2022-06-11 15:14:00 +02:00
|
|
|
error: error instanceof Error ? error : Error(error as string),
|
2022-01-05 17:19:03 -08:00
|
|
|
success: false,
|
|
|
|
|
}));
|
|
|
|
|
}
|
|
|
|
|
} else {
|
2023-09-25 18:04:34 +01:00
|
|
|
logger.error("Client not initialized before calling saveProfile");
|
2022-01-05 17:19:03 -08:00
|
|
|
}
|
|
|
|
|
},
|
2023-10-11 10:42:04 -04:00
|
|
|
[client],
|
2022-01-05 17:19:03 -08:00
|
|
|
);
|
|
|
|
|
|
2022-06-11 15:14:00 +02:00
|
|
|
return {
|
|
|
|
|
loading,
|
|
|
|
|
error,
|
|
|
|
|
displayName,
|
|
|
|
|
avatarUrl,
|
|
|
|
|
saveProfile,
|
|
|
|
|
success,
|
|
|
|
|
};
|
2022-01-05 17:19:03 -08:00
|
|
|
}
|