From 1752702f74ae04e60eca7b7d60f75edc02150771 Mon Sep 17 00:00:00 2001 From: MHSanaei Date: Wed, 27 May 2026 03:12:05 +0200 Subject: [PATCH] feat(clients): hide QR for post-quantum links in client info modal MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Post-quantum keys (mldsa65 / ML-KEM-768) blow the encoded URL past what a single QR can hold. Detect them by the markers VLESS share links actually carry — `pqv=` for mldsa65Verify and `encryption=mlkem768x25519plus.*` for ML-KEM-768 — and drop the QR button for those rows. Copy still works. --- .../src/pages/clients/ClientInfoModal.tsx | 37 ++++++++++++++----- 1 file changed, 27 insertions(+), 10 deletions(-) diff --git a/frontend/src/pages/clients/ClientInfoModal.tsx b/frontend/src/pages/clients/ClientInfoModal.tsx index 5e755fd1..4a500a28 100644 --- a/frontend/src/pages/clients/ClientInfoModal.tsx +++ b/frontend/src/pages/clients/ClientInfoModal.tsx @@ -33,6 +33,20 @@ const INBOUND_PROTOCOL_COLORS: Record = { const INBOUND_CHIP_LIMIT = 1; +// Post-quantum keys blow up the encoded URL past what a single QR can +// hold. In VLESS share links the algorithm names don't appear as plain +// text — they ride inside query params: +// - mldsa65Verify becomes `pqv=` (sub/subService.go:841) +// - ML-KEM-768 becomes `encryption=mlkem768x25519plus.<...>` +// We also keep the literal substrings so configs that DO embed them +// directly (e.g. wireguard config text) still match. +function isPostQuantumLink(link: string): boolean { + if (/[?&]pqv=/.test(link)) return true; + if (link.includes('mlkem768') || link.includes('mldsa65')) return true; + if (link.includes('ML-KEM-768')) return true; + return false; +} + // 3x-ui's genRemark concatenates inbound remark + client email (and an // optional extra) using a configurable separator. The email half is // redundant in the row title — the modal already names the client by @@ -356,6 +370,7 @@ export default function ClientInfoModal({ const qrRemark = meta.remark || `${t('pages.clients.link')} ${idx + 1}`; const rowTitle = trimEmail(meta.remark, client.email) || `${t('pages.clients.link')} ${idx + 1}`; + const canQr = !isPostQuantumLink(link); return (
@@ -366,16 +381,18 @@ export default function ClientInfoModal({
);