Selaa lähdekoodia

fix(ui): make the Happy Eyeballs toggle produce a config xray actually enables

Toggling Happy Eyeballs on filled the object with schema defaults, and
tryDelayMs defaulted to 0. That broke the feature twice over: xray-core
treats tryDelayMs=0 as happy-eyeballs-off, and the wire normalizer
strips every field that equals its default, leaving an empty object it
then deletes - so the switch silently flipped back off on reopen (the
"disabled when Prefer IPv6 is off" symptom; prioritizeIPv6=true was the
one non-default that let the object survive). Default tryDelayMs to the
recommended 250ms so an enabled config survives serialization and is
functional in the core.

Closes #5780
MHSanaei 1 päivä sitten
vanhempi
sitoutus
579a9daaa0

+ 1 - 1
frontend/src/schemas/protocols/stream/sockopt.ts

@@ -33,7 +33,7 @@ export const AddressPortStrategySchema = z.enum([
 export type AddressPortStrategy = z.infer<typeof AddressPortStrategySchema>;
 
 export const HappyEyeballsSchema = z.object({
-  tryDelayMs: z.number().int().min(0).default(0),
+  tryDelayMs: z.number().int().min(0).default(250),
   prioritizeIPv6: z.boolean().default(false),
   interleave: z.number().int().min(1).default(1),
   maxConcurrentTry: z.number().int().min(0).default(4),

+ 9 - 0
frontend/src/test/stream-wire-normalize.test.ts

@@ -10,6 +10,7 @@ import {
   validateRealityTarget,
 } from '@/lib/xray/stream-wire-normalize';
 import { InboundFormSchema } from '@/schemas/forms/inbound-form';
+import { HappyEyeballsSchema } from '@/schemas/protocols/stream/sockopt';
 import type { InboundFormValues } from '@/schemas/forms/inbound-form';
 import { XHttpXmuxSchema } from '@/schemas/protocols/stream/xhttp';
 
@@ -204,6 +205,14 @@ describe('normalizeSockoptForWire', () => {
     });
     expect(out?.domainStrategy).toBe('UseIP');
   });
+
+  it('keeps a freshly toggled happyEyeballs (schema defaults) across the wire round trip', () => {
+    const out = normalizeSockoptForWire({
+      happyEyeballs: HappyEyeballsSchema.parse({}),
+    });
+
+    expect(out?.happyEyeballs).toEqual({ tryDelayMs: 250 });
+  });
 });
 
 describe('normalizeStreamSettingsForWire reality', () => {