import { AlertOctagon, AlertTriangle, DownloadCloud, Github, HelpCircle, Trash2 } from 'lucide-react'; import cls from 'classnames'; import { type AddonData } from '~main/types'; import { api } from '~renderer/utils/api'; import TextButton from '~renderer/components/styled/TextButton'; import { ColoredText } from '~renderer/components/styled/ColoredText'; import IconSpinner from '~renderer/components/styled/IconSpinner'; import DialogButton from '~renderer/components/styled/DialogButton'; import { isNotUndef } from '~common/utils'; import CloseButton from '~renderer/components/styled/CloseButton'; import { useT } from '~renderer/i18n'; import AddonDetail from './AddonDetail'; export type Dependencies = { [folder: string]: 'installed' | 'available' | string; }; export type LocalDependencies = { name: string; optional: boolean; status: 'installed' | 'available' | 'missing' | string; }[]; type Props = Omit & { row: number; dependencies: Dependencies; gitRef?: string; }; const toRepoUrl = (git?: string) => git ? git.replace(/\.git$/, '') : undefined; const AddonListItem = ({ row, dependencies, ...addon }: Props) => { const t = useT(); const update = api.addons.update.useMutation(); const remove = api.addons.remove.useMutation(); const openLink = api.general.openLink.useMutation(); const repoUrl = toRepoUrl(addon.git); const localDependencies: LocalDependencies = [ ...(addon.toc?.Dependencies?.split(', ')?.map(d => [d, false] as const) ?? []), ...(addon.toc?.OptionalDeps?.split(', ')?.map(d => [d, true] as const) ?? []) ].map(([d, optional]) => ({ name: d, optional, status: dependencies[d] ?? 'missing' })); const warnings = [ addon.toc && addon.toc?.Interface !== '11200' ? { full: t('addons.warnIncorrectVersionFull', { version: addon.toc?.Interface ?? '' }), short: t('addons.warnIncorrectVersionShort') } : undefined, localDependencies.some(d => d.status !== 'installed' && !d.optional) ? { full: t('addons.warnMissingDependenciesFull', { deps: localDependencies .filter(d => d.status !== 'installed' && !d.optional) .map(d => d.name) .join(', ') }), short: t('addons.warnMissingDependenciesShort') } : undefined ].filter(isNotUndef); return (
{addon.status === 'fetching' ? ( ) : ( ( )} > {open => ( )} )}
{addon.toc?.Title ?? addon.folder} {repoUrl && ( openLink.mutateAsync(repoUrl)} className="!p-1 text-blueGray/60 hocus:text-pink" /> )}
{addon.toc?.Notes ?? addon.description ?? ''}
{addon.status === 'downloading' ? ( <>

{addon.progress}

) : addon.status === 'invalid' ? (

{addon.error}

) : warnings.length ? (

{warnings[0].short}

) : (

{addon.status === 'upToDate' ? t('addons.upToDate') : !addon.git ? t('addons.notVersioned') : ''}

)} {addon.status === 'outOfDate' && ( update.mutateAsync({ toUpdate: [addon.folder] })} className="s1 -mx-2 justify-self-end" > {t('addons.update')} )} {addon.status === 'available' ? ( update.mutateAsync({ toUpdate: [addon.folder] })} className="text-warmGreen" icon={DownloadCloud} size={18} title={t('addons.download')} /> ) : ( (

{t('addons.deleteConfirmTitle')}


{t('addons.deleteConfirmBody', { folder: addon.folder })}

{t('addons.deleteConfirmFiles')}

{ await remove.mutateAsync({ toDelete: [addon.folder] }); close(); }} disabled={remove.isLoading} className="self-end text-red" > {t('addons.delete')}
)} > {open => ( )}
)}
); }; export default AddonListItem;