mirror of
https://github.com/clash-verge-rev/clash-verge-rev.git
synced 2026-10-24 12:42:22 +08:00
feat(proxy): confirm before enabling chain proxy
Show the speed warning with explicit enable/keep-disabled actions, and add a close button to the empty chain panel.
This commit is contained in:
@@ -22,6 +22,7 @@
|
||||
<details>
|
||||
<summary><strong> 🚀 优化改进 </strong></summary>
|
||||
|
||||
- 优化「链式代理」:开启前需确认网速影响提示,空面板新增「关闭」按钮
|
||||
|
||||
**🖥️ Windows**
|
||||
|
||||
|
||||
@@ -75,6 +75,7 @@ interface ProxyChainProps {
|
||||
onMarkUnsavedChanges?: () => void
|
||||
mode?: string
|
||||
selectedGroup?: string | null
|
||||
onExitChainMode: () => void
|
||||
}
|
||||
|
||||
interface ProxyChainItemProps {
|
||||
@@ -331,6 +332,7 @@ export const ProxyChain = ({
|
||||
onMarkUnsavedChanges,
|
||||
mode,
|
||||
selectedGroup,
|
||||
onExitChainMode,
|
||||
}: ProxyChainProps) => {
|
||||
const theme = useTheme()
|
||||
const { t } = useTranslation()
|
||||
@@ -696,13 +698,18 @@ export const ProxyChain = ({
|
||||
<Box
|
||||
sx={{
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
gap: 2,
|
||||
height: '100%',
|
||||
color: theme.palette.text.secondary,
|
||||
}}
|
||||
>
|
||||
<Typography>{t('proxies.page.chain.empty')}</Typography>
|
||||
<Button size="small" variant="outlined" onClick={onExitChainMode}>
|
||||
{t('shared.actions.close')}
|
||||
</Button>
|
||||
</Box>
|
||||
) : (
|
||||
<DragDropProvider
|
||||
|
||||
@@ -77,6 +77,7 @@ interface GroupSelectMenuProps {
|
||||
interface ProxyGroupsChainProps {
|
||||
mode: string
|
||||
chainConfigData?: string | null
|
||||
onExitChainMode: () => void
|
||||
availableGroups: any[]
|
||||
activeSelectedGroup: string | null
|
||||
showScrollTop: boolean
|
||||
@@ -305,6 +306,7 @@ export function ProxyGroupsChain(props: ProxyGroupsChainProps) {
|
||||
const {
|
||||
mode,
|
||||
chainConfigData,
|
||||
onExitChainMode,
|
||||
availableGroups,
|
||||
activeSelectedGroup,
|
||||
showScrollTop,
|
||||
@@ -521,6 +523,7 @@ export function ProxyGroupsChain(props: ProxyGroupsChainProps) {
|
||||
chainConfigData={chainConfigData}
|
||||
mode={mode}
|
||||
selectedGroup={activeSelectedGroup}
|
||||
onExitChainMode={onExitChainMode}
|
||||
/>
|
||||
</Box>
|
||||
</Box>
|
||||
|
||||
@@ -71,6 +71,7 @@ interface Props {
|
||||
mode: string
|
||||
isChainMode?: boolean
|
||||
chainConfigData?: string | null
|
||||
onExitChainMode: () => void
|
||||
}
|
||||
|
||||
function useEmptyRenderList() {
|
||||
@@ -199,8 +200,9 @@ function useProxyRenderState(
|
||||
function ChainProxyGroups(props: {
|
||||
mode: string
|
||||
chainConfigData?: string | null
|
||||
onExitChainMode: () => void
|
||||
}) {
|
||||
const { mode, chainConfigData } = props
|
||||
const { mode, chainConfigData, onExitChainMode } = props
|
||||
const { proxyView } = useProxiesData()
|
||||
const [selectedGroup, setSelectedGroup] = useState<string | null>(null)
|
||||
|
||||
@@ -355,6 +357,7 @@ function ChainProxyGroups(props: {
|
||||
<ProxyGroupsChain
|
||||
mode={mode}
|
||||
chainConfigData={chainConfigData}
|
||||
onExitChainMode={onExitChainMode}
|
||||
availableGroups={availableGroups}
|
||||
activeSelectedGroup={activeSelectedGroup}
|
||||
showScrollTop={showScrollTop}
|
||||
@@ -626,7 +629,7 @@ function NormalProxyGroups(props: { mode: string }) {
|
||||
}
|
||||
|
||||
export const ProxyGroups = (props: Props) => {
|
||||
const { mode, isChainMode = false, chainConfigData } = props
|
||||
const { mode, isChainMode = false, chainConfigData, onExitChainMode } = props
|
||||
const { profiles, isLoading: isProfilesLoading } = useProfiles()
|
||||
const { isProxyViewPending } = useProxiesData()
|
||||
const { isRunningModePending } = useSystemData()
|
||||
@@ -648,7 +651,11 @@ export const ProxyGroups = (props: Props) => {
|
||||
return <ProxyEmptyState reason={listState.reason} />
|
||||
case 'render':
|
||||
return isChainMode ? (
|
||||
<ChainProxyGroups mode={mode} chainConfigData={chainConfigData} />
|
||||
<ChainProxyGroups
|
||||
mode={mode}
|
||||
chainConfigData={chainConfigData}
|
||||
onExitChainMode={onExitChainMode}
|
||||
/>
|
||||
) : (
|
||||
<NormalProxyGroups mode={mode} />
|
||||
)
|
||||
|
||||
@@ -70,6 +70,8 @@
|
||||
"chain": {
|
||||
"header": "Chain Proxy Config",
|
||||
"warning": "Chain proxy will significantly reduce network speed. If you do not have a clear business need, or do not understand this configuration, keep it disabled.",
|
||||
"confirmEnable": "I understand, enable",
|
||||
"keepDisabled": "Keep disabled",
|
||||
"empty": "Chain proxy will significantly reduce network speed. If you do not have a clear business need, or do not understand this configuration, keep it disabled.",
|
||||
"instruction": "Click nodes in order to add to proxy chain",
|
||||
"minimumNodes": "Chain proxy requires at least 2 nodes",
|
||||
|
||||
@@ -70,6 +70,8 @@
|
||||
"chain": {
|
||||
"header": "Proxy-Kette konfigurieren",
|
||||
"warning": "Eine Proxy-Kette verringert die Netzwerkgeschwindigkeit deutlich. Wenn Sie keinen klaren Bedarf haben oder diese Konfiguration nicht verstehen, lassen Sie sie deaktiviert.",
|
||||
"confirmEnable": "Verstanden, aktivieren",
|
||||
"keepDisabled": "Deaktiviert lassen",
|
||||
"empty": "Eine Proxy-Kette verringert die Netzwerkgeschwindigkeit deutlich. Wenn Sie keinen klaren Bedarf haben oder diese Konfiguration nicht verstehen, lassen Sie sie deaktiviert.",
|
||||
"instruction": "Klicken Sie die Knoten nacheinander an, um sie zur Proxy-Kette hinzuzufügen",
|
||||
"minimumNodes": "Eine Proxy-Kette braucht mindestens 2 Knoten",
|
||||
|
||||
@@ -70,6 +70,8 @@
|
||||
"chain": {
|
||||
"header": "Chain Proxy Config",
|
||||
"warning": "Chain proxy will significantly reduce network speed. If you do not have a clear business need, or do not understand this configuration, keep it disabled.",
|
||||
"confirmEnable": "I understand, enable",
|
||||
"keepDisabled": "Keep disabled",
|
||||
"empty": "Chain proxy will significantly reduce network speed. If you do not have a clear business need, or do not understand this configuration, keep it disabled.",
|
||||
"instruction": "Click nodes in order to add to proxy chain",
|
||||
"minimumNodes": "Chain proxy requires at least 2 nodes",
|
||||
|
||||
@@ -70,6 +70,8 @@
|
||||
"chain": {
|
||||
"header": "Chain Proxy Config",
|
||||
"warning": "Chain proxy will significantly reduce network speed. If you do not have a clear business need, or do not understand this configuration, keep it disabled.",
|
||||
"confirmEnable": "I understand, enable",
|
||||
"keepDisabled": "Keep disabled",
|
||||
"empty": "Chain proxy will significantly reduce network speed. If you do not have a clear business need, or do not understand this configuration, keep it disabled.",
|
||||
"instruction": "Click nodes in order to add to proxy chain",
|
||||
"minimumNodes": "Chain proxy requires at least 2 nodes",
|
||||
|
||||
@@ -70,6 +70,8 @@
|
||||
"chain": {
|
||||
"header": "Chain Proxy Config",
|
||||
"warning": "Chain proxy will significantly reduce network speed. If you do not have a clear business need, or do not understand this configuration, keep it disabled.",
|
||||
"confirmEnable": "I understand, enable",
|
||||
"keepDisabled": "Keep disabled",
|
||||
"empty": "Chain proxy will significantly reduce network speed. If you do not have a clear business need, or do not understand this configuration, keep it disabled.",
|
||||
"instruction": "Click nodes in order to add to proxy chain",
|
||||
"minimumNodes": "Chain proxy requires at least 2 nodes",
|
||||
|
||||
@@ -70,6 +70,8 @@
|
||||
"chain": {
|
||||
"header": "Chain Proxy Config",
|
||||
"warning": "Chain proxy will significantly reduce network speed. If you do not have a clear business need, or do not understand this configuration, keep it disabled.",
|
||||
"confirmEnable": "I understand, enable",
|
||||
"keepDisabled": "Keep disabled",
|
||||
"empty": "Chain proxy will significantly reduce network speed. If you do not have a clear business need, or do not understand this configuration, keep it disabled.",
|
||||
"instruction": "Click nodes in order to add to proxy chain",
|
||||
"minimumNodes": "Chain proxy requires at least 2 nodes",
|
||||
|
||||
@@ -70,6 +70,8 @@
|
||||
"chain": {
|
||||
"header": "Chain Proxy Config",
|
||||
"warning": "Chain proxy will significantly reduce network speed. If you do not have a clear business need, or do not understand this configuration, keep it disabled.",
|
||||
"confirmEnable": "I understand, enable",
|
||||
"keepDisabled": "Keep disabled",
|
||||
"empty": "Chain proxy will significantly reduce network speed. If you do not have a clear business need, or do not understand this configuration, keep it disabled.",
|
||||
"instruction": "Click nodes in order to add to proxy chain",
|
||||
"minimumNodes": "Chain proxy requires at least 2 nodes",
|
||||
|
||||
@@ -70,6 +70,8 @@
|
||||
"chain": {
|
||||
"header": "체인 프록시 구성",
|
||||
"warning": "체인 프록시는 네트워크 속도를 크게 저하시킬 수 있습니다. 명확한 업무상 필요가 없거나 이 구성을 이해하지 못한다면 비활성화 상태로 두세요.",
|
||||
"confirmEnable": "이해했습니다, 활성화",
|
||||
"keepDisabled": "비활성화 유지",
|
||||
"empty": "체인 프록시는 네트워크 속도를 크게 저하시킬 수 있습니다. 명확한 업무상 필요가 없거나 이 구성을 이해하지 못한다면 비활성화 상태로 두세요.",
|
||||
"instruction": "프록시 체인에 추가하려면 순서대로 노드를 클릭하세요",
|
||||
"minimumNodes": "체인 프록시는 최소 2개의 노드가 필요합니다",
|
||||
|
||||
@@ -70,6 +70,8 @@
|
||||
"chain": {
|
||||
"header": "Configuração do proxy em cadeia",
|
||||
"warning": "O proxy em cadeia reduz significativamente a velocidade da rede. Se você não tem uma necessidade clara ou não entende esta configuração, mantenha-o desativado.",
|
||||
"confirmEnable": "Entendi, ativar",
|
||||
"keepDisabled": "Manter desativado",
|
||||
"empty": "O proxy em cadeia reduz significativamente a velocidade da rede. Se você não tem uma necessidade clara ou não entende esta configuração, mantenha-o desativado.",
|
||||
"instruction": "Clique nos nós em ordem para adicioná-los à cadeia de proxy",
|
||||
"minimumNodes": "O proxy em cadeia requer pelo menos 2 nós",
|
||||
|
||||
@@ -70,6 +70,8 @@
|
||||
"chain": {
|
||||
"header": "Цепочка прокси",
|
||||
"warning": "Цепочка прокси может значительно снизить скорость сети. Если у вас нет явной рабочей необходимости или вы не понимаете эту настройку, оставьте ее отключенной.",
|
||||
"confirmEnable": "Понятно, включить",
|
||||
"keepDisabled": "Оставить выключенным",
|
||||
"empty": "Цепочка прокси может значительно снизить скорость сети. Если у вас нет явной рабочей необходимости или вы не понимаете эту настройку, оставьте ее отключенной.",
|
||||
"instruction": "Нажимайте на узлы по порядку, чтобы добавить их в цепочку",
|
||||
"minimumNodes": "Для цепочки требуется минимум 2 узла",
|
||||
|
||||
@@ -70,6 +70,8 @@
|
||||
"chain": {
|
||||
"header": "Zincir Vekil Yapılandırması",
|
||||
"warning": "Zincir vekil ağ hızını belirgin biçimde düşürür. Açık bir ihtiyacınız yoksa ya da bu yapılandırmayı bilmiyorsanız devre dışı bırakın.",
|
||||
"confirmEnable": "Anladım, etkinleştir",
|
||||
"keepDisabled": "Devre dışı kalsın",
|
||||
"empty": "Zincir vekil ağ hızını belirgin biçimde düşürür. Açık bir ihtiyacınız yoksa ya da bu yapılandırmayı bilmiyorsanız devre dışı bırakın.",
|
||||
"instruction": "Vekil zincirine eklemek için düğümlere sırayla tıklayın",
|
||||
"minimumNodes": "Zincir vekil en az 2 düğüm gerektirir",
|
||||
|
||||
@@ -70,6 +70,8 @@
|
||||
"chain": {
|
||||
"header": "Chain Proxy Config",
|
||||
"warning": "Chain proxy will significantly reduce network speed. If you do not have a clear business need, or do not understand this configuration, keep it disabled.",
|
||||
"confirmEnable": "I understand, enable",
|
||||
"keepDisabled": "Keep disabled",
|
||||
"empty": "Chain proxy will significantly reduce network speed. If you do not have a clear business need, or do not understand this configuration, keep it disabled.",
|
||||
"instruction": "Click nodes in order to add to proxy chain",
|
||||
"minimumNodes": "Chain proxy requires at least 2 nodes",
|
||||
|
||||
@@ -70,6 +70,8 @@
|
||||
"chain": {
|
||||
"header": "代理链配置",
|
||||
"warning": "链式代理会显著降低网速。如果您没有明确的业务需求,或不了解此项配置,请保持关闭",
|
||||
"confirmEnable": "我明白,开启",
|
||||
"keepDisabled": "保持关闭",
|
||||
"empty": "链式代理会显著降低网速。如果您没有明确的业务需求,或不了解此项配置,请保持关闭",
|
||||
"instruction": "顺序点击节点添加到代理链中",
|
||||
"minimumNodes": "链式代理至少需要 2 个节点",
|
||||
|
||||
@@ -70,6 +70,8 @@
|
||||
"chain": {
|
||||
"header": "鏈式代理設定",
|
||||
"warning": "鏈式代理會顯著降低網速。如果您沒有明確的業務需求,或不了解此項設定,請保持關閉",
|
||||
"confirmEnable": "我明白,開啟",
|
||||
"keepDisabled": "保持關閉",
|
||||
"empty": "鏈式代理會顯著降低網速。如果您沒有明確的業務需求,或不了解此項設定,請保持關閉",
|
||||
"instruction": "依序點擊節點新增到鏈式代理中",
|
||||
"minimumNodes": "鏈式代理至少需要 2 個節點",
|
||||
|
||||
+43
-24
@@ -1,10 +1,10 @@
|
||||
import { LanOutlined, LanRounded, WarningRounded } from '@mui/icons-material'
|
||||
import { Box, Button, ButtonGroup } from '@mui/material'
|
||||
import { Box, Button, ButtonGroup, Typography } from '@mui/material'
|
||||
import { useLockFn } from 'ahooks'
|
||||
import { useCallback, useEffect, useReducer, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
|
||||
import { BasePage, TooltipIcon } from '@/components/base'
|
||||
import { BaseDialog, BasePage, TooltipIcon } from '@/components/base'
|
||||
import { ProviderButton } from '@/components/proxy/provider-button'
|
||||
import { ProxyGroups } from '@/components/proxy/proxy-groups'
|
||||
import {
|
||||
@@ -38,6 +38,7 @@ const ProxyPage = () => {
|
||||
return false
|
||||
}
|
||||
})
|
||||
const [chainConfirmOpen, setChainConfirmOpen] = useState(false)
|
||||
|
||||
const [chainConfigData, dispatchChainConfigData] = useReducer(
|
||||
(_: string | null, action: string | null) => action,
|
||||
@@ -68,32 +69,34 @@ const ProxyPage = () => {
|
||||
}
|
||||
})
|
||||
|
||||
const onToggleChainMode = useLockFn(async () => {
|
||||
const newChainMode = !isChainMode
|
||||
const applyChainMode = (enabled: boolean) => {
|
||||
setIsChainMode(enabled)
|
||||
localStorage.setItem('proxy-chain-mode-enabled', enabled.toString())
|
||||
}
|
||||
|
||||
if (!newChainMode) {
|
||||
// 退出链式代理模式时,清除链式代理配置
|
||||
try {
|
||||
debugLog('Exiting chain mode, clearing chain configuration')
|
||||
const result = await mutate(
|
||||
() => updateProxyChainConfigInRuntime(null),
|
||||
{
|
||||
id: 'update-proxy-chain-runtime',
|
||||
errorNotice: false,
|
||||
},
|
||||
)
|
||||
if (!result.ok) return
|
||||
debugLog('Chain configuration cleared successfully')
|
||||
} catch (error) {
|
||||
console.error('Failed to clear chain configuration:', error)
|
||||
showNotice.error(error)
|
||||
return
|
||||
}
|
||||
const onExitChainMode = useLockFn(async () => {
|
||||
// 退出链式代理模式时,清除链式代理配置
|
||||
try {
|
||||
debugLog('Exiting chain mode, clearing chain configuration')
|
||||
const result = await mutate(() => updateProxyChainConfigInRuntime(null), {
|
||||
id: 'update-proxy-chain-runtime',
|
||||
errorNotice: false,
|
||||
})
|
||||
if (!result.ok) return
|
||||
debugLog('Chain configuration cleared successfully')
|
||||
} catch (error) {
|
||||
console.error('Failed to clear chain configuration:', error)
|
||||
showNotice.error(error)
|
||||
return
|
||||
}
|
||||
setIsChainMode(newChainMode)
|
||||
localStorage.setItem('proxy-chain-mode-enabled', newChainMode.toString())
|
||||
applyChainMode(false)
|
||||
})
|
||||
|
||||
const onToggleChainMode = () => {
|
||||
if (isChainMode) onExitChainMode().catch(() => {})
|
||||
else setChainConfirmOpen(true)
|
||||
}
|
||||
|
||||
// 当开启链式代理模式时,获取配置数据
|
||||
useEffect(() => {
|
||||
if (!isChainMode) {
|
||||
@@ -202,7 +205,23 @@ const ProxyPage = () => {
|
||||
mode={curMode ?? 'rule'}
|
||||
isChainMode={isChainMode}
|
||||
chainConfigData={chainConfigData}
|
||||
onExitChainMode={onExitChainMode}
|
||||
/>
|
||||
<BaseDialog
|
||||
open={chainConfirmOpen}
|
||||
title={t('proxies.page.actions.toggleChain')}
|
||||
okBtn={t('proxies.page.chain.confirmEnable')}
|
||||
cancelBtn={t('proxies.page.chain.keepDisabled')}
|
||||
contentSx={{ width: { xs: 320, sm: 420 } }}
|
||||
onCancel={() => setChainConfirmOpen(false)}
|
||||
onClose={() => setChainConfirmOpen(false)}
|
||||
onOk={() => {
|
||||
setChainConfirmOpen(false)
|
||||
applyChainMode(true)
|
||||
}}
|
||||
>
|
||||
<Typography variant="body2">{chainWarning}</Typography>
|
||||
</BaseDialog>
|
||||
</BasePage>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -322,6 +322,8 @@ export const translationKeys = [
|
||||
'proxies.page.empty.actions.openLogs',
|
||||
'proxies.page.chain.header',
|
||||
'proxies.page.chain.warning',
|
||||
'proxies.page.chain.confirmEnable',
|
||||
'proxies.page.chain.keepDisabled',
|
||||
'proxies.page.chain.empty',
|
||||
'proxies.page.chain.instruction',
|
||||
'proxies.page.chain.minimumNodes',
|
||||
|
||||
@@ -525,6 +525,7 @@ export interface TranslationResources {
|
||||
toggleChain: string
|
||||
}
|
||||
chain: {
|
||||
confirmEnable: string
|
||||
connectFailed: string
|
||||
disconnectFailed: string
|
||||
duplicateNode: string
|
||||
@@ -533,6 +534,7 @@ export interface TranslationResources {
|
||||
exitNode: string
|
||||
header: string
|
||||
instruction: string
|
||||
keepDisabled: string
|
||||
minimumNodes: string
|
||||
minimumNodesHint: string
|
||||
warning: string
|
||||
|
||||
Reference in New Issue
Block a user