mirror of
https://github.com/lone-cloud/gerbil
synced 2026-06-04 04:04:44 -07:00
246 lines
6.4 KiB
TypeScript
246 lines
6.4 KiB
TypeScript
import {
|
|
Card,
|
|
Stack,
|
|
Group,
|
|
Text,
|
|
Badge,
|
|
Button,
|
|
Loader,
|
|
Progress,
|
|
rem,
|
|
} from '@mantine/core';
|
|
import { Download, Trash2 } from 'lucide-react';
|
|
import { MouseEvent } from 'react';
|
|
import { pretifyBinName, isWindowsROCmBuild } from '@/utils/assets';
|
|
import { usePreferencesStore } from '@/stores/preferences';
|
|
import type { VersionInfo } from '@/types';
|
|
|
|
interface DownloadCardProps {
|
|
version: VersionInfo;
|
|
size: string;
|
|
description?: string;
|
|
isLoading?: boolean;
|
|
downloadProgress?: number;
|
|
disabled?: boolean;
|
|
onDownload: (e: MouseEvent<HTMLButtonElement>) => void;
|
|
onMakeCurrent?: () => void;
|
|
onUpdate?: (e: MouseEvent<HTMLButtonElement>) => void;
|
|
onRedownload?: (e: MouseEvent<HTMLButtonElement>) => void;
|
|
onDelete?: (e: MouseEvent<HTMLButtonElement>) => void;
|
|
}
|
|
|
|
export const DownloadCard = ({
|
|
version: versionInfo,
|
|
size,
|
|
description,
|
|
isLoading = false,
|
|
downloadProgress = 0,
|
|
disabled = false,
|
|
onDownload,
|
|
onMakeCurrent,
|
|
onUpdate,
|
|
onRedownload,
|
|
onDelete,
|
|
}: DownloadCardProps) => {
|
|
const { resolvedColorScheme: colorScheme } = usePreferencesStore();
|
|
const hasVersionMismatch = Boolean(
|
|
versionInfo.version &&
|
|
versionInfo.actualVersion &&
|
|
versionInfo.version !== versionInfo.actualVersion
|
|
);
|
|
|
|
// eslint-disable-next-line sonarjs/cognitive-complexity
|
|
const renderActionButtons = () => {
|
|
const buttons = [];
|
|
|
|
if (!versionInfo.isInstalled) {
|
|
return (
|
|
<Button
|
|
key="download"
|
|
variant="filled"
|
|
size="xs"
|
|
onClick={onDownload}
|
|
loading={isLoading}
|
|
disabled={disabled}
|
|
leftSection={
|
|
isLoading ? (
|
|
<Loader size="1rem" />
|
|
) : (
|
|
<Download style={{ width: rem(14), height: rem(14) }} />
|
|
)
|
|
}
|
|
>
|
|
{isLoading ? 'Downloading...' : 'Download'}
|
|
</Button>
|
|
);
|
|
}
|
|
|
|
if (!versionInfo.isCurrent && onMakeCurrent) {
|
|
buttons.push(
|
|
<Button
|
|
key="makeCurrent"
|
|
variant="filled"
|
|
size="xs"
|
|
onClick={onMakeCurrent}
|
|
disabled={disabled}
|
|
>
|
|
Make Current
|
|
</Button>
|
|
);
|
|
}
|
|
|
|
if (versionInfo.hasUpdate && onUpdate) {
|
|
buttons.push(
|
|
<Button
|
|
key="update"
|
|
variant="filled"
|
|
size="xs"
|
|
onClick={onUpdate}
|
|
loading={isLoading}
|
|
disabled={disabled}
|
|
color="orange"
|
|
leftSection={
|
|
isLoading ? (
|
|
<Loader size="1rem" />
|
|
) : (
|
|
<Download style={{ width: rem(14), height: rem(14) }} />
|
|
)
|
|
}
|
|
>
|
|
{isLoading ? 'Updating...' : `Update to ${versionInfo.newerVersion}`}
|
|
</Button>
|
|
);
|
|
}
|
|
|
|
if (hasVersionMismatch && onRedownload) {
|
|
buttons.push(
|
|
<Button
|
|
key="redownload"
|
|
variant="filled"
|
|
size="xs"
|
|
onClick={onRedownload}
|
|
loading={isLoading}
|
|
disabled={disabled}
|
|
color="red"
|
|
leftSection={
|
|
isLoading ? (
|
|
<Loader size="1rem" />
|
|
) : (
|
|
<Download style={{ width: rem(14), height: rem(14) }} />
|
|
)
|
|
}
|
|
>
|
|
{isLoading ? 'Re-downloading...' : 'Re-download'}
|
|
</Button>
|
|
);
|
|
}
|
|
|
|
if (onDelete && versionInfo.isInstalled && !versionInfo.isCurrent) {
|
|
buttons.push(
|
|
<Button
|
|
key="delete"
|
|
variant="light"
|
|
size="xs"
|
|
onClick={onDelete}
|
|
loading={isLoading}
|
|
disabled={disabled}
|
|
color="red"
|
|
leftSection={
|
|
isLoading ? (
|
|
<Loader size="1rem" />
|
|
) : (
|
|
<Trash2 style={{ width: rem(14), height: rem(14) }} />
|
|
)
|
|
}
|
|
>
|
|
{isLoading ? 'Deleting...' : 'Delete'}
|
|
</Button>
|
|
);
|
|
}
|
|
|
|
return buttons.length > 0 ? <Stack gap="xs">{buttons}</Stack> : null;
|
|
};
|
|
|
|
return (
|
|
<Card
|
|
withBorder
|
|
radius="sm"
|
|
padding="sm"
|
|
{...(versionInfo.isCurrent && {
|
|
bg: colorScheme === 'dark' ? 'dark.6' : 'gray.0',
|
|
bd: `2px solid var(--mantine-color-${colorScheme === 'dark' ? 'blue-4' : 'blue-6'})`,
|
|
})}
|
|
>
|
|
<Group justify="space-between" align="center">
|
|
<div style={{ flex: 1 }}>
|
|
<Group gap="xs" align="center" mb="xs">
|
|
<Text fw={500} size="sm">
|
|
{pretifyBinName(versionInfo.name)}
|
|
</Text>
|
|
{versionInfo.isCurrent && (
|
|
<Badge variant="light" color="blue" size="sm">
|
|
Current
|
|
</Badge>
|
|
)}
|
|
{versionInfo.hasUpdate && (
|
|
<Badge variant="light" color="orange" size="sm">
|
|
Update Available
|
|
</Badge>
|
|
)}
|
|
{isWindowsROCmBuild(versionInfo.name) && (
|
|
<Badge variant="light" color="yellow" size="sm">
|
|
Experimental
|
|
</Badge>
|
|
)}
|
|
</Group>
|
|
{description && (
|
|
<Text size="xs" c="dimmed" mb="xs">
|
|
{description}
|
|
</Text>
|
|
)}
|
|
<Group gap="xs" align="center">
|
|
{versionInfo.version && (
|
|
<Text size="xs" c="dimmed">
|
|
Version {versionInfo.version}
|
|
{hasVersionMismatch && versionInfo.actualVersion && (
|
|
<span style={{ color: 'var(--mantine-color-red-6)' }}>
|
|
{' '}
|
|
(actual: {versionInfo.actualVersion})
|
|
</span>
|
|
)}
|
|
</Text>
|
|
)}
|
|
{size && (
|
|
<>
|
|
<Text size="xs" c="dimmed">
|
|
•
|
|
</Text>
|
|
<Badge variant="light" color="gray" size="xs">
|
|
{size}
|
|
</Badge>
|
|
</>
|
|
)}
|
|
</Group>
|
|
</div>
|
|
|
|
{renderActionButtons()}
|
|
</Group>
|
|
|
|
{isLoading && downloadProgress !== undefined && (
|
|
<Stack gap="xs" mt="sm">
|
|
<Progress
|
|
value={Math.min(downloadProgress, 100)}
|
|
color="blue"
|
|
radius="xl"
|
|
/>
|
|
<Text size="xs" c="dimmed" ta="center">
|
|
{Math.min(downloadProgress, 100) === 100
|
|
? '100%'
|
|
: `${Math.min(downloadProgress, 100).toFixed(1)}%`}{' '}
|
|
complete
|
|
</Text>
|
|
</Stack>
|
|
)}
|
|
</Card>
|
|
);
|
|
};
|