'use client'; import { useRef, useState } from 'react'; import { useViewMedia } from '../../hooks/useViewMedia'; import { groupByTime } from '../../lib/grouping'; import { Icon, type IconName } from '../../icons'; import { useGallery, useGalleryStoreApi } from '../../store/context'; import { liveMedia } from '../../store/selectors'; import { MediaGrid } from '../MediaGrid'; function Welcome({ onImport }: { onImport: () => void }) { // Host-neutral copy: the SDK is embedded in other products (see `title`), so the // empty state must not name a specific photo app or reference its settings. const hints: Array<{ icon: IconName; text: string }> = [ { icon: 'download', text: 'Click the + button to import.' }, { icon: 'duplicates', text: 'Drag photos and videos straight in.' }, { icon: 'camera', text: 'Capture a shot with your camera.' }, { icon: 'image', text: 'Everything you add is searchable.' }, ]; const title = useGallery((s) => s.config.title); return (
Welcome to {title}
To get started, do any of the following:
{hints.map((h, i) => (
{h.text}
))}
); } export function LibraryView() { const api = useGalleryStoreApi(); const items = useViewMedia(); const scale = useGallery((s) => s.libraryScale); const searchQuery = useGallery((s) => s.searchQuery); const objectFocus = useGallery((s) => s.objectFocus); const tagFocus = useGallery((s) => s.tagFocus); const personFocus = useGallery((s) => s.personFocus); const personName = useGallery((s) => { if (!s.personFocus) return null; const p = s.people.find((x) => x.id === s.personFocus); return p?.name ?? 'Unnamed person'; }); const totalLive = useGallery((s) => liveMedia(s.media).length); const fileRef = useRef(null); const [dragging, setDragging] = useState(false); const importFiles = async (files: FileList | null) => { if (!files?.length) return; await api.getState().importFiles(files); if (fileRef.current) fileRef.current.value = ''; }; const onDrop = (e: React.DragEvent) => { e.preventDefault(); setDragging(false); void importFiles(e.dataTransfer.files); }; let content: React.ReactNode; if (items.length === 0) { if (totalLive === 0) { content = fileRef.current?.click()} />; } else { content = (
No Results
{objectFocus ? `No photos containing “${objectFocus}”.` : searchQuery ? 'Try a different search term.' : 'No items match this filter.'}
); } } else if (scale === 'all') { content = ; } else { const granularity = scale === 'years' ? 'year' : scale === 'months' ? 'month' : 'day'; const sections = groupByTime(items, granularity); content = ( <> {sections.map((s) => ( ))} ); } return (
{ e.preventDefault(); setDragging(true); }} onDragLeave={() => setDragging(false)} onDrop={onDrop} style={dragging ? { outline: '3px dashed var(--apg-accent)', outlineOffset: -8 } : undefined} > {objectFocus || tagFocus || personFocus ? (
{objectFocus ? `Object: ${objectFocus}` : personFocus ? `Person: ${personName}` : `Tag: ${tagFocus}`}
) : null} {content} void importFiles(e.target.files)} />
); }