Merge pull request #144 from matrix-org/thumbnails

Use thumbnails api instead of mxc download
This commit is contained in:
Jorik Schellekens 2020-09-24 10:49:18 +01:00 committed by GitHub
commit 32c6119243
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 133 additions and 32 deletions

View file

@ -16,13 +16,16 @@ limitations under the License.
import React, { useEffect, useState } from 'react';
import classNames from 'classnames';
import { Group, Room, User } from '../matrix-cypher';
import { getMediaQueryFromMCX } from '../utils/cypher-wrapper';
import { Group, Room, User } from '../matrix-cypher';
import useHSs from '../utils/getHS';
import { getThumbnailURI } from '../utils/cypher-wrapper';
import logo from '../imgs/chat-icon.svg';
import './Avatar.scss';
const AVATAR_SIZE = 96;
interface IProps {
className?: string;
avatarUrl: string;
@ -56,12 +59,20 @@ interface IPropsUserAvatar {
export const UserAvatar: React.FC<IPropsUserAvatar> = ({
user,
userId,
}: IPropsUserAvatar) => (
<Avatar
avatarUrl={getMediaQueryFromMCX(user.avatar_url)}
label={user.displayname ? user.displayname : userId}
/>
);
}: IPropsUserAvatar) => {
const [hs] = useHSs({ identifier: userId });
return (
<Avatar
avatarUrl={getThumbnailURI(
hs,
AVATAR_SIZE,
AVATAR_SIZE,
user.avatar_url
)}
label={user.displayname ? user.displayname : userId}
/>
);
};
interface IPropsRoomAvatar {
room: Room;
@ -69,24 +80,42 @@ interface IPropsRoomAvatar {
export const RoomAvatar: React.FC<IPropsRoomAvatar> = ({
room,
}: IPropsRoomAvatar) => (
<Avatar
avatarUrl={getMediaQueryFromMCX(room.avatar_url)}
label={room.name || room.room_id}
/>
);
}: IPropsRoomAvatar) => {
const [hs] = useHSs({ identifier: room.room_id });
return (
<Avatar
avatarUrl={getThumbnailURI(
hs,
AVATAR_SIZE,
AVATAR_SIZE,
room.avatar_url
)}
label={room.name || room.room_id}
/>
);
};
interface IPropsGroupAvatar {
group: Group;
groupId: string;
}
export const GroupAvatar: React.FC<IPropsGroupAvatar> = ({
group,
}: IPropsGroupAvatar) => (
<Avatar
avatarUrl={getMediaQueryFromMCX(group.avatar_url)}
label={group.name}
/>
);
groupId,
}: IPropsGroupAvatar) => {
const [hs] = useHSs({ identifier: groupId });
return (
<Avatar
avatarUrl={getThumbnailURI(
hs,
AVATAR_SIZE,
AVATAR_SIZE,
group.avatar_url
)}
label={group.name}
/>
);
};
export default Avatar;

View file

