Merge pull request #106 from matrix-org/matrixtwo/clients

Matrix.to client framework
This commit is contained in:
Jorik Schellekens 2020-09-13 15:00:16 +01:00 committed by GitHub
commit f5f4eb7dae
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
34 changed files with 1574 additions and 248 deletions

View file

@ -3,13 +3,14 @@
"version": "0.1.0",
"private": true,
"dependencies": {
"@quentin-sommer/react-useragent": "^3.1.0",
"classnames": "^2.2.6",
"formik": "^2.1.4",
"matrix-cypher": "^0.1.12",
"react": "^16.13.1",
"react-dom": "^16.13.1",
"react-scripts": "3.4.1",
"yup": "^0.29.1"
"zod": "^1.10.3"
},
"scripts": {
"start": "react-scripts start",
@ -68,14 +69,12 @@
"@types/node": "^12.0.0",
"@types/react": "^16.9.0",
"@types/react-dom": "^16.9.0",
"@types/react-router-dom": "^5.1.5",
"@types/yup": "^0.29.3",
"eslint-config-matrix-org": "^0.1.0",
"husky": "^4.2.5",
"lint-staged": "^10.2.7",
"node-sass": "^4.14.1",
"prettier": "^2.0.5",
"react-router-dom": "^5.2.0",
"storybook-addon-designs": "^5.4.0",
"ts-jest": "^26.1.4",
"typescript": "~3.7.2"

View file

@ -14,10 +14,13 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
@import "./color-scheme";
@import './color-scheme';
#root {
background-color: $app-background;
background-image: url('./imgs/background.svg');
background-repeat: no-repeat;
background-position: 50% -20%;
}
@mixin spacer {

View file

@ -14,33 +14,36 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import React from "react";
import React from 'react';
import SingleColumn from "./layouts/SingleColumn";
import CreateLinkTile from "./components/CreateLinkTile";
import MatrixTile from "./components/MatrixTile";
import Tile from "./components/Tile";
import LinkRouter from "./pages/LinkRouter";
import SingleColumn from './layouts/SingleColumn';
import CreateLinkTile from './components/CreateLinkTile';
import MatrixTile from './components/MatrixTile';
import Tile from './components/Tile';
import LinkRouter from './pages/LinkRouter';
import "./App.scss";
import './App.scss';
import GlobalContext from './contexts/GlobalContext';
/* eslint-disable no-restricted-globals */
const App: React.FC = () => {
let page = (
<>
<CreateLinkTile /> <hr />{" "}
<CreateLinkTile />
<hr />
</>
);
if (location.hash) {
console.log(location.hash);
if (location.hash.startsWith("#/")) {
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{">"}
Links should be in the format {location.host}/#/{'<'}
matrix-resource-identifier{'>'}
</Tile>
);
}
@ -49,7 +52,7 @@ const App: React.FC = () => {
return (
<SingleColumn>
<div className="topSpacer" />
{page}
<GlobalContext>{page}</GlobalContext>
<MatrixTile />
<div className="bottomSpacer" />
</SingleColumn>

View file

@ -14,9 +14,15 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import { LinkedClient, Maturity, ClientKind } from './types';
import {
LinkedClient,
Maturity,
ClientKind,
ClientId,
Platform,
} from './types';
import { LinkKind } from '../parser/types';
import logo from './element.svg';
import logo from '../imgs/element.svg';
const Element: LinkedClient = {
kind: ClientKind.LINKED_CLIENT,
@ -26,7 +32,9 @@ const Element: LinkedClient = {
homepage: 'https://element.io',
maturity: Maturity.STABLE,
description: 'Fully-featured Matrix client for the Web',
tags: [],
platform: Platform.Desktop,
experimental: false,
clientId: ClientId.Element,
toUrl: (link) => {
switch (link.kind) {
case LinkKind.Alias:
@ -50,4 +58,37 @@ const Element: LinkedClient = {
},
};
export const ElementDevelop: LinkedClient = {
kind: ClientKind.LINKED_CLIENT,
name: 'Element Develop',
author: 'Element',
logo: logo,
homepage: 'https://element.io',
maturity: Maturity.STABLE,
description: 'Fully-featured Matrix client for the Web',
platform: Platform.Desktop,
experimental: true,
clientId: ClientId.ElementDevelop,
toUrl: (link) => {
switch (link.kind) {
case LinkKind.Alias:
case LinkKind.RoomId:
return new URL(
`https://develop.element.io/#/room/${link.identifier}`
);
case LinkKind.UserId:
return new URL(
`https://develop.element.io/#/user/${link.identifier}`
);
case LinkKind.Permalink:
return new URL(
`https://develop.element.io/#/room/${link.identifier}`
);
case LinkKind.GroupId:
return new URL(
`https://develop.element.io/#/group/${link.identifier}`
);
}
},
};
export default Element;

74
src/clients/Weechat.tsx Normal file
View file

@ -0,0 +1,74 @@
/*
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 { TextClient, Maturity, ClientKind, ClientId, Platform } from './types';
import { LinkKind } from '../parser/types';
import logo from '../imgs/weechat.svg';
const Weechat: TextClient = {
kind: ClientKind.TEXT_CLIENT,
name: 'Weechat',
logo: logo,
author: 'Poljar',
homepage: 'https://github.com/poljar/weechat-matrix',
maturity: Maturity.LATE_BETA,
experimental: false,
platform: Platform.Desktop,
clientId: ClientId.WeeChat,
toInviteString: (link) => {
switch (link.kind) {
case LinkKind.Alias:
case LinkKind.RoomId:
return (
<span>
Type{' '}
<code>
/join <b>{link.identifier}</b>
</code>
</span>
);
case LinkKind.UserId:
return (
<span>
Type{' '}
<code>
/invite <b>{link.identifier}</b>
</code>
</span>
);
default:
return <span>Weechat doesn't support this kind of link</span>;
}
},
copyString: (link) => {
switch (link.kind) {
case LinkKind.Alias:
case LinkKind.RoomId:
return `/join ${link.identifier}`;
case LinkKind.UserId:
return `/invite ${link.identifier}`;
default:
return '';
}
},
description: 'Command-line Matrix interface using Weechat',
};
export default Weechat;

View file

@ -16,12 +16,24 @@ limitations under the License.
import { Client } from './types';
import Element from './Element.io';
import Element, { ElementDevelop } from './Element.io';
import Weechat from './Weechat';
/*
* All the supported clients of matrix.to
*/
const clients: Client[] = [Element];
const clients: Client[] = [Element, Weechat, ElementDevelop];
/*
* A map from sharer string to client.
* Configured by hand so we can change the mappings
* easily later.
*/
export const clientMap: { [key: string]: Client } = {
[Element.clientId]: Element,
[Weechat.clientId]: Weechat,
[ElementDevelop.clientId]: ElementDevelop,
};
/*
* All the supported clients of matrix.to

View file

@ -20,10 +20,10 @@ 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',
export enum Platform {
iOS = 'iOS',
Android = 'ANDROID',
Desktop = 'DESKTOP',
}
/*
@ -45,6 +45,12 @@ export enum ClientKind {
TEXT_CLIENT = 'TEXT_CLIENT',
}
export enum ClientId {
Element = 'element.io',
ElementDevelop = 'develop.element.io',
WeeChat = 'weechat',
}
/*
* The descriptive details of a client
*/
@ -54,8 +60,10 @@ export interface ClientDescription {
homepage: string;
logo: string;
description: string;
tags: Tag[];
platform: Platform;
maturity: Maturity;
clientId: ClientId;
experimental: boolean;
}
/*
@ -72,7 +80,8 @@ export interface LinkedClient extends ClientDescription {
*/
export interface TextClient extends ClientDescription {
kind: ClientKind.TEXT_CLIENT;
toInviteString(parsedLink: SafeLink): string;
toInviteString(parsedLink: SafeLink): JSX.Element;
copyString(parsedLink: SafeLink): string;
}
/*

View file

@ -0,0 +1,22 @@
/*
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.
*/
.clientList {
display: grid;
row-gap: 20px;
list-style-type: none;
padding-inline-start: 0;
}

View file

@ -0,0 +1,92 @@
/*
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, { useContext } from 'react';
import { UAContext } from '@quentin-sommer/react-useragent';
import { SafeLink } from '../parser/types';
import { ActionType, ClientContext } from '../contexts/ClientContext';
import Clients from '../clients';
import { Client, Platform } from '../clients/types';
import ClientTile from './ClientTile';
import './ClientList.scss';
interface IProps {
link: SafeLink;
rememberSelection: boolean;
}
const ClientList: React.FC<IProps> = ({ link, rememberSelection }: IProps) => {
const [
{ showOnlyDeviceClients, showExperimentalClients },
clientDispatcher,
] = useContext(ClientContext);
const { uaResults } = useContext(UAContext);
/*
* Function to decide whether a client is shown
*/
const showClient = (client: Client): boolean => {
let showClient = false;
if (!showOnlyDeviceClients || uaResults === {}) {
showClient = true;
}
switch (client.platform) {
case Platform.Desktop:
showClient = showClient || !(uaResults as any).mobile;
break;
case Platform.iOS:
showClient = showClient || (uaResults as any).ios;
break;
case Platform.Android:
showClient = showClient || (uaResults as any).android;
break;
}
if (!showExperimentalClients && client.experimental) {
showClient = false;
}
return showClient;
};
const clientLi = (client: Client): JSX.Element => (
<li
key={client.clientId}
onClick={(): void =>
rememberSelection
? clientDispatcher({
action: ActionType.SetClient,
clientId: client.clientId,
})
: undefined
}
>
<ClientTile client={client} link={link} />
</li>
);
return (
<ul className="clientList">
{Clients.filter(showClient).map(clientLi)}
</ul>
);
};
export default ClientList;

View file

@ -0,0 +1,27 @@
/*
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.
*/
.advanced {
display: grid;
row-gap: 20px;
.advancedOptions {
display: flex;
flex-direction: column;
align-items: flex-start;
}
}

View file

@ -0,0 +1,94 @@
/*
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, { useContext, useState } from 'react';
import './ClientSelection.scss';
import { ActionType, ClientContext } from '../contexts/ClientContext';
import ClientList from './ClientList';
import { SafeLink } from '../parser/types';
import Button from './Button';
interface IProps {
link: SafeLink;
}
const ClientSelection: React.FC<IProps> = ({ link }: IProps) => {
const [clientState, clientStateDispatch] = useContext(ClientContext);
const [rememberSelection, setRememberSelection] = useState(false);
const options = (
<div className="advancedOptions">
<label>
<input
type="checkbox"
onChange={(): void => {
setRememberSelection(!rememberSelection);
}}
checked={rememberSelection}
/>
Remember my selection for future invites in this browser
</label>
<label>
<input
type="checkbox"
onChange={(): void => {
clientStateDispatch({
action: ActionType.ToggleShowOnlyDeviceClients,
});
}}
checked={clientState.showOnlyDeviceClients}
/>
Show only clients suggested for this device
</label>
<label>
<input
type="checkbox"
onChange={(): void => {
clientStateDispatch({
action: ActionType.ToggleShowExperimentalClients,
});
}}
checked={clientState.showExperimentalClients}
/>
Show experimental clients
</label>
</div>
);
const clearSelection =
clientState.clientId !== null ? (
<Button
onClick={(): void =>
clientStateDispatch({
action: ActionType.ClearClient,
})
}
>
Clear my default client
</Button>
) : null;
return (
<div className="advanced">
{options}
<h4>Clients you can accept this invite with</h4>
<ClientList link={link} rememberSelection={rememberSelection} />
{clearSelection}
</div>
);
};
export default ClientSelection;

View file

@ -0,0 +1,79 @@
/*
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 '../color-scheme';
.clientTile {
display: flex;
flex-direction: row;
align-items: center;
min-height: 150px;
width: 100%;
color: $foreground;
> img {
flex-shrink: 0;
height: 130px;
}
> div {
display: flex;
flex-direction: column;
justify-content: space-between;
h1 {
text-align: left;
font-size: 14px;
line-height: 24px;
}
p {
margin-right: 20px;
text-align: left;
}
.button {
margin: 5px;
}
}
border: 1px solid $borders;
border-radius: 8px;
padding: 15px;
// For the chevron
position: relative;
&::hover {
background-color: $grey;
}
}
.clientTileLink {
position: relative;
width: 100%;
&::after {
// TODO: add chevron top right
position: absolute;
right: 10px;
top: 5px;
content: '>';
}
}

View file

@ -0,0 +1,75 @@
/*
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 classNames from 'classnames';
import { Client, ClientKind } from '../clients/types';
import { SafeLink } from '../parser/types';
import Tile from './Tile';
import Button from './Button';
import './ClientTile.scss';
interface IProps {
client: Client;
link: SafeLink;
}
const ClientTile: React.FC<IProps> = ({ client, link }: IProps) => {
const inviteLine =
client.kind === ClientKind.TEXT_CLIENT ? (
<p>{client.toInviteString(link)}</p>
) : null;
const className = classNames('clientTile', {
clientTileLink: client.kind === ClientKind.LINKED_CLIENT,
});
const inviteButton =
client.kind === ClientKind.LINKED_CLIENT ? (
<Button>Accept invite</Button>
) : (
<Button
onClick={() =>
navigator.clipboard.writeText(client.copyString(link))
}
flashChildren="Invite copied"
>
Copy invite
</Button>
);
let clientTile = (
<Tile className={className}>
<img src={client.logo} alt={client.name + ' logo'} />
<div>
<h1>{client.name}</h1>
<p>{client.description}</p>
{inviteLine}
{inviteButton}
</div>
</Tile>
);
if (client.kind === ClientKind.LINKED_CLIENT) {
clientTile = <a href={client.toUrl(link).toString()}>{clientTile}</a>;
}
return clientTile;
};
export default ClientTile;

View file

@ -14,6 +14,8 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
@import '../color-scheme';
.createLinkTile {
background: none;
@ -29,4 +31,12 @@ limitations under the License.
align-self: center;
padding: 0 30px;
}
> a {
color: $foreground;
}
h1 {
word-break: break-all;
}
}

View file

@ -15,12 +15,14 @@ limitations under the License.
*/
import React, { useEffect, useRef } from 'react';
import { Formik, Form } from 'formik';
import Tile from './Tile';
import Button from './Button';
import TextButton from './TextButton';
import Input from './Input';
import { Formik, Form } from 'formik';
import * as Yup from 'yup';
import { parseHash } from '../parser/parser';
import { LinkKind } from '../parser/types';
import './CreateLinkTile.scss';
@ -28,6 +30,24 @@ interface ILinkNotCreatedTileProps {
setLink: React.Dispatch<React.SetStateAction<string>>;
}
interface FormValues {
identifier: string;
}
// Hacky use of types here
function validate(values: FormValues): Partial<FormValues> {
const errors: Partial<FormValues> = {};
const parse = parseHash(values.identifier);
if (parse.kind === LinkKind.ParseFailed) {
errors.identifier =
"That link doesn't look right. Double check the details.";
}
return errors;
}
const LinkNotCreatedTile: React.FC<ILinkNotCreatedTileProps> = (
props: ILinkNotCreatedTileProps
) => {
@ -41,21 +61,13 @@ const LinkNotCreatedTile: React.FC<ILinkNotCreatedTileProps> = (
initialValues={{
identifier: '',
}}
validationSchema={Yup.object({
identifier: Yup.string()
.test(
'is-identifier',
"That link doesn't look right. Double check the details.",
(link) => link
)
.required('Required'),
})}
validate={validate}
onSubmit={(values): void => {
props.setLink(
document.location.protocol +
'//' +
document.location.host +
'/' +
'/#/' +
values.identifier
);
}}
@ -91,9 +103,11 @@ const LinkCreatedTile: React.FC<ILinkCreatedTileProps> = (props) => {
return (
<Tile className="createLinkTile">
<TextButton onClick={(): void => props.setLink('')}>
Create another lnk
Create another link
</TextButton>
<h1>{props.link}</h1>
<a href={props.link}>
<h1>{props.link}</h1>
</a>
<Button
flashChildren={'Copied'}
onClick={(): void => {
@ -109,7 +123,6 @@ const LinkCreatedTile: React.FC<ILinkCreatedTileProps> = (props) => {
const CreateLinkTile: React.FC = () => {
const [link, setLink] = React.useState('');
console.log(link);
if (!link) {
return <LinkNotCreatedTile setLink={setLink} />;
} else {

View file

@ -0,0 +1,31 @@
/*
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 '../color-scheme';
.fakeProgress {
width: 100%;
height: 4px;
background-color: lighten($grey, 50%);
border-radius: 4px;
> div {
width: 60%;
height: 100%;
background-color: $foreground;
border-radius: 4px;
}
}

View file

@ -0,0 +1,27 @@
/*
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 './FakeProgress.scss';
const FakeProgress = () => (
<div className="fakeProgress">
<div />
</div>
);
export default FakeProgress;

View file

@ -15,11 +15,14 @@ limitations under the License.
*/
.inviteTile {
.button {
margin-top: 24px;
}
display: grid;
row-gap: 24px;
> .textButton {
margin-top: 28px;
.inviteTileClientSelection {
margin: 0 5%;
display: grid;
justify-content: space-between;
row-gap: 20px;
}
}

View file

@ -14,43 +14,104 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import React from 'react';
import React, { useState } from 'react';
import './InviteTile.scss';
import Tile from './Tile';
import LinkButton from './LinkButton';
import TextButton from './TextButton';
import Button from './Button';
import ClientSelection from './ClientSelection';
import { Client, ClientKind } from '../clients/types';
import { SafeLink } from '../parser/types';
import TextButton from './TextButton';
import FakeProgress from './FakeProgress';
interface IProps {
children?: React.ReactNode;
client: Client;
client: Client | null;
link: SafeLink;
}
const InviteTile: React.FC<IProps> = ({ children, client, link }: IProps) => {
const [showAdvanced, setShowAdvanced] = useState(false);
let invite: React.ReactNode;
switch (client.kind) {
case ClientKind.LINKED_CLIENT:
invite = (
<LinkButton href={client.toUrl(link).toString()}>
Accept invite
</LinkButton>
let advanced: React.ReactNode;
if (client === null) {
invite = showAdvanced ? (
<FakeProgress />
) : (
<Button onClick={() => setShowAdvanced(!showAdvanced)}>
Accept invite
</Button>
);
} else {
let inviteUseString: string;
switch (client.kind) {
case ClientKind.LINKED_CLIENT:
invite = (
<LinkButton href={client.toUrl(link).toString()}>
Accept invite
</LinkButton>
);
inviteUseString = `Accepting will open ${link.identifier} in ${client.name}.`;
break;
case ClientKind.TEXT_CLIENT:
// TODO: copy to clipboard
invite = <p>{client.toInviteString(link)}</p>;
navigator.clipboard.writeText(client.copyString(link));
inviteUseString = `These are instructions for ${client.name}.`;
break;
}
const advancedToggle = (
<p>
{inviteUseString}
<TextButton
onClick={(): void => setShowAdvanced(!showAdvanced)}
>
Change Client.
</TextButton>
</p>
);
invite = (
<>
{invite}
{advancedToggle}
</>
);
}
if (showAdvanced) {
if (client === null) {
advanced = (
<>
<h4>Pick an app to accept the invite with</h4>
<ClientSelection link={link} />
</>
);
break;
case ClientKind.TEXT_CLIENT:
invite = <p>{client.toInviteString(link)}</p>;
break;
} else {
advanced = (
<>
<hr />
<h4>Change app</h4>
<ClientSelection link={link} />
</>
);
}
}
return (
<Tile className="inviteTile">
{children}
{invite}
<TextButton>Advanced options</TextButton>
</Tile>
<>
<Tile className="inviteTile">
{children}
{invite}
<div className="inviteTileClientSelection">{advanced}</div>
</Tile>
</>
);
};

View file

@ -0,0 +1,23 @@
/*
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 ClientTile from './InvitingClientTile';
export default { title: 'ClientTile' };
export const Element = <ClientTile clientName={'element.io'} />;

View file

@ -0,0 +1,58 @@
/*
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 './Tile';
import { clientMap } from '../clients';
import './MatrixTile.scss';
interface IProps {
clientName: string;
}
const InvitingClientTile: React.FC<IProps> = ({ clientName }: IProps) => {
const client = clientMap[clientName];
if (!client) {
return (
<Tile className="matrixTile">
{/* TODO: add gh link */}
<p>
The client that created this link "{clientName}" is not a
recognised client. If this is a mistake and you'd like a
nice advertisement for it here please{' '}
<a href="https://github.com/matrix-org/matrix.to">
open a pr
</a>
.
</p>
</Tile>
);
}
return (
<Tile className="matrixTile">
<img src={client.logo} alt={client.name} />
<h2>
Invite created with <a href={client.homepage}>{client.name}</a>
</h2>
<div>{client.description}</div>
</Tile>
);
};
export default InvitingClientTile;

View file

@ -21,8 +21,14 @@ import './Button.scss';
interface IProps extends React.LinkHTMLAttributes<HTMLElement> {}
const LinkButton: React.FC<IProps> = ({ className, ...props }: IProps) => (
<a className={classnames('button', className)} {...props} />
const LinkButton: React.FC<IProps> = ({
className,
children,
...props
}: IProps) => (
<a className={classnames('button', className)} {...props}>
{children}
</a>
);
export default LinkButton;

View file

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import React, { useState, useEffect } from 'react';
import React, { useState, useEffect, useContext } from 'react';
import { getEvent, client } from 'matrix-cypher';
import { RoomPreviewWithTopic } from './RoomPreview';
@ -22,13 +22,14 @@ import InviteTile from './InviteTile';
import { SafeLink, LinkKind } from '../parser/types';
import UserPreview from './UserPreview';
import EventPreview from './EventPreview';
import Clients from '../clients';
import { clientMap } from '../clients';
import {
getRoomFromId,
getRoomFromAlias,
getRoomFromPermalink,
getUser,
} from '../utils/cypher-wrapper';
import { ClientContext } from '../contexts/ClientContext';
interface IProps {
link: SafeLink;
@ -91,8 +92,19 @@ const LinkPreview: React.FC<IProps> = ({ link }: IProps) => {
(async (): Promise<void> => setContent(await invite({ link })))();
}, [link]);
const [{ clientId }] = useContext(ClientContext);
// Select which client to link to
const displayClientId = clientId
? clientId
: link.arguments.client
? link.arguments.client
: null;
const client = displayClientId ? clientMap[displayClientId] : null;
return (
<InviteTile client={Clients[0]} link={link}>
<InviteTile client={client} link={link}>
{content}
</InviteTile>
);

View file

@ -26,11 +26,15 @@ interface IProps {
}
const RoomPreview: React.FC<IProps> = ({ room }: IProps) => {
const roomAlias = room.aliases ? room.aliases[0] : room.room_id;
const roomAlias = room.canonical_alias
? room.canonical_alias
: room.aliases
? room.aliases[0]
: room.room_id;
return (
<div className="roomPreview">
<RoomAvatar room={room} />
<h1>{room.name ? room.name : room.room_id}</h1>
<h1>{room.name ? room.name : roomAlias}</h1>
<p>{room.num_joined_members.toLocaleString()} members</p>
<p>{roomAlias}</p>
</div>

View file

@ -15,54 +15,92 @@ limitations under the License.
*/
import React from 'react';
import { object, string, boolean, TypeOf } from 'zod';
import { prefixFetch, Client, discoverServer } from 'matrix-cypher';
import { ClientId } from '../clients/types';
import { persistReducer } from '../utils/localStorage';
type State = {
clientURL: string;
client: Client;
}[];
const STATE_SCHEMA = object({
clientId: string().nullable(),
showOnlyDeviceClients: boolean(),
showExperimentalClients: boolean(),
});
type State = TypeOf<typeof STATE_SCHEMA>;
// Actions are a discriminated union.
export enum ActionTypes {
AddClient = 'ADD_CLIENT',
RemoveClient = 'REMOVE_CLIENT',
export enum ActionType {
SetClient = 'SET_CLIENT',
ClearClient = 'CLEAR_CLIENT',
ToggleShowOnlyDeviceClients = 'TOGGLE_SHOW_ONLY_DEVICE_CLIENTS',
ToggleShowExperimentalClients = 'TOGGLE_SHOW_EXPERIMENTAL_CLIENTS',
}
export interface AddClient {
action: ActionTypes.AddClient;
clientURL: string;
interface SetClient {
action: ActionType.SetClient;
clientId: ClientId;
}
export interface RemoveClient {
action: ActionTypes.RemoveClient;
clientURL: string;
interface ClearClient {
action: ActionType.ClearClient;
}
export type Action = AddClient | RemoveClient;
interface ToggleShowOnlyDeviceClients {
action: ActionType.ToggleShowOnlyDeviceClients;
}
export const INITIAL_STATE: State = [];
export const reducer = async (state: State, action: Action): Promise<State> => {
switch (action.action) {
case ActionTypes.AddClient:
return state.filter((x) => x.clientURL !== action.clientURL);
interface ToggleShowExperimentalClients {
action: ActionType.ToggleShowExperimentalClients;
}
case ActionTypes.RemoveClient:
if (!state.filter((x) => x.clientURL === action.clientURL)) {
const resolvedURL = await discoverServer(action.clientURL);
state.push({
clientURL: resolvedURL,
client: prefixFetch(resolvedURL),
});
}
}
return state;
export type Action =
| SetClient
| ClearClient
| ToggleShowOnlyDeviceClients
| ToggleShowExperimentalClients;
const INITIAL_STATE: State = {
clientId: null,
showOnlyDeviceClients: true,
showExperimentalClients: false,
};
// The null is a hack to make the type checker happy
// create context does not need an argument
const { Provider, Consumer } = React.createContext<typeof reducer | null>(null);
export const [initialState, reducer] = persistReducer(
'default-client',
INITIAL_STATE,
STATE_SCHEMA,
(state: State, action: Action): State => {
switch (action.action) {
case ActionType.SetClient:
return {
...state,
clientId: action.clientId,
};
case ActionType.ToggleShowOnlyDeviceClients:
return {
...state,
showOnlyDeviceClients: !state.showOnlyDeviceClients,
};
case ActionType.ToggleShowExperimentalClients:
return {
...state,
showExperimentalClients: !state.showExperimentalClients,
};
case ActionType.ClearClient:
return {
...state,
clientId: null,
};
}
}
);
// The defualt reducer needs to be overwritten with the one above
// after it's been put through react's useReducer
export const ClientContext = React.createContext<
[State, React.Dispatch<Action>]
>([initialState, (): void => {}]);
// Quick rename to make importing easier
export const ClientProvider = Provider;
export const ClientConsumer = Consumer;
export const ClientProvider = ClientContext.Provider;
export const ClientConsumer = ClientContext.Consumer;

View file

@ -0,0 +1,36 @@
/*
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, { useReducer } from 'react';
import { UserAgentProvider } from '@quentin-sommer/react-useragent';
import {
ClientProvider,
reducer as clientReducer,
initialState as clientInitialState,
} from './ClientContext';
interface IProps {
children: React.ReactNode;
}
export default ({ children }: IProps): JSX.Element => (
<UserAgentProvider ua={window.navigator.userAgent}>
<ClientProvider value={useReducer(clientReducer, clientInitialState)}>
{children}
</ClientProvider>
</UserAgentProvider>
);

113
src/contexts/HSContext.ts Normal file
View file

@ -0,0 +1,113 @@
/*
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 { string, object, union, literal, TypeOf } from 'zod';
import { persistReducer } from '../utils/localStorage';
//import { prefixFetch, Client, discoverServer } from 'matrix-cypher';
enum HSOptions {
// The homeserver contact policy hasn't
// been set yet.
Unset = 'UNSET',
// Matrix.to should only contact a single provided homeserver
TrustedClientOnly = 'TRUSTED_CLIENT_ONLY',
// Matrix.to may contact any homeserver it requires
Any = 'ANY',
// Matrix.to may not contact any homeservers
None = 'NONE',
}
const STATE_SCHEMA = union([
object({
option: literal(HSOptions.Unset),
}),
object({
option: literal(HSOptions.None),
}),
object({
option: literal(HSOptions.Any),
}),
object({
option: literal(HSOptions.TrustedClientOnly),
hs: string(),
}),
]);
type State = TypeOf<typeof STATE_SCHEMA>;
// TODO: rename actions to something with more meaning out of context
export enum ActionTypes {
SetHS = 'SET_HS',
SetAny = 'SET_ANY',
SetNone = 'SET_NONE',
}
export interface SetHS {
action: ActionTypes.SetHS;
HSURL: string;
}
export interface SetAny {
action: ActionTypes.SetAny;
}
export interface SetNone {
action: ActionTypes.SetNone;
}
export type Action = SetHS | SetAny | SetNone;
export const INITIAL_STATE: State = {
option: HSOptions.Unset,
};
export const [initialState, reducer] = persistReducer(
'home-server-options',
INITIAL_STATE,
STATE_SCHEMA,
(state: State, action: Action): State => {
switch (action.action) {
case ActionTypes.SetNone:
return {
option: HSOptions.None,
};
case ActionTypes.SetAny:
return {
option: HSOptions.Any,
};
case ActionTypes.SetHS:
return {
option: HSOptions.TrustedClientOnly,
hs: action.HSURL,
};
default:
return state;
}
}
);
// The defualt reducer needs to be overwritten with the one above
// after it's been put through react's useReducer
const { Provider, Consumer } = React.createContext<
[State, React.Dispatch<Action>]
>([initialState, (): void => {}]);
// Quick rename to make importing easier
export const HSProvider = Provider;
export const HSConsumer = Consumer;

221
src/imgs/background.svg Normal file
View file

@ -0,0 +1,221 @@
<svg width="1440" height="1042" viewBox="0 0 1440 1042" fill="none" xmlns="http://www.w3.org/2000/svg">
<g opacity="0.26">
<path d="M1027.99 490.479C1262.01 747.694 1465.48 1130.2 1528.69 1431.86C1592.2 1735.13 1503.31 1905.67 1310.8 1852.11C1117.48 1798.33 851.081 1526.18 658.35 1185.16C466.355 845.4 378.93 495.041 443.1 322.215C506.167 152.333 707.508 183.749 938.653 399.615C968.31 427.352 998.261 457.739 1027.99 490.479Z" stroke="url(#paint0_linear)" stroke-opacity="0.5" stroke-miterlimit="10"/>
<path d="M1044.18 491.803C1277.61 755.198 1476.23 1143.01 1532.89 1446.28C1589.85 1751.17 1493.74 1919.21 1297.33 1860.57C1100.11 1801.64 833.789 1522.5 645.032 1176.41C457.01 831.568 376.871 479.001 447.59 307.942C517.133 139.825 723.184 176.612 954.844 398.585C984.648 427.132 1014.53 458.327 1044.18 491.803Z" stroke="url(#paint1_linear)" stroke-opacity="0.5" stroke-miterlimit="10"/>
<path d="M1060.81 493.569C1293.5 763.144 1486.97 1156.1 1536.79 1460.77C1586.9 1767.06 1483.51 1932.53 1283.27 1868.59C1082.22 1804.44 816.124 1518.16 631.709 1167.14C447.955 817.515 375.249 462.889 452.665 293.816C528.757 127.612 739.517 169.917 971.546 397.996C1001.42 427.279 1031.3 459.284 1060.81 493.569Z" stroke="url(#paint2_linear)" stroke-opacity="0.5" stroke-miterlimit="10"/>
<path d="M1077.88 495.776C1309.61 771.458 1497.64 1169.49 1540.46 1475.41C1583.51 1782.95 1472.69 1945.55 1268.62 1876.32C1063.75 1806.79 798.166 1513.52 618.239 1157.72C439.048 803.168 374.068 446.776 458.328 279.763C541.117 115.62 756.587 163.59 988.836 397.849C1018.64 427.941 1048.44 460.755 1077.88 495.776Z" stroke="url(#paint3_linear)" stroke-opacity="0.5" stroke-miterlimit="10"/>
<path d="M1095.4 498.425C1325.96 780.214 1508.24 1183.1 1543.86 1490.06C1579.62 1798.62 1461.21 1958.21 1253.4 1883.53C1044.7 1808.56 779.774 1508.23 604.704 1147.72C430.223 788.601 373.265 430.59 464.516 265.932C554.148 104.069 774.329 157.778 1006.5 398.144C1036.31 429.045 1066.11 462.668 1095.4 498.425Z" stroke="url(#paint4_linear)" stroke-opacity="0.5" stroke-miterlimit="10"/>
<path d="M1113.28 501.589C1342.51 789.484 1518.76 1197.08 1546.94 1504.92C1575.2 1814.37 1449.14 1970.71 1237.57 1890.44C1025.12 1809.88 761.152 1502.64 591.086 1137.56C421.609 773.813 372.967 414.404 471.209 252.247C567.832 92.8854 792.575 152.407 1024.68 398.953C1054.48 430.663 1084.14 465.022 1113.28 501.589Z" stroke="url(#paint5_linear)" stroke-opacity="0.5" stroke-miterlimit="10"/>
<path d="M1131.6 505.194C1359.29 799.122 1529.21 1211.36 1549.67 1519.78C1570.2 1829.89 1436.27 1982.78 1221.02 1896.92C1004.88 1810.69 741.947 1496.46 577.253 1126.97C413.148 758.878 373.042 398.218 478.496 238.783C582.184 81.9969 811.636 147.551 1043.3 400.204C1073.1 432.724 1102.68 467.892 1131.6 505.194Z" stroke="url(#paint6_linear)" stroke-opacity="0.5" stroke-miterlimit="10"/>
<path d="M1150.29 509.314C1376.21 809.202 1539.51 1225.85 1552.02 1534.71C1564.6 1845.27 1422.72 1994.48 1203.79 1902.88C983.98 1810.91 722.443 1489.76 563.342 1115.93C404.83 743.574 373.554 382.031 486.367 225.466C597.267 71.549 831.282 143.21 1062.5 402.043C1092.23 435.299 1121.59 471.203 1150.29 509.314Z" stroke="url(#paint7_linear)" stroke-opacity="0.5" stroke-miterlimit="10"/>
<path d="M1169.43 513.949C1393.36 819.796 1549.74 1240.64 1554.08 1549.8C1558.42 1860.57 1408.52 2005.96 1186.06 1908.54C962.716 1810.69 702.724 1482.62 549.436 1104.75C396.738 728.122 374.514 365.918 494.833 212.369C613.018 61.4687 851.596 139.384 1082.15 404.323C1111.73 438.388 1140.95 475.028 1169.43 513.949Z" stroke="url(#paint8_linear)" stroke-opacity="0.5" stroke-miterlimit="10"/>
<path d="M1188.93 519.027C1410.65 830.76 1559.82 1255.65 1555.77 1564.81C1551.73 1875.58 1393.58 2016.92 1167.59 1913.55C940.711 1809.73 682.485 1474.83 535.38 1092.98C388.863 712.453 375.984 349.733 503.883 199.569C629.574 51.9056 872.567 136.221 1102.24 407.194C1131.75 441.921 1160.74 479.444 1188.93 519.027Z" stroke="url(#paint9_linear)" stroke-opacity="0.5" stroke-miterlimit="10"/>
<path d="M1208.87 524.692C1428.24 842.237 1569.83 1271.03 1557.1 1579.89C1544.37 1890.45 1377.91 2027.44 1148.53 1918.11C918.192 1808.26 662.027 1466.59 521.323 1080.91C381.135 696.634 377.971 333.694 513.523 186.914C646.794 42.7086 894.276 133.425 1122.85 410.505C1152.21 446.115 1180.98 484.299 1208.87 524.692Z" stroke="url(#paint10_linear)" stroke-opacity="0.5" stroke-miterlimit="10"/>
<path d="M1229.18 530.871C1445.9 854.229 1579.62 1286.62 1558.05 1595.05C1536.42 1905.16 1361.5 2037.67 1128.73 1922.15C895.012 1806.2 641.127 1457.76 507.12 1068.4C373.702 680.521 380.399 317.654 523.752 174.626C664.676 34.0263 916.573 131.365 1143.89 414.404C1173.11 450.749 1201.66 489.743 1229.18 530.871Z" stroke="url(#paint11_linear)" stroke-opacity="0.5" stroke-miterlimit="10"/>
<path d="M1249.94 537.566C1463.79 866.589 1589.26 1302.37 1558.65 1610.13C1527.81 1919.51 1344.43 2047.3 1108.35 1925.61C871.318 1803.41 619.936 1448.34 492.994 1055.53C366.493 664.261 383.345 301.688 534.645 162.56C683.37 25.7857 939.609 129.819 1165.46 418.891C1194.52 456.046 1222.78 495.776 1249.94 537.566Z" stroke="url(#paint12_linear)" stroke-opacity="0.5" stroke-miterlimit="10"/>
<path d="M1271.06 544.851C1481.74 879.465 1598.75 1318.48 1558.79 1625.28C1518.61 1933.71 1326.54 2056.57 1087.3 1928.63C847.033 1800.1 598.447 1438.41 478.791 1042.36C359.502 647.854 386.877 285.87 546.199 150.788C702.871 18.0611 963.305 128.937 1187.53 423.895C1216.31 461.859 1244.27 502.325 1271.06 544.851Z" stroke="url(#paint13_linear)" stroke-opacity="0.5" stroke-miterlimit="10"/>
<path d="M1292.55 552.649C1499.92 892.782 1608.1 1334.81 1558.5 1640.44C1508.68 1947.69 1307.93 2065.33 1065.52 1931.06C822.088 1796.12 576.52 1427.89 464.443 1028.82C352.734 631.226 390.853 270.052 558.417 139.311C723.11 10.7768 987.739 128.642 1210.05 429.56C1238.61 468.186 1266.2 509.461 1292.55 552.649Z" stroke="url(#paint14_linear)" stroke-opacity="0.5" stroke-miterlimit="10"/>
<path d="M1314.47 561.037C1518.24 906.614 1617.22 1351.37 1557.91 1655.6C1498.23 1961.44 1288.64 2073.64 1043.15 1932.9C796.623 1791.56 554.44 1416.85 450.163 1014.92C346.328 614.378 395.413 254.455 571.218 128.202C744.007 4.15597 1012.83 129.085 1233.01 435.814C1261.27 475.177 1288.57 517.187 1314.47 561.037Z" stroke="url(#paint15_linear)" stroke-opacity="0.5" stroke-miterlimit="10"/>
<path d="M1336.7 570.087C1536.64 921.035 1626.13 1368.22 1556.73 1670.75C1486.97 1974.83 1268.48 2081.44 1019.97 1934.15C770.502 1786.26 531.85 1405.15 435.816 1000.57C340.149 597.456 400.566 238.93 584.688 117.46C765.718 -1.95092 1038.59 130.114 1256.41 442.657C1284.45 482.828 1311.31 525.501 1336.7 570.087Z" stroke="url(#paint16_linear)" stroke-opacity="0.5" stroke-miterlimit="10"/>
<path d="M1359.36 579.651C1555.18 935.823 1634.81 1385.29 1555.18 1685.84C1475.12 1988 1247.58 2088.65 996.27 1934.74C743.931 1780.16 509.106 1392.86 421.534 985.853C334.257 580.313 406.228 223.553 598.885 107.012C788.232 -7.46897 1065.08 131.88 1280.4 450.088C1308.07 490.995 1334.49 534.403 1359.36 579.651Z" stroke="url(#paint17_linear)" stroke-opacity="0.5" stroke-miterlimit="10"/>
<path d="M1382.32 589.804C1573.8 951.052 1643.27 1402.5 1553.12 1700.77C1462.46 2000.66 1225.8 2095.2 971.765 1934.59C716.629 1773.31 485.999 1379.92 407.185 970.623C328.665 563.023 412.483 208.323 613.751 97.0059C811.56 -12.3986 1092.23 134.308 1304.76 458.254C1332.06 499.823 1358.04 543.894 1382.32 589.804Z" stroke="url(#paint18_linear)" stroke-opacity="0.5" stroke-miterlimit="10"/>
<path d="M1405.73 600.62C1592.57 966.871 1651.51 1420.01 1550.62 1715.78C1449.22 2013.09 1203.35 2101.31 946.599 1933.93C688.815 1765.88 462.6 1366.38 392.837 955.173C323.442 545.587 419.329 193.241 629.281 87.368C835.626 -16.6656 1120.05 137.472 1329.63 466.936C1356.49 509.315 1381.96 554.048 1405.73 600.62Z" stroke="url(#paint19_linear)" stroke-opacity="0.5" stroke-miterlimit="10"/>
<path d="M1429.42 612.024C1611.33 983.204 1659.53 1437.74 1547.6 1730.72C1435.16 2025.23 1180.02 2106.83 920.768 1932.6C660.407 1757.72 438.903 1352.32 378.559 939.354C318.51 528.002 426.834 178.379 645.469 78.1708C860.424 -20.2711 1148.53 141.444 1354.8 476.427C1381.37 519.467 1406.31 564.863 1429.42 612.024Z" stroke="url(#paint20_linear)" stroke-opacity="0.5" stroke-miterlimit="10"/>
<path d="M1453.49 624.089C1630.25 999.979 1667.19 1455.7 1544.15 1745.5C1420.45 2036.93 1155.96 2111.61 894.279 1930.54C631.49 1748.74 414.99 1337.54 364.36 923.168C313.951 510.344 434.933 163.737 662.472 69.4153C886.111 -23.2879 1177.82 146.153 1380.63 486.506C1406.68 530.283 1431.04 576.34 1453.49 624.089Z" stroke="url(#paint21_linear)" stroke-opacity="0.5" stroke-miterlimit="10"/>
<path d="M1477.91 636.745C1649.23 1017.27 1674.69 1473.72 1540.24 1760.22C1405.06 2048.19 1131.16 2115.8 867.12 1927.82C602.05 1739.03 390.848 1322.16 350.226 906.615C309.752 492.54 443.612 149.318 680.129 61.1025C912.525 -25.5676 1207.69 151.598 1406.83 497.249C1432.36 541.761 1456.13 588.407 1477.91 636.745Z" stroke="url(#paint22_linear)" stroke-opacity="0.5" stroke-miterlimit="10"/>
<path d="M1502.64 650.135C1668.29 1035.07 1681.84 1492.12 1535.69 1774.86C1388.8 2059.08 1105.41 2119.33 839.233 1924.36C571.956 1728.58 366.346 1306.19 336.101 889.691C305.929 474.661 452.961 135.117 698.456 53.3026C939.757 -27.1137 1238.24 157.925 1433.32 508.799C1458.42 553.9 1481.6 601.208 1502.64 650.135Z" stroke="url(#paint23_linear)" stroke-opacity="0.5" stroke-miterlimit="10"/>
<path d="M1527.74 664.114C1687.35 1053.39 1688.68 1510.58 1530.75 1789.28C1371.95 2069.52 1078.99 2122.13 810.753 1920.02C541.415 1717.1 341.767 1289.42 322.118 872.181C302.47 456.635 463.042 121.138 717.589 45.9454C967.794 -27.9229 1269.51 164.988 1460.4 520.939C1484.91 566.702 1507.43 614.672 1527.74 664.114Z" stroke="url(#paint24_linear)" stroke-opacity="0.5" stroke-miterlimit="10"/>
<path d="M1553.05 678.755C1706.41 1072.16 1695.15 1529.27 1525.09 1803.63C1354.14 2079.46 1051.54 2124.26 781.463 1915.09C510.212 1705.04 316.745 1272.13 308.061 854.597C299.451 438.536 473.711 107.453 737.383 39.1764C996.566 -27.9966 1301.45 172.934 1487.78 533.961C1511.77 580.313 1533.62 628.798 1553.05 678.755Z" stroke="url(#paint25_linear)" stroke-opacity="0.5" stroke-miterlimit="10"/>
<path d="M1578.73 694.132C1725.47 1091.51 1701.41 1548.11 1519.05 1817.83C1335.74 2089.02 1023.5 2125.66 751.66 1909.28C478.642 1692.02 291.725 1254.1 294.3 836.424C296.802 420.363 485.045 94.1365 757.989 32.8494C1026.3 -27.3341 1334.05 181.69 1515.67 547.499C1539 594.587 1560.12 643.661 1578.73 694.132Z" stroke="url(#paint26_linear)" stroke-opacity="0.5" stroke-miterlimit="10"/>
<path d="M1604.71 710.171C1744.6 1111.3 1707.22 1567.16 1512.36 1831.88C1316.46 2098.07 994.506 2126.32 721.046 1902.73C446.41 1678.26 266.409 1235.49 280.539 818.03C294.594 402.19 497.113 81.0396 779.329 27.1099C1056.76 -25.8633 1367.31 191.327 1543.93 561.919C1566.59 609.521 1586.9 659.184 1604.71 710.171Z" stroke="url(#paint27_linear)" stroke-opacity="0.5" stroke-miterlimit="10"/>
<path d="M1630.98 726.872C1763.74 1131.6 1712.74 1586.29 1505.14 1845.71C1296.44 2106.53 964.776 2126.18 689.845 1895.37C413.81 1663.62 240.874 1216.21 266.925 799.269C292.829 383.871 509.771 68.3118 801.407 21.9602C1088.04 -23.5821 1401.24 201.849 1572.55 577.076C1594.56 625.267 1614.06 675.444 1630.98 726.872Z" stroke="url(#paint28_linear)" stroke-opacity="0.5" stroke-miterlimit="10"/>
<path d="M1657.48 744.236C1782.8 1152.42 1717.82 1605.49 1497.27 1859.32C1275.55 2114.48 934.089 2125.15 657.833 1887.13C380.474 1648.09 215.118 1196.13 253.385 780.066C291.504 365.551 523.238 55.8777 824.22 17.3985C1120.05 -20.4185 1435.82 213.326 1601.55 592.968C1622.89 641.747 1641.58 692.366 1657.48 744.236Z" stroke="url(#paint29_linear)" stroke-opacity="0.5" stroke-miterlimit="10"/>
<path d="M1684.26 762.41C1801.78 1173.76 1722.53 1624.99 1488.88 1872.79C1253.98 2121.91 902.667 2123.45 625.307 1878.09C346.77 1631.69 189.289 1175.53 240.065 760.57C290.695 347.232 537.368 43.8863 847.842 13.4266C1152.94 -16.4444 1471.07 225.688 1630.98 609.596C1651.51 658.965 1669.32 710.099 1684.26 762.41Z" stroke="url(#paint30_linear)" stroke-opacity="0.5" stroke-miterlimit="10"/>
<path d="M1711.27 781.17C1820.77 1195.54 1726.87 1644.49 1479.83 1885.88C1231.54 2128.6 870.434 2120.73 592.045 1868C312.551 1614.25 163.238 1153.97 226.893 740.631C290.327 328.837 552.233 32.187 872.127 10.1148C1186.58 -11.5896 1506.91 239.003 1660.64 627.032C1680.44 676.916 1697.36 728.565 1711.27 781.17Z" stroke="url(#paint31_linear)" stroke-opacity="0.5" stroke-miterlimit="10"/>
<path d="M1738.5 800.741C1839.61 1217.91 1730.7 1664.13 1470.19 1898.91C1208.28 2134.86 837.319 2117.35 558.193 1857.26C277.89 1596.08 137.113 1131.97 213.941 720.472C290.474 310.518 567.834 21.0044 897.295 7.46681C1221.09 -5.85008 1543.41 253.277 1690.74 645.28C1709.72 695.678 1725.69 747.768 1738.5 800.741Z" stroke="url(#paint32_linear)" stroke-opacity="0.5" stroke-miterlimit="10"/>
<path d="M1766.02 820.974C1858.45 1240.71 1734.23 1683.85 1459.96 1911.56C1184.22 2140.45 803.394 2113.01 523.68 1845.49C242.788 1576.87 110.842 1109.24 201.136 699.871C291.137 292.124 584.244 10.1889 923.198 5.48016C1256.41 0.845004 1580.57 268.507 1721.2 664.335C1739.31 715.248 1754.25 767.706 1766.02 820.974Z" stroke="url(#paint33_linear)" stroke-opacity="0.5" stroke-miterlimit="10"/>
<path d="M1793.69 842.016C1877.14 1264.04 1737.24 1703.79 1449.07 1923.99C1159.34 2145.38 768.73 2107.78 488.574 1832.91C207.241 1556.86 84.567 1085.84 188.623 679.049C292.311 273.804 601.314 -0.185527 949.908 4.15534C1292.54 8.4962 1618.32 284.693 1751.96 684.2C1769.18 735.554 1783.09 788.38 1793.69 842.016Z" stroke="url(#paint34_linear)" stroke-opacity="0.5" stroke-miterlimit="10"/>
<path d="M1821.58 863.72C1895.68 1287.87 1739.82 1723.65 1437.51 1936.06C1133.59 2149.65 733.114 2101.53 452.737 1819.22C171.183 1535.82 58.0761 1061.63 176.261 657.786C294.005 255.484 619.197 -10.1182 977.358 3.56654C1329.41 17.1042 1656.66 301.909 1783.02 704.8C1799.28 756.67 1812.16 809.864 1821.58 863.72Z" stroke="url(#paint35_linear)" stroke-opacity="0.5" stroke-miterlimit="10"/>
<path d="M1849.62 886.16C1914.08 1312.15 1741.88 1743.59 1425.3 1947.83C1107.03 2153.18 696.764 2094.39 416.313 1804.66C134.759 1513.82 31.5131 1036.77 164.195 636.229C296.289 237.237 637.818 -19.536 1005.62 3.78695C1367.09 26.742 1695.67 320.229 1814.37 726.357C1829.68 778.594 1841.45 832.083 1849.62 886.16Z" stroke="url(#paint36_linear)" stroke-opacity="0.5" stroke-miterlimit="10"/>
<path d="M1877.8 909.409C1932.33 1336.95 1743.43 1763.6 1412.42 1959.31C1079.65 2156.05 659.526 2086.3 379.297 1789.21C97.8897 1490.86 4.94595 1011.23 152.346 614.377C299.084 219.064 657.245 -28.5124 1034.61 4.66948C1405.5 37.2627 1735.11 339.431 1846.01 748.649C1860.29 801.255 1870.89 855.037 1877.8 909.409Z" stroke="url(#paint37_linear)" stroke-opacity="0.5" stroke-miterlimit="10"/>
<path d="M1906.21 933.321C1950.51 1362.18 1744.53 1783.62 1398.88 1970.42C1051.39 2158.18 621.478 2077.18 341.69 1772.65C60.6512 1466.88 -21.622 984.97 140.717 592.232C302.54 200.965 677.48 -36.8991 1064.41 6.36235C1444.73 48.8881 1775.22 359.812 1877.95 771.826C1891.12 824.799 1900.54 878.876 1906.21 933.321Z" stroke="url(#paint38_linear)" stroke-opacity="0.5" stroke-miterlimit="10"/>
<path d="M1934.69 958.042C1968.39 1387.93 1745.05 1803.7 1384.68 1981.16C1022.32 2159.58 582.699 2067.02 303.426 1755.14C23.0499 1441.94 -48.3321 957.968 129.387 569.718C306.517 183.014 698.456 -44.7714 1095.03 8.86405C1484.76 61.543 1815.91 381.222 1910.11 795.885C1922.18 849.152 1930.42 903.45 1934.69 958.042Z" stroke="url(#paint39_linear)" stroke-opacity="0.5" stroke-miterlimit="10"/>
<path d="M1963.32 983.498C1986.13 1414.13 1745.12 1823.79 1369.82 1991.54C992.449 2160.17 543.11 2055.91 264.721 1736.6C-14.9201 1416.04 -74.8957 930.304 118.498 546.984C311.156 165.135 720.314 -52.0554 1126.46 12.1747C1525.61 75.3011 1857.13 403.735 1942.56 820.753C1953.46 874.315 1960.37 928.833 1963.32 983.498Z" stroke="url(#paint40_linear)" stroke-opacity="0.5" stroke-miterlimit="10"/>
<path d="M1992.02 1009.76C2003.57 1440.83 1744.61 1843.87 1354.14 2001.54C961.613 2160.02 502.634 2043.7 225.275 1717.1C-53.2619 1389.11 -101.537 901.978 107.826 523.955C316.379 147.404 742.905 -58.7503 1158.61 16.2951C1567.11 90.0898 1898.85 427.279 1975.09 846.43C1984.88 900.286 1990.54 954.952 1992.02 1009.76Z" stroke="url(#paint41_linear)" stroke-opacity="0.5" stroke-miterlimit="10"/>
<path d="M2020.79 1036.7C2020.79 1467.91 1743.5 1863.89 1337.88 2010.96C930.117 2158.85 461.498 2030.31 185.39 1696.36C-91.8961 1361.16 -128.102 872.846 97.5236 500.636C322.193 129.749 766.306 -64.8539 1191.51 21.3012C1609.42 106.058 1941.02 452.003 2007.91 872.993C2016.52 927.144 2020.79 981.956 2020.79 1036.7Z" stroke="url(#paint42_linear)" stroke-opacity="0.5" stroke-miterlimit="10"/>
</g>
<defs>
<linearGradient id="paint0_linear" x1="985.633" y1="213.388" x2="985.633" y2="1861.88" gradientUnits="userSpaceOnUse">
<stop stop-color="#999999"/>
<stop offset="1" stop-color="#7D92FF"/>
</linearGradient>
<linearGradient id="paint1_linear" x1="985.644" y1="203.088" x2="985.644" y2="1872.15" gradientUnits="userSpaceOnUse">
<stop stop-color="#999999"/>
<stop offset="1" stop-color="#7D92FF"/>
</linearGradient>
<linearGradient id="paint2_linear" x1="985.667" y1="192.966" x2="985.667" y2="1882.21" gradientUnits="userSpaceOnUse">
<stop stop-color="#999999"/>
<stop offset="1" stop-color="#7D92FF"/>
</linearGradient>
<linearGradient id="paint3_linear" x1="985.745" y1="182.945" x2="985.745" y2="1892.13" gradientUnits="userSpaceOnUse">
<stop stop-color="#999999"/>
<stop offset="1" stop-color="#7D92FF"/>
</linearGradient>
<linearGradient id="paint4_linear" x1="985.811" y1="173.189" x2="985.811" y2="1901.74" gradientUnits="userSpaceOnUse">
<stop stop-color="#999999"/>
<stop offset="1" stop-color="#7D92FF"/>
</linearGradient>
<linearGradient id="paint5_linear" x1="985.893" y1="163.626" x2="985.893" y2="1911.29" gradientUnits="userSpaceOnUse">
<stop stop-color="#999999"/>
<stop offset="1" stop-color="#7D92FF"/>
</linearGradient>
<linearGradient id="paint6_linear" x1="985.932" y1="154.25" x2="985.932" y2="1920.58" gradientUnits="userSpaceOnUse">
<stop stop-color="#999999"/>
<stop offset="1" stop-color="#7D92FF"/>
</linearGradient>
<linearGradient id="paint7_linear" x1="985.934" y1="145.104" x2="985.934" y2="1929.59" gradientUnits="userSpaceOnUse">
<stop stop-color="#999999"/>
<stop offset="1" stop-color="#7D92FF"/>
</linearGradient>
<linearGradient id="paint8_linear" x1="985.952" y1="136.161" x2="985.952" y2="1938.51" gradientUnits="userSpaceOnUse">
<stop stop-color="#999999"/>
<stop offset="1" stop-color="#7D92FF"/>
</linearGradient>
<linearGradient id="paint9_linear" x1="985.954" y1="127.54" x2="985.954" y2="1947.04" gradientUnits="userSpaceOnUse">
<stop stop-color="#999999"/>
<stop offset="1" stop-color="#7D92FF"/>
</linearGradient>
<linearGradient id="paint10_linear" x1="985.935" y1="119.049" x2="985.935" y2="1955.34" gradientUnits="userSpaceOnUse">
<stop stop-color="#999999"/>
<stop offset="1" stop-color="#7D92FF"/>
</linearGradient>
<linearGradient id="paint11_linear" x1="985.894" y1="110.897" x2="985.894" y2="1963.44" gradientUnits="userSpaceOnUse">
<stop stop-color="#999999"/>
<stop offset="1" stop-color="#7D92FF"/>
</linearGradient>
<linearGradient id="paint12_linear" x1="985.853" y1="102.951" x2="985.853" y2="1971.17" gradientUnits="userSpaceOnUse">
<stop stop-color="#999999"/>
<stop offset="1" stop-color="#7D92FF"/>
</linearGradient>
<linearGradient id="paint13_linear" x1="985.78" y1="95.2832" x2="985.78" y2="1978.72" gradientUnits="userSpaceOnUse">
<stop stop-color="#999999"/>
<stop offset="1" stop-color="#7D92FF"/>
</linearGradient>
<linearGradient id="paint14_linear" x1="985.655" y1="87.8389" x2="985.655" y2="1985.98" gradientUnits="userSpaceOnUse">
<stop stop-color="#999999"/>
<stop offset="1" stop-color="#7D92FF"/>
</linearGradient>
<linearGradient id="paint15_linear" x1="985.579" y1="80.7549" x2="985.579" y2="1992.98" gradientUnits="userSpaceOnUse">
<stop stop-color="#999999"/>
<stop offset="1" stop-color="#7D92FF"/>
</linearGradient>
<linearGradient id="paint16_linear" x1="985.428" y1="73.9326" x2="985.428" y2="1999.68" gradientUnits="userSpaceOnUse">
<stop stop-color="#999999"/>
<stop offset="1" stop-color="#7D92FF"/>
</linearGradient>
<linearGradient id="paint17_linear" x1="985.288" y1="67.3818" x2="985.288" y2="2006.07" gradientUnits="userSpaceOnUse">
<stop stop-color="#999999"/>
<stop offset="1" stop-color="#7D92FF"/>
</linearGradient>
<linearGradient id="paint18_linear" x1="985.116" y1="61.1455" x2="985.116" y2="2012.04" gradientUnits="userSpaceOnUse">
<stop stop-color="#999999"/>
<stop offset="1" stop-color="#7D92FF"/>
</linearGradient>
<linearGradient id="paint19_linear" x1="984.964" y1="55.2139" x2="984.964" y2="2017.85" gradientUnits="userSpaceOnUse">
<stop stop-color="#999999"/>
<stop offset="1" stop-color="#7D92FF"/>
</linearGradient>
<linearGradient id="paint20_linear" x1="984.807" y1="49.6152" x2="984.807" y2="2023.36" gradientUnits="userSpaceOnUse">
<stop stop-color="#999999"/>
<stop offset="1" stop-color="#7D92FF"/>
</linearGradient>
<linearGradient id="paint21_linear" x1="984.669" y1="44.2988" x2="984.669" y2="2028.49" gradientUnits="userSpaceOnUse">
<stop stop-color="#999999"/>
<stop offset="1" stop-color="#7D92FF"/>
</linearGradient>
<linearGradient id="paint22_linear" x1="984.581" y1="39.3066" x2="984.581" y2="2033.33" gradientUnits="userSpaceOnUse">
<stop stop-color="#999999"/>
<stop offset="1" stop-color="#7D92FF"/>
</linearGradient>
<linearGradient id="paint23_linear" x1="984.47" y1="34.6699" x2="984.47" y2="2037.87" gradientUnits="userSpaceOnUse">
<stop stop-color="#999999"/>
<stop offset="1" stop-color="#7D92FF"/>
</linearGradient>
<linearGradient id="paint24_linear" x1="984.413" y1="30.3184" x2="984.413" y2="2042.04" gradientUnits="userSpaceOnUse">
<stop stop-color="#999999"/>
<stop offset="1" stop-color="#7D92FF"/>
</linearGradient>
<linearGradient id="paint25_linear" x1="984.278" y1="26.333" x2="984.278" y2="2045.94" gradientUnits="userSpaceOnUse">
<stop stop-color="#999999"/>
<stop offset="1" stop-color="#7D92FF"/>
</linearGradient>
<linearGradient id="paint26_linear" x1="984.286" y1="22.5957" x2="984.286" y2="2049.54" gradientUnits="userSpaceOnUse">
<stop stop-color="#999999"/>
<stop offset="1" stop-color="#7D92FF"/>
</linearGradient>
<linearGradient id="paint27_linear" x1="984.263" y1="19.2061" x2="984.263" y2="2052.85" gradientUnits="userSpaceOnUse">
<stop stop-color="#999999"/>
<stop offset="1" stop-color="#7D92FF"/>
</linearGradient>
<linearGradient id="paint28_linear" x1="984.295" y1="16.1455" x2="984.295" y2="2055.82" gradientUnits="userSpaceOnUse">
<stop stop-color="#999999"/>
<stop offset="1" stop-color="#7D92FF"/>
</linearGradient>
<linearGradient id="paint29_linear" x1="984.293" y1="13.4053" x2="984.293" y2="2058.45" gradientUnits="userSpaceOnUse">
<stop stop-color="#999999"/>
<stop offset="1" stop-color="#7D92FF"/>
</linearGradient>
<linearGradient id="paint30_linear" x1="984.353" y1="10.9443" x2="984.353" y2="2060.88" gradientUnits="userSpaceOnUse">
<stop stop-color="#999999"/>
<stop offset="1" stop-color="#7D92FF"/>
</linearGradient>
<linearGradient id="paint31_linear" x1="984.425" y1="8.80859" x2="984.425" y2="2062.86" gradientUnits="userSpaceOnUse">
<stop stop-color="#999999"/>
<stop offset="1" stop-color="#7D92FF"/>
</linearGradient>
<linearGradient id="paint32_linear" x1="984.506" y1="6.97656" x2="984.506" y2="2064.76" gradientUnits="userSpaceOnUse">
<stop stop-color="#999999"/>
<stop offset="1" stop-color="#7D92FF"/>
</linearGradient>
<linearGradient id="paint33_linear" x1="984.625" y1="5.4209" x2="984.625" y2="2066.33" gradientUnits="userSpaceOnUse">
<stop stop-color="#999999"/>
<stop offset="1" stop-color="#7D92FF"/>
</linearGradient>
<linearGradient id="paint34_linear" x1="984.762" y1="4.10449" x2="984.762" y2="2067.67" gradientUnits="userSpaceOnUse">
<stop stop-color="#999999"/>
<stop offset="1" stop-color="#7D92FF"/>
</linearGradient>
<linearGradient id="paint35_linear" x1="984.858" y1="3.06152" x2="984.858" y2="2068.73" gradientUnits="userSpaceOnUse">
<stop stop-color="#999999"/>
<stop offset="1" stop-color="#7D92FF"/>
</linearGradient>
<linearGradient id="paint36_linear" x1="984.956" y1="2.32031" x2="984.956" y2="2069.59" gradientUnits="userSpaceOnUse">
<stop stop-color="#999999"/>
<stop offset="1" stop-color="#7D92FF"/>
</linearGradient>
<linearGradient id="paint37_linear" x1="985.041" y1="1.7002" x2="985.041" y2="2070.3" gradientUnits="userSpaceOnUse">
<stop stop-color="#999999"/>
<stop offset="1" stop-color="#7D92FF"/>
</linearGradient>
<linearGradient id="paint38_linear" x1="985.161" y1="1.30957" x2="985.161" y2="2070.82" gradientUnits="userSpaceOnUse">
<stop stop-color="#999999"/>
<stop offset="1" stop-color="#7D92FF"/>
</linearGradient>
<linearGradient id="paint39_linear" x1="985.213" y1="1.08789" x2="985.213" y2="2071.2" gradientUnits="userSpaceOnUse">
<stop stop-color="#999999"/>
<stop offset="1" stop-color="#7D92FF"/>
</linearGradient>
<linearGradient id="paint40_linear" x1="985.322" y1="1" x2="985.322" y2="2071.49" gradientUnits="userSpaceOnUse">
<stop stop-color="#999999"/>
<stop offset="1" stop-color="#7D92FF"/>
</linearGradient>
<linearGradient id="paint41_linear" x1="985.357" y1="1" x2="985.357" y2="2071.72" gradientUnits="userSpaceOnUse">
<stop stop-color="#999999"/>
<stop offset="1" stop-color="#7D92FF"/>
</linearGradient>
<linearGradient id="paint42_linear" x1="985.395" y1="1.07812" x2="985.395" y2="2071.73" gradientUnits="userSpaceOnUse">
<stop stop-color="#999999"/>
<stop offset="1" stop-color="#7D92FF"/>
</linearGradient>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 25 KiB

View file

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

170
src/imgs/weechat.svg Normal file
View file

@ -0,0 +1,170 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
inkscape:export-ydpi="797.66998"
inkscape:export-xdpi="797.66998"
inkscape:export-filename="/tmp/weechat512.png"
inkscape:version="1.0 (4035a4fb49, 2020-05-01)"
sodipodi:docname="weechat2.svg"
width="64"
height="64"
version="1.1"
id="svg8">
<sodipodi:namedview
inkscape:current-layer="svg8"
inkscape:window-maximized="1"
inkscape:window-y="42"
inkscape:window-x="148"
inkscape:cy="32"
inkscape:cx="11.643564"
inkscape:zoom="12.625"
showgrid="false"
id="namedview1443"
inkscape:window-height="968"
inkscape:window-width="1638"
inkscape:pageshadow="2"
inkscape:pageopacity="0"
guidetolerance="10"
gridtolerance="10"
objecttolerance="10"
borderopacity="1"
bordercolor="#666666"
pagecolor="#ffffff" />
<defs
id="defs2">
<linearGradient
id="linearGradient891">
<stop
style="stop-color:#0e16be;stop-opacity:1;"
offset="0"
id="stop887" />
<stop
style="stop-color:#63a4e1;stop-opacity:1"
offset="1"
id="stop889" />
</linearGradient>
<linearGradient
id="linearGradient883">
<stop
style="stop-color:#008726;stop-opacity:1;"
offset="0"
id="stop879" />
<stop
style="stop-color:#7ecc6f;stop-opacity:1"
offset="1"
id="stop881" />
</linearGradient>
<linearGradient
xlink:href="#linearGradient883"
id="linearGradient885"
x1="115.09375"
y1="42.862499"
x2="26.987501"
y2="42.862499"
gradientUnits="userSpaceOnUse" />
<linearGradient
xlink:href="#linearGradient891"
id="linearGradient893"
x1="60.854168"
y1="97.102089"
x2="60.854168"
y2="62.706253"
gradientUnits="userSpaceOnUse" />
<filter
style="color-interpolation-filters:sRGB"
id="filter5519">
<feFlood
flood-opacity="0.60422568746132421"
flood-color="rgb(0,0,0)"
result="flood"
id="feFlood5509" />
<feComposite
in="flood"
in2="SourceGraphic"
operator="in"
result="composite1"
id="feComposite5511" />
<feGaussianBlur
in="composite1"
stdDeviation="0.5"
result="blur"
id="feGaussianBlur5513" />
<feOffset
dx="1.9"
dy="1.4"
result="offset"
id="feOffset5515" />
<feComposite
in="SourceGraphic"
in2="offset"
operator="over"
result="fbSourceGraphic"
id="feComposite5517" />
</filter>
<filter
style="color-interpolation-filters:sRGB"
id="filter5531">
<feFlood
flood-opacity="0.60101983098700495"
flood-color="rgb(0,0,0)"
result="flood"
id="feFlood5521" />
<feComposite
in="flood"
in2="SourceGraphic"
operator="in"
result="composite1"
id="feComposite5523" />
<feGaussianBlur
in="composite1"
stdDeviation="0.5"
result="blur"
id="feGaussianBlur5525" />
<feOffset
dx="1.9"
dy="1.4"
result="offset"
id="feOffset5527" />
<feComposite
in="SourceGraphic"
in2="offset"
operator="over"
result="fbSourceGraphic"
id="feComposite5529" />
</filter>
</defs>
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="layer2"
style="display:inline"
transform="translate(-59.26667,-59.26667)">
<path
style="fill:url(#linearGradient885);fill-opacity:1;stroke:none;stroke-width:0.26458335px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter5519)"
d="m 121.70834,29.368751 -68.262505,1.5875 c -6.711747,0.156087 -13.464507,2.719336 -18.785501,7.005035 -5.124508,4.228038 -8.190215,10.463836 -9.7895,16.807465 l 24.341667,-1.058333 c 0.214884,-2.67862 1.733902,-5.109484 3.689147,-6.885223 1.76299,-1.5286 4.013062,-2.554657 6.365024,-2.639795 l 58.472918,-2.116649 z"
id="path195"
transform="matrix(0.47244092,0,0,0.47244092,59.26667,59.26667)" />
<path
style="fill:url(#linearGradient893);fill-opacity:1;stroke:none;stroke-width:0.26458335px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter5531)"
d="m 22.489584,61.647918 -10.31875,27.252084 c -1.362514,3.598435 -1.128016,8.11836 1.70141,10.913234 3.337143,3.296424 8.403518,3.779984 12.85067,3.374224 l 72.495838,-6.614541 16.139588,-47.625001 -20.637504,0.79375 -12.435417,35.189584 -11.112501,0.79375 12.435417,-35.454167 -22.225,1.058333 -13.229167,36.512501 -7.408314,0.264613 c -2.145162,0.07662 -3.30664,-2.908063 -2.645853,-4.76253 l 8.202083,-23.01875 z"
id="path32"
transform="matrix(0.47244092,0,0,0.47244092,59.26667,59.26667)" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 5.5 KiB

View file

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
@import "color-scheme";
@import 'color-scheme';
// CSS reset
@ -39,7 +39,7 @@ body,
color: $font;
overflow: scroll;
overflow: auto;
}
h1 {
@ -49,6 +49,11 @@ h1 {
text-align: center;
}
h4 {
text-align: left;
width: 100%;
}
a {
color: $link;
text-decoration: none;

View file

@ -18,6 +18,7 @@ import React from 'react';
import Tile from '../components/Tile';
import LinkPreview from '../components/LinkPreview';
import InvitingClientTile from '../components/InvitingClientTile';
import { parseHash } from '../parser/parser';
import { LinkKind } from '../parser/types';
@ -28,9 +29,9 @@ interface IProps {
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;
let client: JSX.Element = <></>;
switch (parsedLink.kind) {
case LinkKind.ParseFailed:
feedback = (
@ -41,7 +42,21 @@ const LinkRouter: React.FC<IProps> = ({ link }: IProps) => {
);
break;
default:
feedback = <LinkPreview link={parsedLink} />;
if (parsedLink.arguments.client) {
client = (
<InvitingClientTile
clientName={parsedLink.arguments.client}
/>
);
}
feedback = (
<>
<LinkPreview link={parsedLink} />
<hr />
{client}
</>
);
}
return feedback;

59
src/utils/localStorage.ts Normal file
View file

@ -0,0 +1,59 @@
/*
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 {
Schema,
} from 'zod';
import React from 'react';
/*
* Initialises local storage to initial value if
* a value matching the schema is not in storage.
*/
export function persistReducer<T, A>(
stateKey: string,
initialState: T,
schema: Schema<T>,
reducer: React.Reducer<T, A>,
): [T, React.Reducer<T, A>] {
let currentState = initialState;
// Try to load state from local storage
const stateInStorage = localStorage.getItem(stateKey);
if (stateInStorage) {
try {
// Validate state type
const parsedState = JSON.parse(stateInStorage);
if (parsedState as T) {
currentState = schema.parse(parsedState);
}
} catch (e) {
// if invalid delete state
localStorage.setItem(stateKey, JSON.stringify(initialState));
}
} else {
localStorage.setItem(stateKey, JSON.stringify(initialState));
}
return [
currentState,
(state: T, action: A) => {
// state passed to this reducer is the source of truth
const newState = reducer(state, action);
localStorage.setItem(stateKey, JSON.stringify(newState));
return newState;
},
];
}

163
yarn.lock
View file

@ -1133,7 +1133,7 @@
dependencies:
regenerator-runtime "^0.13.4"
"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.10.2", "@babel/runtime@^7.10.3", "@babel/runtime@^7.10.5", "@babel/runtime@^7.3.1", "@babel/runtime@^7.3.4", "@babel/runtime@^7.4.4", "@babel/runtime@^7.4.5", "@babel/runtime@^7.5.0", "@babel/runtime@^7.5.1", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.3", "@babel/runtime@^7.7.2", "@babel/runtime@^7.7.6", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2":
"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.10.2", "@babel/runtime@^7.10.3", "@babel/runtime@^7.3.1", "@babel/runtime@^7.3.4", "@babel/runtime@^7.4.4", "@babel/runtime@^7.4.5", "@babel/runtime@^7.5.0", "@babel/runtime@^7.5.1", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.3", "@babel/runtime@^7.7.2", "@babel/runtime@^7.7.6", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2":
version "7.11.2"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.11.2.tgz#f549c13c754cc40b87644b9fa9f09a6a95fe0736"
integrity sha512-TeWkU52so0mPtDcaCTxNBI/IHiz0pZgr8VEFqXFtZWpYD08ZB6FaSwVAS8MKRQAP3bYKiVjwysOJgMFY28o6Tw==
@ -1512,6 +1512,13 @@
resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz#2b5a3ab3f918cca48a8c754c08168e3f03eba61b"
integrity sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw==
"@quentin-sommer/react-useragent@^3.1.0":
version "3.1.0"
resolved "https://registry.yarnpkg.com/@quentin-sommer/react-useragent/-/react-useragent-3.1.0.tgz#8aa823fed7da5034edbf5bb1dc3cefd3d19473ea"
integrity sha512-twLVX4A7GpHCEcr5M3c97QR88t+uSZUjvNSTZMqoY5vjPXhpAcw0ZlWpMF6Nlg7Ofkwo3pZa3paQ9Nt7VJYHOA==
dependencies:
ua-parser-js "^0.7.20"
"@reach/router@^1.2.1":
version "1.3.4"
resolved "https://registry.yarnpkg.com/@reach/router/-/router-1.3.4.tgz#d2574b19370a70c80480ed91f3da840136d10f8c"
@ -2345,23 +2352,6 @@
dependencies:
"@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":
version "11.0.4"
resolved "https://registry.yarnpkg.com/@types/react-syntax-highlighter/-/react-syntax-highlighter-11.0.4.tgz#d86d17697db62f98046874f62fdb3e53a0bbc4cd"
@ -6614,11 +6604,6 @@ flush-write-stream@^1.0.0:
inherits "^2.0.3"
readable-stream "^2.3.6"
fn-name@~3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/fn-name/-/fn-name-3.0.0.tgz#0596707f635929634d791f452309ab41558e3c5c"
integrity sha512-eNMNr5exLoavuAMhIUVsOKF79SWd/zG104ef6sxBTSw+cZc6BXdQXDvYcGvp0VbxVVSp1XDUNoz7mg1xMtSznA==
focus-lock@^0.7.0:
version "0.7.0"
resolved "https://registry.yarnpkg.com/focus-lock/-/focus-lock-0.7.0.tgz#b2bfb0ca7beacc8710a1ff74275fe0dc60a1d88a"
@ -7209,18 +7194,6 @@ highlight.js@~9.13.0:
resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-9.13.1.tgz#054586d53a6863311168488a0f58d6c505ce641e"
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:
version "1.0.1"
resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1"
@ -7230,7 +7203,7 @@ hmac-drbg@^1.0.0:
minimalistic-assert "^1.0.0"
minimalistic-crypto-utils "^1.0.1"
hoist-non-react-statics@^3.1.0, hoist-non-react-statics@^3.3.0:
hoist-non-react-statics@^3.3.0:
version "3.3.2"
resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45"
integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==
@ -8078,11 +8051,6 @@ is-wsl@^2.1.1:
dependencies:
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:
version "1.0.0"
resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
@ -9010,7 +8978,7 @@ locate-path@^5.0.0:
dependencies:
p-locate "^4.1.0"
lodash-es@^4.17.11, lodash-es@^4.17.14:
lodash-es@^4.17.14:
version "4.17.15"
resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.15.tgz#21bd96839354412f23d7a10340e5eac6ee455d78"
integrity sha512-rlrc3yU3+JNOpZ9zj5pQtxnx2THmvRykwL4Xlxoa8I9lHBlVbbyPhgyPMioxVZ4NqyxaVVtaJnzsyOidQIhyyQ==
@ -9102,7 +9070,7 @@ loglevelnext@^1.0.1:
es6-symbol "^3.1.1"
object.assign "^4.1.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:
loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf"
integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==
@ -9231,10 +9199,10 @@ material-colors@^1.2.1:
resolved "https://registry.yarnpkg.com/material-colors/-/material-colors-1.2.6.tgz#6d1958871126992ceecc72f4bcc4d8f010865f46"
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==
matrix-cypher@^0.1.12:
version "0.1.13"
resolved "https://registry.yarnpkg.com/matrix-cypher/-/matrix-cypher-0.1.13.tgz#a8aadaaf7c15d0b85cca3c8d31f7ee007cefa65a"
integrity sha512-n0PiKVD4On3Vwvm8iXlYZhpTh5edwWVnd1U4nEjNEbjX9MyclxeSsBja4R1w+8NV2WIxV35iypC2y6u+ElX2zg==
dependencies:
cross-fetch "^3.0.5"
promise.any "^2.0.1"
@ -9435,14 +9403,6 @@ min-indent@^1.0.0:
resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.1.tgz#a63f681673b30571fbe8bc25686ae746eefa9869"
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:
version "0.9.0"
resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-0.9.0.tgz#47f2cf07aa165ab35733b1fc97d4c46c0564339e"
@ -10373,13 +10333,6 @@ path-to-regexp@0.1.7:
resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c"
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:
version "1.1.0"
resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441"
@ -11386,11 +11339,6 @@ prop-types@^15.5.10, prop-types@^15.5.8, prop-types@^15.6.0, prop-types@^15.6.1,
object-assign "^4.1.1"
react-is "^16.8.1"
property-expr@^2.0.2:
version "2.0.2"
resolved "https://registry.yarnpkg.com/property-expr/-/property-expr-2.0.2.tgz#fff2a43919135553a3bc2fdd94bdb841965b2330"
integrity sha512-bc/5ggaYZxNkFKj374aLbEDqVADdYaLcFo8XBkishUWbaAdjlphaBFns9TvRA2pUseVL/wMFmui9X3IdNDU37g==
property-information@^5.0.0:
version "5.5.0"
resolved "https://registry.yarnpkg.com/property-information/-/property-information-5.5.0.tgz#4dc075d493061a82e2b7d096f406e076ed859943"
@ -11777,7 +11725,7 @@ react-inspector@^4.0.0:
is-dom "^1.0.9"
prop-types "^15.6.1"
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:
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:
version "16.13.1"
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==
@ -11831,35 +11779,6 @@ react-redux@^7.0.2:
prop-types "^15.7.2"
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:
version "3.4.1"
resolved "https://registry.yarnpkg.com/react-scripts/-/react-scripts-3.4.1.tgz#f551298b5c71985cc491b9acf3c8e8c0ae3ada0a"
@ -12353,11 +12272,6 @@ resolve-from@^5.0.0:
resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69"
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:
version "3.1.1"
resolved "https://registry.yarnpkg.com/resolve-url-loader/-/resolve-url-loader-3.1.1.tgz#28931895fa1eab9be0647d3b2958c100ae3c0bf0"
@ -13516,11 +13430,6 @@ symbol.prototype.description@^1.0.0:
es-abstract "^1.17.0-next.1"
has-symbols "^1.0.1"
synchronous-promise@^2.0.13:
version "2.0.13"
resolved "https://registry.yarnpkg.com/synchronous-promise/-/synchronous-promise-2.0.13.tgz#9d8c165ddee69c5a6542862b405bc50095926702"
integrity sha512-R9N6uDkVsghHePKh1TEqbnLddO2IY25OcsksyFp/qBe7XYd0PVbKEWxhcdMhpLzE1I6skj5l4aEZ3CRxcbArlA==
table@^5.2.3:
version "5.4.6"
resolved "https://registry.yarnpkg.com/table/-/table-5.4.6.tgz#1292d19500ce3f86053b05f0e8e7e4a3bb21079e"
@ -13678,12 +13587,7 @@ tiny-emitter@^2.0.0:
resolved "https://registry.yarnpkg.com/tiny-emitter/-/tiny-emitter-2.1.0.tgz#1d1a56edfc51c43e863cbb5382a72330e3555423"
integrity sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==
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:
tiny-warning@^1.0.2:
version "1.0.3"
resolved "https://registry.yarnpkg.com/tiny-warning/-/tiny-warning-1.0.3.tgz#94a30db453df4c643d0fd566060d60a875d84754"
integrity sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==
@ -13757,11 +13661,6 @@ toidentifier@1.0.0:
resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553"
integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==
toposort@^2.0.2:
version "2.0.2"
resolved "https://registry.yarnpkg.com/toposort/-/toposort-2.0.2.tgz#ae21768175d1559d48bef35420b2f4962f09c330"
integrity sha1-riF2gXXRVZ1IvvNUILL0li8JwzA=
tough-cookie@^2.3.3, tough-cookie@^2.3.4, tough-cookie@^2.5.0, tough-cookie@~2.5.0:
version "2.5.0"
resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2"
@ -13919,6 +13818,11 @@ typescript@~3.7.2:
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.7.5.tgz#0692e21f65fd4108b9330238aac11dd2e177a1ae"
integrity sha512-/P5lkRXkWHNAbcJIiHPfRoKqyd7bsyCma1hZNUGfn20qm64T6ZBlrzprymeu918H+mB/0rIg2gGK/BXkhhYgBw==
ua-parser-js@^0.7.20:
version "0.7.21"
resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.21.tgz#853cf9ce93f642f67174273cc34565ae6f308777"
integrity sha512-+O8/qh/Qj8CgC6eYBVBykMrNtp5Gebn4dlGD/kKXVkJNDwyrAwSIqwz8CDf+tsAIWVycKcku6gIXJ0qwx/ZXaQ==
unfetch@^4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/unfetch/-/unfetch-4.1.0.tgz#6ec2dd0de887e58a4dee83a050ded80ffc4137db"
@ -14129,11 +14033,6 @@ validate-npm-package-license@^3.0.1:
spdx-correct "^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:
version "1.1.2"
resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"
@ -14799,20 +14698,12 @@ yargs@^13.3.0, yargs@^13.3.2:
y18n "^4.0.0"
yargs-parser "^13.1.2"
yup@^0.29.1:
version "0.29.3"
resolved "https://registry.yarnpkg.com/yup/-/yup-0.29.3.tgz#69a30fd3f1c19f5d9e31b1cf1c2b851ce8045fea"
integrity sha512-RNUGiZ/sQ37CkhzKFoedkeMfJM0vNQyaz+wRZJzxdKE7VfDeVKH8bb4rr7XhRLbHJz5hSjoDNwMEIaKhuMZ8gQ==
dependencies:
"@babel/runtime" "^7.10.5"
fn-name "~3.0.0"
lodash "^4.17.15"
lodash-es "^4.17.11"
property-expr "^2.0.2"
synchronous-promise "^2.0.13"
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==
zod@^1.10.3:
version "1.10.3"
resolved "https://registry.yarnpkg.com/zod/-/zod-1.10.3.tgz#a69e60a96115d8968020e42aa0d7d1903e3e50c7"
integrity sha512-TxvLXUx7red0MKzx85sOwcoAWSsO+ChnYIsPzV/rWouS57yagZZlPp2bBTaXOu685lZE8H9vQK2nJs1vxleQTA==