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": "直連模式"