From a4617d1fed56ef1d541efb28917489c4017b86a1 Mon Sep 17 00:00:00 2001 From: wonfen Date: Wed, 11 Feb 2026 04:41:46 +0800 Subject: [PATCH] feat: add clear ingress/egress and data flow indicators for proxy chain --- .gitignore | 1 + Changelog.md | 1 + src/components/proxy/proxy-chain.tsx | 88 +++++++++++++++++++++++----- src/locales/ar/proxies.json | 4 +- src/locales/de/proxies.json | 4 +- src/locales/en/proxies.json | 4 +- src/locales/es/proxies.json | 4 +- src/locales/fa/proxies.json | 4 +- src/locales/id/proxies.json | 4 +- src/locales/jp/proxies.json | 4 +- src/locales/ko/proxies.json | 4 +- src/locales/ru/proxies.json | 4 +- src/locales/tr/proxies.json | 4 +- src/locales/tt/proxies.json | 4 +- src/locales/zh/proxies.json | 4 +- src/locales/zhtw/proxies.json | 4 +- 16 files changed, 114 insertions(+), 28 deletions(-) diff --git a/.gitignore b/.gitignore index 8728a85c1..57bc26ddd 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,4 @@ scripts/_env.sh .eslintcache .changelog_backups target +CLAUDE.md diff --git a/Changelog.md b/Changelog.md index ab8da7a82..d98978f0f 100644 --- a/Changelog.md +++ b/Changelog.md @@ -27,5 +27,6 @@ - 避免脏订阅地址无法 Scheme 导入订阅 - macOS TUN 覆盖 DNS 时使用 114.114.114.114 - 连通性测试替换为更快的 https://1.1.1.1 +- 链式代理增加明显的入口出口与数据流向标识 diff --git a/src/components/proxy/proxy-chain.tsx b/src/components/proxy/proxy-chain.tsx index c26d14a3d..b668b84ac 100644 --- a/src/components/proxy/proxy-chain.tsx +++ b/src/components/proxy/proxy-chain.tsx @@ -16,6 +16,7 @@ import { } from "@dnd-kit/sortable"; import { CSS } from "@dnd-kit/utilities"; import { + ArrowDownward, Delete as DeleteIcon, DragIndicator, Link, @@ -69,10 +70,18 @@ interface ProxyChainProps { interface SortableItemProps { proxy: ProxyChainItem; index: number; + isFirst: boolean; + isLast: boolean; onRemove: (id: string) => void; } -const SortableItem = ({ proxy, index, onRemove }: SortableItemProps) => { +const SortableItem = ({ + proxy, + index, + isFirst, + isLast, + onRemove, +}: SortableItemProps) => { const theme = useTheme(); const { t } = useTranslation(); const { @@ -90,12 +99,24 @@ const SortableItem = ({ proxy, index, onRemove }: SortableItemProps) => { opacity: isDragging ? 0.5 : 1, }; + const roleLabel = isFirst + ? t("proxies.page.chain.entryNode") + : isLast + ? t("proxies.page.chain.exitNode") + : undefined; + + const roleColor = isFirst + ? theme.palette.success.main + : isLast + ? theme.palette.warning.main + : undefined; + return ( { ? theme.palette.action.selected : theme.palette.background.default, borderRadius: 1, - border: `1px solid ${theme.palette.divider}`, + border: roleColor + ? `1.5px solid ${roleColor}` + : `1px solid ${theme.palette.divider}`, boxShadow: isDragging ? theme.shadows[4] : theme.shadows[1], transition: "box-shadow 0.2s, background-color 0.2s", }} @@ -125,12 +148,25 @@ const SortableItem = ({ proxy, index, onRemove }: SortableItemProps) => { - + {roleLabel ? ( + + ) : ( + + )} {proxyChain.map((proxy, index) => ( - + + 1 + } + onRemove={handleRemoveProxy} + /> + {index < proxyChain.length - 1 && ( + + + + )} + ))} diff --git a/src/locales/ar/proxies.json b/src/locales/ar/proxies.json index 071069f0c..c2eb1a017 100644 --- a/src/locales/ar/proxies.json +++ b/src/locales/ar/proxies.json @@ -49,7 +49,9 @@ "minimumNodesHint": "Chain proxy requires at least 2 nodes. Please add one more node.", "connectFailed": "Failed to connect to proxy chain", "disconnectFailed": "Failed to disconnect from proxy chain", - "duplicateNode": "Proxy node already exists in chain" + "duplicateNode": "Proxy node already exists in chain", + "entryNode": "مدخل", + "exitNode": "مخرج" }, "messages": { "directMode": "الوضع المباشر" diff --git a/src/locales/de/proxies.json b/src/locales/de/proxies.json index 92e11588a..a952d8c51 100644 --- a/src/locales/de/proxies.json +++ b/src/locales/de/proxies.json @@ -49,7 +49,9 @@ "minimumNodesHint": "Chain proxy requires at least 2 nodes. Please add one more node.", "connectFailed": "Failed to connect to proxy chain", "disconnectFailed": "Failed to disconnect from proxy chain", - "duplicateNode": "Proxy node already exists in chain" + "duplicateNode": "Proxy node already exists in chain", + "entryNode": "Eingang", + "exitNode": "Ausgang" }, "messages": { "directMode": "Direktverbindungs-Modus" diff --git a/src/locales/en/proxies.json b/src/locales/en/proxies.json index f7cba5d77..f9e432d2e 100644 --- a/src/locales/en/proxies.json +++ b/src/locales/en/proxies.json @@ -49,7 +49,9 @@ "minimumNodesHint": "Chain proxy requires at least 2 nodes. Please add one more node.", "connectFailed": "Failed to connect to proxy chain", "disconnectFailed": "Failed to disconnect from proxy chain", - "duplicateNode": "Proxy node already exists in chain" + "duplicateNode": "Proxy node already exists in chain", + "entryNode": "Entry", + "exitNode": "Exit" }, "messages": { "directMode": "Direct Mode" diff --git a/src/locales/es/proxies.json b/src/locales/es/proxies.json index 719d4e5a3..3de8171be 100644 --- a/src/locales/es/proxies.json +++ b/src/locales/es/proxies.json @@ -49,7 +49,9 @@ "minimumNodesHint": "Chain proxy requires at least 2 nodes. Please add one more node.", "connectFailed": "Failed to connect to proxy chain", "disconnectFailed": "Failed to disconnect from proxy chain", - "duplicateNode": "Proxy node already exists in chain" + "duplicateNode": "Proxy node already exists in chain", + "entryNode": "Entrada", + "exitNode": "Salida" }, "messages": { "directMode": "Modo de conexión directa" diff --git a/src/locales/fa/proxies.json b/src/locales/fa/proxies.json index d2e7c0b6d..94bd80e9a 100644 --- a/src/locales/fa/proxies.json +++ b/src/locales/fa/proxies.json @@ -49,7 +49,9 @@ "minimumNodesHint": "Chain proxy requires at least 2 nodes. Please add one more node.", "connectFailed": "Failed to connect to proxy chain", "disconnectFailed": "Failed to disconnect from proxy chain", - "duplicateNode": "Proxy node already exists in chain" + "duplicateNode": "Proxy node already exists in chain", + "entryNode": "ورودی", + "exitNode": "خروجی" }, "messages": { "directMode": "حالت مستقیم" diff --git a/src/locales/id/proxies.json b/src/locales/id/proxies.json index 26945b1d6..fa5b47599 100644 --- a/src/locales/id/proxies.json +++ b/src/locales/id/proxies.json @@ -49,7 +49,9 @@ "minimumNodesHint": "Chain proxy requires at least 2 nodes. Please add one more node.", "connectFailed": "Failed to connect to proxy chain", "disconnectFailed": "Failed to disconnect from proxy chain", - "duplicateNode": "Proxy node already exists in chain" + "duplicateNode": "Proxy node already exists in chain", + "entryNode": "Masuk", + "exitNode": "Keluar" }, "messages": { "directMode": "Mode Langsung" diff --git a/src/locales/jp/proxies.json b/src/locales/jp/proxies.json index e46215b70..f24c17031 100644 --- a/src/locales/jp/proxies.json +++ b/src/locales/jp/proxies.json @@ -49,7 +49,9 @@ "minimumNodesHint": "Chain proxy requires at least 2 nodes. Please add one more node.", "connectFailed": "Failed to connect to proxy chain", "disconnectFailed": "Failed to disconnect from proxy chain", - "duplicateNode": "Proxy node already exists in chain" + "duplicateNode": "Proxy node already exists in chain", + "entryNode": "入口", + "exitNode": "出口" }, "messages": { "directMode": "直接接続モード" diff --git a/src/locales/ko/proxies.json b/src/locales/ko/proxies.json index 00e6b383e..adbcde732 100644 --- a/src/locales/ko/proxies.json +++ b/src/locales/ko/proxies.json @@ -49,7 +49,9 @@ "minimumNodesHint": "체인 프록시는 최소 2개의 노드가 필요합니다. 하나 더 추가하세요.", "connectFailed": "프록시 체인 연결 실패", "disconnectFailed": "프록시 체인 연결 해제 실패", - "duplicateNode": "프록시 노드가 체인에 이미 존재합니다" + "duplicateNode": "프록시 노드가 체인에 이미 존재합니다", + "entryNode": "입구", + "exitNode": "출구" }, "messages": { "directMode": "직접 모드" diff --git a/src/locales/ru/proxies.json b/src/locales/ru/proxies.json index 67676e931..bac77f5e5 100644 --- a/src/locales/ru/proxies.json +++ b/src/locales/ru/proxies.json @@ -49,7 +49,9 @@ "minimumNodesHint": "Chain proxy requires at least 2 nodes. Please add one more node.", "connectFailed": "Failed to connect to proxy chain", "disconnectFailed": "Failed to disconnect from proxy chain", - "duplicateNode": "Proxy node already exists in chain" + "duplicateNode": "Proxy node already exists in chain", + "entryNode": "Вход", + "exitNode": "Выход" }, "messages": { "directMode": "Прямой режим" diff --git a/src/locales/tr/proxies.json b/src/locales/tr/proxies.json index 89e71d09f..c7fa045e1 100644 --- a/src/locales/tr/proxies.json +++ b/src/locales/tr/proxies.json @@ -49,7 +49,9 @@ "minimumNodesHint": "Chain proxy requires at least 2 nodes. Please add one more node.", "connectFailed": "Failed to connect to proxy chain", "disconnectFailed": "Failed to disconnect from proxy chain", - "duplicateNode": "Proxy node already exists in chain" + "duplicateNode": "Proxy node already exists in chain", + "entryNode": "Giriş", + "exitNode": "Çıkış" }, "messages": { "directMode": "Doğrudan Mod" diff --git a/src/locales/tt/proxies.json b/src/locales/tt/proxies.json index b35b89172..63a88bd5b 100644 --- a/src/locales/tt/proxies.json +++ b/src/locales/tt/proxies.json @@ -49,7 +49,9 @@ "minimumNodesHint": "Chain proxy requires at least 2 nodes. Please add one more node.", "connectFailed": "Failed to connect to proxy chain", "disconnectFailed": "Failed to disconnect from proxy chain", - "duplicateNode": "Proxy node already exists in chain" + "duplicateNode": "Proxy node already exists in chain", + "entryNode": "Кереш", + "exitNode": "Чыгыш" }, "messages": { "directMode": "Туры режим" diff --git a/src/locales/zh/proxies.json b/src/locales/zh/proxies.json index e70101bd5..2bcb9596f 100644 --- a/src/locales/zh/proxies.json +++ b/src/locales/zh/proxies.json @@ -49,7 +49,9 @@ "minimumNodesHint": "链式代理至少需要 2 个节点,请再添加一个节点。", "connectFailed": "连接链式代理失败", "disconnectFailed": "断开链式代理失败", - "duplicateNode": "该节点已在链式代理表中" + "duplicateNode": "该节点已在链式代理表中", + "entryNode": "入口", + "exitNode": "出口" }, "messages": { "directMode": "直连模式" diff --git a/src/locales/zhtw/proxies.json b/src/locales/zhtw/proxies.json index 48b14e03b..f77a1b56c 100644 --- a/src/locales/zhtw/proxies.json +++ b/src/locales/zhtw/proxies.json @@ -49,7 +49,9 @@ "minimumNodesHint": "鏈式代理至少需要 2 個節點,請再新增一個節點。", "connectFailed": "連線鏈式代理失敗", "disconnectFailed": "中斷鏈式代理失敗", - "duplicateNode": "該節點已在鏈式代理表中" + "duplicateNode": "該節點已在鏈式代理表中", + "entryNode": "入口", + "exitNode": "出口" }, "messages": { "directMode": "直連模式"