344 lines
13 KiB
TypeScript
344 lines
13 KiB
TypeScript
import React, { useCallback, useEffect, useState } from 'react';
|
|
import { getVersion } from '@tauri-apps/api/app';
|
|
import { Box, Text, IconButton, Icon, Icons, Scroll, Button, 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 PaarrotSVG from '../../../../../public/res/svg/paarrot.svg';
|
|
import { clearCacheAndReload } from '../../../../client/initMatrix';
|
|
import { useMatrixClient } from '../../../hooks/useMatrixClient';
|
|
|
|
type AboutProps = {
|
|
requestClose: () => void;
|
|
};
|
|
export function About({ requestClose }: AboutProps) {
|
|
const mx = useMatrixClient();
|
|
const [version, setVersion] = useState<string>('');
|
|
const [protocolStatus, setProtocolStatus] = useState<string>('Checking desktop protocol integration...');
|
|
const [protocolBusy, setProtocolBusy] = useState<boolean>(false);
|
|
|
|
const formatProtocolStatus = useCallback((data: {
|
|
scheme: string;
|
|
platform: string;
|
|
isDefault: boolean;
|
|
registerCall: boolean;
|
|
error: string | null;
|
|
windows: null | {
|
|
userChoiceProgId: string | null;
|
|
userChoiceCommand: string | null;
|
|
hkcuCommand: string | null;
|
|
hklmCommand: string | null;
|
|
};
|
|
}): string => {
|
|
const state = data.isDefault ? 'registered' : 'not registered';
|
|
const startupState = data.registerCall ? 'ok' : 'no-change';
|
|
const owner =
|
|
data.platform === 'win32' && data.windows?.userChoiceProgId
|
|
? ` Current default ProgId=${data.windows.userChoiceProgId}.`
|
|
: '';
|
|
const missingHint =
|
|
data.platform === 'win32' && !data.windows?.hkcuCommand && !data.windows?.hklmCommand
|
|
? ` ${data.scheme} link type is missing from Windows registry. Use Repair to create it.`
|
|
: '';
|
|
const errorPart = data.error ? ` Error: ${data.error}` : '';
|
|
|
|
return `${data.scheme} is ${state} (startup=${startupState}) on ${data.platform}.${owner}${missingHint}${errorPart}`;
|
|
}, []);
|
|
|
|
const refreshProtocolStatus = useCallback(() => {
|
|
if (!window.electron?.protocol?.getStatus) {
|
|
setProtocolStatus('Desktop protocol diagnostics are unavailable in this environment.');
|
|
return;
|
|
}
|
|
|
|
window.electron.protocol
|
|
.getStatus()
|
|
.then((result) => {
|
|
if (!result?.success || !result.data) {
|
|
setProtocolStatus(result?.error ?? 'Unable to query protocol state.');
|
|
return;
|
|
}
|
|
|
|
setProtocolStatus(formatProtocolStatus(result.data));
|
|
})
|
|
.catch((error) => {
|
|
setProtocolStatus(`Protocol diagnostics failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
});
|
|
}, [formatProtocolStatus]);
|
|
|
|
const repairProtocolHandler = () => {
|
|
if (!window.electron?.protocol?.repair) {
|
|
setProtocolStatus('Protocol repair is unavailable in this environment.');
|
|
return;
|
|
}
|
|
|
|
setProtocolBusy(true);
|
|
window.electron.protocol
|
|
.repair()
|
|
.then((result) => {
|
|
if (!result?.success || !result.data) {
|
|
setProtocolStatus(result?.error ?? 'Protocol repair failed.');
|
|
return;
|
|
}
|
|
|
|
setProtocolStatus(formatProtocolStatus(result.data));
|
|
setProtocolBusy(false);
|
|
})
|
|
.catch((error) => {
|
|
setProtocolStatus(`Protocol repair failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
setProtocolBusy(false);
|
|
});
|
|
};
|
|
|
|
useEffect(() => {
|
|
getVersion().then(setVersion).catch(() => setVersion('unknown'));
|
|
refreshProtocolStatus();
|
|
}, [refreshProtocolStatus]);
|
|
|
|
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">
|
|
<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={PaarrotSVG}
|
|
alt="Paarrot logo"
|
|
/>
|
|
</Box>
|
|
<Box direction="Column" gap="300">
|
|
<Box direction="Column" gap="100">
|
|
<Box gap="100" alignItems="End">
|
|
<Text size="H3">Paarrot</Text>
|
|
<Text size="T200">v{version}</Text>
|
|
</Box>
|
|
<Text>Squawk to yer mateys!</Text>
|
|
</Box>
|
|
|
|
<Box gap="200" wrap="Wrap">
|
|
<Button
|
|
as="a"
|
|
href="https://github.com/Paarrot/Paarrot-Desktop"
|
|
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>
|
|
</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>
|
|
}
|
|
/>
|
|
<SettingTile
|
|
title="Protocol Handler (paarrot://)"
|
|
description={protocolStatus}
|
|
after={
|
|
<Box gap="100">
|
|
<Button
|
|
onClick={repairProtocolHandler}
|
|
variant="Secondary"
|
|
fill="Soft"
|
|
size="300"
|
|
radii="300"
|
|
outlined
|
|
disabled={protocolBusy}
|
|
>
|
|
<Text size="B300">Repair</Text>
|
|
</Button>
|
|
<Button
|
|
onClick={refreshProtocolStatus}
|
|
variant="Secondary"
|
|
fill="Soft"
|
|
size="300"
|
|
radii="300"
|
|
outlined
|
|
disabled={protocolBusy}
|
|
>
|
|
<Text size="B300">Refresh</Text>
|
|
</Button>
|
|
</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{' '}
|
|
<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>
|
|
);
|
|
}
|