mirror of
https://github.com/clash-verge-rev/clash-verge-rev.git
synced 2026-11-14 14:52:08 +08:00
feat(proxies): add empty-state troubleshooting guidance
This commit is contained in:
@@ -0,0 +1,88 @@
|
||||
import type { ProxyViewV1 } from '@/types/proxy-view'
|
||||
|
||||
export type ProxyEmptyStateReason =
|
||||
| 'no-subscriptions'
|
||||
| 'inactive-subscription'
|
||||
| 'core-unavailable'
|
||||
| 'no-proxy-info'
|
||||
|
||||
type ProfileSummary = {
|
||||
current?: string
|
||||
items?: Array<{
|
||||
uid?: string
|
||||
type?: string
|
||||
}>
|
||||
}
|
||||
|
||||
interface ProxyEmptyStateInput {
|
||||
mode: string
|
||||
isChainMode: boolean
|
||||
profiles?: ProfileSummary
|
||||
isProfilesPending: boolean
|
||||
proxyView?: ProxyViewV1
|
||||
isProxyViewPending: boolean
|
||||
isProxyViewError: boolean
|
||||
runningMode?: string
|
||||
isRunningModePending: boolean
|
||||
}
|
||||
|
||||
const isSubscriptionProfile = (item: { type?: string }): boolean =>
|
||||
item.type === 'remote' || item.type === 'local'
|
||||
|
||||
export const hasRenderableProxyContent = (
|
||||
proxyView: ProxyViewV1 | undefined,
|
||||
mode: string,
|
||||
isChainMode: boolean,
|
||||
) => {
|
||||
if (!proxyView) return false
|
||||
|
||||
if (isChainMode) {
|
||||
return proxyView.groups.some(
|
||||
(group) => group.type === 'Selector' || group.type === 'URLTest',
|
||||
)
|
||||
}
|
||||
|
||||
if (mode === 'rule' || mode === 'script') {
|
||||
return proxyView.groups.some((group) => !group.hidden)
|
||||
}
|
||||
|
||||
return proxyView.global !== null
|
||||
}
|
||||
|
||||
export const resolveProxyEmptyState = ({
|
||||
mode,
|
||||
isChainMode,
|
||||
profiles,
|
||||
isProfilesPending,
|
||||
proxyView,
|
||||
isProxyViewPending,
|
||||
isProxyViewError,
|
||||
runningMode,
|
||||
isRunningModePending,
|
||||
}: ProxyEmptyStateInput): ProxyEmptyStateReason | 'loading' | null => {
|
||||
if (mode === 'direct') return null
|
||||
|
||||
if (isProfilesPending || isProxyViewPending || isRunningModePending) {
|
||||
return 'loading'
|
||||
}
|
||||
|
||||
if (profiles) {
|
||||
const subscriptions = (profiles.items ?? []).filter(isSubscriptionProfile)
|
||||
if (subscriptions.length === 0) return 'no-subscriptions'
|
||||
|
||||
const hasActiveSubscription = subscriptions.some(
|
||||
(item) => item.uid === profiles.current,
|
||||
)
|
||||
if (!hasActiveSubscription) return 'inactive-subscription'
|
||||
}
|
||||
|
||||
if (hasRenderableProxyContent(proxyView, mode, isChainMode)) {
|
||||
return null
|
||||
}
|
||||
|
||||
if (runningMode === 'NotRunning' || isProxyViewError) {
|
||||
return 'core-unavailable'
|
||||
}
|
||||
|
||||
return 'no-proxy-info'
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
import { Alert, AlertTitle, Box, Button, Stack } from '@mui/material'
|
||||
import { useLockFn } from 'ahooks'
|
||||
import { useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useNavigate } from 'react-router'
|
||||
|
||||
import { useAppRefreshers } from '@/providers/app-data-context'
|
||||
import { openLogsDir, restartCore } from '@/services/cmds'
|
||||
import { showNotice } from '@/services/notice-service'
|
||||
import { revalidateQuery } from '@/services/query-client'
|
||||
|
||||
import type { ProxyEmptyStateReason } from './proxy-empty-state-model'
|
||||
|
||||
interface Props {
|
||||
reason: ProxyEmptyStateReason
|
||||
}
|
||||
|
||||
export const ProxyEmptyState = ({ reason }: Props) => {
|
||||
const { t } = useTranslation()
|
||||
const navigate = useNavigate()
|
||||
const { refreshProxy } = useAppRefreshers()
|
||||
const [isRestarting, setIsRestarting] = useState(false)
|
||||
|
||||
const handleRestart = useLockFn(async () => {
|
||||
setIsRestarting(true)
|
||||
try {
|
||||
await restartCore()
|
||||
await Promise.all([refreshProxy(), revalidateQuery(['getRunningMode'])])
|
||||
} catch (error) {
|
||||
showNotice.error(error)
|
||||
} finally {
|
||||
setIsRestarting(false)
|
||||
}
|
||||
})
|
||||
|
||||
const title =
|
||||
reason === 'no-subscriptions'
|
||||
? t('proxies.page.empty.noSubscriptions.title')
|
||||
: reason === 'inactive-subscription'
|
||||
? t('proxies.page.empty.inactiveSubscription.title')
|
||||
: reason === 'core-unavailable'
|
||||
? t('proxies.page.empty.coreUnavailable.title')
|
||||
: t('proxies.page.empty.noProxyInfo.title')
|
||||
const description =
|
||||
reason === 'no-subscriptions'
|
||||
? t('proxies.page.empty.noSubscriptions.description')
|
||||
: reason === 'inactive-subscription'
|
||||
? t('proxies.page.empty.inactiveSubscription.description')
|
||||
: reason === 'core-unavailable'
|
||||
? t('proxies.page.empty.coreUnavailable.description')
|
||||
: t('proxies.page.empty.noProxyInfo.description')
|
||||
const showProfiles =
|
||||
reason === 'no-subscriptions' ||
|
||||
reason === 'inactive-subscription' ||
|
||||
reason === 'no-proxy-info'
|
||||
const showCoreActions =
|
||||
reason === 'core-unavailable' || reason === 'no-proxy-info'
|
||||
|
||||
return (
|
||||
<Box
|
||||
sx={{
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
p: 2,
|
||||
}}
|
||||
>
|
||||
<Alert
|
||||
severity="warning"
|
||||
variant="outlined"
|
||||
sx={{ width: '100%', maxWidth: 640 }}
|
||||
>
|
||||
<AlertTitle>{title}</AlertTitle>
|
||||
{description}
|
||||
|
||||
<Stack
|
||||
direction="row"
|
||||
spacing={1}
|
||||
useFlexGap
|
||||
sx={{ mt: 2, flexWrap: 'wrap' }}
|
||||
>
|
||||
{showProfiles && (
|
||||
<Button
|
||||
size="small"
|
||||
variant="contained"
|
||||
onClick={() => navigate('/profile')}
|
||||
>
|
||||
{t('proxies.page.empty.actions.openProfiles')}
|
||||
</Button>
|
||||
)}
|
||||
|
||||
{showCoreActions && (
|
||||
<>
|
||||
<Button
|
||||
size="small"
|
||||
variant="contained"
|
||||
loading={isRestarting}
|
||||
onClick={() => void handleRestart()}
|
||||
>
|
||||
{t('proxies.page.empty.actions.restartCore')}
|
||||
</Button>
|
||||
<Button
|
||||
size="small"
|
||||
variant="outlined"
|
||||
disabled={isRestarting}
|
||||
onClick={() => void openLogsDir()}
|
||||
>
|
||||
{t('proxies.page.empty.actions.openLogs')}
|
||||
</Button>
|
||||
</>
|
||||
)}
|
||||
</Stack>
|
||||
</Alert>
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
@@ -18,9 +18,10 @@ import {
|
||||
StickyVirtualList,
|
||||
type StickyVirtualListHandle,
|
||||
} from '@/components/base'
|
||||
import { useProfiles } from '@/hooks/use-profiles'
|
||||
import { useProxySelection } from '@/hooks/use-proxy-selection'
|
||||
import { useVerge } from '@/hooks/use-verge'
|
||||
import { useProxiesData } from '@/providers/app-data-context'
|
||||
import { useProxiesData, useSystemData } from '@/providers/app-data-context'
|
||||
import delayManager from '@/services/delay'
|
||||
import {
|
||||
isInteractableMember,
|
||||
@@ -30,6 +31,8 @@ import {
|
||||
} from '@/types/proxy-view'
|
||||
import { debugLog } from '@/utils/debug'
|
||||
|
||||
import { ProxyEmptyState } from './proxy-empty-state'
|
||||
import { resolveProxyEmptyState } from './proxy-empty-state-model'
|
||||
import {
|
||||
DEFAULT_HOVER_DELAY,
|
||||
ProxyGroupNavigator,
|
||||
@@ -598,11 +601,34 @@ function NormalProxyGroups(props: { mode: string }) {
|
||||
|
||||
export const ProxyGroups = (props: Props) => {
|
||||
const { mode, isChainMode = false, chainConfigData } = props
|
||||
const { profiles, isLoading: isProfilesLoading } = useProfiles()
|
||||
const { proxyView, isProxyViewPending, isProxyViewError } = useProxiesData()
|
||||
const { runningMode, isRunningModePending } = useSystemData()
|
||||
|
||||
const emptyState = resolveProxyEmptyState({
|
||||
mode,
|
||||
isChainMode,
|
||||
profiles,
|
||||
isProfilesPending: !profiles && isProfilesLoading,
|
||||
proxyView,
|
||||
isProxyViewPending,
|
||||
isProxyViewError,
|
||||
runningMode,
|
||||
isRunningModePending,
|
||||
})
|
||||
|
||||
if (mode === 'direct') {
|
||||
return <BaseEmpty textKey="proxies.page.messages.directMode" />
|
||||
}
|
||||
|
||||
if (emptyState === 'loading') {
|
||||
return <BaseLoading />
|
||||
}
|
||||
|
||||
if (emptyState) {
|
||||
return <ProxyEmptyState reason={emptyState} />
|
||||
}
|
||||
|
||||
if (isChainMode) {
|
||||
return <ChainProxyGroups mode={mode} chainConfigData={chainConfigData} />
|
||||
}
|
||||
|
||||
@@ -44,7 +44,28 @@
|
||||
},
|
||||
"empty": {
|
||||
"noAvailableGroups": "لا توجد مجموعات وكيل متاحة",
|
||||
"noProxies": "لا توجد وكلاء"
|
||||
"noProxies": "لا توجد وكلاء",
|
||||
"noSubscriptions": {
|
||||
"title": "لم يتم استيراد أي اشتراك",
|
||||
"description": "لا يوجد محتوى لعرضه في صفحة الوكلاء. انتقل إلى صفحة «الملفات الشخصية» لاستيراد اشتراك وتفعيله."
|
||||
},
|
||||
"inactiveSubscription": {
|
||||
"title": "لا يوجد اشتراك مفعّل",
|
||||
"description": "تم العثور على اشتراكات، لكن لا يوجد أي اشتراك مفعّل حاليًا. انتقل إلى صفحة «الملفات الشخصية» واختر اشتراكًا لتفعيله."
|
||||
},
|
||||
"coreUnavailable": {
|
||||
"title": "النواة غير متاحة مؤقتًا",
|
||||
"description": "تعذر الحصول على معلومات الوكلاء من النواة. حاول إعادة تشغيل النواة. إذا استمرت المشكلة، افتح مجلد السجلات وتحقق من سجلات النواة."
|
||||
},
|
||||
"noProxyInfo": {
|
||||
"title": "معلومات الوكلاء غير متاحة",
|
||||
"description": "لا توجد مجموعات أو عقد وكلاء لعرضها. تحقق من أن الاشتراك المفعّل يحتوي على مجموعات وعقد صالحة، أو أعد تشغيل النواة وراجع السجلات."
|
||||
},
|
||||
"actions": {
|
||||
"openProfiles": "الانتقال إلى الملفات الشخصية",
|
||||
"restartCore": "إعادة تشغيل النواة",
|
||||
"openLogs": "فتح مجلد السجلات"
|
||||
}
|
||||
},
|
||||
"chain": {
|
||||
"header": "Chain Proxy Config",
|
||||
|
||||
@@ -44,7 +44,28 @@
|
||||
},
|
||||
"empty": {
|
||||
"noAvailableGroups": "Keine Proxy-Gruppen verfügbar",
|
||||
"noProxies": "Keine Proxys"
|
||||
"noProxies": "Keine Proxys",
|
||||
"noSubscriptions": {
|
||||
"title": "Kein Abonnement importiert",
|
||||
"description": "Auf der Proxy-Seite gibt es nichts anzuzeigen. Öffnen Sie „Abonnement“, um ein Abonnement zu importieren und zu aktivieren."
|
||||
},
|
||||
"inactiveSubscription": {
|
||||
"title": "Kein aktives Abonnement",
|
||||
"description": "Es wurden Abonnements gefunden, aber keines ist derzeit aktiv. Öffnen Sie „Abonnement“, wählen Sie eines aus und aktivieren Sie es."
|
||||
},
|
||||
"coreUnavailable": {
|
||||
"title": "Kern vorübergehend nicht verfügbar",
|
||||
"description": "Die Proxy-Informationen konnten nicht vom Kern abgerufen werden. Starten Sie den Kern neu. Falls das Problem weiterhin besteht, öffnen Sie den Protokollordner und prüfen Sie die Kernprotokolle."
|
||||
},
|
||||
"noProxyInfo": {
|
||||
"title": "Keine Proxy-Informationen verfügbar",
|
||||
"description": "Es gibt keine Proxy-Gruppen oder -Knoten zum Anzeigen. Prüfen Sie, ob das aktive Abonnement gültige Proxy-Gruppen und -Knoten enthält, oder starten Sie den Kern neu und prüfen Sie die Protokolle."
|
||||
},
|
||||
"actions": {
|
||||
"openProfiles": "Zum Abonnement",
|
||||
"restartCore": "Kern neu starten",
|
||||
"openLogs": "Protokollordner öffnen"
|
||||
}
|
||||
},
|
||||
"chain": {
|
||||
"header": "Chain Proxy Config",
|
||||
|
||||
@@ -44,7 +44,28 @@
|
||||
},
|
||||
"empty": {
|
||||
"noAvailableGroups": "No proxy groups are available",
|
||||
"noProxies": "No proxies"
|
||||
"noProxies": "No proxies",
|
||||
"noSubscriptions": {
|
||||
"title": "No subscription imported",
|
||||
"description": "There is nothing to display on the Proxies page. Go to Profiles to import and activate a subscription."
|
||||
},
|
||||
"inactiveSubscription": {
|
||||
"title": "No active subscription",
|
||||
"description": "Subscriptions were found, but none is currently active. Go to Profiles and select one to activate."
|
||||
},
|
||||
"coreUnavailable": {
|
||||
"title": "Core temporarily unavailable",
|
||||
"description": "Proxy information could not be retrieved from the core. Try restarting the core. If the problem persists, open the logs folder and check the core logs."
|
||||
},
|
||||
"noProxyInfo": {
|
||||
"title": "No proxy information available",
|
||||
"description": "There are no proxy groups or nodes to display. Check that the active subscription contains valid proxy groups and nodes, or restart the core and review the logs."
|
||||
},
|
||||
"actions": {
|
||||
"openProfiles": "Go to Profiles",
|
||||
"restartCore": "Restart Core",
|
||||
"openLogs": "Open Logs Folder"
|
||||
}
|
||||
},
|
||||
"chain": {
|
||||
"header": "Chain Proxy Config",
|
||||
|
||||
@@ -44,7 +44,28 @@
|
||||
},
|
||||
"empty": {
|
||||
"noAvailableGroups": "No hay grupos de proxy disponibles",
|
||||
"noProxies": "Sin proxies"
|
||||
"noProxies": "Sin proxies",
|
||||
"noSubscriptions": {
|
||||
"title": "No se ha importado ninguna suscripción",
|
||||
"description": "No hay contenido para mostrar en la página de proxies. Ve a Perfiles para importar y activar una suscripción."
|
||||
},
|
||||
"inactiveSubscription": {
|
||||
"title": "No hay ninguna suscripción activa",
|
||||
"description": "Se encontraron suscripciones, pero ninguna está activa. Ve a Perfiles, selecciona una suscripción y actívala."
|
||||
},
|
||||
"coreUnavailable": {
|
||||
"title": "El núcleo no está disponible temporalmente",
|
||||
"description": "No se pudo obtener la información de proxies del núcleo. Intenta reiniciar el núcleo. Si el problema continúa, abre la carpeta de registros y revisa los registros del núcleo."
|
||||
},
|
||||
"noProxyInfo": {
|
||||
"title": "No hay información de proxies disponible",
|
||||
"description": "No hay grupos ni nodos de proxy para mostrar. Comprueba que la suscripción activa contenga grupos y nodos válidos, o reinicia el núcleo y revisa los registros."
|
||||
},
|
||||
"actions": {
|
||||
"openProfiles": "Ir a Perfiles",
|
||||
"restartCore": "Reiniciar núcleo",
|
||||
"openLogs": "Abrir carpeta de registros"
|
||||
}
|
||||
},
|
||||
"chain": {
|
||||
"header": "Chain Proxy Config",
|
||||
|
||||
@@ -44,7 +44,28 @@
|
||||
},
|
||||
"empty": {
|
||||
"noAvailableGroups": "هیچ گروه پروکسی در دسترس نیست",
|
||||
"noProxies": "پروکسیای وجود ندارد"
|
||||
"noProxies": "پروکسیای وجود ندارد",
|
||||
"noSubscriptions": {
|
||||
"title": "هیچ اشتراکی وارد نشده است",
|
||||
"description": "چیزی برای نمایش در صفحه پروکسی وجود ندارد. برای وارد کردن و فعالسازی اشتراک به صفحه «پروفایلها» بروید."
|
||||
},
|
||||
"inactiveSubscription": {
|
||||
"title": "هیچ اشتراک فعالی وجود ندارد",
|
||||
"description": "اشتراکهایی پیدا شدند، اما در حال حاضر هیچکدام فعال نیستند. به صفحه «پروفایلها» بروید، یک اشتراک را انتخاب و فعال کنید."
|
||||
},
|
||||
"coreUnavailable": {
|
||||
"title": "هسته موقتاً در دسترس نیست",
|
||||
"description": "دریافت اطلاعات پروکسی از هسته ممکن نشد. هسته را دوباره راهاندازی کنید. اگر مشکل ادامه داشت، پوشه گزارشها را باز کرده و گزارشهای هسته را بررسی کنید."
|
||||
},
|
||||
"noProxyInfo": {
|
||||
"title": "اطلاعات پروکسی در دسترس نیست",
|
||||
"description": "هیچ گروه یا گره پروکسی برای نمایش وجود ندارد. بررسی کنید که اشتراک فعال دارای گروهها و گرههای معتبر باشد، یا هسته را دوباره راهاندازی کرده و گزارشها را ببینید."
|
||||
},
|
||||
"actions": {
|
||||
"openProfiles": "رفتن به پروفایلها",
|
||||
"restartCore": "راهاندازی مجدد هسته",
|
||||
"openLogs": "باز کردن پوشه گزارشها"
|
||||
}
|
||||
},
|
||||
"chain": {
|
||||
"header": "Chain Proxy Config",
|
||||
|
||||
@@ -44,7 +44,28 @@
|
||||
},
|
||||
"empty": {
|
||||
"noAvailableGroups": "Tidak ada grup proxy yang tersedia",
|
||||
"noProxies": "Tidak ada proxy"
|
||||
"noProxies": "Tidak ada proxy",
|
||||
"noSubscriptions": {
|
||||
"title": "Belum ada langganan yang diimpor",
|
||||
"description": "Tidak ada yang dapat ditampilkan di halaman Proksi. Buka halaman Profil untuk mengimpor dan mengaktifkan langganan."
|
||||
},
|
||||
"inactiveSubscription": {
|
||||
"title": "Tidak ada langganan aktif",
|
||||
"description": "Langganan ditemukan, tetapi tidak ada yang sedang aktif. Buka halaman Profil, lalu pilih dan aktifkan langganan."
|
||||
},
|
||||
"coreUnavailable": {
|
||||
"title": "Inti sementara tidak tersedia",
|
||||
"description": "Informasi proksi tidak dapat diambil dari inti. Coba mulai ulang inti. Jika masalah berlanjut, buka folder log dan periksa log inti."
|
||||
},
|
||||
"noProxyInfo": {
|
||||
"title": "Informasi proksi tidak tersedia",
|
||||
"description": "Tidak ada grup atau node proksi yang dapat ditampilkan. Pastikan langganan aktif berisi grup dan node yang valid, atau mulai ulang inti dan periksa log."
|
||||
},
|
||||
"actions": {
|
||||
"openProfiles": "Buka Profil",
|
||||
"restartCore": "Mulai Ulang Inti",
|
||||
"openLogs": "Buka Folder Log"
|
||||
}
|
||||
},
|
||||
"chain": {
|
||||
"header": "Chain Proxy Config",
|
||||
|
||||
@@ -44,7 +44,28 @@
|
||||
},
|
||||
"empty": {
|
||||
"noAvailableGroups": "利用可能なプロキシグループがありません",
|
||||
"noProxies": "プロキシがありません"
|
||||
"noProxies": "プロキシがありません",
|
||||
"noSubscriptions": {
|
||||
"title": "サブスクリプションがインポートされていません",
|
||||
"description": "プロキシページに表示する内容がありません。プロファイルページでサブスクリプションをインポートして有効化してください。"
|
||||
},
|
||||
"inactiveSubscription": {
|
||||
"title": "有効なサブスクリプションがありません",
|
||||
"description": "サブスクリプションは見つかりましたが、現在有効なものがありません。プロファイルページで選択して有効化してください。"
|
||||
},
|
||||
"coreUnavailable": {
|
||||
"title": "コアを一時的に利用できません",
|
||||
"description": "コアからプロキシ情報を取得できませんでした。コアを再起動してください。問題が解決しない場合は、ログフォルダーを開いてコアのログを確認してください。"
|
||||
},
|
||||
"noProxyInfo": {
|
||||
"title": "プロキシ情報を取得できませんでした",
|
||||
"description": "表示できるプロキシグループまたはノードがありません。有効なサブスクリプションに正しいプロキシグループとノードが含まれているか確認するか、コアを再起動してログを確認してください。"
|
||||
},
|
||||
"actions": {
|
||||
"openProfiles": "プロファイルへ移動",
|
||||
"restartCore": "コアを再起動",
|
||||
"openLogs": "ログフォルダーを開く"
|
||||
}
|
||||
},
|
||||
"chain": {
|
||||
"header": "Chain Proxy Config",
|
||||
|
||||
@@ -44,7 +44,28 @@
|
||||
},
|
||||
"empty": {
|
||||
"noAvailableGroups": "사용 가능한 프록시 그룹이 없습니다",
|
||||
"noProxies": "프록시 없음"
|
||||
"noProxies": "프록시 없음",
|
||||
"noSubscriptions": {
|
||||
"title": "가져온 구독이 없습니다",
|
||||
"description": "프록시 페이지에 표시할 내용이 없습니다. 프로필 페이지에서 구독을 가져와 활성화하세요."
|
||||
},
|
||||
"inactiveSubscription": {
|
||||
"title": "활성화된 구독이 없습니다",
|
||||
"description": "구독이 있지만 현재 활성화된 구독이 없습니다. 프로필 페이지에서 구독을 선택하고 활성화하세요."
|
||||
},
|
||||
"coreUnavailable": {
|
||||
"title": "코어를 일시적으로 사용할 수 없습니다",
|
||||
"description": "코어에서 프록시 정보를 가져오지 못했습니다. 코어를 재시작해 보세요. 문제가 계속되면 로그 폴더를 열어 코어 로그를 확인하세요."
|
||||
},
|
||||
"noProxyInfo": {
|
||||
"title": "프록시 정보를 가져오지 못했습니다",
|
||||
"description": "표시할 프록시 그룹이나 노드가 없습니다. 활성 구독에 유효한 프록시 그룹과 노드가 포함되어 있는지 확인하거나 코어를 재시작하고 로그를 확인하세요."
|
||||
},
|
||||
"actions": {
|
||||
"openProfiles": "프로필로 이동",
|
||||
"restartCore": "코어 재시작",
|
||||
"openLogs": "로그 폴더 열기"
|
||||
}
|
||||
},
|
||||
"chain": {
|
||||
"header": "체인 프록시 구성",
|
||||
|
||||
@@ -44,7 +44,28 @@
|
||||
},
|
||||
"empty": {
|
||||
"noAvailableGroups": "Нет доступных групп прокси",
|
||||
"noProxies": "Нет прокси"
|
||||
"noProxies": "Нет прокси",
|
||||
"noSubscriptions": {
|
||||
"title": "Нет импортированных подписок",
|
||||
"description": "На странице прокси нечего отображать. Перейдите в раздел «Профили», чтобы импортировать и активировать подписку."
|
||||
},
|
||||
"inactiveSubscription": {
|
||||
"title": "Нет активной подписки",
|
||||
"description": "Подписки найдены, но ни одна из них сейчас не активна. Перейдите в раздел «Профили», выберите подписку и активируйте её."
|
||||
},
|
||||
"coreUnavailable": {
|
||||
"title": "Ядро временно недоступно",
|
||||
"description": "Не удалось получить информацию о прокси от ядра. Попробуйте перезапустить ядро. Если проблема сохраняется, откройте папку журналов и проверьте журналы ядра."
|
||||
},
|
||||
"noProxyInfo": {
|
||||
"title": "Нет информации о прокси",
|
||||
"description": "Нет групп или узлов прокси для отображения. Убедитесь, что активная подписка содержит допустимые группы и узлы, либо перезапустите ядро и проверьте журналы."
|
||||
},
|
||||
"actions": {
|
||||
"openProfiles": "Перейти к профилям",
|
||||
"restartCore": "Перезапустить ядро",
|
||||
"openLogs": "Открыть папку журналов"
|
||||
}
|
||||
},
|
||||
"chain": {
|
||||
"header": "Цепочка прокси",
|
||||
|
||||
@@ -44,7 +44,28 @@
|
||||
},
|
||||
"empty": {
|
||||
"noAvailableGroups": "Kullanılabilir proxy grubu yok",
|
||||
"noProxies": "Proxy yok"
|
||||
"noProxies": "Proxy yok",
|
||||
"noSubscriptions": {
|
||||
"title": "İçe aktarılmış abonelik yok",
|
||||
"description": "Proxy sayfasında görüntülenecek içerik yok. Bir aboneliği içe aktarmak ve etkinleştirmek için Profiller sayfasına gidin."
|
||||
},
|
||||
"inactiveSubscription": {
|
||||
"title": "Etkin abonelik yok",
|
||||
"description": "Abonelikler bulundu ancak hiçbiri şu anda etkin değil. Profiller sayfasına gidip bir abonelik seçin ve etkinleştirin."
|
||||
},
|
||||
"coreUnavailable": {
|
||||
"title": "Çekirdek geçici olarak kullanılamıyor",
|
||||
"description": "Proxy bilgileri çekirdekten alınamadı. Çekirdeği yeniden başlatmayı deneyin. Sorun devam ederse günlükler klasörünü açıp çekirdek günlüklerini kontrol edin."
|
||||
},
|
||||
"noProxyInfo": {
|
||||
"title": "Proxy bilgisi yok",
|
||||
"description": "Görüntülenecek proxy grubu veya düğümü yok. Etkin aboneliğin geçerli proxy grupları ve düğümleri içerdiğini doğrulayın ya da çekirdeği yeniden başlatıp günlükleri inceleyin."
|
||||
},
|
||||
"actions": {
|
||||
"openProfiles": "Profillere Git",
|
||||
"restartCore": "Çekirdeği Yeniden Başlat",
|
||||
"openLogs": "Günlükler Klasörünü Aç"
|
||||
}
|
||||
},
|
||||
"chain": {
|
||||
"header": "Chain Proxy Config",
|
||||
|
||||
@@ -44,7 +44,28 @@
|
||||
},
|
||||
"empty": {
|
||||
"noAvailableGroups": "Кулланырлык прокси төркемнәре юк",
|
||||
"noProxies": "Проксилар юк"
|
||||
"noProxies": "Проксилар юк",
|
||||
"noSubscriptions": {
|
||||
"title": "Язылу импортланмаган",
|
||||
"description": "Прокси битендә күрсәтерлек мәгълүмат юк. Язылуны импортлау һәм активлаштыру өчен «Профильләр» битенә күчегез."
|
||||
},
|
||||
"inactiveSubscription": {
|
||||
"title": "Актив язылу юк",
|
||||
"description": "Язылулар табылды, ләкин хәзер берсе дә актив түгел. «Профильләр» битенә күчеп, язылуны сайлагыз һәм активлаштырыгыз."
|
||||
},
|
||||
"coreUnavailable": {
|
||||
"title": "Ядро вакытлыча кулланылмый",
|
||||
"description": "Ядродан прокси мәгълүматын алып булмады. Ядроны яңадан эшләтеп карагыз. Мәсьәлә чишелмәсә, журналлар папкасын ачып, ядро журналларын тикшерегез."
|
||||
},
|
||||
"noProxyInfo": {
|
||||
"title": "Прокси мәгълүматы юк",
|
||||
"description": "Күрсәтү өчен прокси төркемнәре яки төеннәре юк. Актив язылуда дөрес төркемнәр һәм төеннәр булуын тикшерегез, яки ядроны яңадан эшләтеп журналларны карагыз."
|
||||
},
|
||||
"actions": {
|
||||
"openProfiles": "Профильләргә күчү",
|
||||
"restartCore": "Ядроны яңадан эшләтү",
|
||||
"openLogs": "Журналлар папкасын ачу"
|
||||
}
|
||||
},
|
||||
"chain": {
|
||||
"header": "Chain Proxy Config",
|
||||
|
||||
@@ -44,7 +44,28 @@
|
||||
},
|
||||
"empty": {
|
||||
"noAvailableGroups": "暂无可用代理组",
|
||||
"noProxies": "暂无代理"
|
||||
"noProxies": "暂无代理",
|
||||
"noSubscriptions": {
|
||||
"title": "尚未导入订阅",
|
||||
"description": "代理页没有可展示的内容。请先前往“订阅”页面导入并启用订阅。"
|
||||
},
|
||||
"inactiveSubscription": {
|
||||
"title": "尚未激活订阅",
|
||||
"description": "检测到已有订阅,但当前没有有效订阅被激活。请前往“订阅”页面选择并激活一个订阅。"
|
||||
},
|
||||
"coreUnavailable": {
|
||||
"title": "内核暂不可用",
|
||||
"description": "无法从内核获取代理信息。请尝试重启内核;若问题仍然存在,请打开日志目录检查内核日志。"
|
||||
},
|
||||
"noProxyInfo": {
|
||||
"title": "未获取到代理信息",
|
||||
"description": "当前没有可展示的代理组或节点。请检查当前订阅是否包含有效的代理组和节点,或尝试重启内核并查看日志。"
|
||||
},
|
||||
"actions": {
|
||||
"openProfiles": "前往订阅",
|
||||
"restartCore": "重启内核",
|
||||
"openLogs": "打开日志目录"
|
||||
}
|
||||
},
|
||||
"chain": {
|
||||
"header": "代理链配置",
|
||||
|
||||
@@ -44,7 +44,28 @@
|
||||
},
|
||||
"empty": {
|
||||
"noAvailableGroups": "目前沒有可用的代理群組",
|
||||
"noProxies": "目前沒有代理"
|
||||
"noProxies": "目前沒有代理",
|
||||
"noSubscriptions": {
|
||||
"title": "尚未匯入訂閱",
|
||||
"description": "代理頁沒有可顯示的內容。請先前往「訂閱」頁面匯入並啟用訂閱。"
|
||||
},
|
||||
"inactiveSubscription": {
|
||||
"title": "尚未啟用訂閱",
|
||||
"description": "偵測到已有訂閱,但目前沒有有效訂閱被啟用。請前往「訂閱」頁面選擇並啟用一個訂閱。"
|
||||
},
|
||||
"coreUnavailable": {
|
||||
"title": "核心暫時無法使用",
|
||||
"description": "無法從核心取得代理資訊。請嘗試重新啟動核心;若問題仍然存在,請開啟日誌目錄檢查核心日誌。"
|
||||
},
|
||||
"noProxyInfo": {
|
||||
"title": "未取得代理資訊",
|
||||
"description": "目前沒有可顯示的代理群組或節點。請檢查目前訂閱是否包含有效的代理群組和節點,或嘗試重新啟動核心並查看日誌。"
|
||||
},
|
||||
"actions": {
|
||||
"openProfiles": "前往訂閱",
|
||||
"restartCore": "重新啟動核心",
|
||||
"openLogs": "開啟日誌目錄"
|
||||
}
|
||||
},
|
||||
"chain": {
|
||||
"header": "鏈式代理設定",
|
||||
|
||||
@@ -6,6 +6,7 @@ import type { ProxyViewV1 } from '@/types/proxy-view'
|
||||
export interface ProxiesContextType {
|
||||
proxyView: ProxyViewV1 | undefined
|
||||
isProxyViewPending: boolean
|
||||
isProxyViewError: boolean
|
||||
}
|
||||
|
||||
export interface RulesContextType {
|
||||
@@ -21,6 +22,7 @@ export interface ClashConfigContextType {
|
||||
export interface SystemContextType {
|
||||
sysproxy: any
|
||||
runningMode?: string
|
||||
isRunningModePending: boolean
|
||||
systemProxyAddress: string
|
||||
}
|
||||
|
||||
|
||||
@@ -60,6 +60,7 @@ export const AppDataProvider = ({
|
||||
|
||||
const {
|
||||
data: proxyView,
|
||||
error: proxyViewError,
|
||||
isPending: isProxyViewPending,
|
||||
refetch: _refetchProxyView,
|
||||
} = useQuery({
|
||||
@@ -99,7 +100,7 @@ export const AppDataProvider = ({
|
||||
...TQ_DEFAULTS,
|
||||
})
|
||||
|
||||
const { data: runningMode } = useQuery({
|
||||
const { data: runningMode, isPending: isRunningModePending } = useQuery({
|
||||
queryKey: ['getRunningMode'],
|
||||
queryFn: getRunningMode,
|
||||
...TQ_DEFAULTS,
|
||||
@@ -216,8 +217,9 @@ export const AppDataProvider = ({
|
||||
() => ({
|
||||
proxyView,
|
||||
isProxyViewPending,
|
||||
isProxyViewError: Boolean(proxyViewError),
|
||||
}),
|
||||
[proxyView, isProxyViewPending],
|
||||
[proxyView, isProxyViewPending, proxyViewError],
|
||||
)
|
||||
|
||||
const rulesValue = useMemo(
|
||||
@@ -273,9 +275,18 @@ export const AppDataProvider = ({
|
||||
return {
|
||||
sysproxy,
|
||||
runningMode,
|
||||
isRunningModePending,
|
||||
systemProxyAddress: calculateSystemProxyAddress(),
|
||||
}
|
||||
}, [sysproxy, runningMode, verge, clashConfig, runtimeConfig, clashInfo])
|
||||
}, [
|
||||
sysproxy,
|
||||
runningMode,
|
||||
isRunningModePending,
|
||||
verge,
|
||||
clashConfig,
|
||||
runtimeConfig,
|
||||
clashInfo,
|
||||
])
|
||||
|
||||
const uptimeValue = useMemo(() => ({ uptime: uptimeData || 0 }), [uptimeData])
|
||||
|
||||
|
||||
@@ -288,6 +288,17 @@ export const translationKeys = [
|
||||
'proxies.page.placeholders.delayCheckUrl',
|
||||
'proxies.page.empty.noAvailableGroups',
|
||||
'proxies.page.empty.noProxies',
|
||||
'proxies.page.empty.noSubscriptions.title',
|
||||
'proxies.page.empty.noSubscriptions.description',
|
||||
'proxies.page.empty.inactiveSubscription.title',
|
||||
'proxies.page.empty.inactiveSubscription.description',
|
||||
'proxies.page.empty.coreUnavailable.title',
|
||||
'proxies.page.empty.coreUnavailable.description',
|
||||
'proxies.page.empty.noProxyInfo.title',
|
||||
'proxies.page.empty.noProxyInfo.description',
|
||||
'proxies.page.empty.actions.openProfiles',
|
||||
'proxies.page.empty.actions.restartCore',
|
||||
'proxies.page.empty.actions.openLogs',
|
||||
'proxies.page.chain.header',
|
||||
'proxies.page.chain.warning',
|
||||
'proxies.page.chain.empty',
|
||||
|
||||
@@ -508,8 +508,29 @@ export interface TranslationResources {
|
||||
warning: string
|
||||
}
|
||||
empty: {
|
||||
actions: {
|
||||
openLogs: string
|
||||
openProfiles: string
|
||||
restartCore: string
|
||||
}
|
||||
coreUnavailable: {
|
||||
description: string
|
||||
title: string
|
||||
}
|
||||
inactiveSubscription: {
|
||||
description: string
|
||||
title: string
|
||||
}
|
||||
noAvailableGroups: string
|
||||
noProxies: string
|
||||
noProxyInfo: {
|
||||
description: string
|
||||
title: string
|
||||
}
|
||||
noSubscriptions: {
|
||||
description: string
|
||||
title: string
|
||||
}
|
||||
}
|
||||
labels: {
|
||||
delayCheckReset: string
|
||||
|
||||
Reference in New Issue
Block a user