v221 ⑦ public views: node name prefers the public remark
buildProbeNodeView now sources its 'name' from probeDisplayName: the node's public remark (probe_meta.public_remark) when non-empty after trimming, else the node name as before. Contract field name unchanged, theme packages untouched, both audiences (anonymous and admin frames share the builder); the panel's internal node list is a different surface and keeps the plain node name. Tests: display-name unit cases (remark / empty / whitespace) and view-level assertions for both audiences; the public contract test's seeded expectation updated to the remark (its fixture sets public_remark='shown publicly' on node 'PubNode').
This commit is contained in:
@@ -323,7 +323,9 @@ func TestProbePublicContract(t *testing.T) {
|
||||
assertKeys(t, keySet(t, nodeBody), anonNodeKeys)
|
||||
var node map[string]any
|
||||
_ = json.Unmarshal(nodeBody, &node)
|
||||
if node["id"] != float64(pubID) || node["name"] != "PubNode" || node["online"] != true ||
|
||||
// V2.2.1 ⑦: the public view's name is the public remark when one
|
||||
// is set (the seed sets "shown publicly"), not the node name.
|
||||
if node["id"] != float64(pubID) || node["name"] != "shown publicly" || node["online"] != true ||
|
||||
node["month_rx"] != float64(33) || node["month_used"] != float64(77) ||
|
||||
node["total_tx"] != float64(222) || node["price"] != float64(10) {
|
||||
t.Fatalf("anon node values wrong: %v", node)
|
||||
|
||||
@@ -268,6 +268,19 @@ func expiresInDays(expires *string, now time.Time) any {
|
||||
return days
|
||||
}
|
||||
|
||||
// probeDisplayName is the name a node carries in the public views
|
||||
// (V2.2.1 ⑦): the operator's public remark when one is set — it is
|
||||
// the label written for public consumption — else the node name. The
|
||||
// contract field stays "name"; themes and the public API keep their
|
||||
// shape, only the value's source changes. The panel's internal node
|
||||
// list is a different surface and keeps the plain node name.
|
||||
func probeDisplayName(name, publicRemark string) string {
|
||||
if r := strings.TrimSpace(publicRemark); r != "" {
|
||||
return r
|
||||
}
|
||||
return name
|
||||
}
|
||||
|
||||
// buildProbeNodeView renders one node for one audience. The public
|
||||
// shape is built by whitelist (hub node_view): address, hostname and
|
||||
// the private remark exist only in the admin (full) rendering.
|
||||
@@ -298,7 +311,7 @@ func buildProbeNodeView(src probeNodeSource, full bool) map[string]any {
|
||||
|
||||
view := map[string]any{
|
||||
"id": a.Id,
|
||||
"name": src.name,
|
||||
"name": probeDisplayName(src.name, m.PublicRemark),
|
||||
"country": m.CountryPin,
|
||||
"group": m.GroupName,
|
||||
"public_remark": m.PublicRemark,
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/mhsanaei/3x-ui/v3/internal/web/service/probe"
|
||||
)
|
||||
|
||||
// V2.2.1 ⑦: the public views' node name is the operator's public
|
||||
// remark when one is set, and the node name otherwise — the panel's
|
||||
// own list (a different surface) is untouched.
|
||||
|
||||
func TestProbeDisplayNamePrefersPublicRemark(t *testing.T) {
|
||||
if got := probeDisplayName("node-name", "东京 01"); got != "东京 01" {
|
||||
t.Fatalf("with remark = %q, want the remark", got)
|
||||
}
|
||||
if got := probeDisplayName("node-name", ""); got != "node-name" {
|
||||
t.Fatalf("empty remark = %q, want node name", got)
|
||||
}
|
||||
if got := probeDisplayName("node-name", " "); got != "node-name" {
|
||||
t.Fatalf("whitespace-only remark = %q, want node name", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuildProbeNodeViewNameSource(t *testing.T) {
|
||||
withRemark := probeNodeSource{
|
||||
name: "internal-name",
|
||||
meta: probe.Meta{PublicRemark: "公开名", Public: true},
|
||||
}
|
||||
if got := buildProbeNodeView(withRemark, false)["name"]; got != "公开名" {
|
||||
t.Fatalf("anonymous view name = %v, want the public remark", got)
|
||||
}
|
||||
if got := buildProbeNodeView(withRemark, true)["name"]; got != "公开名" {
|
||||
t.Fatalf("admin view name = %v, want the public remark", got)
|
||||
}
|
||||
without := probeNodeSource{name: "internal-name", meta: probe.Meta{Public: true}}
|
||||
if got := buildProbeNodeView(without, false)["name"]; got != "internal-name" {
|
||||
t.Fatalf("view name without remark = %v, want the node name", got)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user