diff options
| author | Larvan2 <[email protected]> | 2026-07-03 14:42:55 +0800 |
|---|---|---|
| committer | Larvan2 <[email protected]> | 2026-07-03 14:42:55 +0800 |
| commit | 37367efe2a385114adac21f9bb044bc82c8789d5 (patch) | |
| tree | 9c12c4b270cd5bd171e6dcf4d7120534a9197a7c | |
| parent | 5f9935312b1703561caf1187fa94abed1d046894 (diff) | |
feat(proxies): add fixed selection feature and related translations
| -rw-r--r-- | src/components/CollapsibleSectionHeader.module.scss | 8 | ||||
| -rw-r--r-- | src/components/CollapsibleSectionHeader.tsx | 13 | ||||
| -rw-r--r-- | src/components/proxies/ProxyGroup.tsx | 12 | ||||
| -rw-r--r-- | src/components/shared/FeatherIcons.ts | 1 | ||||
| -rw-r--r-- | src/i18n/en.ts | 1 | ||||
| -rw-r--r-- | src/i18n/zh-cn.ts | 1 | ||||
| -rw-r--r-- | src/i18n/zh-tw.ts | 1 | ||||
| -rw-r--r-- | src/store/types.ts | 3 |
8 files changed, 36 insertions, 4 deletions
diff --git a/src/components/CollapsibleSectionHeader.module.scss b/src/components/CollapsibleSectionHeader.module.scss index f0797dd..3fd8bd3 100644 --- a/src/components/CollapsibleSectionHeader.module.scss +++ b/src/components/CollapsibleSectionHeader.module.scss @@ -27,6 +27,14 @@ margin-left: 5px; } +.lock { + display: inline-flex; + align-items: center; + margin-left: 6px; + color: var(--color-latency-medium, #d4b75c); + cursor: help; +} + /* TODO duplicate with connQty in Connections.module.css */ .qty { font-family: var(--font-normal); diff --git a/src/components/CollapsibleSectionHeader.tsx b/src/components/CollapsibleSectionHeader.tsx index e243950..729f072 100644 --- a/src/components/CollapsibleSectionHeader.tsx +++ b/src/components/CollapsibleSectionHeader.tsx @@ -1,7 +1,9 @@ import * as React from 'react'; +import { useTranslation } from 'react-i18next'; import s from './CollapsibleSectionHeader.module.scss'; import { SectionNameType } from './shared/Basic'; +import { Lock } from './shared/FeatherIcons'; type Props = { name: string; @@ -9,9 +11,12 @@ type Props = { qty?: number | string; toggle?: () => void; isOpen?: boolean; + // URLTest/Fallback group has a manually-fixed selection + fixed?: boolean; }; -export default function Header({ name, type, toggle, qty }: Props) { +export default function Header({ name, type, toggle, qty, fixed }: Props) { + const { t } = useTranslation(); const handleKeyDown = React.useCallback( (e: React.KeyboardEvent) => { e.preventDefault(); @@ -34,6 +39,12 @@ export default function Header({ name, type, toggle, qty }: Props) { <SectionNameType name={name} type={type} /> </div> + {fixed ? ( + <span className={s.lock} title={t('group_fixed_tip')}> + <Lock size={13} /> + </span> + ) : null} + {typeof qty === 'number' ? <span className={s.qty}>{qty}</span> : null} </div> ); diff --git a/src/components/proxies/ProxyGroup.tsx b/src/components/proxies/ProxyGroup.tsx index f436944..d838685 100644 --- a/src/components/proxies/ProxyGroup.tsx +++ b/src/components/proxies/ProxyGroup.tsx @@ -109,8 +109,8 @@ export const ProxyGroup = memo(function ProxyGroup({ dispatch, proxyGroupByProvider = false, }: Props) { - const group = proxies[name] as ProxyItem & { all?: string[]; now?: string }; - const { all: allItems = [], type, now } = group || {}; + const group = proxies[name] as ProxyItem & { all?: string[]; now?: string; fixed?: string }; + const { all: allItems = [], type, now, fixed } = group || {}; const all = useFilteredAndSorted(allItems, delay, hideUnavailableProxies, proxySortBy, proxies); const nowChain = useMemo(() => buildNowChain(proxies, name), [proxies, name]); @@ -179,7 +179,13 @@ export const ProxyGroup = memo(function ProxyGroup({ return ( <div className={s0.group}> <div className={s0.groupHeader}> - <CollapsibleSectionHeader name={name} type={type} toggle={toggle} qty={qtyLabel} /> + <CollapsibleSectionHeader + name={name} + type={type} + toggle={toggle} + qty={qtyLabel} + fixed={!!fixed} + /> <div className={s0.btnGroup}> <Button kind="minimal" diff --git a/src/components/shared/FeatherIcons.ts b/src/components/shared/FeatherIcons.ts index ee1f410..ca9c359 100644 --- a/src/components/shared/FeatherIcons.ts +++ b/src/components/shared/FeatherIcons.ts @@ -17,6 +17,7 @@ export { Hash, Info, Link, + Lock, LogOut, Menu, Monitor, diff --git a/src/i18n/en.ts b/src/i18n/en.ts index 1f42f3c..39c1d04 100644 --- a/src/i18n/en.ts +++ b/src/i18n/en.ts @@ -91,4 +91,5 @@ export const data = { disconnect: 'Close Connection', internel: 'Internal Connection', Clear: 'Clear', + group_fixed_tip: 'This group has a manually fixed selection; run a latency test to release it', }; diff --git a/src/i18n/zh-cn.ts b/src/i18n/zh-cn.ts index ff6ceac..b9c8ddf 100644 --- a/src/i18n/zh-cn.ts +++ b/src/i18n/zh-cn.ts @@ -92,4 +92,5 @@ export const data = { disconnect: '断开连接', internel: '内部链接', Clear: '清空', + group_fixed_tip: '该组已手动固定选择,点击测速可解除固定', }; diff --git a/src/i18n/zh-tw.ts b/src/i18n/zh-tw.ts index c3ea79f..ba3a9c6 100644 --- a/src/i18n/zh-tw.ts +++ b/src/i18n/zh-tw.ts @@ -85,4 +85,5 @@ export const data = { disconnect: '斷開連線', internel: '內部連線', Clear: '清空', + group_fixed_tip: '該組已手動固定選擇,點擊測速可解除固定', }; diff --git a/src/store/types.ts b/src/store/types.ts index 2d4459b..eaefaf1 100644 --- a/src/store/types.ts +++ b/src/store/types.ts @@ -75,6 +75,9 @@ export type ProxyItem = { now?: string; hidden?: boolean; // group-only fields (Selector/URLTest/Fallback/LoadBalance) from GET /proxies + // set by URLTest/Fallback groups to the manually-fixed member name; cleared by the + // backend when the group is latency-tested via /group/{name}/delay + fixed?: string; testUrl?: string; expectedStatus?: string; // extra latency history keyed by test URL — its keys are the URLs the backend tests against |
