Modal close: BalancersTab / OutboundsTab / RoutingTab confirmDelete used
arrow expressions that returned splice's removed-items array. AD-Vue 4
treats truthy non-thenables from onOk as "still pending" and never closes
the dialog (see ActionButton.js:103-106), so the confirm modal stayed
open. Wrap the body so onOk returns undefined and AD-Vue auto-closes.
Tag validation: outbound + balancer modals only flipped between
warning/success on duplicate, leaving the empty case as a green ✓.
Split into a 3-state computed — error (empty) / warning (duplicate) /
success — and wire a help message so the input clearly explains why
the OK button is disabled.
Reset to default: re-add the legacy "Reset to Default" panel at the
bottom of BasicsTab. Calls /panel/setting/getDefaultJsonConfig and
overwrites templateSettings; the existing watch re-stringifies so the
JSON tab + dirty-poll see the new state.
Restored Basics option lists from main: IPs (4→10, +Vietnam/Spain/
Indonesia/Ukraine/Türkiye/Brazil), DomainsOptions (4→10, +regex
entries), BlockDomainsOptions (5→17, +Malware/Phishing/Adult/regex),
ServicesOptions (Reddit/Speedtest in, off-template Microsoft out).
Outbound form parity with main:
• Reverse Sniffing UI for VLESS — toggle + destOverride checkboxes
(HTTP/TLS/QUIC/FAKEDNS) + Metadata/Route Only + IPs/Domains
excluded multi-selects, gated on reverseTag being set.
• Full XHTTP transport — request headers list, Max Upload Size /
Min Upload Interval (packet-up), Padding Obfs Mode + sub-fields,
Uplink HTTP Method, Session/Sequence/UplinkData placement +
keys, No gRPC Header (stream-up/stream-one), expanded XMUX with
Max Concurrency/Connections/Reuse/Request/Reusable/Keep-alive.
Strip a-divider from the outbound form per request — replaced with
plain section/item heading divs so the labels and per-row delete
icons stay but the horizontal rule is gone.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The light-theme --bg-page was #f0f2f5 — close enough to AD-Vue's #fff
card background that the cards faded into the page. Bump it to #e6e8ec
(a more visibly distinct gray) so cards lift cleanly off the surface.
Dark and ultra-dark stay where they were.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
When 5f1aba28 dropped the local antdThemeConfig computed (now shared
from useTheme), it also stripped `computed` from the import list — but
both pages still call computed() elsewhere (confAlerts, advanced-tab
helpers). Re-adds it.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The legacy panel CSS (custom.min.css ported as legacy.css) tinted every
non-primary button teal-green via .dark .ant-btn:not(.ant-btn-primary)
overrides while AD-Vue 4's darkAlgorithm kept primary buttons blue —
producing the mixed blue/green button look on dark mode. Drop legacy.css
entirely and let AD-Vue 4's algorithms own the palette.
Centralize antdThemeConfig in useTheme.js so every page resolves to the
same source of truth (light = defaultAlgorithm, dark = darkAlgorithm,
ultra-dark = darkAlgorithm + deeper colorBgBase/Layout/Container/
Elevated tokens). Each page's <a-config-provider> now imports the
shared computed instead of defining its own copy.
Drops the 67 KB legacy CSS chunk; per-page CSS bundles fall to ≤5.9 KB.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The Basics tab already exposes this field through BasicsTab —
duplicating it on the Advanced tab let two inputs race the same
ref and only added clutter.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Continues the page-by-page translation pass started in cb37dd55 — runs
every user-visible string on settings (General/Security/Telegram/Sub),
inbounds (Client/QR/Info modals), and xray (Routing/Balancer/Rule/Warp/
Nord/Basics/Outbounds tabs) through useI18n. Updates the TOML→JSON sync
script to escape `@` (vue-i18n parses it as a linked-format prefix) and
refreshes all 13 locale files.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Replaces hardcoded English with t() calls in the components every
user sees on every page load. The translations themselves come from
the existing TOML files via the sync script — no new strings, no
new locale keys.
Per component:
- AppSidebar.vue: 5 menu titles (dashboard / inbounds / settings /
xray / logout). Computed so the sidebar re-renders when the
cookie-driven locale flips on reload.
- IndexPage.vue: Quick actions card title + Logs / Backup / Up-to-
date / Update buttons.
- StatusCard.vue: CPU / Memory / Swap / Storage labels +
logical-processors / frequency tooltips.
- XrayStatusCard.vue: card title + error popover header + Stop /
Restart / Switch xray action labels (kept the v-prefix version
string as-is — it's content, not a label).
- SettingsPage.vue: 5 tab titles + Save / Restart-panel buttons +
unsaved-changes warning.
- XrayPage.vue: 6 tab titles + Save / Restart-xray buttons +
unsaved-changes warning.
- InboundsPage.vue: 5 summary-stat card titles.
- InboundList.vue: 10 column titles (computed for live locale),
Add inbound / General actions buttons + every dropdown menu item,
search placeholder, filter radio labels, popover titles
(disabled / depleted / depleting / online), traffic + info
popover row labels.
Total: ~75 strings localised across 8 files. The remaining English
labels live in the per-tab settings forms, the form modals
(Inbound / Client / Outbound / Rule / Balancer / WARP / Nord), and
the per-row table cell helpers — all incremental work that doesn't
touch infrastructure.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Replaces the toast stubs on the Basics tab and Outbounds toolbar
with the legacy WARP + NordVPN provisioning flows. Both modals now
stage their wireguard outbounds back into templateSettings.outbounds
through the same event channels OutboundsTab uses, so the existing
add / reset / delete / refresh-traffic surface keeps working.
- WarpModal.vue: empty state shows a single Create button that
generates a wireguard keypair locally (Wireguard.generateKeypair)
and posts it to /panel/xray/warp/reg; populated state surfaces
the access_token / device_id / license_key / private_key, lets
the user upgrade to WARP+ via /panel/xray/warp/license, refreshes
the account info from /panel/xray/warp/config (plan / quota /
usage in human-readable bytes), and stages a wireguard outbound
with the WARP-specific reserved-byte encoding pulled from
client_id. Add / Reset / Delete go through events the parent
routes back to templateSettings.outbounds.
- NordModal.vue: dual-tab login (NordVPN access token →
/panel/xray/nord/reg, or paste a NordLynx private key →
/panel/xray/nord/setKey). Once authenticated, country / city /
server selectors fetch from /panel/xray/nord/{countries,servers},
servers sort by load ascending, the lowest-load server in the
current city auto-selects. Reset emits oldTag/newTag so the
parent renames matching routing rules in place; logout emits a
remove-routing-rules event with prefix `nord-` to purge any
dangling references.
- XrayPage.vue: holds warpOpen / nordOpen flags, ensures the
outbounds array exists before mutating it, and wires the modal
events (add-outbound / reset-outbound / remove-outbound /
remove-routing-rules) to in-place edits of templateSettings.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Brings Balancers to full parity with the legacy panel and adds a
DNS tab placeholder that exposes the full dns/fakedns trees as JSON
so users can edit them without falling through to Advanced.
- BalancerFormModal.vue: tag (with duplicate-tag warning across
other balancers), strategy (random/roundRobin/leastLoad/leastPing),
selector tag-mode multi-select sourced from existing outbound
tags + free-form additions, fallback. Disable-on-invalid is
driven by the duplicateTag + emptySelector computed flags.
- BalancersTab.vue: empty state with a single "Add balancer" CTA;
populated state shows the legacy 4-column table (action / tag /
strategy / selector / fallback) with per-row edit + delete in a
dropdown. On submit the wire shape preserves the
`strategy: { type }` nesting only when the strategy is non-default,
matching the legacy emit. Tag renames also chase across
routing.rules.balancerTag references so existing rules don't dangle.
- DnsTab.vue: master enable switch + raw JSON for `dns` and
`fakedns`. Legacy had a dedicated server-by-server editor + a
fakedns row editor; both are big enough to deserve their own
commits, and the JSON path supports every field today.
WARP / NordVPN provisioning modals still toast as "coming soon" —
those are third-party API integrations worth their own commits.
The xray page now has structured editors for Basics / Routing /
Outbounds / Balancers and JSON editors for DNS / Advanced — every
xray tab the legacy panel offered is functional.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Replaces the Outbounds tab placeholder with a full table + add/edit
flow. The 1.3k-line legacy outbound modal is condensed to a tabbed
modal with structured Basics fields (tag/protocol/sendThrough/domain
strategy) and JSON tabs for the protocol-specific settings + stream
trees — same approach the Inbound modal uses, and a power user can
still edit the same trees via the page-level Advanced (JSON) tab.
- useXraySetting.js: adds fetchOutboundsTraffic +
resetOutboundsTraffic + testOutbound. Test states are tracked per
outbound index so the row's Test button can show loading + the
Test-result column can render the response delay / status / error.
- OutboundsTab.vue: full table (action / identity / address / traffic
/ test result / test) plus a card-list mobile variant with the
same row dropdown (set-first / edit / move up/down / reset traffic
/ delete). outboundAddresses() reproduces the legacy
findOutboundAddress logic so each protocol's host:port list is
rendered consistently. Add/edit go through OutboundFormModal,
delete goes through Modal.confirm, reset traffic posts to
/panel/xray/resetOutboundsTraffic with the row's tag (or
"-alltags-" from the toolbar).
- OutboundFormModal.vue: tag/protocol/sendThrough/domainStrategy on
the Basics tab; settings + streamSettings as raw JSON on their
respective tabs. Tag-collision check happens client-side before
emitting; malformed JSON aborts the save with a message.error.
- XrayPage.vue: imports OutboundsTab and wires the test action to
the composable's testOutbound helper.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Replaces the Routing tab placeholder with a full editor for
templateSettings.routing.rules:
- RoutingTab.vue: a-table over the parsed rules with the legacy six-
column layout (action / source / network / destination / inbound /
outbound) and the same "lead value + N more" pill renderer for
multi-value criteria. Mobile drops source/network/destination for
readability. Per-row dropdown handles edit / move-up / move-down /
delete; the array-mutation reordering replaces the legacy jQuery
Sortable drag handle without pulling in a sortable lib.
- RuleFormModal.vue: full form mirroring xray_rule_modal.html —
CSV inputs for sourceIP/sourcePort/vlessRoute/ip/domain/user/port,
Network select, Protocol multi-select, Attrs key/value pairs,
inbound-tag multi-select sourced from
templateSettings.inbounds + parent inboundTags + dnsTag,
outbound-tag single-select sourced from templateSettings.outbounds
+ clientReverseTags, and balancerTag from
templateSettings.routing.balancers. Submit serializes via the
same shape the legacy `getResult` produces (CSV → array, drop
empty fields).
- XrayPage.vue: imports RoutingTab and exposes inboundTags +
clientReverseTags from useXraySetting so the modal can populate
its tag pools.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Replaces the placeholder on the Basics tab with a structured form for
the most-touched fields of the xray template — outbound + routing
strategy, log levels, traffic stat counters, and the "basic routing"
shortcuts (block torrent / IPs / domains, direct IPs / domains, IPv4
forced, WARP / NordVPN routing).
- useXraySetting.js: hoists a parsed `templateSettings` reactive
alongside the JSON string, with two cooperating watches that keep
them in sync. Editing structured fields stringifies into xraySetting
for the dirty-poll + Advanced JSON tab; editing the JSON re-parses
into templateSettings only when valid, so structured tabs stay
readable mid-edit.
- BasicsTab.vue: collapse panels mirror the legacy partial — General,
Statistics, Logs, Basic routing. Every input is a computed v-model
reading/writing into templateSettings; the routing-rule shortcuts
funnel through ruleGetter/ruleSetter which match the legacy
templateRuleGetter/templateRuleSetter behavior (replace-first,
drop-duplicates, pop-the-rule-when-empty). Direct/IPv4 setters
also call syncOutbound() to provision/prune the matching outbound.
- XrayPage.vue: imports BasicsTab + derives `warpExist`/`nordExist`
from the parsed templateSettings. WARP/NordVPN provisioning modals
are still placeholders that toast — those land in 6-v with the
routing/outbound editors.
Default tab flips back to Basics so users land on the structured
editor.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The fifth and last legacy page comes online. Tabs are scaffolded with
a-empty placeholders for the structured editors (Basics / Routing /
Outbounds / Balancers / DNS) so navigation is stable; the
Advanced (JSON) tab is fully functional and lets power users edit
the raw xraySetting tree exactly like the legacy CodeMirror pane.
- xray.html + src/xray.js: fifth Vite multi-page entry, mounted as
XrayPage; vite.config.js routes /panel/xray and /panel/xray/ to it
through the dev proxy bypass alongside the other pages.
- XrayPage.vue: page chrome with the Save / Restart-xray bar, restart-
output popover (surfaces /panel/xray/getXrayResult content when
startup fails), 6 a-tabs, and a textarea-backed Advanced JSON editor.
CodeMirror is intentionally not pulled in — the textarea works for
every modern browser and keeps the bundle slim while structured
editors land in 6-ii through 6-v.
- useXraySetting.js composable: POST /panel/xray/ on mount, mirrors
the settings-page 1s busy-loop dirty check for both xraySetting
and outboundTestUrl, and exposes saveAll + restartXray. The dirty
flag relies on string equality of the pretty-printed JSON, so
reformat-only edits don't enable Save.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>