Merge pull request #103 from matrix-org/matrixtwo/mvp

Matrixtwo/mvp
This commit is contained in:
Jorik Schellekens 2020-08-19 16:56:35 +01:00 committed by GitHub
commit 53e1aa57d4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
30 changed files with 702 additions and 133 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -5,6 +5,7 @@
"dependencies": { "dependencies": {
"classnames": "^2.2.6", "classnames": "^2.2.6",
"formik": "^2.1.4", "formik": "^2.1.4",
"matrix-cypher": "^0.1.12",
"react": "^16.13.1", "react": "^16.13.1",
"react-dom": "^16.13.1", "react-dom": "^16.13.1",
"react-scripts": "3.4.1", "react-scripts": "3.4.1",
@ -67,12 +68,14 @@
"@types/node": "^12.0.0", "@types/node": "^12.0.0",
"@types/react": "^16.9.0", "@types/react": "^16.9.0",
"@types/react-dom": "^16.9.0", "@types/react-dom": "^16.9.0",
"@types/react-router-dom": "^5.1.5",
"@types/yup": "^0.29.3", "@types/yup": "^0.29.3",
"eslint-config-matrix-org": "^0.1.0", "eslint-config-matrix-org": "^0.1.0",
"husky": "^4.2.5", "husky": "^4.2.5",
"lint-staged": "^10.2.7", "lint-staged": "^10.2.7",
"node-sass": "^4.14.1", "node-sass": "^4.14.1",
"prettier": "^2.0.5", "prettier": "^2.0.5",
"react-router-dom": "^5.2.0",
"storybook-addon-designs": "^5.4.0", "storybook-addon-designs": "^5.4.0",
"ts-jest": "^26.1.4", "ts-jest": "^26.1.4",
"typescript": "~3.7.2" "typescript": "~3.7.2"

View File

@ -15,18 +15,41 @@ limitations under the License.
*/ */
import React from "react"; import React from "react";
import "./App.scss";
import SingleColumn from "./layouts/SingleColumn"; import SingleColumn from "./layouts/SingleColumn";
import CreateLinkTile from "./components/CreateLinkTile"; import CreateLinkTile from "./components/CreateLinkTile";
import MatrixTile from "./components/MatrixTile"; import MatrixTile from "./components/MatrixTile";
import Tile from "./components/Tile";
import LinkRouter from "./pages/LinkRouter";
import "./App.scss";
/* eslint-disable no-restricted-globals */
const App: React.FC = () => { const App: React.FC = () => {
let page = (
<>
<CreateLinkTile /> <hr />{" "}
</>
);
if (location.hash) {
console.log(location.hash);
if (location.hash.startsWith("#/")) {
page = <LinkRouter link={location.hash.slice(2)} />;
} else {
page = (
<Tile>
Links should be in the format {location.host}/#/{"<"}
matrix-resource-identifier{">"}
</Tile>
);
}
}
return ( return (
<SingleColumn> <SingleColumn>
<div className="topSpacer" /> <div className="topSpacer" />
<CreateLinkTile /> {page}
<hr />
<MatrixTile /> <MatrixTile />
<div className="bottomSpacer" /> <div className="bottomSpacer" />
</SingleColumn> </SingleColumn>

53
src/clients/Element.io.ts Normal file
View File

@ -0,0 +1,53 @@
/*
Copyright 2020 The Matrix.org Foundation C.I.C.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
import { LinkedClient, Maturity, ClientKind } from "./types";
import { LinkKind } from "../parser/types";
import logo from "./element.svg";
const Element: LinkedClient = {
kind: ClientKind.LINKED_CLIENT,
name: "Element",
author: "Element",
logo: logo,
homepage: "https://element.io",
maturity: Maturity.STABLE,
description: "Fully-featured Matrix client for the Web",
tags: [],
toUrl: (link) => {
switch (link.kind) {
case LinkKind.Alias:
case LinkKind.RoomId:
return new URL(
`https://app.element.io/#/room/${link.identifier}`
);
case LinkKind.UserId:
return new URL(
`https://app.element.io/#/user/${link.identifier}`
);
case LinkKind.Permalink:
return new URL(
`https://app.element.io/#/room/${link.identifier}`
);
case LinkKind.GroupId:
return new URL(
`https://app.element.io/#/group/${link.identifier}`
);
}
},
};
export default Element;

6
src/clients/element.svg Normal file
View File

@ -0,0 +1,6 @@
<svg width="64" height="64" viewBox="0 0 64 64" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M25.28 10.88C25.28 9.28942 26.5694 8 28.16 8C38.7639 8 47.36 16.5961 47.36 27.2C47.36 28.7906 46.0706 30.08 44.48 30.08C42.8894 30.08 41.6 28.7906 41.6 27.2C41.6 19.7773 35.5827 13.76 28.16 13.76C26.5694 13.76 25.28 12.4706 25.28 10.88Z" fill="#0DBD8B"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M38.72 53.12C38.72 54.7106 37.4306 56 35.84 56C25.2361 56 16.64 47.4039 16.64 36.8C16.64 35.2094 17.9294 33.92 19.52 33.92C21.1105 33.92 22.4 35.2094 22.4 36.8C22.4 44.2227 28.4173 50.24 35.84 50.24C37.4306 50.24 38.72 51.5294 38.72 53.12Z" fill="#0DBD8B"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M10.88 38.72C9.28942 38.72 8 37.4306 8 35.84C8 25.2361 16.5961 16.64 27.2 16.64C28.7906 16.64 30.08 17.9294 30.08 19.52C30.08 21.1105 28.7906 22.4 27.2 22.4C19.7773 22.4 13.76 28.4173 13.76 35.84C13.76 37.4306 12.4706 38.72 10.88 38.72Z" fill="#0DBD8B"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M53.12 25.28C54.7106 25.28 56 26.5694 56 28.16C56 38.7639 47.4039 47.36 36.8 47.36C35.2094 47.36 33.92 46.0706 33.92 44.48C33.92 42.8895 35.2094 41.6 36.8 41.6C44.2227 41.6 50.24 35.5827 50.24 28.16C50.24 26.5694 51.5294 25.28 53.12 25.28Z" fill="#0DBD8B"/>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

29
src/clients/index.ts Normal file
View File

@ -0,0 +1,29 @@
/*
Copyright 2020 The Matrix.org Foundation C.I.C.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
import { Client } from "./types";
import Element from "./Element.io";
/*
* All the supported clients of matrix.to
*/
const clients: Client[] = [Element];
/*
* All the supported clients of matrix.to
*/
export default clients;

82
src/clients/types.ts Normal file
View File

@ -0,0 +1,82 @@
/*
Copyright 2020 The Matrix.org Foundation C.I.C.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
import { SafeLink } from "../parser/types";
/*
* A collection of descriptive tags that can be added to
* a clients description.
*/
export enum Tag {
IOS = "IOS",
ANDROID = "ANDROID",
DESKTOP = "DESKTOP",
}
/*
* A collection of states used for describing a clients maturity.
*/
export enum Maturity {
ALPHA = "ALPHA",
LATE_ALPHA = "LATE ALPHA",
BETA = "BETA",
LATE_BETA = "LATE_BETA",
STABLE = "STABLE",
}
/*
* Used for constructing the discriminated union of all client types.
*/
export enum ClientKind {
LINKED_CLIENT = "LINKED_CLIENT",
TEXT_CLIENT = "TEXT_CLIENT",
}
/*
* The descriptive details of a client
*/
export interface ClientDescription {
name: string;
author: string;
homepage: string;
logo: string;
description: string;
tags: Tag[];
maturity: Maturity;
}
/*
* A client which can be opened using a link with the matrix resource.
*/
export interface LinkedClient extends ClientDescription {
kind: ClientKind.LINKED_CLIENT;
toUrl(parsedLink: SafeLink): URL;
}
/*
* A client which provides isntructions for how to access the descired
* resource.
*/
export interface TextClient extends ClientDescription {
kind: ClientKind.TEXT_CLIENT;
toInviteString(parsedLink: SafeLink): string;
}
/*
* A description for a client as well as a method for converting matrix.to
* links to the client's specific representation.
*/
export type Client = LinkedClient | TextClient;

View File

@ -35,5 +35,6 @@ export const Default: React.FC<{}> = () => (
avatar_url: "mxc://matrix.org/EqMZYbAYhREvHXvYFyfxOlkf", avatar_url: "mxc://matrix.org/EqMZYbAYhREvHXvYFyfxOlkf",
displayname: "Jorik Schellekens", displayname: "Jorik Schellekens",
}} }}
userId="@jorik:matrix.org"
/> />
); );

View File

@ -16,9 +16,9 @@ limitations under the License.
import React, { useEffect, useState } from "react"; import React, { useEffect, useState } from "react";
import classNames from "classnames"; import classNames from "classnames";
import { convertMXCtoMediaQuery } from "cypher"; import { Room, User } from "matrix-cypher";
import { Room } from "cypher/src/schemas/PublicRoomsSchema";
import { User } from "cypher/src/schemas/UserSchema"; import { convertMXCtoMediaQuery } from "../utils/cypher-wrapper";
import logo from "../imgs/matrix-logo.svg"; import logo from "../imgs/matrix-logo.svg";
import "./Avatar.scss"; import "./Avatar.scss";
@ -38,7 +38,7 @@ const Avatar: React.FC<IProps> = ({ className, avatarUrl, label }: IProps) => {
return ( return (
<img <img
src={src} src={src}
onError={(_) => setSrc(logo)} onError={(): void => setSrc(logo)}
alt={label} alt={label}
className={classNames("avatar", className)} className={classNames("avatar", className)}
/> />
@ -47,18 +47,24 @@ const Avatar: React.FC<IProps> = ({ className, avatarUrl, label }: IProps) => {
interface IPropsUserAvatar { interface IPropsUserAvatar {
user: User; user: User;
userId: string;
} }
export const UserAvatar: React.FC<IPropsUserAvatar> = ({ export const UserAvatar: React.FC<IPropsUserAvatar> = ({
user, user,
userId,
}: IPropsUserAvatar) => ( }: IPropsUserAvatar) => (
<Avatar <Avatar
avatarUrl={convertMXCtoMediaQuery( avatarUrl={
// TODO: replace with correct client
"matrix.org",
user.avatar_url user.avatar_url
)} ? convertMXCtoMediaQuery(
label={user.displayname} // TODO: replace with correct client
"https://matrix.org",
user.avatar_url
)
: ""
}
label={user.displayname ? user.displayname : userId}
/> />
); );
@ -74,7 +80,7 @@ export const RoomAvatar: React.FC<IPropsRoomAvatar> = ({
room.avatar_url room.avatar_url
? convertMXCtoMediaQuery( ? convertMXCtoMediaQuery(
// TODO: replace with correct client // TODO: replace with correct client
"matrix.org", "https://matrix.org",
room.avatar_url room.avatar_url
) )
: "" : ""

View File

@ -22,7 +22,7 @@ import Button from "./Button";
export default { title: "Button" }; export default { title: "Button" };
export const WithText = () => ( export const WithText: React.FC = () => (
<Button onClick={action("clicked")}> <Button onClick={action("clicked")}>
{text("label", "Hello Story Book")} {text("label", "Hello Story Book")}
</Button> </Button>

View File

@ -29,4 +29,4 @@ export default {
}, },
}; };
export const Default = () => <CreateLinkTile />; export const Default: React.FC = () => <CreateLinkTile />;

View File

@ -28,7 +28,9 @@ interface ILinkNotCreatedTileProps {
setLink: React.Dispatch<React.SetStateAction<string>>; setLink: React.Dispatch<React.SetStateAction<string>>;
} }
const LinkNotCreatedTile = (props: ILinkNotCreatedTileProps) => { const LinkNotCreatedTile: React.FC<ILinkNotCreatedTileProps> = (
props: ILinkNotCreatedTileProps
) => {
return ( return (
<Tile className="createLinkTile"> <Tile className="createLinkTile">
<h1> <h1>
@ -48,7 +50,7 @@ const LinkNotCreatedTile = (props: ILinkNotCreatedTileProps) => {
) )
.required("Required"), .required("Required"),
})} })}
onSubmit={(values) => { onSubmit={(values): void => {
props.setLink( props.setLink(
document.location.protocol + document.location.protocol +
"//" + "//" +
@ -80,7 +82,7 @@ const LinkCreatedTile: React.FC<ILinkCreatedTileProps> = (props) => {
const buttonRef = useRef<HTMLButtonElement>(null); const buttonRef = useRef<HTMLButtonElement>(null);
// Focus button on render // Focus button on render
useEffect(() => { useEffect((): void => {
if (buttonRef && buttonRef.current) { if (buttonRef && buttonRef.current) {
buttonRef.current.focus(); buttonRef.current.focus();
} }
@ -88,13 +90,15 @@ const LinkCreatedTile: React.FC<ILinkCreatedTileProps> = (props) => {
return ( return (
<Tile className="createLinkTile"> <Tile className="createLinkTile">
<TextButton onClick={() => props.setLink("")}> <TextButton onClick={(): void => props.setLink("")}>
Create another lnk Create another lnk
</TextButton> </TextButton>
<h1>{props.link}</h1> <h1>{props.link}</h1>
<Button <Button
flashChildren={"Copied"} flashChildren={"Copied"}
onClick={() => navigator.clipboard.writeText(props.link)} onClick={(): void => {
navigator.clipboard.writeText(props.link);
}}
ref={buttonRef} ref={buttonRef}
> >
Copy Link Copy Link

View File

@ -15,8 +15,7 @@ limitations under the License.
*/ */
import React from "react"; import React from "react";
import { Room } from "cypher/src/schemas/PublicRoomsSchema"; import { Room, Event } from "matrix-cypher";
import { Event } from "cypher/src/schemas/EventSchema";
import RoomPreview from "./RoomPreview"; import RoomPreview from "./RoomPreview";

View File

@ -32,8 +32,8 @@ export default {
decorators: [withDesign], decorators: [withDesign],
}; };
export const Default = () => ( export const Default: React.FC = () => (
<Formik initialValues={{}} onSubmit={() => {}}> <Formik initialValues={{}} onSubmit={(): void => {}}>
<Form> <Form>
<Input <Input
name="Example input" name="Example input"

View File

@ -19,6 +19,8 @@ import React from "react";
import InviteTile from "./InviteTile"; import InviteTile from "./InviteTile";
import UserPreview, { InviterPreview } from "./UserPreview"; import UserPreview, { InviterPreview } from "./UserPreview";
import RoomPreview, { RoomPreviewWithTopic } from "./RoomPreview"; import RoomPreview, { RoomPreviewWithTopic } from "./RoomPreview";
import Clients from "../clients";
import { LinkKind, SafeLink } from "../parser/types";
export default { export default {
title: "InviteTile", title: "InviteTile",
@ -31,35 +33,38 @@ export default {
}, },
}; };
const userLink: SafeLink = {
kind: LinkKind.UserId,
identifier: "@jorik:matrix.org",
arguments: {
vias: [],
},
originalLink: "asdfsadf",
};
const roomLink: SafeLink = {
kind: LinkKind.Alias,
identifier: "#element-dev:matrix.org",
arguments: {
vias: [],
},
originalLink: "asdfsadf",
};
export const withLink: React.FC<{}> = () => ( export const withLink: React.FC<{}> = () => (
<InviteTile <InviteTile client={Clients[0]} link={userLink}>
inviteAction={{
type: "link",
link: "https://app.element.io/#/room/#asdfasf:matrix.org",
}}
>
This is an invite with a link This is an invite with a link
</InviteTile> </InviteTile>
); );
export const withInstruction: React.FC<{}> = () => ( export const withInstruction: React.FC<{}> = () => (
<InviteTile <InviteTile client={Clients[0]} link={userLink}>
inviteAction={{
type: "instruction",
text: "Type /join #asdfasf:matrix.org",
}}
>
This is an invite with an instruction This is an invite with an instruction
</InviteTile> </InviteTile>
); );
export const withUserPreview: React.FC<{}> = () => ( export const withUserPreview: React.FC<{}> = () => (
<InviteTile <InviteTile client={Clients[0]} link={userLink}>
inviteAction={{
type: "link",
link: "https://app.element.io/#/room/#asdfasf:matrix.org",
}}
>
<UserPreview <UserPreview
user={{ user={{
avatar_url: "mxc://matrix.org/EqMZYbAYhREvHXvYFyfxOlkf", avatar_url: "mxc://matrix.org/EqMZYbAYhREvHXvYFyfxOlkf",
@ -71,12 +76,7 @@ export const withUserPreview: React.FC<{}> = () => (
); );
export const withRoomPreviewAndRoomTopic: React.FC<{}> = () => ( export const withRoomPreviewAndRoomTopic: React.FC<{}> = () => (
<InviteTile <InviteTile client={Clients[0]} link={roomLink}>
inviteAction={{
type: "link",
link: "https://app.element.io/#/room/#asdfasf:matrix.org",
}}
>
<RoomPreviewWithTopic <RoomPreviewWithTopic
room={{ room={{
aliases: ["#murrays:cheese.bar"], aliases: ["#murrays:cheese.bar"],
@ -93,12 +93,7 @@ export const withRoomPreviewAndRoomTopic: React.FC<{}> = () => (
); );
export const withRoomPreviewAndInviter: React.FC<{}> = () => ( export const withRoomPreviewAndInviter: React.FC<{}> = () => (
<InviteTile <InviteTile client={Clients[0]} link={roomLink}>
inviteAction={{
type: "link",
link: "https://app.element.io/#/room/#asdfasf:matrix.org",
}}
>
<InviterPreview <InviterPreview
user={{ user={{
avatar_url: "mxc://matrix.org/EqMZYbAYhREvHXvYFyfxOlkf", avatar_url: "mxc://matrix.org/EqMZYbAYhREvHXvYFyfxOlkf",

View File

@ -16,39 +16,32 @@ limitations under the License.
import React from "react"; import React from "react";
import "./InviteTile.scss";
import Tile from "./Tile"; import Tile from "./Tile";
import LinkButton from "./LinkButton"; import LinkButton from "./LinkButton";
import TextButton from "./TextButton"; import TextButton from "./TextButton";
import { Client, ClientKind } from "../clients/types";
import "./InviteTile.scss"; import { SafeLink } from "../parser/types";
export interface InviteLink {
type: "link";
link: string;
}
export interface InviteInstruction {
type: "instruction";
text: string;
}
type InviteAction = InviteLink | InviteInstruction;
interface IProps { interface IProps {
children?: React.ReactNode; children?: React.ReactNode;
inviteAction: InviteAction; client: Client;
link: SafeLink;
} }
const InviteTile: React.FC<IProps> = ({ children, inviteAction }: IProps) => { const InviteTile: React.FC<IProps> = ({ children, client, link }: IProps) => {
let invite: React.ReactNode; let invite: React.ReactNode;
switch (inviteAction.type) { switch (client.kind) {
case "link": case ClientKind.LINKED_CLIENT:
invite = ( invite = (
<LinkButton href={inviteAction.link}>Accept invite</LinkButton> <LinkButton href={client.toUrl(link).toString()}>
Accept invite
</LinkButton>
); );
break; break;
case "instruction": case ClientKind.TEXT_CLIENT:
invite = <p>{inviteAction.text}</p>; invite = <p>{client.toInviteString(link)}</p>;
break; break;
} }

View File

@ -0,0 +1,126 @@
/*
Copyright 2020 The Matrix.org Foundation C.I.C.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
import React, { useState, useEffect } from "react";
import { Client, getEvent, client } from "matrix-cypher";
import {
getRoomIdFromAlias,
searchPublicRooms,
getUserDetails,
} from "../utils/cypher-wrapper";
import { RoomPreviewWithTopic } from "./RoomPreview";
import InviteTile from "./InviteTile";
import { SafeLink } from "../parser/types";
import { LinkKind } from "../parser/types";
import UserPreview from "./UserPreview";
import EventPreview from "./EventPreview";
import Clients from "../clients";
interface IProps {
link: SafeLink;
}
// TODO: replace with client fetch
const defaultClient: () => Promise<Client> = () => client("https://matrix.org");
const LOADING: JSX.Element = <>Generating invite</>;
const invite = async ({ link }: { link: SafeLink }): Promise<JSX.Element> => {
switch (link.kind) {
case LinkKind.Alias:
return (
<RoomPreviewWithTopic
room={
await searchPublicRooms(
await defaultClient(),
(
await getRoomIdFromAlias(
await defaultClient(),
link.identifier
)
).room_id
)
}
/>
);
case LinkKind.RoomId:
return (
<RoomPreviewWithTopic
room={
await searchPublicRooms(
await defaultClient(),
link.identifier
)
}
/>
);
case LinkKind.UserId:
return (
<UserPreview
user={
await getUserDetails(
await defaultClient(),
link.identifier
)
}
userId={link.identifier}
/>
);
case LinkKind.Permalink:
return (
<EventPreview
room={
await searchPublicRooms(
await defaultClient(),
link.identifier
)
}
event={
await getEvent(
await defaultClient(),
link.roomLink,
link.eventId
)
}
/>
);
default:
// Todo Implement events
return <></>;
}
};
const LinkPreview: React.FC<IProps> = ({ link }: IProps) => {
const [content, setContent] = useState(LOADING);
useEffect(() => {
(async (): Promise<void> => setContent(await invite({ link })))();
}, [link]);
return (
<InviteTile client={Clients[0]} link={link}>
{content}
</InviteTile>
);
};
export default LinkPreview;

View File

@ -20,4 +20,4 @@ import MatrixTile from "./MatrixTile";
export default { title: "MatrixTile" }; export default { title: "MatrixTile" };
export const Default = () => <MatrixTile />; export const Default: React.FC = () => <MatrixTile />;

View File

@ -15,7 +15,7 @@ limitations under the License.
*/ */
import React from "react"; import React from "react";
import { Room } from "cypher/src/schemas/PublicRoomsSchema"; import { Room } from "matrix-cypher";
import { RoomAvatar } from "./Avatar"; import { RoomAvatar } from "./Avatar";
@ -30,7 +30,7 @@ const RoomPreview: React.FC<IProps> = ({ room }: IProps) => {
return ( return (
<div className="roomPreview"> <div className="roomPreview">
<RoomAvatar room={room} /> <RoomAvatar room={room} />
<h1>{room.name}</h1> <h1>{room.name ? room.name : room.room_id}</h1>
<p>{room.num_joined_members.toLocaleString()} members</p> <p>{room.num_joined_members.toLocaleString()} members</p>
<p>{roomAlias}</p> <p>{roomAlias}</p>
</div> </div>

View File

@ -29,4 +29,6 @@ export default {
}, },
}; };
export const Default = () => <TextButton>This is a button?</TextButton>; export const Default: React.FC = () => (
<TextButton>This is a button?</TextButton>
);

View File

@ -29,7 +29,7 @@ export default {
}, },
}; };
export const Default = () => ( export const Default: React.FC = () => (
<Tile> <Tile>
<h1>This is a tile</h1> <h1>This is a tile</h1>
<p>Some text</p> <p>Some text</p>

View File

@ -15,7 +15,7 @@ limitations under the License.
*/ */
import React from "react"; import React from "react";
import { User } from "cypher/src/schemas/UserSchema"; import { User } from "matrix-cypher";
import { UserAvatar } from "./Avatar"; import { UserAvatar } from "./Avatar";
@ -28,7 +28,7 @@ interface IProps {
const UserPreview: React.FC<IProps> = ({ user, userId }: IProps) => ( const UserPreview: React.FC<IProps> = ({ user, userId }: IProps) => (
<div className="userPreview"> <div className="userPreview">
<UserAvatar user={user} /> <UserAvatar user={user} userId={userId} />
<h1>{user.displayname} invites you to connect</h1> <h1>{user.displayname} invites you to connect</h1>
<p>{userId}</p> <p>{userId}</p>
<hr /> <hr />
@ -45,6 +45,6 @@ export const InviterPreview: React.FC<IProps> = ({ user, userId }: IProps) => (
</h1> </h1>
<p>{userId}</p> <p>{userId}</p>
</div> </div>
<UserAvatar user={user} /> <UserAvatar user={user} userId={userId} />
</div> </div>
); );

View File

@ -16,8 +16,7 @@ limitations under the License.
import React from "react"; import React from "react";
import { Client, discoverServer } from "cypher"; import { prefixFetch, Client, discoverServer } from "matrix-cypher";
import { prefixFetch } from "cypher/src/utils/fetch";
type State = { type State = {
clientURL: string; clientURL: string;
@ -62,4 +61,8 @@ export const reducer = async (state: State, action: Action): Promise<State> => {
// The null is a hack to make the type checker happy // The null is a hack to make the type checker happy
// create context does not need an argument // create context does not need an argument
export default React.createContext<typeof reducer | null>(null); const { Provider, Consumer } = React.createContext<typeof reducer | null>(null);
// Quick rename to make importing easier
export const ClientProvider = Provider;
export const ClientConsumer = Consumer;

View File

@ -38,6 +38,8 @@ body,
line-height: 24px; line-height: 24px;
color: $font; color: $font;
overflow: scroll;
} }
h1 { h1 {

50
src/pages/LinkRouter.tsx Normal file
View File

@ -0,0 +1,50 @@
/*
Copyright 2020 The Matrix.org Foundation C.I.C.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
import React from "react";
import Tile from "../components/Tile";
import LinkPreview from "../components/LinkPreview";
import { parseHash } from "../parser/parser";
import { LinkKind } from "../parser/types";
interface IProps {
link: string;
}
const LinkRouter: React.FC<IProps> = ({ link }: IProps) => {
// our room id's will be stored in the hash
const parsedLink = parseHash(link);
console.log({ link });
let feedback: JSX.Element;
switch (parsedLink.kind) {
case LinkKind.ParseFailed:
feedback = (
<Tile>
<h1>Invalid matrix.to link</h1>
<p>{link}</p>
</Tile>
);
break;
default:
feedback = <LinkPreview link={parsedLink} />;
}
return feedback;
};
export default LinkRouter;

View File

@ -20,7 +20,7 @@ export const roomVerifiers: Verifier<LinkKind.Alias | LinkKind.RoomId>[] = [
[/^!([^/:]+?):(.+)$/, LinkKind.RoomId], [/^!([^/:]+?):(.+)$/, LinkKind.RoomId],
]; ];
export const verifiers: Verifier<LinkKind>[] = [ export const verifiers: Verifier<LinkKind>[] = [
[/^[!#]([^/:]+?):(.+?)\/\$([^/:]+?):(.+?)$/, LinkKind.Permalink], [/^[!#]([^/:]+?):(.+?)\/\$([^/:]+?)$/, LinkKind.Permalink],
[/^@([^/:]+?):(.+)$/, LinkKind.UserId], [/^@([^/:]+?):(.+)$/, LinkKind.UserId],
[/^\+([^/:]+?):(.+)$/, LinkKind.GroupId], [/^\+([^/:]+?):(.+)$/, LinkKind.GroupId],
...roomVerifiers, ...roomVerifiers,
@ -56,7 +56,9 @@ export function identifyTypeFromRegex<T, F>(
* Parses a permalink. * Parses a permalink.
* Assumes the permalink is correct. * Assumes the permalink is correct.
*/ */
export function parsePermalink(identifier: string): Permalink { export function parsePermalink(
identifier: string
): Pick<Permalink, "roomKind" | "roomLink" | "eventId"> {
const [roomLink, eventId] = identifier.split("/"); const [roomLink, eventId] = identifier.split("/");
const roomKind = identifyTypeFromRegex( const roomKind = identifyTypeFromRegex(
roomLink, roomLink,

View File

@ -49,6 +49,5 @@ export interface ParseFailed {
originalLink: string; originalLink: string;
} }
export type Link = Alias | RoomId | UserId | Permalink | GroupId | ParseFailed;
export type SafeLink = Alias | RoomId | UserId | Permalink | GroupId; export type SafeLink = Alias | RoomId | UserId | Permalink | GroupId;
export type Link = SafeLink | ParseFailed;

View File

@ -0,0 +1,88 @@
/*
Copyright 2020 The Matrix.org Foundation C.I.C.
Licensed under the Apache License, Version 2.0 (the 'License');
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an 'AS IS' BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
import {
Client,
getUserDetails as cGetUserDetails,
User,
getRoomDetails as cGetRoomDetails,
searchPublicRooms as cSearchPublicRooms,
Room,
convertMXCtoMediaQuery as cConvertMXCtoMediaQuery,
getRoomIdFromAlias as cGetRoomIdFromAlias,
RoomAlias,
} from "matrix-cypher";
/*
* Gets the details for a user
*/
export function getUserDetails(client: Client, userId: string): Promise<User> {
return cGetUserDetails(client, userId).catch(() => ({
displayname: userId,
}));
}
function defaultRoom(roomId: string): Room {
return {
aliases: [roomId],
topic: "Unable to find room details.",
canonical_alias: roomId,
name: roomId,
num_joined_members: 0,
room_id: roomId,
guest_can_join: true,
avatar_url: "",
world_readable: false,
};
}
/*
* Gets the details of a room if that room is public
*/
export function getRoomDetails(
clients: Client[],
roomId: string
): Promise<Room> {
return cGetRoomDetails(clients, roomId).catch(() => defaultRoom(roomId));
}
/*
* Searches the public rooms of a homeserver for the metadata of a particular
*/
export function searchPublicRooms(
client: Client,
roomId: string
): Promise<Room> {
return cSearchPublicRooms(client, roomId).catch(() => defaultRoom(roomId));
}
export function convertMXCtoMediaQuery(clientURL: string, mxc: string): string {
try {
return cConvertMXCtoMediaQuery(clientURL, mxc);
} catch {
return "";
}
}
export function getRoomIdFromAlias(
client: Client,
roomAlias: string
): Promise<RoomAlias> {
return cGetRoomIdFromAlias(client, roomAlias).catch(() => ({
room_id: roomAlias,
servers: [],
}));
}

155
yarn.lock
View File

@ -2345,6 +2345,23 @@
dependencies: dependencies:
"@types/react" "*" "@types/react" "*"
"@types/react-router-dom@^5.1.5":
version "5.1.5"
resolved "https://registry.yarnpkg.com/@types/react-router-dom/-/react-router-dom-5.1.5.tgz#7c334a2ea785dbad2b2dcdd83d2cf3d9973da090"
integrity sha512-ArBM4B1g3BWLGbaGvwBGO75GNFbLDUthrDojV2vHLih/Tq8M+tgvY1DSwkuNrPSwdp/GUL93WSEpTZs8nVyJLw==
dependencies:
"@types/history" "*"
"@types/react" "*"
"@types/react-router" "*"
"@types/react-router@*":
version "5.1.8"
resolved "https://registry.yarnpkg.com/@types/react-router/-/react-router-5.1.8.tgz#4614e5ba7559657438e17766bb95ef6ed6acc3fa"
integrity sha512-HzOyJb+wFmyEhyfp4D4NYrumi+LQgQL/68HvJO+q6XtuHSDvw6Aqov7sCAhjbNq3bUPgPqbdvjXC5HeB2oEAPg==
dependencies:
"@types/history" "*"
"@types/react" "*"
"@types/react-syntax-highlighter@11.0.4": "@types/react-syntax-highlighter@11.0.4":
version "11.0.4" version "11.0.4"
resolved "https://registry.yarnpkg.com/@types/react-syntax-highlighter/-/react-syntax-highlighter-11.0.4.tgz#d86d17697db62f98046874f62fdb3e53a0bbc4cd" resolved "https://registry.yarnpkg.com/@types/react-syntax-highlighter/-/react-syntax-highlighter-11.0.4.tgz#d86d17697db62f98046874f62fdb3e53a0bbc4cd"
@ -4834,6 +4851,13 @@ create-react-context@0.3.0, create-react-context@^0.3.0:
gud "^1.0.0" gud "^1.0.0"
warning "^4.0.3" warning "^4.0.3"
cross-fetch@^3.0.5:
version "3.0.5"
resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.0.5.tgz#2739d2981892e7ab488a7ad03b92df2816e03f4c"
integrity sha512-FFLcLtraisj5eteosnX1gf01qYDCOc4fDy0+euOt8Kn9YBY2NtXL/pCoYPavw24NIQkQqm5ZOLsGD5Zzj0gyew==
dependencies:
node-fetch "2.6.0"
cross-spawn@6.0.5, cross-spawn@^6.0.0, cross-spawn@^6.0.5: cross-spawn@6.0.5, cross-spawn@^6.0.0, cross-spawn@^6.0.5:
version "6.0.5" version "6.0.5"
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4"
@ -5695,7 +5719,7 @@ error-ex@^1.2.0, error-ex@^1.3.1:
dependencies: dependencies:
is-arrayish "^0.2.1" is-arrayish "^0.2.1"
es-abstract@^1.17.0, es-abstract@^1.17.0-next.0, es-abstract@^1.17.0-next.1, es-abstract@^1.17.2, es-abstract@^1.17.4, es-abstract@^1.17.5: es-abstract@^1.17.0, es-abstract@^1.17.0-next.0, es-abstract@^1.17.0-next.1, es-abstract@^1.17.2, es-abstract@^1.17.4, es-abstract@^1.17.5, es-abstract@^1.17.6:
version "1.17.6" version "1.17.6"
resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.17.6.tgz#9142071707857b2cacc7b89ecb670316c3e2d52a" resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.17.6.tgz#9142071707857b2cacc7b89ecb670316c3e2d52a"
integrity sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw== integrity sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==
@ -5712,6 +5736,17 @@ es-abstract@^1.17.0, es-abstract@^1.17.0-next.0, es-abstract@^1.17.0-next.1, es-
string.prototype.trimend "^1.0.1" string.prototype.trimend "^1.0.1"
string.prototype.trimstart "^1.0.1" string.prototype.trimstart "^1.0.1"
es-aggregate-error@^1.0.2:
version "1.0.4"
resolved "https://registry.yarnpkg.com/es-aggregate-error/-/es-aggregate-error-1.0.4.tgz#60662b73fddb1656e7bd6bd4285321406c567d2d"
integrity sha512-syuWJHsRD5TJ3nwqjf8eFEeGLJM6OxUjVFz0dMg2b/GB/Ub5VAFiQPEVB6ewdU2VHgkOJBo00uYwPmo7fyfzEg==
dependencies:
define-properties "^1.1.3"
es-abstract "^1.17.6"
function-bind "^1.1.1"
functions-have-names "^1.2.1"
globalthis "^1.0.1"
es-array-method-boxes-properly@^1.0.0: es-array-method-boxes-properly@^1.0.0:
version "1.0.0" version "1.0.0"
resolved "https://registry.yarnpkg.com/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz#873f3e84418de4ee19c5be752990b2e44718d09e" resolved "https://registry.yarnpkg.com/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz#873f3e84418de4ee19c5be752990b2e44718d09e"
@ -6804,7 +6839,7 @@ functional-red-black-tree@^1.0.1:
resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327"
integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=
functions-have-names@^1.2.0: functions-have-names@^1.2.0, functions-have-names@^1.2.1:
version "1.2.1" version "1.2.1"
resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.1.tgz#a981ac397fa0c9964551402cdc5533d7a4d52f91" resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.1.tgz#a981ac397fa0c9964551402cdc5533d7a4d52f91"
integrity sha512-j48B/ZI7VKs3sgeI2cZp7WXWmZXu7Iq5pl5/vptV5N2mq+DGFuS/ulaDjtaoLpYzuD6u8UgrUKHfgo7fDTSiBA== integrity sha512-j48B/ZI7VKs3sgeI2cZp7WXWmZXu7Iq5pl5/vptV5N2mq+DGFuS/ulaDjtaoLpYzuD6u8UgrUKHfgo7fDTSiBA==
@ -6969,7 +7004,7 @@ globals@^12.1.0:
dependencies: dependencies:
type-fest "^0.8.1" type-fest "^0.8.1"
globalthis@^1.0.0: globalthis@^1.0.0, globalthis@^1.0.1:
version "1.0.1" version "1.0.1"
resolved "https://registry.yarnpkg.com/globalthis/-/globalthis-1.0.1.tgz#40116f5d9c071f9e8fb0037654df1ab3a83b7ef9" resolved "https://registry.yarnpkg.com/globalthis/-/globalthis-1.0.1.tgz#40116f5d9c071f9e8fb0037654df1ab3a83b7ef9"
integrity sha512-mJPRTc/P39NH/iNG4mXa9aIhNymaQikTrnspeCa2ZuJ+mH2QN/rXwtX3XwKrHqWgUQFbNZKtHM105aHzJalElw== integrity sha512-mJPRTc/P39NH/iNG4mXa9aIhNymaQikTrnspeCa2ZuJ+mH2QN/rXwtX3XwKrHqWgUQFbNZKtHM105aHzJalElw==
@ -7174,6 +7209,18 @@ highlight.js@~9.13.0:
resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-9.13.1.tgz#054586d53a6863311168488a0f58d6c505ce641e" resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-9.13.1.tgz#054586d53a6863311168488a0f58d6c505ce641e"
integrity sha512-Sc28JNQNDzaH6PORtRLMvif9RSn1mYuOoX3omVjnb0+HbpPygU2ALBI0R/wsiqCb4/fcp07Gdo8g+fhtFrQl6A== integrity sha512-Sc28JNQNDzaH6PORtRLMvif9RSn1mYuOoX3omVjnb0+HbpPygU2ALBI0R/wsiqCb4/fcp07Gdo8g+fhtFrQl6A==
history@^4.9.0:
version "4.10.1"
resolved "https://registry.yarnpkg.com/history/-/history-4.10.1.tgz#33371a65e3a83b267434e2b3f3b1b4c58aad4cf3"
integrity sha512-36nwAD620w12kuzPAsyINPWJqlNbij+hpK1k9XRloDtym8mxzGYl2c17LnV6IAGB2Dmg4tEa7G7DlawS0+qjew==
dependencies:
"@babel/runtime" "^7.1.2"
loose-envify "^1.2.0"
resolve-pathname "^3.0.0"
tiny-invariant "^1.0.2"
tiny-warning "^1.0.0"
value-equal "^1.0.1"
hmac-drbg@^1.0.0: hmac-drbg@^1.0.0:
version "1.0.1" version "1.0.1"
resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1"
@ -7183,7 +7230,7 @@ hmac-drbg@^1.0.0:
minimalistic-assert "^1.0.0" minimalistic-assert "^1.0.0"
minimalistic-crypto-utils "^1.0.1" minimalistic-crypto-utils "^1.0.1"
hoist-non-react-statics@^3.3.0: hoist-non-react-statics@^3.1.0, hoist-non-react-statics@^3.3.0:
version "3.3.2" version "3.3.2"
resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45" resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45"
integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw== integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==
@ -8031,6 +8078,11 @@ is-wsl@^2.1.1:
dependencies: dependencies:
is-docker "^2.0.0" is-docker "^2.0.0"
isarray@0.0.1:
version "0.0.1"
resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf"
integrity sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=
isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0: isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0:
version "1.0.0" version "1.0.0"
resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
@ -8118,7 +8170,7 @@ iterate-iterator@^1.0.1:
resolved "https://registry.yarnpkg.com/iterate-iterator/-/iterate-iterator-1.0.1.tgz#1693a768c1ddd79c969051459453f082fe82e9f6" resolved "https://registry.yarnpkg.com/iterate-iterator/-/iterate-iterator-1.0.1.tgz#1693a768c1ddd79c969051459453f082fe82e9f6"
integrity sha512-3Q6tudGN05kbkDQDI4CqjaBf4qf85w6W6GnuZDtUVYwKgtC1q8yxYX7CZed7N+tLzQqS6roujWvszf13T+n9aw== integrity sha512-3Q6tudGN05kbkDQDI4CqjaBf4qf85w6W6GnuZDtUVYwKgtC1q8yxYX7CZed7N+tLzQqS6roujWvszf13T+n9aw==
iterate-value@^1.0.0: iterate-value@^1.0.0, iterate-value@^1.0.1:
version "1.0.2" version "1.0.2"
resolved "https://registry.yarnpkg.com/iterate-value/-/iterate-value-1.0.2.tgz#935115bd37d006a52046535ebc8d07e9c9337f57" resolved "https://registry.yarnpkg.com/iterate-value/-/iterate-value-1.0.2.tgz#935115bd37d006a52046535ebc8d07e9c9337f57"
integrity sha512-A6fMAio4D2ot2r/TYzr4yUWrmwNdsN5xL7+HUiyACE4DXm+q8HtPcnFTp+NnW3k4N05tZ7FVYFFb2CR13NxyHQ== integrity sha512-A6fMAio4D2ot2r/TYzr4yUWrmwNdsN5xL7+HUiyACE4DXm+q8HtPcnFTp+NnW3k4N05tZ7FVYFFb2CR13NxyHQ==
@ -9050,7 +9102,7 @@ loglevelnext@^1.0.1:
es6-symbol "^3.1.1" es6-symbol "^3.1.1"
object.assign "^4.1.0" object.assign "^4.1.0"
loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.4.0: loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.2.0, loose-envify@^1.3.1, loose-envify@^1.4.0:
version "1.4.0" version "1.4.0"
resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf"
integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==
@ -9179,6 +9231,15 @@ material-colors@^1.2.1:
resolved "https://registry.yarnpkg.com/material-colors/-/material-colors-1.2.6.tgz#6d1958871126992ceecc72f4bcc4d8f010865f46" resolved "https://registry.yarnpkg.com/material-colors/-/material-colors-1.2.6.tgz#6d1958871126992ceecc72f4bcc4d8f010865f46"
integrity sha512-6qE4B9deFBIa9YSpOc9O0Sgc43zTeVYbgDT5veRKSlB2+ZuHNoVVxA1L/ckMUayV9Ay9y7Z/SZCLcGteW9i7bg== integrity sha512-6qE4B9deFBIa9YSpOc9O0Sgc43zTeVYbgDT5veRKSlB2+ZuHNoVVxA1L/ckMUayV9Ay9y7Z/SZCLcGteW9i7bg==
matrix-cypher@^0.1.11:
version "0.1.11"
resolved "https://registry.yarnpkg.com/matrix-cypher/-/matrix-cypher-0.1.11.tgz#3152f47c097943592a12729f9c9340f56b130393"
integrity sha512-fwEntUxC79ycItPl8PRhiJD1oBgOSrMaOjkmt3eYHvmj1F4ylUyxRl3pJICAqZdUeBpbRrMFDhg7oWtGp9v2Ng==
dependencies:
cross-fetch "^3.0.5"
promise.any "^2.0.1"
zod "^1.10.2"
md5.js@^1.3.4: md5.js@^1.3.4:
version "1.3.5" version "1.3.5"
resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f" resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f"
@ -9374,6 +9435,14 @@ min-indent@^1.0.0:
resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.1.tgz#a63f681673b30571fbe8bc25686ae746eefa9869" resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.1.tgz#a63f681673b30571fbe8bc25686ae746eefa9869"
integrity sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg== integrity sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==
mini-create-react-context@^0.4.0:
version "0.4.0"
resolved "https://registry.yarnpkg.com/mini-create-react-context/-/mini-create-react-context-0.4.0.tgz#df60501c83151db69e28eac0ef08b4002efab040"
integrity sha512-b0TytUgFSbgFJGzJqXPKCFCBWigAjpjo+Fl7Vf7ZbKRDptszpppKxXH6DRXEABZ/gcEQczeb0iZ7JvL8e8jjCA==
dependencies:
"@babel/runtime" "^7.5.5"
tiny-warning "^1.0.3"
mini-css-extract-plugin@0.9.0: mini-css-extract-plugin@0.9.0:
version "0.9.0" version "0.9.0"
resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-0.9.0.tgz#47f2cf07aa165ab35733b1fc97d4c46c0564339e" resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-0.9.0.tgz#47f2cf07aa165ab35733b1fc97d4c46c0564339e"
@ -9605,7 +9674,7 @@ node-ensure@^0.0.0:
resolved "https://registry.yarnpkg.com/node-ensure/-/node-ensure-0.0.0.tgz#ecae764150de99861ec5c810fd5d096b183932a7" resolved "https://registry.yarnpkg.com/node-ensure/-/node-ensure-0.0.0.tgz#ecae764150de99861ec5c810fd5d096b183932a7"
integrity sha1-7K52QVDemYYexcgQ/V0Jaxg5Mqc= integrity sha1-7K52QVDemYYexcgQ/V0Jaxg5Mqc=
node-fetch@^2.6.0: node-fetch@2.6.0, node-fetch@^2.6.0:
version "2.6.0" version "2.6.0"
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.0.tgz#e633456386d4aa55863f676a7ab0daa8fdecb0fd" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.0.tgz#e633456386d4aa55863f676a7ab0daa8fdecb0fd"
integrity sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA== integrity sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA==
@ -10304,6 +10373,13 @@ path-to-regexp@0.1.7:
resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c"
integrity sha1-32BBeABfUi8V60SQ5yR6G/qmf4w= integrity sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=
path-to-regexp@^1.7.0:
version "1.8.0"
resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-1.8.0.tgz#887b3ba9d84393e87a0a0b9f4cb756198b53548a"
integrity sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==
dependencies:
isarray "0.0.1"
path-type@^1.0.0: path-type@^1.0.0:
version "1.1.0" version "1.1.0"
resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441" resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441"
@ -11265,6 +11341,18 @@ promise.allsettled@^1.0.0:
function-bind "^1.1.1" function-bind "^1.1.1"
iterate-value "^1.0.0" iterate-value "^1.0.0"
promise.any@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/promise.any/-/promise.any-2.0.1.tgz#381c8f31b5312865c6c2a8104ff501f7f847e66d"
integrity sha512-3amHUuhVhkhFVw8mAM33pyt1zBoYK9O9SorjWbE+E3zSTb4AUpJmK5+rt5g6OCtZpgBlT1cTxF/bp/SNeMQSUQ==
dependencies:
array.prototype.map "^1.0.1"
define-properties "^1.1.3"
es-abstract "^1.17.0-next.1"
es-aggregate-error "^1.0.2"
function-bind "^1.1.1"
iterate-value "^1.0.1"
promise.prototype.finally@^3.1.0: promise.prototype.finally@^3.1.0:
version "3.1.2" version "3.1.2"
resolved "https://registry.yarnpkg.com/promise.prototype.finally/-/promise.prototype.finally-3.1.2.tgz#b8af89160c9c673cefe3b4c4435b53cfd0287067" resolved "https://registry.yarnpkg.com/promise.prototype.finally/-/promise.prototype.finally-3.1.2.tgz#b8af89160c9c673cefe3b4c4435b53cfd0287067"
@ -11689,7 +11777,7 @@ react-inspector@^4.0.0:
is-dom "^1.0.9" is-dom "^1.0.9"
prop-types "^15.6.1" prop-types "^15.6.1"
react-is@^16.12.0, react-is@^16.7.0, react-is@^16.8.1, react-is@^16.8.4, react-is@^16.9.0: react-is@^16.12.0, react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.1, react-is@^16.8.4, react-is@^16.9.0:
version "16.13.1" version "16.13.1"
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==
@ -11743,6 +11831,35 @@ react-redux@^7.0.2:
prop-types "^15.7.2" prop-types "^15.7.2"
react-is "^16.9.0" react-is "^16.9.0"
react-router-dom@^5.2.0:
version "5.2.0"
resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-5.2.0.tgz#9e65a4d0c45e13289e66c7b17c7e175d0ea15662"
integrity sha512-gxAmfylo2QUjcwxI63RhQ5G85Qqt4voZpUXSEqCwykV0baaOTQDR1f0PmY8AELqIyVc0NEZUj0Gov5lNGcXgsA==
dependencies:
"@babel/runtime" "^7.1.2"
history "^4.9.0"
loose-envify "^1.3.1"
prop-types "^15.6.2"
react-router "5.2.0"
tiny-invariant "^1.0.2"
tiny-warning "^1.0.0"
react-router@5.2.0:
version "5.2.0"
resolved "https://registry.yarnpkg.com/react-router/-/react-router-5.2.0.tgz#424e75641ca8747fbf76e5ecca69781aa37ea293"
integrity sha512-smz1DUuFHRKdcJC0jobGo8cVbhO3x50tCL4icacOlcwDOEQPq4TMqwx3sY1TP+DvtTgz4nm3thuo7A+BK2U0Dw==
dependencies:
"@babel/runtime" "^7.1.2"
history "^4.9.0"
hoist-non-react-statics "^3.1.0"
loose-envify "^1.3.1"
mini-create-react-context "^0.4.0"
path-to-regexp "^1.7.0"
prop-types "^15.6.2"
react-is "^16.6.0"
tiny-invariant "^1.0.2"
tiny-warning "^1.0.0"
react-scripts@3.4.1: react-scripts@3.4.1:
version "3.4.1" version "3.4.1"
resolved "https://registry.yarnpkg.com/react-scripts/-/react-scripts-3.4.1.tgz#f551298b5c71985cc491b9acf3c8e8c0ae3ada0a" resolved "https://registry.yarnpkg.com/react-scripts/-/react-scripts-3.4.1.tgz#f551298b5c71985cc491b9acf3c8e8c0ae3ada0a"
@ -12236,6 +12353,11 @@ resolve-from@^5.0.0:
resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69"
integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==
resolve-pathname@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/resolve-pathname/-/resolve-pathname-3.0.0.tgz#99d02224d3cf263689becbb393bc560313025dcd"
integrity sha512-C7rARubxI8bXFNB/hqcp/4iUeIXJhJZvFPFPiSPRnhU5UPxzMFIl+2E6yY6c4k9giDJAhtV+enfA+G89N6Csng==
resolve-url-loader@3.1.1: resolve-url-loader@3.1.1:
version "3.1.1" version "3.1.1"
resolved "https://registry.yarnpkg.com/resolve-url-loader/-/resolve-url-loader-3.1.1.tgz#28931895fa1eab9be0647d3b2958c100ae3c0bf0" resolved "https://registry.yarnpkg.com/resolve-url-loader/-/resolve-url-loader-3.1.1.tgz#28931895fa1eab9be0647d3b2958c100ae3c0bf0"
@ -13556,7 +13678,12 @@ tiny-emitter@^2.0.0:
resolved "https://registry.yarnpkg.com/tiny-emitter/-/tiny-emitter-2.1.0.tgz#1d1a56edfc51c43e863cbb5382a72330e3555423" resolved "https://registry.yarnpkg.com/tiny-emitter/-/tiny-emitter-2.1.0.tgz#1d1a56edfc51c43e863cbb5382a72330e3555423"
integrity sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q== integrity sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==
tiny-warning@^1.0.2: tiny-invariant@^1.0.2:
version "1.1.0"
resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.1.0.tgz#634c5f8efdc27714b7f386c35e6760991d230875"
integrity sha512-ytxQvrb1cPc9WBEI/HSeYYoGD0kWnGEOR8RY6KomWLBVhqz0RgTwVO9dLrGz7dC+nN9llyI7OKAgRq8Vq4ZBSw==
tiny-warning@^1.0.0, tiny-warning@^1.0.2, tiny-warning@^1.0.3:
version "1.0.3" version "1.0.3"
resolved "https://registry.yarnpkg.com/tiny-warning/-/tiny-warning-1.0.3.tgz#94a30db453df4c643d0fd566060d60a875d84754" resolved "https://registry.yarnpkg.com/tiny-warning/-/tiny-warning-1.0.3.tgz#94a30db453df4c643d0fd566060d60a875d84754"
integrity sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA== integrity sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==
@ -14002,6 +14129,11 @@ validate-npm-package-license@^3.0.1:
spdx-correct "^3.0.0" spdx-correct "^3.0.0"
spdx-expression-parse "^3.0.0" spdx-expression-parse "^3.0.0"
value-equal@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/value-equal/-/value-equal-1.0.1.tgz#1e0b794c734c5c0cade179c437d356d931a34d6c"
integrity sha512-NOJ6JZCAWr0zlxZt+xqCHNTEKOsrks2HQd4MqhP1qy4z1SkbEP467eNx6TgDKXMvUOb+OENfJCZwM+16n7fRfw==
vary@~1.1.2: vary@~1.1.2:
version "1.1.2" version "1.1.2"
resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"
@ -14679,3 +14811,8 @@ yup@^0.29.1:
property-expr "^2.0.2" property-expr "^2.0.2"
synchronous-promise "^2.0.13" synchronous-promise "^2.0.13"
toposort "^2.0.2" toposort "^2.0.2"
zod@^1.10.2:
version "1.10.2"
resolved "https://registry.yarnpkg.com/zod/-/zod-1.10.2.tgz#fd2585bfcabc6a1dee267815ce0a036f184a5473"
integrity sha512-/T7CBnpJNf2hOlFburyOSP56nedBqrhwTgrwTKp3xPcZzfdRgRXORVHgDLMOIUQUVJyZbDrQqbS2RHuU/2XmHg==