feat: Add protocol status handling and repair functionality in About component
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
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';
|
||||
@@ -7,7 +8,6 @@ import { SettingTile } from '../../../components/setting-tile';
|
||||
import PaarrotSVG from '../../../../../public/res/svg/paarrot.svg';
|
||||
import { clearCacheAndReload } from '../../../../client/initMatrix';
|
||||
import { useMatrixClient } from '../../../hooks/useMatrixClient';
|
||||
import { getVersion } from '@tauri-apps/api/app';
|
||||
|
||||
type AboutProps = {
|
||||
requestClose: () => void;
|
||||
@@ -15,10 +15,100 @@ type AboutProps = {
|
||||
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: {
|
||||
platform: string;
|
||||
primaryScheme: string;
|
||||
schemes: Record<string, {
|
||||
isDefault: boolean;
|
||||
registerCall: boolean;
|
||||
error: string | null;
|
||||
}>;
|
||||
windows: null | Record<string, {
|
||||
userChoiceProgId: string | null;
|
||||
userChoiceCommand: string | null;
|
||||
hkcuCommand: string | null;
|
||||
hklmCommand: string | null;
|
||||
}>;
|
||||
}): string => {
|
||||
const { element } = data.schemes;
|
||||
const primary = data.schemes[data.primaryScheme];
|
||||
const primaryState = primary?.isDefault ? 'registered' : 'not registered';
|
||||
const elementState = element?.isDefault ? 'registered' : 'not registered';
|
||||
const primaryCall = primary?.registerCall ? 'ok' : 'no-change';
|
||||
const elementCall = element?.registerCall ? 'ok' : 'no-change';
|
||||
|
||||
const primaryError = primary?.error ? ` ${data.primaryScheme} error: ${primary.error}` : '';
|
||||
const elementError = element?.error ? ` element error: ${element.error}` : '';
|
||||
|
||||
const primaryWindows = data.windows?.[data.primaryScheme];
|
||||
const primaryOwner =
|
||||
data.platform === 'win32' && primaryWindows?.userChoiceProgId
|
||||
? ` Current ${data.primaryScheme} default ProgId=${primaryWindows.userChoiceProgId}.`
|
||||
: '';
|
||||
const primaryMissingHint =
|
||||
data.platform === 'win32' && !primaryWindows?.hkcuCommand && !primaryWindows?.hklmCommand
|
||||
? ` ${data.primaryScheme} link type is missing from Windows registry. Use Repair to create it.`
|
||||
: '';
|
||||
|
||||
return `Primary ${data.primaryScheme} is ${primaryState} (startup=${primaryCall}) on ${data.platform}. Legacy element is ${elementState} (startup=${elementCall}).${primaryOwner}${primaryMissingHint}${primaryError}${elementError}`;
|
||||
}, []);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
const settingsHint =
|
||||
result.data.platform === 'win32' && result.data.openedSettings
|
||||
? ' Windows Default Apps was opened; set PAARROT to Paarrot and press Refresh.'
|
||||
: '';
|
||||
setProtocolStatus(`${formatProtocolStatus(result.data)}${settingsHint}`);
|
||||
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>
|
||||
@@ -98,6 +188,36 @@ export function About({ requestClose }: AboutProps) {
|
||||
</Button>
|
||||
}
|
||||
/>
|
||||
<SettingTile
|
||||
title="Protocol Handlers (paarrot:// + element://)"
|
||||
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">
|
||||
|
||||
Reference in New Issue
Block a user