435 lines
17 KiB
TypeScript
435 lines
17 KiB
TypeScript
import React, { useEffect, useState } from 'react';
|
|
import { Box, Text, IconButton, Icon, Icons, Scroll, Button, Spinner, config, toRem } from 'folds';
|
|
import { Page, PageContent, PageHeader } from '../../../components/page';
|
|
import { SequenceCard } from '../../../components/sequence-card';
|
|
import { SequenceCardStyle } from '../styles.css';
|
|
import { SettingTile } from '../../../components/setting-tile';
|
|
import pkg from '../../../../../package.json';
|
|
import { clearCacheAndReload } from '../../../../client/initMatrix';
|
|
import { useMatrixClient } from '../../../hooks/useMatrixClient';
|
|
import { getOriginBaseUrl, withOriginBaseUrl } from '../../../pages/pathUtils';
|
|
|
|
const LotusLogo = withOriginBaseUrl(getOriginBaseUrl(), '/Lotus.png');
|
|
|
|
type MSC1929Contact = {
|
|
matrix_id?: string;
|
|
email_address?: string;
|
|
role?: string;
|
|
};
|
|
|
|
type MSC1929Support = {
|
|
contacts?: MSC1929Contact[];
|
|
support_page?: string;
|
|
};
|
|
|
|
function isMSC1929Support(data: unknown): data is MSC1929Support {
|
|
if (typeof data !== 'object' || data === null) return false;
|
|
const d = data as Record<string, unknown>;
|
|
if ('contacts' in d && !Array.isArray(d.contacts)) return false;
|
|
if ('support_page' in d && typeof d.support_page !== 'string') return false;
|
|
return true;
|
|
}
|
|
|
|
function formatRole(role?: string): string {
|
|
if (!role) return 'Contact';
|
|
if (role === 'm.role.admin') return 'Admin';
|
|
if (role === 'm.role.security') return 'Security';
|
|
return role.startsWith('m.role.') ? role.slice(7) : role;
|
|
}
|
|
|
|
function useServerSupport(): { support: MSC1929Support | null; loading: boolean } {
|
|
const mx = useMatrixClient();
|
|
const [support, setSupport] = useState<MSC1929Support | null>(null);
|
|
const [loading, setLoading] = useState(true);
|
|
|
|
useEffect(() => {
|
|
const controller = new AbortController();
|
|
// MSC1929 support info is served from the MXID server-name host (like
|
|
// /.well-known/matrix/client), which on delegated/split-domain servers is
|
|
// NOT the client-API URL. Derive it from the user's domain.
|
|
const serverName = mx.getDomain();
|
|
if (!serverName) {
|
|
setLoading(false);
|
|
return undefined;
|
|
}
|
|
setLoading(true);
|
|
fetch(`https://${serverName}/.well-known/matrix/support`, { signal: controller.signal })
|
|
.then((res) => {
|
|
if (!res.ok) return null;
|
|
return res.json();
|
|
})
|
|
.then((data) => {
|
|
if (isMSC1929Support(data) && (data.contacts?.length || data.support_page)) {
|
|
setSupport(data);
|
|
}
|
|
})
|
|
.catch((e) => {
|
|
if (e.name !== 'AbortError') {
|
|
// Graceful degradation — server may not have this configured
|
|
}
|
|
})
|
|
.finally(() => setLoading(false));
|
|
return () => controller.abort();
|
|
}, [mx]);
|
|
|
|
return { support, loading };
|
|
}
|
|
|
|
type AboutProps = {
|
|
requestClose: () => void;
|
|
};
|
|
export function About({ requestClose }: AboutProps) {
|
|
const mx = useMatrixClient();
|
|
const { support: serverSupport, loading: supportLoading } = useServerSupport();
|
|
|
|
return (
|
|
<Page>
|
|
<PageHeader outlined={false}>
|
|
<Box grow="Yes" gap="200">
|
|
<Box grow="Yes" alignItems="Center" gap="200">
|
|
<Text size="H3" truncate>
|
|
About
|
|
</Text>
|
|
</Box>
|
|
<Box shrink="No">
|
|
<IconButton onClick={requestClose} variant="Surface" aria-label="Close">
|
|
<Icon src={Icons.Cross} />
|
|
</IconButton>
|
|
</Box>
|
|
</Box>
|
|
</PageHeader>
|
|
<Box grow="Yes">
|
|
<Scroll hideTrack visibility="Hover">
|
|
<PageContent>
|
|
<Box direction="Column" gap="700">
|
|
<Box gap="400">
|
|
<Box shrink="No">
|
|
<img
|
|
style={{ width: toRem(60), height: toRem(60) }}
|
|
src={LotusLogo}
|
|
alt="Lotus Chat logo"
|
|
/>
|
|
</Box>
|
|
<Box direction="Column" gap="300">
|
|
<Box direction="Column" gap="100">
|
|
<Box gap="100" alignItems="End">
|
|
<Text size="H3">Lotus Chat</Text>
|
|
<Text size="T200">v{pkg.version}</Text>
|
|
</Box>
|
|
<Text>A Matrix client for Lotus Guild.</Text>
|
|
</Box>
|
|
|
|
<Box gap="200" wrap="Wrap">
|
|
<Button
|
|
as="a"
|
|
href="https://code.lotusguild.org/LotusGuild/cinny"
|
|
rel="noreferrer noopener"
|
|
target="_blank"
|
|
variant="Secondary"
|
|
fill="Soft"
|
|
size="300"
|
|
radii="300"
|
|
before={<Icon src={Icons.Code} size="100" filled />}
|
|
>
|
|
<Text size="B300">Source Code</Text>
|
|
</Button>
|
|
<Button
|
|
as="a"
|
|
href="https://matrix.lotusguild.org"
|
|
rel="noreferrer noopener"
|
|
target="_blank"
|
|
variant="Critical"
|
|
fill="Soft"
|
|
size="300"
|
|
radii="300"
|
|
before={<Icon src={Icons.Heart} size="100" filled />}
|
|
>
|
|
<Text size="B300">Support</Text>
|
|
</Button>
|
|
</Box>
|
|
</Box>
|
|
</Box>
|
|
<Box direction="Column" gap="100">
|
|
<Text size="L400">Options</Text>
|
|
<SequenceCard
|
|
className={SequenceCardStyle}
|
|
variant="SurfaceVariant"
|
|
direction="Column"
|
|
gap="400"
|
|
>
|
|
<SettingTile
|
|
title="Clear Cache & Reload"
|
|
description="Clear all your locally stored data and reload from server."
|
|
after={
|
|
<Button
|
|
onClick={() => clearCacheAndReload(mx)}
|
|
variant="Secondary"
|
|
fill="Soft"
|
|
size="300"
|
|
radii="300"
|
|
outlined
|
|
>
|
|
<Text size="B300">Clear Cache</Text>
|
|
</Button>
|
|
}
|
|
/>
|
|
</SequenceCard>
|
|
</Box>
|
|
{(serverSupport || supportLoading) && (
|
|
<Box direction="Column" gap="100">
|
|
<Text size="L400">Homeserver Support</Text>
|
|
<SequenceCard
|
|
className={SequenceCardStyle}
|
|
variant="SurfaceVariant"
|
|
direction="Column"
|
|
gap="400"
|
|
>
|
|
<Box direction="Column" gap="200" style={{ padding: config.space.S200 }}>
|
|
{supportLoading && !serverSupport && (
|
|
<Box alignItems="Center" gap="200">
|
|
<Spinner size="100" variant="Secondary" />
|
|
<Text size="T300" priority="300">
|
|
Loading support info…
|
|
</Text>
|
|
</Box>
|
|
)}
|
|
{serverSupport?.contacts && serverSupport.contacts.length > 0 && (
|
|
<Box direction="Column" gap="100">
|
|
{serverSupport.contacts.map((contact, i) => (
|
|
<Box key={i} direction="Column" gap="100">
|
|
<Text size="T300" priority="300">
|
|
{formatRole(contact.role)}:
|
|
</Text>
|
|
<Box
|
|
direction="Column"
|
|
gap="100"
|
|
style={{ paddingLeft: config.space.S200 }}
|
|
>
|
|
{contact.matrix_id && (
|
|
<Text
|
|
as="a"
|
|
href={`https://matrix.to/#/${encodeURIComponent(contact.matrix_id)}`}
|
|
target="_blank"
|
|
rel="noreferrer noopener"
|
|
size="T300"
|
|
>
|
|
{contact.matrix_id}
|
|
</Text>
|
|
)}
|
|
{contact.email_address && (
|
|
<Text as="a" href={`mailto:${contact.email_address}`} size="T300">
|
|
{contact.email_address}
|
|
</Text>
|
|
)}
|
|
</Box>
|
|
</Box>
|
|
))}
|
|
</Box>
|
|
)}
|
|
{serverSupport?.support_page && (
|
|
<Box alignItems="Center" gap="200">
|
|
<Text size="T300" priority="300">
|
|
Support Page:
|
|
</Text>
|
|
<Text
|
|
as="a"
|
|
href={serverSupport.support_page}
|
|
target="_blank"
|
|
rel="noreferrer noopener"
|
|
aria-label="Open support page"
|
|
size="T300"
|
|
>
|
|
{serverSupport.support_page}
|
|
</Text>
|
|
</Box>
|
|
)}
|
|
</Box>
|
|
</SequenceCard>
|
|
</Box>
|
|
)}
|
|
<Box direction="Column" gap="100">
|
|
<Text size="L400">Credits</Text>
|
|
<SequenceCard
|
|
className={SequenceCardStyle}
|
|
variant="SurfaceVariant"
|
|
direction="Column"
|
|
gap="400"
|
|
>
|
|
<Box
|
|
as="ul"
|
|
direction="Column"
|
|
gap="200"
|
|
style={{
|
|
margin: 0,
|
|
paddingLeft: config.space.S400,
|
|
}}
|
|
>
|
|
<li>
|
|
<Text size="T300">
|
|
The Lotus Chat logo is a derivative work based on the original{' '}
|
|
<a
|
|
href="https://github.com/cinnyapp/cinny"
|
|
rel="noreferrer noopener"
|
|
target="_blank"
|
|
>
|
|
Cinny
|
|
</a>{' '}
|
|
logo by{' '}
|
|
<a
|
|
href="https://github.com/ajbura"
|
|
rel="noreferrer noopener"
|
|
target="_blank"
|
|
>
|
|
Ajay Bura
|
|
</a>{' '}
|
|
and contributors, used under the terms of{' '}
|
|
<a
|
|
href="https://creativecommons.org/licenses/by/4.0/"
|
|
rel="noreferrer noopener"
|
|
target="_blank"
|
|
>
|
|
CC-BY 4.0
|
|
</a>
|
|
. The modified logo is © Lotus Guild, also under CC-BY 4.0.
|
|
</Text>
|
|
</li>
|
|
<li>
|
|
<Text size="T300">
|
|
Lotus Chat is a fork of{' '}
|
|
<a
|
|
href="https://github.com/cinnyapp/cinny"
|
|
rel="noreferrer noopener"
|
|
target="_blank"
|
|
>
|
|
Cinny
|
|
</a>{' '}
|
|
by Ajay Bura and contributors, used under the terms of{' '}
|
|
<a
|
|
href="https://www.gnu.org/licenses/agpl-3.0.html"
|
|
rel="noreferrer noopener"
|
|
target="_blank"
|
|
>
|
|
AGPL-3.0
|
|
</a>
|
|
.
|
|
</Text>
|
|
</li>
|
|
<li>
|
|
<Text size="T300">
|
|
The{' '}
|
|
<a
|
|
href="https://github.com/matrix-org/matrix-js-sdk"
|
|
rel="noreferrer noopener"
|
|
target="_blank"
|
|
>
|
|
matrix-js-sdk
|
|
</a>{' '}
|
|
is ©{' '}
|
|
<a
|
|
href="https://matrix.org/foundation"
|
|
rel="noreferrer noopener"
|
|
target="_blank"
|
|
>
|
|
The Matrix.org Foundation C.I.C
|
|
</a>{' '}
|
|
used under the terms of{' '}
|
|
<a
|
|
href="http://www.apache.org/licenses/LICENSE-2.0"
|
|
rel="noreferrer noopener"
|
|
target="_blank"
|
|
>
|
|
Apache 2.0
|
|
</a>
|
|
.
|
|
</Text>
|
|
</li>
|
|
<li>
|
|
<Text size="T300">
|
|
The{' '}
|
|
<a
|
|
href="https://github.com/mozilla/twemoji-colr"
|
|
target="_blank"
|
|
rel="noreferrer noopener"
|
|
>
|
|
twemoji-colr
|
|
</a>{' '}
|
|
font is ©{' '}
|
|
<a href="https://mozilla.org/" target="_blank" rel="noreferrer noopener">
|
|
Mozilla Foundation
|
|
</a>{' '}
|
|
used under the terms of{' '}
|
|
<a
|
|
href="http://www.apache.org/licenses/LICENSE-2.0"
|
|
target="_blank"
|
|
rel="noreferrer noopener"
|
|
>
|
|
Apache 2.0
|
|
</a>
|
|
.
|
|
</Text>
|
|
</li>
|
|
<li>
|
|
<Text size="T300">
|
|
The{' '}
|
|
<a
|
|
href="https://twemoji.twitter.com"
|
|
target="_blank"
|
|
rel="noreferrer noopener"
|
|
>
|
|
Twemoji
|
|
</a>{' '}
|
|
emoji art is ©{' '}
|
|
<a
|
|
href="https://twemoji.twitter.com"
|
|
target="_blank"
|
|
rel="noreferrer noopener"
|
|
>
|
|
Twitter, Inc and other contributors
|
|
</a>{' '}
|
|
used under the terms of{' '}
|
|
<a
|
|
href="https://creativecommons.org/licenses/by/4.0/"
|
|
target="_blank"
|
|
rel="noreferrer noopener"
|
|
>
|
|
CC-BY 4.0
|
|
</a>
|
|
.
|
|
</Text>
|
|
</li>
|
|
<li>
|
|
<Text size="T300">
|
|
The{' '}
|
|
<a
|
|
href="https://material.io/design/sound/sound-resources.html"
|
|
target="_blank"
|
|
rel="noreferrer noopener"
|
|
>
|
|
Material sound resources
|
|
</a>{' '}
|
|
are ©{' '}
|
|
<a href="https://google.com" target="_blank" rel="noreferrer noopener">
|
|
Google
|
|
</a>{' '}
|
|
used under the terms of{' '}
|
|
<a
|
|
href="https://creativecommons.org/licenses/by/4.0/"
|
|
target="_blank"
|
|
rel="noreferrer noopener"
|
|
>
|
|
CC-BY 4.0
|
|
</a>
|
|
.
|
|
</Text>
|
|
</li>
|
|
</Box>
|
|
</SequenceCard>
|
|
</Box>
|
|
</Box>
|
|
</PageContent>
|
|
</Scroll>
|
|
</Box>
|
|
</Page>
|
|
);
|
|
}
|