From bc9a43d6de4f45ce3a8c583153127ace4f79c97e Mon Sep 17 00:00:00 2001 From: Evandro Fonseca Junior Date: Sat, 10 Oct 2026 03:56:37 -0300 Subject: [PATCH] feat(web): exibe erros ao enfileirar e melhora acessibilidade e contraste MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Mostra no formulário o erro devolvido pela API ao enfileirar (antes só ia ao console) e desabilita o botão durante o envio. - Adiciona aria-label no campo de URL, role=alert no erro e role=progressbar na barra. - Clareia a cor destructive (contraste do texto de erro sobre o fundo escuro ~2:1 para ~4,5:1). - Corrige o título da página (era 'web'). --- web/index.html | 2 +- web/src/App.tsx | 10 +------- web/src/components/feature/DownloadForm.tsx | 27 ++++++++++++++++----- web/src/components/ui/ProgressBar.tsx | 4 +++ web/src/context/SessionContext.tsx | 7 ++++-- web/src/index.css | 2 +- 6 files changed, 33 insertions(+), 19 deletions(-) diff --git a/web/index.html b/web/index.html index af88f03..7801b60 100644 --- a/web/index.html +++ b/web/index.html @@ -4,7 +4,7 @@ - web + Ephemeral Downloader
diff --git a/web/src/App.tsx b/web/src/App.tsx index febb914..1aea168 100644 --- a/web/src/App.tsx +++ b/web/src/App.tsx @@ -35,14 +35,6 @@ function DownloadList() { function Main() { const { queueDownload } = useSession(); - const handleDownload = async (url: string) => { - try { - await queueDownload(url); - } catch (error) { - console.error("Failed to queue", error); - } - }; - return (
@@ -56,7 +48,7 @@ function Main() { Paste a link to start. Files are downloaded to the server first.

- + diff --git a/web/src/components/feature/DownloadForm.tsx b/web/src/components/feature/DownloadForm.tsx index f5e1f05..ef2a138 100644 --- a/web/src/components/feature/DownloadForm.tsx +++ b/web/src/components/feature/DownloadForm.tsx @@ -9,14 +9,15 @@ const formSchema = z.object({ }); interface DownloadFormProps { - onDownload: (url: string) => void; + onDownload: (url: string) => Promise; } export function DownloadForm({ onDownload }: DownloadFormProps) { const [url, setUrl] = useState(""); const [error, setError] = useState(null); + const [submitting, setSubmitting] = useState(false); - const handleSubmit = (e: React.FormEvent) => { + const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); setError(null); @@ -27,8 +28,15 @@ export function DownloadForm({ onDownload }: DownloadFormProps) { return; } - onDownload(url); - setUrl(""); + setSubmitting(true); + try { + await onDownload(url); + setUrl(""); + } catch (err) { + setError(err instanceof Error ? err.message : "Failed to queue download"); + } finally { + setSubmitting(false); + } }; return ( @@ -37,14 +45,21 @@ export function DownloadForm({ onDownload }: DownloadFormProps) {
setUrl(e.target.value)} className={error ? "border-destructive focus-visible:ring-destructive" : ""} /> - {error &&

{error}

} + {error && ( + + )}
- diff --git a/web/src/components/ui/ProgressBar.tsx b/web/src/components/ui/ProgressBar.tsx index bcc15bb..3cf0466 100644 --- a/web/src/components/ui/ProgressBar.tsx +++ b/web/src/components/ui/ProgressBar.tsx @@ -14,6 +14,10 @@ const Progress = React.forwardRef( return (
{ - if (!sessionId) return; + if (!sessionId) throw new Error("Session not ready, try again in a moment"); try { const res = await fetch(`${API_URL}/api/queue`, { method: "POST", @@ -101,7 +101,10 @@ export function SessionProvider({ children }: { children: React.ReactNode }) { body: JSON.stringify({ url }), }); - if (!res.ok) throw new Error("Failed to queue download"); + if (!res.ok) { + const body = (await res.json().catch(() => null)) as { error?: string } | null; + throw new Error(body?.error || "Failed to queue download"); + } await refreshTasks(); // Immediate refresh diff --git a/web/src/index.css b/web/src/index.css index 583a1de..7c47070 100644 --- a/web/src/index.css +++ b/web/src/index.css @@ -45,7 +45,7 @@ --accent: 217.2 32.6% 17.5%; --accent-foreground: 210 40% 98%; - --destructive: 0 62.8% 30.6%; + --destructive: 0 72% 54%; --destructive-foreground: 210 40% 98%; --border: 217.2 32.6% 17.5%;