Implement better fallbacks

This commit is contained in:
Jorik Schellekens 2020-08-18 11:07:26 +01:00
parent 1ad11ed25f
commit 0ac4116b24
3 changed files with 122 additions and 97 deletions

View file

@ -18,7 +18,7 @@ import React, { useEffect, useState } from "react";
import classNames from "classnames"; import classNames from "classnames";
import { Room, User } from "matrix-cypher"; import { Room, User } from "matrix-cypher";
import { convertMXCtoMediaQuery } from "../utils/cypher-wrapper"; import { getMediaQueryFromMCX } from "../utils/cypher-wrapper";
import logo from "../imgs/matrix-logo.svg"; import logo from "../imgs/matrix-logo.svg";
import "./Avatar.scss"; import "./Avatar.scss";
@ -55,15 +55,7 @@ export const UserAvatar: React.FC<IPropsUserAvatar> = ({
userId, userId,
}: IPropsUserAvatar) => ( }: IPropsUserAvatar) => (
<Avatar <Avatar
avatarUrl={ avatarUrl={getMediaQueryFromMCX(user.avatar_url)}
user.avatar_url
? convertMXCtoMediaQuery(
// TODO: replace with correct client
"https://matrix.org",
user.avatar_url
)
: ""
}
label={user.displayname ? user.displayname : userId} label={user.displayname ? user.displayname : userId}
/> />
); );
@ -76,15 +68,7 @@ export const RoomAvatar: React.FC<IPropsRoomAvatar> = ({
room, room,
}: IPropsRoomAvatar) => ( }: IPropsRoomAvatar) => (
<Avatar <Avatar
avatarUrl={ avatarUrl={getMediaQueryFromMCX(room.avatar_url)}
room.avatar_url
? convertMXCtoMediaQuery(
// TODO: replace with correct client
"https://matrix.org",
room.avatar_url
)
: ""
}
label={room.name || room.room_id} label={room.name || room.room_id}
/> />
); );

View file

