mirror of
https://github.com/vector-im/element-call.git
synced 2026-03-31 07:00:26 +00:00
Load authenicated media
This commit is contained in:
@@ -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}
|
||||
/>
|
||||
|
||||
@@ -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)!;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user