mirror of
https://github.com/clash-verge-rev/clash-verge-rev.git
synced 2026-04-13 05:20:28 +08:00
Compare commits
2 Commits
830c0773dc
...
b8fbabae04
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b8fbabae04 | ||
|
|
2c766e1ada |
@ -54,7 +54,7 @@
|
||||
"@tauri-apps/plugin-http": "~2.5.7",
|
||||
"@tauri-apps/plugin-process": "^2.3.1",
|
||||
"@tauri-apps/plugin-shell": "2.3.5",
|
||||
"@tauri-apps/plugin-updater": "2.10.0",
|
||||
"@tauri-apps/plugin-updater": "2.10.1",
|
||||
"ahooks": "^3.9.6",
|
||||
"cidr-block": "^2.3.0",
|
||||
"dayjs": "1.11.20",
|
||||
|
||||
10
pnpm-lock.yaml
generated
10
pnpm-lock.yaml
generated
@ -69,8 +69,8 @@ importers:
|
||||
specifier: 2.3.5
|
||||
version: 2.3.5
|
||||
'@tauri-apps/plugin-updater':
|
||||
specifier: 2.10.0
|
||||
version: 2.10.0
|
||||
specifier: 2.10.1
|
||||
version: 2.10.1
|
||||
ahooks:
|
||||
specifier: ^3.9.6
|
||||
version: 3.9.7(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
|
||||
@ -1562,8 +1562,8 @@ packages:
|
||||
'@tauri-apps/plugin-shell@2.3.5':
|
||||
resolution: {integrity: sha512-jewtULhiQ7lI7+owCKAjc8tYLJr92U16bPOeAa472LHJdgaibLP83NcfAF2e+wkEcA53FxKQAZ7byDzs2eeizg==}
|
||||
|
||||
'@tauri-apps/plugin-updater@2.10.0':
|
||||
resolution: {integrity: sha512-ljN8jPlnT0aSn8ecYhuBib84alxfMx6Hc8vJSKMJyzGbTPFZAC44T2I1QNFZssgWKrAlofvJqCC6Rr472JWfkQ==}
|
||||
'@tauri-apps/plugin-updater@2.10.1':
|
||||
resolution: {integrity: sha512-NFYMg+tWOZPJdzE/PpFj2qfqwAWwNS3kXrb1tm1gnBJ9mYzZ4WDRrwy8udzWoAnfGCHLuePNLY1WVCNHnh3eRA==}
|
||||
|
||||
'@tybys/wasm-util@0.10.1':
|
||||
resolution: {integrity: sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==}
|
||||
@ -5059,7 +5059,7 @@ snapshots:
|
||||
dependencies:
|
||||
'@tauri-apps/api': 2.10.1
|
||||
|
||||
'@tauri-apps/plugin-updater@2.10.0':
|
||||
'@tauri-apps/plugin-updater@2.10.1':
|
||||
dependencies:
|
||||
'@tauri-apps/api': 2.10.1
|
||||
|
||||
|
||||
@ -444,6 +444,12 @@ export const CurrentProxyCard = () => {
|
||||
[setState],
|
||||
)
|
||||
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
if (timeoutRef.current) clearTimeout(timeoutRef.current)
|
||||
}
|
||||
}, [])
|
||||
|
||||
// 处理代理组变更
|
||||
const handleGroupChange = useCallback(
|
||||
(event: SelectChangeEvent<string>) => {
|
||||
|
||||
@ -425,7 +425,7 @@ function useIPInfo() {
|
||||
queryKey: [IP_INFO_CACHE_KEY],
|
||||
queryFn: getIpInfo,
|
||||
staleTime: Infinity,
|
||||
gcTime: Infinity,
|
||||
gcTime: 60 * 60 * 1000,
|
||||
refetchOnWindowFocus: false,
|
||||
refetchOnReconnect: false,
|
||||
retry: 1,
|
||||
|
||||
@ -168,6 +168,13 @@ export const EditorViewer = ({
|
||||
}
|
||||
}, [open, syncMaximizedState])
|
||||
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
editorRef.current?.dispose()
|
||||
editorRef.current = null
|
||||
}
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<Dialog
|
||||
open={open}
|
||||
|
||||
@ -34,11 +34,13 @@ import {
|
||||
requestIdleCallback,
|
||||
} from 'foxact/request-idle-callback'
|
||||
import yaml from 'js-yaml'
|
||||
import type { editor } from 'monaco-editor'
|
||||
import {
|
||||
startTransition,
|
||||
useCallback,
|
||||
useEffect,
|
||||
useMemo,
|
||||
useRef,
|
||||
useState,
|
||||
} from 'react'
|
||||
import { Controller, useForm } from 'react-hook-form'
|
||||
@ -149,6 +151,7 @@ export const GroupsEditorViewer = (props: Props) => {
|
||||
[t],
|
||||
)
|
||||
const themeMode = useThemeMode()
|
||||
const editorRef = useRef<editor.IStandaloneCodeEditor | null>(null)
|
||||
const [prevData, setPrevData] = useState('')
|
||||
const [currData, setCurrData] = useState('')
|
||||
const [visualization, setVisualization] = useState(true)
|
||||
@ -481,6 +484,13 @@ export const GroupsEditorViewer = (props: Props) => {
|
||||
getInterfaceNameList()
|
||||
}, [fetchContent, fetchProfile, getInterfaceNameList, open])
|
||||
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
editorRef.current?.dispose()
|
||||
editorRef.current = null
|
||||
}
|
||||
}, [])
|
||||
|
||||
const validateGroup = () => {
|
||||
const group = formIns.getValues()
|
||||
if (group.name === '') {
|
||||
@ -1105,6 +1115,9 @@ export const GroupsEditorViewer = (props: Props) => {
|
||||
language="yaml"
|
||||
value={currData}
|
||||
theme={themeMode === 'light' ? 'light' : 'vs-dark'}
|
||||
onMount={(editorInstance) => {
|
||||
editorRef.current = editorInstance
|
||||
}}
|
||||
options={{
|
||||
tabSize: 2, // 根据语言类型设置缩进大小
|
||||
minimap: {
|
||||
|
||||
@ -19,7 +19,7 @@ import {
|
||||
import { open } from '@tauri-apps/plugin-shell'
|
||||
import { useLockFn } from 'ahooks'
|
||||
import dayjs from 'dayjs'
|
||||
import { useCallback, useEffect, useReducer, useState } from 'react'
|
||||
import { useCallback, useEffect, useReducer, useRef, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
|
||||
import { ConfirmViewer } from '@/components/profile/confirm-viewer'
|
||||
@ -96,7 +96,11 @@ export const ProfileItem = (props: Props) => {
|
||||
|
||||
// 新增状态:是否显示下次更新时间
|
||||
const [showNextUpdate, setShowNextUpdate] = useState(false)
|
||||
const showNextUpdateRef = useRef(false)
|
||||
const [nextUpdateTime, setNextUpdateTime] = useState('')
|
||||
const refreshTimeoutRef = useRef<ReturnType<typeof setTimeout> | undefined>(
|
||||
undefined,
|
||||
)
|
||||
|
||||
const { uid, name = 'Profile', extra, updated = 0, option } = itemData
|
||||
|
||||
@ -178,6 +182,10 @@ export const ProfileItem = (props: Props) => {
|
||||
setShowNextUpdate(!showNextUpdate)
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
showNextUpdateRef.current = showNextUpdate
|
||||
}, [showNextUpdate])
|
||||
|
||||
// 当组件加载或更新间隔变化时更新下次更新时间
|
||||
useEffect(() => {
|
||||
if (showNextUpdate) {
|
||||
@ -192,19 +200,18 @@ export const ProfileItem = (props: Props) => {
|
||||
|
||||
// 订阅定时器更新事件
|
||||
useEffect(() => {
|
||||
let refreshTimeout: number | undefined
|
||||
// 处理定时器更新事件 - 这个事件专门用于通知定时器变更
|
||||
const handleTimerUpdate = (event: Event) => {
|
||||
const source = event as CustomEvent<string> & { payload?: string }
|
||||
const updatedUid = source.detail ?? source.payload
|
||||
|
||||
// 只有当更新的是当前配置时才刷新显示
|
||||
if (updatedUid === itemData.uid && showNextUpdate) {
|
||||
if (updatedUid === itemData.uid && showNextUpdateRef.current) {
|
||||
debugLog(`收到定时器更新事件: uid=${updatedUid}`)
|
||||
if (refreshTimeout !== undefined) {
|
||||
clearTimeout(refreshTimeout)
|
||||
if (refreshTimeoutRef.current !== undefined) {
|
||||
clearTimeout(refreshTimeoutRef.current)
|
||||
}
|
||||
refreshTimeout = window.setTimeout(() => {
|
||||
refreshTimeoutRef.current = window.setTimeout(() => {
|
||||
fetchNextUpdateTime(true)
|
||||
}, 1000)
|
||||
}
|
||||
@ -214,13 +221,13 @@ export const ProfileItem = (props: Props) => {
|
||||
window.addEventListener('verge://timer-updated', handleTimerUpdate)
|
||||
|
||||
return () => {
|
||||
if (refreshTimeout !== undefined) {
|
||||
clearTimeout(refreshTimeout)
|
||||
if (refreshTimeoutRef.current !== undefined) {
|
||||
clearTimeout(refreshTimeoutRef.current)
|
||||
}
|
||||
// 清理事件监听
|
||||
window.removeEventListener('verge://timer-updated', handleTimerUpdate)
|
||||
}
|
||||
}, [fetchNextUpdateTime, itemData.uid, showNextUpdate])
|
||||
}, [fetchNextUpdateTime, itemData.uid])
|
||||
|
||||
// local file mode
|
||||
// remote file mode
|
||||
|
||||
@ -27,11 +27,13 @@ import {
|
||||
} from '@mui/material'
|
||||
import { useLockFn } from 'ahooks'
|
||||
import yaml from 'js-yaml'
|
||||
import type { editor } from 'monaco-editor'
|
||||
import {
|
||||
startTransition,
|
||||
useCallback,
|
||||
useEffect,
|
||||
useMemo,
|
||||
useRef,
|
||||
useState,
|
||||
} from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
@ -56,6 +58,7 @@ export const ProxiesEditorViewer = (props: Props) => {
|
||||
const { profileUid, property, open, onClose, onSave } = props
|
||||
const { t } = useTranslation()
|
||||
const themeMode = useThemeMode()
|
||||
const editorRef = useRef<editor.IStandaloneCodeEditor | null>(null)
|
||||
const [prevData, setPrevData] = useState('')
|
||||
const [currData, setCurrData] = useState('')
|
||||
const [visualization, setVisualization] = useState(true)
|
||||
@ -343,6 +346,13 @@ export const ProxiesEditorViewer = (props: Props) => {
|
||||
fetchProfile()
|
||||
}, [fetchContent, fetchProfile, open])
|
||||
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
editorRef.current?.dispose()
|
||||
editorRef.current = null
|
||||
}
|
||||
}, [])
|
||||
|
||||
const handleSave = useLockFn(async () => {
|
||||
try {
|
||||
await saveProfileFile(property, currData)
|
||||
@ -469,6 +479,9 @@ export const ProxiesEditorViewer = (props: Props) => {
|
||||
language="yaml"
|
||||
value={currData}
|
||||
theme={themeMode === 'light' ? 'light' : 'vs-dark'}
|
||||
onMount={(editorInstance) => {
|
||||
editorRef.current = editorInstance
|
||||
}}
|
||||
options={{
|
||||
tabSize: 2, // 根据语言类型设置缩进大小
|
||||
minimap: {
|
||||
|
||||
@ -29,11 +29,13 @@ import {
|
||||
} from '@mui/material'
|
||||
import { useLockFn } from 'ahooks'
|
||||
import yaml from 'js-yaml'
|
||||
import type { editor } from 'monaco-editor'
|
||||
import {
|
||||
startTransition,
|
||||
useCallback,
|
||||
useEffect,
|
||||
useMemo,
|
||||
useRef,
|
||||
useState,
|
||||
} from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
@ -251,6 +253,8 @@ export const RulesEditorViewer = (props: Props) => {
|
||||
const { t } = useTranslation()
|
||||
const themeMode = useThemeMode()
|
||||
|
||||
const editorRef = useRef<editor.IStandaloneCodeEditor | null>(null)
|
||||
|
||||
const [prevData, setPrevData] = useState('')
|
||||
const [currData, setCurrData] = useState('')
|
||||
const [visualization, setVisualization] = useState(true)
|
||||
@ -536,6 +540,13 @@ export const RulesEditorViewer = (props: Props) => {
|
||||
fetchProfile()
|
||||
}, [fetchContent, fetchProfile, open])
|
||||
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
editorRef.current?.dispose()
|
||||
editorRef.current = null
|
||||
}
|
||||
}, [])
|
||||
|
||||
const validateRule = () => {
|
||||
if ((ruleType.required ?? true) && !ruleContent) {
|
||||
throw new Error(
|
||||
@ -770,6 +781,9 @@ export const RulesEditorViewer = (props: Props) => {
|
||||
language="yaml"
|
||||
value={currData}
|
||||
theme={themeMode === 'light' ? 'light' : 'vs-dark'}
|
||||
onMount={(editorInstance) => {
|
||||
editorRef.current = editorInstance
|
||||
}}
|
||||
options={{
|
||||
tabSize: 2, // 根据语言类型设置缩进大小
|
||||
minimap: {
|
||||
|
||||
@ -16,6 +16,7 @@ import {
|
||||
import { invoke } from '@tauri-apps/api/core'
|
||||
import { useLockFn } from 'ahooks'
|
||||
import yaml from 'js-yaml'
|
||||
import type { editor } from 'monaco-editor'
|
||||
import type { Ref } from 'react'
|
||||
import {
|
||||
useCallback,
|
||||
@ -189,6 +190,7 @@ export function DnsViewer({ ref }: { ref?: Ref<DialogRef> }) {
|
||||
const [open, setOpen] = useState(false)
|
||||
const [visualization, setVisualization] = useState(true)
|
||||
const skipYamlSyncRef = useRef(false)
|
||||
const editorRef = useRef<editor.IStandaloneCodeEditor | null>(null)
|
||||
const [values, setValues] = useState<{
|
||||
enable: boolean
|
||||
listen: string
|
||||
@ -453,6 +455,13 @@ export function DnsViewer({ ref }: { ref?: Ref<DialogRef> }) {
|
||||
}
|
||||
}, [visualization])
|
||||
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
editorRef.current?.dispose()
|
||||
editorRef.current = null
|
||||
}
|
||||
}, [])
|
||||
|
||||
const initDnsConfig = useCallback(async () => {
|
||||
try {
|
||||
const dnsConfigExists = await invoke<boolean>(
|
||||
@ -1057,6 +1066,9 @@ export function DnsViewer({ ref }: { ref?: Ref<DialogRef> }) {
|
||||
value={yamlContent}
|
||||
theme={themeMode === 'light' ? 'light' : 'vs-dark'}
|
||||
className="flex-grow"
|
||||
onMount={(editorInstance) => {
|
||||
editorRef.current = editorInstance
|
||||
}}
|
||||
options={{
|
||||
tabSize: 2,
|
||||
minimap: {
|
||||
|
||||
@ -42,7 +42,7 @@ export const useIconCache = ({
|
||||
refetchOnWindowFocus: false,
|
||||
refetchOnReconnect: false,
|
||||
staleTime: Infinity,
|
||||
gcTime: Infinity,
|
||||
gcTime: 30 * 60 * 1000,
|
||||
retry: 2,
|
||||
})
|
||||
|
||||
|
||||
@ -93,7 +93,7 @@ export const useMihomoWsSubscription = <T>(
|
||||
subscriptionCacheKey ?? '$sub$__disabled__',
|
||||
]) ?? fallbackData,
|
||||
staleTime: Infinity,
|
||||
gcTime: Infinity,
|
||||
gcTime: 30_000,
|
||||
enabled: subscriptionCacheKey !== null,
|
||||
})
|
||||
|
||||
@ -243,8 +243,11 @@ export const useMihomoWsSubscription = <T>(
|
||||
}, [subscriptionCacheKey])
|
||||
|
||||
const refresh = useCallback(() => {
|
||||
if (subscriptionCacheKey) {
|
||||
queryClient.removeQueries({ queryKey: [subscriptionCacheKey] })
|
||||
}
|
||||
setDate(Date.now())
|
||||
}, [setDate])
|
||||
}, [queryClient, subscriptionCacheKey, setDate])
|
||||
|
||||
return { response, refresh, subscriptionCacheKey, wsRef }
|
||||
}
|
||||
|
||||
@ -309,20 +309,22 @@ export const useCustomTheme = () => {
|
||||
styleElement.innerHTML = effectiveInjectedCss + globalStyles
|
||||
}
|
||||
|
||||
const { palette } = muiTheme
|
||||
setTimeout(() => {
|
||||
const dom = document.querySelector('#Gradient2')
|
||||
if (dom) {
|
||||
dom.innerHTML = `
|
||||
<stop offset="0%" stop-color="${palette.primary.main}" />
|
||||
<stop offset="80%" stop-color="${palette.primary.dark}" />
|
||||
<stop offset="100%" stop-color="${palette.primary.dark}" />
|
||||
`
|
||||
}
|
||||
}, 0)
|
||||
|
||||
return muiTheme
|
||||
}, [mode, theme_setting, userBackgroundImage, hasUserBackground])
|
||||
|
||||
useEffect(() => {
|
||||
const id = setTimeout(() => {
|
||||
const dom = document.querySelector('#Gradient2')
|
||||
if (dom) {
|
||||
dom.innerHTML = `
|
||||
<stop offset="0%" stop-color="${theme.palette.primary.main}" />
|
||||
<stop offset="80%" stop-color="${theme.palette.primary.dark}" />
|
||||
<stop offset="100%" stop-color="${theme.palette.primary.dark}" />
|
||||
`
|
||||
}
|
||||
}, 0)
|
||||
return () => clearTimeout(id)
|
||||
}, [theme.palette.primary.main, theme.palette.primary.dark])
|
||||
|
||||
return { theme }
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user