3x-ui/frontend/src
MHSanaei a038ad6135
fix(sub): multi-inbound traffic + trojan/hysteria userinfo + utf-8 vmess remark
Three bugs surfaced by the new SubPage and the recent client-record
refactor:

- xray.ClientTraffic.Email is globally unique, so a multi-inbound
  client has exactly one traffic row attached to whichever inbound
  claimed it. Iterating inbound.ClientStats per inbound dedup-locked
  the first lookup to zero for clients that lived under any other
  inbound, so the SubPage info table read 0 B for all the multi-
  inbound subs. Replaced appendUniqueTraffic with a single
  AggregateTrafficByEmails(emails) helper that runs one WHERE email
  IN (?) over xray.ClientTraffic and folds the rows. GetSubs /
  SubClashService.GetClash / SubJsonService.GetJson all share it.

- Trojan and Hysteria share-links embedded the raw password/auth into
  the userinfo (scheme://<value>@host) without percent-encoding, so
  passwords containing `/` or `=` (e.g., base64-with-padding) broke
  popular trojan clients with parse errors. Added encodeUserinfo()
  that wraps url.QueryEscape and rewrites the `+` (space) back to
  `%20` for parity with encodeURIComponent on the frontend; applied
  to trojan.password and hysteria.auth. Same fix on the frontend's
  genTrojanLink.

- VMess link remarks ride inside a base64-encoded JSON payload, but
  the SubPage / ClientInfoModal parser used JSON.parse(atob(body)),
  which treats the binary string as Latin-1 and shreds any multi-byte
  UTF-8 sequence. Most visible on the emoji decorations
  (genRemark appends 📊/), so a remark like `test-1.00GB📊` rendered
  as `test-1.00GBð…`. Routed through Uint8Array +
  TextDecoder('utf-8') so multi-byte codepoints survive.
2026-05-27 04:22:51 +02:00
..
api feat(frontend): extend Zod validation to remaining query/mutation hooks 2026-05-25 16:14:00 +02:00
components refactor(frontend): retire all AntD + Zod deprecations 2026-05-27 01:19:29 +02:00
entries Migrate frontend models/api/utils to TypeScript and modernize AntD theming (#4563) 2026-05-25 14:34:53 +02:00
generated feat(codegen): Go-first tool emitting Zod schemas and TS types 2026-05-25 19:29:44 +02:00
hooks feat(sub): clash row + reorganise SubPage around Subscription info 2026-05-27 03:24:48 +02:00
i18n Frontend rewrite: React + TypeScript with AntD v6 (#4498) 2026-05-23 15:21:45 +02:00
layouts feat(frontend): TanStack Query + React Router migration & in-panel API docs (#4541) 2026-05-24 21:34:52 +02:00
lib/xray fix(sub): multi-inbound traffic + trojan/hysteria userinfo + utf-8 vmess remark 2026-05-27 04:22:51 +02:00
models refactor(frontend): retire class-based xray models (Step 5) 2026-05-26 19:49:42 +02:00
pages fix(sub): multi-inbound traffic + trojan/hysteria userinfo + utf-8 vmess remark 2026-05-27 04:22:51 +02:00
schemas feat(sub): clash row + reorganise SubPage around Subscription info 2026-05-27 03:24:48 +02:00
styles Migrate frontend models/api/utils to TypeScript and modernize AntD theming (#4563) 2026-05-25 14:34:53 +02:00
test test(frontend): golden fixtures for DNS, Balancer, Rule schemas 2026-05-26 23:36:27 +02:00
utils refactor(frontend): retire all AntD + Zod deprecations 2026-05-27 01:19:29 +02:00
env.d.ts feat(sub): compact subscription rows with per-link email + PQ QR hide 2026-05-27 03:11:59 +02:00
main.tsx Migrate frontend models/api/utils to TypeScript and modernize AntD theming (#4563) 2026-05-25 14:34:53 +02:00
queryClient.ts feat(frontend): TanStack Query + React Router migration & in-panel API docs (#4541) 2026-05-24 21:34:52 +02:00
routes.tsx feat(frontend): TanStack Query + React Router migration & in-panel API docs (#4541) 2026-05-24 21:34:52 +02:00