diff --git a/src/app/api/img/route.ts b/src/app/api/img/route.ts index 7892097..dd37eff 100644 --- a/src/app/api/img/route.ts +++ b/src/app/api/img/route.ts @@ -12,7 +12,7 @@ export async function GET(request: Request) { const res = await fetch(target, { redirect: 'follow' }); const contentType = res.headers.get('content-type') || ''; if (!res.ok || !contentType.startsWith('image/')) { - return Response.json({ error: `Obrázok sa nepodarilo načítať (${res.status}).` }, { status: 502 }); + return Response.json({ error: `Obrázok sa nepodarilo načítať (${res.status}).`, upstreamStatus: res.status }, { status: 502 }); } const body = await res.arrayBuffer(); if (body.byteLength > MAX_BYTES) { diff --git a/src/components/editor/ImageUploadInput.tsx b/src/components/editor/ImageUploadInput.tsx index 065b526..191bf14 100644 --- a/src/components/editor/ImageUploadInput.tsx +++ b/src/components/editor/ImageUploadInput.tsx @@ -49,19 +49,31 @@ export const ImageUploadInput: React.FC = ({ // Vložená URL: príliš veľký obrázok sa zmenší a uloží k nám (posledná spracovaná adresa, aby sa nerobilo dvakrát) const lastCheckedUrl = useRef(''); + const [urlNote, setUrlNote] = useState<{ tone: 'ok' | 'warn'; text: string } | null>(null); const checkUrl = async (url: string) => { url = url.trim(); if (!url || url === lastCheckedUrl.current) return; lastCheckedUrl.current = url; setIsUploading(true); + setUrlNote(null); try { - const smaller = await shrinkRemoteImage(url); - if (smaller) { - lastCheckedUrl.current = smaller; - onChange(smaller); + const result = await shrinkRemoteImage(url); + if (result.status === 'shrunk') { + lastCheckedUrl.current = result.url; + onChange(result.url); + setUrlNote({ tone: 'ok', text: 'Obrázok bol väčší ako 1000 px – zmenšili sme ho a uložili k nám.' }); + } else if (result.status === 'small') { + setUrlNote({ tone: 'ok', text: 'Obrázok je v poriadku (najviac 1000 px), adresa ostáva.' }); + } else if (result.status === 'login') { + setUrlNote({ + tone: 'warn', + text: 'Obrázok je za prihlásením – v e-maile sa nezobrazí. Otvorte ho v prehliadači, pravým klikom „Kopírovať obrázok“ a sem vložte Ctrl+V.' + }); + } else if (result.status === 'failed') { + setUrlNote({ tone: 'warn', text: `Obrázok sa nepodarilo stiahnuť (${result.error}). Skontrolujte adresu, prípadne obrázok skopírujte a vložte Ctrl+V.` }); } } catch (err) { - console.warn('Obrázok z URL sa nepodarilo zmenšiť:', err); + setUrlNote({ tone: 'warn', text: `Obrázok sa nepodarilo spracovať: ${(err as Error).message}` }); } finally { setIsUploading(false); } @@ -104,7 +116,13 @@ export const ImageUploadInput: React.FC = ({ onChange(e.target.value)} + onChange={(e) => { + setUrlNote(null); + onChange(e.target.value); + }} + onKeyDown={(e) => { + if (e.key === 'Enter') checkUrl(e.currentTarget.value); + }} onPaste={handlePaste} onBlur={(e) => checkUrl(e.target.value)} placeholder={placeholder} @@ -140,6 +158,12 @@ export const ImageUploadInput: React.FC = ({ + {urlNote && ( +

+ {urlNote.text} +

+ )} + {onAltChange && ( { - if (!/^https?:\/\//i.test(url) || isOwnStorageUrl(url)) return null; +// a ak je väčší ako 1000 px, zmenší sa a nahrá do úložiska. +export async function shrinkRemoteImage(url: string): Promise { + if (!/^https?:\/\/[^/]+\.[^/]+\//i.test(url) || isOwnStorageUrl(url)) return { status: 'skip' }; let blob: Blob | null = null; try { const res = await fetch(url); @@ -73,12 +80,16 @@ export async function shrinkRemoteImage(url: string): Promise { } if (!blob || !blob.type.startsWith('image/')) { const res = await fetch(`/api/img?url=${encodeURIComponent(url)}`); - if (!res.ok) return null; + if (!res.ok) { + const data = await res.json().catch(() => ({})); + if (data.upstreamStatus === 401 || data.upstreamStatus === 403) return { status: 'login' }; + return { status: 'failed', error: data.error || `Chyba ${res.status}` }; + } blob = await res.blob(); } const name = decodeURIComponent(new URL(url).pathname.split('/').pop() || '') || 'obrazok.png'; const file = new File([blob], name, { type: blob.type }); const small = await shrinkImage(file); - if (small === file) return null; - return uploadFile(small, small.name); + if (small === file) return { status: 'small' }; + return { status: 'shrunk', url: await uploadFile(small, small.name) }; }