diff options
| author | lolka1333 <xtrafcyz@gmail.com> | 2026-01-03 07:26:00 +0300 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-01-03 07:26:00 +0300 |
| commit | 313a2acbf66125feb4b145a5636351ed03e666da (patch) | |
| tree | 6be6fac0ced2d0dce60ba55e2feaa83c257ed720 /web/html/modals | |
| parent | b7477302112b43a2ae037b63994c59e85f9c0687 (diff) | |
feat: Add WebSocket support for real-time updates and enhance VLESS settings (#3605)
* feat: add support for trusted X-Forwarded-For and testseed parameters in VLESS settings
* chore: update Xray Core version to 25.12.8 in release workflow
* chore: update Xray Core version to 25.12.8 in Docker initialization script
* chore: bump version to 2.8.6 and add watcher for security changes in inbound modal
* refactor: remove default and random seed buttons from outbound form
* refactor: update VLESS form to rename 'Test Seed' to 'Vision Seed' and change button functionality for seed generation
* refactor: enhance TLS settings form layout with improved button styling and spacing
* feat: integrate WebSocket support for real-time updates on inbounds and Xray service status
* chore: downgrade version to 2.8.5
* refactor: translate comments to English
* fix: ensure testseed is initialized correctly for VLESS protocol and improve client handling in inbound modal
* refactor: simplify VLESS divider condition by removing unnecessary flow checks
* fix: add fallback date formatting for cases when IntlUtil is not available
* refactor: simplify WebSocket message handling by removing batching and ensuring individual message delivery
* refactor: disable WebSocket notifications in inbound and index HTML files
* refactor: enhance VLESS testseed initialization and button functionality in inbound modal
* fix:
* refactor: ensure proper WebSocket URL construction by normalizing basePath
* fix:
* fix:
* fix:
* refactor: update testseed methods for improved reactivity and binding in VLESS form
* logger info to debug
---------
Co-authored-by: lolka1333 <test123@gmail.com>
Diffstat (limited to 'web/html/modals')
| -rw-r--r-- | web/html/modals/inbound_modal.html | 94 |
1 files changed, 90 insertions, 4 deletions
diff --git a/web/html/modals/inbound_modal.html b/web/html/modals/inbound_modal.html index 3c844381..c3883285 100644 --- a/web/html/modals/inbound_modal.html +++ b/web/html/modals/inbound_modal.html @@ -6,7 +6,8 @@ </a-modal> <script> - const inModal = { + // Make inModal globally available to ensure it works with any base path + const inModal = window.inModal = { title: '', visible: false, confirmLoading: false, @@ -26,6 +27,14 @@ } else { this.inbound = new Inbound(); } + // Always ensure testseed is initialized for VLESS protocol (even if vision flow is not set yet) + // This ensures Vue reactivity works properly + if (this.inbound.protocol === Protocols.VLESS && this.inbound.settings) { + if (!this.inbound.settings.testseed || !Array.isArray(this.inbound.settings.testseed) || this.inbound.settings.testseed.length < 4) { + // Create a new array to ensure Vue reactivity + this.inbound.settings.testseed = [900, 500, 900, 256].slice(); + } + } if (dbInbound) { this.dbInbound = new DBInbound(dbInbound); } else { @@ -42,9 +51,43 @@ loading(loading = true) { inModal.confirmLoading = loading; }, + // Vision Seed methods - always available regardless of Vue context + updateTestseed(index, value) { + // Use inModal.inbound explicitly to ensure correct context + if (!inModal.inbound || !inModal.inbound.settings) return; + // Ensure testseed is initialized + if (!inModal.inbound.settings.testseed || !Array.isArray(inModal.inbound.settings.testseed)) { + inModal.inbound.settings.testseed = [900, 500, 900, 256]; + } + // Ensure array has enough elements + while (inModal.inbound.settings.testseed.length <= index) { + inModal.inbound.settings.testseed.push(0); + } + // Update value + inModal.inbound.settings.testseed[index] = value; + }, + setRandomTestseed() { + // Use inModal.inbound explicitly to ensure correct context + if (!inModal.inbound || !inModal.inbound.settings) return; + // Ensure testseed is initialized + if (!inModal.inbound.settings.testseed || !Array.isArray(inModal.inbound.settings.testseed) || inModal.inbound.settings.testseed.length < 4) { + inModal.inbound.settings.testseed = [900, 500, 900, 256].slice(); + } + // Create new array with random values + inModal.inbound.settings.testseed = [Math.floor(Math.random()*1000), Math.floor(Math.random()*1000), Math.floor(Math.random()*1000), Math.floor(Math.random()*1000)]; + }, + resetTestseed() { + // Use inModal.inbound explicitly to ensure correct context + if (!inModal.inbound || !inModal.inbound.settings) return; + // Reset testseed to default values + inModal.inbound.settings.testseed = [900, 500, 900, 256].slice(); + } }; - new Vue({ + // Store Vue instance globally to ensure methods are always accessible + let inboundModalVueInstance = null; + + inboundModalVueInstance = new Vue({ delimiters: ['[[', ']]'], el: '#inbound-modal', data: { @@ -60,7 +103,7 @@ return inModal.isEdit; }, get client() { - return inModal.inbound.clients[0]; + return inModal.inbound && inModal.inbound.clients && inModal.inbound.clients.length > 0 ? inModal.inbound.clients[0] : null; }, get datepicker() { return app.datepicker; @@ -87,6 +130,28 @@ } } }, + watch: { + 'inModal.inbound.stream.security'(newVal, oldVal) { + // Clear flow when security changes from reality/tls to none + if (inModal.inbound.protocol == Protocols.VLESS && !inModal.inbound.canEnableTlsFlow()) { + inModal.inbound.settings.vlesses.forEach(client => { + client.flow = ""; + }); + } + }, + // Ensure testseed is always initialized when vision flow is enabled + 'inModal.inbound.settings.vlesses': { + handler() { + if (inModal.inbound.protocol === Protocols.VLESS && inModal.inbound.settings && inModal.inbound.settings.vlesses) { + const hasVisionFlow = inModal.inbound.settings.vlesses.some(c => c.flow === 'xtls-rprx-vision' || c.flow === 'xtls-rprx-vision-udp443'); + if (hasVisionFlow && (!inModal.inbound.settings.testseed || !Array.isArray(inModal.inbound.settings.testseed) || inModal.inbound.settings.testseed.length < 4)) { + inModal.inbound.settings.testseed = [900, 500, 900, 256]; + } + } + }, + deep: true + } + }, methods: { streamNetworkChange() { if (!inModal.inbound.canEnableTls()) { @@ -204,8 +269,29 @@ this.inbound.settings.decryption = 'none'; this.inbound.settings.encryption = 'none'; this.inbound.settings.selectedAuth = undefined; + }, + // Vision Seed methods - must be in Vue methods for proper binding + updateTestseed(index, value) { + // Ensure testseed is initialized + if (!this.inbound.settings.testseed || !Array.isArray(this.inbound.settings.testseed)) { + this.$set(this.inbound.settings, 'testseed', [900, 500, 900, 256]); + } + // Ensure array has enough elements + while (this.inbound.settings.testseed.length <= index) { + this.inbound.settings.testseed.push(0); + } + // Update value using Vue.set for reactivity + this.$set(this.inbound.settings.testseed, index, value); + }, + setRandomTestseed() { + // Create new array with random values and use Vue.set for reactivity + const newSeed = [Math.floor(Math.random()*1000), Math.floor(Math.random()*1000), Math.floor(Math.random()*1000), Math.floor(Math.random()*1000)]; + this.$set(this.inbound.settings, 'testseed', newSeed); + }, + resetTestseed() { + // Reset testseed to default values using Vue.set for reactivity + this.$set(this.inbound.settings, 'testseed', [900, 500, 900, 256]); } - }, }); |
