Show attachment download progress

This commit is contained in:
TerryM
2026-05-27 12:23:06 +08:00
parent 9453777dba
commit 54841a4ed9
6 changed files with 125 additions and 59 deletions

View File

@@ -1,9 +1,9 @@
import { Download } from "lucide-react";
import { Download, LoaderCircle } from "lucide-react";
import { Link } from "react-router-dom";
import type { Resource } from "../api";
import { assetUrl, postJSON } from "../api";
import { useI18n } from "../i18n";
import { useMemo } from "react";
import { useMemo, useState } from "react";
import { formatDateYmd } from "../utils/format";
import { officialRecommendationCoverFallbacks } from "./FigmaBanner";
import {
@@ -31,6 +31,7 @@ export function RecommendedCard({
visualIndex?: number;
}) {
const { t } = useI18n();
const [isDownloading, setIsDownloading] = useState(false);
const cover = useMemo(() => {
const original = r.coverImage || r.previewUrl;
if (isPlaceholderAsset(original)) {
@@ -85,29 +86,46 @@ export function RecommendedCard({
{dl ? (
<button
type="button"
className="shrink-0 rounded-lg p-1 text-ark-gold outline-none hover:bg-ark-gold/10 focus-visible:ring-2 focus-visible:ring-ark-gold/80"
title={t("download")}
aria-label={t("download")}
className="shrink-0 rounded-lg p-1 text-ark-gold outline-none hover:bg-ark-gold/10 focus-visible:ring-2 focus-visible:ring-ark-gold/80 disabled:cursor-wait"
title={isDownloading ? t("downloading") : t("download")}
aria-label={isDownloading ? t("downloading") : t("download")}
aria-busy={isDownloading}
disabled={isDownloading}
onClick={async (e) => {
e.preventDefault();
e.stopPropagation();
if (r.downloadPostId && r.downloadAttachmentId) {
void downloadAttachment(
r.downloadPostId,
r.downloadAttachmentId,
r.title,
).catch(() => {});
return;
}
if (isDownloading) return;
setIsDownloading(true);
try {
await postJSON(`/api/resources/${r.id}/download`, {});
if (r.downloadPostId && r.downloadAttachmentId) {
await downloadAttachment(
r.downloadPostId,
r.downloadAttachmentId,
r.title,
);
return;
}
try {
await postJSON(`/api/resources/${r.id}/download`, {});
} catch {
/* ignore */
}
await downloadFile(dl, r.title);
} catch {
/* ignore */
} finally {
setIsDownloading(false);
}
void downloadFile(dl, r.title).catch(() => {});
}}
>
<Download className="h-5 w-5" strokeWidth={2.2} />
{isDownloading ? (
<LoaderCircle
className="h-5 w-5 animate-spin"
strokeWidth={2.2}
/>
) : (
<Download className="h-5 w-5" strokeWidth={2.2} />
)}
</button>
) : null}
</div>