import { LibraryModal } from './library/LibraryModal' import { LibraryItemCard } from './library/LibraryItemCard' import { LoraInfoPopover } from './LoraInfoPopover' import { useHfAuth } from '../hooks/use-hf-auth' import type { LibraryEntry } from '../lib/lora-library' export type LibraryKind = 'lora' | 'ic-lora' interface LoraLibraryModalProps { open: boolean onClose: () => void kind: LibraryKind items: LibraryEntry[] selectedId: string | null // Which variant of selectedId is actually active — lets the card badge the exact // installed checkpoint as "Selected" rather than the whole catalog entry. selectedVariantId?: string | null downloadingKey: string | null progress: number downloadError: { key: string; message: string } | null // Transient message (e.g. "still syncing installed files") shown when onSelect returns false. syncError?: string | null onDownload: (id: string, variantId?: string) => void // Returns whether the entry was actually selected — the modal only closes on success. onSelect: (entry: LibraryEntry, variantId?: string) => boolean } // Generic catalog library modal — works for both plain LoRAs and IC-LoRAs. The consumer // maps its API/on-disk types into LibraryEntry[]; LibraryModal/LibraryItemCard stay // domain-agnostic. export function LoraLibraryModal({ open, onClose, kind, items, selectedId, selectedVariantId, downloadingKey, progress, downloadError, syncError, onDownload, onSelect, }: LoraLibraryModalProps) { // A catalog entry with no download variants has nothing to show a card for. const visibleItems = items.filter(e => (e.variants?.length ?? 0) > 0) // HF "Connect" CTA: shown only when a gated item is visible and we're not signed in. const anyGated = visibleItems.some(e => e.requiresHfLogin) const { hfAuthStatus } = useHfAuth(open && anyGated) const showConnectCta = anyGated && hfAuthStatus !== 'authenticated' const handleConnect = () => { window.dispatchEvent(new CustomEvent('open-settings', { detail: { tab: 'apiKeys' } })) onClose() } return ( Connect HuggingFace ) : undefined} > {syncError && (
{syncError}
)} {visibleItems.length === 0 ? (
{kind === 'ic-lora' ? 'No IC-LoRAs available.' : 'No LoRAs found. Downloaded and installed LoRAs will appear here.'}
) : (
{visibleItems.map(e => { const cardError = !downloadError ? null : (e.requiresHfLogin && hfAuthStatus !== 'authenticated') ? { key: downloadError.key, message: 'Sign in to HuggingFace (top right), then retry.', gated: false } : { ...downloadError, gated: Boolean(e.requiresHfLogin) } return ( ({ id: v.id, label: v.label, sizeBytes: v.sizeBytes, downloaded: e.downloadedVariantIds?.includes(v.id), })), defaultVariantId: e.defaultVariantId, }} infoSlot={( )} onDownload={onDownload} onRetry={onDownload} onRequestAccess={() => { if (e.repoId) void window.electronAPI.openHuggingFaceRepo({ repoId: e.repoId }) }} onUse={(_id, variantId) => { if (onSelect(e, variantId)) onClose() }} /> ) })}
)}
) }