'use client'; import { formatDay } from '../../lib/format'; import { groupByTime } from '../../lib/grouping'; import { resolveLabel } from '../../lib/smartAlbums'; import { Icon, type IconName } from '../../icons'; import { useGallery, useGalleryStoreApi } from '../../store/context'; import { albumMedia, liveMedia, objectLabelCounts } from '../../store/selectors'; import type { MediaItem, ViewId } from '../../types'; import { openContextMenu } from '../ContextMenu'; import { confirmAction, promptAlbumName } from '../modals'; function SectionHeader({ title, chevronTo, action, }: { title: string; chevronTo?: () => void; action?: { label: string; onClick: () => void }; }) { return (
{ if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); chevronTo(); } } : undefined } > {title} {chevronTo ? : null}
{action ? ( ) : null}
); } function PinnedCard({ label, cover, badge, onClick, }: { label: string; cover?: MediaItem; badge?: IconName; onClick: () => void; }) { return ( ); } function EmptyCard({ icon, title, text, }: { icon: IconName; title: string; text: string; }) { return (
{title}
{text}
); } export function CollectionsView() { const api = useGalleryStoreApi(); const media = useGallery((s) => s.media); const albums = useGallery((s) => s.albums); const labelAliases = useGallery((s) => s.labelAliases); const live = liveMedia(media); const userAlbums = albums.filter((a) => a.kind === 'user' || a.kind === 'folder'); const go = (v: ViewId) => () => api.getState().setView(v); const recentDays = groupByTime(live, 'day').slice(0, 8); const objectEntries = [...objectLabelCounts(media, labelAliases).entries()] .sort((a, b) => b[1] - a[1]) .slice(0, 14); // Right-click an object card โ†’ permanently rename its tag (car โ†’ excavator). const renameTag = (label: string) => (e: React.MouseEvent) => { e.preventDefault(); openContextMenu(e.clientX, e.clientY, [ { label: 'Rename Tag', icon: 'tag', onClick: () => promptAlbumName('Rename Tag', label, (name) => api.getState().renameLabel(label, name), { placeholder: 'Tag name', }), }, { label: 'Delete Tag', icon: 'trash', danger: true, onClick: () => confirmAction({ title: 'Delete Tag', message: `Remove the "${label}" tag? It's deleted from all photos and won't be created again.`, confirmLabel: 'Delete', danger: true, onConfirm: () => api.getState().deleteLabel(label), }), }, ]); }; return (
{/* Albums */}
promptAlbumName('New Album', '', (name) => { const id = api.getState().createAlbum(name); api.getState().setView(`album:${id}` as ViewId); }), }} /> {userAlbums.length === 0 ? ( ) : (
{userAlbums.map((a) => { const am = albumMedia(a, media); return ( m.id === a.coverId) ?? am[0]} onClick={go(a.id as ViewId)} /> ); })}
)}
{/* Objects (AI) โ€” auto categories from on-device object detection */} {objectEntries.length > 0 ? (
{objectEntries.map(([label, count]) => ( ))}
) : null} {/* Shared Albums */}
api.getState().setView('shared-albums') }} />
{/* Recent Days */}
{recentDays.length === 0 ? ( ) : (
{recentDays.map((d) => ( api.getState().openLightbox(d.items[0]!.id)} /> ))}
)}
); }