From 006a4490873c46e5f4d6bc63bbf898fb7b4c359a Mon Sep 17 00:00:00 2001
From: RyanVan <150385913+Ryson-32@users.noreply.github.com>
Date: Wed, 24 Jun 2026 16:08:43 +0800
Subject: [PATCH 1/2] fix(ui): polish advanced proxy group layout
---
.../proxy-group-advanced-panel.test.ts | 50 +++++++++++++++++++
.../sections/proxy-group-advanced-panel.tsx | 22 +++++---
.../proxy-groups-added-rule-sets.test.ts | 1 +
.../sections/proxy-groups-added-rule-sets.tsx | 2 +-
.../sections/proxy-groups-categories.test.ts | 7 ++-
.../sections/proxy-groups-categories.tsx | 8 +--
.../proxy-groups-custom-rules.test.ts | 1 +
.../sections/proxy-groups-custom-rules.tsx | 4 +-
8 files changed, 81 insertions(+), 14 deletions(-)
diff --git a/packages/ui/src/product/converter/advanced-mode/sections/proxy-group-advanced-panel.test.ts b/packages/ui/src/product/converter/advanced-mode/sections/proxy-group-advanced-panel.test.ts
index 7a31443..8c31f28 100644
--- a/packages/ui/src/product/converter/advanced-mode/sections/proxy-group-advanced-panel.test.ts
+++ b/packages/ui/src/product/converter/advanced-mode/sections/proxy-group-advanced-panel.test.ts
@@ -122,6 +122,7 @@ describe("ProxyGroupAdvancedPanel", () => {
expect(html).toContain("DIRECT");
expect(html).toContain("rules-content");
expect(html).toContain("还没有分流规则");
+ expect(html).toContain("max-h-52 space-y-1.5 overflow-y-auto pr-1 custom-scrollbar");
expect(mocks.inputs.map((input) => input.value)).toEqual(["Source", "Japan"]);
mocks.inputs[0].onChange({ target: { value: "IEPL" } });
@@ -198,6 +199,55 @@ describe("ProxyGroupAdvancedPanel", () => {
expect(html).toContain("暂无已启用的节点或代理组");
});
+ it("previews enabled members for a disabled built-in proxy group", () => {
+ mocks.store = {
+ ...mocks.store,
+ enabledProxyGroups: [],
+ customProxyGroups: [],
+ proxyGroupAdvanced: {},
+ };
+
+ const html = renderToStaticMarkup(
+ React.createElement(ProxyGroupAdvancedPanel, {
+ target: { kind: "module", id: "auto", name: "⚡ Auto" },
+ advanced: {},
+ onChange: vi.fn(),
+ rulesCount: 0,
+ rulesContent: null,
+ }),
+ );
+
+ expect(html).toContain("US Source");
+ expect(html).toContain("Japan Source");
+ expect(html).toContain("max-h-52 overflow-y-auto pr-1 custom-scrollbar flex flex-wrap gap-1.5");
+ expect(html).not.toContain("暂无已启用的节点或代理组");
+ });
+
+ it("previews enabled members for a disabled custom proxy group", () => {
+ mocks.store = {
+ ...mocks.store,
+ enabledProxyGroups: [],
+ customProxyGroups: [
+ { id: "media", name: "Media", emoji: "", groupType: "select", enabled: false },
+ ],
+ proxyGroupAdvanced: {},
+ };
+
+ const html = renderToStaticMarkup(
+ React.createElement(ProxyGroupAdvancedPanel, {
+ target: { kind: "custom", id: "media", name: "Media" },
+ advanced: {},
+ onChange: vi.fn(),
+ rulesCount: 0,
+ rulesContent: null,
+ }),
+ );
+
+ expect(html).toContain("US Source");
+ expect(html).toContain("Japan Source");
+ expect(html).not.toContain("暂无已启用的节点或代理组");
+ });
+
it("normalizes advanced member helpers without rendering the panel", () => {
const nodes = [node("US Source")];
const moduleNames = { auto: "Auto", select: "Select" };
diff --git a/packages/ui/src/product/converter/advanced-mode/sections/proxy-group-advanced-panel.tsx b/packages/ui/src/product/converter/advanced-mode/sections/proxy-group-advanced-panel.tsx
index 16dbb10..a635214 100644
--- a/packages/ui/src/product/converter/advanced-mode/sections/proxy-group-advanced-panel.tsx
+++ b/packages/ui/src/product/converter/advanced-mode/sections/proxy-group-advanced-panel.tsx
@@ -182,6 +182,16 @@ export function ProxyGroupAdvancedPanel({
() => customProxyGroups.filter((group) => group.enabled !== false),
[customProxyGroups],
);
+ const previewEnabledProxyGroups = React.useMemo(() => {
+ if (target.kind !== "module" || enabledProxyGroups.includes(target.id)) return enabledProxyGroups;
+ return [...enabledProxyGroups, target.id];
+ }, [enabledProxyGroups, target.id, target.kind]);
+ const previewCustomProxyGroups = React.useMemo(() => {
+ if (target.kind !== "custom") return customProxyGroups;
+ return customProxyGroups.map((group) =>
+ group.id === target.id && group.enabled === false ? { ...group, enabled: true } : group,
+ );
+ }, [customProxyGroups, target.id, target.kind]);
const activeNodes = React.useMemo(
() => nodes.filter((node) => !isSubscriptionInfoNodeName(node.name)),
@@ -202,11 +212,11 @@ export function ProxyGroupAdvancedPanel({
if (nodes.length === 0) return [];
const generated = generateProxyGroups({
nodes,
- enabledModules: enabledProxyGroups,
+ enabledModules: previewEnabledProxyGroups,
ruleProviderBaseUrl,
testUrl,
testInterval,
- customProxyGroups: activeCustomProxyGroups,
+ customProxyGroups: previewCustomProxyGroups,
customRuleSets,
proxyGroupAdvanced,
builtinRuleEdits,
@@ -215,11 +225,11 @@ export function ProxyGroupAdvancedPanel({
return generated.find((group) => group.name === target.name)?.proxies ?? [];
}, [
nodes,
- enabledProxyGroups,
+ previewEnabledProxyGroups,
ruleProviderBaseUrl,
testUrl,
testInterval,
- activeCustomProxyGroups,
+ previewCustomProxyGroups,
customRuleSets,
proxyGroupAdvanced,
builtinRuleEdits,
@@ -325,7 +335,7 @@ export function ProxyGroupAdvancedPanel({
导入源
-
+
{sourceOptions.length === 0 ? (
暂无可匹配的导入源
) : (
@@ -453,7 +463,7 @@ export function ProxyGroupAdvancedPanel({
{excludedMembers.length === 0 ? (
暂无未启用的节点或代理组
) : (
-
+
{excludedMembers.map((member) => {
return (
diff --git a/packages/ui/src/product/converter/advanced-mode/sections/proxy-groups-categories.test.ts b/packages/ui/src/product/converter/advanced-mode/sections/proxy-groups-categories.test.ts
index d27e0ad..4811d00 100644
--- a/packages/ui/src/product/converter/advanced-mode/sections/proxy-groups-categories.test.ts
+++ b/packages/ui/src/product/converter/advanced-mode/sections/proxy-groups-categories.test.ts
@@ -263,7 +263,12 @@ describe("ProxyGroupsCategories", () => {
renderCategories({ 0: new Set(["core"]) });
expect(mocks.captures.inputs).toHaveLength(0);
- expect(renderCategories({ 0: new Set(["core"]) }).html).toContain("https://rules.example/base/");
+ const html = renderCategories({ 0: new Set(["core"]) }).html;
+ expect(html).toContain("https://rules.example/base/");
+ expect(html).toContain("grid-cols-[minmax(0,1fr)]");
+ expect(html).toContain("md:grid-cols-[minmax(0,1fr)_96px]");
+ expect(html).toContain("min-w-0 space-y-1");
+ expect(html).toContain("h-9 w-full");
expect(mocks.store.setRuleProviderBaseUrl).not.toHaveBeenCalled();
expect(mocks.captures.moduleCards).toHaveLength(1);
diff --git a/packages/ui/src/product/converter/advanced-mode/sections/proxy-groups-categories.tsx b/packages/ui/src/product/converter/advanced-mode/sections/proxy-groups-categories.tsx
index a2848bd..7490c16 100644
--- a/packages/ui/src/product/converter/advanced-mode/sections/proxy-groups-categories.tsx
+++ b/packages/ui/src/product/converter/advanced-mode/sections/proxy-groups-categories.tsx
@@ -290,8 +290,8 @@ export function ProxyGroupsCategories() {
return (
<>
-
-
+
+
@@ -302,11 +302,11 @@ export function ProxyGroupsCategories() {
{ruleProviderBaseUrl}
-
+
-
+
{proxyGroupAdvancedModeEnabled ? "已开启" : "未开启"}
diff --git a/packages/ui/src/product/converter/advanced-mode/sections/proxy-groups-custom-rules.test.ts b/packages/ui/src/product/converter/advanced-mode/sections/proxy-groups-custom-rules.test.ts
index a40f352..e73a09b 100644
--- a/packages/ui/src/product/converter/advanced-mode/sections/proxy-groups-custom-rules.test.ts
+++ b/packages/ui/src/product/converter/advanced-mode/sections/proxy-groups-custom-rules.test.ts
@@ -242,6 +242,7 @@ describe("ProxyGroupsCustomRules", () => {
expect(html).toContain(RULE_HEADER_ROW_CLASS);
expect(html).toContain(RULE_EDIT_PRIMARY_GROUP_CLASS);
expect(html).toContain(RULE_EDIT_TRAILING_CONTROLS_CLASS);
+ expect(html).toContain("proxy-group-rule-no-resolve-label");
expect(RULE_EDIT_TRAILING_CONTROLS_CLASS).toContain(
"proxy-group-custom-rule-editor-trailing",
);
diff --git a/packages/ui/src/product/converter/advanced-mode/sections/proxy-groups-custom-rules.tsx b/packages/ui/src/product/converter/advanced-mode/sections/proxy-groups-custom-rules.tsx
index 9720d92..ab83548 100644
--- a/packages/ui/src/product/converter/advanced-mode/sections/proxy-groups-custom-rules.tsx
+++ b/packages/ui/src/product/converter/advanced-mode/sections/proxy-groups-custom-rules.tsx
@@ -296,7 +296,7 @@ export function ProxyGroupsCustomRules() {
checked={newRuleNoResolve}
onCheckedChange={setNewRuleNoResolve}
/>
- no-resolve
+ no-resolve
-
+
no-resolve
From 0b199c7f53466be480bdc19766c0920d774416db Mon Sep 17 00:00:00 2001
From: RyanVan <150385913+Ryson-32@users.noreply.github.com>
Date: Wed, 24 Jun 2026 16:28:30 +0800
Subject: [PATCH 2/2] fix(ui): keep proxy group settings inline
---
.../advanced-mode/sections/proxy-groups-categories.test.ts | 4 ++--
.../advanced-mode/sections/proxy-groups-categories.tsx | 2 +-
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/packages/ui/src/product/converter/advanced-mode/sections/proxy-groups-categories.test.ts b/packages/ui/src/product/converter/advanced-mode/sections/proxy-groups-categories.test.ts
index 4811d00..6d23bb1 100644
--- a/packages/ui/src/product/converter/advanced-mode/sections/proxy-groups-categories.test.ts
+++ b/packages/ui/src/product/converter/advanced-mode/sections/proxy-groups-categories.test.ts
@@ -265,8 +265,8 @@ describe("ProxyGroupsCategories", () => {
expect(mocks.captures.inputs).toHaveLength(0);
const html = renderCategories({ 0: new Set(["core"]) }).html;
expect(html).toContain("https://rules.example/base/");
- expect(html).toContain("grid-cols-[minmax(0,1fr)]");
- expect(html).toContain("md:grid-cols-[minmax(0,1fr)_96px]");
+ expect(html).toContain("grid-cols-[minmax(0,1fr)_96px]");
+ expect(html).not.toContain("md:grid-cols-[minmax(0,1fr)_96px]");
expect(html).toContain("min-w-0 space-y-1");
expect(html).toContain("h-9 w-full");
expect(mocks.store.setRuleProviderBaseUrl).not.toHaveBeenCalled();
diff --git a/packages/ui/src/product/converter/advanced-mode/sections/proxy-groups-categories.tsx b/packages/ui/src/product/converter/advanced-mode/sections/proxy-groups-categories.tsx
index 7490c16..96b8c29 100644
--- a/packages/ui/src/product/converter/advanced-mode/sections/proxy-groups-categories.tsx
+++ b/packages/ui/src/product/converter/advanced-mode/sections/proxy-groups-categories.tsx
@@ -290,7 +290,7 @@ export function ProxyGroupsCategories() {
return (
<>
-