Add client options and styling for client tiles
This commit is contained in:
parent
6e7a119831
commit
74d223e475
6 changed files with 346 additions and 0 deletions
22
src/components/ClientList.scss
Normal file
22
src/components/ClientList.scss
Normal 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;
|
||||
}
|
91
src/components/ClientList.tsx
Normal file
91
src/components/ClientList.tsx
Normal file
|
@ -0,0 +1,91 @@
|
|||
/*
|
||||
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;
|
||||
}
|
||||
|
||||
const ClientList: React.FC<IProps> = ({ link }: IProps) => {
|
||||
const [
|
||||
{ rememberSelection, 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;
|
30
src/components/ClientSelection.scss
Normal file
30
src/components/ClientSelection.scss
Normal file
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
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 {
|
||||
margin: 0 5%;
|
||||
|
||||
.advancedOptions {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.clientList {
|
||||
margin-top: 20px;
|
||||
}
|
||||
}
|
79
src/components/ClientSelection.tsx
Normal file
79
src/components/ClientSelection.tsx
Normal 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 React, { useContext } from 'react';
|
||||
|
||||
import './ClientSelection.scss';
|
||||
import { ActionType, ClientContext } from '../contexts/ClientContext';
|
||||
import ClientList from './ClientList';
|
||||
import { SafeLink } from '../parser/types';
|
||||
|
||||
interface IProps {
|
||||
link: SafeLink;
|
||||
}
|
||||
|
||||
const ClientSelection: React.FC<IProps> = ({ link }: IProps) => {
|
||||
const [clientState, clientStateDispatch] = useContext(ClientContext);
|
||||
const options = (
|
||||
<div className="advancedOptions">
|
||||
<label>
|
||||
<input
|
||||
type="checkbox"
|
||||
onChange={(): void => {
|
||||
clientStateDispatch({
|
||||
action: ActionType.ToggleRememberSelection,
|
||||
});
|
||||
}}
|
||||
checked={clientState.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>
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="advanced">
|
||||
{options}
|
||||
<ClientList link={link} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default ClientSelection;
|
66
src/components/ClientTile.scss
Normal file
66
src/components/ClientTile.scss
Normal file
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
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;
|
||||
|
||||
height: 155px;
|
||||
width: 100%;
|
||||
|
||||
color: $foreground;
|
||||
|
||||
> img {
|
||||
flex-shrink: 0;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
h1 {
|
||||
text-align: left;
|
||||
font-size: 14px;
|
||||
line-height: 24px;
|
||||
}
|
||||
|
||||
p {
|
||||
margin-right: 20px;
|
||||
margin-top: 20px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
border: 1px solid $borders;
|
||||
border-radius: 8px;
|
||||
|
||||
padding: 8px;
|
||||
|
||||
// For the chevron
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.clientTileLink {
|
||||
position: relative;
|
||||
|
||||
width: 100%;
|
||||
|
||||
&::after {
|
||||
// TODO: add chevron top right
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
top: 5px;
|
||||
content: '>';
|
||||
}
|
||||
}
|
58
src/components/ClientTile.tsx
Normal file
58
src/components/ClientTile.tsx
Normal 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 classNames from 'classnames';
|
||||
|
||||
import { Client, ClientKind } from '../clients/types';
|
||||
import { SafeLink } from '../parser/types';
|
||||
import Tile from './Tile';
|
||||
|
||||
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,
|
||||
});
|
||||
let clientTile = (
|
||||
<Tile className={className}>
|
||||
<img src={client.logo} alt={client.name + ' logo'} />
|
||||
<div>
|
||||
<h1>{client.name}</h1>
|
||||
<p>{client.description}</p>
|
||||
{inviteLine}
|
||||
</div>
|
||||
</Tile>
|
||||
);
|
||||
|
||||
if (client.kind === ClientKind.LINKED_CLIENT) {
|
||||
clientTile = <a href={client.toUrl(link).toString()}>{clientTile}</a>;
|
||||
}
|
||||
|
||||
return clientTile;
|
||||
};
|
||||
|
||||
export default ClientTile;
|
Loading…
Reference in a new issue