瀏覽代碼

fix(frontend): Outbound submit crash on non-mux protocols + tab a11y (B21)

Two issues surfaced on Outbound save:

1. Crash: `Cannot read properties of undefined (reading 'enabled')` at
   formValuesToWirePayload. The modal hides the Mux switch entirely
   for non-stream protocols (dns/freedom/blackhole/loopback) and for
   stream protocols when isMuxAllowed gates it out (xhttp, vless+flow).
   With the field never registered, validateFields() returns no `mux`
   key — `values.mux.enabled` then dereferences undefined.
   Fix: optional chain `values.mux?.enabled` so missing mux skips the
   mux clause silently. Documented why mux can be absent.

2. Chrome a11y warning: "Blocked aria-hidden on an element because its
   descendant retained focus" — when the user has an input focused
   inside one Tab panel and switches to another tab, AntD marks the
   outgoing panel aria-hidden while focus is still inside. The browser
   warns, but the focused control is now invisible to AT users.
   Fix: blur the active element before setActiveKey in onTabChange.
MHSanaei 23 小時之前
父節點
當前提交
d2f5f530e0
共有 2 個文件被更改,包括 11 次插入1 次删除
  1. 4 1
      frontend/src/lib/xray/outbound-form-adapter.ts
  2. 7 0
      frontend/src/pages/xray/OutboundFormModal.tsx

+ 4 - 1
frontend/src/lib/xray/outbound-form-adapter.ts

@@ -620,7 +620,10 @@ export function formValuesToWirePayload(values: OutboundFormValues): WireOutboun
   }
 
   if (values.sendThrough) result.sendThrough = values.sendThrough;
-  if (values.mux.enabled && muxAllowed(values)) {
+  // mux may be absent when the modal didn't render the Mux switch (non-
+  // stream protocols or when isMuxAllowed gated it out). validateFields()
+  // only returns registered fields, so values.mux can be undefined.
+  if (values.mux?.enabled && muxAllowed(values)) {
     result.mux = values.mux;
   }
   return result;

+ 7 - 0
frontend/src/pages/xray/OutboundFormModal.tsx

@@ -372,6 +372,13 @@ export default function OutboundFormModal({
     if (key === '1' && activeKey === '2') {
       if (!applyJsonToForm()) return;
     }
+    // Blur the currently focused element before AntD marks the outgoing
+    // tab panel aria-hidden. Without this, a focused input inside the
+    // hidden panel triggers a Chrome a11y warning ("Blocked aria-hidden
+    // on an element because its descendant retained focus").
+    if (typeof document !== 'undefined') {
+      (document.activeElement as HTMLElement | null)?.blur?.();
+    }
     setActiveKey(key);
   }