feat: Adjust Vless node filtering logic to conditionally display internal agent nodes in sandbox mode for the QR card and agent list.

This commit is contained in:
Haitao Pan 2026-02-06 18:35:41 +08:00
parent b4b932eea4
commit c9ff466609
2 changed files with 22 additions and 2 deletions

View File

@ -70,10 +70,19 @@ export default function VlessQrCard({
const nodes = useMemo(() => {
return (allNodes ?? []).filter((node) => {
const name = (node.name || '').toLowerCase()
const address = (node.address || '').trim()
if (!address || address === '*') return false
if (allowSandboxFallbackNode) {
// In sandbox mode, allow internal agents so the user can see their bound node
// even if it belongs to the shared token bucket.
return true
}
// Skip the redundant Internal Agents (Shared Token) node
return !(name.includes('internal agents') && name.includes('shared token'))
})
}, [allNodes])
}, [allNodes, allowSandboxFallbackNode])
const [selectedNode, setSelectedNode] = useState<VlessNode | null>(null)
const [preferredTransport, setPreferredTransport] = useState<VlessTransport>('tcp')
const [isSelectorOpen, setIsSelectorOpen] = useState(false)

View File

@ -10,6 +10,7 @@ import { translations } from '@i18n/translations'
import { useUserStore } from '@lib/userStore'
import { fetchSandboxNodeBinding } from '../lib/sandboxNodeBinding'
interface VlessNode {
name: string
address: string
@ -61,12 +62,22 @@ export default function UserCenterAgentRoute() {
const t = translations[language].userCenter
const user = useUserStore((state) => state.user)
const { data: nodes, error, isLoading, mutate } = useSWR<VlessNode[]>('/api/agent-server/v1/nodes', fetcher)
const visibleNodes = useMemo(() => (nodes ?? []).filter(isDisplayableNode), [nodes])
const [boundNode, setBoundNode] = useState<VlessNode | null>(null)
const normalizedEmail = user?.email?.toLowerCase() ?? ''
const isGuestSandboxReadOnly = Boolean(
user?.isReadOnly && (normalizedEmail === 'sandbox@svc.plus' || normalizedEmail === 'demo@svc.plus'),
)
const visibleNodes = useMemo(() => {
return (nodes ?? []).filter((node) => {
if (isGuestSandboxReadOnly) {
// In sandbox mode, allow internal agents so the user can see their bound node
// even if it belongs to the shared token bucket.
const address = (node.address || '').trim()
return address && address !== '*'
}
return isDisplayableNode(node)
})
}, [nodes, isGuestSandboxReadOnly])
const [boundAddress, setBoundAddress] = useState<string | null>(null)
useEffect(() => {