Download Avatar from relevent source

Instead of relying on failures directly use the
available method to download the avatar.
This commit is contained in:
JephDiel
2026-03-09 22:25:54 -05:00
parent 005b965fba
commit 699e31f59a
4 changed files with 47 additions and 76 deletions

View File

@@ -15,7 +15,7 @@ import {
import { Avatar as CompoundAvatar } from "@vector-im/compound-web";
import { type MatrixClient } from "matrix-js-sdk";
import { ClientState, useClientState } from "./ClientContext";
import { useClientState } from "./ClientContext";
import { widget } from "./widget";
import { WidgetApi } from "matrix-widget-api";
@@ -80,7 +80,7 @@ export const Avatar: FC<Props> = ({
const sizePx = useMemo(
() =>
Object.values(Size).includes(size as Size)
? sizes.get(size as Size)
? sizes.get(size as Size)!
: (size as number),
[size],
);
@@ -88,17 +88,29 @@ export const Avatar: FC<Props> = ({
const [avatarUrl, setAvatarUrl] = useState<string | undefined>(undefined);
useEffect(() => {
if (!src) {
if (!src || clientState?.state !== "valid") {
setAvatarUrl(undefined);
return;
}
const { authenticated, supportedFeatures } = clientState;
let blob: Promise<Blob>;
if (
supportedFeatures.authenticatedMedia &&
authenticated?.client &&
sizePx
) {
blob = getAvatarFromServer(authenticated.client, src, sizePx);
} else if (widget?.api) {
blob = getAvatarFromWidgetAPI(widget.api, src);
} else {
setAvatarUrl(undefined);
return;
}
let objectUrl: string | undefined;
getAvatarFromServer(clientState, src, sizePx) // Try to download directly from the mxc://
.catch((ex) => {
return getAvatarFromWidget(widget?.api, src); // Fallback to trying to use the MSC4039 Widget API
})
blob
.then((blob) => {
objectUrl = URL.createObjectURL(blob);
setAvatarUrl(objectUrl);
@@ -128,26 +140,10 @@ export const Avatar: FC<Props> = ({
};
async function getAvatarFromServer(
clientState: ClientState | undefined,
client: MatrixClient,
src: string,
sizePx: number | undefined,
sizePx: number,
): Promise<Blob> {
if (clientState?.state !== "valid") {
throw new Error("Client state must be valid");
}
if (!sizePx) {
throw new Error("size must be supplied");
}
const { authenticated, supportedFeatures } = clientState;
const client = authenticated?.client;
if (!client) {
throw new Error("Client must be supplied");
}
if (!supportedFeatures.thumbnails) {
throw new Error("Thumbnails are not supported");
}
const httpSrc = getAvatarUrl(client, src, sizePx);
if (!httpSrc) {
throw new Error("Failed to get http avatar URL");
@@ -169,14 +165,10 @@ async function getAvatarFromServer(
return blob;
}
async function getAvatarFromWidget(
api: WidgetApi | undefined,
async function getAvatarFromWidgetAPI(
api: WidgetApi,
src: string,
): Promise<Blob> {
if (!api) {
throw new Error("No widget api given");
}
const response = await api.downloadFile(src);
const file = response.file;