docs: improve Linux installation guide with CLI one-liner and copy feature

This commit is contained in:
dyzulk
2026-01-06 15:14:47 +07:00
parent 1b0e504040
commit 74e1a2cb93
3 changed files with 66 additions and 23 deletions

View File

@@ -99,22 +99,37 @@ function OsGuideContent({ title, steps }: { title: string, steps: string[] }) {
{title}
</h4>
<ul className="space-y-4">
{steps.map((step, idx) => (
<li key={idx} className="flex gap-4">
<span className="flex-shrink-0 w-6 h-6 rounded-full bg-brand-50 dark:bg-brand-500/10 text-brand-600 dark:text-brand-400 flex items-center justify-center text-xs font-bold border border-brand-100 dark:border-brand-500/20">
{idx + 1}
</span>
<p className="text-sm text-gray-600 dark:text-gray-400 leading-relaxed font-medium">
{step}
</p>
</li>
))}
{steps.map((step, idx) => {
const isCommand = step.includes('curl') || step.includes('bash') || step.includes('sudo');
return (
<li key={idx} className="flex gap-4">
<span className="flex-shrink-0 w-6 h-6 rounded-full bg-brand-50 dark:bg-brand-500/10 text-brand-600 dark:text-brand-400 flex items-center justify-center text-xs font-bold border border-brand-100 dark:border-brand-500/20">
{idx + 1}
</span>
<div className="flex-1">
<p className={`text-sm text-gray-600 dark:text-gray-400 leading-relaxed ${isCommand ? 'font-mono bg-gray-100 dark:bg-gray-900 px-3 py-1.5 rounded-lg border border-gray-200 dark:border-gray-700 break-all' : 'font-medium'}`}>
{step}
</p>
</div>
</li>
);
})}
</ul>
</div>
);
}
function CaCard({ cert, isRoot, t, selectedOs, setSelectedOs }: { cert: CaCertificate, isRoot: boolean, t: any, selectedOs: string, setSelectedOs: (os: any) => void }) {
const [copied, setCopied] = useState(false);
const copyLinuxCli = () => {
if (!cert.linux_cdn_url) return;
const command = `curl -sL ${cert.linux_cdn_url} | sudo bash`;
navigator.clipboard.writeText(command);
setCopied(true);
setTimeout(() => setCopied(false), 2000);
};
return (
<div className="group relative bg-white/40 dark:bg-gray-900/40 backdrop-blur-xl rounded-[2.5rem] p-8 border border-white/50 dark:border-gray-800/50 shadow-xl hover:shadow-2xl transition-all duration-500 hover:-translate-y-1">
{/* Sync Status Badge */}
@@ -152,30 +167,30 @@ function CaCard({ cert, isRoot, t, selectedOs, setSelectedOs }: { cert: CaCertif
</div>
</div>
<div className="grid grid-cols-2 sm:grid-cols-4 gap-4">
<div className="grid grid-cols-2 lg:grid-cols-4 gap-3 sm:gap-4">
<DownloadBtn
href={cert.cdn_url || `/api/public/ca-certificates/${cert.serial}/download`}
label={t('download_standard')}
label={t('download_standard') || "PEM"}
icon={<FileIcon className="w-4 h-4" />}
onClick={() => {}}
/>
<DownloadBtn
href={cert.der_cdn_url || `/api/public/ca-certificates/${cert.serial}/download?format=der`}
label={t('download_android')}
label={t('download_android') || "Android/DER"}
icon={<MobileIcon className="w-4 h-4" />}
onClick={() => setSelectedOs('mobile')}
variant="green"
/>
<DownloadBtn
href={cert.bat_cdn_url || `/api/public/ca-certificates/${cert.serial}/download/windows`}
label={t('download_windows')}
label={t('download_windows') || "Windows"}
icon={<WindowsIcon className="w-4 h-4" />}
onClick={() => setSelectedOs('windows')}
variant="blue"
/>
<DownloadBtn
href={cert.mac_cdn_url || `/api/public/ca-certificates/${cert.serial}/download/mac`}
label={t('download_macos')}
label={t('download_macos') || "macOS"}
icon={<AppleIcon className="w-4 h-4" />}
onClick={() => setSelectedOs('macos')}
variant="gray"
@@ -183,15 +198,27 @@ function CaCard({ cert, isRoot, t, selectedOs, setSelectedOs }: { cert: CaCertif
</div>
{cert.linux_cdn_url && (
<div className="mt-4">
<div className="mt-4 flex gap-3">
<DownloadBtn
href={cert.linux_cdn_url || `/api/public/ca-certificates/${cert.serial}/download/linux`}
label={t('download_linux')}
label={t('download_linux') || "Linux (.sh)"}
icon={<LinuxIcon className="w-4 h-4" />}
onClick={() => setSelectedOs('linux')}
variant="gray"
isFullWidth
/>
<button
onClick={copyLinuxCli}
className={`flex items-center justify-center gap-2 px-6 py-3 rounded-2xl border font-bold text-xs transition-all duration-300 active:scale-95 ${
copied
? 'bg-green-500 text-white border-green-500 shadow-lg'
: 'bg-brand-500 text-white border-brand-500 hover:bg-brand-600 shadow-md hover:shadow-xl'
}`}
title="Copy CLI Command"
>
{copied ? <CheckIcon className="w-4 h-4" /> : <CopyIcon className="w-4 h-4" />}
{copied ? (t('copied') || "Copied!") : (t('copy_cli') || "Copy CLI")}
</button>
</div>
)}
</div>
@@ -251,6 +278,18 @@ const FileIcon = ({ className }: { className?: string }) => (
</svg>
);
const CopyIcon = ({ className }: { className?: string }) => (
<svg className={className} fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M8 5H6a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2v-1M8 5a2 2 0 002 2h2a2 2 0 002-2M8 5a2 2 0 012-2h2a2 2 0 012 2m0 0h2a2 2 0 012 2v3m2 4H10m0 0l3-3m-3 3l3 3" />
</svg>
);
const CheckIcon = ({ className }: { className?: string }) => (
<svg className={className} fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M5 13l4 4L19 7" />
</svg>
);
export default function HomeClient() {
const t = useTranslations("Home");
const [certificates, setCertificates] = useState<CaCertificate[]>([]);

View File

@@ -189,6 +189,8 @@
"download_windows_title": "Download Windows Installer (.bat)",
"download_macos_title": "Download macOS Profile (.mobileconfig)",
"download_linux_title": "Download Linux Installer (.sh)",
"copy_cli": "Copy CLI",
"copied": "Copied!",
"root_ca": "Root CA",
"intermediate_ca": "Intermediate CA",
"root_ca_hierarchy": "Root Trust Foundation",
@@ -210,9 +212,9 @@
"Go to 'About' > 'Certificate Trust Settings' and enable full trust."
],
"guide_steps_linux": [
"Download the .sh installer script.",
"Open terminal and run: sudo bash install-*.sh",
"The script will automatically detect and update your CA store."
"Use the one-liner command for instant setup (recommended):",
"curl -sL [URL] | sudo bash",
"Note: Get the [URL] by right-clicking the 'Linux' download button on the certificate card above."
],
"guide_steps_mobile": [
"Android: Settings > Security > Install from storage > CA Certificate.",

View File

@@ -189,6 +189,8 @@
"download_windows_title": "Unduh Penginstal Windows (.bat)",
"download_macos_title": "Unduh Profil macOS (.mobileconfig)",
"download_linux_title": "Unduh Penginstal Linux (.sh)",
"copy_cli": "Salin CLI",
"copied": "Tersalin!",
"root_ca": "Root CA",
"intermediate_ca": "Intermediate CA",
"root_ca_hierarchy": "Fondasi Kepercayaan Akar",
@@ -210,9 +212,9 @@
"Buka 'About' > 'Certificate Trust Settings' dan aktifkan kepercayaan penuh."
],
"guide_steps_linux": [
"Unduh skrip penginstal .sh.",
"Buka terminal dan jalankan: sudo bash install-*.sh",
"Skrip akan secara otomatis mendeteksi distro dan memperbarui penyimpanan CA Anda."
"Gunakan perintah satu-baris untuk instalasi instan (disarankan):",
"curl -sL [URL] | sudo bash",
"Catatan: Dapatkan [URL] dengan klik kanan tombol 'Linux' pada kartu sertifikat di atas lalu 'Salin Alamat Link'."
],
"guide_steps_mobile": [
"Android: Pengaturan > Keamanan > Instal dari penyimpanan > Sertifikat CA.",