Load authenicated media

This commit is contained in:
Will Hunt
2024-12-02 13:54:00 +00:00
parent e142493380
commit 773492d458
2 changed files with 46 additions and 19 deletions

View File

@@ -5,11 +5,11 @@ SPDX-License-Identifier: AGPL-3.0-only
Please see LICENSE in the repository root for full details.
*/
import { useMemo, FC, CSSProperties } from "react";
import { useMemo, FC, CSSProperties, useState, useEffect } from "react";
import { Avatar as CompoundAvatar } from "@vector-im/compound-web";
import { getAvatarUrl } from "./utils/matrix";
import { useClient } from "./ClientContext";
import { MatrixClient } from "matrix-js-sdk/src/client";
export enum Size {
XS = "xs",
@@ -36,6 +36,18 @@ interface Props {
style?: CSSProperties;
}
export function getAvatarUrl(
client: MatrixClient,
mxcUrl: string|null,
avatarSize = 96,
): string|null {
const width = Math.floor(avatarSize * window.devicePixelRatio);
const height = Math.floor(avatarSize * window.devicePixelRatio);
// scale is more suitable for larger sizes
const resizeMethod = avatarSize <= 96 ? "crop" : "scale";
return mxcUrl ? client.mxcUrlToHttp(mxcUrl, width, height, resizeMethod, false, true, true) : null;
}
export const Avatar: FC<Props> = ({
className,
id,
@@ -55,9 +67,36 @@ export const Avatar: FC<Props> = ({
[size],
);
const resolvedSrc = useMemo(() => {
if (!client || !src || !sizePx) return undefined;
return src.startsWith("mxc://") ? getAvatarUrl(client, src, sizePx) : src;
const [avatarUrl, setAvatarUrl] = useState<string|undefined>(undefined);
useEffect(() => {
if (!client || !src || !sizePx) {
return;
};
const token = client.getAccessToken();
if (!token) {
return;
}
const resolveSrc = getAvatarUrl(client, src, sizePx);
if (!resolveSrc) {
setAvatarUrl(undefined);
return;
}
let objectUrl: string|undefined;
fetch(resolveSrc, {
headers: {
'Authorization': `Bearer ${token}`
}
}).then((req) => req.blob()).then((res) => {
objectUrl = URL.createObjectURL(res);
setAvatarUrl(objectUrl);
}).catch((ex) => {
console.warn("Failed to get avatar URL", ex);
setAvatarUrl(undefined);
});
() => objectUrl && URL.revokeObjectURL(objectUrl);
}, [client, src, sizePx]);
return (
@@ -66,7 +105,7 @@ export const Avatar: FC<Props> = ({
id={id}
name={name}
size={`${sizePx}px`}
src={resolvedSrc}
src={avatarUrl}
style={style}
{...props}
/>

View File

@@ -332,16 +332,4 @@ export function getRelativeRoomUrl(
? "/" + roomAliasLocalpartFromRoomName(roomName)
: "";
return `/room/#${roomPart}?${generateUrlSearchParams(roomId, encryptionSystem, viaServers).toString()}`;
}
export function getAvatarUrl(
client: MatrixClient,
mxcUrl: string,
avatarSize = 96,
): string {
const width = Math.floor(avatarSize * window.devicePixelRatio);
const height = Math.floor(avatarSize * window.devicePixelRatio);
// scale is more suitable for larger sizes
const resizeMethod = avatarSize <= 96 ? "crop" : "scale";
return mxcUrl && client.mxcUrlToHttp(mxcUrl, width, height, resizeMethod)!;
}
}