@ -23,9 +23,10 @@ import './GroupPreview.scss';
interface IProps {
group: Group;
groupId: string;
}
const GroupPreview: React.FC<IProps> = ({ group }: IProps) => {
const GroupPreview: React.FC<IProps> = ({ group, groupId }: IProps) => {
const description = group.long_description
? group.long_description
: group.short_description
@ -34,7 +35,7 @@ const GroupPreview: React.FC<IProps> = ({ group }: IProps) => {
return (
<div className="groupPreview">
<GroupAvatar group={group} />
<GroupAvatar group={group} groupId={groupId}/>
<h1>{group.name}</h1>
{description ? <p>{description}</p> : null}
</div>

View file

@ -92,6 +92,7 @@ const invite = async ({
return (
<GroupPreview
group={await getGroup(clientAddress, link.identifier)}
groupId={link.identifier}
/>
);
@ -126,7 +127,7 @@ const LinkPreview: React.FC<IProps> = ({ link }: IProps) => {
let content: JSX.Element;
const [showHSOptions, setShowHSOPtions] = useState(false);
const hses = useHSs(link);
const hses = useHSs({link});
if (!hses.length) {
content = (

View file

@ -84,7 +84,7 @@ export const WrappedInviterPreview: React.FC<WrappedInviterProps> = ({
link,
}: WrappedInviterProps) => {
const [user, setUser] = useState<User | undefined>(undefined);
const hss = useHSs(link);
const hss = useHSs({link});
useEffect(() => {
if (hss.length) {
client(hss[0])

View file

@ -182,6 +182,21 @@ export async function getGroupDetails(
.then(GroupSchema.parse);
}
export function getThumbnailURI(
clientURL: string,
mxcId: string,
height: number,
width: number,
): string {
const mxcParse = mxcId.match(/mxc:\/\/(?<server>.+)\/(?<mediaId>.+)/);
if (!mxcParse || !mxcParse.groups) {
throw new Error(`mxc invalid. mxc: ${mxcId}`);
}
// eslint-disable-next-line max-len
return `https://${clientURL}/_matrix/media/r0/thumbnail/${mxcParse.groups.server}/${mxcParse.groups.mediaId}?height=${height}&width=${width}&method=crop`;
}
/*
* Gets an mxc resource
*/

View file

@ -30,6 +30,7 @@ import {
getUserDetails,
convertMXCtoMediaQuery,
getGroupDetails,
getThumbnailURI as cypherGetThumbnailURI,
} from '../matrix-cypher';
import { LinkKind, Permalink } from '../parser/types';
@ -177,6 +178,24 @@ export function getMediaQueryFromMCX(mxc?: string): string {
}
}
export function getThumbnailURI(
clientURL: string,
height: number,
width: number,
mxcId?: string,
): string {
if (!mxcId) {
return '';
}
try {
return cypherGetThumbnailURI(clientURL, mxcId, height, width);
} catch (e){
console.error(e);
return '';
}
}
export async function getGroup(
clientURL: string,
groupId: string

View file

@ -22,7 +22,34 @@ import HSContext, {
} from '../contexts/HSContext';
import { SafeLink } from '../parser/types';
function selectedClient(link: SafeLink, hsOptions: State): string[] {
function selectedClient({ link, identifier, hsOptions }: {
link?: SafeLink,
identifier?: string;
hsOptions: State
}): string[] {
const linkHSs = link ? [
...link.identifier
.split('/')
.map((i) => 'https://' + i.split(':')[1]),
...link.arguments.vias,
] : [];
const identifierHS: string[] = [];
try {
if (identifier) {
const match = identifier.match(/^.*:(?<server>.*)$/);
if (match && match.groups) {
const server = match.groups.server;
if (server) {
identifierHS.push(server);
}
}
}
} catch (e) {
console.error(`Could parse user identifier: ${identifier}`);
console.error(e);
}
switch (hsOptions.option) {
case HSOptions.Unset:
return [];
@ -30,22 +57,31 @@ function selectedClient(link: SafeLink, hsOptions: State): string[] {
return [hsOptions.hs];
case HSOptions.Any:
return [
...link.identifier
.split('/')
.map((i) => 'https://' + i.split(':')[1]),
...link.arguments.vias,
...linkHSs,
...identifierHS,
];
}
}
export default function useHSs(link: SafeLink): string[] {
export default function useHSs({ link, identifier }: {
link?: SafeLink,
identifier?: string,
}): string[] {
const [HSState] = useContext(HSContext);
const [TempHSState] = useContext(TempHSContext);
if (HSState.option !== HSOptions.Unset) {
return selectedClient(link, HSState);
return selectedClient({
link,
identifier,
hsOptions: HSState
});
} else if (TempHSState.option !== HSOptions.Unset) {
return selectedClient(link, TempHSState);
return selectedClient({
link,
identifier,
hsOptions: TempHSState
});
} else {
return [];
}