fix: supprime le layout shift des boutons qBittorrent au chargement
La config qBittorrent est maintenant récupérée côté serveur et passée en prop au QbittorrentProvider, évitant le fetch client qui causait l'apparition tardive des boutons de téléchargement. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -65,11 +65,12 @@ function formatEta(seconds: number): string {
|
||||
interface DownloadsPageProps {
|
||||
initialDownloads: TorrentDownloadDto[];
|
||||
initialLatestFound: LatestFoundPerLibraryDto[];
|
||||
qbConfigured?: boolean;
|
||||
}
|
||||
|
||||
const PAGE_SIZE = 10;
|
||||
|
||||
export function DownloadsPage({ initialDownloads, initialLatestFound }: DownloadsPageProps) {
|
||||
export function DownloadsPage({ initialDownloads, initialLatestFound, qbConfigured }: DownloadsPageProps) {
|
||||
const { t } = useTranslation();
|
||||
const [downloads, setDownloads] = useState<TorrentDownloadDto[]>(initialDownloads);
|
||||
const [filter, setFilter] = useState<string>("all");
|
||||
@@ -184,7 +185,7 @@ export function DownloadsPage({ initialDownloads, initialLatestFound }: Download
|
||||
|
||||
{/* Available downloads from latest detection */}
|
||||
{initialLatestFound.length > 0 && (
|
||||
<QbittorrentProvider>
|
||||
<QbittorrentProvider initialConfigured={qbConfigured}>
|
||||
<div className="mt-10">
|
||||
<h2 className="text-xl font-bold text-foreground mb-4 flex items-center gap-2">
|
||||
<Icon name="search" size="lg" />
|
||||
|
||||
@@ -3,10 +3,20 @@ import { DownloadsPage } from "./DownloadsPage";
|
||||
|
||||
export const dynamic = "force-dynamic";
|
||||
|
||||
async function isQbConfigured(): Promise<boolean> {
|
||||
try {
|
||||
const data = await apiFetch<{ url?: string; username?: string }>("/settings/qbittorrent");
|
||||
return !!(data && data.url?.trim() && data.username?.trim());
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export default async function Page() {
|
||||
const [downloads, latestFound] = await Promise.all([
|
||||
const [downloads, latestFound, qbConfigured] = await Promise.all([
|
||||
fetchTorrentDownloads().catch(() => [] as TorrentDownloadDto[]),
|
||||
apiFetch<LatestFoundPerLibraryDto[]>("/download-detection/latest-found").catch(() => [] as LatestFoundPerLibraryDto[]),
|
||||
isQbConfigured(),
|
||||
]);
|
||||
return <DownloadsPage initialDownloads={downloads} initialLatestFound={latestFound} />;
|
||||
return <DownloadsPage initialDownloads={downloads} initialLatestFound={latestFound} qbConfigured={qbConfigured} />;
|
||||
}
|
||||
|
||||
@@ -48,15 +48,16 @@ export function DownloadDetectionErrorsCard({ results, t }: {
|
||||
);
|
||||
}
|
||||
|
||||
export function DownloadDetectionResultsCard({ results, libraryId, t }: {
|
||||
export function DownloadDetectionResultsCard({ results, libraryId, qbConfigured, t }: {
|
||||
results: DownloadDetectionResultDto[];
|
||||
libraryId: string | null;
|
||||
qbConfigured?: boolean;
|
||||
t: TranslateFunction;
|
||||
}) {
|
||||
if (results.length === 0) return null;
|
||||
|
||||
return (
|
||||
<QbittorrentProvider>
|
||||
<QbittorrentProvider initialConfigured={qbConfigured}>
|
||||
<Card className="lg:col-span-2">
|
||||
<CardHeader>
|
||||
<CardTitle>{t("jobDetail.downloadAvailableReleases")}</CardTitle>
|
||||
|
||||
@@ -149,11 +149,15 @@ export default async function JobDetailPage({ params }: JobDetailPageProps) {
|
||||
let downloadDetectionReport: DownloadDetectionReportDto | null = null;
|
||||
let downloadDetectionResults: DownloadDetectionResultDto[] = [];
|
||||
let downloadDetectionErrors: DownloadDetectionResultDto[] = [];
|
||||
let qbConfigured = false;
|
||||
if (isDownloadDetection) {
|
||||
[downloadDetectionReport, downloadDetectionResults, downloadDetectionErrors] = await Promise.all([
|
||||
[downloadDetectionReport, downloadDetectionResults, downloadDetectionErrors, qbConfigured] = await Promise.all([
|
||||
getDownloadDetectionReport(id).catch(() => null),
|
||||
getDownloadDetectionResults(id, "found").catch(() => []),
|
||||
getDownloadDetectionResults(id, "error").catch(() => []),
|
||||
apiFetch<{ url?: string; username?: string }>("/settings/qbittorrent")
|
||||
.then(d => !!(d?.url?.trim() && d?.username?.trim()))
|
||||
.catch(() => false),
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -273,7 +277,7 @@ export default async function JobDetailPage({ params }: JobDetailPageProps) {
|
||||
{/* Download detection */}
|
||||
{isDownloadDetection && downloadDetectionReport && <DownloadDetectionReportCard report={downloadDetectionReport} t={t} />}
|
||||
{isDownloadDetection && <DownloadDetectionErrorsCard results={downloadDetectionErrors} t={t} />}
|
||||
{isDownloadDetection && <DownloadDetectionResultsCard results={downloadDetectionResults} libraryId={job.library_id} t={t} />}
|
||||
{isDownloadDetection && <DownloadDetectionResultsCard results={downloadDetectionResults} libraryId={job.library_id} qbConfigured={qbConfigured} t={t} />}
|
||||
|
||||
{/* Metadata batch results */}
|
||||
{isMetadataBatch && <MetadataBatchResultsCard results={batchResults} libraryId={job.library_id} t={t} />}
|
||||
|
||||
Reference in New Issue
Block a user