feat: improve mirror download (new tab & manual link)

This commit is contained in:
dyzulk
2025-12-31 09:47:39 +07:00
parent 8e0f97dbc2
commit 90261a5796
2 changed files with 47 additions and 10 deletions

View File

@@ -249,6 +249,8 @@ export default function HomeClient() {
<div className="grid grid-cols-2 gap-3"> <div className="grid grid-cols-2 gap-3">
<a <a
href={`/download/ca-certificate?serial=${cert.serial}`} href={`/download/ca-certificate?serial=${cert.serial}`}
target="_blank"
rel="noopener noreferrer"
className="flex items-center justify-center gap-2 px-4 py-3 bg-white dark:bg-gray-800 text-gray-700 dark:text-gray-200 rounded-xl border border-gray-200 dark:border-gray-700 font-medium text-sm hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors" className="flex items-center justify-center gap-2 px-4 py-3 bg-white dark:bg-gray-800 text-gray-700 dark:text-gray-200 rounded-xl border border-gray-200 dark:border-gray-700 font-medium text-sm hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors"
title={t('download_standard_title')} title={t('download_standard_title')}
> >
@@ -259,6 +261,8 @@ export default function HomeClient() {
</a> </a>
<a <a
href={`/download/ca-certificate?serial=${cert.serial}&format=der`} href={`/download/ca-certificate?serial=${cert.serial}&format=der`}
target="_blank"
rel="noopener noreferrer"
className="flex items-center justify-center gap-2 px-4 py-3 bg-green-50 dark:bg-green-500/10 text-green-700 dark:text-green-400 rounded-xl border border-green-200 dark:border-green-500/20 font-medium text-sm hover:bg-green-100 dark:hover:bg-green-500/20 transition-colors" className="flex items-center justify-center gap-2 px-4 py-3 bg-green-50 dark:bg-green-500/10 text-green-700 dark:text-green-400 rounded-xl border border-green-200 dark:border-green-500/20 font-medium text-sm hover:bg-green-100 dark:hover:bg-green-500/20 transition-colors"
title={t('download_android_title')} title={t('download_android_title')}
> >
@@ -271,6 +275,8 @@ export default function HomeClient() {
<div className="grid grid-cols-2 gap-3"> <div className="grid grid-cols-2 gap-3">
<a <a
href={`/download/ca-certificate?serial=${cert.serial}&target=windows`} href={`/download/ca-certificate?serial=${cert.serial}&target=windows`}
target="_blank"
rel="noopener noreferrer"
className="flex items-center justify-center gap-2 px-4 py-3 bg-blue-50 dark:bg-blue-500/10 text-blue-700 dark:text-blue-400 rounded-xl border border-blue-200 dark:border-blue-500/20 font-medium text-sm hover:bg-blue-100 dark:hover:bg-blue-500/20 transition-colors" className="flex items-center justify-center gap-2 px-4 py-3 bg-blue-50 dark:bg-blue-500/10 text-blue-700 dark:text-blue-400 rounded-xl border border-blue-200 dark:border-blue-500/20 font-medium text-sm hover:bg-blue-100 dark:hover:bg-blue-500/20 transition-colors"
title={t('download_windows_title')} title={t('download_windows_title')}
> >
@@ -281,6 +287,8 @@ export default function HomeClient() {
</a> </a>
<a <a
href={`/download/ca-certificate?serial=${cert.serial}&target=mac`} href={`/download/ca-certificate?serial=${cert.serial}&target=mac`}
target="_blank"
rel="noopener noreferrer"
className="flex items-center justify-center gap-2 px-4 py-3 bg-gray-100 dark:bg-gray-700 text-gray-800 dark:text-gray-100 rounded-xl border border-gray-200 dark:border-gray-600 font-medium text-sm hover:bg-gray-200 dark:hover:bg-gray-600 transition-colors" className="flex items-center justify-center gap-2 px-4 py-3 bg-gray-100 dark:bg-gray-700 text-gray-800 dark:text-gray-100 rounded-xl border border-gray-200 dark:border-gray-600 font-medium text-sm hover:bg-gray-200 dark:hover:bg-gray-600 transition-colors"
title={t('download_macos_title')} title={t('download_macos_title')}
> >
@@ -318,6 +326,8 @@ export default function HomeClient() {
<div className="grid grid-cols-2 gap-3"> <div className="grid grid-cols-2 gap-3">
<a <a
href={`/download/ca-certificate?serial=${cert.serial}`} href={`/download/ca-certificate?serial=${cert.serial}`}
target="_blank"
rel="noopener noreferrer"
className="flex items-center justify-center gap-2 px-4 py-3 bg-white dark:bg-gray-800 text-gray-700 dark:text-gray-200 rounded-xl border border-gray-200 dark:border-gray-700 font-medium text-sm hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors" className="flex items-center justify-center gap-2 px-4 py-3 bg-white dark:bg-gray-800 text-gray-700 dark:text-gray-200 rounded-xl border border-gray-200 dark:border-gray-700 font-medium text-sm hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors"
title={t('download_standard_title')} title={t('download_standard_title')}
> >
@@ -328,6 +338,8 @@ export default function HomeClient() {
</a> </a>
<a <a
href={`/download/ca-certificate?serial=${cert.serial}&format=der`} href={`/download/ca-certificate?serial=${cert.serial}&format=der`}
target="_blank"
rel="noopener noreferrer"
className="flex items-center justify-center gap-2 px-4 py-3 bg-green-50 dark:bg-green-500/10 text-green-700 dark:text-green-400 rounded-xl border border-green-200 dark:border-green-500/20 font-medium text-sm hover:bg-green-100 dark:hover:bg-green-500/20 transition-colors" className="flex items-center justify-center gap-2 px-4 py-3 bg-green-50 dark:bg-green-500/10 text-green-700 dark:text-green-400 rounded-xl border border-green-200 dark:border-green-500/20 font-medium text-sm hover:bg-green-100 dark:hover:bg-green-500/20 transition-colors"
title={t('download_android_title')} title={t('download_android_title')}
> >
@@ -340,6 +352,8 @@ export default function HomeClient() {
<div className="grid grid-cols-2 gap-3"> <div className="grid grid-cols-2 gap-3">
<a <a
href={`/download/ca-certificate?serial=${cert.serial}&target=windows`} href={`/download/ca-certificate?serial=${cert.serial}&target=windows`}
target="_blank"
rel="noopener noreferrer"
className="flex items-center justify-center gap-2 px-4 py-3 bg-blue-50 dark:bg-blue-500/10 text-blue-700 dark:text-blue-400 rounded-xl border border-blue-200 dark:border-blue-500/20 font-medium text-sm hover:bg-blue-100 dark:hover:bg-blue-500/20 transition-colors" className="flex items-center justify-center gap-2 px-4 py-3 bg-blue-50 dark:bg-blue-500/10 text-blue-700 dark:text-blue-400 rounded-xl border border-blue-200 dark:border-blue-500/20 font-medium text-sm hover:bg-blue-100 dark:hover:bg-blue-500/20 transition-colors"
title={t('download_windows_title')} title={t('download_windows_title')}
> >
@@ -350,6 +364,8 @@ export default function HomeClient() {
</a> </a>
<a <a
href={`/download/ca-certificate?serial=${cert.serial}&target=mac`} href={`/download/ca-certificate?serial=${cert.serial}&target=mac`}
target="_blank"
rel="noopener noreferrer"
className="flex items-center justify-center gap-2 px-4 py-3 bg-gray-100 dark:bg-gray-700 text-gray-800 dark:text-gray-100 rounded-xl border border-gray-200 dark:border-gray-600 font-medium text-sm hover:bg-gray-200 dark:hover:bg-gray-600 transition-colors" className="flex items-center justify-center gap-2 px-4 py-3 bg-gray-100 dark:bg-gray-700 text-gray-800 dark:text-gray-100 rounded-xl border border-gray-200 dark:border-gray-600 font-medium text-sm hover:bg-gray-200 dark:hover:bg-gray-600 transition-colors"
title={t('download_macos_title')} title={t('download_macos_title')}
> >

View File

@@ -8,6 +8,7 @@ function DownloadMirrorContent() {
const searchParams = useSearchParams(); const searchParams = useSearchParams();
const [status, setStatus] = useState("Preparing your download..."); const [status, setStatus] = useState("Preparing your download...");
const [error, setError] = useState<string | null>(null); const [error, setError] = useState<string | null>(null);
const [downloadUrl, setDownloadUrl] = useState<string | null>(null);
useEffect(() => { useEffect(() => {
const serial = searchParams.get("serial"); const serial = searchParams.get("serial");
@@ -22,27 +23,27 @@ function DownloadMirrorContent() {
// Construct backend URL // Construct backend URL
const baseUrl = process.env.NEXT_PUBLIC_BACKEND_URL; const baseUrl = process.env.NEXT_PUBLIC_BACKEND_URL;
let downloadUrl = `${baseUrl}/api/public/ca-certificates/${serial}/download`; let url = `${baseUrl}/api/public/ca-certificates/${serial}/download`;
// Append target if specified (windows/mac) // Append target if specified (windows/mac)
if (target) { if (target) {
downloadUrl += `/${target}`; url += `/${target}`;
} }
// Append format if specified (der) // Append format if specified (der)
if (format) { if (format) {
downloadUrl += `?format=${format}`; url += `?format=${format}`;
} }
setDownloadUrl(url);
// Mirroring: Redirect to the backend download URL // Mirroring: Redirect to the backend download URL
setStatus("Redirecting to download..."); setStatus("Redirecting to download...");
window.location.href = downloadUrl; window.location.href = url;
// Optional: Auto close or go back after some time
// But usually the download happens in the background and the page stays
const timeout = setTimeout(() => { const timeout = setTimeout(() => {
setStatus("If your download didn't start automatically, please refresh this page."); setStatus("Your download should have started.");
}, 5000); }, 3000);
return () => clearTimeout(timeout); return () => clearTimeout(timeout);
}, [searchParams]); }, [searchParams]);
@@ -76,11 +77,31 @@ function DownloadMirrorContent() {
<path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path> <path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
</svg> </svg>
</div> </div>
<div>
<h2 className="text-xl font-bold text-gray-900 dark:text-white">{status}</h2> <h2 className="text-xl font-bold text-gray-900 dark:text-white">{status}</h2>
<p className="text-sm text-gray-500 dark:text-gray-400">Mirroring Download from TrustLab Trust Store</p> <p className="text-sm text-gray-500 dark:text-gray-400 mt-2">Mirroring Download from TrustLab Trust Store</p>
</div>
{downloadUrl && (
<div className="pt-4 animate-in fade-in slide-in-from-bottom-4 duration-700 delay-500 fill-mode-both">
<p className="text-sm text-gray-500 dark:text-gray-400 mb-4">
If your download didn't start automatically,
</p>
<a
href={downloadUrl}
className="inline-flex items-center gap-2 text-brand-600 dark:text-brand-400 font-semibold hover:underline"
>
<svg className="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4" />
</svg>
klik disini untuk download manual
</a>
</div> </div>
)} )}
</div> </div>
)}
</div>
<div className="absolute inset-0 overflow-hidden pointer-events-none"> <div className="absolute inset-0 overflow-hidden pointer-events-none">
<CommonGridShape /> <CommonGridShape />