-
-
-
-
-
- {(job.job_kind === "edit" || job.job_kind === "clip") && (
-
- {t("downloads.clipBadge")}
-
- )}
- {linkTitle ? (
- // No name yet: the title IS the link, so the link line below leaves it out (it said the
- // same URL a third time).
-
- {jobTitle(job)}
-
- ) : (
- jobTitle(job)
- )}
-
-
-
- {/* The meta line never wraps (the owner, 2026-09-27: on the iPad its "18.9 / MB" pieces broke
- into a jumble). One line, cut at its end, so the least telling part (the age) goes first. */}
-
-
- {job.asset?.container ? (
- // Concrete container (mp4 / m4a / webm …) — reads as the file format, and its audio-vs-video
- // extension is the video/audio distinction the running-only phase pill can't show at rest.
-
· {job.asset.container}
- ) : null}
- {job.asset?.size_bytes ? (
-
· {formatBytes(job.asset.size_bytes, lang)}
- ) : null}
- {job.asset?.duration_s ? (
-
· {formatDuration(job.asset.duration_s)}
- ) : null}
- {job.status === "done" && job.created_at ? (
-
- {" · "}
- {" "}
- {relativeTime(job.created_at, lang, t)}
-
- ) : null}
- {job.status === "error" ? (
- <>
- {" "}
-
onShowError?.(job)}
- className="text-danger inline-block leading-6 min-h-6 touch-target pointer-coarse:leading-(--touch-target)"
- title={t(failTitleKey(job))}
- >
- · {t(failCopyKeys(job, "short"))}{" "}
-
- {t("downloads.errors.fail.detailsLink")}
-
-
- >
- ) : null}
-
- {/* Wide, this wrapper is `contents`: the source and the actions are grid items of their own
- (src under the meta, act down the right). Stacked, it is ONE wrapping line: the link and
- the actions side by side while they fit, the actions under the link only when they don't
- (at 375). On touch each is a 44px box, so separate lines stacked 44px gaps (the owner,
- 2026-09-27: "what are those huge empty parts?"). */}
-
- {(!!sourceLink || !!job.extra_links?.length) && (
-
- {sourceLink && }
- {job.extra_links?.map((url) => (
-
- ))}
-
- )}
- {/* The row's visible actions — its primary one and the save link — then its "…": the md
- rung here (the row stands alone), the sm rung in the modals, one IconBtn for both. */}
-
- {children}
- {more}
-
-
- {running && (
-
- {job.phase && !DOWNLOAD_PHASES.includes(job.phase) ? (
- // ffmpeg post-steps aren't byte-progress — show an indeterminate pulse, no %.
-
- ) : (
- <>
-
-
- {job.progress}%
- {job.speed_bps ? {formatSpeed(job.speed_bps, lang)} : null}
- {job.eta_s ? {formatEta(t, job.eta_s)} : null}
-
- >
- )}
-
- )}
-