'use client'; import { useState, useMemo } from 'react'; import { useScrollLock } from './useScrollLock'; import { useModalDialog } from '@/hooks/useModalDialog'; import { IconFolder } from './Icons'; interface ImmichAlbumInfo { id: string; albumName: string; description: string; thumbnailAssetId: string | null; assetCount: number; isConfigured: boolean; /** Immich's own flag. Undefined on older Immich — silence beats a false alarm. */ shared?: boolean; } interface Props { albums: ImmichAlbumInfo[]; onSelect: (albumId: string) => void; onClose: () => void; usedAlbumIds: Set; } export default function AlbumPicker({ albums, onSelect, onClose, usedAlbumIds }: Props) { useScrollLock(true); const [search, setSearch] = useState(''); const filtered = useMemo(() => { if (!search.trim()) return albums; const q = search.toLowerCase(); return albums.filter( (a) => a.albumName.toLowerCase().includes(q) || a.description.toLowerCase().includes(q) || a.id.includes(q), ); }, [albums, search]); const cardRef = useModalDialog(onClose); return (
e.stopPropagation()} >

Select Album

setSearch(e.target.value)} autoFocus />
{filtered.length === 0 && (

No albums found. Make sure you have shared albums in Immich.

)} {filtered.map((album) => { const isUsed = usedAlbumIds.has(album.id); return (
!isUsed && onSelect(album.id)} >
{album.thumbnailAssetId ? ( ) : (
)}
{album.albumName} {album.assetCount} photos {album.description && ` · ${album.description.slice(0, 40)}`} {/* Not a warning and not a barrier: publishing an unshared album has always worked, because Immich ignores the ?shared=true filter this list is fetched with (#515). It is here so nobody publishes a private album unaware. */} {album.shared === false && ( Not shared in Immich )}
{isUsed ? ( In use ) : ( Select )}
); })}
); }