'use client'; import { useRef, useState } from 'react'; import { Icon } from '../icons'; import { isAcceptedMediaFile } from '../lib/media'; import { useGallery, useGalleryStoreApi } from '../store/context'; import type { AlbumId } from '../types'; import { closeModal, openModal } from './Modal'; /** Use the SAME allow-list the import pipeline enforces (mediaFromFile), so the * "N files ready" count matches what will actually be accepted — no silent skips. */ const acceptFile = (f: File) => isAcceptedMediaFile(f); function UploadModal({ defaultAlbumId }: { defaultAlbumId?: AlbumId }) { const api = useGalleryStoreApi(); const albums = useGallery((s) => s.albums.filter((a) => a.kind === 'user' || a.kind === 'folder')); const [files, setFiles] = useState([]); const [rejected, setRejected] = useState(0); const [album, setAlbum] = useState(defaultAlbumId ?? ''); const [busy, setBusy] = useState(false); const [drag, setDrag] = useState(false); const inputRef = useRef(null); const add = (list: FileList | File[] | null) => { if (!list) return; const all = Array.from(list); const ok = all.filter(acceptFile); setRejected((r) => r + (all.length - ok.length)); if (ok.length) setFiles((prev) => [...prev, ...ok]); }; // Open the native OS file picker. A real, explicit control triggering input.click() // is the most reliable cross-browser way to open the file dialog. const browse = () => inputRef.current?.click(); const upload = async () => { if (!files.length) return; setBusy(true); try { await api.getState().importFiles(files, album || undefined); closeModal(); } finally { setBusy(false); } }; return (
Add Photos & Videos
{/* Explicit, always-visible browse control (the dropzone click can be flaky on some setups; a real button reliably opens the OS file dialog). */} { add(e.target.files); // Reset so choosing the SAME file again still fires onChange. e.target.value = ''; }} />
); } /** Open the upload modal, defaulting the album to the currently-open one. */ export function openUploadModal(defaultAlbumId?: AlbumId) { openModal(); }