mirror of
https://github.com/vector-im/element-call.git
synced 2026-08-29 21:15:19 +00:00
Add widget behaviour and test.
This commit is contained in:
@@ -14,10 +14,9 @@ import { ClientContextProvider } from "./ClientContext";
|
|||||||
import { Avatar } from "./Avatar";
|
import { Avatar } from "./Avatar";
|
||||||
import { mockMatrixRoomMember } from "./utils/test";
|
import { mockMatrixRoomMember } from "./utils/test";
|
||||||
|
|
||||||
const TestComponent: FC<PropsWithChildren<{ client: MatrixClient }>> = ({
|
const TestComponent: FC<
|
||||||
client,
|
PropsWithChildren<{ client: MatrixClient; supportsThumbnails?: boolean }>
|
||||||
children,
|
> = ({ client, children, supportsThumbnails }) => {
|
||||||
}) => {
|
|
||||||
return (
|
return (
|
||||||
<ClientContextProvider
|
<ClientContextProvider
|
||||||
value={{
|
value={{
|
||||||
@@ -25,6 +24,7 @@ const TestComponent: FC<PropsWithChildren<{ client: MatrixClient }>> = ({
|
|||||||
disconnected: false,
|
disconnected: false,
|
||||||
supportedFeatures: {
|
supportedFeatures: {
|
||||||
reactions: true,
|
reactions: true,
|
||||||
|
thumbnails: supportsThumbnails ?? true,
|
||||||
},
|
},
|
||||||
setClient: vi.fn(),
|
setClient: vi.fn(),
|
||||||
authenticated: {
|
authenticated: {
|
||||||
@@ -70,6 +70,34 @@ test("should just render a placeholder when the user has no avatar", () => {
|
|||||||
expect(element.tagName).toEqual("SPAN");
|
expect(element.tagName).toEqual("SPAN");
|
||||||
expect(client.mxcUrlToHttp).toBeCalledTimes(0);
|
expect(client.mxcUrlToHttp).toBeCalledTimes(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("should just render a placeholder when thumbnaisl are not supported", () => {
|
||||||
|
const client = vi.mocked<MatrixClient>({
|
||||||
|
getAccessToken: () => "my-access-token",
|
||||||
|
mxcUrlToHttp: () => vi.fn(),
|
||||||
|
} as unknown as MatrixClient);
|
||||||
|
|
||||||
|
vi.spyOn(client, "mxcUrlToHttp");
|
||||||
|
const member = mockMatrixRoomMember({
|
||||||
|
userId: "@alice:example.org",
|
||||||
|
getMxcAvatarUrl: () => "mxc://example.org/alice-avatar",
|
||||||
|
});
|
||||||
|
const displayName = "Alice";
|
||||||
|
render(
|
||||||
|
<TestComponent client={client} supportsThumbnails={false}>
|
||||||
|
<Avatar
|
||||||
|
id={member.userId}
|
||||||
|
name={displayName}
|
||||||
|
size={96}
|
||||||
|
src={member?.getMxcAvatarUrl()}
|
||||||
|
/>
|
||||||
|
</TestComponent>,
|
||||||
|
);
|
||||||
|
const element = screen.getByRole("img", { name: "@alice:example.org" });
|
||||||
|
expect(element.tagName).toEqual("SPAN");
|
||||||
|
expect(client.mxcUrlToHttp).toBeCalledTimes(0);
|
||||||
|
});
|
||||||
|
|
||||||
test("should attempt to fetch authenticated media", async () => {
|
test("should attempt to fetch authenticated media", async () => {
|
||||||
const expectedAuthUrl = "http://example.org/media/alice-avatar";
|
const expectedAuthUrl = "http://example.org/media/alice-avatar";
|
||||||
const expectedObjectURL = "my-object-url";
|
const expectedObjectURL = "my-object-url";
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import { useMemo, FC, CSSProperties, useState, useEffect } from "react";
|
|||||||
import { Avatar as CompoundAvatar } from "@vector-im/compound-web";
|
import { Avatar as CompoundAvatar } from "@vector-im/compound-web";
|
||||||
import { MatrixClient } from "matrix-js-sdk/src/client";
|
import { MatrixClient } from "matrix-js-sdk/src/client";
|
||||||
|
|
||||||
import { useClient } from "./ClientContext";
|
import { useClientState } from "./ClientContext";
|
||||||
|
|
||||||
export enum Size {
|
export enum Size {
|
||||||
XS = "xs",
|
XS = "xs",
|
||||||
@@ -67,7 +67,7 @@ export const Avatar: FC<Props> = ({
|
|||||||
style,
|
style,
|
||||||
...props
|
...props
|
||||||
}) => {
|
}) => {
|
||||||
const { client } = useClient();
|
const clientState = useClientState();
|
||||||
|
|
||||||
const sizePx = useMemo(
|
const sizePx = useMemo(
|
||||||
() =>
|
() =>
|
||||||
@@ -80,9 +80,16 @@ export const Avatar: FC<Props> = ({
|
|||||||
const [avatarUrl, setAvatarUrl] = useState<string | undefined>(undefined);
|
const [avatarUrl, setAvatarUrl] = useState<string | undefined>(undefined);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!client || !src || !sizePx) {
|
if (clientState?.state !== "valid") {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
const { authenticated, supportedFeatures } = clientState;
|
||||||
|
const client = authenticated?.client;
|
||||||
|
|
||||||
|
if (!client || !src || !sizePx || !supportedFeatures.thumbnails) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const token = client.getAccessToken();
|
const token = client.getAccessToken();
|
||||||
if (!token) {
|
if (!token) {
|
||||||
return;
|
return;
|
||||||
@@ -113,7 +120,7 @@ export const Avatar: FC<Props> = ({
|
|||||||
URL.revokeObjectURL(objectUrl);
|
URL.revokeObjectURL(objectUrl);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}, [client, src, sizePx]);
|
}, [clientState, src, sizePx]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CompoundAvatar
|
<CompoundAvatar
|
||||||
|
|||||||
@@ -48,6 +48,7 @@ export type ValidClientState = {
|
|||||||
disconnected: boolean;
|
disconnected: boolean;
|
||||||
supportedFeatures: {
|
supportedFeatures: {
|
||||||
reactions: boolean;
|
reactions: boolean;
|
||||||
|
thumbnails: boolean;
|
||||||
};
|
};
|
||||||
setClient: (params?: SetClientParams) => void;
|
setClient: (params?: SetClientParams) => void;
|
||||||
};
|
};
|
||||||
@@ -255,6 +256,7 @@ export const ClientProvider: FC<Props> = ({ children }) => {
|
|||||||
|
|
||||||
const [isDisconnected, setIsDisconnected] = useState(false);
|
const [isDisconnected, setIsDisconnected] = useState(false);
|
||||||
const [supportsReactions, setSupportsReactions] = useState(false);
|
const [supportsReactions, setSupportsReactions] = useState(false);
|
||||||
|
const [supportsThumbnails, setSupportsThumbnails] = useState(false);
|
||||||
|
|
||||||
const state: ClientState | undefined = useMemo(() => {
|
const state: ClientState | undefined = useMemo(() => {
|
||||||
if (alreadyOpenedErr) {
|
if (alreadyOpenedErr) {
|
||||||
@@ -280,6 +282,7 @@ export const ClientProvider: FC<Props> = ({ children }) => {
|
|||||||
disconnected: isDisconnected,
|
disconnected: isDisconnected,
|
||||||
supportedFeatures: {
|
supportedFeatures: {
|
||||||
reactions: supportsReactions,
|
reactions: supportsReactions,
|
||||||
|
thumbnails: supportsThumbnails,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}, [
|
}, [
|
||||||
@@ -290,6 +293,7 @@ export const ClientProvider: FC<Props> = ({ children }) => {
|
|||||||
setClient,
|
setClient,
|
||||||
isDisconnected,
|
isDisconnected,
|
||||||
supportsReactions,
|
supportsReactions,
|
||||||
|
supportsThumbnails,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const onSync = useCallback(
|
const onSync = useCallback(
|
||||||
@@ -315,6 +319,8 @@ export const ClientProvider: FC<Props> = ({ children }) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (initClientState.widgetApi) {
|
if (initClientState.widgetApi) {
|
||||||
|
// There is currently no widget API for authenticated media thumbnails.
|
||||||
|
setSupportsThumbnails(false);
|
||||||
const reactSend = initClientState.widgetApi.hasCapability(
|
const reactSend = initClientState.widgetApi.hasCapability(
|
||||||
"org.matrix.msc2762.send.event:m.reaction",
|
"org.matrix.msc2762.send.event:m.reaction",
|
||||||
);
|
);
|
||||||
@@ -336,6 +342,7 @@ export const ClientProvider: FC<Props> = ({ children }) => {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
setSupportsReactions(true);
|
setSupportsReactions(true);
|
||||||
|
setSupportsThumbnails(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (): void => {
|
return (): void => {
|
||||||
|
|||||||
Reference in New Issue
Block a user