From f68a14a3cafe3b4b73d67df2aea6dbd2ad2b2df8 Mon Sep 17 00:00:00 2001 From: MHSanaei Date: Sat, 9 May 2026 23:17:31 +0200 Subject: [PATCH] fix(xray): align DNS outbound to spec and repair item-list rules UI DNS outbound now mirrors xray-core's documented shape: rewriteNetwork / rewriteAddress / rewritePort / userLevel replace the legacy network / address / port keys, and unset values are dropped on the wire. Old configs are still accepted on read so saved configs migrate cleanly. While there, fix two latent bugs in repeat-item editors (DNS rules, Freedom noise, WireGuard peers): - The "+" buttons pushed plain objects into arrays of class instances, so toJson() crashed on the next read and the JSON tab silently went blank. Push proper class instances instead. - Each item heading lived outside any a-form-item, so the delete icon ignored the form's column grid and slumped left. Wrap the heading in a form-item with the standard offset wrapper-col and switch the flex to space-between so the icon sits at the right of the input column, in line with the fields below it. --- frontend/src/models/outbound.js | 41 ++++++------- frontend/src/pages/xray/OutboundFormModal.vue | 58 ++++++++++++------- frontend/src/pages/xray/OutboundsTab.vue | 7 ++- 3 files changed, 63 insertions(+), 43 deletions(-) diff --git a/frontend/src/models/outbound.js b/frontend/src/models/outbound.js index 645f6100..b6ed8df2 100644 --- a/frontend/src/models/outbound.js +++ b/frontend/src/models/outbound.js @@ -1292,7 +1292,6 @@ export class Outbound extends CommonClass { hasAddressPort() { return [ - Protocols.DNS, Protocols.VMess, Protocols.VLESS, Protocols.Trojan, @@ -1846,15 +1845,17 @@ Outbound.DNSRule = class extends CommonClass { Outbound.DNSSettings = class extends CommonClass { constructor( - network = 'udp', - address = '', - port = 53, + rewriteNetwork = '', + rewriteAddress = '', + rewritePort = 53, + userLevel = 0, rules = [] ) { super(); - this.network = network; - this.address = address; - this.port = port; + this.rewriteNetwork = rewriteNetwork; + this.rewriteAddress = rewriteAddress; + this.rewritePort = rewritePort; + this.userLevel = userLevel; this.rules = Array.isArray(rules) ? rules.map(rule => rule instanceof Outbound.DNSRule ? rule : Outbound.DNSRule.fromJson(rule)) : []; } @@ -1867,25 +1868,25 @@ Outbound.DNSSettings = class extends CommonClass { } static fromJson(json = {}) { + // Spec uses rewrite{Network,Address,Port}; older configs used the + // bare network/address/port keys — accept both so existing saved + // configs keep working after the migration. return new Outbound.DNSSettings( - json.network, - json.address, - json.port, + json.rewriteNetwork ?? json.network ?? '', + json.rewriteAddress ?? json.address ?? '', + Number(json.rewritePort ?? json.port ?? 53) || 53, + Number(json.userLevel ?? 0) || 0, getDNSRulesFromJson(json), ); } toJson() { - const json = { - network: this.network, - address: this.address, - port: this.port, - }; - - if (this.rules.length > 0) { - json.rules = Outbound.DNSRule.toJsonArray(this.rules); - } - + const json = {}; + if (!ObjectUtil.isEmpty(this.rewriteNetwork)) json.rewriteNetwork = this.rewriteNetwork; + if (!ObjectUtil.isEmpty(this.rewriteAddress)) json.rewriteAddress = this.rewriteAddress; + if (this.rewritePort > 0) json.rewritePort = this.rewritePort; + if (this.userLevel > 0) json.userLevel = this.userLevel; + if (this.rules.length > 0) json.rules = Outbound.DNSRule.toJsonArray(this.rules); return json; } }; diff --git a/frontend/src/pages/xray/OutboundFormModal.vue b/frontend/src/pages/xray/OutboundFormModal.vue index b49c3c31..f058d5eb 100644 --- a/frontend/src/pages/xray/OutboundFormModal.vue +++ b/frontend/src/pages/xray/OutboundFormModal.vue @@ -268,21 +268,23 @@ function regenerateWgKeys() { + @change="(checked) => outbound.settings.noises = checked ? [new Outbound.FreedomSettings.Noise()] : []" /> + @click="outbound.settings.noises.push(new Outbound.FreedomSettings.Noise())">