Files
NanoKVM-MIRROR/web/src/pages/desktop/menu/settings/tailscale/install.tsx
wj-xiao 6eb4a4ea62 update version to 2.1.6
feat: support downloading image from online URL
feat: add keyboard shortcut Ctrl+Alt+Del
fix: fix the CSRF issue
perf: add an option to configure custom ICE servers
perf: removed unnecessary modifications to DNS configuration
perf: add an SSH enable/disable toggle in the web UI
perf: add a Tailscale enable/disable toggle in the web UI
perf: download Tailscale installation package from the official source
perf: automatic enable/disable GOMEMLIMIT on tailscale start/stop
perf: add JWT configuration
perf: implement secure password storage using bcrypt hashing
perf: implement integrity checks for online updates
refactor: refactor HDMI module and remove the dependency libmaixcam_lib.so
refactor: web terminal use pty instead of SSH
refactor: move Tailscale APIs from the network module to the extensions module
2025-02-14 14:18:13 +08:00

84 lines
2.3 KiB
TypeScript

import { useState } from 'react';
import { DownloadOutlined, InfoCircleOutlined } from '@ant-design/icons';
import { Button, Card, Result } from 'antd';
import { useTranslation } from 'react-i18next';
import * as api from '@/api/extensions/tailscale.ts';
type InstallProps = {
setIsLocked: (setIsLocked: boolean) => void;
onSuccess: () => void;
};
export const Install = ({ setIsLocked, onSuccess }: InstallProps) => {
const { t } = useTranslation();
const [state, setState] = useState('');
function install() {
if (state === 'installing') return;
setState('installing');
setIsLocked(true);
api
.install()
.then((rsp) => {
if (rsp.code !== 0) {
setState('failed');
return;
}
onSuccess();
})
.finally(() => {
setState('');
setIsLocked(false);
});
}
return (
<>
{state !== 'failed' ? (
<Result
icon={<DownloadOutlined />}
subTitle={t('settings.tailscale.notInstall')}
extra={
<Button type="primary" size="large" loading={state === 'installing'} onClick={install}>
{state === 'installing'
? t('settings.tailscale.installing')
: t('settings.tailscale.install')}
</Button>
}
/>
) : (
<Result
status="warning"
title={t('settings.tailscale.failed')}
subTitle={t('settings.tailscale.retry')}
icon={<InfoCircleOutlined />}
extra={
<Card styles={{ body: { padding: 0 } }}>
<ul className="list-decimal text-left font-mono text-sm text-neutral-300">
<li>
{t('settings.tailscale.download')}
<a
className="px-1"
href="https://pkgs.tailscale.com/stable/tailscale_latest_riscv64.tgz"
target="_blank"
>
{t('settings.tailscale.package')}
</a>
{t('settings.tailscale.unzip')}
</li>
<li>{t('settings.tailscale.upTailscale')}</li>
<li>{t('settings.tailscale.upTailscaled')}</li>
<li>{t('settings.tailscale.refresh')}</li>
</ul>
</Card>
}
/>
)}
</>
);
};