feat: add clipboard paste-to-upload for images in media library
This commit is contained in:
parent
b90ca876db
commit
9e82fad875
@ -13,6 +13,8 @@ export default function MediaLibrary({ onInsert, onSetFeature, showSetFeature }:
|
|||||||
const [error, setError] = useState('');
|
const [error, setError] = useState('');
|
||||||
const [query, setQuery] = useState('');
|
const [query, setQuery] = useState('');
|
||||||
const [sortBy, setSortBy] = useState<'date_desc' | 'date_asc' | 'name_asc' | 'size_desc'>('date_desc');
|
const [sortBy, setSortBy] = useState<'date_desc' | 'date_asc' | 'name_asc' | 'size_desc'>('date_desc');
|
||||||
|
const [uploading, setUploading] = useState(false);
|
||||||
|
const [uploadingCount, setUploadingCount] = useState(0);
|
||||||
|
|
||||||
const load = async () => {
|
const load = async () => {
|
||||||
try {
|
try {
|
||||||
@ -33,6 +35,42 @@ export default function MediaLibrary({ onInsert, onSetFeature, showSetFeature }:
|
|||||||
load();
|
load();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
// Paste-to-upload clipboard images
|
||||||
|
useEffect(() => {
|
||||||
|
const handler = async (e: ClipboardEvent) => {
|
||||||
|
try {
|
||||||
|
const items = e.clipboardData?.items;
|
||||||
|
if (!items || items.length === 0) return;
|
||||||
|
const files: File[] = [];
|
||||||
|
for (let i = 0; i < items.length; i++) {
|
||||||
|
const it = items[i];
|
||||||
|
if (it.kind === 'file') {
|
||||||
|
const f = it.getAsFile();
|
||||||
|
if (f && f.type.startsWith('image/')) files.push(f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (files.length === 0) return;
|
||||||
|
setUploading(true);
|
||||||
|
setUploadingCount(files.length);
|
||||||
|
for (const file of files) {
|
||||||
|
try {
|
||||||
|
const fd = new FormData();
|
||||||
|
fd.append('image', file, file.name || 'pasted-image.png');
|
||||||
|
const res = await fetch('/api/media/image', { method: 'POST', body: fd });
|
||||||
|
if (!res.ok) throw new Error(await res.text());
|
||||||
|
} catch (err: any) {
|
||||||
|
setError(err?.message || 'Clipboard upload failed');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setUploading(false);
|
||||||
|
setUploadingCount(0);
|
||||||
|
await load();
|
||||||
|
} catch {}
|
||||||
|
};
|
||||||
|
window.addEventListener('paste', handler);
|
||||||
|
return () => window.removeEventListener('paste', handler);
|
||||||
|
}, []);
|
||||||
|
|
||||||
const del = async (key: string) => {
|
const del = async (key: string) => {
|
||||||
try {
|
try {
|
||||||
setError('');
|
setError('');
|
||||||
@ -81,7 +119,7 @@ export default function MediaLibrary({ onInsert, onSetFeature, showSetFeature }:
|
|||||||
<Paper sx={{ p: 2 }}>
|
<Paper sx={{ p: 2 }}>
|
||||||
<Stack direction="row" justifyContent="space-between" alignItems="center" sx={{ mb: 2 }}>
|
<Stack direction="row" justifyContent="space-between" alignItems="center" sx={{ mb: 2 }}>
|
||||||
<Typography variant="h6">Media Library</Typography>
|
<Typography variant="h6">Media Library</Typography>
|
||||||
<Stack direction="row" spacing={1}>
|
<Stack direction="row" spacing={1} alignItems="center">
|
||||||
<TextField
|
<TextField
|
||||||
size="small"
|
size="small"
|
||||||
placeholder="Search by name…"
|
placeholder="Search by name…"
|
||||||
@ -95,6 +133,9 @@ export default function MediaLibrary({ onInsert, onSetFeature, showSetFeature }:
|
|||||||
<MenuItem value="size_desc">Largest</MenuItem>
|
<MenuItem value="size_desc">Largest</MenuItem>
|
||||||
</TextField>
|
</TextField>
|
||||||
<Button size="small" onClick={load} disabled={loading}>Refresh</Button>
|
<Button size="small" onClick={load} disabled={loading}>Refresh</Button>
|
||||||
|
<Typography variant="caption" sx={{ color: 'text.secondary' }}>
|
||||||
|
Tip: paste an image (Cmd/Ctrl+V) to upload{uploading ? ` — uploading ${uploadingCount}…` : ''}
|
||||||
|
</Typography>
|
||||||
</Stack>
|
</Stack>
|
||||||
</Stack>
|
</Stack>
|
||||||
{error && <Typography color="error" sx={{ mb: 1 }}>{error}</Typography>}
|
{error && <Typography color="error" sx={{ mb: 1 }}>{error}</Typography>}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user