From 6de9b2422957d95c7bc24b265911cccefb3314e9 Mon Sep 17 00:00:00 2001 From: Abdalrahman Date: Wed, 13 May 2026 02:02:48 +0300 Subject: [PATCH 01/33] fix: preserve space between date and time in log modal (#4326) Vue 3's whitespace: condense strips bare whitespace text nodes and trailing whitespace inside elements, causing the <template> trick to fail. Use mustache interpolations (which compile to _createTextVNode) for all spacing between fields so they survive compilation. --- frontend/src/pages/index/LogModal.vue | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/frontend/src/pages/index/LogModal.vue b/frontend/src/pages/index/LogModal.vue index a385a919..2fbe0c5a 100644 --- a/frontend/src/pages/index/LogModal.vue +++ b/frontend/src/pages/index/LogModal.vue @@ -53,7 +53,9 @@ function parseLogLine(line) { service = 'X-UI:'; } - return { date, time, levelText, levelClass, service, body }; + const stamp = [date, time].filter(Boolean).join(' '); + + return { date, time, stamp, levelText, levelClass, service, body }; } const parsedLogs = computed(() => logs.value.map(parseLogLine)); @@ -133,33 +135,25 @@ const modalWidth = computed(() => (isMobile.value ? '100vw' : '800px')); From 48e90bba51426f96f0843f1abc3c3cd69adb50ff Mon Sep 17 00:00:00 2001 From: Abdalrahman Date: Wed, 13 May 2026 02:12:25 +0300 Subject: [PATCH 02/33] fix: show UDP tag for Hysteria and fix client count spacing (#4318) --- frontend/src/models/dbinbound.js | 4 ++++ frontend/src/pages/inbounds/InboundList.vue | 26 ++++++++++++--------- 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/frontend/src/models/dbinbound.js b/frontend/src/models/dbinbound.js index e2e0adfe..d7a9483e 100644 --- a/frontend/src/models/dbinbound.js +++ b/frontend/src/models/dbinbound.js @@ -70,6 +70,10 @@ export class DBInbound { return this.protocol === Protocols.WIREGUARD; } + get isHysteria() { + return this.protocol === Protocols.HYSTERIA; + } + get address() { let address = location.hostname; if (!ObjectUtil.isEmpty(this.listen) && this.listen !== "0.0.0.0") { diff --git a/frontend/src/pages/inbounds/InboundList.vue b/frontend/src/pages/inbounds/InboundList.vue index c425ced5..30ffcc68 100644 --- a/frontend/src/pages/inbounds/InboundList.vue +++ b/frontend/src/pages/inbounds/InboundList.vue @@ -395,8 +395,8 @@ function showQrCodeMenu(dbInbound) {
{{ t('pages.inbounds.protocol') }} {{ record.protocol }} - + + + + diff --git a/sub/subJsonService.go b/sub/subJsonService.go index fc35698e..4fe77b88 100644 --- a/sub/subJsonService.go +++ b/sub/subJsonService.go @@ -447,6 +447,9 @@ func (s *SubJsonService) genHy(inbound *model.Inbound, newStream map[string]any, if udpIdleTimeout, ok := hyStream["udpIdleTimeout"].(float64); ok { outHyStream["udpIdleTimeout"] = int(udpIdleTimeout) } + if masquerade, ok := hyStream["masquerade"].(map[string]any); ok { + outHyStream["masquerade"] = masquerade + } newStream["hysteriaSettings"] = outHyStream if finalmask, ok := hyStream["finalmask"].(map[string]any); ok { From 9f7e8178d46dde2398b0729e50fbd8faeb8ec37a Mon Sep 17 00:00:00 2001 From: Abdalrahman Date: Wed, 13 May 2026 02:27:10 +0300 Subject: [PATCH 05/33] fix: delete button missing after searching for a user (#4315) When searching for a user, the projected DBInbound only contains the matching clients, so isRemovable evaluated to alse (since a single match made clients.value.length === 1), hiding the Delete button. Pass the original total client count from the parent's clientCount prop and use it in the isRemovable check instead of the projected clients array length. --- frontend/src/pages/inbounds/ClientRowTable.vue | 3 ++- frontend/src/pages/inbounds/InboundList.vue | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/frontend/src/pages/inbounds/ClientRowTable.vue b/frontend/src/pages/inbounds/ClientRowTable.vue index f6119323..dc4b8b84 100644 --- a/frontend/src/pages/inbounds/ClientRowTable.vue +++ b/frontend/src/pages/inbounds/ClientRowTable.vue @@ -32,6 +32,7 @@ const props = defineProps({ lastOnlineMap: { type: Object, default: () => ({}) }, isDarkTheme: { type: Boolean, default: false }, pageSize: { type: Number, default: 0 }, + totalClientCount: { type: Number, default: 0 }, }); const emit = defineEmits([ @@ -138,7 +139,7 @@ function statsExpColor(email) { return PURPLE; } -const isRemovable = computed(() => clients.value.length > 1); +const isRemovable = computed(() => (props.totalClientCount || clients.value.length) > 1); function totalGbDisplay(client) { if (!client.totalGB || client.totalGB <= 0) return ''; diff --git a/frontend/src/pages/inbounds/InboundList.vue b/frontend/src/pages/inbounds/InboundList.vue index 30ffcc68..38465818 100644 --- a/frontend/src/pages/inbounds/InboundList.vue +++ b/frontend/src/pages/inbounds/InboundList.vue @@ -457,7 +457,7 @@ function showQrCodeMenu(dbInbound) {
Date: Wed, 13 May 2026 02:47:09 +0300 Subject: [PATCH 06/33] feat(api-docs): enhance in-panel API documentation (#4312) * feat(api-docs): enhance API documentation with missing endpoints, search, collapse, and route sync test - Add 29 undocumented routes across 4 new sections (Settings, Xray Settings, Subscription Server, WebSocket) plus 4 missing Server API endpoints - Fix inaccuracies: history metric keys, node metric keys, VLESS enc description - Add response schemas to 15+ key endpoints - Add search bar and expand/collapse all controls to the docs page - Add collapsible endpoint sections with endpoint count - Add Go test (TestAPIRoutesDocumented) to verify all Go routes are documented * feat(api-docs): add JSON syntax highlighting and top-right copy button to code blocks * fix(api-docs): use distinct colors for JSON syntax highlighting (green strings, amber numbers) * feat(api-docs): add request body examples, error responses, WebSocket message types, and subscription response headers * fix(api-docs): use ClipboardManager.copyText instead of copy to fix API token copy button --- frontend/src/pages/api-docs/ApiDocsPage.vue | 109 +++++- frontend/src/pages/api-docs/CodeBlock.vue | 152 ++++++++ frontend/src/pages/api-docs/EndpointRow.vue | 26 +- .../src/pages/api-docs/EndpointSection.vue | 105 +++++- frontend/src/pages/api-docs/endpoints.js | 335 +++++++++++++++++- web/controller/api_docs_test.go | 160 +++++++++ 6 files changed, 859 insertions(+), 28 deletions(-) create mode 100644 frontend/src/pages/api-docs/CodeBlock.vue create mode 100644 web/controller/api_docs_test.go diff --git a/frontend/src/pages/api-docs/ApiDocsPage.vue b/frontend/src/pages/api-docs/ApiDocsPage.vue index 28fee7b4..9a5f958e 100644 --- a/frontend/src/pages/api-docs/ApiDocsPage.vue +++ b/frontend/src/pages/api-docs/ApiDocsPage.vue @@ -1,5 +1,5 @@ + + + + + + diff --git a/frontend/src/pages/api-docs/EndpointRow.vue b/frontend/src/pages/api-docs/EndpointRow.vue index 0b7fb300..761e4a88 100644 --- a/frontend/src/pages/api-docs/EndpointRow.vue +++ b/frontend/src/pages/api-docs/EndpointRow.vue @@ -1,6 +1,7 @@