@ -15,46 +15,36 @@ limitations under the License.
*/ */
import React, { useState, useEffect } from "react"; import React, { useState, useEffect } from "react";
import { Client, getEvent, client } from "matrix-cypher"; import { getEvent, client } from "matrix-cypher";
import {
getRoomIdFromAlias,
searchPublicRooms,
getUserDetails,
} from "../utils/cypher-wrapper";
import { RoomPreviewWithTopic } from "./RoomPreview"; import { RoomPreviewWithTopic } from "./RoomPreview";
import InviteTile from "./InviteTile"; import InviteTile from "./InviteTile";
import { SafeLink, LinkKind } from "../parser/types";
import { SafeLink } from "../parser/types";
import { LinkKind } from "../parser/types";
import UserPreview from "./UserPreview"; import UserPreview from "./UserPreview";
import EventPreview from "./EventPreview"; import EventPreview from "./EventPreview";
import Clients from "../clients"; import Clients from "../clients";
import {
getRoomFromId,
getRoomFromAlias,
getRoomFromPermalink,
getUser,
} from "../utils/cypher-wrapper";
interface IProps { interface IProps {
link: SafeLink; link: SafeLink;
} }
// TODO: replace with client fetch
const defaultClient: () => Promise<Client> = () => client("https://matrix.org");
const LOADING: JSX.Element = <>Generating invite</>; const LOADING: JSX.Element = <>Generating invite</>;
const invite = async ({ link }: { link: SafeLink }): Promise<JSX.Element> => { const invite = async ({ link }: { link: SafeLink }): Promise<JSX.Element> => {
// TODO: replace with client fetch
const defaultClient = await client("https://matrix.org");
switch (link.kind) { switch (link.kind) {
case LinkKind.Alias: case LinkKind.Alias:
return ( return (
<RoomPreviewWithTopic <RoomPreviewWithTopic
room={ room={
await searchPublicRooms( await getRoomFromAlias(defaultClient, link.identifier)
await defaultClient(),
(
await getRoomIdFromAlias(
await defaultClient(),
link.identifier
)
).room_id
)
} }
/> />
); );
@ -62,24 +52,14 @@ const invite = async ({ link }: { link: SafeLink }): Promise<JSX.Element> => {
case LinkKind.RoomId: case LinkKind.RoomId:
return ( return (
<RoomPreviewWithTopic <RoomPreviewWithTopic
room={ room={await getRoomFromId(defaultClient, link.identifier)}
await searchPublicRooms(
await defaultClient(),
link.identifier
)
}
/> />
); );
case LinkKind.UserId: case LinkKind.UserId:
return ( return (
<UserPreview <UserPreview
user={ user={await getUser(defaultClient, link.identifier)}
await getUserDetails(
await defaultClient(),
link.identifier
)
}
userId={link.identifier} userId={link.identifier}
/> />
); );
@ -87,15 +67,10 @@ const invite = async ({ link }: { link: SafeLink }): Promise<JSX.Element> => {
case LinkKind.Permalink: case LinkKind.Permalink:
return ( return (
<EventPreview <EventPreview
room={ room={await getRoomFromPermalink(defaultClient, link)}
await searchPublicRooms(
await defaultClient(),
link.identifier
)
}
event={ event={
await getEvent( await getEvent(
await defaultClient(), defaultClient,
link.roomLink, link.roomLink,
link.eventId link.eventId
) )

View file

@ -16,73 +16,139 @@ limitations under the License.
import { import {
Client, Client,
getUserDetails as cGetUserDetails,
User,
getRoomDetails as cGetRoomDetails,
searchPublicRooms as cSearchPublicRooms,
Room, Room,
convertMXCtoMediaQuery as cConvertMXCtoMediaQuery,
getRoomIdFromAlias as cGetRoomIdFromAlias,
RoomAlias, RoomAlias,
User,
getRoomIdFromAlias,
searchPublicRooms,
getUserDetails,
convertMXCtoMediaQuery,
} from "matrix-cypher"; } from "matrix-cypher";
import { LinkKind, Permalink } from "../parser/types";
/* This is a collection of methods for providing fallback metadata
* for cypher queries
*/
/* /*
* Gets the details for a user * Returns an instance of User with fallback information instead
* of fetched metadata
*/ */
export function getUserDetails(client: Client, userId: string): Promise<User> { export const fallbackUser = (userId: string): User => ({
return cGetUserDetails(client, userId).catch(() => ({
displayname: userId, displayname: userId,
})); });
}
function defaultRoom(roomId: string): Room { /*
* Returns an instance of Room with fallback information instead
* of fecthed metadata
*/
export const fallbackRoom = ({
identifier,
roomId,
roomAlias,
}: {
identifier: string;
roomId?: string;
roomAlias?: string;
}): Room => {
const roomId_ = roomId ? roomId : identifier;
const roomAlias_ = roomAlias ? roomAlias : identifier;
return { return {
aliases: [roomId], aliases: [roomAlias_],
topic: "Unable to find room details.", topic: "Unable to find room details.",
canonical_alias: roomId, canonical_alias: roomAlias_,
name: roomId, name: roomAlias_,
num_joined_members: 0, num_joined_members: 0,
room_id: roomId, room_id: roomId_,
guest_can_join: true, guest_can_join: true,
avatar_url: "", avatar_url: "",
world_readable: false, world_readable: false,
}; };
} };
/* /*
* Gets the details of a room if that room is public * Tries to fetch room details from an alias. If it fails it uses
* a `fallbackRoom`
*/ */
export function getRoomDetails( export async function getRoomFromAlias(
clients: Client[], client: Client,
roomId: string roomAlias: string
): Promise<Room> { ): Promise<Room> {
return cGetRoomDetails(clients, roomId).catch(() => defaultRoom(roomId)); let resolvedRoomAlias: RoomAlias;
try {
resolvedRoomAlias = await getRoomIdFromAlias(client, roomAlias);
} catch {
return fallbackRoom({ identifier: roomAlias });
}
try {
return await searchPublicRooms(client, resolvedRoomAlias.room_id);
} catch {
return fallbackRoom({
identifier: roomAlias,
roomId: resolvedRoomAlias.room_id,
roomAlias: roomAlias,
});
}
} }
/* /*
* Searches the public rooms of a homeserver for the metadata of a particular * Tries to fetch room details from a roomId. If it fails it uses
* a `fallbackRoom`
*/ */
export function searchPublicRooms( export async function getRoomFromId(
client: Client, client: Client,
roomId: string roomId: string
): Promise<Room> { ): Promise<Room> {
return cSearchPublicRooms(client, roomId).catch(() => defaultRoom(roomId)); try {
return await searchPublicRooms(client, roomId);
} catch {
return fallbackRoom({ identifier: roomId });
}
} }
export function convertMXCtoMediaQuery(clientURL: string, mxc: string): string { /*
* Tries to fetch user details. If it fails it uses a `fallbackUser`
*/
export async function getUser(client: Client, userId: string): Promise<User> {
try { try {
return cConvertMXCtoMediaQuery(clientURL, mxc); return await getUserDetails(client, userId);
} catch {
return fallbackUser(userId);
}
}
/*
* Tries to fetch room details from a permalink. If it fails it uses
* a `fallbackRoom`
*/
export async function getRoomFromPermalink(
client: Client,
link: Permalink
): Promise<Room> {
switch (link.roomKind) {
case LinkKind.Alias:
return getRoomFromAlias(client, link.roomLink);
case LinkKind.RoomId:
return getRoomFromId(client, link.roomLink);
}
}
/*
* tries to convert an mxc to a media query. If it fails it
* uses the empty string
*/
export function getMediaQueryFromMCX(mxc?: string): string {
if (!mxc) {
return "";
}
try {
return convertMXCtoMediaQuery(
// TODO: replace with correct client
"https://matrix.org",
mxc
);
} catch { } catch {
return ""; return "";
} }
} }
export function getRoomIdFromAlias(
client: Client,
roomAlias: string
): Promise<RoomAlias> {
return cGetRoomIdFromAlias(client, roomAlias).catch(() => ({
room_id: roomAlias,
servers: [],
}));
}