From 2a96ac9721d0e82ac1cf0d06d8a5982ba4ce1a75 Mon Sep 17 00:00:00 2001 From: MHSanaei Date: Fri, 22 May 2026 03:05:55 +0200 Subject: [PATCH] =?UTF-8?q?fix(frontend):=20qr=20code=20collapse=20?= =?UTF-8?q?=E2=80=94=20open=20only=20first=20panel,=20allow=20toggle?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ClientQrModal and QrCodeModal both used activeKey without onChange, forcing every panel open and blocking user toggle. Switch to controlled state initialized to the first item's key on open, with onChange so clicks update state. Also remove unused AppBridge.tsx (superseded by per-page message.useMessage hook). --- frontend/src/components/AppBridge.tsx | 11 --------- frontend/src/pages/clients/ClientQrModal.tsx | 24 +++++++++++++------- frontend/src/pages/inbounds/QrCodeModal.tsx | 15 ++++++++---- 3 files changed, 27 insertions(+), 23 deletions(-) delete mode 100644 frontend/src/components/AppBridge.tsx diff --git a/frontend/src/components/AppBridge.tsx b/frontend/src/components/AppBridge.tsx deleted file mode 100644 index f8d05786..00000000 --- a/frontend/src/components/AppBridge.tsx +++ /dev/null @@ -1,11 +0,0 @@ -import { useEffect } from 'react'; -import { App } from 'antd'; -import { setMessageInstance } from '@/utils/messageBus'; - -export default function AppBridge({ children }: { children: React.ReactNode }) { - const { message } = App.useApp(); - useEffect(() => { - setMessageInstance(message); - }, [message]); - return <>{children}; -} diff --git a/frontend/src/pages/clients/ClientQrModal.tsx b/frontend/src/pages/clients/ClientQrModal.tsx index 731489ee..6263414a 100644 --- a/frontend/src/pages/clients/ClientQrModal.tsx +++ b/frontend/src/pages/clients/ClientQrModal.tsx @@ -71,13 +71,7 @@ export default function ClientQrModal({ return () => { cancelled = true; }; }, [open, client?.subId]); - const activeKeys = useMemo(() => { - const keys: string[] = []; - if (subLink) keys.push('sub'); - if (subJsonLink) keys.push('subJson'); - if (links.length > 0) keys.push('l0'); - return keys; - }, [subLink, subJsonLink, links.length]); + const [activeKey, setActiveKey] = useState([]); const items = useMemo(() => { const out: { key: string; label: string; children: React.ReactNode }[] = []; @@ -105,6 +99,14 @@ export default function ClientQrModal({ return out; }, [subLink, subJsonLink, links, client?.email, t]); + useEffect(() => { + if (!open) { + setActiveKey([]); + return; + } + setActiveKey(items.length > 0 ? [items[0].key] : []); + }, [open, items]); + return ( {t('pages.clients.noLinks')} )} - {hasAnything && } + {hasAnything && ( + setActiveKey(typeof keys === 'string' ? [keys] : (keys as string[]))} + items={items} + /> + )} ); diff --git a/frontend/src/pages/inbounds/QrCodeModal.tsx b/frontend/src/pages/inbounds/QrCodeModal.tsx index 7eed15dd..f4fae390 100644 --- a/frontend/src/pages/inbounds/QrCodeModal.tsx +++ b/frontend/src/pages/inbounds/QrCodeModal.tsx @@ -57,7 +57,7 @@ export default function QrCodeModal({ const [wireguardLinks, setWireguardLinks] = useState([]); const [subLink, setSubLink] = useState(''); const [subJsonLink, setSubJsonLink] = useState(''); - const [defaultActive, setDefaultActive] = useState([]); + const [activeKey, setActiveKey] = useState([]); useEffect(() => { if (!open || !dbInbound) return; @@ -84,7 +84,6 @@ export default function QrCodeModal({ } setSubLink(nextSub); setSubJsonLink(nextSubJson); - setDefaultActive(nextSub ? ['sub'] : []); }, [open, dbInbound, client, remarkModel, nodeAddress, subSettings]); const qrItems = useMemo(() => { @@ -128,13 +127,21 @@ export default function QrCodeModal({ [qrItems], ); + useEffect(() => { + if (!open) { + setActiveKey([]); + return; + } + setActiveKey(qrItems.length > 0 ? [qrItems[0].key] : []); + }, [open, qrItems]); + return ( {dbInbound && collapseItems && collapseItems.length > 0 && ( i?.key).join('|')} ghost - defaultActiveKey={defaultActive} + activeKey={activeKey} + onChange={(keys) => setActiveKey(typeof keys === 'string' ? [keys] : (keys as string[]))} items={collapseItems} /> )}